* [PATCH v2 01/12] target/ppc: Make checkstop actually stop the system
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 15:32 ` Miles Glenn
2024-05-21 1:30 ` [PATCH v2 02/12] target/ppc: improve checkstop logging Nicholas Piggin
` (10 subsequent siblings)
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
checkstop state does not halt the system, interrupts continue to be
serviced, and other CPUs run. Make it stop the machine with
qemu_system_guest_panicked.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/excp_helper.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 3be086d10b..b2b51537b7 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -19,6 +19,8 @@
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/runstate.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "internal.h"
@@ -425,6 +427,8 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
static void powerpc_mcheck_checkstop(CPUPPCState *env)
{
+ /* KVM guests always have MSR[ME] enabled */
+#ifdef CONFIG_TCG
CPUState *cs = env_cpu(env);
if (FIELD_EX64(env->msr, MSR, ME)) {
@@ -437,9 +441,15 @@ static void powerpc_mcheck_checkstop(CPUPPCState *env)
if (qemu_log_separate()) {
qemu_log("Machine check while not allowed. "
"Entering checkstop state\n");
- }
- cs->halted = 1;
- cpu_interrupt_exittb(cs);
+
+ /*
+ * This stops the machine and logs CPU state without killing QEMU
+ * (like cpu_abort()) so the machine can still be debugged (because
+ * it is often a guest error).
+ */
+ qemu_system_guest_panicked(NULL);
+ cpu_loop_exit_noexc(cs);
+#endif
}
static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 01/12] target/ppc: Make checkstop actually stop the system
2024-05-21 1:30 ` [PATCH v2 01/12] target/ppc: Make checkstop actually stop the system Nicholas Piggin
@ 2024-05-21 15:32 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 15:32 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> checkstop state does not halt the system, interrupts continue to be
> serviced, and other CPUs run. Make it stop the machine with
> qemu_system_guest_panicked.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/excp_helper.c | 16 +++++++++++++---
> 1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 3be086d10b..b2b51537b7 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -19,6 +19,8 @@
> #include "qemu/osdep.h"
> #include "qemu/main-loop.h"
> #include "qemu/log.h"
> +#include "sysemu/sysemu.h"
> +#include "sysemu/runstate.h"
> #include "cpu.h"
> #include "exec/exec-all.h"
> #include "internal.h"
> @@ -425,6 +427,8 @@ static void powerpc_set_excp_state(PowerPCCPU
> *cpu, target_ulong vector,
>
> static void powerpc_mcheck_checkstop(CPUPPCState *env)
> {
> + /* KVM guests always have MSR[ME] enabled */
> +#ifdef CONFIG_TCG
> CPUState *cs = env_cpu(env);
>
> if (FIELD_EX64(env->msr, MSR, ME)) {
> @@ -437,9 +441,15 @@ static void powerpc_mcheck_checkstop(CPUPPCState
> *env)
> if (qemu_log_separate()) {
> qemu_log("Machine check while not allowed. "
> "Entering checkstop state\n");
> - }
> - cs->halted = 1;
> - cpu_interrupt_exittb(cs);
> +
> + /*
> + * This stops the machine and logs CPU state without killing
> QEMU
> + * (like cpu_abort()) so the machine can still be debugged
> (because
> + * it is often a guest error).
> + */
> + qemu_system_guest_panicked(NULL);
> + cpu_loop_exit_noexc(cs);
> +#endif
> }
>
> static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 02/12] target/ppc: improve checkstop logging
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
2024-05-21 1:30 ` [PATCH v2 01/12] target/ppc: Make checkstop actually stop the system Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 15:37 ` Miles Glenn
` (2 more replies)
2024-05-21 1:30 ` [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors Nicholas Piggin
` (9 subsequent siblings)
11 siblings, 3 replies; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
Change the logging not to print to stderr as well, because a
checkstop is a guest error (or perhaps a simulated machine error)
rather than a QEMU error, so send it to the log.
Update the checkstop message, and log CPU registers too.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/excp_helper.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index b2b51537b7..17bf8df9d7 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -430,17 +430,19 @@ static void powerpc_mcheck_checkstop(CPUPPCState *env)
/* KVM guests always have MSR[ME] enabled */
#ifdef CONFIG_TCG
CPUState *cs = env_cpu(env);
+ FILE *f;
if (FIELD_EX64(env->msr, MSR, ME)) {
return;
}
- /* Machine check exception is not enabled. Enter checkstop state. */
- fprintf(stderr, "Machine check while not allowed. "
- "Entering checkstop state\n");
- if (qemu_log_separate()) {
- qemu_log("Machine check while not allowed. "
- "Entering checkstop state\n");
+ f = qemu_log_trylock();
+ if (f) {
+ fprintf(f, "Entering checkstop state: "
+ "machine check with MSR[ME]=0\n");
+ cpu_dump_state(cs, f, CPU_DUMP_FPU | CPU_DUMP_CCOP);
+ qemu_log_unlock(f);
+ }
/*
* This stops the machine and logs CPU state without killing QEMU
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 02/12] target/ppc: improve checkstop logging
2024-05-21 1:30 ` [PATCH v2 02/12] target/ppc: improve checkstop logging Nicholas Piggin
@ 2024-05-21 15:37 ` Miles Glenn
2024-05-21 17:29 ` Richard Henderson
2025-04-29 6:49 ` Philippe Mathieu-Daudé
2 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 15:37 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> Change the logging not to print to stderr as well, because a
> checkstop is a guest error (or perhaps a simulated machine error)
> rather than a QEMU error, so send it to the log.
>
> Update the checkstop message, and log CPU registers too.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/excp_helper.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index b2b51537b7..17bf8df9d7 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -430,17 +430,19 @@ static void
> powerpc_mcheck_checkstop(CPUPPCState *env)
> /* KVM guests always have MSR[ME] enabled */
> #ifdef CONFIG_TCG
> CPUState *cs = env_cpu(env);
> + FILE *f;
>
> if (FIELD_EX64(env->msr, MSR, ME)) {
> return;
> }
>
> - /* Machine check exception is not enabled. Enter checkstop
> state. */
> - fprintf(stderr, "Machine check while not allowed. "
> - "Entering checkstop state\n");
> - if (qemu_log_separate()) {
> - qemu_log("Machine check while not allowed. "
> - "Entering checkstop state\n");
> + f = qemu_log_trylock();
> + if (f) {
> + fprintf(f, "Entering checkstop state: "
> + "machine check with MSR[ME]=0\n");
> + cpu_dump_state(cs, f, CPU_DUMP_FPU | CPU_DUMP_CCOP);
> + qemu_log_unlock(f);
> + }
>
> /*
> * This stops the machine and logs CPU state without killing
> QEMU
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 02/12] target/ppc: improve checkstop logging
2024-05-21 1:30 ` [PATCH v2 02/12] target/ppc: improve checkstop logging Nicholas Piggin
2024-05-21 15:37 ` Miles Glenn
@ 2024-05-21 17:29 ` Richard Henderson
2025-04-29 6:49 ` Philippe Mathieu-Daudé
2 siblings, 0 replies; 31+ messages in thread
From: Richard Henderson @ 2024-05-21 17:29 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles, Chinmay Rath
On 5/20/24 18:30, Nicholas Piggin wrote:
> Change the logging not to print to stderr as well, because a
> checkstop is a guest error (or perhaps a simulated machine error)
> rather than a QEMU error, so send it to the log.
>
> Update the checkstop message, and log CPU registers too.
>
> Signed-off-by: Nicholas Piggin<npiggin@gmail.com>
> ---
> target/ppc/excp_helper.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 02/12] target/ppc: improve checkstop logging
2024-05-21 1:30 ` [PATCH v2 02/12] target/ppc: improve checkstop logging Nicholas Piggin
2024-05-21 15:37 ` Miles Glenn
2024-05-21 17:29 ` Richard Henderson
@ 2025-04-29 6:49 ` Philippe Mathieu-Daudé
2 siblings, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-04-29 6:49 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
(merged as commit 9728fb5c22a)
On 21/5/24 03:30, Nicholas Piggin wrote:
> Change the logging not to print to stderr as well, because a
> checkstop is a guest error (or perhaps a simulated machine error)
> rather than a QEMU error, so send it to the log.
>
> Update the checkstop message, and log CPU registers too.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/excp_helper.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index b2b51537b7..17bf8df9d7 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -430,17 +430,19 @@ static void powerpc_mcheck_checkstop(CPUPPCState *env)
> /* KVM guests always have MSR[ME] enabled */
> #ifdef CONFIG_TCG
> CPUState *cs = env_cpu(env);
> + FILE *f;
>
> if (FIELD_EX64(env->msr, MSR, ME)) {
> return;
> }
>
> - /* Machine check exception is not enabled. Enter checkstop state. */
> - fprintf(stderr, "Machine check while not allowed. "
> - "Entering checkstop state\n");
> - if (qemu_log_separate()) {
> - qemu_log("Machine check while not allowed. "
> - "Entering checkstop state\n");
> + f = qemu_log_trylock();
> + if (f) {
> + fprintf(f, "Entering checkstop state: "
> + "machine check with MSR[ME]=0\n");
> + cpu_dump_state(cs, f, CPU_DUMP_FPU | CPU_DUMP_CCOP);
CPU_DUMP_CCOP seems unused.
> + qemu_log_unlock(f);
> + }
>
> /*
> * This stops the machine and logs CPU state without killing QEMU
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
2024-05-21 1:30 ` [PATCH v2 01/12] target/ppc: Make checkstop actually stop the system Nicholas Piggin
2024-05-21 1:30 ` [PATCH v2 02/12] target/ppc: improve checkstop logging Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 15:41 ` Miles Glenn
2024-05-21 17:34 ` Richard Henderson
2024-05-21 1:30 ` [PATCH v2 04/12] target/ppc: BookE DECAR SPR is 32-bit Nicholas Piggin
` (8 subsequent siblings)
11 siblings, 2 replies; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
attn is an implementation-specific instruction that on POWER (and G5/
970) can be enabled with a HID bit (disabled = illegal), and executing
it causes the host processor to stop and the service processor to be
notified. Generally used for debugging.
Implement attn and make it checkstop the system, which should be good
enough for QEMU debugging.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu.h | 12 +++++
target/ppc/helper.h | 1 +
target/ppc/insn32.decode | 4 ++
target/ppc/cpu_init.c | 69 ++++++++++++++++++++++++++++
target/ppc/excp_helper.c | 43 +++++++++++++----
target/ppc/translate/misc-impl.c.inc | 10 ++++
6 files changed, 130 insertions(+), 9 deletions(-)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index c358927211..2532408be0 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1375,6 +1375,9 @@ struct CPUArchState {
/* Power management */
int (*check_pow)(CPUPPCState *env);
+ /* attn instruction enable */
+ int (*check_attn)(CPUPPCState *env);
+
#if !defined(CONFIG_USER_ONLY)
void *load_info; /* holds boot loading state */
#endif
@@ -1523,6 +1526,7 @@ struct PowerPCCPUClass {
int n_host_threads;
void (*init_proc)(CPUPPCState *env);
int (*check_pow)(CPUPPCState *env);
+ int (*check_attn)(CPUPPCState *env);
};
ObjectClass *ppc_cpu_class_by_name(const char *name);
@@ -2320,6 +2324,8 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define HID0_NAP (1 << 22) /* pre-2.06 */
#define HID0_HILE PPC_BIT(19) /* POWER8 */
#define HID0_POWER9_HILE PPC_BIT(4)
+#define HID0_ENABLE_ATTN PPC_BIT(31) /* POWER8 */
+#define HID0_POWER9_ENABLE_ATTN PPC_BIT(3)
/*****************************************************************************/
/* PowerPC Instructions types definitions */
@@ -3025,6 +3031,12 @@ static inline int check_pow_nocheck(CPUPPCState *env)
return 1;
}
+/* attn enable check */
+static inline int check_attn_none(CPUPPCState *env)
+{
+ return 0;
+}
+
/*****************************************************************************/
/* PowerPC implementations definitions */
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 55293e20a9..09d50f9b76 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -825,5 +825,6 @@ DEF_HELPER_FLAGS_1(fixup_thrm, TCG_CALL_NO_RWG, void, env)
#if defined(TARGET_PPC64)
DEF_HELPER_1(clrbhrb, void, env)
DEF_HELPER_FLAGS_2(mfbhrbe, TCG_CALL_NO_WG, i64, env, i32)
+DEF_HELPER_1(attn, noreturn, env)
#endif
#endif
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index d4dd022df4..ee33141476 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -1198,3 +1198,7 @@ EIEIO 011111 ----- ----- ----- 1101010110 -
MFBHRBE 011111 ..... ..... ..... 0100101110 - @XFX_bhrbe
CLRBHRB 011111 ----- ----- ----- 0110101110 -
+
+## Misc POWER instructions
+
+ATTN 000000 00000 00000 00000 0100000000 0
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 1ec84b5ddc..ee01415c32 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2107,6 +2107,26 @@ static int check_pow_hid0_74xx(CPUPPCState *env)
return 0;
}
+#if defined(TARGET_PPC64)
+static int check_attn_hid0(CPUPPCState *env)
+{
+ if (env->spr[SPR_HID0] & HID0_ENABLE_ATTN) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int check_attn_hid0_power9(CPUPPCState *env)
+{
+ if (env->spr[SPR_HID0] & HID0_POWER9_ENABLE_ATTN) {
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
static void init_proc_405(CPUPPCState *env)
{
register_40x_sprs(env);
@@ -2138,6 +2158,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 405";
pcc->init_proc = init_proc_405;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_DCR | PPC_WRTEE |
PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
@@ -2210,6 +2231,7 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440 EP";
pcc->init_proc = init_proc_440EP;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -2248,6 +2270,7 @@ POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 460 EX";
pcc->init_proc = init_proc_440EP;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -2308,6 +2331,7 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440 GP";
pcc->init_proc = init_proc_440GP;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI |
PPC_CACHE | PPC_CACHE_ICBI |
@@ -2382,6 +2406,7 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440x5";
pcc->init_proc = init_proc_440x5;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_DCR | PPC_WRTEE | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_ICBI |
@@ -2417,6 +2442,7 @@ POWERPC_FAMILY(440x5wDFPU)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440x5 with double precision FPU";
pcc->init_proc = init_proc_440x5;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_FLOAT | PPC_FLOAT_FSQRT |
PPC_FLOAT_STFIWX |
@@ -2465,6 +2491,7 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
dc->desc = "Freescale 5xx cores (aka RCPU)";
pcc->init_proc = init_proc_MPC5xx;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_MEM_EIEIO | PPC_MEM_SYNC |
PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX |
@@ -2507,6 +2534,7 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
dc->desc = "Freescale 8xx cores (aka PowerQUICC)";
pcc->init_proc = init_proc_MPC8xx;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_MEM_EIEIO | PPC_MEM_SYNC |
PPC_CACHE_ICBI | PPC_MFTB;
@@ -2557,6 +2585,7 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
dc->desc = "PowerPC G2";
pcc->init_proc = init_proc_G2;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_STFIWX |
@@ -2595,6 +2624,7 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
dc->desc = "PowerPC G2LE";
pcc->init_proc = init_proc_G2;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_STFIWX |
@@ -2741,6 +2771,7 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
dc->desc = "e200 core";
pcc->init_proc = init_proc_e200;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
/*
* XXX: unimplemented instructions:
* dcblc
@@ -3029,6 +3060,7 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data)
dc->desc = "e500v1 core";
pcc->init_proc = init_proc_e500v1;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
PPC_SPE | PPC_SPE_SINGLE |
PPC_WRTEE | PPC_RFDI |
@@ -3072,6 +3104,7 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data)
dc->desc = "e500v2 core";
pcc->init_proc = init_proc_e500v2;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE |
PPC_WRTEE | PPC_RFDI |
@@ -3115,6 +3148,7 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data)
dc->desc = "e500mc core";
pcc->init_proc = init_proc_e500mc;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
@@ -3161,6 +3195,7 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
dc->desc = "e5500 core";
pcc->init_proc = init_proc_e5500;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
@@ -3209,6 +3244,7 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void *data)
dc->desc = "e6500 core";
pcc->init_proc = init_proc_e6500;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
@@ -3271,6 +3307,7 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 603";
pcc->init_proc = init_proc_603;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3310,6 +3347,7 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 603e";
pcc->init_proc = init_proc_603;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3355,6 +3393,7 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
dc->desc = "e300 core";
pcc->init_proc = init_proc_e300;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_STFIWX |
@@ -3410,6 +3449,7 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 604";
pcc->init_proc = init_proc_604;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3455,6 +3495,7 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 604E";
pcc->init_proc = init_proc_604E;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3511,6 +3552,7 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 740";
pcc->init_proc = init_proc_740;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3576,6 +3618,7 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750";
pcc->init_proc = init_proc_750;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3722,6 +3765,7 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750 CL";
pcc->init_proc = init_proc_750cl;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
/*
* XXX: not implemented:
* cache lock instructions:
@@ -3829,6 +3873,7 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750CX";
pcc->init_proc = init_proc_750cx;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3901,6 +3946,7 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750FX";
pcc->init_proc = init_proc_750fx;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3973,6 +4019,7 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750GX";
pcc->init_proc = init_proc_750gx;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -4032,6 +4079,7 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 745";
pcc->init_proc = init_proc_745;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -4077,6 +4125,7 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 755";
pcc->init_proc = init_proc_755;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -4143,6 +4192,7 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7400 (aka G4)";
pcc->init_proc = init_proc_7400;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4222,6 +4272,7 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7410 (aka G4)";
pcc->init_proc = init_proc_7410;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4322,6 +4373,7 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7440 (aka G4)";
pcc->init_proc = init_proc_7440;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4444,6 +4496,7 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7450 (aka G4)";
pcc->init_proc = init_proc_7450;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4573,6 +4626,7 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7445 (aka G4)";
pcc->init_proc = init_proc_7445;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4704,6 +4758,7 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7455 (aka G4)";
pcc->init_proc = init_proc_7455;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4855,6 +4910,7 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7457 (aka G4)";
pcc->init_proc = init_proc_7457;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4989,6 +5045,7 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void *data)
dc->desc = "PowerPC e600";
pcc->init_proc = init_proc_e600;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -5904,6 +5961,7 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 970";
pcc->init_proc = init_proc_970;
pcc->check_pow = check_pow_970;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -5979,6 +6037,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
dc->desc = "POWER5+";
pcc->init_proc = init_proc_power5plus;
pcc->check_pow = check_pow_970;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6086,6 +6145,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6247,6 +6307,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER8;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6439,6 +6500,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER9;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0_power9;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6618,6 +6680,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER10;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0_power9;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6856,6 +6919,11 @@ static void init_ppc_proc(PowerPCCPU *cpu)
warn_report("no power management check handler registered."
" Attempt QEMU to crash very soon !");
}
+
+ if (env->check_attn == NULL) {
+ warn_report("no attn check handler registered."
+ " Attempt QEMU to crash very soon !");
+ }
}
@@ -7317,6 +7385,7 @@ static void ppc_cpu_instance_init(Object *obj)
env->flags = pcc->flags;
env->bfd_mach = pcc->bfd_mach;
env->check_pow = pcc->check_pow;
+ env->check_attn = pcc->check_attn;
/*
* Mark HV mode as supported if the CPU has an MSR_HV bit in the
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 17bf8df9d7..e786a9044b 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -154,6 +154,7 @@ static uint32_t ppc_ldl_code(CPUArchState *env, target_ulong addr)
return insn;
}
+
#endif
static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
@@ -425,21 +426,20 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
env->reserve_addr = -1;
}
-static void powerpc_mcheck_checkstop(CPUPPCState *env)
-{
- /* KVM guests always have MSR[ME] enabled */
#ifdef CONFIG_TCG
+/*
+ * This stops the machine and logs CPU state without killing QEMU (like
+ * cpu_abort()) because it is often a guest error as opposed to a QEMU error,
+ * so the machine can still be debugged.
+ */
+static G_NORETURN void powerpc_checkstop(CPUPPCState *env, const char *reason)
+{
CPUState *cs = env_cpu(env);
FILE *f;
- if (FIELD_EX64(env->msr, MSR, ME)) {
- return;
- }
-
f = qemu_log_trylock();
if (f) {
- fprintf(f, "Entering checkstop state: "
- "machine check with MSR[ME]=0\n");
+ fprintf(f, "Entering checkstop state: %s\n", reason);
cpu_dump_state(cs, f, CPU_DUMP_FPU | CPU_DUMP_CCOP);
qemu_log_unlock(f);
}
@@ -451,6 +451,31 @@ static void powerpc_mcheck_checkstop(CPUPPCState *env)
*/
qemu_system_guest_panicked(NULL);
cpu_loop_exit_noexc(cs);
+}
+
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+void helper_attn(CPUPPCState *env)
+{
+ /* POWER attn is unprivileged when enabled by HID, otherwise illegal */
+ if ((*env->check_attn)(env)) {
+ powerpc_checkstop(env, "host executed attn");
+ } else {
+ raise_exception_err(env, POWERPC_EXCP_HV_EMU,
+ POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
+ }
+}
+#endif
+#endif /* CONFIG_TCG */
+
+static void powerpc_mcheck_checkstop(CPUPPCState *env)
+{
+ /* KVM guests always have MSR[ME] enabled */
+#ifdef CONFIG_TCG
+ if (FIELD_EX64(env->msr, MSR, ME)) {
+ return;
+ }
+
+ powerpc_checkstop(env, "machine check with MSR[ME]=0");
#endif
}
diff --git a/target/ppc/translate/misc-impl.c.inc b/target/ppc/translate/misc-impl.c.inc
index c1661d2f43..cbf82b1ea0 100644
--- a/target/ppc/translate/misc-impl.c.inc
+++ b/target/ppc/translate/misc-impl.c.inc
@@ -145,3 +145,13 @@ static bool trans_EIEIO(DisasContext *ctx, arg_EIEIO *a)
return true;
}
+
+static bool trans_ATTN(DisasContext *ctx, arg_ATTN *a)
+{
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+ gen_helper_attn(tcg_env);
+ return true;
+#else
+ return false;
+#endif
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors
2024-05-21 1:30 ` [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors Nicholas Piggin
@ 2024-05-21 15:41 ` Miles Glenn
2024-05-22 1:30 ` Nicholas Piggin
2024-05-21 17:34 ` Richard Henderson
1 sibling, 1 reply; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 15:41 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Looks like this patch is failing to apply to the current master head?
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> attn is an implementation-specific instruction that on POWER (and G5/
> 970) can be enabled with a HID bit (disabled = illegal), and
> executing
> it causes the host processor to stop and the service processor to be
> notified. Generally used for debugging.
>
> Implement attn and make it checkstop the system, which should be good
> enough for QEMU debugging.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/cpu.h | 12 +++++
> target/ppc/helper.h | 1 +
> target/ppc/insn32.decode | 4 ++
> target/ppc/cpu_init.c | 69
> ++++++++++++++++++++++++++++
> target/ppc/excp_helper.c | 43 +++++++++++++----
> target/ppc/translate/misc-impl.c.inc | 10 ++++
> 6 files changed, 130 insertions(+), 9 deletions(-)
>
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index c358927211..2532408be0 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -1375,6 +1375,9 @@ struct CPUArchState {
> /* Power management */
> int (*check_pow)(CPUPPCState *env);
>
> + /* attn instruction enable */
> + int (*check_attn)(CPUPPCState *env);
> +
> #if !defined(CONFIG_USER_ONLY)
> void *load_info; /* holds boot loading state */
> #endif
> @@ -1523,6 +1526,7 @@ struct PowerPCCPUClass {
> int n_host_threads;
> void (*init_proc)(CPUPPCState *env);
> int (*check_pow)(CPUPPCState *env);
> + int (*check_attn)(CPUPPCState *env);
> };
>
> ObjectClass *ppc_cpu_class_by_name(const char *name);
> @@ -2320,6 +2324,8 @@ void ppc_compat_add_property(Object *obj, const
> char *name,
> #define HID0_NAP (1 << 22) /* pre-2.06 */
> #define HID0_HILE PPC_BIT(19) /* POWER8 */
> #define HID0_POWER9_HILE PPC_BIT(4)
> +#define HID0_ENABLE_ATTN PPC_BIT(31) /* POWER8 */
> +#define HID0_POWER9_ENABLE_ATTN PPC_BIT(3)
>
> /*******************************************************************
> **********/
> /* PowerPC Instructions types
> definitions */
> @@ -3025,6 +3031,12 @@ static inline int
> check_pow_nocheck(CPUPPCState *env)
> return 1;
> }
>
> +/* attn enable
> check */
> +static inline int check_attn_none(CPUPPCState *env)
> +{
> + return 0;
> +}
> +
> /*******************************************************************
> **********/
> /* PowerPC implementations
> definitions */
>
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index 55293e20a9..09d50f9b76 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -825,5 +825,6 @@ DEF_HELPER_FLAGS_1(fixup_thrm, TCG_CALL_NO_RWG,
> void, env)
> #if defined(TARGET_PPC64)
> DEF_HELPER_1(clrbhrb, void, env)
> DEF_HELPER_FLAGS_2(mfbhrbe, TCG_CALL_NO_WG, i64, env, i32)
> +DEF_HELPER_1(attn, noreturn, env)
> #endif
> #endif
> diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
> index d4dd022df4..ee33141476 100644
> --- a/target/ppc/insn32.decode
> +++ b/target/ppc/insn32.decode
> @@ -1198,3 +1198,7 @@ EIEIO 011111 ----- ----- -----
> 1101010110 -
>
> MFBHRBE 011111 ..... ..... ..... 0100101110 - @XFX_bhrbe
> CLRBHRB 011111 ----- ----- ----- 0110101110 -
> +
> +## Misc POWER instructions
> +
> +ATTN 000000 00000 00000 00000 0100000000 0
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 1ec84b5ddc..ee01415c32 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -2107,6 +2107,26 @@ static int check_pow_hid0_74xx(CPUPPCState
> *env)
> return 0;
> }
>
> +#if defined(TARGET_PPC64)
> +static int check_attn_hid0(CPUPPCState *env)
> +{
> + if (env->spr[SPR_HID0] & HID0_ENABLE_ATTN) {
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> +static int check_attn_hid0_power9(CPUPPCState *env)
> +{
> + if (env->spr[SPR_HID0] & HID0_POWER9_ENABLE_ATTN) {
> + return 1;
> + }
> +
> + return 0;
> +}
> +#endif
> +
> static void init_proc_405(CPUPPCState *env)
> {
> register_40x_sprs(env);
> @@ -2138,6 +2158,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 405";
> pcc->init_proc = init_proc_405;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_DCR | PPC_WRTEE |
> PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
> @@ -2210,6 +2231,7 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 440 EP";
> pcc->init_proc = init_proc_440EP;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -2248,6 +2270,7 @@ POWERPC_FAMILY(460EX)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 460 EX";
> pcc->init_proc = init_proc_440EP;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -2308,6 +2331,7 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 440 GP";
> pcc->init_proc = init_proc_440GP;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI
> |
> PPC_CACHE | PPC_CACHE_ICBI |
> @@ -2382,6 +2406,7 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 440x5";
> pcc->init_proc = init_proc_440x5;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> PPC_DCR | PPC_WRTEE | PPC_RFMCI |
> PPC_CACHE | PPC_CACHE_ICBI |
> @@ -2417,6 +2442,7 @@ POWERPC_FAMILY(440x5wDFPU)(ObjectClass *oc,
> void *data)
> dc->desc = "PowerPC 440x5 with double precision FPU";
> pcc->init_proc = init_proc_440x5;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> PPC_FLOAT | PPC_FLOAT_FSQRT |
> PPC_FLOAT_STFIWX |
> @@ -2465,6 +2491,7 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void
> *data)
> dc->desc = "Freescale 5xx cores (aka RCPU)";
> pcc->init_proc = init_proc_MPC5xx;
> pcc->check_pow = check_pow_none;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> PPC_MEM_EIEIO | PPC_MEM_SYNC |
> PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX
> |
> @@ -2507,6 +2534,7 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void
> *data)
> dc->desc = "Freescale 8xx cores (aka PowerQUICC)";
> pcc->init_proc = init_proc_MPC8xx;
> pcc->check_pow = check_pow_none;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> PPC_MEM_EIEIO | PPC_MEM_SYNC |
> PPC_CACHE_ICBI | PPC_MFTB;
> @@ -2557,6 +2585,7 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
> dc->desc = "PowerPC G2";
> pcc->init_proc = init_proc_G2;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_STFIWX |
> @@ -2595,6 +2624,7 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC G2LE";
> pcc->init_proc = init_proc_G2;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_STFIWX |
> @@ -2741,6 +2771,7 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void
> *data)
> dc->desc = "e200 core";
> pcc->init_proc = init_proc_e200;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> /*
> * XXX: unimplemented instructions:
> * dcblc
> @@ -3029,6 +3060,7 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void
> *data)
> dc->desc = "e500v1 core";
> pcc->init_proc = init_proc_e500v1;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
> PPC_SPE | PPC_SPE_SINGLE |
> PPC_WRTEE | PPC_RFDI |
> @@ -3072,6 +3104,7 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void
> *data)
> dc->desc = "e500v2 core";
> pcc->init_proc = init_proc_e500v2;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
> PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE |
> PPC_WRTEE | PPC_RFDI |
> @@ -3115,6 +3148,7 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void
> *data)
> dc->desc = "e500mc core";
> pcc->init_proc = init_proc_e500mc;
> pcc->check_pow = check_pow_none;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
> PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
> PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
> @@ -3161,6 +3195,7 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void
> *data)
> dc->desc = "e5500 core";
> pcc->init_proc = init_proc_e5500;
> pcc->check_pow = check_pow_none;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
> PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
> PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
> @@ -3209,6 +3244,7 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void
> *data)
> dc->desc = "e6500 core";
> pcc->init_proc = init_proc_e6500;
> pcc->check_pow = check_pow_none;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
> PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
> PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
> @@ -3271,6 +3307,7 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 603";
> pcc->init_proc = init_proc_603;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3310,6 +3347,7 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 603e";
> pcc->init_proc = init_proc_603;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3355,6 +3393,7 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void
> *data)
> dc->desc = "e300 core";
> pcc->init_proc = init_proc_e300;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_STFIWX |
> @@ -3410,6 +3449,7 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 604";
> pcc->init_proc = init_proc_604;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3455,6 +3495,7 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 604E";
> pcc->init_proc = init_proc_604E;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3511,6 +3552,7 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 740";
> pcc->init_proc = init_proc_740;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3576,6 +3618,7 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 750";
> pcc->init_proc = init_proc_750;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3722,6 +3765,7 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 750 CL";
> pcc->init_proc = init_proc_750cl;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> /*
> * XXX: not implemented:
> * cache lock instructions:
> @@ -3829,6 +3873,7 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 750CX";
> pcc->init_proc = init_proc_750cx;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3901,6 +3946,7 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 750FX";
> pcc->init_proc = init_proc_750fx;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -3973,6 +4019,7 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 750GX";
> pcc->init_proc = init_proc_750gx;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -4032,6 +4079,7 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 745";
> pcc->init_proc = init_proc_745;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -4077,6 +4125,7 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 755";
> pcc->init_proc = init_proc_755;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> @@ -4143,6 +4192,7 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 7400 (aka G4)";
> pcc->init_proc = init_proc_7400;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -4222,6 +4272,7 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 7410 (aka G4)";
> pcc->init_proc = init_proc_7410;
> pcc->check_pow = check_pow_hid0;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -4322,6 +4373,7 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 7440 (aka G4)";
> pcc->init_proc = init_proc_7440;
> pcc->check_pow = check_pow_hid0_74xx;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -4444,6 +4496,7 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 7450 (aka G4)";
> pcc->init_proc = init_proc_7450;
> pcc->check_pow = check_pow_hid0_74xx;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -4573,6 +4626,7 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 7445 (aka G4)";
> pcc->init_proc = init_proc_7445;
> pcc->check_pow = check_pow_hid0_74xx;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -4704,6 +4758,7 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 7455 (aka G4)";
> pcc->init_proc = init_proc_7455;
> pcc->check_pow = check_pow_hid0_74xx;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -4855,6 +4910,7 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 7457 (aka G4)";
> pcc->init_proc = init_proc_7457;
> pcc->check_pow = check_pow_hid0_74xx;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -4989,6 +5045,7 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC e600";
> pcc->init_proc = init_proc_e600;
> pcc->check_pow = check_pow_hid0_74xx;
> + pcc->check_attn = check_attn_none;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -5904,6 +5961,7 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void
> *data)
> dc->desc = "PowerPC 970";
> pcc->init_proc = init_proc_970;
> pcc->check_pow = check_pow_970;
> + pcc->check_attn = check_attn_hid0;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -5979,6 +6037,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void
> *data)
> dc->desc = "POWER5+";
> pcc->init_proc = init_proc_power5plus;
> pcc->check_pow = check_pow_970;
> + pcc->check_attn = check_attn_hid0;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -6086,6 +6145,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void
> *data)
> pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
> pcc->init_proc = init_proc_POWER7;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_hid0;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -6247,6 +6307,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void
> *data)
> pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 |
> PCR_COMPAT_2_05;
> pcc->init_proc = init_proc_POWER8;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_hid0;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -6439,6 +6500,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void
> *data)
> PCR_COMPAT_2_05;
> pcc->init_proc = init_proc_POWER9;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_hid0_power9;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -6618,6 +6680,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void
> *data)
> PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
> pcc->init_proc = init_proc_POWER10;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_hid0_power9;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> PPC_MFTB |
> PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> @@ -6856,6 +6919,11 @@ static void init_ppc_proc(PowerPCCPU *cpu)
> warn_report("no power management check handler registered."
> " Attempt QEMU to crash very soon !");
> }
> +
> + if (env->check_attn == NULL) {
> + warn_report("no attn check handler registered."
> + " Attempt QEMU to crash very soon !");
> + }
> }
>
>
> @@ -7317,6 +7385,7 @@ static void ppc_cpu_instance_init(Object *obj)
> env->flags = pcc->flags;
> env->bfd_mach = pcc->bfd_mach;
> env->check_pow = pcc->check_pow;
> + env->check_attn = pcc->check_attn;
>
> /*
> * Mark HV mode as supported if the CPU has an MSR_HV bit in the
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 17bf8df9d7..e786a9044b 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -154,6 +154,7 @@ static uint32_t ppc_ldl_code(CPUArchState *env,
> target_ulong addr)
>
> return insn;
> }
> +
> #endif
>
> static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
> @@ -425,21 +426,20 @@ static void powerpc_set_excp_state(PowerPCCPU
> *cpu, target_ulong vector,
> env->reserve_addr = -1;
> }
>
> -static void powerpc_mcheck_checkstop(CPUPPCState *env)
> -{
> - /* KVM guests always have MSR[ME] enabled */
> #ifdef CONFIG_TCG
> +/*
> + * This stops the machine and logs CPU state without killing QEMU
> (like
> + * cpu_abort()) because it is often a guest error as opposed to a
> QEMU error,
> + * so the machine can still be debugged.
> + */
> +static G_NORETURN void powerpc_checkstop(CPUPPCState *env, const
> char *reason)
> +{
> CPUState *cs = env_cpu(env);
> FILE *f;
>
> - if (FIELD_EX64(env->msr, MSR, ME)) {
> - return;
> - }
> -
> f = qemu_log_trylock();
> if (f) {
> - fprintf(f, "Entering checkstop state: "
> - "machine check with MSR[ME]=0\n");
> + fprintf(f, "Entering checkstop state: %s\n", reason);
> cpu_dump_state(cs, f, CPU_DUMP_FPU | CPU_DUMP_CCOP);
> qemu_log_unlock(f);
> }
> @@ -451,6 +451,31 @@ static void powerpc_mcheck_checkstop(CPUPPCState
> *env)
> */
> qemu_system_guest_panicked(NULL);
> cpu_loop_exit_noexc(cs);
> +}
> +
> +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> +void helper_attn(CPUPPCState *env)
> +{
> + /* POWER attn is unprivileged when enabled by HID, otherwise
> illegal */
> + if ((*env->check_attn)(env)) {
> + powerpc_checkstop(env, "host executed attn");
> + } else {
> + raise_exception_err(env, POWERPC_EXCP_HV_EMU,
> + POWERPC_EXCP_INVAL |
> POWERPC_EXCP_INVAL_INVAL);
> + }
> +}
> +#endif
> +#endif /* CONFIG_TCG */
> +
> +static void powerpc_mcheck_checkstop(CPUPPCState *env)
> +{
> + /* KVM guests always have MSR[ME] enabled */
> +#ifdef CONFIG_TCG
> + if (FIELD_EX64(env->msr, MSR, ME)) {
> + return;
> + }
> +
> + powerpc_checkstop(env, "machine check with MSR[ME]=0");
> #endif
> }
>
> diff --git a/target/ppc/translate/misc-impl.c.inc
> b/target/ppc/translate/misc-impl.c.inc
> index c1661d2f43..cbf82b1ea0 100644
> --- a/target/ppc/translate/misc-impl.c.inc
> +++ b/target/ppc/translate/misc-impl.c.inc
> @@ -145,3 +145,13 @@ static bool trans_EIEIO(DisasContext *ctx,
> arg_EIEIO *a)
>
> return true;
> }
> +
> +static bool trans_ATTN(DisasContext *ctx, arg_ATTN *a)
> +{
> +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> + gen_helper_attn(tcg_env);
> + return true;
> +#else
> + return false;
> +#endif
> +}
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors
2024-05-21 15:41 ` Miles Glenn
@ 2024-05-22 1:30 ` Nicholas Piggin
0 siblings, 0 replies; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-22 1:30 UTC (permalink / raw)
To: milesg, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Ah sorry, it's on top of some of Chinmay's decodetree series which is
causing a couple of minor rejects.
Thanks,
Nick
On Wed May 22, 2024 at 1:41 AM AEST, Miles Glenn wrote:
> Looks like this patch is failing to apply to the current master head?
>
> Thanks,
>
> Glenn
>
> On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> > attn is an implementation-specific instruction that on POWER (and G5/
> > 970) can be enabled with a HID bit (disabled = illegal), and
> > executing
> > it causes the host processor to stop and the service processor to be
> > notified. Generally used for debugging.
> >
> > Implement attn and make it checkstop the system, which should be good
> > enough for QEMU debugging.
> >
> > Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> > ---
> > target/ppc/cpu.h | 12 +++++
> > target/ppc/helper.h | 1 +
> > target/ppc/insn32.decode | 4 ++
> > target/ppc/cpu_init.c | 69
> > ++++++++++++++++++++++++++++
> > target/ppc/excp_helper.c | 43 +++++++++++++----
> > target/ppc/translate/misc-impl.c.inc | 10 ++++
> > 6 files changed, 130 insertions(+), 9 deletions(-)
> >
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index c358927211..2532408be0 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -1375,6 +1375,9 @@ struct CPUArchState {
> > /* Power management */
> > int (*check_pow)(CPUPPCState *env);
> >
> > + /* attn instruction enable */
> > + int (*check_attn)(CPUPPCState *env);
> > +
> > #if !defined(CONFIG_USER_ONLY)
> > void *load_info; /* holds boot loading state */
> > #endif
> > @@ -1523,6 +1526,7 @@ struct PowerPCCPUClass {
> > int n_host_threads;
> > void (*init_proc)(CPUPPCState *env);
> > int (*check_pow)(CPUPPCState *env);
> > + int (*check_attn)(CPUPPCState *env);
> > };
> >
> > ObjectClass *ppc_cpu_class_by_name(const char *name);
> > @@ -2320,6 +2324,8 @@ void ppc_compat_add_property(Object *obj, const
> > char *name,
> > #define HID0_NAP (1 << 22) /* pre-2.06 */
> > #define HID0_HILE PPC_BIT(19) /* POWER8 */
> > #define HID0_POWER9_HILE PPC_BIT(4)
> > +#define HID0_ENABLE_ATTN PPC_BIT(31) /* POWER8 */
> > +#define HID0_POWER9_ENABLE_ATTN PPC_BIT(3)
> >
> > /*******************************************************************
> > **********/
> > /* PowerPC Instructions types
> > definitions */
> > @@ -3025,6 +3031,12 @@ static inline int
> > check_pow_nocheck(CPUPPCState *env)
> > return 1;
> > }
> >
> > +/* attn enable
> > check */
> > +static inline int check_attn_none(CPUPPCState *env)
> > +{
> > + return 0;
> > +}
> > +
> > /*******************************************************************
> > **********/
> > /* PowerPC implementations
> > definitions */
> >
> > diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> > index 55293e20a9..09d50f9b76 100644
> > --- a/target/ppc/helper.h
> > +++ b/target/ppc/helper.h
> > @@ -825,5 +825,6 @@ DEF_HELPER_FLAGS_1(fixup_thrm, TCG_CALL_NO_RWG,
> > void, env)
> > #if defined(TARGET_PPC64)
> > DEF_HELPER_1(clrbhrb, void, env)
> > DEF_HELPER_FLAGS_2(mfbhrbe, TCG_CALL_NO_WG, i64, env, i32)
> > +DEF_HELPER_1(attn, noreturn, env)
> > #endif
> > #endif
> > diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
> > index d4dd022df4..ee33141476 100644
> > --- a/target/ppc/insn32.decode
> > +++ b/target/ppc/insn32.decode
> > @@ -1198,3 +1198,7 @@ EIEIO 011111 ----- ----- -----
> > 1101010110 -
> >
> > MFBHRBE 011111 ..... ..... ..... 0100101110 - @XFX_bhrbe
> > CLRBHRB 011111 ----- ----- ----- 0110101110 -
> > +
> > +## Misc POWER instructions
> > +
> > +ATTN 000000 00000 00000 00000 0100000000 0
> > diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> > index 1ec84b5ddc..ee01415c32 100644
> > --- a/target/ppc/cpu_init.c
> > +++ b/target/ppc/cpu_init.c
> > @@ -2107,6 +2107,26 @@ static int check_pow_hid0_74xx(CPUPPCState
> > *env)
> > return 0;
> > }
> >
> > +#if defined(TARGET_PPC64)
> > +static int check_attn_hid0(CPUPPCState *env)
> > +{
> > + if (env->spr[SPR_HID0] & HID0_ENABLE_ATTN) {
> > + return 1;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int check_attn_hid0_power9(CPUPPCState *env)
> > +{
> > + if (env->spr[SPR_HID0] & HID0_POWER9_ENABLE_ATTN) {
> > + return 1;
> > + }
> > +
> > + return 0;
> > +}
> > +#endif
> > +
> > static void init_proc_405(CPUPPCState *env)
> > {
> > register_40x_sprs(env);
> > @@ -2138,6 +2158,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 405";
> > pcc->init_proc = init_proc_405;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_DCR | PPC_WRTEE |
> > PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
> > @@ -2210,6 +2231,7 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 440 EP";
> > pcc->init_proc = init_proc_440EP;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> > PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -2248,6 +2270,7 @@ POWERPC_FAMILY(460EX)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 460 EX";
> > pcc->init_proc = init_proc_440EP;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> > PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -2308,6 +2331,7 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 440 GP";
> > pcc->init_proc = init_proc_440GP;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> > PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI
> > |
> > PPC_CACHE | PPC_CACHE_ICBI |
> > @@ -2382,6 +2406,7 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 440x5";
> > pcc->init_proc = init_proc_440x5;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> > PPC_DCR | PPC_WRTEE | PPC_RFMCI |
> > PPC_CACHE | PPC_CACHE_ICBI |
> > @@ -2417,6 +2442,7 @@ POWERPC_FAMILY(440x5wDFPU)(ObjectClass *oc,
> > void *data)
> > dc->desc = "PowerPC 440x5 with double precision FPU";
> > pcc->init_proc = init_proc_440x5;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> > PPC_FLOAT | PPC_FLOAT_FSQRT |
> > PPC_FLOAT_STFIWX |
> > @@ -2465,6 +2491,7 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void
> > *data)
> > dc->desc = "Freescale 5xx cores (aka RCPU)";
> > pcc->init_proc = init_proc_MPC5xx;
> > pcc->check_pow = check_pow_none;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> > PPC_MEM_EIEIO | PPC_MEM_SYNC |
> > PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX
> > |
> > @@ -2507,6 +2534,7 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void
> > *data)
> > dc->desc = "Freescale 8xx cores (aka PowerQUICC)";
> > pcc->init_proc = init_proc_MPC8xx;
> > pcc->check_pow = check_pow_none;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
> > PPC_MEM_EIEIO | PPC_MEM_SYNC |
> > PPC_CACHE_ICBI | PPC_MFTB;
> > @@ -2557,6 +2585,7 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
> > dc->desc = "PowerPC G2";
> > pcc->init_proc = init_proc_G2;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_STFIWX |
> > @@ -2595,6 +2624,7 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC G2LE";
> > pcc->init_proc = init_proc_G2;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_STFIWX |
> > @@ -2741,6 +2771,7 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void
> > *data)
> > dc->desc = "e200 core";
> > pcc->init_proc = init_proc_e200;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > /*
> > * XXX: unimplemented instructions:
> > * dcblc
> > @@ -3029,6 +3060,7 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void
> > *data)
> > dc->desc = "e500v1 core";
> > pcc->init_proc = init_proc_e500v1;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
> > PPC_SPE | PPC_SPE_SINGLE |
> > PPC_WRTEE | PPC_RFDI |
> > @@ -3072,6 +3104,7 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void
> > *data)
> > dc->desc = "e500v2 core";
> > pcc->init_proc = init_proc_e500v2;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
> > PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE |
> > PPC_WRTEE | PPC_RFDI |
> > @@ -3115,6 +3148,7 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void
> > *data)
> > dc->desc = "e500mc core";
> > pcc->init_proc = init_proc_e500mc;
> > pcc->check_pow = check_pow_none;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
> > PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
> > PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
> > @@ -3161,6 +3195,7 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void
> > *data)
> > dc->desc = "e5500 core";
> > pcc->init_proc = init_proc_e5500;
> > pcc->check_pow = check_pow_none;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
> > PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
> > PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
> > @@ -3209,6 +3244,7 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void
> > *data)
> > dc->desc = "e6500 core";
> > pcc->init_proc = init_proc_e6500;
> > pcc->check_pow = check_pow_none;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
> > PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
> > PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
> > @@ -3271,6 +3307,7 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 603";
> > pcc->init_proc = init_proc_603;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3310,6 +3347,7 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 603e";
> > pcc->init_proc = init_proc_603;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3355,6 +3393,7 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void
> > *data)
> > dc->desc = "e300 core";
> > pcc->init_proc = init_proc_e300;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_STFIWX |
> > @@ -3410,6 +3449,7 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 604";
> > pcc->init_proc = init_proc_604;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3455,6 +3495,7 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 604E";
> > pcc->init_proc = init_proc_604E;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3511,6 +3552,7 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 740";
> > pcc->init_proc = init_proc_740;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3576,6 +3618,7 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 750";
> > pcc->init_proc = init_proc_750;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3722,6 +3765,7 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 750 CL";
> > pcc->init_proc = init_proc_750cl;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > /*
> > * XXX: not implemented:
> > * cache lock instructions:
> > @@ -3829,6 +3873,7 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 750CX";
> > pcc->init_proc = init_proc_750cx;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3901,6 +3946,7 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 750FX";
> > pcc->init_proc = init_proc_750fx;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -3973,6 +4019,7 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 750GX";
> > pcc->init_proc = init_proc_750gx;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -4032,6 +4079,7 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 745";
> > pcc->init_proc = init_proc_745;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -4077,6 +4125,7 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 755";
> > pcc->init_proc = init_proc_755;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
> > @@ -4143,6 +4192,7 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 7400 (aka G4)";
> > pcc->init_proc = init_proc_7400;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -4222,6 +4272,7 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 7410 (aka G4)";
> > pcc->init_proc = init_proc_7410;
> > pcc->check_pow = check_pow_hid0;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -4322,6 +4373,7 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 7440 (aka G4)";
> > pcc->init_proc = init_proc_7440;
> > pcc->check_pow = check_pow_hid0_74xx;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -4444,6 +4496,7 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 7450 (aka G4)";
> > pcc->init_proc = init_proc_7450;
> > pcc->check_pow = check_pow_hid0_74xx;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -4573,6 +4626,7 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 7445 (aka G4)";
> > pcc->init_proc = init_proc_7445;
> > pcc->check_pow = check_pow_hid0_74xx;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -4704,6 +4758,7 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 7455 (aka G4)";
> > pcc->init_proc = init_proc_7455;
> > pcc->check_pow = check_pow_hid0_74xx;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -4855,6 +4910,7 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 7457 (aka G4)";
> > pcc->init_proc = init_proc_7457;
> > pcc->check_pow = check_pow_hid0_74xx;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -4989,6 +5045,7 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC e600";
> > pcc->init_proc = init_proc_e600;
> > pcc->check_pow = check_pow_hid0_74xx;
> > + pcc->check_attn = check_attn_none;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -5904,6 +5961,7 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void
> > *data)
> > dc->desc = "PowerPC 970";
> > pcc->init_proc = init_proc_970;
> > pcc->check_pow = check_pow_970;
> > + pcc->check_attn = check_attn_hid0;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -5979,6 +6037,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void
> > *data)
> > dc->desc = "POWER5+";
> > pcc->init_proc = init_proc_power5plus;
> > pcc->check_pow = check_pow_970;
> > + pcc->check_attn = check_attn_hid0;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -6086,6 +6145,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void
> > *data)
> > pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
> > pcc->init_proc = init_proc_POWER7;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_hid0;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> > PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -6247,6 +6307,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void
> > *data)
> > pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 |
> > PCR_COMPAT_2_05;
> > pcc->init_proc = init_proc_POWER8;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_hid0;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> > PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -6439,6 +6500,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void
> > *data)
> > PCR_COMPAT_2_05;
> > pcc->init_proc = init_proc_POWER9;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_hid0_power9;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> > PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -6618,6 +6680,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void
> > *data)
> > PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
> > pcc->init_proc = init_proc_POWER10;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_hid0_power9;
> > pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING |
> > PPC_MFTB |
> > PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
> > PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
> > @@ -6856,6 +6919,11 @@ static void init_ppc_proc(PowerPCCPU *cpu)
> > warn_report("no power management check handler registered."
> > " Attempt QEMU to crash very soon !");
> > }
> > +
> > + if (env->check_attn == NULL) {
> > + warn_report("no attn check handler registered."
> > + " Attempt QEMU to crash very soon !");
> > + }
> > }
> >
> >
> > @@ -7317,6 +7385,7 @@ static void ppc_cpu_instance_init(Object *obj)
> > env->flags = pcc->flags;
> > env->bfd_mach = pcc->bfd_mach;
> > env->check_pow = pcc->check_pow;
> > + env->check_attn = pcc->check_attn;
> >
> > /*
> > * Mark HV mode as supported if the CPU has an MSR_HV bit in the
> > diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> > index 17bf8df9d7..e786a9044b 100644
> > --- a/target/ppc/excp_helper.c
> > +++ b/target/ppc/excp_helper.c
> > @@ -154,6 +154,7 @@ static uint32_t ppc_ldl_code(CPUArchState *env,
> > target_ulong addr)
> >
> > return insn;
> > }
> > +
> > #endif
> >
> > static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
> > @@ -425,21 +426,20 @@ static void powerpc_set_excp_state(PowerPCCPU
> > *cpu, target_ulong vector,
> > env->reserve_addr = -1;
> > }
> >
> > -static void powerpc_mcheck_checkstop(CPUPPCState *env)
> > -{
> > - /* KVM guests always have MSR[ME] enabled */
> > #ifdef CONFIG_TCG
> > +/*
> > + * This stops the machine and logs CPU state without killing QEMU
> > (like
> > + * cpu_abort()) because it is often a guest error as opposed to a
> > QEMU error,
> > + * so the machine can still be debugged.
> > + */
> > +static G_NORETURN void powerpc_checkstop(CPUPPCState *env, const
> > char *reason)
> > +{
> > CPUState *cs = env_cpu(env);
> > FILE *f;
> >
> > - if (FIELD_EX64(env->msr, MSR, ME)) {
> > - return;
> > - }
> > -
> > f = qemu_log_trylock();
> > if (f) {
> > - fprintf(f, "Entering checkstop state: "
> > - "machine check with MSR[ME]=0\n");
> > + fprintf(f, "Entering checkstop state: %s\n", reason);
> > cpu_dump_state(cs, f, CPU_DUMP_FPU | CPU_DUMP_CCOP);
> > qemu_log_unlock(f);
> > }
> > @@ -451,6 +451,31 @@ static void powerpc_mcheck_checkstop(CPUPPCState
> > *env)
> > */
> > qemu_system_guest_panicked(NULL);
> > cpu_loop_exit_noexc(cs);
> > +}
> > +
> > +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> > +void helper_attn(CPUPPCState *env)
> > +{
> > + /* POWER attn is unprivileged when enabled by HID, otherwise
> > illegal */
> > + if ((*env->check_attn)(env)) {
> > + powerpc_checkstop(env, "host executed attn");
> > + } else {
> > + raise_exception_err(env, POWERPC_EXCP_HV_EMU,
> > + POWERPC_EXCP_INVAL |
> > POWERPC_EXCP_INVAL_INVAL);
> > + }
> > +}
> > +#endif
> > +#endif /* CONFIG_TCG */
> > +
> > +static void powerpc_mcheck_checkstop(CPUPPCState *env)
> > +{
> > + /* KVM guests always have MSR[ME] enabled */
> > +#ifdef CONFIG_TCG
> > + if (FIELD_EX64(env->msr, MSR, ME)) {
> > + return;
> > + }
> > +
> > + powerpc_checkstop(env, "machine check with MSR[ME]=0");
> > #endif
> > }
> >
> > diff --git a/target/ppc/translate/misc-impl.c.inc
> > b/target/ppc/translate/misc-impl.c.inc
> > index c1661d2f43..cbf82b1ea0 100644
> > --- a/target/ppc/translate/misc-impl.c.inc
> > +++ b/target/ppc/translate/misc-impl.c.inc
> > @@ -145,3 +145,13 @@ static bool trans_EIEIO(DisasContext *ctx,
> > arg_EIEIO *a)
> >
> > return true;
> > }
> > +
> > +static bool trans_ATTN(DisasContext *ctx, arg_ATTN *a)
> > +{
> > +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> > + gen_helper_attn(tcg_env);
> > + return true;
> > +#else
> > + return false;
> > +#endif
> > +}
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors
2024-05-21 1:30 ` [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors Nicholas Piggin
2024-05-21 15:41 ` Miles Glenn
@ 2024-05-21 17:34 ` Richard Henderson
2024-05-22 1:32 ` Nicholas Piggin
1 sibling, 1 reply; 31+ messages in thread
From: Richard Henderson @ 2024-05-21 17:34 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles, Chinmay Rath
On 5/20/24 18:30, Nicholas Piggin wrote:
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index c358927211..2532408be0 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -3025,6 +3031,12 @@ static inline int check_pow_nocheck(CPUPPCState *env)
> return 1;
> }
>
> +/* attn enable check */
> +static inline int check_attn_none(CPUPPCState *env)
> +{
> + return 0;
> +}
No point in putting this here, as a static inline...
> @@ -2138,6 +2158,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
> dc->desc = "PowerPC 405";
> pcc->init_proc = init_proc_405;
> pcc->check_pow = check_pow_nocheck;
> + pcc->check_attn = check_attn_none;
... when the only uses force an out-of-line instance.
Alternately,
> +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> +void helper_attn(CPUPPCState *env)
> +{
> + /* POWER attn is unprivileged when enabled by HID, otherwise illegal */
> + if ((*env->check_attn)(env)) {
> + powerpc_checkstop(env, "host executed attn");
... allow the hook to be null to indicate no attn.
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors
2024-05-21 17:34 ` Richard Henderson
@ 2024-05-22 1:32 ` Nicholas Piggin
0 siblings, 0 replies; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-22 1:32 UTC (permalink / raw)
To: Richard Henderson, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles, Chinmay Rath
On Wed May 22, 2024 at 3:34 AM AEST, Richard Henderson wrote:
> On 5/20/24 18:30, Nicholas Piggin wrote:
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index c358927211..2532408be0 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -3025,6 +3031,12 @@ static inline int check_pow_nocheck(CPUPPCState *env)
> > return 1;
> > }
> >
> > +/* attn enable check */
> > +static inline int check_attn_none(CPUPPCState *env)
> > +{
> > + return 0;
> > +}
>
> No point in putting this here, as a static inline...
>
> > @@ -2138,6 +2158,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
> > dc->desc = "PowerPC 405";
> > pcc->init_proc = init_proc_405;
> > pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
>
> ... when the only uses force an out-of-line instance.
Yeah... I was following existing convention (although apparently not
naming convention :/).
>
> Alternately,
>
> > +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> > +void helper_attn(CPUPPCState *env)
> > +{
> > + /* POWER attn is unprivileged when enabled by HID, otherwise illegal */
> > + if ((*env->check_attn)(env)) {
> > + powerpc_checkstop(env, "host executed attn");
>
> ... allow the hook to be null to indicate no attn.
I'll add a todo list to change this and check_pow to follow this
suggestion.
>
> Otherwise,
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Thanks,
Nick
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 04/12] target/ppc: BookE DECAR SPR is 32-bit
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (2 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 03/12] target/ppc: Implement attn instruction on BookS 64-bit processors Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 15:44 ` Miles Glenn
2024-05-21 1:30 ` [PATCH v2 05/12] target/ppc: Wire up BookE ATB registers for e500 family Nicholas Piggin
` (7 subsequent siblings)
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
The DECAR SPR is 32-bits width.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu_init.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index ee01415c32..927721d49a 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -792,7 +792,7 @@ static void register_BookE_sprs(CPUPPCState *env, uint64_t ivor_mask)
0x00000000);
spr_register(env, SPR_BOOKE_DECAR, "DECAR",
SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, &spr_write_generic,
+ SPR_NOACCESS, &spr_write_generic32,
0x00000000);
/* SPRGs */
spr_register(env, SPR_USPRG0, "USPRG0",
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 04/12] target/ppc: BookE DECAR SPR is 32-bit
2024-05-21 1:30 ` [PATCH v2 04/12] target/ppc: BookE DECAR SPR is 32-bit Nicholas Piggin
@ 2024-05-21 15:44 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 15:44 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> The DECAR SPR is 32-bits width.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/cpu_init.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index ee01415c32..927721d49a 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -792,7 +792,7 @@ static void register_BookE_sprs(CPUPPCState *env,
> uint64_t ivor_mask)
> 0x00000000);
> spr_register(env, SPR_BOOKE_DECAR, "DECAR",
> SPR_NOACCESS, SPR_NOACCESS,
> - SPR_NOACCESS, &spr_write_generic,
> + SPR_NOACCESS, &spr_write_generic32,
> 0x00000000);
> /* SPRGs */
> spr_register(env, SPR_USPRG0, "USPRG0",
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 05/12] target/ppc: Wire up BookE ATB registers for e500 family
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (3 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 04/12] target/ppc: BookE DECAR SPR is 32-bit Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 1:30 ` [PATCH v2 06/12] target/ppc: Add PPR32 SPR Nicholas Piggin
` (6 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
From the Freescale PowerPC Architecture Primer:
Alternate time base APU. This APU, implemented on the e500v2, defines
a 64-bit time base counter that differs from the PowerPC defined time
base in that it is not writable and counts at a different, and
typically much higher, frequency. The alternate time base always
counts up, wrapping when the 64-bit count overflows.
This implementation of ATB uses the same frequency as the TB. The
existing spr_read_atbu/l functions are unused without this patch
to wire them into the SPR.
RTEMS uses this SPR on the e6500, though this hasn't been tested.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu_init.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 927721d49a..892fb6ce02 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -920,6 +920,18 @@ static void register_BookE206_sprs(CPUPPCState *env, uint32_t mas_mask,
#endif
}
+static void register_atb_sprs(CPUPPCState *env)
+{
+ spr_register(env, SPR_ATBL, "ATBL",
+ &spr_read_atbl, SPR_NOACCESS,
+ &spr_read_atbl, SPR_NOACCESS,
+ 0x00000000);
+ spr_register(env, SPR_ATBU, "ATBU",
+ &spr_read_atbu, SPR_NOACCESS,
+ &spr_read_atbu, SPR_NOACCESS,
+ 0x00000000);
+}
+
/* SPR specific to PowerPC 440 implementation */
static void register_440_sprs(CPUPPCState *env)
{
@@ -2927,6 +2939,11 @@ static void init_proc_e500(CPUPPCState *env, int version)
register_BookE206_sprs(env, 0x000000DF, tlbncfg, mmucfg);
register_usprgh_sprs(env);
+ if (version != fsl_e500v1) {
+ /* e500v1 has no support for alternate timebase */
+ register_atb_sprs(env);
+ }
+
spr_register(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v2 06/12] target/ppc: Add PPR32 SPR
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (4 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 05/12] target/ppc: Wire up BookE ATB registers for e500 family Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 15:52 ` Miles Glenn
2024-05-21 17:40 ` Richard Henderson
2024-05-21 1:30 ` [PATCH v2 07/12] target/ppc: add helper to write per-LPAR SPRs Nicholas Piggin
` (5 subsequent siblings)
11 siblings, 2 replies; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
PPR32 provides access to the upper half of PPR.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu.h | 1 +
target/ppc/spr_common.h | 2 ++
target/ppc/cpu_init.c | 12 ++++++++++++
target/ppc/translate.c | 16 ++++++++++++++++
4 files changed, 31 insertions(+)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 2532408be0..141cbefb4c 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2120,6 +2120,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_POWER_MMCRS (0x37E)
#define SPR_WORT (0x37F)
#define SPR_PPR (0x380)
+#define SPR_PPR32 (0x382)
#define SPR_750_GQR0 (0x390)
#define SPR_440_DNV0 (0x390)
#define SPR_750_GQR1 (0x391)
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index eb2561f593..9e40b3b608 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -203,6 +203,8 @@ void spr_read_tfmr(DisasContext *ctx, int gprn, int sprn);
void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn);
void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn);
void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn);
+void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn);
+void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn);
#endif
void register_low_BATs(CPUPPCState *env);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 892fb6ce02..7684a59d75 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5623,6 +5623,14 @@ static void register_HEIR64_spr(CPUPPCState *env)
0x00000000);
}
+static void register_power7_common_sprs(CPUPPCState *env)
+{
+ spr_register(env, SPR_PPR32, "PPR32",
+ &spr_read_ppr32, &spr_write_ppr32,
+ &spr_read_ppr32, &spr_write_ppr32,
+ 0x00000000);
+}
+
static void register_power8_tce_address_control_sprs(CPUPPCState *env)
{
spr_register_kvm(env, SPR_TAR, "TAR",
@@ -6118,6 +6126,7 @@ static void init_proc_POWER7(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR32_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power7_book4_sprs(env);
/* env variables */
@@ -6264,6 +6273,7 @@ static void init_proc_POWER8(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR32_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power8_tce_address_control_sprs(env);
register_power8_ids_sprs(env);
register_power8_ebb_sprs(env);
@@ -6431,6 +6441,7 @@ static void init_proc_POWER9(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR32_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power8_tce_address_control_sprs(env);
register_power8_ids_sprs(env);
register_power8_ebb_sprs(env);
@@ -6625,6 +6636,7 @@ static void init_proc_POWER10(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR64_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power8_tce_address_control_sprs(env);
register_power8_ids_sprs(env);
register_power8_ebb_sprs(env);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index ca4f4c9371..137370b649 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1414,6 +1414,22 @@ void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn)
gen_load_spr(t0, sprn + 16);
tcg_gen_ext32u_tl(cpu_gpr[gprn], t0);
}
+
+/* The PPR32 SPR accesses the upper 32-bits of PPR */
+void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_load_spr(cpu_gpr[gprn], SPR_PPR);
+ tcg_gen_shri_tl(cpu_gpr[gprn], cpu_gpr[gprn], 32);
+}
+
+void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn)
+{
+ TCGv t0 = tcg_temp_new();
+
+ tcg_gen_shli_tl(t0, cpu_gpr[gprn], 32);
+ gen_store_spr(SPR_PPR, t0);
+ spr_store_dump_spr(SPR_PPR);
+}
#endif
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 06/12] target/ppc: Add PPR32 SPR
2024-05-21 1:30 ` [PATCH v2 06/12] target/ppc: Add PPR32 SPR Nicholas Piggin
@ 2024-05-21 15:52 ` Miles Glenn
2024-05-21 17:40 ` Richard Henderson
1 sibling, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 15:52 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> PPR32 provides access to the upper half of PPR.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/cpu.h | 1 +
> target/ppc/spr_common.h | 2 ++
> target/ppc/cpu_init.c | 12 ++++++++++++
> target/ppc/translate.c | 16 ++++++++++++++++
> 4 files changed, 31 insertions(+)
>
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 2532408be0..141cbefb4c 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -2120,6 +2120,7 @@ void ppc_compat_add_property(Object *obj, const
> char *name,
> #define SPR_POWER_MMCRS (0x37E)
> #define SPR_WORT (0x37F)
> #define SPR_PPR (0x380)
> +#define SPR_PPR32 (0x382)
> #define SPR_750_GQR0 (0x390)
> #define SPR_440_DNV0 (0x390)
> #define SPR_750_GQR1 (0x391)
> diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
> index eb2561f593..9e40b3b608 100644
> --- a/target/ppc/spr_common.h
> +++ b/target/ppc/spr_common.h
> @@ -203,6 +203,8 @@ void spr_read_tfmr(DisasContext *ctx, int gprn,
> int sprn);
> void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn);
> void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn);
> void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn);
> #endif
>
> void register_low_BATs(CPUPPCState *env);
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 892fb6ce02..7684a59d75 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -5623,6 +5623,14 @@ static void register_HEIR64_spr(CPUPPCState
> *env)
> 0x00000000);
> }
>
> +static void register_power7_common_sprs(CPUPPCState *env)
> +{
> + spr_register(env, SPR_PPR32, "PPR32",
> + &spr_read_ppr32, &spr_write_ppr32,
> + &spr_read_ppr32, &spr_write_ppr32,
> + 0x00000000);
> +}
> +
> static void register_power8_tce_address_control_sprs(CPUPPCState
> *env)
> {
> spr_register_kvm(env, SPR_TAR, "TAR",
> @@ -6118,6 +6126,7 @@ static void init_proc_POWER7(CPUPPCState *env)
> register_power6_common_sprs(env);
> register_HEIR32_spr(env);
> register_power6_dbg_sprs(env);
> + register_power7_common_sprs(env);
> register_power7_book4_sprs(env);
>
> /* env variables */
> @@ -6264,6 +6273,7 @@ static void init_proc_POWER8(CPUPPCState *env)
> register_power6_common_sprs(env);
> register_HEIR32_spr(env);
> register_power6_dbg_sprs(env);
> + register_power7_common_sprs(env);
> register_power8_tce_address_control_sprs(env);
> register_power8_ids_sprs(env);
> register_power8_ebb_sprs(env);
> @@ -6431,6 +6441,7 @@ static void init_proc_POWER9(CPUPPCState *env)
> register_power6_common_sprs(env);
> register_HEIR32_spr(env);
> register_power6_dbg_sprs(env);
> + register_power7_common_sprs(env);
> register_power8_tce_address_control_sprs(env);
> register_power8_ids_sprs(env);
> register_power8_ebb_sprs(env);
> @@ -6625,6 +6636,7 @@ static void init_proc_POWER10(CPUPPCState *env)
> register_power6_common_sprs(env);
> register_HEIR64_spr(env);
> register_power6_dbg_sprs(env);
> + register_power7_common_sprs(env);
> register_power8_tce_address_control_sprs(env);
> register_power8_ids_sprs(env);
> register_power8_ebb_sprs(env);
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index ca4f4c9371..137370b649 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -1414,6 +1414,22 @@ void spr_read_dexcr_ureg(DisasContext *ctx,
> int gprn, int sprn)
> gen_load_spr(t0, sprn + 16);
> tcg_gen_ext32u_tl(cpu_gpr[gprn], t0);
> }
> +
> +/* The PPR32 SPR accesses the upper 32-bits of PPR */
> +void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn)
> +{
> + gen_load_spr(cpu_gpr[gprn], SPR_PPR);
> + tcg_gen_shri_tl(cpu_gpr[gprn], cpu_gpr[gprn], 32);
> +}
> +
> +void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn)
> +{
> + TCGv t0 = tcg_temp_new();
> +
> + tcg_gen_shli_tl(t0, cpu_gpr[gprn], 32);
> + gen_store_spr(SPR_PPR, t0);
> + spr_store_dump_spr(SPR_PPR);
> +}
> #endif
>
> #define GEN_HANDLER(name, opc1, opc2, opc3, inval,
> type) \
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 06/12] target/ppc: Add PPR32 SPR
2024-05-21 1:30 ` [PATCH v2 06/12] target/ppc: Add PPR32 SPR Nicholas Piggin
2024-05-21 15:52 ` Miles Glenn
@ 2024-05-21 17:40 ` Richard Henderson
2024-05-22 1:43 ` Nicholas Piggin
1 sibling, 1 reply; 31+ messages in thread
From: Richard Henderson @ 2024-05-21 17:40 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles, Chinmay Rath
On 5/20/24 18:30, Nicholas Piggin wrote:
> +void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn)
> +{
> + TCGv t0 = tcg_temp_new();
> +
> + tcg_gen_shli_tl(t0, cpu_gpr[gprn], 32);
> + gen_store_spr(SPR_PPR, t0);
> + spr_store_dump_spr(SPR_PPR);
> +}
The documentation isn't clear on whether this zaps the low 32 bits. If the low bits of PPR
are {reserved, must-be-zero, undefined} or suchlike, this is fine.
If not, then you need a deposit here, to preserve those bits, e.g.:
gen_load_spr(t0, SPR_PPR);
tcg_gen_deposit_tl(t0, t0, cpu_gpr[gprn], 32, 32);
gen_store_spr(SPR_PPR, t0);
Anyway, it might be best to add a comment here re the above.
r~
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v2 06/12] target/ppc: Add PPR32 SPR
2024-05-21 17:40 ` Richard Henderson
@ 2024-05-22 1:43 ` Nicholas Piggin
0 siblings, 0 replies; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-22 1:43 UTC (permalink / raw)
To: Richard Henderson, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Glenn Miles, Chinmay Rath
On Wed May 22, 2024 at 3:40 AM AEST, Richard Henderson wrote:
> On 5/20/24 18:30, Nicholas Piggin wrote:
> > +void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn)
> > +{
> > + TCGv t0 = tcg_temp_new();
> > +
> > + tcg_gen_shli_tl(t0, cpu_gpr[gprn], 32);
> > + gen_store_spr(SPR_PPR, t0);
> > + spr_store_dump_spr(SPR_PPR);
> > +}
>
> The documentation isn't clear on whether this zaps the low 32 bits. If the low bits of PPR
> are {reserved, must-be-zero, undefined} or suchlike, this is fine.
>
> If not, then you need a deposit here, to preserve those bits, e.g.:
>
> gen_load_spr(t0, SPR_PPR);
> tcg_gen_deposit_tl(t0, t0, cpu_gpr[gprn], 32, 32);
> gen_store_spr(SPR_PPR, t0);
>
> Anyway, it might be best to add a comment here re the above.
Oh good catch. The other bits are reserved which means they can return 0
but it's not necessary. We implement all the bits though, so we should
not have mtPPR32 zeroing out the other half. In theory we probably can
since they're "undefined", but it doesn't seem nice. Actually now I look
the ISA says reserved bits in SPRs should return 0 for reads in
user-mode which we get wrong in a few places.
Anyway yes, for now I'll go with your deposit. Thank you.
Thanks,
Nick
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 07/12] target/ppc: add helper to write per-LPAR SPRs
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (5 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 06/12] target/ppc: Add PPR32 SPR Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 16:50 ` Miles Glenn
2024-05-21 1:30 ` [PATCH v2 08/12] target/ppc: Add SMT support to simple SPRs Nicholas Piggin
` (4 subsequent siblings)
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
An SPR can be either per-thread, per-core, or per-LPAR. Per-LPAR means
per-thread or per-core, depending on 1LPAR mode.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/spr_common.h | 2 ++
target/ppc/translate.c | 28 ++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index 9e40b3b608..85f73b860b 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -83,6 +83,8 @@ void spr_read_generic(DisasContext *ctx, int gprn, int sprn);
void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn);
+void spr_core_write_generic32(DisasContext *ctx, int sprn, int gprn);
+void spr_core_lpar_write_generic(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCRA(DisasContext *ctx, int sprn, int gprn);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 137370b649..c688551434 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -535,6 +535,34 @@ void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn)
spr_store_dump_spr(sprn);
}
+void spr_core_write_generic32(DisasContext *ctx, int sprn, int gprn)
+{
+ TCGv t0;
+
+ if (!(ctx->flags & POWERPC_FLAG_SMT)) {
+ spr_write_generic32(ctx, sprn, gprn);
+ return;
+ }
+
+ if (!gen_serialize(ctx)) {
+ return;
+ }
+
+ t0 = tcg_temp_new();
+ tcg_gen_ext32u_tl(t0, cpu_gpr[gprn]);
+ gen_helper_spr_core_write_generic(tcg_env, tcg_constant_i32(sprn), t0);
+ spr_store_dump_spr(sprn);
+}
+
+void spr_core_lpar_write_generic(DisasContext *ctx, int sprn, int gprn)
+{
+ if (ctx->flags & POWERPC_FLAG_SMT_1LPAR) {
+ spr_core_write_generic(ctx, sprn, gprn);
+ } else {
+ spr_write_generic(ctx, sprn, gprn);
+ }
+}
+
static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn)
{
/* This does not implement >1 thread */
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 07/12] target/ppc: add helper to write per-LPAR SPRs
2024-05-21 1:30 ` [PATCH v2 07/12] target/ppc: add helper to write per-LPAR SPRs Nicholas Piggin
@ 2024-05-21 16:50 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 16:50 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> An SPR can be either per-thread, per-core, or per-LPAR. Per-LPAR
> means
> per-thread or per-core, depending on 1LPAR mode.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/spr_common.h | 2 ++
> target/ppc/translate.c | 28 ++++++++++++++++++++++++++++
> 2 files changed, 30 insertions(+)
>
> diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
> index 9e40b3b608..85f73b860b 100644
> --- a/target/ppc/spr_common.h
> +++ b/target/ppc/spr_common.h
> @@ -83,6 +83,8 @@ void spr_read_generic(DisasContext *ctx, int gprn,
> int sprn);
> void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
> void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
> void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn);
> +void spr_core_write_generic32(DisasContext *ctx, int sprn, int
> gprn);
> +void spr_core_lpar_write_generic(DisasContext *ctx, int sprn, int
> gprn);
> void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn);
> void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn);
> void spr_write_MMCRA(DisasContext *ctx, int sprn, int gprn);
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 137370b649..c688551434 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -535,6 +535,34 @@ void spr_core_write_generic(DisasContext *ctx,
> int sprn, int gprn)
> spr_store_dump_spr(sprn);
> }
>
> +void spr_core_write_generic32(DisasContext *ctx, int sprn, int gprn)
> +{
> + TCGv t0;
> +
> + if (!(ctx->flags & POWERPC_FLAG_SMT)) {
> + spr_write_generic32(ctx, sprn, gprn);
> + return;
> + }
> +
> + if (!gen_serialize(ctx)) {
> + return;
> + }
> +
> + t0 = tcg_temp_new();
> + tcg_gen_ext32u_tl(t0, cpu_gpr[gprn]);
> + gen_helper_spr_core_write_generic(tcg_env,
> tcg_constant_i32(sprn), t0);
> + spr_store_dump_spr(sprn);
> +}
> +
> +void spr_core_lpar_write_generic(DisasContext *ctx, int sprn, int
> gprn)
> +{
> + if (ctx->flags & POWERPC_FLAG_SMT_1LPAR) {
> + spr_core_write_generic(ctx, sprn, gprn);
> + } else {
> + spr_write_generic(ctx, sprn, gprn);
> + }
> +}
> +
> static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn)
> {
> /* This does not implement >1 thread */
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 08/12] target/ppc: Add SMT support to simple SPRs
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (6 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 07/12] target/ppc: add helper to write per-LPAR SPRs Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 15:56 ` Miles Glenn
2024-05-21 1:30 ` [PATCH v2 09/12] target/ppc: Add SMT support to PTCR SPR Nicholas Piggin
` (3 subsequent siblings)
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
AMOR, MMCRC, HRMOR, TSCR, HMEER, RPR SPRs are per-core or per-LPAR
registers with simple (generic) implementations.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu_init.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 7684a59d75..023b58a3ac 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -246,7 +246,7 @@ static void register_amr_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_AMOR, "AMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_lpar_write_generic,
0);
#endif /* !CONFIG_USER_ONLY */
}
@@ -5489,7 +5489,7 @@ static void register_book3s_ids_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_MMCRC, "MMCRC",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic32,
+ &spr_read_generic, &spr_core_write_generic32,
0x00000000);
spr_register_hv(env, SPR_MMCRH, "MMCRH",
SPR_NOACCESS, SPR_NOACCESS,
@@ -5529,7 +5529,7 @@ static void register_book3s_ids_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_HRMOR, "HRMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_write_generic,
0x00000000);
}
@@ -5757,7 +5757,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_TSCR, "TSCR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic32,
+ &spr_read_generic, &spr_core_write_generic32,
0x00000000);
spr_register_hv(env, SPR_HMER, "HMER",
SPR_NOACCESS, SPR_NOACCESS,
@@ -5767,7 +5767,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_HMEER, "HMEER",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_write_generic,
0x00000000);
spr_register_hv(env, SPR_TFMR, "TFMR",
SPR_NOACCESS, SPR_NOACCESS,
@@ -5843,7 +5843,7 @@ static void register_power8_rpr_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_RPR, "RPR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_write_generic,
0x00000103070F1F3F);
#endif
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 08/12] target/ppc: Add SMT support to simple SPRs
2024-05-21 1:30 ` [PATCH v2 08/12] target/ppc: Add SMT support to simple SPRs Nicholas Piggin
@ 2024-05-21 15:56 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 15:56 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> AMOR, MMCRC, HRMOR, TSCR, HMEER, RPR SPRs are per-core or per-LPAR
> registers with simple (generic) implementations.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/cpu_init.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 7684a59d75..023b58a3ac 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -246,7 +246,7 @@ static void register_amr_sprs(CPUPPCState *env)
> spr_register_hv(env, SPR_AMOR, "AMOR",
> SPR_NOACCESS, SPR_NOACCESS,
> SPR_NOACCESS, SPR_NOACCESS,
> - &spr_read_generic, &spr_write_generic,
> + &spr_read_generic, &spr_core_lpar_write_generic,
> 0);
> #endif /* !CONFIG_USER_ONLY */
> }
> @@ -5489,7 +5489,7 @@ static void
> register_book3s_ids_sprs(CPUPPCState *env)
> spr_register_hv(env, SPR_MMCRC, "MMCRC",
> SPR_NOACCESS, SPR_NOACCESS,
> SPR_NOACCESS, SPR_NOACCESS,
> - &spr_read_generic, &spr_write_generic32,
> + &spr_read_generic, &spr_core_write_generic32,
> 0x00000000);
> spr_register_hv(env, SPR_MMCRH, "MMCRH",
> SPR_NOACCESS, SPR_NOACCESS,
> @@ -5529,7 +5529,7 @@ static void
> register_book3s_ids_sprs(CPUPPCState *env)
> spr_register_hv(env, SPR_HRMOR, "HRMOR",
> SPR_NOACCESS, SPR_NOACCESS,
> SPR_NOACCESS, SPR_NOACCESS,
> - &spr_read_generic, &spr_write_generic,
> + &spr_read_generic, &spr_core_write_generic,
> 0x00000000);
> }
>
> @@ -5757,7 +5757,7 @@ static void
> register_power_common_book4_sprs(CPUPPCState *env)
> spr_register_hv(env, SPR_TSCR, "TSCR",
> SPR_NOACCESS, SPR_NOACCESS,
> SPR_NOACCESS, SPR_NOACCESS,
> - &spr_read_generic, &spr_write_generic32,
> + &spr_read_generic, &spr_core_write_generic32,
> 0x00000000);
> spr_register_hv(env, SPR_HMER, "HMER",
> SPR_NOACCESS, SPR_NOACCESS,
> @@ -5767,7 +5767,7 @@ static void
> register_power_common_book4_sprs(CPUPPCState *env)
> spr_register_hv(env, SPR_HMEER, "HMEER",
> SPR_NOACCESS, SPR_NOACCESS,
> SPR_NOACCESS, SPR_NOACCESS,
> - &spr_read_generic, &spr_write_generic,
> + &spr_read_generic, &spr_core_write_generic,
> 0x00000000);
> spr_register_hv(env, SPR_TFMR, "TFMR",
> SPR_NOACCESS, SPR_NOACCESS,
> @@ -5843,7 +5843,7 @@ static void
> register_power8_rpr_sprs(CPUPPCState *env)
> spr_register_hv(env, SPR_RPR, "RPR",
> SPR_NOACCESS, SPR_NOACCESS,
> SPR_NOACCESS, SPR_NOACCESS,
> - &spr_read_generic, &spr_write_generic,
> + &spr_read_generic, &spr_core_write_generic,
> 0x00000103070F1F3F);
> #endif
> }
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 09/12] target/ppc: Add SMT support to PTCR SPR
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (7 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 08/12] target/ppc: Add SMT support to simple SPRs Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 16:02 ` Miles Glenn
2024-05-21 1:30 ` [PATCH v2 10/12] target/ppc: Implement LDBAR, TTR SPRs Nicholas Piggin
` (2 subsequent siblings)
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
PTCR is a per-core register.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/misc_helper.c | 16 ++++++++++++++--
target/ppc/translate.c | 4 ++++
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 6f419c9346..a67930d031 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -173,6 +173,7 @@ void helper_store_sdr1(CPUPPCState *env, target_ulong val)
void helper_store_ptcr(CPUPPCState *env, target_ulong val)
{
if (env->spr[SPR_PTCR] != val) {
+ CPUState *cs = env_cpu(env);
PowerPCCPU *cpu = env_archcpu(env);
target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
target_ulong patbsize = val & PTCR_PATS;
@@ -194,8 +195,19 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val)
return;
}
- env->spr[SPR_PTCR] = val;
- tlb_flush(env_cpu(env));
+ if (cs->nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+ env->spr[SPR_PTCR] = val;
+ tlb_flush(cs);
+ } else {
+ CPUState *ccs;
+
+ THREAD_SIBLING_FOREACH(cs, ccs) {
+ PowerPCCPU *ccpu = POWERPC_CPU(ccs);
+ CPUPPCState *cenv = &ccpu->env;
+ cenv->spr[SPR_PTCR] = val;
+ tlb_flush(ccs);
+ }
+ }
}
}
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index c688551434..76f829ad12 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -971,6 +971,10 @@ void spr_write_hior(DisasContext *ctx, int sprn, int gprn)
}
void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
{
+ if (!gen_serialize_core(ctx)) {
+ return;
+ }
+
gen_helper_store_ptcr(tcg_env, cpu_gpr[gprn]);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 09/12] target/ppc: Add SMT support to PTCR SPR
2024-05-21 1:30 ` [PATCH v2 09/12] target/ppc: Add SMT support to PTCR SPR Nicholas Piggin
@ 2024-05-21 16:02 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 16:02 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> PTCR is a per-core register.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/misc_helper.c | 16 ++++++++++++++--
> target/ppc/translate.c | 4 ++++
> 2 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
> index 6f419c9346..a67930d031 100644
> --- a/target/ppc/misc_helper.c
> +++ b/target/ppc/misc_helper.c
> @@ -173,6 +173,7 @@ void helper_store_sdr1(CPUPPCState *env,
> target_ulong val)
> void helper_store_ptcr(CPUPPCState *env, target_ulong val)
> {
> if (env->spr[SPR_PTCR] != val) {
> + CPUState *cs = env_cpu(env);
> PowerPCCPU *cpu = env_archcpu(env);
> target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
> target_ulong patbsize = val & PTCR_PATS;
> @@ -194,8 +195,19 @@ void helper_store_ptcr(CPUPPCState *env,
> target_ulong val)
> return;
> }
>
> - env->spr[SPR_PTCR] = val;
> - tlb_flush(env_cpu(env));
> + if (cs->nr_threads == 1 || !(env->flags &
> POWERPC_FLAG_SMT_1LPAR)) {
> + env->spr[SPR_PTCR] = val;
> + tlb_flush(cs);
> + } else {
> + CPUState *ccs;
> +
> + THREAD_SIBLING_FOREACH(cs, ccs) {
> + PowerPCCPU *ccpu = POWERPC_CPU(ccs);
> + CPUPPCState *cenv = &ccpu->env;
> + cenv->spr[SPR_PTCR] = val;
> + tlb_flush(ccs);
> + }
> + }
> }
> }
>
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index c688551434..76f829ad12 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -971,6 +971,10 @@ void spr_write_hior(DisasContext *ctx, int sprn,
> int gprn)
> }
> void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
> {
> + if (!gen_serialize_core(ctx)) {
> + return;
> + }
> +
> gen_helper_store_ptcr(tcg_env, cpu_gpr[gprn]);
> }
>
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 10/12] target/ppc: Implement LDBAR, TTR SPRs
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (8 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 09/12] target/ppc: Add SMT support to PTCR SPR Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 16:41 ` Miles Glenn
2024-05-21 1:30 ` [PATCH v2 11/12] target/ppc: Implement SPRC/SPRD SPRs Nicholas Piggin
2024-05-21 1:30 ` [PATCH v2 12/12] target/ppc: add SMT support to msgsnd broadcast Nicholas Piggin
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
LDBAR, TTR are a Power-specific SPRs. These simple implementations
are enough for IBM proprietary firmware for now.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu.h | 2 ++
target/ppc/cpu_init.c | 10 ++++++++++
2 files changed, 12 insertions(+)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 141cbefb4c..823be85d03 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2098,6 +2098,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_DEXCR (0x33C)
#define SPR_IC (0x350)
#define SPR_VTB (0x351)
+#define SPR_LDBAR (0x352)
#define SPR_MMCRC (0x353)
#define SPR_PSSCR (0x357)
#define SPR_440_INV0 (0x370)
@@ -2144,6 +2145,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_440_IVLIM (0x399)
#define SPR_TSCR (0x399)
#define SPR_750_DMAU (0x39A)
+#define SPR_POWER_TTR (0x39A)
#define SPR_750_DMAL (0x39B)
#define SPR_440_RSTCFG (0x39B)
#define SPR_BOOKE_DCDBTRL (0x39C)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 023b58a3ac..7f2f8e5a4a 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5784,6 +5784,16 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
&spr_access_nop, &spr_write_generic,
&spr_access_nop, &spr_write_generic,
0x00000000);
+ spr_register_hv(env, SPR_LDBAR, "LDBAR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_core_lpar_write_generic,
+ 0x00000000);
+ spr_register_hv(env, SPR_POWER_TTR, "TTR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_core_write_generic,
+ 0x00000000);
#endif
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 10/12] target/ppc: Implement LDBAR, TTR SPRs
2024-05-21 1:30 ` [PATCH v2 10/12] target/ppc: Implement LDBAR, TTR SPRs Nicholas Piggin
@ 2024-05-21 16:41 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 16:41 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> LDBAR, TTR are a Power-specific SPRs. These simple implementations
> are enough for IBM proprietary firmware for now.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/cpu.h | 2 ++
> target/ppc/cpu_init.c | 10 ++++++++++
> 2 files changed, 12 insertions(+)
>
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 141cbefb4c..823be85d03 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -2098,6 +2098,7 @@ void ppc_compat_add_property(Object *obj, const
> char *name,
> #define SPR_DEXCR (0x33C)
> #define SPR_IC (0x350)
> #define SPR_VTB (0x351)
> +#define SPR_LDBAR (0x352)
> #define SPR_MMCRC (0x353)
> #define SPR_PSSCR (0x357)
> #define SPR_440_INV0 (0x370)
> @@ -2144,6 +2145,7 @@ void ppc_compat_add_property(Object *obj, const
> char *name,
> #define SPR_440_IVLIM (0x399)
> #define SPR_TSCR (0x399)
> #define SPR_750_DMAU (0x39A)
> +#define SPR_POWER_TTR (0x39A)
> #define SPR_750_DMAL (0x39B)
> #define SPR_440_RSTCFG (0x39B)
> #define SPR_BOOKE_DCDBTRL (0x39C)
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 023b58a3ac..7f2f8e5a4a 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -5784,6 +5784,16 @@ static void
> register_power_common_book4_sprs(CPUPPCState *env)
> &spr_access_nop, &spr_write_generic,
> &spr_access_nop, &spr_write_generic,
> 0x00000000);
> + spr_register_hv(env, SPR_LDBAR, "LDBAR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_core_lpar_write_generic,
> + 0x00000000);
> + spr_register_hv(env, SPR_POWER_TTR, "TTR",
> + SPR_NOACCESS, SPR_NOACCESS,
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_core_write_generic,
> + 0x00000000);
> #endif
> }
>
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 11/12] target/ppc: Implement SPRC/SPRD SPRs
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (9 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 10/12] target/ppc: Implement LDBAR, TTR SPRs Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 16:37 ` Miles Glenn
2024-05-21 1:30 ` [PATCH v2 12/12] target/ppc: add SMT support to msgsnd broadcast Nicholas Piggin
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
This implements the POWER SPRC/SPRD SPRs, and SCRATCH0-7 registers that
can be accessed via these indirect SPRs.
SCRATCH registers only provide storage, but they are used by firmware
for low level crash and progress data, so this implementation logs
writes to the registers to help with analysis.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu.h | 7 +++--
target/ppc/helper.h | 3 ++
target/ppc/spr_common.h | 3 ++
target/ppc/cpu_init.c | 10 ++++++
target/ppc/misc_helper.c | 66 ++++++++++++++++++++++++++++++++++++++++
target/ppc/translate.c | 18 +++++++++++
6 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 823be85d03..e4c342b17d 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1264,6 +1264,9 @@ struct CPUArchState {
ppc_slb_t slb[MAX_SLB_ENTRIES]; /* PowerPC 64 SLB area */
struct CPUBreakpoint *ciabr_breakpoint;
struct CPUWatchpoint *dawr0_watchpoint;
+
+ /* POWER CPU regs/state */
+ target_ulong scratch[8]; /* SCRATCH registers (shared across core) */
#endif
target_ulong sr[32]; /* segment registers */
uint32_t nb_BATs; /* number of BATs */
@@ -1806,9 +1809,9 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_SPRG2 (0x112)
#define SPR_SPRG3 (0x113)
#define SPR_SPRG4 (0x114)
-#define SPR_SCOMC (0x114)
+#define SPR_POWER_SPRC (0x114)
#define SPR_SPRG5 (0x115)
-#define SPR_SCOMD (0x115)
+#define SPR_POWER_SPRD (0x115)
#define SPR_SPRG6 (0x116)
#define SPR_SPRG7 (0x117)
#define SPR_ASR (0x118)
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 09d50f9b76..57bf8354e7 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -730,6 +730,9 @@ DEF_HELPER_2(book3s_msgsndp, void, env, tl)
DEF_HELPER_2(book3s_msgclrp, void, env, tl)
DEF_HELPER_1(load_tfmr, tl, env)
DEF_HELPER_2(store_tfmr, void, env, tl)
+DEF_HELPER_FLAGS_2(store_sprc, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_1(load_sprd, TCG_CALL_NO_RWG_SE, tl, env)
+DEF_HELPER_FLAGS_2(store_sprd, TCG_CALL_NO_RWG, void, env, tl)
#endif
DEF_HELPER_2(store_sdr1, void, env, tl)
DEF_HELPER_2(store_pidr, void, env, tl)
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index 85f73b860b..01aff449bc 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -207,6 +207,9 @@ void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn);
void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn);
void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn);
+void spr_write_sprc(DisasContext *ctx, int sprn, int gprn);
+void spr_read_sprd(DisasContext *ctx, int sprn, int gprn);
+void spr_write_sprd(DisasContext *ctx, int sprn, int gprn);
#endif
void register_low_BATs(CPUPPCState *env);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 7f2f8e5a4a..f21dbcfefb 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5794,6 +5794,16 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_core_write_generic,
0x00000000);
+ spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_sprc,
+ 0x00000000);
+ spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_sprd, &spr_write_sprd,
+ 0x00000000);
#endif
}
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index a67930d031..fa47be2298 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -307,6 +307,72 @@ void helper_store_dpdes(CPUPPCState *env, target_ulong val)
}
bql_unlock();
}
+
+/* Indirect SCOM (SPRC/SPRD) access to SCRATCH0-7 are implemented. */
+void helper_store_sprc(CPUPPCState *env, target_ulong val)
+{
+ if (val & ~0x3f8ULL) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid SPRC register value "
+ TARGET_FMT_lx"\n", val);
+ return;
+ }
+ env->spr[SPR_POWER_SPRC] = val;
+}
+
+target_ulong helper_load_sprd(CPUPPCState *env)
+{
+ target_ulong sprc = env->spr[SPR_POWER_SPRC];
+
+ switch (sprc & 0x3c0) {
+ case 0: /* SCRATCH0-7 */
+ return env->scratch[(sprc >> 3) & 0x7];
+ default:
+ qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
+ TARGET_FMT_lx"\n", sprc);
+ break;
+ }
+ return 0;
+}
+
+static void do_store_scratch(CPUPPCState *env, int nr, target_ulong val)
+{
+ CPUState *cs = env_cpu(env);
+ CPUState *ccs;
+ uint32_t nr_threads = cs->nr_threads;
+
+ /*
+ * Log stores to SCRATCH, because some firmware uses these for debugging
+ * and logging, but they would normally be read by the BMC, which is
+ * not implemented in QEMU yet. This gives a way to get at the information.
+ * Could also dump these upon checkstop.
+ */
+ qemu_log("SPRD write 0x" TARGET_FMT_lx " to SCRATCH%d\n", val, nr);
+
+ if (nr_threads == 1) {
+ env->scratch[nr] = val;
+ return;
+ }
+
+ THREAD_SIBLING_FOREACH(cs, ccs) {
+ CPUPPCState *cenv = &POWERPC_CPU(ccs)->env;
+ cenv->scratch[nr] = val;
+ }
+}
+
+void helper_store_sprd(CPUPPCState *env, target_ulong val)
+{
+ target_ulong sprc = env->spr[SPR_POWER_SPRC];
+
+ switch (sprc & 0x3c0) {
+ case 0: /* SCRATCH0-7 */
+ do_store_scratch(env, (sprc >> 3) & 0x7, val);
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
+ TARGET_FMT_lx"\n", sprc);
+ break;
+ }
+}
#endif /* defined(TARGET_PPC64) */
void helper_store_pidr(CPUPPCState *env, target_ulong val)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 76f829ad12..ab11e48e3f 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1363,6 +1363,24 @@ void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn)
gen_helper_store_tfmr(tcg_env, cpu_gpr[gprn]);
}
+void spr_write_sprc(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_sprc(tcg_env, cpu_gpr[gprn]);
+}
+
+void spr_read_sprd(DisasContext *ctx, int gprn, int sprn)
+{
+ gen_helper_load_sprd(cpu_gpr[gprn], tcg_env);
+}
+
+void spr_write_sprd(DisasContext *ctx, int sprn, int gprn)
+{
+ if (!gen_serialize_core(ctx)) {
+ return;
+ }
+ gen_helper_store_sprd(tcg_env, cpu_gpr[gprn]);
+}
+
void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn)
{
translator_io_start(&ctx->base);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 11/12] target/ppc: Implement SPRC/SPRD SPRs
2024-05-21 1:30 ` [PATCH v2 11/12] target/ppc: Implement SPRC/SPRD SPRs Nicholas Piggin
@ 2024-05-21 16:37 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 16:37 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> This implements the POWER SPRC/SPRD SPRs, and SCRATCH0-7 registers
> that
> can be accessed via these indirect SPRs.
>
> SCRATCH registers only provide storage, but they are used by firmware
> for low level crash and progress data, so this implementation logs
> writes to the registers to help with analysis.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/cpu.h | 7 +++--
> target/ppc/helper.h | 3 ++
> target/ppc/spr_common.h | 3 ++
> target/ppc/cpu_init.c | 10 ++++++
> target/ppc/misc_helper.c | 66
> ++++++++++++++++++++++++++++++++++++++++
> target/ppc/translate.c | 18 +++++++++++
> 6 files changed, 105 insertions(+), 2 deletions(-)
>
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 823be85d03..e4c342b17d 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -1264,6 +1264,9 @@ struct CPUArchState {
> ppc_slb_t slb[MAX_SLB_ENTRIES]; /* PowerPC 64 SLB area */
> struct CPUBreakpoint *ciabr_breakpoint;
> struct CPUWatchpoint *dawr0_watchpoint;
> +
> + /* POWER CPU regs/state */
> + target_ulong scratch[8]; /* SCRATCH registers (shared across
> core) */
> #endif
> target_ulong sr[32]; /* segment registers */
> uint32_t nb_BATs; /* number of BATs */
> @@ -1806,9 +1809,9 @@ void ppc_compat_add_property(Object *obj, const
> char *name,
> #define SPR_SPRG2 (0x112)
> #define SPR_SPRG3 (0x113)
> #define SPR_SPRG4 (0x114)
> -#define SPR_SCOMC (0x114)
> +#define SPR_POWER_SPRC (0x114)
> #define SPR_SPRG5 (0x115)
> -#define SPR_SCOMD (0x115)
> +#define SPR_POWER_SPRD (0x115)
> #define SPR_SPRG6 (0x116)
> #define SPR_SPRG7 (0x117)
> #define SPR_ASR (0x118)
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index 09d50f9b76..57bf8354e7 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -730,6 +730,9 @@ DEF_HELPER_2(book3s_msgsndp, void, env, tl)
> DEF_HELPER_2(book3s_msgclrp, void, env, tl)
> DEF_HELPER_1(load_tfmr, tl, env)
> DEF_HELPER_2(store_tfmr, void, env, tl)
> +DEF_HELPER_FLAGS_2(store_sprc, TCG_CALL_NO_RWG, void, env, tl)
> +DEF_HELPER_FLAGS_1(load_sprd, TCG_CALL_NO_RWG_SE, tl, env)
> +DEF_HELPER_FLAGS_2(store_sprd, TCG_CALL_NO_RWG, void, env, tl)
> #endif
> DEF_HELPER_2(store_sdr1, void, env, tl)
> DEF_HELPER_2(store_pidr, void, env, tl)
> diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
> index 85f73b860b..01aff449bc 100644
> --- a/target/ppc/spr_common.h
> +++ b/target/ppc/spr_common.h
> @@ -207,6 +207,9 @@ void spr_write_lpcr(DisasContext *ctx, int sprn,
> int gprn);
> void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn);
> void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn);
> void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_sprc(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_sprd(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_sprd(DisasContext *ctx, int sprn, int gprn);
> #endif
>
> void register_low_BATs(CPUPPCState *env);
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 7f2f8e5a4a..f21dbcfefb 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -5794,6 +5794,16 @@ static void
> register_power_common_book4_sprs(CPUPPCState *env)
> SPR_NOACCESS, SPR_NOACCESS,
> &spr_read_generic, &spr_core_write_generic,
> 0x00000000);
> + spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
> + SPR_NOACCESS, SPR_NOACCESS,
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_generic, &spr_write_sprc,
> + 0x00000000);
> + spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
> + SPR_NOACCESS, SPR_NOACCESS,
> + SPR_NOACCESS, SPR_NOACCESS,
> + &spr_read_sprd, &spr_write_sprd,
> + 0x00000000);
> #endif
> }
>
> diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
> index a67930d031..fa47be2298 100644
> --- a/target/ppc/misc_helper.c
> +++ b/target/ppc/misc_helper.c
> @@ -307,6 +307,72 @@ void helper_store_dpdes(CPUPPCState *env,
> target_ulong val)
> }
> bql_unlock();
> }
> +
> +/* Indirect SCOM (SPRC/SPRD) access to SCRATCH0-7 are implemented.
> */
> +void helper_store_sprc(CPUPPCState *env, target_ulong val)
> +{
> + if (val & ~0x3f8ULL) {
> + qemu_log_mask(LOG_GUEST_ERROR, "Invalid SPRC register value
> "
> + TARGET_FMT_lx"\n", val);
> + return;
> + }
> + env->spr[SPR_POWER_SPRC] = val;
> +}
> +
> +target_ulong helper_load_sprd(CPUPPCState *env)
> +{
> + target_ulong sprc = env->spr[SPR_POWER_SPRC];
> +
> + switch (sprc & 0x3c0) {
> + case 0: /* SCRATCH0-7 */
> + return env->scratch[(sprc >> 3) & 0x7];
> + default:
> + qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
> + TARGET_FMT_lx"\n", sprc);
> + break;
> + }
> + return 0;
> +}
> +
> +static void do_store_scratch(CPUPPCState *env, int nr, target_ulong
> val)
> +{
> + CPUState *cs = env_cpu(env);
> + CPUState *ccs;
> + uint32_t nr_threads = cs->nr_threads;
> +
> + /*
> + * Log stores to SCRATCH, because some firmware uses these for
> debugging
> + * and logging, but they would normally be read by the BMC,
> which is
> + * not implemented in QEMU yet. This gives a way to get at the
> information.
> + * Could also dump these upon checkstop.
> + */
> + qemu_log("SPRD write 0x" TARGET_FMT_lx " to SCRATCH%d\n", val,
> nr);
> +
> + if (nr_threads == 1) {
> + env->scratch[nr] = val;
> + return;
> + }
> +
> + THREAD_SIBLING_FOREACH(cs, ccs) {
> + CPUPPCState *cenv = &POWERPC_CPU(ccs)->env;
> + cenv->scratch[nr] = val;
> + }
> +}
> +
> +void helper_store_sprd(CPUPPCState *env, target_ulong val)
> +{
> + target_ulong sprc = env->spr[SPR_POWER_SPRC];
> +
> + switch (sprc & 0x3c0) {
> + case 0: /* SCRATCH0-7 */
> + do_store_scratch(env, (sprc >> 3) & 0x7, val);
> + break;
> + default:
> + qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
> + TARGET_FMT_lx"\n", sprc);
> + break;
> + }
> +}
> #endif /* defined(TARGET_PPC64) */
>
> void helper_store_pidr(CPUPPCState *env, target_ulong val)
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 76f829ad12..ab11e48e3f 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -1363,6 +1363,24 @@ void spr_write_tfmr(DisasContext *ctx, int
> sprn, int gprn)
> gen_helper_store_tfmr(tcg_env, cpu_gpr[gprn]);
> }
>
> +void spr_write_sprc(DisasContext *ctx, int sprn, int gprn)
> +{
> + gen_helper_store_sprc(tcg_env, cpu_gpr[gprn]);
> +}
> +
> +void spr_read_sprd(DisasContext *ctx, int gprn, int sprn)
> +{
> + gen_helper_load_sprd(cpu_gpr[gprn], tcg_env);
> +}
> +
> +void spr_write_sprd(DisasContext *ctx, int sprn, int gprn)
> +{
> + if (!gen_serialize_core(ctx)) {
> + return;
> + }
> + gen_helper_store_sprd(tcg_env, cpu_gpr[gprn]);
> +}
> +
> void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn)
> {
> translator_io_start(&ctx->base);
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 12/12] target/ppc: add SMT support to msgsnd broadcast
2024-05-21 1:30 [PATCH v2 00/12] target/ppc: Various TCG emulation patches Nicholas Piggin
` (10 preceding siblings ...)
2024-05-21 1:30 ` [PATCH v2 11/12] target/ppc: Implement SPRC/SPRD SPRs Nicholas Piggin
@ 2024-05-21 1:30 ` Nicholas Piggin
2024-05-21 17:07 ` Miles Glenn
11 siblings, 1 reply; 31+ messages in thread
From: Nicholas Piggin @ 2024-05-21 1:30 UTC (permalink / raw)
To: qemu-ppc
Cc: Nicholas Piggin, qemu-devel, Daniel Henrique Barboza, Glenn Miles,
Richard Henderson, Chinmay Rath
msgsnd has a broadcast mode that sends hypervisor doorbells to all
threads belonging to the same core as the target. A "subcore" mode
sends to all or one thread depending on 1LPAR mode.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu.h | 6 +-
target/ppc/helper.h | 2 +-
target/ppc/excp_helper.c | 57 +++++++++++++------
.../ppc/translate/processor-ctrl-impl.c.inc | 2 +-
4 files changed, 46 insertions(+), 21 deletions(-)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index e4c342b17d..e201b7f6c2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1163,7 +1163,11 @@ FIELD(FPSCR, FI, FPSCR_FI, 1)
#define DBELL_TYPE_DBELL_SERVER (0x05 << DBELL_TYPE_SHIFT)
-#define DBELL_BRDCAST PPC_BIT(37)
+#define DBELL_BRDCAST_MASK PPC_BITMASK(37, 38)
+#define DBELL_BRDCAST_SHIFT 25
+#define DBELL_BRDCAST_SUBPROC (0x1 << DBELL_BRDCAST_SHIFT)
+#define DBELL_BRDCAST_CORE (0x2 << DBELL_BRDCAST_SHIFT)
+
#define DBELL_LPIDTAG_SHIFT 14
#define DBELL_LPIDTAG_MASK (0xfff << DBELL_LPIDTAG_SHIFT)
#define DBELL_PIRTAG_MASK 0x3fff
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 57bf8354e7..dd92c6a937 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -695,7 +695,7 @@ DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, tl, tl)
DEF_HELPER_1(msgsnd, void, tl)
DEF_HELPER_2(msgclr, void, env, tl)
-DEF_HELPER_1(book3s_msgsnd, void, tl)
+DEF_HELPER_2(book3s_msgsnd, void, env, tl)
DEF_HELPER_2(book3s_msgclr, void, env, tl)
#endif
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index e786a9044b..0a9e8539a4 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -2978,7 +2978,7 @@ void helper_msgsnd(target_ulong rb)
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *cenv = &cpu->env;
- if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
+ if ((rb & DBELL_BRDCAST_MASK) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
ppc_set_irq(cpu, irq, 1);
}
}
@@ -2997,6 +2997,16 @@ static bool dbell_type_server(target_ulong rb)
return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
}
+static inline bool dbell_bcast_core(target_ulong rb)
+{
+ return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_CORE;
+}
+
+static inline bool dbell_bcast_subproc(target_ulong rb)
+{
+ return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_SUBPROC;
+}
+
void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
{
if (!dbell_type_server(rb)) {
@@ -3006,32 +3016,43 @@ void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_HDOORBELL, 0);
}
-static void book3s_msgsnd_common(int pir, int irq)
+void helper_book3s_msgsnd(CPUPPCState *env, target_ulong rb)
{
- CPUState *cs;
+ int pir = rb & DBELL_PROCIDTAG_MASK;
+ bool brdcast = false;
+ CPUState *cs, *ccs;
+ PowerPCCPU *cpu;
- bql_lock();
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- CPUPPCState *cenv = &cpu->env;
+ if (!dbell_type_server(rb)) {
+ return;
+ }
- /* TODO: broadcast message to all threads of the same processor */
- if (cenv->spr_cb[SPR_PIR].default_value == pir) {
- ppc_set_irq(cpu, irq, 1);
- }
+ cpu = ppc_get_vcpu_by_pir(pir);
+ if (!cpu) {
+ return;
}
- bql_unlock();
-}
+ cs = CPU(cpu);
-void helper_book3s_msgsnd(target_ulong rb)
-{
- int pir = rb & DBELL_PROCIDTAG_MASK;
+ if (dbell_bcast_core(rb) || (dbell_bcast_subproc(rb) &&
+ (env->flags & POWERPC_FLAG_SMT_1LPAR))) {
+ brdcast = true;
+ }
- if (!dbell_type_server(rb)) {
+ if (cs->nr_threads == 1 || !brdcast) {
+ ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1);
return;
}
- book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
+ /*
+ * Why is bql needed for walking CPU list? Answer seems to be because ppc
+ * irq handling needs it, but ppc_set_irq takes the lock itself if needed,
+ * so could this be removed?
+ */
+ bql_lock();
+ THREAD_SIBLING_FOREACH(cs, ccs) {
+ ppc_set_irq(POWERPC_CPU(ccs), PPC_INTERRUPT_HDOORBELL, 1);
+ }
+ bql_unlock();
}
#ifdef TARGET_PPC64
diff --git a/target/ppc/translate/processor-ctrl-impl.c.inc b/target/ppc/translate/processor-ctrl-impl.c.inc
index 0142801985..8abbb89630 100644
--- a/target/ppc/translate/processor-ctrl-impl.c.inc
+++ b/target/ppc/translate/processor-ctrl-impl.c.inc
@@ -59,7 +59,7 @@ static bool trans_MSGSND(DisasContext *ctx, arg_X_rb *a)
#if !defined(CONFIG_USER_ONLY)
if (is_book3s_arch2x(ctx)) {
- gen_helper_book3s_msgsnd(cpu_gpr[a->rb]);
+ gen_helper_book3s_msgsnd(tcg_env, cpu_gpr[a->rb]);
} else {
gen_helper_msgsnd(cpu_gpr[a->rb]);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 12/12] target/ppc: add SMT support to msgsnd broadcast
2024-05-21 1:30 ` [PATCH v2 12/12] target/ppc: add SMT support to msgsnd broadcast Nicholas Piggin
@ 2024-05-21 17:07 ` Miles Glenn
0 siblings, 0 replies; 31+ messages in thread
From: Miles Glenn @ 2024-05-21 17:07 UTC (permalink / raw)
To: Nicholas Piggin, qemu-ppc
Cc: qemu-devel, Daniel Henrique Barboza, Richard Henderson,
Chinmay Rath
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Thanks,
Glenn
On Tue, 2024-05-21 at 11:30 +1000, Nicholas Piggin wrote:
> msgsnd has a broadcast mode that sends hypervisor doorbells to all
> threads belonging to the same core as the target. A "subcore" mode
> sends to all or one thread depending on 1LPAR mode.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> target/ppc/cpu.h | 6 +-
> target/ppc/helper.h | 2 +-
> target/ppc/excp_helper.c | 57 +++++++++++++--
> ----
> .../ppc/translate/processor-ctrl-impl.c.inc | 2 +-
> 4 files changed, 46 insertions(+), 21 deletions(-)
>
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index e4c342b17d..e201b7f6c2 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -1163,7 +1163,11 @@ FIELD(FPSCR, FI, FPSCR_FI, 1)
>
> #define DBELL_TYPE_DBELL_SERVER (0x05 << DBELL_TYPE_SHIFT)
>
> -#define DBELL_BRDCAST PPC_BIT(37)
> +#define DBELL_BRDCAST_MASK PPC_BITMASK(37, 38)
> +#define DBELL_BRDCAST_SHIFT 25
> +#define DBELL_BRDCAST_SUBPROC (0x1 << DBELL_BRDCAST_SHIFT)
> +#define DBELL_BRDCAST_CORE (0x2 << DBELL_BRDCAST_SHIFT)
> +
> #define DBELL_LPIDTAG_SHIFT 14
> #define DBELL_LPIDTAG_MASK (0xfff <<
> DBELL_LPIDTAG_SHIFT)
> #define DBELL_PIRTAG_MASK 0x3fff
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index 57bf8354e7..dd92c6a937 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -695,7 +695,7 @@ DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG,
> void, env, tl, tl)
>
> DEF_HELPER_1(msgsnd, void, tl)
> DEF_HELPER_2(msgclr, void, env, tl)
> -DEF_HELPER_1(book3s_msgsnd, void, tl)
> +DEF_HELPER_2(book3s_msgsnd, void, env, tl)
> DEF_HELPER_2(book3s_msgclr, void, env, tl)
> #endif
>
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index e786a9044b..0a9e8539a4 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -2978,7 +2978,7 @@ void helper_msgsnd(target_ulong rb)
> PowerPCCPU *cpu = POWERPC_CPU(cs);
> CPUPPCState *cenv = &cpu->env;
>
> - if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] ==
> pir)) {
> + if ((rb & DBELL_BRDCAST_MASK) || (cenv->spr[SPR_BOOKE_PIR]
> == pir)) {
> ppc_set_irq(cpu, irq, 1);
> }
> }
> @@ -2997,6 +2997,16 @@ static bool dbell_type_server(target_ulong rb)
> return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
> }
>
> +static inline bool dbell_bcast_core(target_ulong rb)
> +{
> + return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_CORE;
> +}
> +
> +static inline bool dbell_bcast_subproc(target_ulong rb)
> +{
> + return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_SUBPROC;
> +}
> +
> void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
> {
> if (!dbell_type_server(rb)) {
> @@ -3006,32 +3016,43 @@ void helper_book3s_msgclr(CPUPPCState *env,
> target_ulong rb)
> ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_HDOORBELL, 0);
> }
>
> -static void book3s_msgsnd_common(int pir, int irq)
> +void helper_book3s_msgsnd(CPUPPCState *env, target_ulong rb)
> {
> - CPUState *cs;
> + int pir = rb & DBELL_PROCIDTAG_MASK;
> + bool brdcast = false;
> + CPUState *cs, *ccs;
> + PowerPCCPU *cpu;
>
> - bql_lock();
> - CPU_FOREACH(cs) {
> - PowerPCCPU *cpu = POWERPC_CPU(cs);
> - CPUPPCState *cenv = &cpu->env;
> + if (!dbell_type_server(rb)) {
> + return;
> + }
>
> - /* TODO: broadcast message to all threads of the
> same processor */
> - if (cenv->spr_cb[SPR_PIR].default_value == pir) {
> - ppc_set_irq(cpu, irq, 1);
> - }
> + cpu = ppc_get_vcpu_by_pir(pir);
> + if (!cpu) {
> + return;
> }
> - bql_unlock();
> -}
> + cs = CPU(cpu);
>
> -void helper_book3s_msgsnd(target_ulong rb)
> -{
> - int pir = rb & DBELL_PROCIDTAG_MASK;
> + if (dbell_bcast_core(rb) || (dbell_bcast_subproc(rb) &&
> + (env->flags &
> POWERPC_FLAG_SMT_1LPAR))) {
> + brdcast = true;
> + }
>
> - if (!dbell_type_server(rb)) {
> + if (cs->nr_threads == 1 || !brdcast) {
> + ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1);
> return;
> }
>
> - book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
> + /*
> + * Why is bql needed for walking CPU list? Answer seems to be
> because ppc
> + * irq handling needs it, but ppc_set_irq takes the lock itself
> if needed,
> + * so could this be removed?
> + */
> + bql_lock();
> + THREAD_SIBLING_FOREACH(cs, ccs) {
> + ppc_set_irq(POWERPC_CPU(ccs), PPC_INTERRUPT_HDOORBELL, 1);
> + }
> + bql_unlock();
> }
>
> #ifdef TARGET_PPC64
> diff --git a/target/ppc/translate/processor-ctrl-impl.c.inc
> b/target/ppc/translate/processor-ctrl-impl.c.inc
> index 0142801985..8abbb89630 100644
> --- a/target/ppc/translate/processor-ctrl-impl.c.inc
> +++ b/target/ppc/translate/processor-ctrl-impl.c.inc
> @@ -59,7 +59,7 @@ static bool trans_MSGSND(DisasContext *ctx,
> arg_X_rb *a)
>
> #if !defined(CONFIG_USER_ONLY)
> if (is_book3s_arch2x(ctx)) {
> - gen_helper_book3s_msgsnd(cpu_gpr[a->rb]);
> + gen_helper_book3s_msgsnd(tcg_env, cpu_gpr[a->rb]);
> } else {
> gen_helper_msgsnd(cpu_gpr[a->rb]);
> }
^ permalink raw reply [flat|nested] 31+ messages in thread