ppc patch queue 2020-05-27

Here's the next pull request for qemu-5.1.  It includes:
  * Support for the scv and rfscv POWER9 instructions in TCG
  * Support for the new SPAPR_LMB_FLAGS_HOTREMOVABLE flag, which
    provides a way for guests to know memory which should be removable
    (so the guest can avoid putting immovable allocations there).
  * Some fixes for the recently added partition scope radix translation
    in softmmu
  * Assorted minor fixes and cleanups
 
 It includes one patch to avoid a clash with SELinux when using NVLink
 VFIO devices.  That's not technically within the files under my
 maintainership, but it is in a section of the VFIO quirks code that's
 specific to the POWER-only NVLink devices, and has an ack from Alex
 Williamson.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAl7N/HsACgkQbDjKyiDZ
 s5L3hw/9Fv8/8hdf9gtLqPLDsSw8Unakr8sWsMGzWkkBXQ4HVJs7d6AGjv2dqRGj
 raLWgW/U37cdHEpfK0wmhtzeLeeVL0cgd6ySH2bbzsn9pAYxTGRc2ekkXp3VN1ua
 uNlQrgPdSm7Z0D063giaFlNHaDgJSJcNSOTZOL+U6/W5MWdChgDXw99muonmbT5l
 UbfNdv150/0TVXuvibtQ24KSUJcXn8pIeO+Gb3xOkM3+gViUy60+yQhRGDCtO5wJ
 HXQO00NzOP3mbsy3O4WdkKSmeMix0oRKkUs2VeUZCWiUwAn6nG7NwzN7NSixfDH9
 2PmpW1IAif5mu9NgZRWCgALVZWEFb96VSm66BsLJ/U0/gdO4mzSya3FUyTenB6O+
 VRnAQhW8pXOSXnEJSdDW7CWnEVeZjmqqVyKADlCR+4r3kq4tAhEovENvm+oldgEk
 dL9xXko+UfjxtbqobjO6tK+5Yzd8pcYeMr7ujn5x4vPSlRWNkx6jctmwHNwrxe31
 nUp0vM/o1eML0EXRYbeiNpMsno3qc4BcvW1CGHe9qrdxVWBjGxIicqnJdHfPt5mI
 t/rHVYPAXkBRgNrBYdv4pkqycp201jL/VEpDQ4FXzp6ovNRTtFsBhUEbO1fBs6Wv
 8/Mj9UxyzlcM+lGMCLw0IlWMcYeziCFqRAdHhEIIOF7jsYFyM9w=
 =mkPg
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-5.1-20200527' into staging

ppc patch queue 2020-05-27

Here's the next pull request for qemu-5.1.  It includes:
 * Support for the scv and rfscv POWER9 instructions in TCG
 * Support for the new SPAPR_LMB_FLAGS_HOTREMOVABLE flag, which
   provides a way for guests to know memory which should be removable
   (so the guest can avoid putting immovable allocations there).
 * Some fixes for the recently added partition scope radix translation
   in softmmu
 * Assorted minor fixes and cleanups

It includes one patch to avoid a clash with SELinux when using NVLink
VFIO devices.  That's not technically within the files under my
maintainership, but it is in a section of the VFIO quirks code that's
specific to the POWER-only NVLink devices, and has an ack from Alex
Williamson.

# gpg: Signature made Wed 27 May 2020 06:36:59 BST
# gpg:                using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full]
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full]
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full]
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown]
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-5.1-20200527:
  vfio/nvlink: Remove exec permission to avoid SELinux AVCs
  target/ppc: Fix argument to ppc_radix64_partition_scoped_xlate() again
  hw/nvram/mac_nvram: Convert debug printf()s to trace events
  hw/pci-bridge/dec: Remove dead debug code
  target/ppc: Don't update radix PTE R/C bits with gdbstub
  target/ppc: Fix arguments to ppc_radix64_partition_scoped_xlate()
  target/ppc: Add missing braces in ppc_radix64_partition_scoped_xlate()
  target/ppc: Don't initialize some local variables in ppc_radix64_xlate()
  target/ppc: Pass const pointer to ppc_radix64_get_fully_qualified_addr()
  target/ppc: Pass const pointer to ppc_radix64_get_prot_amr()
  ppc/spapr: Add hotremovable flag on DIMM LMBs on drmem_v2
  target/ppc: Add support for scv and rfscv instructions
  target/ppc: Untabify excp_helper.c
  ppc/spapr: add a POWER10 CPU model
  ppc/pnv: Fix NMI system reset SRR1 value

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-05-27 22:23:13 +01:00
commit 8b92b9ef86
16 changed files with 237 additions and 102 deletions

