diff options
author | Peter Maydell | 2021-09-30 17:13:04 +0200 |
---|---|---|
committer | Peter Maydell | 2021-09-30 17:13:04 +0200 |
commit | fce8f7735fcea23056ff41be55e73eacbca31b5e (patch) | |
tree | c9cf170dc81151d2b0c5e7ec8929c4c5af3d4e12 /target | |
parent | Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2021-09-27-v2' into... (diff) | |
parent | MAINTAINERS: Demote sPAPR from "Supported" to "Maintained" (diff) | |
download | qemu-fce8f7735fcea23056ff41be55e73eacbca31b5e.tar.gz qemu-fce8f7735fcea23056ff41be55e73eacbca31b5e.tar.xz qemu-fce8f7735fcea23056ff41be55e73eacbca31b5e.zip |
Merge remote-tracking branch 'remotes/dg-gitlab/tags/ppc-for-6.2-20210930' into staging
ppc patch queue for 2021-09-30
Here's the next batch of ppc related patches for qemu-6.2. Highlights
are:
* Fixes for several TCG math instructions from the El Dorado Institute
* A number of improvements to the powernv machine type
* Support for a new DEVICE_UNPLUG_GUEST_ERROR QAPI event from Daniel
Barboza
* Support for the new FORM2 PAPR NUMA representation. This allows
more specific NUMA distances, as well as asymmetric configurations
* Fix for 64-bit decrementer (used on MicroWatt CPUs)
* Assorted fixes and cleanups
* A number of updates to MAINTAINERS
Note that the DEVICE_UNPLUG_GUEST_ERROR stuff includes changes to
files outside my normal area, but has suitable Acks.
The MAINTAINERS updates are mostly about marking minor platforms
unmaintained / orphaned, and moving some pieces away from myself and
Greg. As we move onto other projects, we're going to need to drop
more of the ppc maintainership, though we're hoping we can avoid too
abrupt a change.
# gpg: Signature made Thu 30 Sep 2021 06:42:41 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/dg-gitlab/tags/ppc-for-6.2-20210930: (44 commits)
MAINTAINERS: Demote sPAPR from "Supported" to "Maintained"
MAINTAINERS: Add information for OpenPIC
MAINTAINERS: Remove David & Greg as reviewers/co-maintainers of powernv
MAINTAINERS: Orphan obscure ppc platforms
MAINTAINERS: Remove David & Greg as reviewers for a number of boards
MAINTAINERS: Remove machine specific files from ppc TCG CPUs entry
spapr/xive: Fix kvm_xive_source_reset trace event
spapr_numa.c: fixes in spapr_numa_FORM2_write_rtas_tables()
hw/intc: openpic: Clean up the styles
hw/intc: openpic: Drop Raven related codes
hw/intc: openpic: Correct the reset value of IPIDR for FSL chipset
target/ppc: Fix 64-bit decrementer
target/ppc: Convert debug to trace events (decrementer and IRQ)
spapr_numa.c: handle auto NUMA node with no distance info
spapr_numa.c: FORM2 NUMA affinity support
spapr: move FORM1 verifications to post CAS
spapr_numa.c: rename numa_assoc_array to FORM1_assoc_array
spapr_numa.c: parametrize FORM1 macros
spapr_numa.c: scrap 'legacy_numa' concept
spapr_numa.c: split FORM1 code into helpers
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/ppc/cpu.h | 1 | ||||
-rw-r--r-- | target/ppc/excp_helper.c | 38 | ||||
-rw-r--r-- | target/ppc/helper_regs.c | 3 | ||||
-rw-r--r-- | target/ppc/int_helper.c | 61 | ||||
-rw-r--r-- | target/ppc/trace-events | 8 | ||||
-rw-r--r-- | target/ppc/translate.c | 28 |
6 files changed, 93 insertions, 46 deletions
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 01d3773bc7..baa4e7c34d 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -600,6 +600,7 @@ enum { HFLAGS_64 = 2, /* computed from MSR_CE and MSR_SF */ HFLAGS_GTSE = 3, /* computed from SPR_LPCR[GTSE] */ HFLAGS_DR = 4, /* MSR_DR */ + HFLAGS_HR = 5, /* computed from SPR_LPCR[HR] */ HFLAGS_SPE = 6, /* from MSR_SPE if cpu has SPE; avoid overlap w/ MSR_VR */ HFLAGS_TM = 8, /* computed from MSR_TM */ HFLAGS_BE = 9, /* MSR_BE -- from elsewhere on embedded ppc */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index d7e32ee107..b7d1767920 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -23,20 +23,14 @@ #include "internal.h" #include "helper_regs.h" +#include "trace.h" + #ifdef CONFIG_TCG #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" #endif -/* #define DEBUG_OP */ /* #define DEBUG_SOFTWARE_TLB */ -/* #define DEBUG_EXCEPTIONS */ - -#ifdef DEBUG_EXCEPTIONS -# define LOG_EXCP(...) qemu_log(__VA_ARGS__) -#else -# define LOG_EXCP(...) do { } while (0) -#endif /*****************************************************************************/ /* Exception processing */ @@ -414,12 +408,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } break; case POWERPC_EXCP_DSI: /* Data storage exception */ - LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx - "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); + trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); break; case POWERPC_EXCP_ISI: /* Instruction storage exception */ - LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx - "\n", msr, env->nip); + trace_ppc_excp_isi(msr, env->nip); msr |= env->error_code; break; case POWERPC_EXCP_EXTERNAL: /* External input */ @@ -474,7 +466,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) switch (env->error_code & ~0xF) { case POWERPC_EXCP_FP: if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { - LOG_EXCP("Ignore floating point exception\n"); + trace_ppc_excp_fp_ignore(); cs->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; return; @@ -489,7 +481,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) env->spr[SPR_BOOKE_ESR] = ESR_FP; break; case POWERPC_EXCP_INVAL: - LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); + trace_ppc_excp_inval(env->nip); msr |= 0x00080000; env->spr[SPR_BOOKE_ESR] = ESR_PIL; break; @@ -547,10 +539,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) break; case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ /* FIT on 4xx */ - LOG_EXCP("FIT exception\n"); + trace_ppc_excp_print("FIT"); break; case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ - LOG_EXCP("WDT exception\n"); + trace_ppc_excp_print("WDT"); switch (excp_model) { case POWERPC_EXCP_BOOKE: srr0 = SPR_BOOKE_CSRR0; @@ -657,7 +649,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) #endif break; case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ - LOG_EXCP("PIT exception\n"); + trace_ppc_excp_print("PIT"); break; case POWERPC_EXCP_IO: /* IO error exception */ /* XXX: TODO */ @@ -1115,14 +1107,6 @@ bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) #endif /* !CONFIG_USER_ONLY */ -#if defined(DEBUG_OP) -static void cpu_dump_rfi(target_ulong RA, target_ulong msr) -{ - qemu_log("Return from exception at " TARGET_FMT_lx " with flags " - TARGET_FMT_lx "\n", RA, msr); -} -#endif - /*****************************************************************************/ /* Exceptions processing helpers */ @@ -1221,9 +1205,7 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) /* XXX: beware: this is false if VLE is supported */ env->nip = nip & ~((target_ulong)0x00000003); hreg_store_msr(env, msr, 1); -#if defined(DEBUG_OP) - cpu_dump_rfi(env->nip, env->msr); -#endif + trace_ppc_excp_rfi(env->nip, env->msr); /* * No need to raise an exception here, as rfi is always the last * insn of a TB diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 405450d863..1bfb480ecf 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -106,6 +106,9 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env) if (env->spr[SPR_LPCR] & LPCR_GTSE) { hflags |= 1 << HFLAGS_GTSE; } + if (env->spr[SPR_LPCR] & LPCR_HR) { + hflags |= 1 << HFLAGS_HR; + } #ifndef CONFIG_USER_ONLY if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) { diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index c2d3248d1e..f5dac3aa87 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -2480,10 +2480,26 @@ uint32_t helper_bcdctz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) return cr; } +/** + * Compare 2 128-bit unsigned integers, passed in as unsigned 64-bit pairs + * + * Returns: + * > 0 if ahi|alo > bhi|blo, + * 0 if ahi|alo == bhi|blo, + * < 0 if ahi|alo < bhi|blo + */ +static inline int ucmp128(uint64_t alo, uint64_t ahi, + uint64_t blo, uint64_t bhi) +{ + return (ahi == bhi) ? + (alo > blo ? 1 : (alo == blo ? 0 : -1)) : + (ahi > bhi ? 1 : -1); +} + uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) { int i; - int cr = 0; + int cr; uint64_t lo_value; uint64_t hi_value; ppc_avr_t ret = { .u64 = { 0, 0 } }; @@ -2492,28 +2508,47 @@ uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) lo_value = -b->VsrSD(1); hi_value = ~b->VsrD(0) + !lo_value; bcd_put_digit(&ret, 0xD, 0); + + cr = CRF_LT; } else { lo_value = b->VsrD(1); hi_value = b->VsrD(0); bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0); - } - if (divu128(&lo_value, &hi_value, 1000000000000000ULL) || - lo_value > 9999999999999999ULL) { - cr = CRF_SO; + if (hi_value == 0 && lo_value == 0) { + cr = CRF_EQ; + } else { + cr = CRF_GT; + } } - for (i = 1; i < 16; hi_value /= 10, i++) { - bcd_put_digit(&ret, hi_value % 10, i); - } + /* + * Check src limits: abs(src) <= 10^31 - 1 + * + * 10^31 - 1 = 0x0000007e37be2022 c0914b267fffffff + */ + if (ucmp128(lo_value, hi_value, + 0xc0914b267fffffffULL, 0x7e37be2022ULL) > 0) { + cr |= CRF_SO; - for (; i < 32; lo_value /= 10, i++) { - bcd_put_digit(&ret, lo_value % 10, i); - } + /* + * According to the ISA, if src wouldn't fit in the destination + * register, the result is undefined. + * In that case, we leave r unchanged. + */ + } else { + divu128(&lo_value, &hi_value, 1000000000000000ULL); - cr |= bcd_cmp_zero(&ret); + for (i = 1; i < 16; hi_value /= 10, i++) { + bcd_put_digit(&ret, hi_value % 10, i); + } - *r = ret; + for (; i < 32; lo_value /= 10, i++) { + bcd_put_digit(&ret, lo_value % 10, i); + } + + *r = ret; + } return cr; } diff --git a/target/ppc/trace-events b/target/ppc/trace-events index c88cfccf8d..53b107f56e 100644 --- a/target/ppc/trace-events +++ b/target/ppc/trace-events @@ -28,3 +28,11 @@ kvm_handle_epr(void) "handle epr" kvm_handle_watchdog_expiry(void) "handle watchdog expiry" kvm_handle_debug_exception(void) "handle debug exception" kvm_handle_nmi_exception(void) "handle NMI exception" + +# excp_helper.c +ppc_excp_rfi(uint64_t nip, uint64_t msr) "Return from exception at 0x%" PRIx64 " with flags 0x%016" PRIx64 +ppc_excp_dsi(uint64_t dsisr, uint64_t dar) "DSI exception: DSISR=0x%" PRIx64 " DAR=0x%" PRIx64 +ppc_excp_isi(uint64_t msr, uint64_t nip) "ISI exception: msr=0x%016" PRIx64 " nip=0x%" PRIx64 +ppc_excp_fp_ignore(void) "Ignore floating point exception" +ppc_excp_inval(uint64_t nip) "Invalid instruction at 0x%" PRIx64 +ppc_excp_print(const char *excp) "%s exception" diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 5d8b06bd80..b985e9e55b 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -175,6 +175,7 @@ struct DisasContext { bool spe_enabled; bool tm_enabled; bool gtse; + bool hr; ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ int singlestep_enabled; uint32_t flags; @@ -5516,7 +5517,15 @@ static void gen_tlbiel(DisasContext *ctx) #if defined(CONFIG_USER_ONLY) GEN_PRIV; #else - CHK_SV; + bool psr = (ctx->opcode >> 17) & 0x1; + + if (ctx->pr || (!ctx->hv && !psr && ctx->hr)) { + /* + * tlbiel is privileged except when PSR=0 and HR=1, making it + * hypervisor privileged. + */ + GEN_PRIV; + } gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); #endif /* defined(CONFIG_USER_ONLY) */ @@ -5528,12 +5537,20 @@ static void gen_tlbie(DisasContext *ctx) #if defined(CONFIG_USER_ONLY) GEN_PRIV; #else + bool psr = (ctx->opcode >> 17) & 0x1; TCGv_i32 t1; - if (ctx->gtse) { - CHK_SV; /* If gtse is set then tlbie is supervisor privileged */ - } else { - CHK_HV; /* Else hypervisor privileged */ + if (ctx->pr) { + /* tlbie is privileged... */ + GEN_PRIV; + } else if (!ctx->hv) { + if (!ctx->gtse || (!psr && ctx->hr)) { + /* + * ... except when GTSE=0 or when PSR=0 and HR=1, making it + * hypervisor privileged. + */ + GEN_PRIV; + } } if (NARROW_MODE(ctx)) { @@ -8539,6 +8556,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->vsx_enabled = (hflags >> HFLAGS_VSX) & 1; ctx->tm_enabled = (hflags >> HFLAGS_TM) & 1; ctx->gtse = (hflags >> HFLAGS_GTSE) & 1; + ctx->hr = (hflags >> HFLAGS_HR) & 1; ctx->singlestep_enabled = 0; if ((hflags >> HFLAGS_SE) & 1) { |