summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell2022-01-13 12:18:24 +0100
committerPeter Maydell2022-01-13 12:18:24 +0100
commitf8d75e10d3e0033a0a29a7a7e4777a4fbc17a016 (patch)
tree73e17a7077c2655bd668b4a8683aa46deb193831 /target
parentMerge remote-tracking branch 'remotes/lvivier-gitlab/tags/linux-user-for-7.0-... (diff)
parentppc/pnv: use stack->pci_regs[] in pnv_pec_stk_pci_xscom_write() (diff)
downloadqemu-f8d75e10d3e0033a0a29a7a7e4777a4fbc17a016.tar.gz
qemu-f8d75e10d3e0033a0a29a7a7e4777a4fbc17a016.tar.xz
qemu-f8d75e10d3e0033a0a29a7a7e4777a4fbc17a016.zip
Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220112' into staging
ppc 7.0 queue: * New SLOF for PPC970 and POWER5+ (Alexey) * Fixes for POWER5+ pseries (Cedric) * Updates of documentation (Leonardo and Thomas) * First step of exception model cleanup (Fabiano) * User created PHB3/PHB4 devices (Daniel and Cedric) # gpg: Signature made Wed 12 Jan 2022 10:43:21 GMT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * remotes/legoater/tags/pull-ppc-20220112: (34 commits) ppc/pnv: use stack->pci_regs[] in pnv_pec_stk_pci_xscom_write() ppc/pnv: turn pnv_phb4_update_regions() into static ppc/pnv: Introduce user creatable pnv-phb4 devices ppc/pnv: turn 'phb' into a pointer in struct PnvPhb4PecStack ppc/pnv: move PHB4 XSCOM init to phb4_realize() ppc/pnv: set phb4 properties in stk_realize() pnv_phb4_pec: use pnv_phb4_pec_get_phb_id() in pnv_pec_dt_xscom() pnv_phb4_pec.c: move pnv_pec_phb_offset() to pnv_phb4.c pnv_phb4.c: change TYPE_PNV_PHB4_ROOT_BUS name pnv_phb3.h: change TYPE_PNV_PHB3_ROOT_BUS name ppc/pnv: Move num_phbs under Pnv8Chip ppc/pnv: Complete user created PHB3 devices ppc/pnv: Reparent user created PHB3 devices to the PnvChip ppc/pnv: Introduce support for user created PHB3 devices pnv_phb4.c: check if root port exists in rc_config functions pnv_phb4.c: make pnv-phb4-root-port user creatable ppc/pnv: Attach PHB3 root port device when defaults are enabled pnv_phb4.c: add unique chassis and slot for pnv_phb4_root_port pnv_phb3.c: add unique chassis and slot for pnv_phb3_root_port target/ppc: Set the correct endianness for powernv memory dumps ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/ppc/arch_dump.c2
-rw-r--r--target/ppc/cpu.h25
-rw-r--r--target/ppc/cpu_init.c2
-rw-r--r--target/ppc/excp_helper.c185
4 files changed, 76 insertions, 138 deletions
diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c
index bb392f6d88..993740897d 100644
--- a/target/ppc/arch_dump.c
+++ b/target/ppc/arch_dump.c
@@ -237,7 +237,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
info->d_machine = PPC_ELF_MACHINE;
info->d_class = ELFCLASS;
- if (ppc_interrupts_little_endian(cpu)) {
+ if (ppc_interrupts_little_endian(cpu, cpu->env.has_hv_mode)) {
info->d_endian = ELFDATA2LSB;
} else {
info->d_endian = ELFDATA2MSB;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index f20d4ffa6d..f99cd0ea92 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2728,20 +2728,29 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr)
return cpu->env.spr_cb[spr].name != NULL;
}
-static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu)
+#if !defined(CONFIG_USER_ONLY)
+static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ bool ile;
+
+ if (hv && env->has_hv_mode) {
+ if (is_isa300(pcc)) {
+ ile = !!(env->spr[SPR_HID0] & HID0_POWER9_HILE);
+ } else {
+ ile = !!(env->spr[SPR_HID0] & HID0_HILE);
+ }
- /*
- * Only models that have an LPCR and know about LPCR_ILE can do little
- * endian.
- */
- if (pcc->lpcr_mask & LPCR_ILE) {
- return !!(cpu->env.spr[SPR_LPCR] & LPCR_ILE);
+ } else if (pcc->lpcr_mask & LPCR_ILE) {
+ ile = !!(env->spr[SPR_LPCR] & LPCR_ILE);
+ } else {
+ ile = !!(msr_ile);
}
- return false;
+ return ile;
}
+#endif
void dump_mmu(CPUPPCState *env);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index cc93bff3fa..e30e86fe9d 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6953,10 +6953,12 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
PPC_FLOAT_STFIWX |
+ PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B |
+ PPC_POPCNTB |
PPC_SEGMENT_64B | PPC_SLBI;
pcc->insns_flags2 = PPC2_FP_CVT_S64;
pcc->msr_mask = (1ull << MSR_SF) |
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index a779dc936a..bc646c67a0 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -30,8 +30,6 @@
#include "exec/cpu_ldst.h"
#endif
-/* #define DEBUG_SOFTWARE_TLB */
-
/*****************************************************************************/
/* Exception processing */
#if !defined(CONFIG_USER_ONLY)
@@ -135,6 +133,39 @@ static void dump_hcall(CPUPPCState *env)
env->nip);
}
+static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
+{
+ const char *es;
+ target_ulong *miss, *cmp;
+ int en;
+
+ if (!qemu_loglevel_mask(CPU_LOG_MMU)) {
+ return;
+ }
+
+ if (excp == POWERPC_EXCP_IFTLB) {
+ es = "I";
+ en = 'I';
+ miss = &env->spr[SPR_IMISS];
+ cmp = &env->spr[SPR_ICMP];
+ } else {
+ if (excp == POWERPC_EXCP_DLTLB) {
+ es = "DL";
+ } else {
+ es = "DS";
+ }
+ en = 'D';
+ miss = &env->spr[SPR_DMISS];
+ cmp = &env->spr[SPR_DCMP];
+ }
+ qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
+ TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
+ TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
+ env->spr[SPR_HASH1], env->spr[SPR_HASH2],
+ env->error_code);
+}
+
+
static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
target_ulong *msr)
{
@@ -365,7 +396,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu,
* Note that this function should be greatly optimized when called
* with a constant excp, from ppc_hw_interrupt
*/
-static void powerpc_excp(PowerPCCPU *cpu, int excp)
+static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
@@ -669,23 +700,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
break;
- case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "Embedded floating point data exception "
- "is not implemented yet !\n");
- env->spr[SPR_BOOKE_ESR] = ESR_SPV;
- break;
- case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "Embedded floating point round exception "
- "is not implemented yet !\n");
- env->spr[SPR_BOOKE_ESR] = ESR_SPV;
- break;
- case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
- /* XXX: TODO */
- cpu_abort(cs,
- "Performance counter exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
break;
case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
@@ -750,19 +764,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
trace_ppc_excp_print("PIT");
break;
- case POWERPC_EXCP_IO: /* IO error exception */
- /* XXX: TODO */
- cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
- break;
- case POWERPC_EXCP_RUNM: /* Run mode exception */
- /* XXX: TODO */
- cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
- break;
- case POWERPC_EXCP_EMUL: /* Emulation trap exception */
- /* XXX: TODO */
- cpu_abort(cs, "602 emulation trap exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
@@ -777,34 +778,8 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
}
/* fall through */
case POWERPC_EXCP_7x5:
-#if defined(DEBUG_SOFTWARE_TLB)
- if (qemu_log_enabled()) {
- const char *es;
- target_ulong *miss, *cmp;
- int en;
-
- if (excp == POWERPC_EXCP_IFTLB) {
- es = "I";
- en = 'I';
- miss = &env->spr[SPR_IMISS];
- cmp = &env->spr[SPR_ICMP];
- } else {
- if (excp == POWERPC_EXCP_DLTLB) {
- es = "DL";
- } else {
- es = "DS";
- }
- en = 'D';
- miss = &env->spr[SPR_DMISS];
- cmp = &env->spr[SPR_DCMP];
- }
- qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
- TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
- TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
- env->spr[SPR_HASH1], env->spr[SPR_HASH2],
- env->error_code);
- }
-#endif
+ ppc_excp_debug_sw_tlb(env, excp);
+
msr |= env->crf[0] << 28;
msr |= env->error_code; /* key, D/I, S/L bits */
/* Set way using a LRU mechanism */
@@ -815,56 +790,25 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
break;
}
break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
+ case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
+ case POWERPC_EXCP_IO: /* IO error exception */
+ case POWERPC_EXCP_RUNM: /* Run mode exception */
+ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
case POWERPC_EXCP_FPA: /* Floating-point assist exception */
- /* XXX: TODO */
- cpu_abort(cs, "Floating point assist exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_DABR: /* Data address breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "DABR exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "IABR exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_SMI: /* System management interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "SMI exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_THERM: /* Thermal interrupt */
- /* XXX: TODO */
- cpu_abort(cs, "Thermal management exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
- /* XXX: TODO */
- cpu_abort(cs,
- "Performance counter exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_VPUA: /* Vector assist exception */
- /* XXX: TODO */
- cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_SOFTP: /* Soft patch exception */
- /* XXX: TODO */
- cpu_abort(cs,
- "970 soft-patch exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_MAINT: /* Maintenance exception */
- /* XXX: TODO */
- cpu_abort(cs,
- "970 maintenance exception is not implemented yet !\n");
- break;
case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "Maskable external exception "
- "is not implemented yet !\n");
- break;
case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
- /* XXX: TODO */
- cpu_abort(cs, "Non maskable external exception "
- "is not implemented yet !\n");
+ cpu_abort(cs, "%s exception not implemented\n",
+ powerpc_excp_name(excp));
break;
default:
excp_invalid:
@@ -888,36 +832,9 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
* Sort out endianness of interrupt, this differs depending on the
* CPU, the HV mode, etc...
*/
-#ifdef TARGET_PPC64
- if (excp_model == POWERPC_EXCP_POWER7) {
- if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (excp_model == POWERPC_EXCP_POWER8) {
- if (new_msr & MSR_HVB) {
- if (env->spr[SPR_HID0] & HID0_HILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (excp_model == POWERPC_EXCP_POWER9 ||
- excp_model == POWERPC_EXCP_POWER10) {
- if (new_msr & MSR_HVB) {
- if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
- } else if (msr_ile) {
+ if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
new_msr |= (target_ulong)1 << MSR_LE;
}
-#else
- if (msr_ile) {
- new_msr |= (target_ulong)1 << MSR_LE;
- }
-#endif
#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_BOOKE) {
@@ -950,6 +867,16 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
powerpc_set_excp_state(cpu, vector, new_msr);
}
+static void powerpc_excp(PowerPCCPU *cpu, int excp)
+{
+ CPUPPCState *env = &cpu->env;
+
+ switch (env->excp_model) {
+ default:
+ powerpc_excp_legacy(cpu, excp);
+ }
+}
+
void ppc_cpu_do_interrupt(CPUState *cs)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -1126,7 +1053,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
*/
msr = (1ULL << MSR_ME);
msr |= env->msr & (1ULL << MSR_SF);
- if (ppc_interrupts_little_endian(cpu)) {
+ if (ppc_interrupts_little_endian(cpu, false)) {
msr |= (1ULL << MSR_LE);
}