View File

@ -30,18 +30,9 @@
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "trace.h"
#include <zlib.h> #include <zlib.h>
/* debug NVR */
//#define DEBUG_NVR
#ifdef DEBUG_NVR
#define NVR_DPRINTF(fmt, ...) \
do { printf("NVR: " fmt , ## __VA_ARGS__); } while (0)
#else
#define NVR_DPRINTF(fmt, ...)
#endif
#define DEF_SYSTEM_SIZE 0xc10 #define DEF_SYSTEM_SIZE 0xc10
/* macio style NVRAM device */ /* macio style NVRAM device */
@ -51,9 +42,8 @@ static void macio_nvram_writeb(void *opaque, hwaddr addr,
MacIONVRAMState *s = opaque; MacIONVRAMState *s = opaque;
addr = (addr >> s->it_shift) & (s->size - 1); addr = (addr >> s->it_shift) & (s->size - 1);
trace_macio_nvram_write(addr, value);
s->data[addr] = value; s->data[addr] = value;
NVR_DPRINTF("writeb addr %04" HWADDR_PRIx " val %" PRIx64 "\n",
addr, value);
} }
static uint64_t macio_nvram_readb(void *opaque, hwaddr addr, static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
@ -64,8 +54,7 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
addr = (addr >> s->it_shift) & (s->size - 1); addr = (addr >> s->it_shift) & (s->size - 1);
value = s->data[addr]; value = s->data[addr];
NVR_DPRINTF("readb addr %04" HWADDR_PRIx " val %" PRIx32 "\n", trace_macio_nvram_read(addr, value);
addr, value);
return value; return value;
} }

View File

