diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-15 14:00:06 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-15 14:00:15 +0100 |
commit | 2f77ec7390d307842286f64019475c4fdf5dad18 (patch) | |
tree | cfcee905da63cc0c40ed544d79412996b99f4667 | |
parent | 3a8760664d5c1a1a93c9012bdb8ac07ab8fd4b0d (diff) | |
parent | e9edd931eb1b7e4be2274a8d9b3e5d5c4b7d1aad (diff) | |
download | qemu-2f77ec7390d307842286f64019475c4fdf5dad18.zip qemu-2f77ec7390d307842286f64019475c4fdf5dad18.tar.gz qemu-2f77ec7390d307842286f64019475c4fdf5dad18.tar.bz2 |
Merge remote-tracking branch 'dgibson/tags/ppc-for-2.10-20170511' into staging
ppc patch queue for 2017-05-11
This pull request supersedes the one from yesterday (20170510), fixing
an important style bug in one patch, and adding an extra couple of
simple patches.
Highlights of this set:
* Some fixes for POWER9
* TCG support for POWER9 radix MMU
* VGA rom for Mac machine types
* Fixes for the XICS interrupt controller
* MTTCG support for ppc targets
As suggested by Paolo, I've tried to add the Docker tests to my
standard pre-pull-request tests. I haven't wholly suceeded; this has
been tested with some of the Docker images, but others I haven't
managed due to problems that as best I can tell are not due to
problems in this patch series. I'll continue working on this for
future pull requests. Specifically, 'travis', 'fedora', and 'centos6'
seem to work. 'min-glib' jammed while gtesting moxie, which seems
very unlikely to be caused by this series. 'ubuntu', 'debian' and
'debian-bootstrap' hit build errors almost immediately that look like
problems with the container configuration, and 'debian-*-cross' hit
build errors later on which also look like missing dependencies from
the container.
# gpg: Signature made Thu 11 May 2017 05:13:46 AM BST
# gpg: using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>"
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* dgibson/tags/ppc-for-2.10-20170511: (23 commits)
target/ppc: Avoid printing wrong aliases in CPU help text
pnv: Fix build failures on some host platforms
target/ppc: Allow workarounds for POWER9 DD1
spapr: Don't accidentally advertise HTM support on POWER9
ppc: xics: fix compilation with CentOS 6
target/ppc: Enable RADIX mmu mode for pseries TCG guest
target/ppc: Implement ISA V3.00 radix page fault handler
target/ppc: Change tlbie invalid fields for POWER9 support
target/ppc: Update tlbie to check privilege level based on GTSE
target/ppc: Set UPRT and GTSE on all cpus in H_REGISTER_PROCESS_TABLE
ppc: add qemu_vga.ndrv ROM to fw_cfg interface for NewWorld Macs
ppc: add qemu_vga.ndrv ROM to fw_cfg interface for OldWorld Macs
Add QemuMacDrivers qemu_vga.ndrv revision d4e7d7a built as submodule
Add QemuMacDrivers as submodule
ppc/xics: preserve P and Q bits for KVM IRQs
ppc/xics: Fix stale irq->status bits after get
target/ppc: do not reset reserve_addr in exec_enter
tcg: enable MTTCG by default for PPC64 on x86
cpus: Fix CPU unplug for MTTCG
target/ppc: Generate fence operations
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | cpus.c | 6 | ||||
-rw-r--r-- | cputlb.c | 8 | ||||
-rw-r--r-- | hw/intc/xics_kvm.c | 13 | ||||
-rw-r--r-- | hw/ppc/mac_newworld.c | 18 | ||||
-rw-r--r-- | hw/ppc/mac_oldworld.c | 18 | ||||
-rw-r--r-- | hw/ppc/pnv.c | 2 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 17 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 18 | ||||
-rw-r--r-- | include/hw/ppc/pnv.h | 3 | ||||
-rw-r--r-- | include/hw/ppc/pnv_lpc.h | 4 | ||||
-rw-r--r-- | include/hw/ppc/pnv_occ.h | 4 | ||||
-rw-r--r-- | include/hw/ppc/xics.h | 4 | ||||
-rw-r--r-- | pc-bios/README | 3 | ||||
-rw-r--r-- | pc-bios/qemu_vga.ndrv | bin | 0 -> 14752 bytes | |||
m--------- | roms/QemuMacDrivers | 0 | ||||
-rw-r--r-- | target/ppc/Makefile.objs | 1 | ||||
-rw-r--r-- | target/ppc/cpu-models.h | 1 | ||||
-rw-r--r-- | target/ppc/cpu.h | 5 | ||||
-rw-r--r-- | target/ppc/excp_helper.c | 3 | ||||
-rw-r--r-- | target/ppc/kvm.c | 23 | ||||
-rw-r--r-- | target/ppc/mmu-book3s-v3.c | 6 | ||||
-rw-r--r-- | target/ppc/mmu-book3s-v3.h | 5 | ||||
-rw-r--r-- | target/ppc/mmu-radix64.c | 259 | ||||
-rw-r--r-- | target/ppc/mmu-radix64.h | 72 | ||||
-rw-r--r-- | target/ppc/translate.c | 48 | ||||
-rw-r--r-- | target/ppc/translate_init.c | 38 |
29 files changed, 524 insertions, 63 deletions
diff --git a/.gitmodules b/.gitmodules index ca323b4..5b0c212 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,3 +34,6 @@ [submodule "roms/skiboot"] path = roms/skiboot url = git://git.qemu.org/skiboot.git +[submodule "roms/QemuMacDrivers"] + path = roms/QemuMacDrivers + url = git://git.qemu.org/QemuMacDrivers.git @@ -552,7 +552,8 @@ multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \ s390-ccw.img \ spapr-rtas.bin slof.bin skiboot.lid \ palcode-clipper \ -u-boot.e500 +u-boot.e500 \ +qemu_vga.ndrv else BLOBS= endif @@ -6101,12 +6101,14 @@ case "$target_name" in ppc64) TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc + mttcg=yes gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" ;; ppc64le) TARGET_ARCH=ppc64 TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc + mttcg=yes gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" ;; ppc64abi32) @@ -1483,6 +1483,12 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) /* Ignore everything else? */ break; } + } else if (cpu->unplug) { + qemu_tcg_destroy_vcpu(cpu); + cpu->created = false; + qemu_cond_signal(&qemu_cpu_cond); + qemu_mutex_unlock_iothread(); + return NULL; } atomic_mb_set(&cpu->exit_request, 0); @@ -930,7 +930,13 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr, tlb_addr = tlbe->addr_write; } - /* Notice an IO access, or a notdirty page. */ + /* Check notdirty */ + if (unlikely(tlb_addr & TLB_NOTDIRTY)) { + tlb_set_dirty(ENV_GET_CPU(env), addr); + tlb_addr = tlb_addr & ~TLB_NOTDIRTY; + } + + /* Notice an IO access */ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { /* There's really nothing that can be done to support this apart from stop-the-world. */ diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 42e0e0e..dd93531 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -213,6 +213,7 @@ static void ics_get_kvm_state(ICSState *ics) irq->priority = irq->saved_priority; } + irq->status = 0; if (state & KVM_XICS_PENDING) { if (state & KVM_XICS_LEVEL_SENSITIVE) { irq->status |= XICS_STATUS_ASSERTED; @@ -228,6 +229,12 @@ static void ics_get_kvm_state(ICSState *ics) | XICS_STATUS_REJECTED; } } + if (state & KVM_XICS_PRESENTED) { + irq->status |= XICS_STATUS_PRESENTED; + } + if (state & KVM_XICS_QUEUED) { + irq->status |= XICS_STATUS_QUEUED; + } } } @@ -265,6 +272,12 @@ static int ics_set_kvm_state(ICSState *ics, int version_id) state |= KVM_XICS_PENDING; } } + if (irq->status & XICS_STATUS_PRESENTED) { + state |= KVM_XICS_PRESENTED; + } + if (irq->status & XICS_STATUS_QUEUED) { + state |= KVM_XICS_QUEUED; + } ret = ioctl(kernel_xics_fd, KVM_SET_DEVICE_ATTR, &attr); if (ret != 0) { diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 68aaedc..bae1c0a 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -80,6 +80,8 @@ #define CLOCKFREQ (266UL * 1000UL * 1000UL) #define BUSFREQ (100UL * 1000UL * 1000UL) +#define NDRV_VGA_FILENAME "qemu_vga.ndrv" + /* UniN device */ static void unin_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) @@ -160,7 +162,8 @@ static void ppc_core99_init(MachineState *machine) MACIOIDEState *macio_ide; BusState *adb_bus; MacIONVRAMState *nvr; - int bios_size; + int bios_size, ndrv_size; + uint8_t *ndrv_file; MemoryRegion *pic_mem, *escc_mem; MemoryRegion *escc_bar = g_new(MemoryRegion, 1); int ppc_boot_device; @@ -494,6 +497,19 @@ static void ppc_core99_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_NVRAM_ADDR, nvram_addr); + /* MacOS NDRV VGA driver */ + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME); + if (filename) { + ndrv_size = get_image_size(filename); + if (ndrv_size != -1) { + ndrv_file = g_malloc(ndrv_size); + ndrv_size = load_image(filename, ndrv_file); + + fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size); + } + g_free(filename); + } + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 5df94e2..97bb854 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -53,6 +53,8 @@ #define CLOCKFREQ 266000000UL #define BUSFREQ 66000000UL +#define NDRV_VGA_FILENAME "qemu_vga.ndrv" + static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) { @@ -99,7 +101,8 @@ static void ppc_heathrow_init(MachineState *machine) MACIOIDEState *macio_ide; DeviceState *dev; BusState *adb_bus; - int bios_size; + int bios_size, ndrv_size; + uint8_t *ndrv_file; MemoryRegion *pic_mem; MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1); uint16_t ppc_boot_device; @@ -355,6 +358,19 @@ static void ppc_heathrow_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); + /* MacOS NDRV VGA driver */ + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME); + if (filename) { + ndrv_size = get_image_size(filename); + if (ndrv_size != -1) { + ndrv_file = g_malloc(ndrv_size); + ndrv_size = load_image(filename, ndrv_file); + + fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size); + } + g_free(filename); + } + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6a49856..231ed97 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -511,7 +511,7 @@ static void ppc_powernv_reset(void) * This is the internal simulator but it could also be an external * BMC. */ - obj = object_resolve_path_type("", TYPE_IPMI_BMC, NULL); + obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL); if (obj) { pnv->bmc = IPMI_BMC(obj); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 80d12d0..1b7cada 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -219,7 +219,7 @@ static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset, /* 16: Vector */ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 18 - 23 */ + 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ @@ -855,6 +855,8 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) * option vector 5: */ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) { + PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); + char val[2 * 3] = { 24, 0x00, /* Hash/Radix, filled in below. */ 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ @@ -870,8 +872,13 @@ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) val[1] = 0x00; /* Hash */ } } else { - /* TODO: TCG case, hash */ - val[1] = 0x00; + if (first_ppc_cpu->env.mmu_model & POWERPC_MMU_V3) { + /* V3 MMU supports both hash and radix (with dynamic switching) */ + val[1] = 0xC0; + } else { + /* Otherwise we can only do hash */ + val[1] = 0x00; + } } _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", val, sizeof(val))); @@ -2101,8 +2108,8 @@ static void ppc_spapr_init(MachineState *machine) } spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); - if (kvmppc_has_cap_mmu_radix()) { - /* KVM always allows GTSE with radix... */ + if (!kvm_enabled() || kvmppc_has_cap_mmu_radix()) { + /* KVM and TCG always allow GTSE with radix... */ spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); } /* ... but not with hash (currently). */ diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 9f18f75..0d608d6 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -936,7 +936,7 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, target_ulong opcode, target_ulong *args) { - CPUPPCState *env = &cpu->env; + CPUState *cs; target_ulong flags = args[0]; target_ulong proc_tbl = args[1]; target_ulong page_size = args[2]; @@ -992,16 +992,12 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, spapr_check_setup_free_hpt(spapr, spapr->patb_entry, cproc); spapr->patb_entry = cproc; /* Save new process table */ - if ((flags & FLAG_RADIX) || (flags & FLAG_HASH_PROC_TBL)) { - /* Use Process TBL */ - env->spr[SPR_LPCR] |= LPCR_UPRT; - } else { - env->spr[SPR_LPCR] &= ~LPCR_UPRT; - } - if (flags & FLAG_GTSE) { /* Partition Uses Guest Translation Shootdwn */ - env->spr[SPR_LPCR] |= LPCR_GTSE; - } else { - env->spr[SPR_LPCR] &= ~LPCR_GTSE; + + /* Update the UPRT and GTSE bits in the LPCR for all cpus */ + CPU_FOREACH(cs) { + set_spr(cs, SPR_LPCR, LPCR_UPRT | LPCR_GTSE, + ((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) | + ((flags & FLAG_GTSE) ? LPCR_GTSE : 0)); } if (kvm_enabled()) { diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index c1288f9..9c5437d 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -21,6 +21,7 @@ #include "hw/boards.h" #include "hw/sysbus.h" +#include "hw/ipmi/ipmi.h" #include "hw/ppc/pnv_lpc.h" #include "hw/ppc/pnv_psi.h" #include "hw/ppc/pnv_occ.h" @@ -118,8 +119,6 @@ typedef struct PnvChipClass { #define POWERNV_MACHINE(obj) \ OBJECT_CHECK(PnvMachineState, (obj), TYPE_POWERNV_MACHINE) -typedef struct IPMIBmc IPMIBmc; - typedef struct PnvMachineState { /*< private >*/ MachineState parent_obj; diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h index ccf969af..023b4f0 100644 --- a/include/hw/ppc/pnv_lpc.h +++ b/include/hw/ppc/pnv_lpc.h @@ -19,12 +19,12 @@ #ifndef _PPC_PNV_LPC_H #define _PPC_PNV_LPC_H +#include "hw/ppc/pnv_psi.h" + #define TYPE_PNV_LPC "pnv-lpc" #define PNV_LPC(obj) \ OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV_LPC) -typedef struct PnvPsi PnvPsi; - typedef struct PnvLpcController { DeviceState parent; diff --git a/include/hw/ppc/pnv_occ.h b/include/hw/ppc/pnv_occ.h index f8ec330..82f299d 100644 --- a/include/hw/ppc/pnv_occ.h +++ b/include/hw/ppc/pnv_occ.h @@ -19,11 +19,11 @@ #ifndef _PPC_PNV_OCC_H #define _PPC_PNV_OCC_H +#include "hw/ppc/pnv_psi.h" + #define TYPE_PNV_OCC "pnv-occ" #define PNV_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV_OCC) -typedef struct PnvPsi PnvPsi; - typedef struct PnvOCC { DeviceState xd; diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index c215dc7..05e6acb 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -29,6 +29,7 @@ #define XICS_H #include "hw/qdev.h" +#include "target/ppc/cpu-qom.h" #define XICS_IPI 0x2 #define XICS_BUID 0x1 @@ -46,7 +47,6 @@ typedef struct ICSStateClass ICSStateClass; typedef struct ICSState ICSState; typedef struct ICSIRQState ICSIRQState; typedef struct XICSFabric XICSFabric; -typedef struct PowerPCCPU PowerPCCPU; #define TYPE_ICP "icp" #define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP) @@ -144,6 +144,8 @@ struct ICSIRQState { #define XICS_STATUS_SENT 0x2 #define XICS_STATUS_REJECTED 0x4 #define XICS_STATUS_MASKED_PENDING 0x8 +#define XICS_STATUS_PRESENTED 0x10 +#define XICS_STATUS_QUEUED 0x20 uint8_t status; /* (flags & XICS_FLAGS_IRQ_MASK) == 0 means the interrupt is not allocated */ #define XICS_FLAGS_IRQ_LSI 0x1 diff --git a/pc-bios/README b/pc-bios/README index dcead36..ebc699d 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -47,3 +47,6 @@ (OpenPower Abstraction Layer) firmware for OpenPOWER systems. It can run an hypervisor OS or simply a host OS on the "baremetal" platform, also known as the PowerNV (Non-Virtualized) platform. + +- QemuMacDrivers (https://github.com/ozbenh/QemuMacDrivers) is a project to + provide virtualised drivers for PPC MacOS guests. diff --git a/pc-bios/qemu_vga.ndrv b/pc-bios/qemu_vga.ndrv Binary files differnew file mode 100644 index 0000000..6e02f74 --- /dev/null +++ b/pc-bios/qemu_vga.ndrv diff --git a/roms/QemuMacDrivers b/roms/QemuMacDrivers new file mode 160000 +Subproject d4e7d7ac663fcb55f1b93575445fcbca372f17a diff --git a/target/ppc/Makefile.objs b/target/ppc/Makefile.objs index f963777..f92ba67 100644 --- a/target/ppc/Makefile.objs +++ b/target/ppc/Makefile.objs @@ -4,6 +4,7 @@ obj-y += translate.o ifeq ($(CONFIG_SOFTMMU),y) obj-y += machine.o mmu_helper.o mmu-hash32.o monitor.o arch_dump.o obj-$(TARGET_PPC64) += mmu-hash64.o mmu-book3s-v3.o compat.o +obj-$(TARGET_PPC64) += mmu-radix64.o endif obj-$(CONFIG_KVM) += kvm.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index d587e69..b563c45 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -561,6 +561,7 @@ enum { CPU_POWERPC_POWER8NVL_BASE = 0x004C0000, CPU_POWERPC_POWER8NVL_v10 = 0x004C0100, CPU_POWERPC_POWER9_BASE = 0x004E0000, + CPU_POWERPC_POWER9_DD1 = 0x004E0100, CPU_POWERPC_970_v22 = 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index e0ff041..401e10e 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -30,6 +30,8 @@ #define TARGET_LONG_BITS 64 #define TARGET_PAGE_BITS 12 +#define TCG_GUEST_DEFAULT_MO 0 + /* Note that the official physical address space bits is 62-M where M is implementation dependent. I've not looked up M for the set of cpus we emulate at the system level. */ @@ -480,6 +482,8 @@ struct ppc_slb_t { #define DSISR_ISSTORE 0x02000000 /* Not permitted by virtual page class key protection */ #define DSISR_AMR 0x00200000 +/* Unsupported Radix Tree Configuration */ +#define DSISR_R_BADCONFIG 0x00080000 /* SRR1 error code fields */ @@ -1221,6 +1225,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env) PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr); PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr); +PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc); struct PPCVirtualHypervisor { Object parent; diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index f4ee7aa..a6bcb47 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -728,6 +728,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) cs->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; + /* Reset the reservation */ + env->reserve_addr = -1; + /* Any interrupt is context synchronizing, check if TCG TLB * needs a delayed flush on ppc64 */ diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 8574c36..51249ce 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -2380,6 +2380,17 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) #if defined(TARGET_PPC64) pcc->radix_page_info = kvm_get_radix_page_info(); + + if ((pcc->pvr & 0xffffff00) == CPU_POWERPC_POWER9_DD1) { + /* + * POWER9 DD1 has some bugs which make it not really ISA 3.00 + * compliant. More importantly, advertising ISA 3.00 + * architected mode may prevent guests from activating + * necessary DD1 workarounds. + */ + pcc->pcr_supported &= ~(PCR_COMPAT_3_00 | PCR_COMPAT_2_07 + | PCR_COMPAT_2_06 | PCR_COMPAT_2_05); + } #endif /* defined(TARGET_PPC64) */ } @@ -2413,18 +2424,6 @@ bool kvmppc_has_cap_mmu_hash_v3(void) return cap_mmu_hash_v3; } -static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) -{ - ObjectClass *oc = OBJECT_CLASS(pcc); - - while (oc && !object_class_is_abstract(oc)) { - oc = object_class_get_parent(oc); - } - assert(oc); - - return POWERPC_CPU_CLASS(oc); -} - PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) { uint32_t host_pvr = mfpvr(); diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c index 005c963..e7798b3 100644 --- a/target/ppc/mmu-book3s-v3.c +++ b/target/ppc/mmu-book3s-v3.c @@ -22,15 +22,13 @@ #include "cpu.h" #include "mmu-hash64.h" #include "mmu-book3s-v3.h" -#include "qemu/error-report.h" +#include "mmu-radix64.h" int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx) { if (ppc64_radix_guest(cpu)) { /* Guest uses radix */ - /* TODO - Unsupported */ - error_report("Guest Radix Support Unimplemented"); - exit(1); + return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx); } else { /* Guest uses hash */ return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx); } diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h index 636f6ab..56095da 100644 --- a/target/ppc/mmu-book3s-v3.h +++ b/target/ppc/mmu-book3s-v3.h @@ -25,6 +25,11 @@ /* Partition Table Entry Fields */ #define PATBE1_GR 0x8000000000000000 +/* Process Table Entry */ +struct prtb_entry { + uint64_t prtbe0, prtbe1; +}; + #ifdef TARGET_PPC64 static inline bool ppc64_use_proc_tbl(PowerPCCPU *cpu) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c new file mode 100644 index 0000000..de18c0b --- /dev/null +++ b/target/ppc/mmu-radix64.c @@ -0,0 +1,259 @@ +/* + * PowerPC Radix MMU mulation helpers for QEMU. + * + * Copyright (c) 2016 Suraj Jitindar Singh, IBM Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" +#include "kvm_ppc.h" +#include "exec/log.h" +#include "mmu-radix64.h" +#include "mmu-book3s-v3.h" + +static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr, + uint64_t *lpid, uint64_t *pid) +{ + /* We don't have HV support yet and shouldn't get here with it set anyway */ + assert(!msr_hv); + + if (!msr_hv) { /* !MSR[HV] -> Guest */ + switch (eaddr & R_EADDR_QUADRANT) { + case R_EADDR_QUADRANT0: /* Guest application */ + *lpid = env->spr[SPR_LPIDR]; + *pid = env->spr[SPR_BOOKS_PID]; + break; + case R_EADDR_QUADRANT1: /* Illegal */ + case R_EADDR_QUADRANT2: + return false; + case R_EADDR_QUADRANT3: /* Guest OS */ + *lpid = env->spr[SPR_LPIDR]; + *pid = 0; /* pid set to 0 -> addresses guest operating system */ + break; + } + } + + return true; +} + +static void ppc_radix64_raise_segi(PowerPCCPU *cpu, int rwx, vaddr eaddr) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + if (rwx == 2) { /* Instruction Segment Interrupt */ + cs->exception_index = POWERPC_EXCP_ISEG; + } else { /* Data Segment Interrupt */ + cs->exception_index = POWERPC_EXCP_DSEG; + env->spr[SPR_DAR] = eaddr; + } + env->error_code = 0; +} + +static void ppc_radix64_raise_si(PowerPCCPU *cpu, int rwx, vaddr eaddr, + uint32_t cause) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + if (rwx == 2) { /* Instruction Storage Interrupt */ + cs->exception_index = POWERPC_EXCP_ISI; + env->error_code = cause; + } else { /* Data Storage Interrupt */ + cs->exception_index = POWERPC_EXCP_DSI; + if (rwx == 1) { /* Write -> Store */ + cause |= DSISR_ISSTORE; + } + env->spr[SPR_DSISR] = cause; + env->spr[SPR_DAR] = eaddr; + env->error_code = 0; + } +} + + +static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int rwx, uint64_t pte, + int *fault_cause, int *prot) +{ + CPUPPCState *env = &cpu->env; + const int need_prot[] = { PAGE_READ, PAGE_WRITE, PAGE_EXEC }; + + /* Check Page Attributes (pte58:59) */ + if (((pte & R_PTE_ATT) == R_PTE_ATT_NI_IO) && (rwx == 2)) { + /* + * Radix PTE entries with the non-idempotent I/O attribute are treated + * as guarded storage + */ + *fault_cause |= SRR1_NOEXEC_GUARD; + return true; + } + + /* Determine permissions allowed by Encoded Access Authority */ + if ((pte & R_PTE_EAA_PRIV) && msr_pr) { /* Insufficient Privilege */ + *prot = 0; + } else if (msr_pr || (pte & R_PTE_EAA_PRIV)) { + *prot = ppc_radix64_get_prot_eaa(pte); + } else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) */ + *prot = ppc_radix64_get_prot_eaa(pte); + *prot &= ppc_radix64_get_prot_amr(cpu); /* Least combined permissions */ + } + + /* Check if requested access type is allowed */ + if (need_prot[rwx] & ~(*prot)) { /* Page Protected for that Access */ + *fault_cause |= DSISR_PROTFAULT; + return true; + } + + return false; +} + +static void ppc_radix64_set_rc(PowerPCCPU *cpu, int rwx, uint64_t pte, + hwaddr pte_addr, int *prot) +{ + CPUState *cs = CPU(cpu); + uint64_t npte; + + npte = pte | R_PTE_R; /* Always set reference bit */ + + if (rwx == 1) { /* Store/Write */ + npte |= R_PTE_C; /* Set change bit */ + } else { + /* + * Treat the page as read-only for now, so that a later write + * will pass through this function again to set the C bit. + */ + *prot &= ~PAGE_WRITE; + } + + if (pte ^ npte) { /* If pte has changed then write it back */ + stq_phys(cs->as, pte_addr, npte); + } +} + +static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, int rwx, vaddr eaddr, + uint64_t base_addr, uint64_t nls, + hwaddr *raddr, int *psize, + int *fault_cause, int *prot, + hwaddr *pte_addr) +{ + CPUState *cs = CPU(cpu); + uint64_t index, pde; + + if (nls < 5) { /* Directory maps less than 2**5 entries */ + *fault_cause |= DSISR_R_BADCONFIG; + return 0; + } + + /* Read page <directory/table> entry from guest address space */ + index = eaddr >> (*psize - nls); /* Shift */ + index &= ((1UL << nls) - 1); /* Mask */ + pde = ldq_phys(cs->as, base_addr + (index * sizeof(pde))); + if (!(pde & R_PTE_VALID)) { /* Invalid Entry */ + *fault_cause |= DSISR_NOPTE; + return 0; + } + + *psize -= nls; + + /* Check if Leaf Entry -> Page Table Entry -> Stop the Search */ + if (pde & R_PTE_LEAF) { + uint64_t rpn = pde & R_PTE_RPN; + uint64_t mask = (1UL << *psize) - 1; + + if (ppc_radix64_check_prot(cpu, rwx, pde, fault_cause, prot)) { + return 0; /* Protection Denied Access */ + } + + /* Or high bits of rpn and low bits to ea to form whole real addr */ + *raddr = (rpn & ~mask) | (eaddr & mask); + *pte_addr = base_addr + (index * sizeof(pde)); + return pde; + } + + /* Next Level of Radix Tree */ + return ppc_radix64_walk_tree(cpu, rwx, eaddr, pde & R_PDE_NLB, + pde & R_PDE_NLS, raddr, psize, + fault_cause, prot, pte_addr); +} + +int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, + int mmu_idx) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + hwaddr raddr, pte_addr; + uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte; + int page_size, prot, fault_cause = 0; + + assert((rwx == 0) || (rwx == 1) || (rwx == 2)); + assert(!msr_hv); /* For now there is no Radix PowerNV Support */ + assert(cpu->vhyp); + assert(ppc64_use_proc_tbl(cpu)); + + /* Real Mode Access */ + if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) { + /* In real mode top 4 effective addr bits (mostly) ignored */ + raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; + + tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, + PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx, + TARGET_PAGE_SIZE); + return 0; + } + + /* Virtual Mode Access - get the fully qualified address */ + if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) { + ppc_radix64_raise_segi(cpu, rwx, eaddr); + return 1; + } + + /* Get Process Table */ + patbe = vhc->get_patbe(cpu->vhyp); + + /* Index Process Table by PID to Find Corresponding Process Table Entry */ + offset = pid * sizeof(struct prtb_entry); + size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12); + if (offset >= size) { + /* offset exceeds size of the process table */ + ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); + return 1; + } + prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset); + + /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ + page_size = PRTBE_R_GET_RTS(prtbe0); + pte = ppc_radix64_walk_tree(cpu, rwx, eaddr & R_EADDR_MASK, + prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, + &raddr, &page_size, &fault_cause, &prot, + &pte_addr); + if (!pte) { + ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); + return 1; + } + + /* Update Reference and Change Bits */ + ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, &prot); + + tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, + prot, mmu_idx, 1UL << page_size); + return 1; +} diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h new file mode 100644 index 0000000..1d5c7cf --- /dev/null +++ b/target/ppc/mmu-radix64.h @@ -0,0 +1,72 @@ +#ifndef MMU_RADIX64_H +#define MMU_RADIX64_H + +#ifndef CONFIG_USER_ONLY + +/* Radix Quadrants */ +#define R_EADDR_MASK 0x3FFFFFFFFFFFFFFF +#define R_EADDR_QUADRANT 0xC000000000000000 +#define R_EADDR_QUADRANT0 0x0000000000000000 +#define R_EADDR_QUADRANT1 0x4000000000000000 +#define R_EADDR_QUADRANT2 0x8000000000000000 +#define R_EADDR_QUADRANT3 0xC000000000000000 + +/* Radix Partition Table Entry Fields */ +#define PATBE1_R_PRTB 0x0FFFFFFFFFFFF000 +#define PATBE1_R_PRTS 0x000000000000001F + +/* Radix Process Table Entry Fields */ +#define PRTBE_R_GET_RTS(rts) \ + ((((rts >> 58) & 0x18) | ((rts >> 5) & 0x7)) + 31) +#define PRTBE_R_RPDB 0x0FFFFFFFFFFFFF00 +#define PRTBE_R_RPDS 0x000000000000001F + +/* Radix Page Directory/Table Entry Fields */ +#define R_PTE_VALID 0x8000000000000000 +#define R_PTE_LEAF 0x4000000000000000 +#define R_PTE_SW0 0x2000000000000000 +#define R_PTE_RPN 0x01FFFFFFFFFFF000 +#define R_PTE_SW1 0x0000000000000E00 +#define R_GET_SW(sw) (((sw >> 58) & 0x8) | ((sw >> 9) & 0x7)) +#define R_PTE_R 0x0000000000000100 +#define R_PTE_C 0x0000000000000080 +#define R_PTE_ATT 0x0000000000000030 +#define R_PTE_ATT_NORMAL 0x0000000000000000 +#define R_PTE_ATT_SAO 0x0000000000000010 +#define R_PTE_ATT_NI_IO 0x0000000000000020 +#define R_PTE_ATT_TOLERANT_IO 0x0000000000000030 +#define R_PTE_EAA_PRIV 0x0000000000000008 +#define R_PTE_EAA_R 0x0000000000000004 +#define R_PTE_EAA_RW 0x0000000000000002 +#define R_PTE_EAA_X 0x0000000000000001 +#define R_PDE_NLB PRTBE_R_RPDB +#define R_PDE_NLS PRTBE_R_RPDS + +#ifdef TARGET_PPC64 + +int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, + int mmu_idx); + +static inline int ppc_radix64_get_prot_eaa(uint64_t pte) +{ + return (pte & R_PTE_EAA_R ? PAGE_READ : 0) | + (pte & R_PTE_EAA_RW ? PAGE_READ | PAGE_WRITE : 0) | + (pte & R_PTE_EAA_X ? PAGE_EXEC : 0); +} + +static inline int ppc_radix64_get_prot_amr(PowerPCCPU *cpu) +{ + CPUPPCState *env = &cpu->env; + int amr = env->spr[SPR_AMR] >> 62; /* We only care about key0 AMR63:62 */ + int iamr = env->spr[SPR_IAMR] >> 62; /* We only care about key0 IAMR63:62 */ + + return (amr & 0x2 ? 0 : PAGE_WRITE) | /* Access denied if bit is set */ + (amr & 0x1 ? 0 : PAGE_READ) | + (iamr & 0x1 ? 0 : PAGE_EXEC); +} + +#endif /* TARGET_PPC64 */ + +#endif /* CONFIG_USER_ONLY */ + +#endif /* MMU_RADIX64_H */ diff --git a/target/ppc/translate.c b/target/ppc/translate.c index f40b5a1..c0cd64d 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -73,6 +73,7 @@ static TCGv cpu_cfar; #endif static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca, cpu_ov32, cpu_ca32; static TCGv cpu_reserve; +static TCGv cpu_reserve_val; static TCGv cpu_fpscr; static TCGv_i32 cpu_access_type; @@ -181,6 +182,9 @@ void ppc_translate_init(void) cpu_reserve = tcg_global_mem_new(cpu_env, offsetof(CPUPPCState, reserve_addr), "reserve_addr"); + cpu_reserve_val = tcg_global_mem_new(cpu_env, + offsetof(CPUPPCState, reserve_val), + "reserve_val"); cpu_fpscr = tcg_global_mem_new(cpu_env, offsetof(CPUPPCState, fpscr), "fpscr"); @@ -214,6 +218,7 @@ struct DisasContext { bool vsx_enabled; bool spe_enabled; bool tm_enabled; + bool gtse; ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ int singlestep_enabled; uint64_t insns_flags; @@ -2967,6 +2972,7 @@ static void gen_stswx(DisasContext *ctx) /* eieio */ static void gen_eieio(DisasContext *ctx) { + tcg_gen_mb(TCG_MO_LD_ST | TCG_BAR_SC); } #if !defined(CONFIG_USER_ONLY) @@ -3004,6 +3010,7 @@ static void gen_isync(DisasContext *ctx) if (!ctx->pr) { gen_check_tlb_flush(ctx, false); } + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); gen_stop_exception(ctx); } @@ -3023,7 +3030,8 @@ static void gen_##name(DisasContext *ctx) \ } \ tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, memop); \ tcg_gen_mov_tl(cpu_reserve, t0); \ - tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val)); \ + tcg_gen_mov_tl(cpu_reserve_val, gpr); \ + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); \ tcg_temp_free(t0); \ } @@ -3155,14 +3163,31 @@ static void gen_conditional_store(DisasContext *ctx, TCGv EA, static void gen_conditional_store(DisasContext *ctx, TCGv EA, int reg, int memop) { - TCGLabel *l1; + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + TCGv t0; - tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); - l1 = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1); - tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ); - tcg_gen_qemu_st_tl(cpu_gpr[reg], EA, ctx->mem_idx, memop); + + t0 = tcg_temp_new(); + tcg_gen_atomic_cmpxchg_tl(t0, cpu_reserve, cpu_reserve_val, + cpu_gpr[reg], ctx->mem_idx, + DEF_MEMOP(memop) | MO_ALIGN); + tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_reserve_val); + tcg_gen_shli_tl(t0, t0, CRF_EQ_BIT); + tcg_gen_or_tl(t0, t0, cpu_so); + tcg_gen_trunc_tl_i32(cpu_crf[0], t0); + tcg_temp_free(t0); + tcg_gen_br(l2); + gen_set_label(l1); + + /* Address mismatch implies failure. But we still need to provide the + memory barrier semantics of the instruction. */ + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); + + gen_set_label(l2); tcg_gen_movi_tl(cpu_reserve, -1); } #endif @@ -3291,6 +3316,7 @@ static void gen_sync(DisasContext *ctx) if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) { gen_check_tlb_flush(ctx, true); } + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); } /* wait */ @@ -4513,7 +4539,12 @@ static void gen_tlbie(DisasContext *ctx) GEN_PRIV; #else TCGv_i32 t1; - CHK_HV; + + if (ctx->gtse) { + CHK_SV; /* If gtse is set then tblie is supervisor privileged */ + } else { + CHK_HV; /* Else hypervisor privileged */ + } if (NARROW_MODE(ctx)) { TCGv t0 = tcg_temp_new(); @@ -6547,6 +6578,8 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA), * different ISA versions */ GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE), GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE), +GEN_HANDLER_E(tlbiel, 0x1F, 0x12, 0x08, 0x00100001, PPC_NONE, PPC2_ISA300), +GEN_HANDLER_E(tlbie, 0x1F, 0x12, 0x09, 0x00100001, PPC_NONE, PPC2_ISA300), GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC), #if defined(TARGET_PPC64) GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x031FFC01, PPC_SLBI), @@ -7227,6 +7260,7 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb) ctx.tm_enabled = false; } #endif + ctx.gtse = !!(env->spr[SPR_LPCR] & LPCR_GTSE); if ((env->flags & POWERPC_FLAG_SE) && msr_se) ctx.singlestep_enabled = CPU_SINGLE_STEP; else diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index e82e3e6..56a0ab2 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -8960,7 +8960,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) PPC_FLOAT_EXT | PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | - PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | + PPC_MEM_TLBSYNC | PPC_64B | PPC_64BX | PPC_ALTIVEC | PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD | @@ -10285,6 +10285,18 @@ PowerPCCPU *cpu_ppc_init(const char *cpu_model) return POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model)); } +PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) +{ + ObjectClass *oc = OBJECT_CLASS(pcc); + + while (oc && !object_class_is_abstract(oc)) { + oc = object_class_get_parent(oc); + } + assert(oc); + + return POWERPC_CPU_CLASS(oc); +} + /* Sort by PVR, ordering special case "host" last. */ static gint ppc_cpu_list_compare(gconstpointer a, gconstpointer b) { @@ -10316,6 +10328,7 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data) ObjectClass *oc = data; CPUListState *s = user_data; PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + DeviceClass *family = DEVICE_CLASS(ppc_cpu_get_family_class(pcc)); const char *typename = object_class_get_name(oc); char *name; int i; @@ -10338,8 +10351,18 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data) if (alias_oc != oc) { continue; } - (*s->cpu_fprintf)(s->file, "PowerPC %-16s (alias for %s)\n", - alias->alias, name); + /* + * If running with KVM, we might update the family alias later, so + * avoid printing the wrong alias here and use "preferred" instead + */ + if (strcmp(alias->alias, family->desc) == 0) { + (*s->cpu_fprintf)(s->file, + "PowerPC %-16s (alias for preferred %s CPU)\n", + alias->alias, family->desc); + } else { + (*s->cpu_fprintf)(s->file, "PowerPC %-16s (alias for %s)\n", + alias->alias, name); + } } g_free(name); } @@ -10436,14 +10459,6 @@ static bool ppc_cpu_has_work(CPUState *cs) return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD); } -static void ppc_cpu_exec_enter(CPUState *cs) -{ - PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - - env->reserve_addr = -1; -} - /* CPUClass::reset() */ static void ppc_cpu_reset(CPUState *s) { @@ -10660,7 +10675,6 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug; cc->vmsd = &vmstate_ppc_cpu; #endif - cc->cpu_exec_enter = ppc_cpu_exec_enter; #if defined(CONFIG_SOFTMMU) cc->write_elf64_note = ppc64_cpu_write_elf64_note; cc->write_elf32_note = ppc32_cpu_write_elf32_note; |