mirror of
https://github.com/qemu/qemu.git
synced 2024-12-05 01:33:41 +08:00
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:
commit
8b92b9ef86
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
26
hw/ppc/pnv.c
26
hw/ppc/pnv.c
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -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]);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user