@ -13,3 +13,7 @@ fw_cfg_add_string(uint16_t key_value, const char *key_name, const char *value) "
fw_cfg_add_i16(uint16_t key_value, const char *key_name, uint16_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx16 fw_cfg_add_i16(uint16_t key_value, const char *key_name, uint16_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx16
fw_cfg_add_i32(uint16_t key_value, const char *key_name, uint32_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx32 fw_cfg_add_i32(uint16_t key_value, const char *key_name, uint32_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx32
fw_cfg_add_i64(uint16_t key_value, const char *key_name, uint64_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx64 fw_cfg_add_i64(uint16_t key_value, const char *key_name, uint64_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx64
# mac_nvram.c
macio_nvram_read(uint32_t addr, uint8_t val) "read addr=0x%04"PRIx32" val=0x%02x"
macio_nvram_write(uint32_t addr, uint8_t val) "write addr=0x%04"PRIx32" val=0x%02x"

View File

@ -32,16 +32,6 @@
#include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h" #include "hw/pci/pci_bus.h"
/* debug DEC */
//#define DEBUG_DEC
#ifdef DEBUG_DEC
#define DEC_DPRINTF(fmt, ...) \
do { printf("DEC: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DEC_DPRINTF(fmt, ...)
#endif
#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154) #define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154)
typedef struct DECState { typedef struct DECState {

View File

@ -1984,12 +1984,26 @@ static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
cpu_synchronize_state(cs); cpu_synchronize_state(cs);
ppc_cpu_do_system_reset(cs); ppc_cpu_do_system_reset(cs);
/* if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
* SRR1[42:45] is set to 0100 which the ISA defines as implementation /*
* dependent. POWER processors use this for xscom triggered interrupts, * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
* which come from the BMC or NMI IPIs. * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
*/ * (PPC_BIT(43)).
env->spr[SPR_SRR1] |= PPC_BIT(43); */
if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
env->spr[SPR_SRR1] |= SRR1_WAKERESET;
}
} else {
/*
* For non-powersave system resets, SRR1[42:45] are defined to be
* implementation-dependent. The POWER9 User Manual specifies that
* an external (SCOM driven, which may come from a BMC nmi command or
* another CPU requesting a NMI IPI) system reset exception should be
* 0b0010 (PPC_BIT(44)).
*/
env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
}
} }
static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)

View File

@ -445,7 +445,8 @@ static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt,
g_assert(drc); g_assert(drc);
elem = spapr_get_drconf_cell(size / lmb_size, addr, elem = spapr_get_drconf_cell(size / lmb_size, addr,
spapr_drc_index(drc), node, spapr_drc_index(drc), node,
SPAPR_LMB_FLAGS_ASSIGNED); (SPAPR_LMB_FLAGS_ASSIGNED |
SPAPR_LMB_FLAGS_HOTREMOVABLE));
QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
nr_entries++; nr_entries++;
cur_addr = addr + size; cur_addr = addr + size;

View File

@ -407,6 +407,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"), DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"), DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"), DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power10_v1.0"),
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
DEFINE_SPAPR_CPU_CORE_TYPE("host"), DEFINE_SPAPR_CPU_CORE_TYPE("host"),
#endif #endif

View File

@ -1620,7 +1620,7 @@ int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp)
} }
cap = (void *) hdr; cap = (void *) hdr;
p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE | PROT_EXEC, p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE,
MAP_SHARED, vdev->vbasedev.fd, nv2reg->offset); MAP_SHARED, vdev->vbasedev.fd, nv2reg->offset);
if (p == MAP_FAILED) { if (p == MAP_FAILED) {
ret = -errno; ret = -errno;
@ -1680,7 +1680,7 @@ int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp)
/* Some NVLink bridges may not have assigned ATSD */ /* Some NVLink bridges may not have assigned ATSD */
if (atsdreg->size) { if (atsdreg->size) {
p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE | PROT_EXEC, p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE,
MAP_SHARED, vdev->vbasedev.fd, atsdreg->offset); MAP_SHARED, vdev->vbasedev.fd, atsdreg->offset);
if (p == MAP_FAILED) { if (p == MAP_FAILED) {
ret = -errno; ret = -errno;

View File

@ -886,6 +886,7 @@ int spapr_rtc_import_offset(SpaprRtcState *rtc, int64_t legacy_offset);
#define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008 #define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008
#define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020 #define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020
#define SPAPR_LMB_FLAGS_RESERVED 0x00000080 #define SPAPR_LMB_FLAGS_RESERVED 0x00000080
#define SPAPR_LMB_FLAGS_HOTREMOVABLE 0x00000100
void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg); void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg);

View File

@ -267,6 +267,7 @@ void cpu_loop(CPUPPCState *env)
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_SYSCALL: /* System call exception */ case POWERPC_EXCP_SYSCALL: /* System call exception */
case POWERPC_EXCP_SYSCALL_VECTORED:
cpu_abort(cs, "Syscall exception while in user mode. " cpu_abort(cs, "Syscall exception while in user mode. "
"Aborting\n"); "Aborting\n");
break; break;

View File

@ -127,8 +127,9 @@ enum {
POWERPC_EXCP_SDOOR_HV = 100, POWERPC_EXCP_SDOOR_HV = 100,
/* ISA 3.00 additions */ /* ISA 3.00 additions */
POWERPC_EXCP_HVIRT = 101, POWERPC_EXCP_HVIRT = 101,
POWERPC_EXCP_SYSCALL_VECTORED = 102, /* scv exception */
/* EOL */ /* EOL */
POWERPC_EXCP_NB = 102, POWERPC_EXCP_NB = 103,
/* QEMU exceptions: used internally during code translation */ /* QEMU exceptions: used internally during code translation */
POWERPC_EXCP_STOP = 0x200, /* stop translation */ POWERPC_EXCP_STOP = 0x200, /* stop translation */
POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */ POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */
@ -475,9 +476,31 @@ typedef struct ppc_v3_pate_t {
#define SRR1_PROTFAULT DSISR_PROTFAULT #define SRR1_PROTFAULT DSISR_PROTFAULT
#define SRR1_IAMR DSISR_AMR #define SRR1_IAMR DSISR_AMR
/* SRR1[42:45] wakeup fields for System Reset Interrupt */
#define SRR1_WAKEMASK 0x003c0000 /* reason for wakeup */
#define SRR1_WAKEHMI 0x00280000 /* Hypervisor maintenance */
#define SRR1_WAKEHVI 0x00240000 /* Hypervisor Virt. Interrupt (P9) */
#define SRR1_WAKEEE 0x00200000 /* External interrupt */
#define SRR1_WAKEDEC 0x00180000 /* Decrementer interrupt */
#define SRR1_WAKEDBELL 0x00140000 /* Privileged doorbell */
#define SRR1_WAKERESET 0x00100000 /* System reset */
#define SRR1_WAKEHDBELL 0x000c0000 /* Hypervisor doorbell */
#define SRR1_WAKESCOM 0x00080000 /* SCOM not in power-saving mode */
/* SRR1[46:47] power-saving exit mode */
#define SRR1_WAKESTATE 0x00030000 /* Powersave exit mask */
#define SRR1_WS_HVLOSS 0x00030000 /* HV resources not maintained */
#define SRR1_WS_GPRLOSS 0x00020000 /* GPRs not maintained */
#define SRR1_WS_NOLOSS 0x00010000 /* All resources maintained */
/* Facility Status and Control (FSCR) bits */ /* Facility Status and Control (FSCR) bits */
#define FSCR_EBB (63 - 56) /* Event-Based Branch Facility */ #define FSCR_EBB (63 - 56) /* Event-Based Branch Facility */
#define FSCR_TAR (63 - 55) /* Target Address Register */ #define FSCR_TAR (63 - 55) /* Target Address Register */
#define FSCR_SCV (63 - 51) /* System call vectored */
/* Interrupt cause mask and position in FSCR. HFSCR has the same format */ /* Interrupt cause mask and position in FSCR. HFSCR has the same format */
#define FSCR_IC_MASK (0xFFULL) #define FSCR_IC_MASK (0xFFULL)
#define FSCR_IC_POS (63 - 7) #define FSCR_IC_POS (63 - 7)
@ -487,6 +510,7 @@ typedef struct ppc_v3_pate_t {
#define FSCR_IC_TM 5 #define FSCR_IC_TM 5
#define FSCR_IC_EBB 7 #define FSCR_IC_EBB 7
#define FSCR_IC_TAR 8 #define FSCR_IC_TAR 8
#define FSCR_IC_SCV 12
/* Exception state register bits definition */ /* Exception state register bits definition */
#define ESR_PIL PPC_BIT(36) /* Illegal Instruction */ #define ESR_PIL PPC_BIT(36) /* Illegal Instruction */
@ -554,6 +578,8 @@ enum {
POWERPC_FLAG_VSX = 0x00080000, POWERPC_FLAG_VSX = 0x00080000,
/* Has Transaction Memory (ISA 2.07) */ /* Has Transaction Memory (ISA 2.07) */
POWERPC_FLAG_TM = 0x00100000, POWERPC_FLAG_TM = 0x00100000,
/* Has SCV (ISA 3.00) */
POWERPC_FLAG_SCV = 0x00200000,
}; };
/*****************************************************************************/ /*****************************************************************************/

View File

@ -67,19 +67,31 @@ static inline void dump_syscall(CPUPPCState *env)
ppc_dump_gpr(env, 8), env->nip); ppc_dump_gpr(env, 8), env->nip);
} }
static inline void dump_syscall_vectored(CPUPPCState *env)
{
qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
" r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
" r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
" nip=" TARGET_FMT_lx "\n",
ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
ppc_dump_gpr(env, 8), env->nip);
}
static inline void dump_hcall(CPUPPCState *env) static inline void dump_hcall(CPUPPCState *env)
{ {
qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
" r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
" r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
" r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
" nip=" TARGET_FMT_lx "\n", " nip=" TARGET_FMT_lx "\n",
ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
env->nip); env->nip);
} }
static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
@ -89,7 +101,7 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
env->resume_as_sreset = false; env->resume_as_sreset = false;
/* Pretend to be returning from doze always as we don't lose state */ /* Pretend to be returning from doze always as we don't lose state */
*msr |= (0x1ull << (63 - 47)); *msr |= SRR1_WS_NOLOSS;
/* Machine checks are sent normally */ /* Machine checks are sent normally */
if (excp == POWERPC_EXCP_MCHECK) { if (excp == POWERPC_EXCP_MCHECK) {
@ -97,25 +109,25 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
} }
switch (excp) { switch (excp) {
case POWERPC_EXCP_RESET: case POWERPC_EXCP_RESET:
*msr |= 0x4ull << (63 - 45); *msr |= SRR1_WAKERESET;
break; break;
case POWERPC_EXCP_EXTERNAL: case POWERPC_EXCP_EXTERNAL:
*msr |= 0x8ull << (63 - 45); *msr |= SRR1_WAKEEE;
break; break;
case POWERPC_EXCP_DECR: case POWERPC_EXCP_DECR:
*msr |= 0x6ull << (63 - 45); *msr |= SRR1_WAKEDEC;
break; break;
case POWERPC_EXCP_SDOOR: case POWERPC_EXCP_SDOOR:
*msr |= 0x5ull << (63 - 45); *msr |= SRR1_WAKEDBELL;
break; break;
case POWERPC_EXCP_SDOOR_HV: case POWERPC_EXCP_SDOOR_HV:
*msr |= 0x3ull << (63 - 45); *msr |= SRR1_WAKEHDBELL;
break; break;
case POWERPC_EXCP_HV_MAINT: case POWERPC_EXCP_HV_MAINT:
*msr |= 0xaull << (63 - 45); *msr |= SRR1_WAKEHMI;
break; break;
case POWERPC_EXCP_HVIRT: case POWERPC_EXCP_HVIRT:
*msr |= 0x9ull << (63 - 45); *msr |= SRR1_WAKEHVI;
break; break;
default: default:
cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
@ -185,7 +197,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector; target_ulong msr, new_msr, vector;
int srr0, srr1, asrr0, asrr1, lev, ail; int srr0, srr1, asrr0, asrr1, lev = -1, ail;
bool lpes0; bool lpes0;
qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
@ -421,6 +433,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
new_msr |= (target_ulong)MSR_HVB; new_msr |= (target_ulong)MSR_HVB;
} }
break; break;
case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
lev = env->error_code;
dump_syscall_vectored(env);
env->nip += 4;
new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
case POWERPC_EXCP_DECR: /* Decrementer exception */ case POWERPC_EXCP_DECR: /* Decrementer exception */
@ -724,12 +743,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
break; break;
} }
/* Save PC */
env->spr[srr0] = env->nip;
/* Save MSR */
env->spr[srr1] = msr;
/* Sanity check */ /* Sanity check */
if (!(env->msr_mask & MSR_HVB)) { if (!(env->msr_mask & MSR_HVB)) {
if (new_msr & MSR_HVB) { if (new_msr & MSR_HVB) {
@ -742,14 +755,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
} }
} }
/* If any alternate SRR register are defined, duplicate saved values */
if (asrr0 != -1) {
env->spr[asrr0] = env->spr[srr0];
}
if (asrr1 != -1) {
env->spr[asrr1] = env->spr[srr1];
}
/* /*
* Sort out endianness of interrupt, this differs depending on the * Sort out endianness of interrupt, this differs depending on the
* CPU, the HV mode, etc... * CPU, the HV mode, etc...
@ -784,14 +789,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
} }
#endif #endif
/* Jump to handler */
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
cpu_abort(cs, "Raised an exception without defined vector %d\n",
excp);
}
vector |= env->excp_prefix;
/* /*
* AIL only works if there is no HV transition and we are running * AIL only works if there is no HV transition and we are running
* with translations enabled * with translations enabled
@ -800,10 +797,21 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
((new_msr & MSR_HVB) && !(msr & MSR_HVB))) { ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) {
ail = 0; ail = 0;
} }
/* Handle AIL */
if (ail) { vector = env->excp_vectors[excp];
new_msr |= (1 << MSR_IR) | (1 << MSR_DR); if (vector == (target_ulong)-1ULL) {
vector |= ppc_excp_vector_offset(cs, ail); cpu_abort(cs, "Raised an exception without defined vector %d\n",
excp);
}
vector |= env->excp_prefix;
/* If any alternate SRR register are defined, duplicate saved values */
if (asrr0 != -1) {
env->spr[asrr0] = env->nip;
}
if (asrr1 != -1) {
env->spr[asrr1] = msr;
} }
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
@ -823,6 +831,37 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
} }
#endif #endif
if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
/* Save PC */
env->spr[srr0] = env->nip;
/* Save MSR */
env->spr[srr1] = msr;
/* Handle AIL */
if (ail) {
new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
vector |= ppc_excp_vector_offset(cs, ail);
}
#if defined(TARGET_PPC64)
} else {
/* scv AIL is a little different */
if (ail) {
new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
}
if (ail == AIL_C000_0000_0000_4000) {
vector |= 0xc000000000003000ull;
} else {
vector |= 0x0000000000017000ull;
}
vector += lev * 0x20;
env->lr = env->nip;
env->ctr = msr;
#endif
}
powerpc_set_excp_state(cpu, vector, new_msr); powerpc_set_excp_state(cpu, vector, new_msr);
} }
@ -1160,6 +1199,11 @@ void helper_rfid(CPUPPCState *env)
do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]); do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
} }
void helper_rfscv(CPUPPCState *env)
{
do_rfi(env, env->lr, env->ctr);
}
void helper_hrfid(CPUPPCState *env) void helper_hrfid(CPUPPCState *env)
{ {
do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);

View File

@ -15,6 +15,7 @@ DEF_HELPER_1(rfmci, void, env)
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
DEF_HELPER_2(pminsn, void, env, i32) DEF_HELPER_2(pminsn, void, env, i32)
DEF_HELPER_1(rfid, void, env) DEF_HELPER_1(rfid, void, env)
DEF_HELPER_1(rfscv, void, env)
DEF_HELPER_1(hrfid, void, env) DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl) DEF_HELPER_2(store_lpcr, void, env, tl)
DEF_HELPER_2(store_pcr, void, env, tl) DEF_HELPER_2(store_pcr, void, env, tl)

