diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2013-04-27 00:33:23 +0200 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2013-04-27 00:33:23 +0200 |
commit | 076bfd7c65ce08c18d0c375e3779be25206ee2b7 (patch) | |
tree | 971dce0c1274b68054d48395113d0c449dfa5498 | |
parent | 75f6e8b0f121beeee6a95eb9e35d88ec1f01824f (diff) | |
parent | 7d08d85645def18eac2a9d672c1868a35e0bcf79 (diff) | |
download | hqemu-076bfd7c65ce08c18d0c375e3779be25206ee2b7.zip hqemu-076bfd7c65ce08c18d0c375e3779be25206ee2b7.tar.gz |
Merge branch 'ppc-for-upstream' of git://github.com/agraf/qemu
* 'ppc-for-upstream' of git://github.com/agraf/qemu: (30 commits)
target-ppc: add support for extended mtfsf/mtfsfi forms
target-ppc: emulate store doubleword pair instructions
target-ppc: emulate load doubleword pair instructions
target-ppc: emulate lfiwax instruction
target-ppc: emulate fcpsgn instruction
target-ppc: emulate prtyw and prtyd instructions
target-ppc: emulate cmpb instruction
target-ppc: add instruction flags for Book I 2.05
disas: Disassemble all ppc insns for the guest
target-ppc: optimize fabs, fnabs, fneg
PPC: Fix dcbz for linux-user on 970
powerpc: correctly handle fpu exceptions.
pseries: Generate device paths for VIO devices
pseries: Convert VIO code to QOM style type safe(ish) casts
target-ppc: Synchronize VPA state with KVM
pseries: Fix some small errors in XICS logic
target-ppc: Add more stubs for POWER7 PMU registers
pseries: Fixes and enhancements to L1 cache properties
pseries: Fix incorrect calculation of RMA size in certain configurations
PPC: Fix compile with profiling enabled
...
-rw-r--r-- | disas.c | 1 | ||||
-rw-r--r-- | hw/char/spapr_vty.c | 18 | ||||
-rw-r--r-- | hw/net/spapr_llan.c | 24 | ||||
-rw-r--r-- | hw/nvram/spapr_nvram.c | 10 | ||||
-rw-r--r-- | hw/ppc/e500plat.c | 7 | ||||
-rw-r--r-- | hw/ppc/mac_newworld.c | 2 | ||||
-rw-r--r-- | hw/ppc/ppc_booke.c | 45 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 27 | ||||
-rw-r--r-- | hw/ppc/spapr_vio.c | 41 | ||||
-rw-r--r-- | hw/ppc/xics.c | 2 | ||||
-rw-r--r-- | hw/scsi/spapr_vscsi.c | 15 | ||||
-rw-r--r-- | linux-headers/asm-powerpc/kvm.h | 5 | ||||
-rw-r--r-- | linux-headers/linux/kvm.h | 3 | ||||
-rw-r--r-- | target-ppc/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-ppc/cpu.h | 6 | ||||
-rw-r--r-- | target-ppc/fpu_helper.c | 71 | ||||
-rw-r--r-- | target-ppc/helper.h | 4 | ||||
-rw-r--r-- | target-ppc/int_helper.c | 15 | ||||
-rw-r--r-- | target-ppc/kvm.c | 237 | ||||
-rw-r--r-- | target-ppc/kvm_ppc.h | 30 | ||||
-rw-r--r-- | target-ppc/machine.c | 2 | ||||
-rw-r--r-- | target-ppc/mem_helper.c | 2 | ||||
-rw-r--r-- | target-ppc/translate.c | 296 | ||||
-rw-r--r-- | target-ppc/translate_init.c | 117 | ||||
-rw-r--r-- | translate-all.c | 1 |
25 files changed, 796 insertions, 186 deletions
@@ -227,6 +227,7 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code, s.info.mach = bfd_mach_ppc; #endif } + s.info.disassembler_options = (char *)"any"; print_insn = print_insn_ppc; #elif defined(TARGET_M68K) print_insn = print_insn_m68k; diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index afcec1f..2993848 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -12,16 +12,20 @@ typedef struct VIOsPAPRVTYDevice { uint8_t buf[VTERM_BUFSIZE]; } VIOsPAPRVTYDevice; +#define TYPE_VIO_SPAPR_VTY_DEVICE "spapr-vty" +#define VIO_SPAPR_VTY_DEVICE(obj) \ + OBJECT_CHECK(VIOsPAPRVTYDevice, (obj), TYPE_VIO_SPAPR_VTY_DEVICE) + static int vty_can_receive(void *opaque) { - VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque; + VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque); return (dev->in - dev->out) < VTERM_BUFSIZE; } static void vty_receive(void *opaque, const uint8_t *buf, int size) { - VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque; + VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque); int i; if ((dev->in == dev->out) && size) { @@ -36,7 +40,7 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size) static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max) { - VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev; + VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev); int n = 0; while ((n < max) && (dev->out != dev->in)) { @@ -48,7 +52,7 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max) void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len) { - VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev; + VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev); /* FIXME: should check the qemu_chr_fe_write() return value */ qemu_chr_fe_write(dev->chardev, buf, len); @@ -56,7 +60,7 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len) static int spapr_vty_init(VIOsPAPRDevice *sdev) { - VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev; + VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev); if (!dev->chardev) { fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n"); @@ -151,7 +155,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data) } static const TypeInfo spapr_vty_info = { - .name = "spapr-vty", + .name = TYPE_VIO_SPAPR_VTY_DEVICE, .parent = TYPE_VIO_SPAPR_DEVICE, .instance_size = sizeof(VIOsPAPRVTYDevice), .class_init = spapr_vty_class_init, @@ -177,7 +181,7 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus) continue; } - sdev = DO_UPCAST(VIOsPAPRDevice, qdev, iter); + sdev = VIO_SPAPR_DEVICE(iter); /* First VTY we've found, so it is selected for now */ if (!selected) { diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index 34332f2..3150add 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -73,6 +73,10 @@ typedef uint64_t vlan_bd_t; #define VLAN_RX_BDS_OFF 16 #define VLAN_MAX_BUFS ((SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8) +#define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan" +#define VIO_SPAPR_VLAN_DEVICE(obj) \ + OBJECT_CHECK(VIOsPAPRVLANDevice, (obj), TYPE_VIO_SPAPR_VLAN_DEVICE) + typedef struct VIOsPAPRVLANDevice { VIOsPAPRDevice sdev; NICConf nicconf; @@ -93,8 +97,8 @@ static int spapr_vlan_can_receive(NetClientState *nc) static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf, size_t size) { - VIOsPAPRDevice *sdev = qemu_get_nic_opaque(nc); - VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev; + VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc); + VIOsPAPRDevice *sdev = VIO_SPAPR_DEVICE(dev); vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF); vlan_bd_t bd; int buf_ptr = dev->use_buf_ptr; @@ -192,7 +196,7 @@ static NetClientInfo net_spapr_vlan_info = { static void spapr_vlan_reset(VIOsPAPRDevice *sdev) { - VIOsPAPRVLANDevice *dev = DO_UPCAST(VIOsPAPRVLANDevice, sdev, sdev); + VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev); dev->buf_list = 0; dev->rx_bufs = 0; @@ -201,7 +205,7 @@ static void spapr_vlan_reset(VIOsPAPRDevice *sdev) static int spapr_vlan_init(VIOsPAPRDevice *sdev) { - VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev; + VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev); qemu_macaddr_default_if_unset(&dev->nicconf.macaddr); @@ -225,7 +229,7 @@ void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd) static int spapr_vlan_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off) { - VIOsPAPRVLANDevice *vdev = (VIOsPAPRVLANDevice *)dev; + VIOsPAPRVLANDevice *vdev = VIO_SPAPR_VLAN_DEVICE(dev); uint8_t padded_mac[8] = {0, 0}; int ret; @@ -282,7 +286,7 @@ static target_ulong h_register_logical_lan(PowerPCCPU *cpu, target_ulong rec_queue = args[2]; target_ulong filter_list = args[3]; VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); - VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev; + VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev); vlan_bd_t filter_list_bd; if (!dev) { @@ -341,7 +345,7 @@ static target_ulong h_free_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr, { target_ulong reg = args[0]; VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); - VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev; + VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev); if (!dev) { return H_PARAMETER; @@ -365,7 +369,7 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu, target_ulong reg = args[0]; target_ulong buf = args[1]; VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); - VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev; + VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev); vlan_bd_t bd; dprintf("H_ADD_LOGICAL_LAN_BUFFER(0x" TARGET_FMT_lx @@ -413,7 +417,7 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong *bufs = args + 1; target_ulong continue_token = args[7]; VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); - VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev; + VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev); unsigned total_len; uint8_t *lbuf, *p; int i, nbufs; @@ -511,7 +515,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data) } static const TypeInfo spapr_vlan_info = { - .name = "spapr-vlan", + .name = TYPE_VIO_SPAPR_VLAN_DEVICE, .parent = TYPE_VIO_SPAPR_DEVICE, .instance_size = sizeof(VIOsPAPRVLANDevice), .class_init = spapr_vlan_class_init, diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index 0cc6cba..1eb05c9 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -36,6 +36,10 @@ typedef struct sPAPRNVRAM { BlockDriverState *drive; } sPAPRNVRAM; +#define TYPE_VIO_SPAPR_NVRAM "spapr-nvram" +#define VIO_SPAPR_NVRAM(obj) \ + OBJECT_CHECK(sPAPRNVRAM, (obj), TYPE_VIO_SPAPR_NVRAM) + #define MIN_NVRAM_SIZE 8192 #define DEFAULT_NVRAM_SIZE 65536 #define MAX_NVRAM_SIZE (UINT16_MAX * 16) @@ -134,7 +138,7 @@ static void rtas_nvram_store(sPAPREnvironment *spapr, static int spapr_nvram_init(VIOsPAPRDevice *dev) { - sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev; + sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev); if (nvram->drive) { nvram->size = bdrv_getlength(nvram->drive); @@ -157,7 +161,7 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev) static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off) { - sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev; + sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev); return fdt_setprop_cell(fdt, node_off, "#bytes", nvram->size); } @@ -182,7 +186,7 @@ static void spapr_nvram_class_init(ObjectClass *klass, void *data) } static const TypeInfo spapr_nvram_type_info = { - .name = "spapr-nvram", + .name = TYPE_VIO_SPAPR_NVRAM, .parent = TYPE_VIO_SPAPR_DEVICE, .instance_size = sizeof(sPAPRNVRAM), .class_init = spapr_nvram_class_init, diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index 7292ce1..c852995 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -16,6 +16,7 @@ #include "sysemu/device_tree.h" #include "hw/pci/pci.h" #include "hw/ppc/openpic.h" +#include "kvm_ppc.h" static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) { @@ -48,6 +49,12 @@ static void e500plat_init(QEMUMachineInitArgs *args) .mpic_version = OPENPIC_MODEL_FSL_MPIC_42, }; + /* Older KVM versions don't support EPR which breaks guests when we announce + MPIC variants that support EPR. Revert to an older one for those */ + if (kvm_enabled() && !kvmppc_has_cap_epr()) { + params.mpic_version = OPENPIC_MODEL_FSL_MPIC_20; + } + ppce500_init(¶ms); } diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 4a9b883..ce44e95 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -126,6 +126,8 @@ static void ppc_core99_reset(void *opaque) PowerPCCPU *cpu = opaque; cpu_reset(CPU(cpu)); + /* 970 CPUs want to get their initial IP as part of their boot protocol */ + cpu->env.nip = PROM_ADDR + 0x100; } /* PowerPC Mac99 hardware initialisation */ diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c index 585f53b..e41b036 100644 --- a/hw/ppc/ppc_booke.c +++ b/hw/ppc/ppc_booke.c @@ -28,6 +28,7 @@ #include "hw/timer/m48t59.h" #include "qemu/log.h" #include "hw/loader.h" +#include "kvm_ppc.h" /* Timer Control Register */ @@ -211,6 +212,7 @@ void store_booke_tsr(CPUPPCState *env, target_ulong val) PowerPCCPU *cpu = ppc_env_get_cpu(env); env->spr[SPR_BOOKE_TSR] &= ~val; + kvmppc_clear_tsr_bits(cpu, val); booke_update_irq(cpu); } @@ -222,6 +224,7 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val) tb_env = env->tb_env; env->spr[SPR_BOOKE_TCR] = val; + kvmppc_set_tcr(cpu); booke_update_irq(cpu); @@ -234,7 +237,6 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val) booke_get_wdt_target(env, tb_env), &booke_timer->wdt_next, booke_timer->wdt_timer); - } static void ppc_booke_timer_reset_handle(void *opaque) @@ -242,16 +244,39 @@ static void ppc_booke_timer_reset_handle(void *opaque) PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; - env->spr[SPR_BOOKE_TSR] = 0; - env->spr[SPR_BOOKE_TCR] = 0; + store_booke_tcr(env, 0); + store_booke_tsr(env, -1); +} - booke_update_irq(cpu); +/* + * This function will be called whenever the CPU state changes. + * CPU states are defined "typedef enum RunState". + * Regarding timer, When CPU state changes to running after debug halt + * or similar cases which takes time then in between final watchdog + * expiry happenes. This will cause exit to QEMU and configured watchdog + * action will be taken. To avoid this we always clear the watchdog state when + * state changes to running. + */ +static void cpu_state_change_handler(void *opaque, int running, RunState state) +{ + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; + + if (!running) { + return; + } + + /* + * Clear watchdog interrupt condition by clearing TSR. + */ + store_booke_tsr(env, TSR_ENW | TSR_WIS | TSR_WRS_MASK); } void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags) { ppc_tb_t *tb_env; booke_timer_t *booke_timer; + int ret = 0; tb_env = g_malloc0(sizeof(ppc_tb_t)); booke_timer = g_malloc0(sizeof(booke_timer_t)); @@ -269,5 +294,17 @@ void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags) booke_timer->wdt_timer = qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu); + ret = kvmppc_booke_watchdog_enable(cpu); + + if (ret) { + /* TODO: Start the QEMU emulated watchdog if not running on KVM. + * Also start the QEMU emulated watchdog if KVM does not support + * emulated watchdog or somehow it is not enabled (supported but + * not enabled is though some bug and requires debugging :)). + */ + } + + qemu_add_vm_change_state_handler(cpu_state_change_handler, cpu); + qemu_register_reset(ppc_booke_timer_reset_handle, cpu); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 7a42501..c96ac81 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -308,6 +308,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, for (env = first_cpu; env != NULL; env = env->next_cpu) { CPUState *cpu = CPU(ppc_env_get_cpu(env)); + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); int index = cpu->cpu_index; uint32_t servers_prop[smp_threads]; uint32_t gservers_prop[smp_threads * 2]; @@ -333,10 +334,26 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_property_string(fdt, "device_type", "cpu"))); _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR]))); - _FDT((fdt_property_cell(fdt, "dcache-block-size", + _FDT((fdt_property_cell(fdt, "d-cache-block-size", env->dcache_line_size))); - _FDT((fdt_property_cell(fdt, "icache-block-size", + _FDT((fdt_property_cell(fdt, "d-cache-line-size", + env->dcache_line_size))); + _FDT((fdt_property_cell(fdt, "i-cache-block-size", + env->icache_line_size))); + _FDT((fdt_property_cell(fdt, "i-cache-line-size", env->icache_line_size))); + + if (pcc->l1_dcache_size) { + _FDT((fdt_property_cell(fdt, "d-cache-size", pcc->l1_dcache_size))); + } else { + fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n"); + } + if (pcc->l1_icache_size) { + _FDT((fdt_property_cell(fdt, "i-cache-size", pcc->l1_icache_size))); + } else { + fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n"); + } + _FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq))); _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq))); _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr))); @@ -801,8 +818,10 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) /* Set time-base frequency to 512 MHz */ cpu_ppc_tb_init(env, TIMEBASE_FREQ); - /* PAPR always has exception vectors in RAM not ROM */ - env->hreset_excp_prefix = 0; + /* PAPR always has exception vectors in RAM not ROM. To ensure this, + * MSR[IP] should never be set. + */ + env->msr_mask &= ~(1 << 6); /* Tell KVM that we're in PAPR mode */ if (kvm_enabled()) { diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 4dbc315..1405c32 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -53,9 +53,29 @@ static Property spapr_vio_props[] = { DEFINE_PROP_END_OF_LIST(), }; +static char *spapr_vio_get_dev_name(DeviceState *qdev) +{ + VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev); + VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); + char *name; + + /* Device tree style name device@reg */ + name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg); + + return name; +} + +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; +} + static const TypeInfo spapr_vio_bus_info = { .name = TYPE_SPAPR_VIO_BUS, .parent = TYPE_BUS, + .class_init = spapr_vio_bus_class_init, .instance_size = sizeof(VIOsPAPRBus), }; @@ -74,17 +94,6 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) return NULL; } -static char *vio_format_dev_name(VIOsPAPRDevice *dev) -{ - VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); - char *name; - - /* Device tree style name device@reg */ - name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg); - - return name; -} - #ifdef CONFIG_FDT static int vio_make_devnode(VIOsPAPRDevice *dev, void *fdt) @@ -98,7 +107,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, return vdevice_off; } - dt_name = vio_format_dev_name(dev); + dt_name = spapr_vio_get_dev_name(DEVICE(dev)); node_off = fdt_add_subnode(fdt, vdevice_off, dt_name); g_free(dt_name); if (node_off < 0) { @@ -379,7 +388,7 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev) * the given dev might already be in the list. */ QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { - other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child); + other = VIO_SPAPR_DEVICE(kid->child); if (other != dev && other->reg == dev->reg) { return other; @@ -391,7 +400,7 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev) static void spapr_vio_busdev_reset(DeviceState *qdev) { - VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev); + VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev); VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); /* Shut down the request queue and TCEs if necessary */ @@ -437,7 +446,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev) /* Don't overwrite ids assigned on the command line */ if (!dev->qdev.id) { - id = vio_format_dev_name(dev); + id = spapr_vio_get_dev_name(DEVICE(dev)); dev->qdev.id = id; } @@ -636,7 +645,7 @@ int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus) return offset; } - name = vio_format_dev_name(dev); + name = spapr_vio_get_dev_name(DEVICE(dev)); path = g_strdup_printf("/vdevice/%s", name); ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path); diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c index 8e1e85e..1b25075 100644 --- a/hw/ppc/xics.c +++ b/hw/ppc/xics.c @@ -101,6 +101,7 @@ static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr) if (XISR(ss) && (cppr <= ss->pending_priority)) { old_xisr = XISR(ss); ss->xirr &= ~XISR_MASK; /* Clear XISR */ + ss->pending_priority = 0xff; qemu_irq_lower(ss->output); ics_reject(icp->ics, old_xisr); } @@ -127,6 +128,7 @@ static uint32_t icp_accept(struct icp_server_state *ss) qemu_irq_lower(ss->output); ss->xirr = ss->pending_priority << 24; + ss->pending_priority = 0xff; trace_xics_icp_accept(xirr, ss->xirr); diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index 999a463..3d322d5 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -91,6 +91,9 @@ typedef struct vscsi_req { int total_desc; } vscsi_req; +#define TYPE_VIO_SPAPR_VSCSI_DEVICE "spapr-vscsi" +#define VIO_SPAPR_VSCSI_DEVICE(obj) \ + OBJECT_CHECK(VSCSIState, (obj), TYPE_VIO_SPAPR_VSCSI_DEVICE) typedef struct { VIOsPAPRDevice vdev; @@ -461,7 +464,7 @@ static int vscsi_preprocess_desc(vscsi_req *req) /* Callback to indicate that the SCSI layer has completed a transfer. */ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len) { - VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent); + VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent); vscsi_req *req = sreq->hba_private; uint8_t *buf; int rc = 0; @@ -492,7 +495,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len) /* Callback to indicate that the SCSI layer has completed a transfer. */ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t resid) { - VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent); + VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent); vscsi_req *req = sreq->hba_private; int32_t res_in = 0, res_out = 0; @@ -827,7 +830,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq) static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data) { - VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev); + VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev); vscsi_crq crq; memcpy(crq.raw, crq_data, 16); @@ -897,7 +900,7 @@ static const struct SCSIBusInfo vscsi_scsi_info = { static void spapr_vscsi_reset(VIOsPAPRDevice *dev) { - VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev); + VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev); int i; memset(s->reqs, 0, sizeof(s->reqs)); @@ -908,7 +911,7 @@ static void spapr_vscsi_reset(VIOsPAPRDevice *dev) static int spapr_vscsi_init(VIOsPAPRDevice *dev) { - VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev); + VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev); dev->crq.SendFunc = vscsi_do_crq; @@ -968,7 +971,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data) } static const TypeInfo spapr_vscsi_info = { - .name = "spapr-vscsi", + .name = TYPE_VIO_SPAPR_VSCSI_DEVICE, .parent = TYPE_VIO_SPAPR_DEVICE, .instance_size = sizeof(VSCSIState), .class_init = spapr_vscsi_class_init, diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h index 16064d0..ef072b1 100644 --- a/linux-headers/asm-powerpc/kvm.h +++ b/linux-headers/asm-powerpc/kvm.h @@ -417,4 +417,9 @@ struct kvm_get_htab_header { #define KVM_REG_PPC_EPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85) #define KVM_REG_PPC_EPR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x86) +/* Timer Status Register OR/CLEAR interface */ +#define KVM_REG_PPC_OR_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x87) +#define KVM_REG_PPC_CLEAR_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88) +#define KVM_REG_PPC_TCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89) +#define KVM_REG_PPC_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a) #endif /* __LINUX_KVM_POWERPC_H */ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index caca979..eb02d8a 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -449,12 +449,15 @@ enum { kvm_ioeventfd_flag_nr_datamatch, kvm_ioeventfd_flag_nr_pio, kvm_ioeventfd_flag_nr_deassign, + kvm_ioeventfd_flag_nr_virtio_ccw_notify, kvm_ioeventfd_flag_nr_max, }; #define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch) #define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio) #define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign) +#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \ + (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify) #define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1) diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index c27cef7..eb03a00 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -63,6 +63,7 @@ typedef struct PowerPCCPUClass { powerpc_input_t bus_model; uint32_t flags; int bfd_mach; + uint32_t l1_dcache_size, l1_icache_size; #if defined(TARGET_PPC64) const struct ppc_segment_page_sizes *sps; #endif diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 42c36e2..7cacb56 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1026,7 +1026,6 @@ struct CPUPPCState { /* Exception vectors */ target_ulong excp_vectors[POWERPC_EXCP_NB]; target_ulong excp_prefix; - target_ulong hreset_excp_prefix; target_ulong ivor_mask; target_ulong ivpr_mask; target_ulong hreset_vector; @@ -1446,6 +1445,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp) #define SPR_PERF2 (0x302) #define SPR_RCPU_MI_RBA2 (0x302) #define SPR_MPC_MI_AP (0x302) +#define SPR_MMCRA (0x302) #define SPR_PERF3 (0x303) #define SPR_RCPU_MI_RBA3 (0x303) #define SPR_MPC_MI_EPN (0x303) @@ -1870,8 +1870,10 @@ enum { PPC2_PRCNTL = 0x0000000000000008ULL, /* Byte-reversed, indexed, double-word load and store */ PPC2_DBRX = 0x0000000000000010ULL, + /* Book I 2.05 PowerPC specification */ + PPC2_ISA205 = 0x0000000000000020ULL, -#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX) +#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX | PPC2_ISA205) }; /*****************************************************************************/ diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c index 9e779ea..4f60218 100644 --- a/target-ppc/fpu_helper.c +++ b/target-ppc/fpu_helper.c @@ -430,20 +430,17 @@ void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit) void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask) { - /* - * We use only the 32 LSB of the incoming fpr - */ - uint32_t prev, new; + target_ulong prev, new; int i; prev = env->fpscr; - new = (uint32_t)arg; - new &= ~0x60000000; - new |= prev & 0x60000000; - for (i = 0; i < 8; i++) { + new = (target_ulong)arg; + new &= ~0x60000000LL; + new |= prev & 0x60000000LL; + for (i = 0; i < sizeof(target_ulong) * 2; i++) { if (mask & (1 << i)) { - env->fpscr &= ~(0xF << (4 * i)); - env->fpscr |= new & (0xF << (4 * i)); + env->fpscr &= ~(0xFLL << (4 * i)); + env->fpscr |= new & (0xFLL << (4 * i)); } } /* Update VX and FEX */ @@ -470,6 +467,18 @@ void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask) void helper_float_check_status(CPUPPCState *env) { + int status = get_float_exception_flags(&env->fp_status); + + if (status & float_flag_divbyzero) { + float_zero_divide_excp(env); + } else if (status & float_flag_overflow) { + float_overflow_excp(env); + } else if (status & float_flag_underflow) { + float_underflow_excp(env); + } else if (status & float_flag_inexact) { + float_inexact_excp(env); + } + if (env->exception_index == POWERPC_EXCP_PROGRAM && (env->error_code & POWERPC_EXCP_FP)) { /* Differred floating-point exception after target FPR update */ @@ -477,17 +486,6 @@ void helper_float_check_status(CPUPPCState *env) helper_raise_exception_err(env, env->exception_index, env->error_code); } - } else { - int status = get_float_exception_flags(&env->fp_status); - if (status & float_flag_divbyzero) { - float_zero_divide_excp(env); - } else if (status & float_flag_overflow) { - float_overflow_excp(env); - } else if (status & float_flag_underflow) { - float_underflow_excp(env); - } else if (status & float_flag_inexact) { - float_inexact_excp(env); - } } } @@ -595,37 +593,6 @@ uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2) return farg1.ll; } -/* fabs */ -uint64_t helper_fabs(CPUPPCState *env, uint64_t arg) -{ - CPU_DoubleU farg; - - farg.ll = arg; - farg.d = float64_abs(farg.d); - return farg.ll; -} - -/* fnabs */ -uint64_t helper_fnabs(CPUPPCState *env, uint64_t arg) -{ - CPU_DoubleU farg; - - farg.ll = arg; - farg.d = float64_abs(farg.d); - farg.d = float64_chs(farg.d); - return farg.ll; -} - -/* fneg */ -uint64_t helper_fneg(CPUPPCState *env, uint64_t arg) -{ - CPU_DoubleU farg; - - farg.ll = arg; - farg.d = float64_chs(farg.d); - return farg.ll; -} - /* fctiw - fctiw. */ uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg) { diff --git a/target-ppc/helper.h b/target-ppc/helper.h index d33ee66..56814b5 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -36,6 +36,7 @@ DEF_HELPER_3(mulldo, i64, env, i64, i64) DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_2(cmpb, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_3(sraw, tl, env, tl, tl) #if defined(TARGET_PPC64) DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_NO_RWG_SE, tl, tl) @@ -80,9 +81,6 @@ DEF_HELPER_4(fmadd, i64, env, i64, i64, i64) DEF_HELPER_4(fmsub, i64, env, i64, i64, i64) DEF_HELPER_4(fnmadd, i64, env, i64, i64, i64) DEF_HELPER_4(fnmsub, i64, env, i64, i64, i64) -DEF_HELPER_2(fabs, i64, env, i64) -DEF_HELPER_2(fnabs, i64, env, i64) -DEF_HELPER_2(fneg, i64, env, i64) DEF_HELPER_2(fsqrt, i64, env, i64) DEF_HELPER_2(fre, i64, env, i64) DEF_HELPER_2(fres, i64, env, i64) diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 54eca9b..e50bdd2 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -53,6 +53,21 @@ target_ulong helper_cntlzd(target_ulong t) } #endif +target_ulong helper_cmpb(target_ulong rs, target_ulong rb) +{ + target_ulong mask = 0xff; + target_ulong ra = 0; + int i; + + for (i = 0; i < sizeof(target_ulong); i++) { + if ((rs & mask) == (rb & mask)) { + ra |= mask; + } + mask <<= 8; + } + return ra; +} + /* shift right arithmetic helper */ target_ulong helper_sraw(CPUPPCState *env, target_ulong value, target_ulong shift) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 5e9dddb..725071e 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -37,6 +37,7 @@ #include "hw/sysbus.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" +#include "sysemu/watchdog.h" //#define DEBUG_KVM @@ -63,6 +64,9 @@ static int cap_ppc_rma; static int cap_spapr_tce; static int cap_hior; static int cap_one_reg; +static int cap_epr; +static int cap_ppc_watchdog; +static int cap_papr; /* XXX We have a race condition where we actually have a level triggered * interrupt, but the infrastructure can't expose that yet, so the guest @@ -95,6 +99,10 @@ int kvm_arch_init(KVMState *s) cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE); cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG); cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR); + cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR); + cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG); + /* Note: we don't set cap_papr here, because this capability is + * only activated after this by kvmppc_set_papr() */ if (!cap_interrupt_level) { fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the " @@ -652,6 +660,103 @@ static int kvm_get_fp(CPUState *cs) return 0; } +#if defined(TARGET_PPC64) +static int kvm_get_vpa(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + struct kvm_one_reg reg; + int ret; + + reg.id = KVM_REG_PPC_VPA_ADDR; + reg.addr = (uintptr_t)&env->vpa_addr; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to get VPA address from KVM: %s\n", strerror(errno)); + return ret; + } + + assert((uintptr_t)&env->slb_shadow_size + == ((uintptr_t)&env->slb_shadow_addr + 8)); + reg.id = KVM_REG_PPC_VPA_SLB; + reg.addr = (uintptr_t)&env->slb_shadow_addr; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to get SLB shadow state from KVM: %s\n", + strerror(errno)); + return ret; + } + + assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8)); + reg.id = KVM_REG_PPC_VPA_DTL; + reg.addr = (uintptr_t)&env->dtl_addr; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to get dispatch trace log state from KVM: %s\n", + strerror(errno)); + return ret; + } + + return 0; +} + +static int kvm_put_vpa(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + struct kvm_one_reg reg; + int ret; + + /* SLB shadow or DTL can't be registered unless a master VPA is + * registered. That means when restoring state, if a VPA *is* + * registered, we need to set that up first. If not, we need to + * deregister the others before deregistering the master VPA */ + assert(env->vpa_addr || !(env->slb_shadow_addr || env->dtl_addr)); + + if (env->vpa_addr) { + reg.id = KVM_REG_PPC_VPA_ADDR; + reg.addr = (uintptr_t)&env->vpa_addr; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno)); + return ret; + } + } + + assert((uintptr_t)&env->slb_shadow_size + == ((uintptr_t)&env->slb_shadow_addr + 8)); + reg.id = KVM_REG_PPC_VPA_SLB; + reg.addr = (uintptr_t)&env->slb_shadow_addr; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set SLB shadow state to KVM: %s\n", strerror(errno)); + return ret; + } + + assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8)); + reg.id = KVM_REG_PPC_VPA_DTL; + reg.addr = (uintptr_t)&env->dtl_addr; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set dispatch trace log state to KVM: %s\n", + strerror(errno)); + return ret; + } + + if (!env->vpa_addr) { + reg.id = KVM_REG_PPC_VPA_ADDR; + reg.addr = (uintptr_t)&env->vpa_addr; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno)); + return ret; + } + } + + return 0; +} +#endif /* TARGET_PPC64 */ + int kvm_arch_put_registers(CPUState *cs, int level) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -752,6 +857,14 @@ int kvm_arch_put_registers(CPUState *cs, int level) kvm_put_one_spr(cs, id, i); } } + +#ifdef TARGET_PPC64 + if (cap_papr) { + if (kvm_put_vpa(cs) < 0) { + dprintf("Warning: Unable to set VPA information to KVM\n"); + } + } +#endif /* TARGET_PPC64 */ } return ret; @@ -953,6 +1066,14 @@ int kvm_arch_get_registers(CPUState *cs) kvm_get_one_spr(cs, id, i); } } + +#ifdef TARGET_PPC64 + if (cap_papr) { + if (kvm_get_vpa(cs) < 0) { + dprintf("Warning: Unable to get VPA information from KVM\n"); + } + } +#endif } return 0; @@ -1092,6 +1213,12 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) run->epr.epr = ldl_phys(env->mpic_iack); ret = 0; break; + case KVM_EXIT_WATCHDOG: + dprintf("handle watchdog expiry\n"); + watchdog_perform_action(); + ret = 0; + break; + default: fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); ret = -1; @@ -1101,6 +1228,71 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) return ret; } +int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) +{ + CPUState *cs = CPU(cpu); + uint32_t bits = tsr_bits; + struct kvm_one_reg reg = { + .id = KVM_REG_PPC_OR_TSR, + .addr = (uintptr_t) &bits, + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); +} + +int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) +{ + + CPUState *cs = CPU(cpu); + uint32_t bits = tsr_bits; + struct kvm_one_reg reg = { + .id = KVM_REG_PPC_CLEAR_TSR, + .addr = (uintptr_t) &bits, + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); +} + +int kvmppc_set_tcr(PowerPCCPU *cpu) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + uint32_t tcr = env->spr[SPR_BOOKE_TCR]; + + struct kvm_one_reg reg = { + .id = KVM_REG_PPC_TCR, + .addr = (uintptr_t) &tcr, + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); +} + +int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu) +{ + CPUState *cs = CPU(cpu); + struct kvm_enable_cap encap = {}; + int ret; + + if (!kvm_enabled()) { + return -1; + } + + if (!cap_ppc_watchdog) { + printf("warning: KVM does not support watchdog"); + return -1; + } + + encap.cap = KVM_CAP_PPC_BOOKE_WATCHDOG; + ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap); + if (ret < 0) { + fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n", + __func__, strerror(-ret)); + return ret; + } + + return ret; +} + static int read_cpuinfo(const char *field, char *value, int len) { FILE *f; @@ -1301,6 +1493,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu) if (ret) { cpu_abort(env, "This KVM version does not support PAPR\n"); } + + /* Update the capability flag so we sync the right information + * with kvm */ + cap_papr = 1; } void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy) @@ -1370,11 +1566,35 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem) uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift) { + struct kvm_ppc_smmu_info info; + long rampagesize, best_page_shift; + int i; + if (cap_ppc_rma >= 2) { return current_size; } + + /* Find the largest hardware supported page size that's less than + * or equal to the (logical) backing page size of guest RAM */ + kvm_get_smmu_info(ppc_env_get_cpu(first_cpu), &info); + rampagesize = getrampagesize(); + best_page_shift = 0; + + for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) { + struct kvm_ppc_one_seg_page_size *sps = &info.sps[i]; + + if (!sps->page_shift) { + continue; + } + + if ((sps->page_shift > best_page_shift) + && ((1UL << sps->page_shift) <= rampagesize)) { + best_page_shift = sps->page_shift; + } + } + return MIN(current_size, - getrampagesize() << (hash_shift - 7)); + 1ULL << (best_page_shift + hash_shift - 7)); } #endif @@ -1503,6 +1723,8 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); uint32_t vmx = kvmppc_get_vmx(); uint32_t dfp = kvmppc_get_dfp(); + uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size"); + uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size"); /* Now fix up the class with information we can query from the host */ @@ -1515,6 +1737,14 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) /* Only override when we know what the host supports */ alter_insns(&pcc->insns_flags2, PPC2_DFP, dfp); } + + if (dcache_size != -1) { + pcc->l1_dcache_size = dcache_size; + } + + if (icache_size != -1) { + pcc->l1_icache_size = icache_size; + } } int kvmppc_fixup_cpu(PowerPCCPU *cpu) @@ -1530,6 +1760,11 @@ int kvmppc_fixup_cpu(PowerPCCPU *cpu) return 0; } +bool kvmppc_has_cap_epr(void) +{ + return cap_epr; +} + static int kvm_ppc_register_host_cpu_type(void) { TypeInfo type_info = { diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index 6bcc5cc..771cfbe 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -25,6 +25,10 @@ int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level); void kvmppc_set_papr(PowerPCCPU *cpu); void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy); int kvmppc_smt_threads(void); +int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits); +int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits); +int kvmppc_set_tcr(PowerPCCPU *cpu); +int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu); #ifndef CONFIG_USER_ONLY off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem); void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd); @@ -33,6 +37,7 @@ int kvmppc_reset_htab(int shift_hint); uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift); #endif /* !CONFIG_USER_ONLY */ int kvmppc_fixup_cpu(PowerPCCPU *cpu); +bool kvmppc_has_cap_epr(void); #else @@ -89,6 +94,26 @@ static inline int kvmppc_smt_threads(void) return 1; } +static inline int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) +{ + return 0; +} + +static inline int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) +{ + return 0; +} + +static inline int kvmppc_set_tcr(PowerPCCPU *cpu) +{ + return 0; +} + +static inline int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu) +{ + return -1; +} + #ifndef CONFIG_USER_ONLY static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem) { @@ -129,6 +154,11 @@ static inline int kvmppc_fixup_cpu(PowerPCCPU *cpu) { return -1; } + +static inline bool kvmppc_has_cap_epr(void) +{ + return false; +} #endif #ifndef CONFIG_KVM diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 235b0d5..2d10adb 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -78,7 +78,6 @@ void cpu_save(QEMUFile *f, void *opaque) for (i = 0; i < POWERPC_EXCP_NB; i++) qemu_put_betls(f, &env->excp_vectors[i]); qemu_put_betls(f, &env->excp_prefix); - qemu_put_betls(f, &env->hreset_excp_prefix); qemu_put_betls(f, &env->ivor_mask); qemu_put_betls(f, &env->ivpr_mask); qemu_put_betls(f, &env->hreset_vector); @@ -167,7 +166,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) for (i = 0; i < POWERPC_EXCP_NB; i++) qemu_get_betls(f, &env->excp_vectors[i]); qemu_get_betls(f, &env->excp_prefix); - qemu_get_betls(f, &env->hreset_excp_prefix); qemu_get_betls(f, &env->ivor_mask); qemu_get_betls(f, &env->ivpr_mask); qemu_get_betls(f, &env->hreset_vector); diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c index 9783e52..d8e63ca 100644 --- a/target-ppc/mem_helper.c +++ b/target-ppc/mem_helper.c @@ -140,7 +140,7 @@ void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t is_dcbzl) { int dcbz_size = env->dcache_line_size; -#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) +#if defined(TARGET_PPC64) if (!is_dcbzl && (env->excp_model == POWERPC_EXCP_970) && ((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) { diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 5e741d1..6182bd7 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -202,6 +202,8 @@ typedef struct DisasContext { int spe_enabled; ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ int singlestep_enabled; + uint64_t insns_flags; + uint64_t insns_flags2; } DisasContext; /* True when active word size < size of target_long. */ @@ -423,9 +425,14 @@ EXTRACT_HELPER(ME, 1, 5); EXTRACT_HELPER(TO, 21, 5); EXTRACT_HELPER(CRM, 12, 8); -EXTRACT_HELPER(FM, 17, 8); EXTRACT_HELPER(SR, 16, 4); + +/* mtfsf/mtfsfi */ +EXTRACT_HELPER(FPBF, 19, 3); EXTRACT_HELPER(FPIMM, 12, 4); +EXTRACT_HELPER(FPL, 21, 1); +EXTRACT_HELPER(FPFLM, 17, 8); +EXTRACT_HELPER(FPW, 16, 1); /*** Jump target decoding ***/ /* Displacement */ @@ -739,6 +746,13 @@ static void gen_isel(DisasContext *ctx) tcg_temp_free_i32(t0); } +/* cmpb: PowerPC 2.05 specification */ +static void gen_cmpb(DisasContext *ctx) +{ + gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], + cpu_gpr[rB(ctx->opcode)]); +} + /*** Integer arithmetic ***/ static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, @@ -746,7 +760,7 @@ static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, { TCGv t0 = tcg_temp_new(); - tcg_gen_xor_tl(cpu_ov, arg0, arg1); + tcg_gen_xor_tl(cpu_ov, arg0, arg2); tcg_gen_xor_tl(t0, arg1, arg2); if (sub) { tcg_gen_and_tl(cpu_ov, cpu_ov, t0); @@ -768,22 +782,25 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, { TCGv t0 = ret; - if (((compute_ca && add_ca) || compute_ov) - && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2))) { + if (compute_ca || compute_ov) { t0 = tcg_temp_new(); } if (compute_ca) { if (NARROW_MODE(ctx)) { + /* Caution: a non-obvious corner case of the spec is that we + must produce the *entire* 64-bit addition, but produce the + carry into bit 32. */ TCGv t1 = tcg_temp_new(); - tcg_gen_ext32u_tl(t1, arg2); - tcg_gen_ext32u_tl(t0, arg1); - tcg_gen_add_tl(t0, t0, t1); - tcg_temp_free(t1); + tcg_gen_xor_tl(t1, arg1, arg2); /* add without carry */ + tcg_gen_add_tl(t0, arg1, arg2); if (add_ca) { tcg_gen_add_tl(t0, t0, cpu_ca); } - tcg_gen_shri_tl(cpu_ca, t0, 32); + tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changed w/ carry */ + tcg_temp_free(t1); + tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */ + tcg_gen_andi_tl(cpu_ca, cpu_ca, 1); } else { TCGv zero = tcg_const_tl(0); if (add_ca) { @@ -1122,24 +1139,30 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, { TCGv t0 = ret; - if (compute_ov && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2))) { + if (compute_ca || compute_ov) { t0 = tcg_temp_new(); } if (compute_ca) { /* dest = ~arg1 + arg2 [+ ca]. */ if (NARROW_MODE(ctx)) { + /* Caution: a non-obvious corner case of the spec is that we + must produce the *entire* 64-bit addition, but produce the + carry into bit 32. */ TCGv inv1 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); tcg_gen_not_tl(inv1, arg1); - tcg_gen_ext32u_tl(t0, arg2); - tcg_gen_ext32u_tl(inv1, inv1); if (add_ca) { - tcg_gen_add_tl(t0, t0, cpu_ca); + tcg_gen_add_tl(t0, arg2, cpu_ca); } else { - tcg_gen_addi_tl(t0, t0, 1); + tcg_gen_addi_tl(t0, arg2, 1); } + tcg_gen_xor_tl(t1, arg2, inv1); /* add without carry */ tcg_gen_add_tl(t0, t0, inv1); - tcg_gen_shri_tl(cpu_ca, t0, 32); + tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changes w/ carry */ + tcg_temp_free(t1); + tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */ + tcg_gen_andi_tl(cpu_ca, cpu_ca, 1); } else if (add_ca) { TCGv zero, inv1 = tcg_temp_new(); tcg_gen_not_tl(inv1, arg1); @@ -1451,6 +1474,38 @@ static void gen_popcntd(DisasContext *ctx) } #endif +/* prtyw: PowerPC 2.05 specification */ +static void gen_prtyw(DisasContext *ctx) +{ + TCGv ra = cpu_gpr[rA(ctx->opcode)]; + TCGv rs = cpu_gpr[rS(ctx->opcode)]; + TCGv t0 = tcg_temp_new(); + tcg_gen_shri_tl(t0, rs, 16); + tcg_gen_xor_tl(ra, rs, t0); + tcg_gen_shri_tl(t0, ra, 8); + tcg_gen_xor_tl(ra, ra, t0); + tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL); + tcg_temp_free(t0); +} + +#if defined(TARGET_PPC64) +/* prtyd: PowerPC 2.05 specification */ +static void gen_prtyd(DisasContext *ctx) +{ + TCGv ra = cpu_gpr[rA(ctx->opcode)]; + TCGv rs = cpu_gpr[rS(ctx->opcode)]; + TCGv t0 = tcg_temp_new(); + tcg_gen_shri_tl(t0, rs, 32); + tcg_gen_xor_tl(ra, rs, t0); + tcg_gen_shri_tl(t0, ra, 16); + tcg_gen_xor_tl(ra, ra, t0); + tcg_gen_shri_tl(t0, ra, 8); + tcg_gen_xor_tl(ra, ra, t0); + tcg_gen_andi_tl(ra, ra, 1); + tcg_temp_free(t0); +} +#endif + #if defined(TARGET_PPC64) /* extsw & extsw. */ GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B); @@ -2161,7 +2216,16 @@ static void gen_fcmpu(DisasContext *ctx) /*** Floating-point move ***/ /* fabs */ /* XXX: beware that fabs never checks for NaNs nor update FPSCR */ -GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT); +static void gen_fabs(DisasContext *ctx) +{ + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], + ~(1ULL << 63)); + gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); +} /* fmr - fmr. */ /* XXX: beware that fmr never checks for NaNs nor update FPSCR */ @@ -2177,10 +2241,42 @@ static void gen_fmr(DisasContext *ctx) /* fnabs */ /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */ -GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT); +static void gen_fnabs(DisasContext *ctx) +{ + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], + 1ULL << 63); + gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); +} + /* fneg */ /* XXX: beware that fneg never checks for NaNs nor update FPSCR */ -GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT); +static void gen_fneg(DisasContext *ctx) +{ + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], + 1ULL << 63); + gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); +} + +/* fcpsgn: PowerPC 2.05 specification */ +/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */ +static void gen_fcpsgn(DisasContext *ctx) +{ + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], + cpu_fpr[rB(ctx->opcode)], 0, 63); + gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); +} /*** Floating-Point status & ctrl register ***/ @@ -2271,19 +2367,27 @@ static void gen_mtfsb1(DisasContext *ctx) static void gen_mtfsf(DisasContext *ctx) { TCGv_i32 t0; - int L = ctx->opcode & 0x02000000; + int flm, l, w; if (unlikely(!ctx->fpu_enabled)) { gen_exception(ctx, POWERPC_EXCP_FPU); return; } + flm = FPFLM(ctx->opcode); + l = FPL(ctx->opcode); + w = FPW(ctx->opcode); + if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); + return; + } /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); gen_reset_fpstatus(); - if (L) - t0 = tcg_const_i32(0xff); - else - t0 = tcg_const_i32(FM(ctx->opcode)); + if (l) { + t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff); + } else { + t0 = tcg_const_i32(flm << (w * 8)); + } gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0); tcg_temp_free_i32(t0); if (unlikely(Rc(ctx->opcode) != 0)) { @@ -2297,7 +2401,7 @@ static void gen_mtfsf(DisasContext *ctx) /* mtfsfi */ static void gen_mtfsfi(DisasContext *ctx) { - int bf, sh; + int bf, sh, w; TCGv_i64 t0; TCGv_i32 t1; @@ -2305,12 +2409,17 @@ static void gen_mtfsfi(DisasContext *ctx) gen_exception(ctx, POWERPC_EXCP_FPU); return; } - bf = crbD(ctx->opcode) >> 2; - sh = 7 - bf; + w = FPW(ctx->opcode); + bf = FPBF(ctx->opcode); + if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); + return; + } + sh = (8 * w) + 7 - bf; /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); gen_reset_fpstatus(); - t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh)); + t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh)); t1 = tcg_const_i32(1 << sh); gen_helper_store_fpscr(cpu_env, t0, t1); tcg_temp_free_i64(t0); @@ -3211,6 +3320,72 @@ GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT); /* lfs lfsu lfsux lfsx */ GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT); +/* lfdp */ +static void gen_lfdp(DisasContext *ctx) +{ + TCGv EA; + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + gen_set_access_type(ctx, ACCESS_FLOAT); + EA = tcg_temp_new(); + gen_addr_imm_index(ctx, EA, 0); \ + if (unlikely(ctx->le_mode)) { + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + } else { + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + } + tcg_temp_free(EA); +} + +/* lfdpx */ +static void gen_lfdpx(DisasContext *ctx) +{ + TCGv EA; + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + gen_set_access_type(ctx, ACCESS_FLOAT); + EA = tcg_temp_new(); + gen_addr_reg_index(ctx, EA); + if (unlikely(ctx->le_mode)) { + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + } else { + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + } + tcg_temp_free(EA); +} + +/* lfiwax */ +static void gen_lfiwax(DisasContext *ctx) +{ + TCGv EA; + TCGv t0; + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + gen_set_access_type(ctx, ACCESS_FLOAT); + EA = tcg_temp_new(); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, EA); + gen_qemu_ld32u(ctx, t0, EA); + tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0); + tcg_gen_ext32s_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); + tcg_temp_free(EA); + tcg_temp_free(t0); +} + /*** Floating-point store ***/ #define GEN_STF(name, stop, opc, type) \ static void glue(gen_, name)(DisasContext *ctx) \ @@ -3304,6 +3479,52 @@ GEN_STFS(stfd, st64, 0x16, PPC_FLOAT); /* stfs stfsu stfsux stfsx */ GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT); +/* stfdp */ +static void gen_stfdp(DisasContext *ctx) +{ + TCGv EA; + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + gen_set_access_type(ctx, ACCESS_FLOAT); + EA = tcg_temp_new(); + gen_addr_imm_index(ctx, EA, 0); \ + if (unlikely(ctx->le_mode)) { + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + } else { + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + } + tcg_temp_free(EA); +} + +/* stfdpx */ +static void gen_stfdpx(DisasContext *ctx) +{ + TCGv EA; + if (unlikely(!ctx->fpu_enabled)) { + gen_exception(ctx, POWERPC_EXCP_FPU); + return; + } + gen_set_access_type(ctx, ACCESS_FLOAT); + EA = tcg_temp_new(); + gen_addr_reg_index(ctx, EA); + if (unlikely(ctx->le_mode)) { + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + } else { + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA); + tcg_gen_addi_tl(EA, EA, 8); + gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA); + } + tcg_temp_free(EA); +} + /* Optional: */ static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) { @@ -8426,6 +8647,7 @@ GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER), GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER), GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER), GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER), +GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205), GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL), GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), @@ -8453,9 +8675,11 @@ GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB), GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD), +GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205), #if defined(TARGET_PPC64) GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD), GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B), +GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205), #endif GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), @@ -8476,13 +8700,17 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT), GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT), GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT), GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT), +GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT), GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT), +GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT), +GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT), +GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205), GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT), GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT), GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT), GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT), -GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT), -GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT), +GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT), +GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT), #if defined(TARGET_PPC64) GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B), GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX), @@ -8833,9 +9061,6 @@ GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT), GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT), GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT), GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT), -GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT), -GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT), -GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT), #undef GEN_LD #undef GEN_LDU @@ -8921,6 +9146,9 @@ GEN_LDXF(name, ldop, 0x17, op | 0x00, type) GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT) GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT) +GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205), +GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205), +GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205), #undef GEN_STF #undef GEN_STUF @@ -8944,6 +9172,8 @@ GEN_STXF(name, stop, 0x17, op | 0x00, type) GEN_STFS(stfd, st64, 0x16, PPC_FLOAT) GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT) GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX) +GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205), +GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205), #undef GEN_CRLOGIC #define GEN_CRLOGIC(name, tcg_op, opc) \ @@ -9518,6 +9748,8 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env, ctx.exception = POWERPC_EXCP_NONE; ctx.spr_cb = env->spr_cb; ctx.mem_idx = env->mmu_idx; + ctx.insns_flags = env->insns_flags; + ctx.insns_flags2 = env->insns_flags2; ctx.access_type = -1; ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0; #if defined(TARGET_PPC64) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 781170f..6feb62a 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -1149,6 +1149,13 @@ static void gen_spr_603 (CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x00000000); + /* Breakpoints */ + /* XXX : not implemented */ + spr_register(env, SPR_IABR, "IABR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + } /* SPR specific to PowerPC G2 implementation */ @@ -2593,7 +2600,6 @@ static void init_excp_4xx_real (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_FIT] = 0x00001010; env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001020; env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000; - env->hreset_excp_prefix = 0x00000000UL; env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2618,7 +2624,6 @@ static void init_excp_4xx_softmmu (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00001100; env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00001200; env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000; - env->hreset_excp_prefix = 0x00000000UL; env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2644,11 +2649,10 @@ static void init_excp_MPC5xx (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001C00; env->excp_vectors[POWERPC_EXCP_MEXTBR] = 0x00001E00; env->excp_vectors[POWERPC_EXCP_NMEXTBR] = 0x00001F00; - env->hreset_excp_prefix = 0x00000000UL; env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2676,11 +2680,10 @@ static void init_excp_MPC8xx (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001C00; env->excp_vectors[POWERPC_EXCP_MEXTBR] = 0x00001E00; env->excp_vectors[POWERPC_EXCP_NMEXTBR] = 0x00001F00; - env->hreset_excp_prefix = 0x00000000UL; env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2704,9 +2707,8 @@ static void init_excp_G2 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2733,7 +2735,6 @@ static void init_excp_e200(CPUPPCState *env, target_ulong ivpr_mask) env->excp_vectors[POWERPC_EXCP_SPEU] = 0x00000000; env->excp_vectors[POWERPC_EXCP_EFPDI] = 0x00000000; env->excp_vectors[POWERPC_EXCP_EFPRI] = 0x00000000; - env->hreset_excp_prefix = 0x00000000UL; env->ivor_mask = 0x0000FFF7UL; env->ivpr_mask = ivpr_mask; /* Hardware reset vector */ @@ -2760,7 +2761,6 @@ static void init_excp_BookE (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00000000; env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00000000; env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00000000; - env->hreset_excp_prefix = 0x00000000UL; env->ivor_mask = 0x0000FFE0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2783,7 +2783,6 @@ static void init_excp_601 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_IO] = 0x00000A00; env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; env->excp_vectors[POWERPC_EXCP_RUNM] = 0x00002000; - env->hreset_excp_prefix = 0xFFF00000UL; /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2811,9 +2810,8 @@ static void init_excp_602 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001500; env->excp_vectors[POWERPC_EXCP_EMUL] = 0x00001600; - env->hreset_excp_prefix = 0xFFF00000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2836,9 +2834,8 @@ static void init_excp_603 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2859,7 +2856,6 @@ static void init_excp_604 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->hreset_excp_prefix = 0xFFF00000UL; /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2883,9 +2879,8 @@ static void init_excp_7x0 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2906,9 +2901,8 @@ static void init_excp_750cl (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2929,9 +2923,8 @@ static void init_excp_750cx (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2957,9 +2950,8 @@ static void init_excp_7x5 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -2983,9 +2975,8 @@ static void init_excp_7400 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600; env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -3011,9 +3002,8 @@ static void init_excp_7450 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600; - env->hreset_excp_prefix = 0x00000000UL; /* Hardware reset vector */ - env->hreset_vector = 0xFFFFFFFCUL; + env->hreset_vector = 0x00000100UL; #endif } @@ -3041,7 +3031,6 @@ static void init_excp_970 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_MAINT] = 0x00001600; env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001700; env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001800; - env->hreset_excp_prefix = 0x00000000FFF00000ULL; /* Hardware reset vector */ env->hreset_vector = 0x0000000000000100ULL; #endif @@ -3070,7 +3059,6 @@ static void init_excp_POWER7 (CPUPPCState *env) env->excp_vectors[POWERPC_EXCP_MAINT] = 0x00001600; env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001700; env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001800; - env->hreset_excp_prefix = 0; /* Hardware reset vector */ env->hreset_vector = 0x0000000000000100ULL; #endif @@ -4157,6 +4145,33 @@ static void init_proc_G2LE (CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x00000000); + /* Breakpoints */ + /* XXX : not implemented */ + spr_register(env, SPR_DABR, "DABR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_DABR2, "DABR2", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_IABR2, "IABR2", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_IBCR, "IBCR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_DBCR, "DBCR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* Memory management */ gen_low_BATs(env); gen_high_BATs(env); @@ -6962,6 +6977,18 @@ static void init_proc_POWER7 (CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_DSCR, 0x00000000); + spr_register_kvm(env, SPR_MMCRA, "SPR_MMCRA", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_MMCRA, 0x00000000); + spr_register_kvm(env, SPR_PMC5, "SPR_PMC5", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_PMC5, 0x00000000); + spr_register_kvm(env, SPR_PMC6, "SPR_PMC6", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_PMC6, 0x00000000); #endif /* !CONFIG_USER_ONLY */ /* Memory management */ /* XXX : not implemented */ @@ -6989,6 +7016,7 @@ static void init_proc_POWER7 (CPUPPCState *env) init_excp_POWER7(env); env->dcache_line_size = 128; env->icache_line_size = 128; + /* Allocate hardware IRQ controller */ ppcPOWER7_irq_init(env); /* Can't find information on what this should be on reset. This @@ -7004,7 +7032,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) dc->desc = "POWER7"; pcc->init_proc = init_proc_POWER7; pcc->check_pow = check_pow_nocheck; - pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | + pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX | @@ -7014,7 +7042,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) PPC_64B | PPC_ALTIVEC | PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD; - pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX; + pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205; pcc->msr_mask = 0x800000000204FF36ULL; pcc->mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) @@ -7026,6 +7054,8 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | POWERPC_FLAG_BE | POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR; + pcc->l1_dcache_size = 0x8000; + pcc->l1_icache_size = 0x8000; } #endif /* defined (TARGET_PPC64) */ @@ -7043,7 +7073,6 @@ static void init_ppc_proc(PowerPCCPU *cpu) /* Set all exception vectors to an invalid address */ for (i = 0; i < POWERPC_EXCP_NB; i++) env->excp_vectors[i] = (target_ulong)(-1ULL); - env->hreset_excp_prefix = 0x00000000; env->ivor_mask = 0x00000000; env->ivpr_mask = 0x00000000; /* Default MMU definitions */ @@ -7080,9 +7109,7 @@ static void init_ppc_proc(PowerPCCPU *cpu) } /* PowerPC implementation specific initialisations (SPRs, timers, ...) */ (*pcc->init_proc)(env); -#if !defined(CONFIG_USER_ONLY) - env->excp_prefix = env->hreset_excp_prefix; -#endif + /* MSR bits & flags consistency checks */ if (env->msr_mask & (1 << 25)) { switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) { @@ -8182,19 +8209,23 @@ static void ppc_cpu_reset(CPUState *s) msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */ msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */ msr |= (target_ulong)1 << MSR_PR; -#else - env->excp_prefix = env->hreset_excp_prefix; - env->nip = env->hreset_vector | env->excp_prefix; - if (env->mmu_model != POWERPC_MMU_REAL) { - ppc_tlb_invalidate_all(env); - } #endif - env->msr = msr & env->msr_mask; + #if defined(TARGET_PPC64) if (env->mmu_model & POWERPC_MMU_64) { env->msr |= (1ULL << MSR_SF); } #endif + + hreg_store_msr(env, msr, 1); + +#if !defined(CONFIG_USER_ONLY) + env->nip = env->hreset_vector | env->excp_prefix; + if (env->mmu_model != POWERPC_MMU_REAL) { + ppc_tlb_invalidate_all(env); + } +#endif + hreg_compute_hflags(env); env->reserve_addr = (target_ulong)-1ULL; /* Be sure no exception or interrupt is pending */ diff --git a/translate-all.c b/translate-all.c index d04a116..da93608 100644 --- a/translate-all.c +++ b/translate-all.c @@ -55,6 +55,7 @@ #else #include "exec/address-spaces.h" #endif +#include "qemu/timer.h" #include "exec/cputlb.h" #include "translate-all.h" |