diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-03-20 11:45:37 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-03-20 11:45:38 +0000 |
commit | 3a87f8b6859e6221b827ab4737779dddb37553ec (patch) | |
tree | ac77d44aba200522bb9311a50849ae12be7387bc /hw/ppc | |
parent | 06c1bee85a7def8d0139ee6829728a891efe623f (diff) | |
parent | 71461b0fef53467d2a85dbd72304dba0e01d8370 (diff) | |
download | qemu-3a87f8b6859e6221b827ab4737779dddb37553ec.zip qemu-3a87f8b6859e6221b827ab4737779dddb37553ec.tar.gz qemu-3a87f8b6859e6221b827ab4737779dddb37553ec.tar.bz2 |
Merge remote-tracking branch 'remotes/afaerber/tags/ppc-for-2.0' into staging
PowerPC queue for 2.0
* sPAPR loop fix
* SPR reset fix
* Reduce allocation size of indirect opcode tables
* Restrict number of CPU threads
* sPAPR H_SET_MODE fixes
* sPAPR firmware path fixes
* Static and constness cleanups
# gpg: Signature made Thu 20 Mar 2014 01:46:14 GMT using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg: aka "Andreas Färber <afaerber@suse.com>"
* remotes/afaerber/tags/ppc-for-2.0:
spapr: Implement interface to fix device pathname
spapr: QOM'ify pseries machine
spapr_vio: Fix firmware names
spapr_llan: Add to boot device list
qdev: Introduce FWPathProvider interface
vl.c: Extend get_boot_devices_list() to ignore suffixes
spapr_hcall: Fix little-endian resource handling in H_SET_MODE
target-ppc: Introduce powerisa-207-server flag
target-ppc: Force CPU threads count to be a power of 2
target-ppc: Fix overallocation of opcode tables
target-ppc: Reset SPRs on CPU reset
spapr_hcall: Fix h_enter to loop correctly
target-ppc: Add missing 'static' and 'const' attributes
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/spapr.c | 107 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 52 | ||||
-rw-r--r-- | hw/ppc/spapr_vio.c | 3 |
3 files changed, 144 insertions, 18 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 5c9a154..a11e121 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -26,6 +26,7 @@ */ #include "sysemu/sysemu.h" #include "hw/hw.h" +#include "hw/fw-path-provider.h" #include "elf.h" #include "net/net.h" #include "sysemu/blockdev.h" @@ -45,6 +46,8 @@ #include "hw/pci/msi.h" #include "hw/pci/pci.h" +#include "hw/scsi/scsi.h" +#include "hw/virtio/virtio-scsi.h" #include "exec/address-spaces.h" #include "hw/usb.h" @@ -81,6 +84,8 @@ #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) +#define TYPE_SPAPR_MACHINE "spapr-machine" + sPAPREnvironment *spapr; int spapr_allocate_irq(int hint, bool lsi) @@ -598,7 +603,9 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, hwaddr rtas_addr, hwaddr rtas_size) { - int ret; + int ret, i; + size_t cb = 0; + char *bootlist; void *fdt; sPAPRPHBState *phb; @@ -640,6 +647,21 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, fprintf(stderr, "Couldn't finalize CPU device tree properties\n"); } + bootlist = get_boot_devices_list(&cb, true); + if (cb && bootlist) { + int offset = fdt_path_offset(fdt, "/chosen"); + if (offset < 0) { + exit(1); + } + for (i = 0; i < cb; i++) { + if (bootlist[i] == '\n') { + bootlist[i] = ' '; + } + + } + ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist); + } + if (!spapr->has_graphics) { spapr_populate_chosen_stdout(fdt, spapr->vio_bus); } @@ -1410,9 +1432,86 @@ static QEMUMachine spapr_machine = { .kvm_type = spapr_kvm_type, }; -static void spapr_machine_init(void) +/* + * Implementation of an interface to adjust firmware patch + * for the bootindex property handling. + */ +static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, + DeviceState *dev) +{ +#define CAST(type, obj, name) \ + ((type *)object_dynamic_cast(OBJECT(obj), (name))) + SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); + sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); + + if (d) { + void *spapr = CAST(void, bus->parent, "spapr-vscsi"); + VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); + USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); + + if (spapr) { + /* + * Replace "channel@0/disk@0,0" with "disk@8000000000000000": + * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun + * in the top 16 bits of the 64-bit LUN + */ + unsigned id = 0x8000 | (d->id << 8) | d->lun; + return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), + (uint64_t)id << 48); + } else if (virtio) { + /* + * We use SRP luns of the form 01000000 | (target << 8) | lun + * in the top 32 bits of the 64-bit LUN + * Note: the quote above is from SLOF and it is wrong, + * the actual binding is: + * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) + */ + unsigned id = 0x1000000 | (d->id << 16) | d->lun; + return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), + (uint64_t)id << 32); + } else if (usb) { + /* + * We use SRP luns of the form 01000000 | (usb-port << 16) | lun + * in the top 32 bits of the 64-bit LUN + */ + unsigned usb_port = atoi(usb->port->path); + unsigned id = 0x1000000 | (usb_port << 16) | d->lun; + return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), + (uint64_t)id << 32); + } + } + + if (phb) { + /* Replace "pci" with "pci@800000020000000" */ + return g_strdup_printf("pci@%"PRIX64, phb->buid); + } + + return NULL; +} + +static void spapr_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); + + mc->qemu_machine = data; + fwc->get_dev_path = spapr_get_fw_dev_path; +} + +static const TypeInfo spapr_machine_info = { + .name = TYPE_SPAPR_MACHINE, + .parent = TYPE_MACHINE, + .class_init = spapr_machine_class_init, + .class_data = &spapr_machine, + .interfaces = (InterfaceInfo[]) { + { TYPE_FW_PATH_PROVIDER }, + { } + }, +}; + +static void spapr_machine_register_types(void) { - qemu_register_machine(&spapr_machine); + type_register_static(&spapr_machine_info); } -machine_init(spapr_machine_init); +type_init(spapr_machine_register_types) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index e999bba..0bae053 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -4,6 +4,36 @@ #include "hw/ppc/spapr.h" #include "mmu-hash64.h" +struct SPRSyncState { + CPUState *cs; + int spr; + target_ulong value; + target_ulong mask; +}; + +static void do_spr_sync(void *arg) +{ + struct SPRSyncState *s = arg; + PowerPCCPU *cpu = POWERPC_CPU(s->cs); + CPUPPCState *env = &cpu->env; + + cpu_synchronize_state(s->cs); + env->spr[s->spr] &= ~s->mask; + env->spr[s->spr] |= s->value; +} + +static void set_spr(CPUState *cs, int spr, target_ulong value, + target_ulong mask) +{ + struct SPRSyncState s = { + .cs = cs, + .spr = spr, + .value = value, + .mask = mask + }; + run_on_cpu(cs, do_spr_sync, &s); +} + static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r, target_ulong pte_index) { @@ -110,16 +140,15 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, if (likely((flags & H_EXACT) == 0)) { pte_index &= ~7ULL; token = ppc_hash64_start_access(cpu, pte_index); - do { - if (index == 8) { - ppc_hash64_stop_access(token); - return H_PTEG_FULL; - } + for (; index < 8; index++) { if ((ppc_hash64_load_hpte0(env, token, index) & HPTE64_V_VALID) == 0) { break; } - } while (index++); + } ppc_hash64_stop_access(token); + if (index == 8) { + return H_PTEG_FULL; + } } else { token = ppc_hash64_start_access(cpu, pte_index); if (ppc_hash64_load_hpte0(env, token, 0) & HPTE64_V_VALID) { @@ -690,7 +719,7 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong value2 = args[3]; target_ulong ret = H_P2; - if (resource == H_SET_MODE_ENDIAN) { + if (resource == H_SET_MODE_RESOURCE_LE) { if (value1) { ret = H_P3; goto out; @@ -699,22 +728,17 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr, ret = H_P4; goto out; } - switch (mflags) { case H_SET_MODE_ENDIAN_BIG: CPU_FOREACH(cs) { - PowerPCCPU *cp = POWERPC_CPU(cs); - CPUPPCState *env = &cp->env; - env->spr[SPR_LPCR] &= ~LPCR_ILE; + set_spr(cs, SPR_LPCR, 0, LPCR_ILE); } ret = H_SUCCESS; break; case H_SET_MODE_ENDIAN_LITTLE: CPU_FOREACH(cs) { - PowerPCCPU *cp = POWERPC_CPU(cs); - CPUPPCState *env = &cp->env; - env->spr[SPR_LPCR] |= LPCR_ILE; + set_spr(cs, SPR_LPCR, LPCR_ILE, LPCR_ILE); } ret = H_SUCCESS; break; diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 4e33f46..2ae06a3 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -68,6 +68,7 @@ static void spapr_vio_bus_class_init(ObjectClass *klass, void *data) BusClass *k = BUS_CLASS(klass); k->get_dev_path = spapr_vio_get_dev_name; + k->get_fw_dev_path = spapr_vio_get_dev_name; } static const TypeInfo spapr_vio_bus_info = { @@ -529,7 +530,9 @@ static int spapr_vio_bridge_init(SysBusDevice *dev) static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + dc->fw_name = "vdevice"; k->init = spapr_vio_bridge_init; } |