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 "qemu/cutils.h"
#include "qemu/module.h"
#include "trace.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
/* macio style NVRAM device */
@ -51,9 +42,8 @@ static void macio_nvram_writeb(void *opaque, hwaddr addr,
MacIONVRAMState *s = opaque;
addr = (addr >> s->it_shift) & (s->size - 1);
trace_macio_nvram_write(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,
@ -64,8 +54,7 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
addr = (addr >> s->it_shift) & (s->size - 1);
value = s->data[addr];
NVR_DPRINTF("readb addr %04" HWADDR_PRIx " val %" PRIx32 "\n",
addr, value);
trace_macio_nvram_read(addr, 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_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
# 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_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)
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);
ppc_cpu_do_system_reset(cs);
/*
* SRR1[42:45] is set to 0100 which the ISA defines as implementation
* dependent. POWER processors use this for xscom triggered interrupts,
* which come from the BMC or NMI IPIs.
*/
env->spr[SPR_SRR1] |= PPC_BIT(43);
if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
/*
* Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
* wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
* (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)

View File

@ -445,7 +445,8 @@ static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt,
g_assert(drc);
elem = spapr_get_drconf_cell(size / lmb_size, addr,
spapr_drc_index(drc), node,
SPAPR_LMB_FLAGS_ASSIGNED);
(SPAPR_LMB_FLAGS_ASSIGNED |
SPAPR_LMB_FLAGS_HOTREMOVABLE));
QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
nr_entries++;
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("power9_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power10_v1.0"),
#ifdef CONFIG_KVM
DEFINE_SPAPR_CPU_CORE_TYPE("host"),
#endif

View File

@ -1620,7 +1620,7 @@ int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp)
}
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);
if (p == MAP_FAILED) {
ret = -errno;
@ -1680,7 +1680,7 @@ int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp)
/* Some NVLink bridges may not have assigned ATSD */
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);
if (p == MAP_FAILED) {
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_DRC_INVALID 0x00000020
#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);

View File

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

View File

@ -127,8 +127,9 @@ enum {
POWERPC_EXCP_SDOOR_HV = 100,
/* ISA 3.00 additions */
POWERPC_EXCP_HVIRT = 101,
POWERPC_EXCP_SYSCALL_VECTORED = 102, /* scv exception */
/* EOL */
POWERPC_EXCP_NB = 102,
POWERPC_EXCP_NB = 103,
/* QEMU exceptions: used internally during code translation */
POWERPC_EXCP_STOP = 0x200, /* stop translation */
POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */
@ -475,9 +476,31 @@ typedef struct ppc_v3_pate_t {
#define SRR1_PROTFAULT DSISR_PROTFAULT
#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 */
#define FSCR_EBB (63 - 56) /* Event-Based Branch Facility */
#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 */
#define FSCR_IC_MASK (0xFFULL)
#define FSCR_IC_POS (63 - 7)
@ -487,6 +510,7 @@ typedef struct ppc_v3_pate_t {
#define FSCR_IC_TM 5
#define FSCR_IC_EBB 7
#define FSCR_IC_TAR 8
#define FSCR_IC_SCV 12
/* Exception state register bits definition */
#define ESR_PIL PPC_BIT(36) /* Illegal Instruction */
@ -554,6 +578,8 @@ enum {
POWERPC_FLAG_VSX = 0x00080000,
/* Has Transaction Memory (ISA 2.07) */
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);
}
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)
{
qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
" r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
" r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
" r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
" r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
" r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
" r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
" nip=" TARGET_FMT_lx "\n",
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),
ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
env->nip);
ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
env->nip);
}
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;
/* 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 */
if (excp == POWERPC_EXCP_MCHECK) {
@ -97,25 +109,25 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
}
switch (excp) {
case POWERPC_EXCP_RESET:
*msr |= 0x4ull << (63 - 45);
*msr |= SRR1_WAKERESET;
break;
case POWERPC_EXCP_EXTERNAL:
*msr |= 0x8ull << (63 - 45);
*msr |= SRR1_WAKEEE;
break;
case POWERPC_EXCP_DECR:
*msr |= 0x6ull << (63 - 45);
*msr |= SRR1_WAKEDEC;
break;
case POWERPC_EXCP_SDOOR:
*msr |= 0x5ull << (63 - 45);
*msr |= SRR1_WAKEDBELL;
break;
case POWERPC_EXCP_SDOOR_HV:
*msr |= 0x3ull << (63 - 45);
*msr |= SRR1_WAKEHDBELL;
break;
case POWERPC_EXCP_HV_MAINT:
*msr |= 0xaull << (63 - 45);
*msr |= SRR1_WAKEHMI;
break;
case POWERPC_EXCP_HVIRT:
*msr |= 0x9ull << (63 - 45);
*msr |= SRR1_WAKEHVI;
break;
default:
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);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
int srr0, srr1, asrr0, asrr1, lev, ail;
int srr0, srr1, asrr0, asrr1, lev = -1, ail;
bool lpes0;
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;
}
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_APU: /* Auxiliary processor unavailable */
case POWERPC_EXCP_DECR: /* Decrementer exception */
@ -724,12 +743,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
break;
}
/* Save PC */
env->spr[srr0] = env->nip;
/* Save MSR */
env->spr[srr1] = msr;
/* Sanity check */
if (!(env->msr_mask & 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
* CPU, the HV mode, etc...
@ -784,14 +789,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
#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
* 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))) {
ail = 0;
}
/* Handle AIL */
if (ail) {
new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
vector |= ppc_excp_vector_offset(cs, ail);
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;
/* 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)
@ -823,6 +831,37 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
#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);
}
@ -1160,6 +1199,11 @@ void helper_rfid(CPUPPCState *env)
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)
{
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)
DEF_HELPER_2(pminsn, void, env, i32)
DEF_HELPER_1(rfid, void, env)
DEF_HELPER_1(rfscv, void, env)
DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl)
DEF_HELPER_2(store_pcr, void, env, tl)

View File

@ -28,7 +28,8 @@
#include "mmu-radix64.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)
{
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;
*pid = 0;
break;
default:
g_assert_not_reached();
}
} else { /* !MSR[HV] -> Guest */
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];
*pid = 0; /* pid set to 0 -> addresses guest operating system */
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,
hwaddr *h_raddr, int *h_prot,
int *h_page_size, bool pde_addr,
bool cause_excp)
bool guest_visible)
{
int fault_cause = 0;
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,
&pte, &fault_cause, &pte_addr) ||
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;
if (cause_excp) {
}
if (guest_visible) {
ppc_radix64_raise_hsi(cpu, rwx, eaddr, g_raddr, fault_cause);
}
return 1;
}
/* Update Reference and Change Bits */
ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot);
if (guest_visible) {
ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot);
}
return 0;
}
@ -299,7 +306,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
vaddr eaddr, uint64_t pid,
ppc_v3_pate_t pate, hwaddr *g_raddr,
int *g_prot, int *g_page_size,
bool cause_excp)
bool guest_visible)
{
CPUState *cs = CPU(cpu);
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);
if (offset >= size) {
/* offset exceeds size of the process table */
if (cause_excp) {
if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
}
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,
pate, &h_raddr, &h_prot,
&h_page_size, 1, 1);
&h_page_size, true,
guest_visible);
if (ret) {
return ret;
}
@ -353,7 +361,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
&fault_cause, &pte_addr);
if (ret) {
/* No valid PTE */
if (cause_excp) {
if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
}
return ret;
@ -372,7 +380,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
do {
ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr,
pate, &h_raddr, &h_prot,
&h_page_size, 1, 1);
&h_page_size, true,
guest_visible);
if (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);
if (ret) {
/* No valid pte */
if (cause_excp) {
if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
}
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)) {
/* Access denied due to protection */
if (cause_excp) {
if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
}
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;
}
@ -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,
bool relocation,
hwaddr *raddr, int *psizep, int *protp,
bool cause_excp)
bool guest_visible)
{
CPUPPCState *env = &cpu->env;
uint64_t lpid = 0, pid = 0;
uint64_t lpid, pid;
ppc_v3_pate_t pate;
int psize, prot;
hwaddr g_raddr;
/* Virtual Mode Access - get the fully qualified address */
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);
}
return 1;
@ -452,13 +463,13 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
vhc->get_pate(cpu->vhyp, &pate);
} else {
if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
if (cause_excp) {
if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
}
return 1;
}
if (!validate_pate(cpu, lpid, &pate)) {
if (cause_excp) {
if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
}
return 1;
@ -479,7 +490,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
if (relocation) {
int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid,
pate, &g_raddr, &prot,
&psize, cause_excp);
&psize, guest_visible);
if (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,
pate, raddr, &prot, &psize,
0, cause_excp);
false, guest_visible);
if (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);
}
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 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 spe_enabled;
bool tm_enabled;
bool scv_enabled;
bool gtse;
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
int singlestep_enabled;
@ -4030,6 +4031,24 @@ static void gen_rfid(DisasContext *ctx)
#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)
{
#if defined(CONFIG_USER_ONLY)
@ -4048,6 +4067,7 @@ static void gen_hrfid(DisasContext *ctx)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED
#endif
static void gen_sc(DisasContext *ctx)
{
@ -4057,6 +4077,23 @@ static void gen_sc(DisasContext *ctx)
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 ***/
/* 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),
#if defined(TARGET_PPC64)
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(doze, 0x13, 0x12, 0x0c, 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(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
#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(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
#if defined(TARGET_PPC64)
@ -7835,6 +7880,12 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
} else {
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 ((env->flags & POWERPC_FLAG_TM) && 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)
env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0;
env->excp_vectors[POWERPC_EXCP_SYSCALL_VECTORED] = 0x00000000;
#endif
}
@ -9030,7 +9031,7 @@ POWERPC_FAMILY(POWER9)(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 |
POWERPC_FLAG_VSX | POWERPC_FLAG_TM;
POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;