View File

@ -28,7 +28,8 @@
#include "mmu-radix64.h" #include "mmu-radix64.h"
#include "mmu-book3s-v3.h" #include "mmu-book3s-v3.h"
static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr, static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env,
vaddr eaddr,
uint64_t *lpid, uint64_t *pid) uint64_t *lpid, uint64_t *pid)
{ {
if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */ if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */
@ -49,6 +50,8 @@ static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr,
*lpid = 0; *lpid = 0;
*pid = 0; *pid = 0;
break; break;
default:
g_assert_not_reached();
} }
} else { /* !MSR[HV] -> Guest */ } else { /* !MSR[HV] -> Guest */
switch (eaddr & R_EADDR_QUADRANT) { switch (eaddr & R_EADDR_QUADRANT) {
@ -63,6 +66,8 @@ static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr,
*lpid = env->spr[SPR_LPIDR]; *lpid = env->spr[SPR_LPIDR];
*pid = 0; /* pid set to 0 -> addresses guest operating system */ *pid = 0; /* pid set to 0 -> addresses guest operating system */
break; break;
default:
g_assert_not_reached();
} }
} }
@ -269,7 +274,7 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, int rwx,
ppc_v3_pate_t pate, ppc_v3_pate_t pate,
hwaddr *h_raddr, int *h_prot, hwaddr *h_raddr, int *h_prot,
int *h_page_size, bool pde_addr, int *h_page_size, bool pde_addr,
bool cause_excp) bool guest_visible)
{ {
int fault_cause = 0; int fault_cause = 0;
hwaddr pte_addr; hwaddr pte_addr;
@ -281,16 +286,18 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, int rwx,
pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size, pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size,
&pte, &fault_cause, &pte_addr) || &pte, &fault_cause, &pte_addr) ||
ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, h_prot, true)) { ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, h_prot, true)) {
if (pde_addr) /* address being translated was that of a guest pde */ if (pde_addr) { /* address being translated was that of a guest pde */
fault_cause |= DSISR_PRTABLE_FAULT; fault_cause |= DSISR_PRTABLE_FAULT;
if (cause_excp) { }
if (guest_visible) {
ppc_radix64_raise_hsi(cpu, rwx, eaddr, g_raddr, fault_cause); ppc_radix64_raise_hsi(cpu, rwx, eaddr, g_raddr, fault_cause);
} }
return 1; return 1;
} }
/* Update Reference and Change Bits */ if (guest_visible) {
ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot); ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot);
}
return 0; return 0;
} }
@ -299,7 +306,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
vaddr eaddr, uint64_t pid, vaddr eaddr, uint64_t pid,
ppc_v3_pate_t pate, hwaddr *g_raddr, ppc_v3_pate_t pate, hwaddr *g_raddr,
int *g_prot, int *g_page_size, int *g_prot, int *g_page_size,
bool cause_excp) bool guest_visible)
{ {
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
@ -313,7 +320,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
if (offset >= size) { if (offset >= size) {
/* offset exceeds size of the process table */ /* offset exceeds size of the process table */
if (cause_excp) { if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
} }
return 1; return 1;
@ -333,7 +340,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
*/ */
ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, prtbe_addr, ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, prtbe_addr,
pate, &h_raddr, &h_prot, pate, &h_raddr, &h_prot,
&h_page_size, 1, 1); &h_page_size, true,
guest_visible);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -353,7 +361,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
&fault_cause, &pte_addr); &fault_cause, &pte_addr);
if (ret) { if (ret) {
/* No valid PTE */ /* No valid PTE */
if (cause_excp) { if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
} }
return ret; return ret;
@ -372,7 +380,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
do { do {
ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr, ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr,
pate, &h_raddr, &h_prot, pate, &h_raddr, &h_prot,
&h_page_size, 1, 1); &h_page_size, true,
guest_visible);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -381,7 +390,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
&nls, g_page_size, &pte, &fault_cause); &nls, g_page_size, &pte, &fault_cause);
if (ret) { if (ret) {
/* No valid pte */ /* No valid pte */
if (cause_excp) { if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
} }
return ret; return ret;
@ -398,13 +407,15 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
if (ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) { if (ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) {
/* Access denied due to protection */ /* Access denied due to protection */
if (cause_excp) { if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
} }
return 1; return 1;
} }
ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot); if (guest_visible) {
ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot);
}
return 0; return 0;
} }
@ -429,17 +440,17 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
bool relocation, bool relocation,
hwaddr *raddr, int *psizep, int *protp, hwaddr *raddr, int *psizep, int *protp,
bool cause_excp) bool guest_visible)
{ {
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
uint64_t lpid = 0, pid = 0; uint64_t lpid, pid;
ppc_v3_pate_t pate; ppc_v3_pate_t pate;
int psize, prot; int psize, prot;
hwaddr g_raddr; hwaddr g_raddr;
/* Virtual Mode Access - get the fully qualified address */ /* Virtual Mode Access - get the fully qualified address */
if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) { if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) {
if (cause_excp) { if (guest_visible) {
ppc_radix64_raise_segi(cpu, rwx, eaddr); ppc_radix64_raise_segi(cpu, rwx, eaddr);
} }
return 1; return 1;
@ -452,13 +463,13 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
vhc->get_pate(cpu->vhyp, &pate); vhc->get_pate(cpu->vhyp, &pate);
} else { } else {
if (!ppc64_v3_get_pate(cpu, lpid, &pate)) { if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
if (cause_excp) { if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
} }
return 1; return 1;
} }
if (!validate_pate(cpu, lpid, &pate)) { if (!validate_pate(cpu, lpid, &pate)) {
if (cause_excp) { if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG); ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
} }
return 1; return 1;
@ -479,7 +490,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
if (relocation) { if (relocation) {
int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid, int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid,
pate, &g_raddr, &prot, pate, &g_raddr, &prot,
&psize, cause_excp); &psize, guest_visible);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -502,7 +513,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
ret = ppc_radix64_partition_scoped_xlate(cpu, rwx, eaddr, g_raddr, ret = ppc_radix64_partition_scoped_xlate(cpu, rwx, eaddr, g_raddr,
pate, raddr, &prot, &psize, pate, raddr, &prot, &psize,
0, cause_excp); false, guest_visible);
if (ret) { if (ret) {
return ret; return ret;
} }

