* [PATCH v3 1/2] target/ppc: Improve syscall exception logging
@ 2020-03-17 5:49 Nicholas Piggin
2020-03-17 5:49 ` [PATCH v3 2/2] target/ppc: Add support for scv and rfscv instructions Nicholas Piggin
2020-03-19 6:22 ` [PATCH v3 1/2] target/ppc: Improve syscall exception logging David Gibson
0 siblings, 2 replies; 4+ messages in thread
From: Nicholas Piggin @ 2020-03-17 5:49 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, Nicholas Piggin, David Gibson
system calls (at least in Linux) use registers r3-r8 for inputs, so
include those registers in the dump.
This also adds a mode for PAPR hcalls, which have a different calling
convention.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
Since v2:
- Rebased on top of FWNMI series
target/ppc/excp_helper.c | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 08bc885ca6..81ee19ebae 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -57,12 +57,29 @@ static void ppc_hw_interrupt(CPUPPCState *env)
#else /* defined(CONFIG_USER_ONLY) */
static inline void dump_syscall(CPUPPCState *env)
{
- qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
- " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
+ 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), env->nip);
+ 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
+ " 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);
}
static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
@@ -379,9 +396,14 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
break;
case POWERPC_EXCP_SYSCALL: /* System call exception */
- dump_syscall(env);
lev = env->error_code;
+ if ((lev == 1) && cpu->vhyp) {
+ dump_hcall(env);
+ } else {
+ dump_syscall(env);
+ }
+
/*
* We need to correct the NIP which in this case is supposed
* to point to the next instruction
--
2.23.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/2] target/ppc: Add support for scv and rfscv instructions
2020-03-17 5:49 [PATCH v3 1/2] target/ppc: Improve syscall exception logging Nicholas Piggin
@ 2020-03-17 5:49 ` Nicholas Piggin
2020-03-19 6:22 ` David Gibson
2020-03-19 6:22 ` [PATCH v3 1/2] target/ppc: Improve syscall exception logging David Gibson
1 sibling, 1 reply; 4+ messages in thread
From: Nicholas Piggin @ 2020-03-17 5:49 UTC (permalink / raw)
To: qemu-ppc; +Cc: qemu-devel, Nicholas Piggin, David Gibson
POWER9 adds scv and rfscv instructions and the system call vectored
interrupt. Linux does not support this instruction yet but it has
been tested with a modified kernel that runs on real hardware.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
Since v2:
- Rebased on top of FWNMI series
linux-user/ppc/cpu_loop.c | 1 +
target/ppc/cpu.h | 7 ++-
target/ppc/excp_helper.c | 98 ++++++++++++++++++++++++---------
target/ppc/helper.h | 1 +
target/ppc/translate.c | 46 +++++++++++++++-
target/ppc/translate_init.inc.c | 3 +-
6 files changed, 126 insertions(+), 30 deletions(-)
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 5b27f8603e..df71e15a25 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -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;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index ed8d2015bd..992f0a49e8 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -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,6 +476,7 @@ typedef struct ppc_v3_pate_t {
/* 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)
@@ -484,6 +486,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 */
@@ -551,6 +554,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,
};
/*****************************************************************************/
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 81ee19ebae..73b5c28d03 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -67,6 +67,18 @@ 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
@@ -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 */
@@ -723,12 +742,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) {
@@ -741,14 +754,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...
@@ -783,14 +788,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
@@ -799,10 +796,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)
@@ -822,6 +830,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);
}
@@ -1162,6 +1201,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]);
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index cfb4c07085..ee1498050d 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -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)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 127c82a24e..eb0ddba850 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -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;
@@ -4012,6 +4013,22 @@ static void gen_rfid(DisasContext *ctx)
#endif
}
+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
+}
+
static void gen_hrfid(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
@@ -4030,6 +4047,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)
{
@@ -4039,6 +4057,21 @@ static void gen_sc(DisasContext *ctx)
gen_exception_err(ctx, POWERPC_SYSCALL, lev);
}
+#if defined(TARGET_PPC64)
+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
+
/*** Trap ***/
/* Check for unconditional traps (always or never) */
@@ -7019,6 +7052,10 @@ 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),
+/* 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),
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),
@@ -7026,7 +7063,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)
@@ -7805,6 +7844,11 @@ 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;
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 0ae145e18d..15025cd5ea 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -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;
--
2.23.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/2] target/ppc: Improve syscall exception logging
2020-03-17 5:49 [PATCH v3 1/2] target/ppc: Improve syscall exception logging Nicholas Piggin
2020-03-17 5:49 ` [PATCH v3 2/2] target/ppc: Add support for scv and rfscv instructions Nicholas Piggin
@ 2020-03-19 6:22 ` David Gibson
1 sibling, 0 replies; 4+ messages in thread
From: David Gibson @ 2020-03-19 6:22 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 3157 bytes --]
On Tue, Mar 17, 2020 at 03:49:17PM +1000, Nicholas Piggin wrote:
> system calls (at least in Linux) use registers r3-r8 for inputs, so
> include those registers in the dump.
>
> This also adds a mode for PAPR hcalls, which have a different calling
> convention.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Applied to a newly created ppc-for-5.1 branch.
> ---
> Since v2:
> - Rebased on top of FWNMI series
>
> target/ppc/excp_helper.c | 30 ++++++++++++++++++++++++++----
> 1 file changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 08bc885ca6..81ee19ebae 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -57,12 +57,29 @@ static void ppc_hw_interrupt(CPUPPCState *env)
> #else /* defined(CONFIG_USER_ONLY) */
> static inline void dump_syscall(CPUPPCState *env)
> {
> - qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
> - " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
> + 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), env->nip);
> + 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
> + " 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);
> }
>
> static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
> @@ -379,9 +396,14 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
> }
> break;
> case POWERPC_EXCP_SYSCALL: /* System call exception */
> - dump_syscall(env);
> lev = env->error_code;
>
> + if ((lev == 1) && cpu->vhyp) {
> + dump_hcall(env);
> + } else {
> + dump_syscall(env);
> + }
> +
> /*
> * We need to correct the NIP which in this case is supposed
> * to point to the next instruction
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 2/2] target/ppc: Add support for scv and rfscv instructions
2020-03-17 5:49 ` [PATCH v3 2/2] target/ppc: Add support for scv and rfscv instructions Nicholas Piggin
@ 2020-03-19 6:22 ` David Gibson
0 siblings, 0 replies; 4+ messages in thread
From: David Gibson @ 2020-03-19 6:22 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 14850 bytes --]
On Tue, Mar 17, 2020 at 03:49:18PM +1000, Nicholas Piggin wrote:
> POWER9 adds scv and rfscv instructions and the system call vectored
> interrupt. Linux does not support this instruction yet but it has
> been tested with a modified kernel that runs on real hardware.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Applied to ppc-for-5.1.
> ---
> Since v2:
> - Rebased on top of FWNMI series
>
> linux-user/ppc/cpu_loop.c | 1 +
> target/ppc/cpu.h | 7 ++-
> target/ppc/excp_helper.c | 98 ++++++++++++++++++++++++---------
> target/ppc/helper.h | 1 +
> target/ppc/translate.c | 46 +++++++++++++++-
> target/ppc/translate_init.inc.c | 3 +-
> 6 files changed, 126 insertions(+), 30 deletions(-)
>
> diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
> index 5b27f8603e..df71e15a25 100644
> --- a/linux-user/ppc/cpu_loop.c
> +++ b/linux-user/ppc/cpu_loop.c
> @@ -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;
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index ed8d2015bd..992f0a49e8 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -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,6 +476,7 @@ typedef struct ppc_v3_pate_t {
> /* 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)
> @@ -484,6 +486,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 */
> @@ -551,6 +554,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,
> };
>
> /*****************************************************************************/
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 81ee19ebae..73b5c28d03 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -67,6 +67,18 @@ 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
> @@ -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 */
> @@ -723,12 +742,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) {
> @@ -741,14 +754,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...
> @@ -783,14 +788,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
> @@ -799,10 +796,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)
> @@ -822,6 +830,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);
> }
>
> @@ -1162,6 +1201,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]);
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index cfb4c07085..ee1498050d 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -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)
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 127c82a24e..eb0ddba850 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -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;
> @@ -4012,6 +4013,22 @@ static void gen_rfid(DisasContext *ctx)
> #endif
> }
>
> +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
> +}
> +
> static void gen_hrfid(DisasContext *ctx)
> {
> #if defined(CONFIG_USER_ONLY)
> @@ -4030,6 +4047,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)
> {
> @@ -4039,6 +4057,21 @@ static void gen_sc(DisasContext *ctx)
> gen_exception_err(ctx, POWERPC_SYSCALL, lev);
> }
>
> +#if defined(TARGET_PPC64)
> +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
> +
> /*** Trap ***/
>
> /* Check for unconditional traps (always or never) */
> @@ -7019,6 +7052,10 @@ 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),
> +/* 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),
> 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),
> @@ -7026,7 +7063,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)
> @@ -7805,6 +7844,11 @@ 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;
> diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
> index 0ae145e18d..15025cd5ea 100644
> --- a/target/ppc/translate_init.inc.c
> +++ b/target/ppc/translate_init.inc.c
> @@ -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;
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-03-19 6:24 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-03-17 5:49 [PATCH v3 1/2] target/ppc: Improve syscall exception logging Nicholas Piggin
2020-03-17 5:49 ` [PATCH v3 2/2] target/ppc: Add support for scv and rfscv instructions Nicholas Piggin
2020-03-19 6:22 ` David Gibson
2020-03-19 6:22 ` [PATCH v3 1/2] target/ppc: Improve syscall exception logging David Gibson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).