From 58f90f21f4d8e3b105b3e3669334f1b98141075c Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Mon, 26 Mar 2012 17:56:46 +0000 Subject: [PATCH 1/8] booke:Use MMU API for creating initial mapping for secondary cpus Initial Mapping creation for secondary CPU in SMP was missing new MMU API. Signed-off-by: Bharat Bhushan Signed-off-by: Alexander Graf --- hw/ppce500_spin.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 960b7b0c3d..95a2825bbd 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -86,6 +86,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env, tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M; tlb->mas7_3 = pa & TARGET_PAGE_MASK; tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; + env->tlb_dirty = true; } static void spin_kick(void *data) From 892c587f22fc97362a595d3c84669a39ce1cd2f5 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 19 Apr 2012 15:34:06 +0200 Subject: [PATCH 2/8] PPC: Fix up e500 cache size setting When initializing the e500 code, we need to expose its cache line size for user and system mode, while the mmu details are only interesting for system emulation. Split the 2 switch statements apart, allowing us to #ifdef out the mmu parts for user mode emulation while keeping all cache information consistent. Signed-off-by: Alexander Graf --- target-ppc/translate_init.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index ba4b84d86b..6f61175e7d 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -4461,33 +4461,36 @@ static void init_proc_e500 (CPUPPCState *env, int version) &spr_read_spefscr, &spr_write_spefscr, &spr_read_spefscr, &spr_write_spefscr, 0x00000000); +#if !defined(CONFIG_USER_ONLY) /* Memory management */ -#if defined(CONFIG_USER_ONLY) - env->dcache_line_size = 32; - env->icache_line_size = 32; -#else /* !defined(CONFIG_USER_ONLY) */ env->nb_pids = 3; env->nb_ways = 2; env->id_tlbs = 0; switch (version) { case fsl_e500v1: - /* e500v1 */ tlbncfg[0] = gen_tlbncfg(2, 1, 1, 0, 256); tlbncfg[1] = gen_tlbncfg(16, 1, 9, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16); - env->dcache_line_size = 32; - env->icache_line_size = 32; break; case fsl_e500v2: - /* e500v2 */ tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512); tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16); + break; + case fsl_e500mc: + tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512); + tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64); + break; + default: + cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); + } +#endif + /* Cache sizes */ + switch (version) { + case fsl_e500v1: + case fsl_e500v2: env->dcache_line_size = 32; env->icache_line_size = 32; break; case fsl_e500mc: - /* e500mc */ - tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512); - tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64); env->dcache_line_size = 64; env->icache_line_size = 64; l1cfg0 |= 0x1000000; /* 64 byte cache block size */ @@ -4495,7 +4498,6 @@ static void init_proc_e500 (CPUPPCState *env, int version) default: cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); } -#endif gen_spr_BookE206(env, 0x000000DF, tlbncfg); /* XXX : not implemented */ spr_register(env, SPR_HID0, "HID0", From d601fac478eee7391f3e7005a9321fbf38d74809 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 25 Apr 2012 17:55:41 +0000 Subject: [PATCH 3/8] pseries: Implement automatic PAPR VIO address allocation PAPR virtual IO (VIO) devices require a unique, but otherwise arbitrary, "address" used as a token to the hypercalls which manipulate them. Currently the pseries machine code does an ok job of allocating these addresses when the legacy -net nic / -serial and so forth options are used but will fail to allocate them properly when using -device. Specifically, you can use -device if all addresses are explicitly assigned. Without explicit assignment, only one VIO device of each type (network, console, SCSI) will be assigned properly, any further ones will attempt to take the same address leading to a fatal error. This patch fixes the situation by adding a proper address allocator to the VIO "bus" code. This is used both by -device and the legacy options and default devices. Addresses can still be explicitly assigned with -device options if desired. This patch changes the (guest visible) numbering of VIO devices, but since their addresses are discovered using the device tree and already differ from the numbering found on existing PowerVM systems, this does not break compatibility. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 7 +++---- hw/spapr_llan.c | 5 ++--- hw/spapr_vio.c | 54 ++++++++++++++++++++++++++++++------------------ hw/spapr_vio.h | 13 ++++++------ hw/spapr_vscsi.c | 5 ++--- hw/spapr_vty.c | 5 ++--- 6 files changed, 49 insertions(+), 40 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index bfaf260d54..cca20f9a51 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -631,8 +631,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, for (i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { - spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i, - serial_hds[i]); + spapr_vty_create(spapr->vio_bus, serial_hds[i]); } } @@ -650,14 +649,14 @@ static void ppc_spapr_init(ram_addr_t ram_size, } if (strcmp(nd->model, "ibmveth") == 0) { - spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd); + spapr_vlan_create(spapr->vio_bus, nd); } else { pci_nic_init_nofail(&nd_table[i], nd->model, NULL); } } for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { - spapr_vscsi_create(spapr->vio_bus, 0x2000 + i); + spapr_vscsi_create(spapr->vio_bus); } if (rma_size < (MIN_RMA_SLOF << 20)) { diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index e18d2eb901..8313043652 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -204,12 +204,11 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev) return 0; } -void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd) +void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd) { DeviceState *dev; dev = qdev_create(&bus->bus, "spapr-vlan"); - qdev_prop_set_uint32(dev, "reg", reg); qdev_set_nic_properties(dev, nd); @@ -480,7 +479,7 @@ static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr, } static Property spapr_vlan_properties[] = { - DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x1000, 0x10000000), + DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x10000000), DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index fccf48bd67..315ab8091c 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -620,28 +620,22 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token, rtas_st(rets, 0, 0); } -static int spapr_vio_check_reg(VIOsPAPRDevice *sdev) +static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev) { - VIOsPAPRDevice *other_sdev; + VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus); DeviceState *qdev; - VIOsPAPRBus *sbus; - - sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus); + VIOsPAPRDevice *other; /* - * Check two device aren't given clashing addresses by the user (or some - * other mechanism). We have to open code this because we have to check - * for matches with devices other than us. + * Check for a device other than the given one which is already + * using the requested address. We have to open code this because + * the given dev might already be in the list. */ - QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) { - other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev); + QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { + other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev); - if (other_sdev != sdev && other_sdev->reg == sdev->reg) { - fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n", - object_get_typename(OBJECT(sdev)), - object_get_typename(OBJECT(qdev)), - sdev->reg); - return -EEXIST; + if (other != dev && other->reg == dev->reg) { + return other; } } @@ -667,11 +661,30 @@ static int spapr_vio_busdev_init(DeviceState *qdev) VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); char *id; - int ret; - ret = spapr_vio_check_reg(dev); - if (ret) { - return ret; + if (dev->reg != -1) { + /* + * Explicitly assigned address, just verify that no-one else + * is using it. other mechanism). We have to open code this + * rather than using spapr_vio_find_by_reg() because sdev + * itself is already in the list. + */ + VIOsPAPRDevice *other = reg_conflict(dev); + + if (other) { + fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n", + object_get_typename(OBJECT(qdev)), + object_get_typename(OBJECT(&other->qdev)), + dev->reg); + return -1; + } + } else { + /* Need to assign an address */ + VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus); + + do { + dev->reg = bus->next_reg++; + } while (reg_conflict(dev)); } /* Don't overwrite ids assigned on the command line */ @@ -731,6 +744,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void) qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio"); bus = DO_UPCAST(VIOsPAPRBus, bus, qbus); + bus->next_reg = 0x1000; /* hcall-vio */ spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal); diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index 10ab3594c0..87816e456d 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -32,8 +32,6 @@ enum VIOsPAPR_TCEAccess { SPAPR_TCE_RW = 3, }; -#define SPAPR_VTY_BASE_ADDRESS 0x30000000 - #define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device" #define VIO_SPAPR_DEVICE(obj) \ OBJECT_CHECK(VIOsPAPRDevice, (obj), TYPE_VIO_SPAPR_DEVICE) @@ -82,13 +80,14 @@ struct VIOsPAPRDevice { VIOsPAPR_CRQ crq; }; -#define DEFINE_SPAPR_PROPERTIES(type, field, default_reg, default_dma_window) \ - DEFINE_PROP_UINT32("reg", type, field.reg, default_reg), \ +#define DEFINE_SPAPR_PROPERTIES(type, field, default_dma_window) \ + DEFINE_PROP_UINT32("reg", type, field.reg, -1), \ DEFINE_PROP_UINT32("dma-window", type, field.rtce_window_size, \ default_dma_window) struct VIOsPAPRBus { BusState bus; + uint32_t next_reg; int (*init)(VIOsPAPRDevice *dev); int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off); }; @@ -119,9 +118,9 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq); VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg); void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len); -void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev); -void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd); -void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg); +void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev); +void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd); +void spapr_vscsi_create(VIOsPAPRBus *bus); VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus); diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c index 538e0b7938..037867ab4f 100644 --- a/hw/spapr_vscsi.c +++ b/hw/spapr_vscsi.c @@ -918,12 +918,11 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev) return 0; } -void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg) +void spapr_vscsi_create(VIOsPAPRBus *bus) { DeviceState *dev; dev = qdev_create(&bus->bus, "spapr-vscsi"); - qdev_prop_set_uint32(dev, "reg", reg); qdev_init_nofail(dev); } @@ -946,7 +945,7 @@ static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off) } static Property spapr_vscsi_properties[] = { - DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x2000, 0x10000000), + DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x10000000), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index a30c040b97..c9674f36a6 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -123,18 +123,17 @@ static target_ulong h_get_term_char(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev) +void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev) { DeviceState *dev; dev = qdev_create(&bus->bus, "spapr-vty"); - qdev_prop_set_uint32(dev, "reg", reg); qdev_prop_set_chr(dev, "chardev", chardev); qdev_init_nofail(dev); } static Property spapr_vty_properties[] = { - DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0), + DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0), DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev), DEFINE_PROP_END_OF_LIST(), }; From 7fb0bd3473dfb2bb1768072ebbfa5771e8c8af4a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 25 Apr 2012 17:55:42 +0000 Subject: [PATCH 4/8] pseries: Use the same interrupt swizzling for host bridges as p2p bridges Currently the pseries PCI code uses a somewhat strange scheme of PCI irq allocation - one per slot up to a maximum that's greater than the usual 4. This scheme more or less worked, because we were able to tell the guest the irq mapping in the device tree, however it's a bit odd and may break assumptions in the future. Worse, the array used to construct the dev tree interrupt map was mis-sized, we got away with it only because it happened that our SPAPR_PCI_NUM_LSI value was greater than 7. This patch changes the pseries PCI code to use the same interrupt swizzling scheme as is standardized for PCI to PCI bridges. This makes for better consistency, deals better with any devices which use multiple interrupt pins and will make life easier in the future when we add passthrough of what may be either a host bridge or a PCI to PCI bridge. This won't break existing guests, because they don't assume a particular mapping scheme for host bridges, but just follow what we tell them in the device tree (also updated to match, of course). This patch also fixes the allocation of the irq map. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 49 ++++++++++++++++++++++++++++--------------------- hw/spapr_pci.h | 5 ++--- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index a564c007b4..25b400aa47 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -198,16 +198,20 @@ static void rtas_write_pci_config(sPAPREnvironment *spapr, finish_write_pci_config(spapr, 0, addr, size, val, rets); } +static int pci_spapr_swizzle(int slot, int pin) +{ + return (slot + pin) % PCI_NUM_PINS; +} + static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num) { /* * Here we need to convert pci_dev + irq_num to some unique value - * which is less than number of IRQs on the specific bus (now it - * is 16). At the moment irq_num == device_id (number of the - * slot?) - * FIXME: we should swizzle in fn and irq_num + * which is less than number of IRQs on the specific bus (4). We + * use standard PCI swizzling, that is (slot number + pin number) + * % 4. */ - return (pci_dev->devfn >> 3) % SPAPR_PCI_NUM_LSI; + return pci_spapr_swizzle(PCI_SLOT(pci_dev->devfn), irq_num); } static void pci_spapr_set_irq(void *opaque, int irq_num, int level) @@ -304,13 +308,13 @@ static int spapr_phb_init(SysBusDevice *s) phb->busname ? phb->busname : phb->dtbusname, pci_spapr_set_irq, pci_spapr_map_irq, phb, &phb->memspace, &phb->iospace, - PCI_DEVFN(0, 0), SPAPR_PCI_NUM_LSI); + PCI_DEVFN(0, 0), PCI_NUM_PINS); phb->host_state.bus = bus; QLIST_INSERT_HEAD(&spapr->phbs, phb, list); /* Initialize the LSI table */ - for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { qemu_irq qirq; uint32_t num; @@ -392,8 +396,7 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt) { - PCIBus *bus = phb->host_state.bus; - int bus_off, i; + int bus_off, i, j; char nodename[256]; uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) }; struct { @@ -415,8 +418,8 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb, }; uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 }; uint32_t interrupt_map_mask[] = { - cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, 0x0}; - uint32_t interrupt_map[bus->nirq][7]; + cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)}; + uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7]; /* Start populating the FDT */ sprintf(nodename, "pci@%" PRIx64, phb->buid); @@ -450,19 +453,23 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb, */ _FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask", &interrupt_map_mask, sizeof(interrupt_map_mask))); - for (i = 0; i < 7; i++) { - uint32_t *irqmap = interrupt_map[i]; - irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0)); - irqmap[1] = 0; - irqmap[2] = 0; - irqmap[3] = 0; - irqmap[4] = cpu_to_be32(xics_phandle); - irqmap[5] = cpu_to_be32(phb->lsi_table[i % SPAPR_PCI_NUM_LSI].dt_irq); - irqmap[6] = cpu_to_be32(0x8); + for (i = 0; i < PCI_SLOT_MAX; i++) { + for (j = 0; j < PCI_NUM_PINS; j++) { + uint32_t *irqmap = interrupt_map[i*PCI_NUM_PINS + j]; + int lsi_num = pci_spapr_swizzle(i, j); + + irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0)); + irqmap[1] = 0; + irqmap[2] = 0; + irqmap[3] = cpu_to_be32(j+1); + irqmap[4] = cpu_to_be32(xics_phandle); + irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].dt_irq); + irqmap[6] = cpu_to_be32(0x8); + } } /* Write interrupt map */ _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map, - 7 * sizeof(interrupt_map[0]))); + sizeof(interrupt_map))); return 0; } diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 039f85bd4b..f54c2e8108 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -23,11 +23,10 @@ #if !defined(__HW_SPAPR_PCI_H__) #define __HW_SPAPR_PCI_H__ +#include "hw/pci.h" #include "hw/pci_host.h" #include "hw/xics.h" -#define SPAPR_PCI_NUM_LSI 16 - typedef struct sPAPRPHBState { SysBusDevice busdev; PCIHostState host_state; @@ -43,7 +42,7 @@ typedef struct sPAPRPHBState { struct { uint32_t dt_irq; qemu_irq qirq; - } lsi_table[SPAPR_PCI_NUM_LSI]; + } lsi_table[PCI_NUM_PINS]; QLIST_ENTRY(sPAPRPHBState) list; } sPAPRPHBState; From 73f7821baca8ec063ace277539bedeb286663965 Mon Sep 17 00:00:00 2001 From: Peter Portante Date: Mon, 23 Apr 2012 07:27:56 +0000 Subject: [PATCH 5/8] pseries: Fix use of global CPU state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit ed120055c7f9b26b5707d3ceabbe5a3f06aaf937 (Implement PAPR VPA functions for pSeries shared processor partitions) introduced the deregister_dtl() function and typo "emv" as name of its argument. This went unnoticed because the code in that function can access the global variable "env" so that no build failure resulted. Fix the argument to read "env". Resolves LP#986241. Signed-off-by: Peter Portante Acked-by: Andreas Färber [agraf: fixed typo in commit message] Signed-off-by: Alexander Graf --- hw/spapr_hcall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 634763eefd..94bb504ca6 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -482,7 +482,7 @@ static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) return H_SUCCESS; } -static target_ulong deregister_dtl(CPUPPCState *emv, target_ulong addr) +static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr) { env->dispatch_trace_log = 0; env->dtl_size = 0; From 5f2c23e61a7cebed05a43dda127c83a21c681420 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 28 Apr 2012 17:52:31 +0200 Subject: [PATCH 6/8] ppce500_spin: Replace assert by hw_error (fixes compiler warning) The default case in function spin_read should never be reached, therefore the old code used assert(0) to abort QEMU. This does not work when QEMU is compiled with macro NDEBUG defined. In this case (and also when the compiler does not know that assert never returns), there is a compiler warning because of the missing return value. Using hw_error allows an improved error message and aborts always. Signed-off-by: Stefan Weil [agraf: use __func__] Signed-off-by: Alexander Graf --- hw/ppce500_spin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 95a2825bbd..fddf2197a9 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -179,7 +179,7 @@ static uint64_t spin_read(void *opaque, target_phys_addr_t addr, unsigned len) case 4: return ldl_p(spin_p); default: - assert(0); + hw_error("ppce500: unexpected %s with len = %u", __func__, len); } } From a738816212614e63aca04e75a22c753644d15f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 24 Apr 2012 06:48:34 +0000 Subject: [PATCH 7/8] target-ppc: Some support for dumping TLB_EMB TLBs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add mmubooke_dump_mmu(). TODO: Add printing of individual flags. Signed-off-by: François Revol [agraf: fix coding style] Signed-off-by: Alexander Graf --- target-ppc/helper.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/target-ppc/helper.c b/target-ppc/helper.c index c610ce3e28..e97e49640d 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -1466,6 +1466,53 @@ static const char *book3e_tsize_to_str[32] = { "1T", "2T" }; +static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf, + CPUPPCState *env) +{ + ppcemb_tlb_t *entry; + int i; + + if (kvm_enabled() && !env->kvm_sw_tlb) { + cpu_fprintf(f, "Cannot access KVM TLB\n"); + return; + } + + cpu_fprintf(f, "\nTLB:\n"); + cpu_fprintf(f, "Effective Physical Size PID Prot " + "Attr\n"); + + entry = &env->tlb.tlbe[0]; + for (i = 0; i < env->nb_tlb; i++, entry++) { + target_phys_addr_t ea, pa; + target_ulong mask; + uint64_t size = (uint64_t)entry->size; + char size_buf[20]; + + /* Check valid flag */ + if (!(entry->prot & PAGE_VALID)) { + continue; + } + + mask = ~(entry->size - 1); + ea = entry->EPN & mask; + pa = entry->RPN & mask; +#if (TARGET_PHYS_ADDR_BITS >= 36) + /* Extend the physical address to 36 bits */ + pa |= (target_phys_addr_t)(entry->RPN & 0xF) << 32; +#endif + size /= 1024; + if (size >= 1024) { + snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / 1024); + } else { + snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size); + } + cpu_fprintf(f, "0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n", + (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID, + entry->prot, entry->attr); + } + +} + static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env, int tlbn, int offset, int tlbsize) @@ -1561,6 +1608,9 @@ static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf, void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) { switch (env->mmu_model) { + case POWERPC_MMU_BOOKE: + mmubooke_dump_mmu(f, cpu_fprintf, env); + break; case POWERPC_MMU_BOOKE206: mmubooke206_dump_mmu(f, cpu_fprintf, env); break; From ddf1ddcf65866e2dd8e5d515bc636617fb2e15ee Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 30 Apr 2012 22:58:55 +0000 Subject: [PATCH 8/8] linux-user: Fix invalid TARGET_ABI_BITS usage on ppc hosts When trying to evaluate the size of the _host_ type size for olddev_t, we need to expose the host's pointer size, not the guest pointer size. This usage got introduced accidently in commit b754e4fc1. Fix things by not using TARGET_.*, but rather use host sizeof() information, which gives us the correct size. Reported-by: Peter Maydell Signed-off-by: Alexander Graf --- thunk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunk.h b/thunk.h index c29576609c..87025c3b04 100644 --- a/thunk.h +++ b/thunk.h @@ -113,7 +113,7 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host) defined(HOST_PARISC) || defined(HOST_SPARC64) return 4; #elif defined(HOST_PPC) - return TARGET_ABI_BITS / 8; + return sizeof(void *); #else return 2; #endif