View File

@ -55,9 +55,9 @@ static inline int ppc_radix64_get_prot_eaa(uint64_t pte)
(pte & R_PTE_EAA_X ? PAGE_EXEC : 0); (pte & R_PTE_EAA_X ? PAGE_EXEC : 0);
} }
static inline int ppc_radix64_get_prot_amr(PowerPCCPU *cpu) static inline int ppc_radix64_get_prot_amr(const PowerPCCPU *cpu)
{ {
CPUPPCState *env = &cpu->env; const CPUPPCState *env = &cpu->env;
int amr = env->spr[SPR_AMR] >> 62; /* We only care about key0 AMR63:62 */ 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 */ int iamr = env->spr[SPR_IAMR] >> 62; /* We only care about key0 IAMR63:62 */

View File

@ -173,6 +173,7 @@ struct DisasContext {
bool vsx_enabled; bool vsx_enabled;
bool spe_enabled; bool spe_enabled;
bool tm_enabled; bool tm_enabled;
bool scv_enabled;
bool gtse; bool gtse;
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
int singlestep_enabled; int singlestep_enabled;
@ -4030,6 +4031,24 @@ static void gen_rfid(DisasContext *ctx)
#endif #endif
} }
#if !defined(CONFIG_USER_ONLY)
static void gen_rfscv(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
GEN_PRIV;
#else
/* Restore CPU state */
CHK_SV;
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_update_cfar(ctx, ctx->base.pc_next - 4);
gen_helper_rfscv(cpu_env);
gen_sync_exception(ctx);
#endif
}
#endif
static void gen_hrfid(DisasContext *ctx) static void gen_hrfid(DisasContext *ctx)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
@ -4048,6 +4067,7 @@ static void gen_hrfid(DisasContext *ctx)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else #else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED
#endif #endif
static void gen_sc(DisasContext *ctx) static void gen_sc(DisasContext *ctx)
{ {
@ -4057,6 +4077,23 @@ static void gen_sc(DisasContext *ctx)
gen_exception_err(ctx, POWERPC_SYSCALL, lev); gen_exception_err(ctx, POWERPC_SYSCALL, lev);
} }
#if defined(TARGET_PPC64)
#if !defined(CONFIG_USER_ONLY)
static void gen_scv(DisasContext *ctx)
{
uint32_t lev;
if (unlikely(!ctx->scv_enabled)) {
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_SCV);
return;
}
lev = (ctx->opcode >> 5) & 0x7F;
gen_exception_err(ctx, POWERPC_SYSCALL_VECTORED, lev);
}
#endif
#endif
/*** Trap ***/ /*** Trap ***/
/* Check for unconditional traps (always or never) */ /* Check for unconditional traps (always or never) */
@ -7049,6 +7086,12 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW), GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B), GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
#if !defined(CONFIG_USER_ONLY)
/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
GEN_HANDLER_E(scv, 0x11, 0x10, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(scv, 0x11, 0x00, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(rfscv, 0x13, 0x12, 0x02, 0x03FF8001, PPC_NONE, PPC2_ISA300),
#endif
GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300), GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
@ -7056,7 +7099,9 @@ GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H), GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
#endif #endif
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW), /* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW),
GEN_HANDLER(sc, 0x11, 0x01, 0xFF, 0x03FFF01D, PPC_FLOW),
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW), GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW), GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
@ -7835,6 +7880,12 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
} else { } else {
ctx->vsx_enabled = false; ctx->vsx_enabled = false;
} }
if ((env->flags & POWERPC_FLAG_SCV)
&& (env->spr[SPR_FSCR] & (1ull << FSCR_SCV))) {
ctx->scv_enabled = true;
} else {
ctx->scv_enabled = false;
}
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
if ((env->flags & POWERPC_FLAG_TM) && msr_tm) { if ((env->flags & POWERPC_FLAG_TM) && msr_tm) {
ctx->tm_enabled = !!msr_tm; ctx->tm_enabled = !!msr_tm;

View File

@ -3382,6 +3382,7 @@ static void init_excp_POWER9(CPUPPCState *env)
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0; env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0;
env->excp_vectors[POWERPC_EXCP_SYSCALL_VECTORED] = 0x00000000;
#endif #endif
} }
@ -9030,7 +9031,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM | POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR | POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
POWERPC_FLAG_VSX | POWERPC_FLAG_TM; POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV;
pcc->l1_dcache_size = 0x8000; pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000; pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;