All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU
@ 2022-03-24 19:08 Leandro Lupori
  2022-03-24 19:08 ` [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction Leandro Lupori
                   ` (6 more replies)
  0 siblings, 7 replies; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 19:08 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

Add support to run softmmu tests for ppc64 and ppc64le.
To make it possible, a new "virtual" TCG test target,
ppc64le-softmmu, was created.

Also add the MMU tests from
https://github.com/legoater/pnv-test, that are the Microwatt
tests adapted to use a PowerNV console and to better integrate
with QEMU test infrastructure.

To be able to finish the test and return an exit code to the
calling process, the Processor Attention instruction is used.
As its behavior is implementation dependent, in QEMU PowerNV
it just calls exit with GPR[3] value, truncated to an uint8_t.

Cédric Le Goater (2):
  target/ppc: Add support for the Processor Attention instruction
  ppc/pnv: Activate support for the Processor Attention instruction

Leandro Lupori (4):
  tests/tcg/ppc64: add basic softmmu test support
  tests/tcg: add support for ppc64le softmmu tests
  tests/tcg/ppc64: add MMU test sources
  tests/tcg/ppc64: add rules to build PowerNV tests

 hw/ppc/pnv_core.c                         |   6 +
 include/hw/ppc/pnv_core.h                 |   1 +
 target/ppc/cpu.h                          |   8 +
 target/ppc/excp_helper.c                  |  27 +
 target/ppc/helper.h                       |   1 +
 target/ppc/translate.c                    |  14 +
 tests/Makefile.include                    |   7 +-
 tests/tcg/configure.sh                    |  11 +-
 tests/tcg/ppc64/Makefile.softmmu-target   |  80 +++
 tests/tcg/ppc64/system/include/asm.h      |  62 ++
 tests/tcg/ppc64/system/include/console.h  |  15 +
 tests/tcg/ppc64/system/include/io.h       |  61 ++
 tests/tcg/ppc64/system/include/pnv.h      |  21 +
 tests/tcg/ppc64/system/include/uart.h     |  54 ++
 tests/tcg/ppc64/system/lib/boot.S         |  68 ++
 tests/tcg/ppc64/system/lib/console.c      | 173 +++++
 tests/tcg/ppc64/system/lib/powerpc.lds    |  27 +
 tests/tcg/ppc64/system/mmu-head.S         | 142 ++++
 tests/tcg/ppc64/system/mmu.c              | 764 ++++++++++++++++++++++
 tests/tcg/ppc64/system/mmu.h              |   9 +
 tests/tcg/ppc64le/Makefile.softmmu-target |   7 +
 21 files changed, 1554 insertions(+), 4 deletions(-)
 create mode 100644 tests/tcg/ppc64/Makefile.softmmu-target
 create mode 100644 tests/tcg/ppc64/system/include/asm.h
 create mode 100644 tests/tcg/ppc64/system/include/console.h
 create mode 100644 tests/tcg/ppc64/system/include/io.h
 create mode 100644 tests/tcg/ppc64/system/include/pnv.h
 create mode 100644 tests/tcg/ppc64/system/include/uart.h
 create mode 100644 tests/tcg/ppc64/system/lib/boot.S
 create mode 100644 tests/tcg/ppc64/system/lib/console.c
 create mode 100644 tests/tcg/ppc64/system/lib/powerpc.lds
 create mode 100644 tests/tcg/ppc64/system/mmu-head.S
 create mode 100644 tests/tcg/ppc64/system/mmu.c
 create mode 100644 tests/tcg/ppc64/system/mmu.h
 create mode 100644 tests/tcg/ppc64le/Makefile.softmmu-target

-- 
2.25.1



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction
  2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
@ 2022-03-24 19:08 ` Leandro Lupori
  2022-03-25 15:11   ` Fabiano Rosas
  2022-03-26 13:04   ` Richard Henderson
  2022-03-24 19:08 ` [RFC PATCH 2/6] ppc/pnv: Activate " Leandro Lupori
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 19:08 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

From: Cédric Le Goater <clg@kaod.org>

Check the HID0 bit to send signal, currently modeled as a checkstop.
The QEMU implementation adds an exit using the GPR[3] value (that's a
hack for tests)

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
---
 target/ppc/cpu.h         |  8 ++++++++
 target/ppc/excp_helper.c | 27 +++++++++++++++++++++++++++
 target/ppc/helper.h      |  1 +
 target/ppc/translate.c   | 14 ++++++++++++++
 4 files changed, 50 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 047b24ba50..12f9f3a880 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -173,6 +173,12 @@ enum {
     POWERPC_EXCP_PRIV_REG      = 0x02,  /* Privileged register exception     */
     /* Trap                                                                  */
     POWERPC_EXCP_TRAP          = 0x40,
+    /* Processor Attention                                                   */
+    POWERPC_EXCP_ATTN          = 0x100,
+    /*
+     * NOTE: POWERPC_EXCP_ATTN uses values from 0x100 to 0x1ff to return
+     *       error codes.
+     */
 };
 
 #define PPC_INPUT(env) ((env)->bus_model)
@@ -2089,6 +2095,8 @@ void ppc_compat_add_property(Object *obj, const char *name,
 #define HID0_DOZE           (1 << 23)           /* pre-2.06 */
 #define HID0_NAP            (1 << 22)           /* pre-2.06 */
 #define HID0_HILE           PPC_BIT(19) /* POWER8 */
+#define HID0_ATTN           PPC_BIT(31) /* Processor Attention */
+#define HID0_POWER9_ATTN    PPC_BIT(3)
 #define HID0_POWER9_HILE    PPC_BIT(4)
 
 /*****************************************************************************/
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index d3e2cfcd71..b0c629905c 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1379,6 +1379,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
             }
             cs->halted = 1;
             cpu_interrupt_exittb(cs);
+            if ((env->error_code & ~0xff) == POWERPC_EXCP_ATTN) {
+                exit(env->error_code & 0xff);
+            }
         }
         if (env->msr_mask & MSR_HVB) {
             /*
@@ -1971,6 +1974,30 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
     env->resume_as_sreset = (insn != PPC_PM_STOP) ||
         (env->spr[SPR_PSSCR] & PSSCR_EC);
 }
+
+/*
+ * Processor Attention instruction (Implementation dependent)
+ */
+void helper_attn(CPUPPCState *env, target_ulong r3)
+{
+    bool attn = false;
+
+    if (env->excp_model == POWERPC_EXCP_POWER8) {
+        attn = !!(env->spr[SPR_HID0] & HID0_ATTN);
+    } else if (env->excp_model == POWERPC_EXCP_POWER9 ||
+               env->excp_model == POWERPC_EXCP_POWER10) {
+        attn = !!(env->spr[SPR_HID0] & HID0_POWER9_ATTN);
+    }
+
+    if (attn) {
+        raise_exception_err(env, POWERPC_EXCP_MCHECK,
+                            POWERPC_EXCP_ATTN | (r3 & 0xff));
+    } else {
+        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL |
+                               POWERPC_EXCP_INVAL_INVAL, GETPC());
+    }
+}
 #endif /* defined(TARGET_PPC64) */
 
 static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 57da11c77e..9a2497569b 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -14,6 +14,7 @@ DEF_HELPER_1(rfmci, void, env)
 #if defined(TARGET_PPC64)
 DEF_HELPER_2(scv, noreturn, env, i32)
 DEF_HELPER_2(pminsn, void, env, i32)
+DEF_HELPER_2(attn, void, env, tl)
 DEF_HELPER_1(rfid, void, env)
 DEF_HELPER_1(rfscv, void, env)
 DEF_HELPER_1(hrfid, void, env)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 408ae26173..5ace6f3a29 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4123,6 +4123,19 @@ static void gen_rvwinkle(DisasContext *ctx)
     gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
+
+static void gen_attn(DisasContext *ctx)
+{
+ #if defined(CONFIG_USER_ONLY)
+    GEN_PRIV;
+#else
+    CHK_SV;
+
+    gen_helper_attn(cpu_env, cpu_gpr[3]);
+    ctx->base.is_jmp = DISAS_NORETURN;
+#endif
+}
+
 #endif /* #if defined(TARGET_PPC64) */
 
 static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
@@ -6844,6 +6857,7 @@ GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
 GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
 GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
 GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
+GEN_HANDLER(attn, 0x0, 0x00, 0x8, 0xfffffdff, PPC_FLOW),
 #endif
 /* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
 GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW),
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 2/6] ppc/pnv: Activate support for the Processor Attention instruction
  2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
  2022-03-24 19:08 ` [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction Leandro Lupori
@ 2022-03-24 19:08 ` Leandro Lupori
  2022-03-24 19:08 ` [RFC PATCH 3/6] tests/tcg/ppc64: add basic softmmu test support Leandro Lupori
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 19:08 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

From: Cédric Le Goater <clg@kaod.org>

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
---
 hw/ppc/pnv_core.c         | 6 ++++++
 include/hw/ppc/pnv_core.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 19e8eb885f..eb59b44a6c 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -46,6 +46,7 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
     CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
+    PnvCoreClass *pcorec = PNV_CORE_GET_CLASS(pc);
 
     cpu_reset(cs);
 
@@ -57,6 +58,8 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
     env->nip = 0x10;
     env->msr |= MSR_HVB; /* Hypervisor mode */
     env->spr[SPR_HRMOR] = pc->hrmor;
+    env->spr[SPR_HID0] |= pcorec->attn;
+
     hreg_compute_hflags(env);
 
     pcc->intc_reset(pc->chip, cpu);
@@ -300,6 +303,7 @@ static void pnv_core_power8_class_init(ObjectClass *oc, void *data)
     PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
 
     pcc->xscom_ops = &pnv_core_power8_xscom_ops;
+    pcc->attn = HID0_ATTN;
 }
 
 static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
@@ -307,6 +311,7 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
     PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
 
     pcc->xscom_ops = &pnv_core_power9_xscom_ops;
+    pcc->attn = HID0_POWER9_ATTN;
 }
 
 static void pnv_core_power10_class_init(ObjectClass *oc, void *data)
@@ -315,6 +320,7 @@ static void pnv_core_power10_class_init(ObjectClass *oc, void *data)
 
     /* TODO: Use the P9 XSCOMs for now on P10 */
     pcc->xscom_ops = &pnv_core_power9_xscom_ops;
+    pcc->attn = HID0_POWER9_ATTN;
 }
 
 static void pnv_core_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index c22eab2e1f..04e1fec1f3 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -47,6 +47,7 @@ struct PnvCoreClass {
     DeviceClass parent_class;
 
     const MemoryRegionOps *xscom_ops;
+    uint64_t attn;
 };
 
 #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 3/6] tests/tcg/ppc64: add basic softmmu test support
  2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
  2022-03-24 19:08 ` [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction Leandro Lupori
  2022-03-24 19:08 ` [RFC PATCH 2/6] ppc/pnv: Activate " Leandro Lupori
@ 2022-03-24 19:08 ` Leandro Lupori
  2022-03-24 19:08 ` [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests Leandro Lupori
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 19:08 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

Add support to build and run the multiarch hello test, that simply
prints a message and exits.

The linker script, console code and related header files were
imported from https://github.com/legoater/pnv-test, that are the
Microwatt tests adapted to use a PowerNV console.
Some other changes were made on top of these, mainly on boot.S,
that was based on pnv-test/mmu/head.S, to better integrate with
QEMU test infrastructure.

Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
---
 tests/tcg/ppc64/Makefile.softmmu-target  |  59 ++++++++
 tests/tcg/ppc64/system/include/asm.h     |  62 ++++++++
 tests/tcg/ppc64/system/include/console.h |  15 ++
 tests/tcg/ppc64/system/include/io.h      |  61 ++++++++
 tests/tcg/ppc64/system/include/pnv.h     |  21 +++
 tests/tcg/ppc64/system/include/uart.h    |  54 +++++++
 tests/tcg/ppc64/system/lib/boot.S        |  68 +++++++++
 tests/tcg/ppc64/system/lib/console.c     | 173 +++++++++++++++++++++++
 tests/tcg/ppc64/system/lib/powerpc.lds   |  27 ++++
 9 files changed, 540 insertions(+)
 create mode 100644 tests/tcg/ppc64/Makefile.softmmu-target
 create mode 100644 tests/tcg/ppc64/system/include/asm.h
 create mode 100644 tests/tcg/ppc64/system/include/console.h
 create mode 100644 tests/tcg/ppc64/system/include/io.h
 create mode 100644 tests/tcg/ppc64/system/include/pnv.h
 create mode 100644 tests/tcg/ppc64/system/include/uart.h
 create mode 100644 tests/tcg/ppc64/system/lib/boot.S
 create mode 100644 tests/tcg/ppc64/system/lib/console.c
 create mode 100644 tests/tcg/ppc64/system/lib/powerpc.lds

diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target
new file mode 100644
index 0000000000..8f9925ca5a
--- /dev/null
+++ b/tests/tcg/ppc64/Makefile.softmmu-target
@@ -0,0 +1,59 @@
+#
+# PowerPC64 system tests
+#
+
+# For now, disable tests that are failing
+DISABLED_TESTS := memory
+DISABLED_EXTRA_RUNS := run-gdbstub-memory
+
+PPC64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/ppc64/system
+VPATH+=$(PPC64_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_PATH=$(PPC64_SYSTEM_SRC)/lib
+CRT_OBJS=boot.o console.o
+
+PPC64_TEST_SRCS=$(wildcard $(PPC64_SYSTEM_SRC)/*.c)
+PPC64_TESTS=$(patsubst $(PPC64_SYSTEM_SRC)/%.c, %, $(PPC64_TEST_SRCS))
+
+LINK_SCRIPT=$(CRT_PATH)/powerpc.lds
+# NOTE: --build-id is stored before the first code section in the linked
+#       binary, which causes problems for most tests, that expect to
+#       begin at address 0.
+LDFLAGS=-Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none -static -nostdlib \
+    $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+TESTS += $(filter-out $(DISABLED_TESTS),$(PPC64_TESTS) $(MULTIARCH_TESTS))
+EXTRA_RUNS += $(filter-out $(DISABLED_EXTRA_RUNS),$(MULTIARCH_RUNS))
+
+# NOTE: -Os doesn't work well with -Wl,--oformat=binary
+#       Some linker generated functions, such as savegpr*/restgpr*,
+#       end up being undefined.
+CFLAGS = -O -g -Wall -std=c99 -msoft-float -mno-vsx -mno-altivec \
+         -fno-stack-protector -ffreestanding \
+         -I $(PPC64_SYSTEM_SRC)/include $(MINILIB_INC) \
+         -mcpu=power8
+
+# Leave the .elf files, to make debugging easier
+.PRECIOUS: $(CRT_OBJS) $(addsuffix .elf,$(TESTS))
+
+# Build CRT objects
+%.o: $(CRT_PATH)/%.S
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+%.o: $(CRT_PATH)/%.c
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
+
+# Build and link the tests
+
+# The .elf files are just for debugging
+%.elf: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+
+%: %.c %.elf $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) -Wl,--oformat=binary
+
+memory: CFLAGS+=-DCHECK_UNALIGNED=1
+
+# Running
+QEMU_BASE_MACHINE=-cpu power9 -M powernv9 -m 1G -vga none -nographic
+QEMU_OPTS+=$(QEMU_BASE_MACHINE) -serial chardev:output -bios
diff --git a/tests/tcg/ppc64/system/include/asm.h b/tests/tcg/ppc64/system/include/asm.h
new file mode 100644
index 0000000000..60bc08cd5c
--- /dev/null
+++ b/tests/tcg/ppc64/system/include/asm.h
@@ -0,0 +1,62 @@
+#ifndef PPC64_ASM_H
+#define PPC64_ASM_H
+
+#define XCONCAT(a, b)       a ## b
+#define CONCAT(a, b)        XCONCAT(a, b)
+
+/* Load an immediate 64-bit value into a register */
+#define LOAD_IMM64(r, e)                        \
+    lis     r, (e)@highest;                     \
+    ori     r, r, (e)@higher;                   \
+    rldicr  r, r, 32, 31;                       \
+    oris    r, r, (e)@h;                        \
+    ori     r, r, (e)@l;
+
+/* Switch CPU to little-endian mode, if needed */
+#define FIXUP_ENDIAN \
+    tdi   0, 0, 0x48;   /* Reverse endian of b . + 8 */             \
+    b     $ + 44;       /* Skip trampoline if endian is good */     \
+    .long 0xa600607d;   /* mfmsr r11 */                             \
+    .long 0x01006b69;   /* xori r11,r11,1 */                        \
+    .long 0x00004039;   /* li r10,0 */                              \
+    .long 0x6401417d;   /* mtmsrd r10,1 */                          \
+    .long 0x05009f42;   /* bcl 20,31,$+4 */                         \
+    .long 0xa602487d;   /* mflr r10 */                              \
+    .long 0x14004a39;   /* addi r10,r10,20 */                       \
+    .long 0xa6035a7d;   /* mtsrr0 r10 */                            \
+    .long 0xa6037b7d;   /* mtsrr1 r11 */                            \
+    .long 0x2400004c    /* rfid */
+
+/* Handle differences between ELFv1 and ELFv2 ABIs */
+
+#define DOT_LABEL(name)     CONCAT(., name)
+
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
+#define FUNCTION(name)                          \
+    .section ".opd", "aw";                      \
+    .p2align 3;                                 \
+    .globl   name;                              \
+name:                                           \
+    .quad   DOT_LABEL(name), .TOC.@tocbase, 0;  \
+    .previous;                                  \
+DOT_LABEL(name):
+
+#define CALL(fn)                                \
+    LOAD_IMM64(%r12, fn);                       \
+    ld      %r12, 0(%r12);                      \
+    mtctr   %r12;                               \
+    bctrl
+
+#else
+#define FUNCTION(name)                          \
+    .globl   name;                              \
+name:
+
+#define CALL(fn)                                \
+    LOAD_IMM64(%r12, fn);                       \
+    mtctr   %r12;                               \
+    bctrl
+
+#endif
+
+#endif
diff --git a/tests/tcg/ppc64/system/include/console.h b/tests/tcg/ppc64/system/include/console.h
new file mode 100644
index 0000000000..37ea45827b
--- /dev/null
+++ b/tests/tcg/ppc64/system/include/console.h
@@ -0,0 +1,15 @@
+#ifndef PPC64_CONSOLE_H
+#define PPC64_CONSOLE_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+void console_init(void);
+void console_set_irq_en(bool rx_irq, bool tx_irq);
+int getchar(void);
+int putchar(int c);
+int puts(const char *str);
+
+size_t strlen(const char *s);
+
+#endif
diff --git a/tests/tcg/ppc64/system/include/io.h b/tests/tcg/ppc64/system/include/io.h
new file mode 100644
index 0000000000..92932a5b75
--- /dev/null
+++ b/tests/tcg/ppc64/system/include/io.h
@@ -0,0 +1,61 @@
+#ifndef PPC64_IO_H
+#define PPC64_IO_H
+
+static inline uint8_t readb(unsigned long addr)
+{
+    uint8_t val;
+    __asm__ volatile("sync; lbzcix %0,0,%1"
+                     : "=r" (val) : "r" (addr) : "memory");
+    return val;
+}
+
+static inline uint16_t readw(unsigned long addr)
+{
+    uint16_t val;
+    __asm__ volatile("sync; lhzcix %0,0,%1"
+                     : "=r" (val) : "r" (addr) : "memory");
+    return val;
+}
+
+static inline uint32_t readl(unsigned long addr)
+{
+    uint32_t val;
+    __asm__ volatile("sync; lwzcix %0,0,%1"
+                     : "=r" (val) : "r" (addr) : "memory");
+    return val;
+}
+
+static inline uint64_t readq(unsigned long addr)
+{
+    uint64_t val;
+    __asm__ volatile("sync; ldcix %0,0,%1"
+                     : "=r" (val) : "r" (addr) : "memory");
+    return val;
+}
+
+static inline void writeb(uint8_t val, unsigned long addr)
+{
+    __asm__ volatile("sync; stbcix %0,0,%1"
+                     : : "r" (val), "r" (addr) : "memory");
+}
+
+static inline void writew(uint16_t val, unsigned long addr)
+{
+    __asm__ volatile("sync; sthcix %0,0,%1"
+                     : : "r" (val), "r" (addr) : "memory");
+}
+
+static inline void writel(uint32_t val, unsigned long addr)
+{
+    __asm__ volatile("sync; stwcix %0,0,%1"
+                     : : "r" (val), "r" (addr) : "memory");
+}
+
+static inline void writeq(uint64_t val, unsigned long addr)
+{
+    __asm__ volatile("sync; stdcix %0,0,%1"
+                     : : "r" (val), "r" (addr) : "memory");
+}
+
+#endif /* PPC64_IO_H */
+
diff --git a/tests/tcg/ppc64/system/include/pnv.h b/tests/tcg/ppc64/system/include/pnv.h
new file mode 100644
index 0000000000..0990a9fad9
--- /dev/null
+++ b/tests/tcg/ppc64/system/include/pnv.h
@@ -0,0 +1,21 @@
+#ifndef PPC64_PNV_H
+#define PPC64_PNV_H
+
+#define LPC_BASE_ADDR   0x0006030000000000
+#define LPC_IO_SPACE    0xd0010000
+#define LPC_FW_SPACE    0xf0000000
+
+#define UART_BASE       (LPC_BASE_ADDR + LPC_IO_SPACE + 0x3f8);
+
+#define MSR_HV (1ULL << (63 - 3))
+
+static inline bool is_pnv()
+{
+    unsigned long msr;
+
+    __asm__ volatile ("mfmsr %0"
+              : "=r" (msr)
+              : : "memory");
+    return !!(msr & MSR_HV);
+}
+#endif
diff --git a/tests/tcg/ppc64/system/include/uart.h b/tests/tcg/ppc64/system/include/uart.h
new file mode 100644
index 0000000000..77610e2ec2
--- /dev/null
+++ b/tests/tcg/ppc64/system/include/uart.h
@@ -0,0 +1,54 @@
+#ifndef PPC64_UART_H
+#define PPC64_UART_H
+
+/*
+ * Register definitions for our standard (16550 style) UART
+ */
+#define UART_REG_RX             0x00
+#define UART_REG_TX             0x00
+#define UART_REG_DLL            0x00
+#define UART_REG_IER            0x04
+#define   UART_REG_IER_RDI      0x01
+#define   UART_REG_IER_THRI     0x02
+#define   UART_REG_IER_RLSI     0x04
+#define   UART_REG_IER_MSI      0x08
+#define UART_REG_DLM            0x04
+#define UART_REG_IIR            0x08
+#define UART_REG_FCR            0x08
+#define   UART_REG_FCR_EN_FIFO  0x01
+#define   UART_REG_FCR_CLR_RCVR 0x02
+#define   UART_REG_FCR_CLR_XMIT 0x04
+#define   UART_REG_FCR_TRIG1    0x00
+#define   UART_REG_FCR_TRIG4    0x40
+#define   UART_REG_FCR_TRIG8    0x80
+#define   UART_REG_FCR_TRIG14   0xc0
+#define UART_REG_LCR            0x0c
+#define   UART_REG_LCR_5BIT     0x00
+#define   UART_REG_LCR_6BIT     0x01
+#define   UART_REG_LCR_7BIT     0x02
+#define   UART_REG_LCR_8BIT     0x03
+#define   UART_REG_LCR_STOP     0x04
+#define   UART_REG_LCR_PAR      0x08
+#define   UART_REG_LCR_EVEN_PAR 0x10
+#define   UART_REG_LCR_STIC_PAR 0x20
+#define   UART_REG_LCR_BREAK    0x40
+#define   UART_REG_LCR_DLAB     0x80
+#define UART_REG_MCR            0x10
+#define   UART_REG_MCR_DTR      0x01
+#define   UART_REG_MCR_RTS      0x02
+#define   UART_REG_MCR_OUT1     0x04
+#define   UART_REG_MCR_OUT2     0x08
+#define   UART_REG_MCR_LOOP     0x10
+#define UART_REG_LSR            0x14
+#define   UART_REG_LSR_DR       0x01
+#define   UART_REG_LSR_OE       0x02
+#define   UART_REG_LSR_PE       0x04
+#define   UART_REG_LSR_FE       0x08
+#define   UART_REG_LSR_BI       0x10
+#define   UART_REG_LSR_THRE     0x20
+#define   UART_REG_LSR_TEMT     0x40
+#define   UART_REG_LSR_FIFOE    0x80
+#define UART_REG_MSR            0x18
+#define UART_REG_SCR            0x1c
+
+#endif
diff --git a/tests/tcg/ppc64/system/lib/boot.S b/tests/tcg/ppc64/system/lib/boot.S
new file mode 100644
index 0000000000..607945fba4
--- /dev/null
+++ b/tests/tcg/ppc64/system/lib/boot.S
@@ -0,0 +1,68 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "asm.h"
+
+#define SPR_HID0                0x3f0
+#define SPR_HID0_POWER9_HILE    0x0800000000000000
+
+    .section ".head","ax"
+
+    /* Microwatt currently enters in LE mode at 0x0 */
+    . = 0
+_start:
+    b start
+
+    /* QEMU enters in BE at 0x10 by default */
+    . = 0x10
+.global start
+start:
+    FIXUP_ENDIAN
+
+    /* Setup TOC */
+    LOAD_IMM64(%r2, .TOC.)
+
+    /* Configure interrupt endian */
+#ifdef __LITTLE_ENDIAN__
+    mfspr   %r10, SPR_HID0
+    LOAD_IMM64(%r11, SPR_HID0_POWER9_HILE)
+    or      %r10, %r10, %r11
+    mtspr   SPR_HID0, %r10
+#endif
+
+    /* Clear .bss */
+    LOAD_IMM64(%r10,__bss_start)
+    LOAD_IMM64(%r11,__bss_end)
+    subf    %r11,%r10,%r11
+    addi    %r11,%r11,63
+    srdi.   %r11,%r11,6
+    beq     2f
+    mtctr   %r11
+1:  dcbz    0,%r10
+    addi    %r10,%r10,64
+    bdnz    1b
+
+    /* Setup stack */
+2:  LOAD_IMM64(%r1,__stack_top)
+    li      %r0,0
+    stdu    %r0,-16(%r1)
+
+    CALL(console_init)
+    CALL(main)
+
+    /* Terminate on exit */
+    attn
+    b       .
diff --git a/tests/tcg/ppc64/system/lib/console.c b/tests/tcg/ppc64/system/lib/console.c
new file mode 100644
index 0000000000..a4d8b02e21
--- /dev/null
+++ b/tests/tcg/ppc64/system/lib/console.c
@@ -0,0 +1,173 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "console.h"
+#include "pnv.h"
+#include "io.h"
+#include "uart.h"
+
+#define UART_BAUDS          115200
+#define H_PUT_TERM_CHAR     88
+
+/*
+ * Core UART functions to implement for a port
+ */
+
+static uint64_t uart_base;
+
+struct console_ops {
+    int (*putchar)(int c);
+} ops;
+
+
+static unsigned long uart_divisor(unsigned long uart_freq, unsigned long bauds)
+{
+    return uart_freq / (bauds * 16);
+}
+
+static bool std_uart_rx_empty(void)
+{
+    return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_DR);
+}
+
+static uint8_t std_uart_read(void)
+{
+    return readb(uart_base + UART_REG_RX);
+}
+
+static bool std_uart_tx_full(void)
+{
+    /* TODO: check UART LSR */
+    return 0;
+}
+
+static void std_uart_write(uint8_t c)
+{
+    writeb(c, uart_base + UART_REG_TX);
+}
+
+static void std_uart_set_irq_en(bool rx_irq, bool tx_irq)
+{
+    uint8_t ier = 0;
+
+    if (tx_irq) {
+        ier |= UART_REG_IER_THRI;
+    }
+    if (rx_irq) {
+        ier |= UART_REG_IER_RDI;
+    }
+    writeb(ier, uart_base + UART_REG_IER);
+}
+
+static void std_uart_init(uint64_t uart_freq)
+{
+    unsigned long div = uart_divisor(uart_freq, UART_BAUDS);
+
+    writeb(UART_REG_LCR_DLAB,     uart_base + UART_REG_LCR);
+    writeb(div & 0xff,            uart_base + UART_REG_DLL);
+    writeb(div >> 8,              uart_base + UART_REG_DLM);
+    writeb(UART_REG_LCR_8BIT,     uart_base + UART_REG_LCR);
+    writeb(UART_REG_MCR_DTR |
+           UART_REG_MCR_RTS,      uart_base + UART_REG_MCR);
+    writeb(UART_REG_FCR_EN_FIFO |
+           UART_REG_FCR_CLR_RCVR |
+           UART_REG_FCR_CLR_XMIT, uart_base + UART_REG_FCR);
+}
+
+int getchar(void)
+{
+    while (std_uart_rx_empty()) {
+        ;   /* Do nothing */
+    }
+    return std_uart_read();
+}
+
+int putchar(int c)
+{
+    return ops.putchar(c);
+}
+
+void __sys_outc(char c)
+{
+    putchar(c);
+}
+
+static int putchar_uart(int c)
+{
+    while (std_uart_tx_full()) {
+        ;   /* Do Nothing */
+    }
+    std_uart_write(c);
+    return c;
+}
+
+static int putchar_hvc(int c)
+{
+    register unsigned long hcall __asm__("r3") = H_PUT_TERM_CHAR;
+    register unsigned long termno __asm__("r4") = 0;
+    register unsigned long length __asm__("r5") = 1;
+    register unsigned long str __asm__("r6") = __builtin_bswap64(c);
+
+    __asm__ volatile ("sc 1" : : "r" (hcall), "r" (termno), "r" (length),
+                      "r" (str) : );
+    return c;
+}
+
+int puts(const char *str)
+{
+    unsigned int i;
+
+    for (i = 0; *str; i++) {
+        char c = *(str++);
+        if (c == 10) {
+            putchar(13);
+        }
+        putchar(c);
+    }
+    return 0;
+}
+
+size_t strlen(const char *s)
+{
+    size_t len = 0;
+
+    while (*s++) {
+        len++;
+    }
+
+    return len;
+}
+
+struct console_ops pseries_console = {
+    .putchar = putchar_hvc,
+};
+
+struct console_ops pnv_console = {
+    .putchar = putchar_uart,
+};
+
+void uart_init(void)
+{
+    uint64_t proc_freq; /* TODO */
+
+    proc_freq = 0; /* TODO */
+
+    uart_base = UART_BASE
+
+    std_uart_init(proc_freq);
+}
+
+void console_init(void)
+{
+    if (is_pnv()) {
+        ops = pnv_console;
+        uart_init();
+    } else {
+        ops = pseries_console;
+    }
+}
+
+void console_set_irq_en(bool rx_irq, bool tx_irq)
+{
+    std_uart_set_irq_en(rx_irq, tx_irq);
+}
diff --git a/tests/tcg/ppc64/system/lib/powerpc.lds b/tests/tcg/ppc64/system/lib/powerpc.lds
new file mode 100644
index 0000000000..db451e1fb9
--- /dev/null
+++ b/tests/tcg/ppc64/system/lib/powerpc.lds
@@ -0,0 +1,27 @@
+SECTIONS
+{
+    . = 0;
+    _start = .;
+    .head : {
+        KEEP(*(.head))
+    }
+    . = ALIGN(0x1000);
+    .text : { *(.text) *(.text.*) *(.rodata) *(.rodata.*) }
+    . = ALIGN(0x1000);
+    .data : { *(.data) *(.data.*) *(.got) *(.toc) }
+    . = ALIGN(0x80);
+    __bss_start = .;
+    .bss : {
+        *(.dynsbss)
+        *(.sbss)
+        *(.scommon)
+        *(.dynbss)
+        *(.bss)
+        *(.common)
+        *(.bss.*)
+    }
+    . = ALIGN(0x80);
+    __bss_end = .;
+    . = . + 0x4000;
+    __stack_top = .;
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests
  2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
                   ` (2 preceding siblings ...)
  2022-03-24 19:08 ` [RFC PATCH 3/6] tests/tcg/ppc64: add basic softmmu test support Leandro Lupori
@ 2022-03-24 19:08 ` Leandro Lupori
  2022-03-24 20:34   ` Alex Bennée
  2022-03-24 19:08 ` [RFC PATCH 5/6] tests/tcg/ppc64: add MMU test sources Leandro Lupori
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 19:08 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

Adding a new, "virtual" TCG test target, ppc64le-softmmu, seems to
be the cleanest way to support both BE and LE tests for
ppc64-softmmu.

Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
---
 tests/Makefile.include                    |  7 ++++---
 tests/tcg/configure.sh                    | 11 ++++++++++-
 tests/tcg/ppc64/Makefile.softmmu-target   |  2 ++
 tests/tcg/ppc64le/Makefile.softmmu-target |  7 +++++++
 4 files changed, 23 insertions(+), 4 deletions(-)
 create mode 100644 tests/tcg/ppc64le/Makefile.softmmu-target

diff --git a/tests/Makefile.include b/tests/Makefile.include
index e7153c8e91..4001fedbc3 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -40,9 +40,10 @@ SPEED = quick
 TARGETS=$(patsubst libqemu-%.fa, %, $(filter libqemu-%.fa, $(ninja-targets)))
 
 # Per guest TCG tests
-BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGETS))
-CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TARGETS))
-RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGETS))
+TCG_TARGETS=$(patsubst tests/tcg/config-%.mak, %, $(wildcard tests/tcg/config-*.mak))
+BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TCG_TARGETS))
+CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TCG_TARGETS))
+RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TCG_TARGETS))
 
 # Probe for the Docker Builds needed for each build
 $(foreach PROBE_TARGET,$(TARGET_DIRS), 				\
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index ed4b5ccb1f..a4ac7a4e44 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -80,6 +80,10 @@ fi
 : ${cross_as_tricore="tricore-as"}
 : ${cross_ld_tricore="tricore-ld"}
 
+# If target ppc64-softmmu is configured, also include the virtual test target
+# ppc64le-softmmu
+target_list=`echo $target_list | sed 's/ppc64-softmmu/& ppc64le-softmmu/'`
+
 for target in $target_list; do
   arch=${target%%-*}
 
@@ -237,7 +241,12 @@ for target in $target_list; do
       ;;
     *-softmmu)
       echo "CONFIG_SOFTMMU=y" >> $config_target_mak
-      echo "QEMU=$PWD/qemu-system-$arch" >> $config_target_mak
+      if test $arch = "ppc64le"; then
+        sys_arch=ppc64
+      else
+        sys_arch=$arch
+      fi
+      echo "QEMU=$PWD/qemu-system-$sys_arch" >> $config_target_mak
       ;;
   esac
 
diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target
index 8f9925ca5a..511b6322df 100644
--- a/tests/tcg/ppc64/Makefile.softmmu-target
+++ b/tests/tcg/ppc64/Makefile.softmmu-target
@@ -2,6 +2,8 @@
 # PowerPC64 system tests
 #
 
+BIG_ENDIAN ?= 1
+
 # For now, disable tests that are failing
 DISABLED_TESTS := memory
 DISABLED_EXTRA_RUNS := run-gdbstub-memory
diff --git a/tests/tcg/ppc64le/Makefile.softmmu-target b/tests/tcg/ppc64le/Makefile.softmmu-target
new file mode 100644
index 0000000000..d4162160ee
--- /dev/null
+++ b/tests/tcg/ppc64le/Makefile.softmmu-target
@@ -0,0 +1,7 @@
+#
+# PowerPC64 LE system tests
+#
+
+BIG_ENDIAN = 0
+
+include $(SRC_PATH)/tests/tcg/ppc64/Makefile.softmmu-target
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 5/6] tests/tcg/ppc64: add MMU test sources
  2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
                   ` (3 preceding siblings ...)
  2022-03-24 19:08 ` [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests Leandro Lupori
@ 2022-03-24 19:08 ` Leandro Lupori
  2022-03-24 19:08 ` [RFC PATCH 6/6] tests/tcg/ppc64: add rules to build PowerNV tests Leandro Lupori
  2022-03-26 13:13 ` [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Richard Henderson
  6 siblings, 0 replies; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 19:08 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

Add MMU test sources, from https://github.com/legoater/pnv-test,
based on Microwatt tests but with some adaptations.

In particular, the tests that check updates to RC bits were
removed, because, apparently, Microwatt never updates RC bits, but
just raise an exception when they must be updated, leaving the
task to the OS
(https://github.com/antonblanchard/microwatt/blob/master/mmu.vhdl#L402).

Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
---
 tests/tcg/ppc64/system/mmu-head.S | 141 ++++++
 tests/tcg/ppc64/system/mmu.c      | 764 ++++++++++++++++++++++++++++++
 tests/tcg/ppc64/system/mmu.h      |   9 +
 3 files changed, 914 insertions(+)
 create mode 100644 tests/tcg/ppc64/system/mmu-head.S
 create mode 100644 tests/tcg/ppc64/system/mmu.c
 create mode 100644 tests/tcg/ppc64/system/mmu.h

diff --git a/tests/tcg/ppc64/system/mmu-head.S b/tests/tcg/ppc64/system/mmu-head.S
new file mode 100644
index 0000000000..b7fb99c379
--- /dev/null
+++ b/tests/tcg/ppc64/system/mmu-head.S
@@ -0,0 +1,141 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "asm.h"
+
+#include "lib/boot.S"
+
+    /* Read a location with translation on */
+FUNCTION(test_read)
+    mfmsr   %r9
+    ori     %r8,%r9,0x10    /* set MSR_DR */
+    mtmsrd  %r8,0
+    mr      %r6,%r3
+    li      %r3,0
+    ld      %r5,0(%r6)
+    li      %r3,1
+    /* land here if DSI occurred */
+    mtmsrd  %r9,0
+    std     %r5,0(%r4)
+    blr
+
+    /* Write a location with translation on */
+FUNCTION(test_write)
+    mfmsr   %r9
+    ori     %r8,%r9,0x10    /* set MSR_DR */
+    mtmsrd  %r8,0
+    mr      %r6,%r3
+    li      %r3,0
+    std     %r4,0(%r6)
+    li      %r3,1
+    /* land here if DSI occurred */
+    mtmsrd  %r9,0
+    blr
+
+    /* Do a dcbz with translation on */
+FUNCTION(test_dcbz)
+    mfmsr   %r9
+    ori     %r8,%r9,0x10    /* set MSR_DR */
+    mtmsrd  %r8,0
+    mr      %r6,%r3
+    li      %r3,0
+    dcbz    0,%r6
+    li      %r3,1
+    /* land here if DSI occurred */
+    mtmsrd  %r9,0
+    blr
+
+FUNCTION(test_exec)
+    mtsrr0  %r4
+    mtsrr1  %r5
+    rfid
+
+#define EXCEPTION(nr)        \
+    .= nr                   ;\
+    attn
+
+    /* DSI vector - skip the failing instruction + the next one */
+    . = 0x300
+    mtsprg0 %r10
+    mfsrr0  %r10
+    addi    %r10,%r10,8
+    mtsrr0  %r10
+    rfid
+
+    EXCEPTION(0x380)
+
+    /*
+     * ISI vector - jump to LR to return from the test,
+     * with r3 cleared
+     */
+    . = 0x400
+    li      %r3,0
+    blr
+
+    /* More exception stubs */
+    EXCEPTION(0x480)
+    EXCEPTION(0x500)
+    EXCEPTION(0x600)
+    EXCEPTION(0x700)
+    EXCEPTION(0x800)
+    EXCEPTION(0x900)
+    EXCEPTION(0x980)
+    EXCEPTION(0xa00)
+    EXCEPTION(0xb00)
+
+    /*
+     * System call - used to exit from tests where MSR[PR]
+     * may have been set.
+     */
+    . = 0xc00
+    blr
+
+    EXCEPTION(0xd00)
+    EXCEPTION(0xe00)
+    EXCEPTION(0xe20)
+    EXCEPTION(0xe40)
+    EXCEPTION(0xe60)
+    EXCEPTION(0xe80)
+    EXCEPTION(0xf00)
+    EXCEPTION(0xf20)
+    EXCEPTION(0xf40)
+    EXCEPTION(0xf60)
+    EXCEPTION(0xf80)
+
+    . = 0x1000
+    /*
+     * This page gets mapped at various locations and
+     * the tests try to execute from it.
+     * r3 contains the test number.
+     */
+FUNCTION(test_start)
+    nop
+    nop
+    cmpdi   %r3,1
+    beq     test_1
+    cmpdi   %r3,2
+    beq     test_2
+test_return:
+    li      %r3,1
+    sc
+
+    . = 0x1ff8
+    /* test a branch near the end of a page */
+test_1:     b   test_return
+
+    /* test flowing from one page to the next */
+test_2:     nop
+    b       test_return
diff --git a/tests/tcg/ppc64/system/mmu.c b/tests/tcg/ppc64/system/mmu.c
new file mode 100644
index 0000000000..8e9fca2675
--- /dev/null
+++ b/tests/tcg/ppc64/system/mmu.c
@@ -0,0 +1,764 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "minilib.h"
+#include "mmu.h"
+
+#define MSR_LE    0x01
+#define MSR_DR    0x10
+#define MSR_IR    0x20
+#define MSR_HV    0x1000000000000000ul
+#define MSR_SF    0x8000000000000000ul
+
+#ifdef __LITTLE_ENDIAN__
+#define MSR_DFLT    (MSR_SF | MSR_HV | MSR_LE)
+#else
+#define MSR_DFLT    (MSR_SF | MSR_HV)
+#endif
+
+#define XSTR(x)     #x
+#define STR(x)      XSTR(x)
+
+#define RIC_TLB     0
+#define RIC_PWC     1
+#define RIC_ALL     2
+
+#define PRS         1
+
+#define IS(x)       ((unsigned long)(x) << 10)
+#define IS_VA       IS(0)
+#define IS_PID      IS(1)
+#define IS_LPID     IS(2)
+#define IS_ALL      IS(3)
+
+#define TLBIE_5(rb, rs, ric, prs, r)                \
+    __asm__ volatile(".long 0x7c000264 | "          \
+        "%0 << 21 | "                               \
+        STR(ric) " << 18 | "                        \
+        STR(prs) " << 17 | "                        \
+        STR(r) "<< 16 | "                           \
+        "%1 << 11"                                  \
+        : : "r" (rs), "r" (rb) : "memory")
+
+static inline void tlbie_all(int prs)
+{
+    if (prs) {
+        TLBIE_5(IS_ALL, 0, RIC_ALL, 1, 1);
+    } else {
+        TLBIE_5(IS_ALL, 0, RIC_ALL, 0, 1);
+    }
+}
+
+static inline void tlbie_va(unsigned long va, int prs)
+{
+    va &= ~0xffful;
+
+    if (prs) {
+        TLBIE_5(IS_VA | va, 0, RIC_TLB, 1, 1);
+    } else {
+        TLBIE_5(IS_VA | va, 0, RIC_TLB, 0, 1);
+    }
+    __asm__ volatile("eieio; tlbsync; ptesync" : : : "memory");
+}
+
+#define DSISR       18
+#define DAR         19
+#define SRR0        26
+#define SRR1        27
+#define PID         48
+#define LPCR        318
+#define PTCR        464
+
+#define PPC_BIT(x)  (0x8000000000000000ul >> (x))
+
+#define LPCR_UPRT   PPC_BIT(41)
+#define LPCR_HR     PPC_BIT(43)
+
+#define PATE_HR     PPC_BIT(0)
+
+static inline unsigned long mfspr(int sprnum)
+{
+    long val;
+
+    __asm__ volatile("mfspr %0,%1" : "=r" (val) : "i" (sprnum));
+    return val;
+}
+
+static inline void mtspr(int sprnum, unsigned long val)
+{
+    __asm__ volatile("mtspr %0,%1" : : "i" (sprnum), "r" (val));
+}
+
+static inline void store_pte(unsigned long *p, unsigned long pte)
+{
+#ifdef __LITTLE_ENDIAN__
+    __asm__ volatile("stdbrx %1,0,%0" : : "r" (p), "r" (pte) : "memory");
+#else
+    __asm__ volatile("stdx   %1,0,%0" : : "r" (p), "r" (pte) : "memory");
+#endif
+    __asm__ volatile("ptesync" : : : "memory");
+}
+
+#define CACHE_LINE_SIZE    64
+
+void zero_memory(void *ptr, unsigned long nbytes)
+{
+    unsigned long nb, i, nl;
+    void *p;
+
+    for (; nbytes != 0; nbytes -= nb, ptr += nb) {
+        nb = -((unsigned long)ptr) & (CACHE_LINE_SIZE - 1);
+        if (nb == 0 && nbytes >= CACHE_LINE_SIZE) {
+            nl = nbytes / CACHE_LINE_SIZE;
+            p = ptr;
+            for (i = 0; i < nl; ++i) {
+                __asm__ volatile("dcbz 0,%0" : : "r" (p) : "memory");
+                p += CACHE_LINE_SIZE;
+            }
+            nb = nl * CACHE_LINE_SIZE;
+        } else {
+            if (nb > nbytes) {
+                nb = nbytes;
+            }
+            for (i = 0; i < nb; ++i) {
+                ((unsigned char *)ptr)[i] = 0;
+            }
+        }
+    }
+}
+
+#define PAGE_SHIFT      12
+#define PAGE_SIZE       (1ul << PAGE_SHIFT)
+
+/* Partition Page Dir params */
+#define PPD_L1_BITS     5
+#define PPD_L2_BITS     14    /* virtual level 2 PGD address bits */
+#define PPD_PA_INC      (1ul << (PAGE_SHIFT + PPD_L2_BITS))
+
+#define RPTE_V          PPC_BIT(0)
+#define RPTE_L          PPC_BIT(1)
+#define RPTE_RPN_MASK   0x01fffffffffff000ul
+#define RPTE_R          PPC_BIT(55)
+#define RPTE_C          PPC_BIT(56)
+#define RPTE_PRIV       PPC_BIT(60)
+#define RPTE_RD         PPC_BIT(61)
+#define RPTE_RW         PPC_BIT(62)
+#define RPTE_EX         PPC_BIT(63)
+#define RPTE_PERM_ALL   (RPTE_RD | RPTE_RW | RPTE_EX)
+
+#define PERM_EX         RPTE_EX
+#define PERM_WR         RPTE_RW
+#define PERM_RD         RPTE_RD
+#define PERM_PRIV       RPTE_PRIV
+#define ATTR_NC         0x020
+#define CHG             RPTE_C
+#define REF             RPTE_R
+
+#define DFLT_PERM       (PERM_WR | PERM_RD | REF | CHG)
+
+/*
+ * Set up an MMU translation tree using memory starting at the 64k point.
+ * We use 2 levels, mapping 2GB (the minimum size possible), with a
+ * 8kB PGD level pointing to 4kB PTE pages.
+ */
+unsigned long *pgdir = (unsigned long *) 0x10000;
+unsigned long *proc_tbl = (unsigned long *) 0x12000;
+unsigned long *part_tbl = (unsigned long *) 0x13000;
+unsigned long *part_pgdir = (unsigned long *) 0x14000;
+unsigned long free_ptr = 0x15000;
+void *eas_mapped[4];
+int neas_mapped;
+
+void init_mmu(void)
+{
+    int i, n;
+    unsigned long pa, pte;
+
+    /* Select Radix MMU (HR), with HW process table */
+    mtspr(LPCR, mfspr(LPCR) | LPCR_UPRT | LPCR_HR);
+
+    /*
+     * Set up partition page dir, needed to translate process table
+     * addresses.
+     * We use only 1 level, mapping 2GB 1-1, with 32 64M pages.
+     */
+    zero_memory(part_tbl, PAGE_SIZE);
+    store_pte(&part_tbl[0], PATE_HR | (unsigned long) part_pgdir |
+            PPD_L1_BITS);
+
+    for (i = 0, n = 1 << PPD_L1_BITS, pa = 0;
+            i < n; i++, pa += PPD_PA_INC) {
+        pte = RPTE_V | RPTE_L | (pa & RPTE_RPN_MASK) | RPTE_PERM_ALL;
+        store_pte(&part_pgdir[i], pte);
+    }
+
+    /* set up partition table */
+    store_pte(&part_tbl[1], (unsigned long)proc_tbl);
+    /* set up process table */
+    zero_memory(proc_tbl, 512 * sizeof(unsigned long));
+    mtspr(PTCR, (unsigned long)part_tbl);
+    mtspr(PID, 1);
+    zero_memory(pgdir, 1024 * sizeof(unsigned long));
+    /* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */
+    store_pte(&proc_tbl[2 * 1], (unsigned long) pgdir | 10);
+    tlbie_all(0);   /* invalidate all TLB entries */
+}
+
+static unsigned long *read_pgd(unsigned long i)
+{
+    unsigned long ret;
+
+#ifdef __LITTLE_ENDIAN__
+    __asm__ volatile("ldbrx %0,%1,%2" : "=r" (ret) : "b" (pgdir),
+                     "r" (i * sizeof(unsigned long)));
+#else
+    __asm__ volatile("ldx   %0,%1,%2" : "=r" (ret) : "b" (pgdir),
+                     "r" (i * sizeof(unsigned long)));
+#endif
+    return (unsigned long *) (ret & 0x00ffffffffffff00);
+}
+
+void map(void *ea, void *pa, unsigned long perm_attr)
+{
+    unsigned long epn = (unsigned long) ea >> 12;
+    unsigned long i, j;
+    unsigned long *ptep;
+
+    i = (epn >> 9) & 0x3ff;
+    j = epn & 0x1ff;
+    if (pgdir[i] == 0) {
+        zero_memory((void *)free_ptr, 512 * sizeof(unsigned long));
+        store_pte(&pgdir[i], 0x8000000000000000 | free_ptr | 9);
+        free_ptr += 512 * sizeof(unsigned long);
+    }
+    ptep = read_pgd(i);
+    store_pte(&ptep[j], 0xc000000000000000 | ((unsigned long)pa &
+                                              0x00fffffffffff000) | perm_attr);
+    eas_mapped[neas_mapped++] = ea;
+}
+
+void unmap(void *ea)
+{
+    unsigned long epn = (unsigned long) ea >> 12;
+    unsigned long i, j;
+    unsigned long *ptep;
+
+    i = (epn >> 9) & 0x3ff;
+    j = epn & 0x1ff;
+    if (pgdir[i] == 0) {
+        return;
+    }
+    ptep = read_pgd(i);
+    store_pte(&ptep[j], 0);
+    tlbie_va((unsigned long)ea, PRS);
+}
+
+void unmap_all(void)
+{
+    int i;
+
+    for (i = 0; i < neas_mapped; ++i) {
+        unmap(eas_mapped[i]);
+    }
+    neas_mapped = 0;
+}
+
+int mmu_test_1(void)
+{
+    long *ptr = (long *) 0x123000;
+    long val;
+
+    /* this should fail */
+    if (test_read(ptr, &val, 0xdeadbeefd00d)) {
+        return 1;
+    }
+    /* dest reg of load should be unchanged */
+    if (val != 0xdeadbeefd00d) {
+        return 2;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != (long) ptr || mfspr(DSISR) != 0x40000000) {
+        return 3;
+    }
+    return 0;
+}
+
+int mmu_test_2(void)
+{
+    long *mem = (long *) 0x8000;
+    long *ptr = (long *) 0x124000;
+    long *ptr2 = (long *) 0x1124000;
+    long val;
+
+    /* create PTE */
+    map(ptr, mem, DFLT_PERM);
+    /* initialize the memory content */
+    mem[33] = 0xbadc0ffee;
+    /* this should succeed and be a cache miss */
+    if (!test_read(&ptr[33], &val, 0xdeadbeefd00d)) {
+        return 1;
+    }
+    /* dest reg of load should have the value written */
+    if (val != 0xbadc0ffee) {
+        return 2;
+    }
+    /* load a second TLB entry in the same set as the first */
+    map(ptr2, mem, DFLT_PERM);
+    /* this should succeed and be a cache hit */
+    if (!test_read(&ptr2[33], &val, 0xdeadbeefd00d)) {
+        return 3;
+    }
+    /* dest reg of load should have the value written */
+    if (val != 0xbadc0ffee) {
+        return 4;
+    }
+    /* check that the first entry still works */
+    if (!test_read(&ptr[33], &val, 0xdeadbeefd00d)) {
+        return 5;
+    }
+    if (val != 0xbadc0ffee) {
+        return 6;
+    }
+    return 0;
+}
+
+int mmu_test_3(void)
+{
+    long *mem = (long *) 0x9000;
+    long *ptr = (long *) 0x14a000;
+    long val;
+
+    /* create PTE */
+    map(ptr, mem, DFLT_PERM);
+    /* initialize the memory content */
+    mem[45] = 0xfee1800d4ea;
+    /* this should succeed and be a cache miss */
+    if (!test_read(&ptr[45], &val, 0xdeadbeefd0d0)) {
+        return 1;
+    }
+    /* dest reg of load should have the value written */
+    if (val != 0xfee1800d4ea) {
+        return 2;
+    }
+    /* remove the PTE */
+    unmap(ptr);
+    /* this should fail */
+    if (test_read(&ptr[45], &val, 0xdeadbeefd0d0)) {
+        return 3;
+    }
+    /* dest reg of load should be unchanged */
+    if (val != 0xdeadbeefd0d0) {
+        return 4;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != (long) &ptr[45] || mfspr(DSISR) != 0x40000000) {
+        return 5;
+    }
+    return 0;
+}
+
+int mmu_test_4(void)
+{
+    long *mem = (long *) 0xa000;
+    long *ptr = (long *) 0x10b000;
+    long *ptr2 = (long *) 0x110b000;
+    long val;
+
+    /* create PTE */
+    map(ptr, mem, DFLT_PERM);
+    /* initialize the memory content */
+    mem[27] = 0xf00f00f00f00;
+    /* this should succeed and be a cache miss */
+    if (!test_write(&ptr[27], 0xe44badc0ffee)) {
+        return 1;
+    }
+    /* memory should now have the value written */
+    if (mem[27] != 0xe44badc0ffee) {
+        return 2;
+    }
+    /* load a second TLB entry in the same set as the first */
+    map(ptr2, mem, DFLT_PERM);
+    /* this should succeed and be a cache hit */
+    if (!test_write(&ptr2[27], 0x6e11ae)) {
+        return 3;
+    }
+    /* memory should have the value written */
+    if (mem[27] != 0x6e11ae) {
+        return 4;
+    }
+    /* check that the first entry still exists */
+    /* (assumes TLB is 2-way associative or more) */
+    if (!test_read(&ptr[27], &val, 0xdeadbeefd00d)) {
+        return 5;
+    }
+    if (val != 0x6e11ae) {
+        return 6;
+    }
+    return 0;
+}
+
+int mmu_test_5(void)
+{
+    long *mem = (long *) 0xbffd;
+    long *ptr = (long *) 0x39fffd;
+    long val;
+
+    /* create PTE */
+    map(ptr, mem, DFLT_PERM);
+    /* this should fail */
+    if (test_read(ptr, &val, 0xdeadbeef0dd0)) {
+        return 1;
+    }
+    /* dest reg of load should be unchanged */
+    if (val != 0xdeadbeef0dd0) {
+        return 2;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != ((long)ptr & ~0xfff) + 0x1000 ||
+            mfspr(DSISR) != 0x40000000) {
+        return 3;
+    }
+    return 0;
+}
+
+int mmu_test_6(void)
+{
+    long *mem = (long *) 0xbffd;
+    long *ptr = (long *) 0x39fffd;
+
+    /* create PTE */
+    map(ptr, mem, DFLT_PERM);
+    /* initialize memory */
+    *mem = 0x123456789abcdef0;
+    /* this should fail */
+    if (test_write(ptr, 0xdeadbeef0dd0)) {
+        return 1;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != ((long)ptr & ~0xfff) + 0x1000 ||
+            mfspr(DSISR) != 0x42000000) {
+        return 2;
+    }
+    return 0;
+}
+
+int mmu_test_7(void)
+{
+    long *mem = (long *) 0x8000;
+    long *ptr = (long *) 0x124000;
+    long val;
+
+    *mem = 0x123456789abcdef0;
+    /* create PTE without read or write permission */
+    map(ptr, mem, REF);
+    /* this should fail */
+    if (test_read(ptr, &val, 0xdeadd00dbeef)) {
+        return 1;
+    }
+    /* dest reg of load should be unchanged */
+    if (val != 0xdeadd00dbeef) {
+        return 2;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != (long) ptr || mfspr(DSISR) != 0x08000000) {
+        return 3;
+    }
+    /* this should fail */
+    if (test_write(ptr, 0xdeadbeef0dd1)) {
+        return 4;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000) {
+        return 5;
+    }
+    /* memory should be unchanged */
+    if (*mem != 0x123456789abcdef0) {
+        return 6;
+    }
+    return 0;
+}
+
+int mmu_test_8(void)
+{
+    long *mem = (long *) 0x8000;
+    long *ptr = (long *) 0x124000;
+    long val;
+
+    *mem = 0x123456789abcdef0;
+    /* create PTE with read but not write permission */
+    map(ptr, mem, REF | PERM_RD);
+    /* this should succeed */
+    if (!test_read(ptr, &val, 0xdeadd00dbeef)) {
+        return 1;
+    }
+    /* this should fail */
+    if (test_write(ptr, 0xdeadbeef0dd1)) {
+        return 2;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000) {
+        return 3;
+    }
+    /* memory should be unchanged */
+    if (*mem != 0x123456789abcdef0) {
+        return 4;
+    }
+    return 0;
+}
+
+int mmu_test_9(void)
+{
+    unsigned long ptr = 0x523000;
+
+    /* this should fail */
+    if (test_exec(0, ptr, MSR_DFLT | MSR_IR)) {
+        return 1;
+    }
+    /* SRR0 and SRR1 should be set correctly */
+    if (mfspr(SRR0) != (long) ptr ||
+            mfspr(SRR1) != (MSR_DFLT | 0x40000000 | MSR_IR)) {
+        return 2;
+    }
+    return 0;
+}
+
+int mmu_test_10(void)
+{
+    unsigned long mem = 0x1000;
+    unsigned long ptr = 0x324000;
+    unsigned long ptr2 = 0x1324000;
+
+    /* create PTE */
+    map((void *)ptr, (void *)mem, PERM_EX | REF);
+    /* this should succeed and be a cache miss */
+    if (!test_exec(0, ptr, MSR_DFLT | MSR_IR)) {
+        return 1;
+    }
+    /* create a second PTE */
+    map((void *)ptr2, (void *)mem, PERM_EX | REF);
+    /* this should succeed and be a cache hit */
+    if (!test_exec(0, ptr2, MSR_DFLT | MSR_IR)) {
+        return 2;
+    }
+    return 0;
+}
+
+int mmu_test_11(void)
+{
+    unsigned long mem = 0x1000;
+    unsigned long ptr = 0x349000;
+    unsigned long ptr2 = 0x34a000;
+
+    /* create a PTE */
+    map((void *)ptr, (void *)mem, PERM_EX | REF);
+    /* this should succeed */
+    if (!test_exec(1, ptr, MSR_DFLT | MSR_IR)) {
+        return 1;
+    }
+    /* invalidate the PTE */
+    unmap((void *)ptr);
+    /* install a second PTE */
+    map((void *)ptr2, (void *)mem, PERM_EX | REF);
+    /* this should fail */
+    if (test_exec(1, ptr, MSR_DFLT | MSR_IR)) {
+        return 2;
+    }
+    /* SRR0 and SRR1 should be set correctly */
+    if (mfspr(SRR0) != (long) ptr ||
+            mfspr(SRR1) != (MSR_DFLT | 0x40000000 | MSR_IR)) {
+        return 3;
+    }
+    return 0;
+}
+
+int mmu_test_12(void)
+{
+    unsigned long mem = 0x1000;
+    unsigned long mem2 = 0x2000;
+    unsigned long ptr = 0x30a000;
+    unsigned long ptr2 = 0x30b000;
+
+    /* create a PTE */
+    map((void *)ptr, (void *)mem, PERM_EX | REF);
+    /* this should fail due to second page not being mapped */
+    if (test_exec(2, ptr, MSR_DFLT | MSR_IR)) {
+        return 1;
+    }
+    /* SRR0 and SRR1 should be set correctly */
+    if (mfspr(SRR0) != ptr2 ||
+            mfspr(SRR1) != (MSR_DFLT | 0x40000000 | MSR_IR)) {
+        return 2;
+    }
+    /* create a PTE for the second page */
+    map((void *)ptr2, (void *)mem2, PERM_EX | REF);
+    /* this should succeed */
+    if (!test_exec(2, ptr, MSR_DFLT | MSR_IR)) {
+        return 3;
+    }
+    return 0;
+}
+
+int mmu_test_13(void)
+{
+    unsigned long mem = 0x1000;
+    unsigned long ptr = 0x324000;
+
+    /* create a PTE without execute permission */
+    map((void *)ptr, (void *)mem, DFLT_PERM);
+    /* this should fail */
+    if (test_exec(0, ptr, MSR_DFLT | MSR_IR)) {
+        return 1;
+    }
+    /* SRR0 and SRR1 should be set correctly */
+    if (mfspr(SRR0) != ptr ||
+            mfspr(SRR1) != (MSR_DFLT | 0x10000000 | MSR_IR)) {
+        return 2;
+    }
+    return 0;
+}
+
+int mmu_test_14(void)
+{
+    unsigned long mem = 0x1000;
+    unsigned long mem2 = 0x2000;
+    unsigned long ptr = 0x30a000;
+    unsigned long ptr2 = 0x30b000;
+
+    /* create a PTE */
+    map((void *)ptr, (void *)mem, PERM_EX | REF);
+    /* create a PTE for the second page without execute permission */
+    map((void *)ptr2, (void *)mem2, PERM_RD | REF);
+    /* this should fail due to second page being no-execute */
+    if (test_exec(2, ptr, MSR_DFLT | MSR_IR)) {
+        return 1;
+    }
+    /* SRR0 and SRR1 should be set correctly */
+    if (mfspr(SRR0) != ptr2 ||
+            mfspr(SRR1) != (MSR_DFLT | 0x10000000 | MSR_IR)) {
+        return 2;
+    }
+    /* create a PTE for the second page with execute permission */
+    map((void *)ptr2, (void *)mem2, PERM_RD | PERM_EX | REF);
+    /* this should succeed */
+    if (!test_exec(2, ptr, MSR_DFLT | MSR_IR)) {
+        return 3;
+    }
+    return 0;
+}
+
+int mmu_test_15(void)
+{
+    unsigned long mem = 0x1000;
+    unsigned long ptr = 0x349000;
+
+    /* create a PTE without ref or execute permission */
+    map((void *)ptr, (void *)mem, 0);
+    /* this should fail */
+    if (test_exec(2, ptr, MSR_DFLT | MSR_IR)) {
+        return 1;
+    }
+    /* SRR0 and SRR1 should be set correctly */
+    /* RC update fail bit should not be set */
+    if (mfspr(SRR0) != (long) ptr ||
+            mfspr(SRR1) != (MSR_DFLT | 0x10000000 | MSR_IR)) {
+        return 2;
+    }
+    return 0;
+}
+
+int mmu_test_16(void)
+{
+    long *mem = (long *) 0x8000;
+    long *ptr = (long *) 0x124000;
+    long *ptr2 = (long *) 0x1124000;
+
+    /* create PTE */
+    map(ptr, mem, DFLT_PERM);
+    /* this should succeed and be a cache miss */
+    if (!test_dcbz(&ptr[129])) {
+        return 1;
+    }
+    /* create a second PTE */
+    map(ptr2, mem, DFLT_PERM);
+    /* this should succeed and be a cache hit */
+    if (!test_dcbz(&ptr2[130])) {
+        return 2;
+    }
+    return 0;
+}
+
+int mmu_test_17(void)
+{
+    long *mem = (long *) 0x8000;
+    long *ptr = (long *) 0x124000;
+
+    *mem = 0x123456789abcdef0;
+    /* create PTE with read but not write permission */
+    map(ptr, mem, REF | PERM_RD);
+    /* this should fail and create a TLB entry */
+    if (test_write(ptr, 0xdeadbeef0dd1)) {
+        return 1;
+    }
+    /* DAR and DSISR should be set correctly */
+    if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000) {
+        return 2;
+    }
+    /* Update the PTE to have write permission */
+    map(ptr, mem, REF | CHG | PERM_RD | PERM_WR);
+    /* this should succeed */
+    if (!test_write(ptr, 0xdeadbeef0dd1)) {
+        return 3;
+    }
+    return 0;
+}
+
+int fail;
+
+void do_test(int num, int (*test)(void))
+{
+    int ret;
+
+    mtspr(DSISR, 0);
+    mtspr(DAR, 0);
+    unmap_all();
+    ml_printf("test %d:", num);
+    ret = test();
+    if (ret == 0) {
+        ml_printf("PASS\r\n");
+    } else {
+        fail = 1;
+        ml_printf("FAIL %d", ret);
+        if (num <= 10 || num == 19) {
+            ml_printf(" DAR=%lx DSISR=%lx", mfspr(DAR), mfspr(DSISR));
+        } else {
+            ml_printf(" SRR0=%lx SRR1=%lx", mfspr(SRR0), mfspr(SRR1));
+        }
+        ml_printf("\r\n");
+    }
+}
+
+int main(void)
+{
+    init_mmu();
+
+    do_test(1, mmu_test_1);
+    do_test(2, mmu_test_2);
+    do_test(3, mmu_test_3);
+    do_test(4, mmu_test_4);
+    do_test(5, mmu_test_5);
+    do_test(6, mmu_test_6);
+    do_test(7, mmu_test_7);
+    do_test(8, mmu_test_8);
+    do_test(9, mmu_test_9);
+    do_test(10, mmu_test_10);
+    do_test(11, mmu_test_11);
+    do_test(12, mmu_test_12);
+    do_test(13, mmu_test_13);
+    do_test(14, mmu_test_14);
+    do_test(15, mmu_test_15);
+    do_test(16, mmu_test_16);
+    do_test(17, mmu_test_17);
+
+    return fail;
+}
diff --git a/tests/tcg/ppc64/system/mmu.h b/tests/tcg/ppc64/system/mmu.h
new file mode 100644
index 0000000000..eb191e4bd0
--- /dev/null
+++ b/tests/tcg/ppc64/system/mmu.h
@@ -0,0 +1,9 @@
+#ifndef PPC64_MMU_H
+#define PPC64_MMU_H
+
+int test_read(long *addr, long *ret, long init);
+int test_write(long *addr, long val);
+int test_dcbz(long *addr);
+int test_exec(int testno, unsigned long pc, unsigned long msr);
+
+#endif
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 6/6] tests/tcg/ppc64: add rules to build PowerNV tests
  2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
                   ` (4 preceding siblings ...)
  2022-03-24 19:08 ` [RFC PATCH 5/6] tests/tcg/ppc64: add MMU test sources Leandro Lupori
@ 2022-03-24 19:08 ` Leandro Lupori
  2022-03-26 13:13 ` [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Richard Henderson
  6 siblings, 0 replies; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 19:08 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

Each Microwatt/PowerNV test use its own head.S file and thus needs
different build rules.

Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
---
 tests/tcg/ppc64/Makefile.softmmu-target | 33 +++++++++++++++++++------
 tests/tcg/ppc64/system/mmu-head.S       |  1 +
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target
index 511b6322df..47343d64aa 100644
--- a/tests/tcg/ppc64/Makefile.softmmu-target
+++ b/tests/tcg/ppc64/Makefile.softmmu-target
@@ -35,24 +35,43 @@ CFLAGS = -O -g -Wall -std=c99 -msoft-float -mno-vsx -mno-altivec \
          -I $(PPC64_SYSTEM_SRC)/include $(MINILIB_INC) \
          -mcpu=power8
 
+# Each Microwatt/PowerNV test use its own head.S file and thus needs
+# different rules.
+PPC64_PNV_TESTS = mmu
+PPC64_PNV_ELFS = $(addsuffix .elf,$(PPC64_PNV_TESTS))
+TESTS += $(PPC64_PNV_TESTS)
+
 # Leave the .elf files, to make debugging easier
 .PRECIOUS: $(CRT_OBJS) $(addsuffix .elf,$(TESTS))
 
-# Build CRT objects
+# Build CRT and test objects
 %.o: $(CRT_PATH)/%.S
 	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
 
+%.o: %.S
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
+
 %.o: $(CRT_PATH)/%.c
 	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
 
-# Build and link the tests
+%.o: %.c
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
+
+# Build .elf files for debugging
+%.elf: %.o $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LDFLAGS)
+
+$(PPC64_PNV_ELFS): %.elf: %-head.o %.o $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ $< $*.o $(LDFLAGS)
 
-# The .elf files are just for debugging
-%.elf: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+# Build test binaries
+%: %.o $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS) %.elf
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LDFLAGS) -Wl,--oformat=binary
 
-%: %.c %.elf $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) -Wl,--oformat=binary
+# NOTE: %-head.o replaces boot.o
+$(PPC64_PNV_TESTS): CRT_OBJS = console.o
+$(PPC64_PNV_TESTS): %: %-head.o %.o $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS) %.elf
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ $< $*.o $(LDFLAGS) -Wl,--oformat=binary
 
 memory: CFLAGS+=-DCHECK_UNALIGNED=1
 
diff --git a/tests/tcg/ppc64/system/mmu-head.S b/tests/tcg/ppc64/system/mmu-head.S
index b7fb99c379..a3f23fcb17 100644
--- a/tests/tcg/ppc64/system/mmu-head.S
+++ b/tests/tcg/ppc64/system/mmu-head.S
@@ -65,6 +65,7 @@ FUNCTION(test_exec)
 
 #define EXCEPTION(nr)        \
     .= nr                   ;\
+    li      %r3, (nr >> 4)  ;\
     attn
 
     /* DSI vector - skip the failing instruction + the next one */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests
  2022-03-24 19:08 ` [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests Leandro Lupori
@ 2022-03-24 20:34   ` Alex Bennée
  2022-03-24 21:11     ` Leandro Lupori
  0 siblings, 1 reply; 19+ messages in thread
From: Alex Bennée @ 2022-03-24 20:34 UTC (permalink / raw)
  To: Leandro Lupori
  Cc: danielhb413, richard.henderson, groug, qemu-devel, qemu-ppc, clg,
	pbonzini, david


Leandro Lupori <leandro.lupori@eldorado.org.br> writes:

> Adding a new, "virtual" TCG test target, ppc64le-softmmu, seems to
> be the cleanest way to support both BE and LE tests for
> ppc64-softmmu.
>
> Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
> ---
>  tests/Makefile.include                    |  7 ++++---
>  tests/tcg/configure.sh                    | 11 ++++++++++-
>  tests/tcg/ppc64/Makefile.softmmu-target   |  2 ++
>  tests/tcg/ppc64le/Makefile.softmmu-target |  7 +++++++
>  4 files changed, 23 insertions(+), 4 deletions(-)
>  create mode 100644 tests/tcg/ppc64le/Makefile.softmmu-target
>
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index e7153c8e91..4001fedbc3 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -40,9 +40,10 @@ SPEED = quick
>  TARGETS=$(patsubst libqemu-%.fa, %, $(filter libqemu-%.fa, $(ninja-targets)))
>  
>  # Per guest TCG tests
> -BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGETS))
> -CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TARGETS))
> -RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGETS))
> +TCG_TARGETS=$(patsubst tests/tcg/config-%.mak, %, $(wildcard tests/tcg/config-*.mak))
> +BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TCG_TARGETS))
> +CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TCG_TARGETS))
> +RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TCG_TARGETS))

I'm not following what is going on here. Are we creating a new target
type? Is this just to avoid duplication in tests/tcg subdirs?

>  
>  # Probe for the Docker Builds needed for each build
>  $(foreach PROBE_TARGET,$(TARGET_DIRS), 				\
> diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
> index ed4b5ccb1f..a4ac7a4e44 100755
> --- a/tests/tcg/configure.sh
> +++ b/tests/tcg/configure.sh
> @@ -80,6 +80,10 @@ fi
>  : ${cross_as_tricore="tricore-as"}
>  : ${cross_ld_tricore="tricore-ld"}
>  
> +# If target ppc64-softmmu is configured, also include the virtual test target
> +# ppc64le-softmmu
> +target_list=`echo $target_list | sed 's/ppc64-softmmu/& ppc64le-softmmu/'`
> +
>  for target in $target_list; do
>    arch=${target%%-*}
>  
> @@ -237,7 +241,12 @@ for target in $target_list; do
>        ;;
>      *-softmmu)
>        echo "CONFIG_SOFTMMU=y" >> $config_target_mak
> -      echo "QEMU=$PWD/qemu-system-$arch" >> $config_target_mak
> +      if test $arch = "ppc64le"; then
> +        sys_arch=ppc64
> +      else
> +        sys_arch=$arch
> +      fi
> +      echo "QEMU=$PWD/qemu-system-$sys_arch" >> $config_target_mak
>        ;;
>    esac
>  
> diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target
> index 8f9925ca5a..511b6322df 100644
> --- a/tests/tcg/ppc64/Makefile.softmmu-target
> +++ b/tests/tcg/ppc64/Makefile.softmmu-target
> @@ -2,6 +2,8 @@
>  # PowerPC64 system tests
>  #
>  
> +BIG_ENDIAN ?= 1
> +
>  # For now, disable tests that are failing
>  DISABLED_TESTS := memory
>  DISABLED_EXTRA_RUNS := run-gdbstub-memory
> diff --git a/tests/tcg/ppc64le/Makefile.softmmu-target b/tests/tcg/ppc64le/Makefile.softmmu-target
> new file mode 100644
> index 0000000000..d4162160ee
> --- /dev/null
> +++ b/tests/tcg/ppc64le/Makefile.softmmu-target
> @@ -0,0 +1,7 @@
> +#
> +# PowerPC64 LE system tests
> +#
> +
> +BIG_ENDIAN = 0
> +
> +include $(SRC_PATH)/tests/tcg/ppc64/Makefile.softmmu-target


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests
  2022-03-24 20:34   ` Alex Bennée
@ 2022-03-24 21:11     ` Leandro Lupori
  2022-03-25  9:50       ` Alex Bennée
  0 siblings, 1 reply; 19+ messages in thread
From: Leandro Lupori @ 2022-03-24 21:11 UTC (permalink / raw)
  To: Alex Bennée
  Cc: danielhb413, richard.henderson, groug, qemu-devel, qemu-ppc, clg,
	pbonzini, david

On 24/03/2022 17:34, Alex Bennée wrote:
> Leandro Lupori <leandro.lupori@eldorado.org.br> writes:
> 
>> Adding a new, "virtual" TCG test target, ppc64le-softmmu, seems to
>> be the cleanest way to support both BE and LE tests for
>> ppc64-softmmu.
>>
>> Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
>> ---
>>   tests/Makefile.include                    |  7 ++++---
>>   tests/tcg/configure.sh                    | 11 ++++++++++-
>>   tests/tcg/ppc64/Makefile.softmmu-target   |  2 ++
>>   tests/tcg/ppc64le/Makefile.softmmu-target |  7 +++++++
>>   4 files changed, 23 insertions(+), 4 deletions(-)
>>   create mode 100644 tests/tcg/ppc64le/Makefile.softmmu-target
>>
>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>> index e7153c8e91..4001fedbc3 100644
>> --- a/tests/Makefile.include
>> +++ b/tests/Makefile.include
>> @@ -40,9 +40,10 @@ SPEED = quick
>>   TARGETS=$(patsubst libqemu-%.fa, %, $(filter libqemu-%.fa, $(ninja-targets)))
>>
>>   # Per guest TCG tests
>> -BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGETS))
>> -CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TARGETS))
>> -RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGETS))
>> +TCG_TARGETS=$(patsubst tests/tcg/config-%.mak, %, $(wildcard tests/tcg/config-*.mak))
>> +BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TCG_TARGETS))
>> +CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TCG_TARGETS))
>> +RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TCG_TARGETS))
> 
> I'm not following what is going on here. Are we creating a new target
> type? Is this just to avoid duplication in tests/tcg subdirs?
> 
Yes, together with the change in test/tcg/configure.sh, a new 
ppc64le-softmmu target is created, in the context of TCG tests only.
But it isn't just to avoid duplication in tests/tcg subdirs.

Without a ppc64le-softmmu target, the tcg tests' makefiles will only 
include tests/tcg/ppc64/Makefile.softmmu-target file. They won't try to 
include tests/tcg/ppc64le/Makefile.softmmu-target, because there is no 
ppc64le-softmmu target.

I've actually tried to do everything in 
tests/tcg/ppc64/Makefile.softmmu-target. But when it is included, 
everything is already setup to build for ppc64 (BE), such as CC, 
EXTRA_CFLAGS and other variables. So it seems that, to be able to also 
build and run the same tests for ppc64le, I would need to somehow change 
CC, EXTRA_CFLAGS, etc, to setup them for a ppc64le build and write 
another set of rules for the LE tests. Then I would also need to handle 
output file conflicts, to be able have both BE and LE binaries 
coexisting in the same ppc64-softmmu output directory.

So that's why I've added this new target, only for TCG tests, to avoid 
the issues above.

>>
>>   # Probe for the Docker Builds needed for each build
>>   $(foreach PROBE_TARGET,$(TARGET_DIRS),                               \
>> diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
>> index ed4b5ccb1f..a4ac7a4e44 100755
>> --- a/tests/tcg/configure.sh
>> +++ b/tests/tcg/configure.sh
>> @@ -80,6 +80,10 @@ fi
>>   : ${cross_as_tricore="tricore-as"}
>>   : ${cross_ld_tricore="tricore-ld"}
>>
>> +# If target ppc64-softmmu is configured, also include the virtual test target
>> +# ppc64le-softmmu
>> +target_list=`echo $target_list | sed 's/ppc64-softmmu/& ppc64le-softmmu/'`
>> +
>>   for target in $target_list; do
>>     arch=${target%%-*}
>>
>> @@ -237,7 +241,12 @@ for target in $target_list; do
>>         ;;
>>       *-softmmu)
>>         echo "CONFIG_SOFTMMU=y" >> $config_target_mak
>> -      echo "QEMU=$PWD/qemu-system-$arch" >> $config_target_mak
>> +      if test $arch = "ppc64le"; then
>> +        sys_arch=ppc64
>> +      else
>> +        sys_arch=$arch
>> +      fi
>> +      echo "QEMU=$PWD/qemu-system-$sys_arch" >> $config_target_mak
>>         ;;
>>     esac
>>
>> diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target
>> index 8f9925ca5a..511b6322df 100644
>> --- a/tests/tcg/ppc64/Makefile.softmmu-target
>> +++ b/tests/tcg/ppc64/Makefile.softmmu-target
>> @@ -2,6 +2,8 @@
>>   # PowerPC64 system tests
>>   #
>>
>> +BIG_ENDIAN ?= 1
>> +
>>   # For now, disable tests that are failing
>>   DISABLED_TESTS := memory
>>   DISABLED_EXTRA_RUNS := run-gdbstub-memory
>> diff --git a/tests/tcg/ppc64le/Makefile.softmmu-target b/tests/tcg/ppc64le/Makefile.softmmu-target
>> new file mode 100644
>> index 0000000000..d4162160ee
>> --- /dev/null
>> +++ b/tests/tcg/ppc64le/Makefile.softmmu-target
>> @@ -0,0 +1,7 @@
>> +#
>> +# PowerPC64 LE system tests
>> +#
>> +
>> +BIG_ENDIAN = 0
>> +
>> +include $(SRC_PATH)/tests/tcg/ppc64/Makefile.softmmu-target
> 
> 
> --
> Alex Bennée



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests
  2022-03-24 21:11     ` Leandro Lupori
@ 2022-03-25  9:50       ` Alex Bennée
  2022-03-31 14:27         ` Leandro Lupori
  0 siblings, 1 reply; 19+ messages in thread
From: Alex Bennée @ 2022-03-25  9:50 UTC (permalink / raw)
  To: Leandro Lupori
  Cc: danielhb413, richard.henderson, groug, qemu-devel, qemu-ppc, clg,
	pbonzini, david


Leandro Lupori <leandro.lupori@eldorado.org.br> writes:

> On 24/03/2022 17:34, Alex Bennée wrote:
>> Leandro Lupori <leandro.lupori@eldorado.org.br> writes:
>> 
>>> Adding a new, "virtual" TCG test target, ppc64le-softmmu, seems to
>>> be the cleanest way to support both BE and LE tests for
>>> ppc64-softmmu.
>>>
>>> Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
>>> ---
>>>   tests/Makefile.include                    |  7 ++++---
>>>   tests/tcg/configure.sh                    | 11 ++++++++++-
>>>   tests/tcg/ppc64/Makefile.softmmu-target   |  2 ++
>>>   tests/tcg/ppc64le/Makefile.softmmu-target |  7 +++++++

Don't forget to add new files to MAINTAINERS by the way ;-)

>>>   4 files changed, 23 insertions(+), 4 deletions(-)
>>>   create mode 100644 tests/tcg/ppc64le/Makefile.softmmu-target
>>>
>>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>>> index e7153c8e91..4001fedbc3 100644
>>> --- a/tests/Makefile.include
>>> +++ b/tests/Makefile.include
>>> @@ -40,9 +40,10 @@ SPEED = quick
>>>   TARGETS=$(patsubst libqemu-%.fa, %, $(filter libqemu-%.fa, $(ninja-targets)))
>>>
>>>   # Per guest TCG tests
>>> -BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGETS))
>>> -CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TARGETS))
>>> -RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGETS))
>>> +TCG_TARGETS=$(patsubst tests/tcg/config-%.mak, %, $(wildcard tests/tcg/config-*.mak))
>>> +BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TCG_TARGETS))
>>> +CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TCG_TARGETS))
>>> +RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TCG_TARGETS))
>> I'm not following what is going on here. Are we creating a new
>> target
>> type? Is this just to avoid duplication in tests/tcg subdirs?
>> 
> Yes, together with the change in test/tcg/configure.sh, a new
> ppc64le-softmmu target is created, in the context of TCG tests only.
> But it isn't just to avoid duplication in tests/tcg subdirs.
>
> Without a ppc64le-softmmu target, the tcg tests' makefiles will only
> include tests/tcg/ppc64/Makefile.softmmu-target file. They won't try
> to include tests/tcg/ppc64le/Makefile.softmmu-target, because there is
> no ppc64le-softmmu target.

So according to IRC this is because the ppc64-softmmu target can support
dynamically switching between BE/LE modes so there is only needs to be
one 64 bit ppc system binary.

> I've actually tried to do everything in
> tests/tcg/ppc64/Makefile.softmmu-target. But when it is included,
> everything is already setup to build for ppc64 (BE), such as CC,
> EXTRA_CFLAGS and other variables. So it seems that, to be able to also
> build and run the same tests for ppc64le, I would need to somehow
> change CC, EXTRA_CFLAGS, etc, to setup them for a ppc64le build and
> write another set of rules for the LE tests. Then I would also need to
> handle output file conflicts, to be able have both BE and LE binaries
> coexisting in the same ppc64-softmmu output directory.

There is another approach you can take which is to generate alternative
binaries from the same sources in the build. For example we build the
sha512 test with a couple of different compiler options and run with
slightly different QEMU_OPTS:

  sha512-vector: CFLAGS +=-mcpu=power10 -O3
  sha512-vector: sha512.c
          $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)

  run-sha512-vector: QEMU_OPTS+=-cpu POWER10
  run-plugin-sha512-vector-with-%: QEMU_OPTS+=-cpu POWER10

  PPC64LE_TESTS += sha512-vector

So you could do something similar for le versions of the tests.

I'm ambivalent to which makes the best approach. I only worry the
"pseudo target" approach might break something else down the line.
However as long as the ppc maintainers are happy with the tests you can
have my:

Acked-by: Alex Bennée <alex.bennee@linaro.org>

for the check-tcg plumbing changes.

>
> So that's why I've added this new target, only for TCG tests, to avoid
> the issues above.
>
>>>
>>>   # Probe for the Docker Builds needed for each build
>>>   $(foreach PROBE_TARGET,$(TARGET_DIRS),                               \
>>> diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
>>> index ed4b5ccb1f..a4ac7a4e44 100755
>>> --- a/tests/tcg/configure.sh
>>> +++ b/tests/tcg/configure.sh
>>> @@ -80,6 +80,10 @@ fi
>>>   : ${cross_as_tricore="tricore-as"}
>>>   : ${cross_ld_tricore="tricore-ld"}
>>>
>>> +# If target ppc64-softmmu is configured, also include the virtual test target
>>> +# ppc64le-softmmu
>>> +target_list=`echo $target_list | sed 's/ppc64-softmmu/& ppc64le-softmmu/'`
>>> +
>>>   for target in $target_list; do
>>>     arch=${target%%-*}
>>>
>>> @@ -237,7 +241,12 @@ for target in $target_list; do
>>>         ;;
>>>       *-softmmu)
>>>         echo "CONFIG_SOFTMMU=y" >> $config_target_mak
>>> -      echo "QEMU=$PWD/qemu-system-$arch" >> $config_target_mak
>>> +      if test $arch = "ppc64le"; then
>>> +        sys_arch=ppc64
>>> +      else
>>> +        sys_arch=$arch
>>> +      fi
>>> +      echo "QEMU=$PWD/qemu-system-$sys_arch" >> $config_target_mak
>>>         ;;
>>>     esac
>>>
>>> diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target
>>> index 8f9925ca5a..511b6322df 100644
>>> --- a/tests/tcg/ppc64/Makefile.softmmu-target
>>> +++ b/tests/tcg/ppc64/Makefile.softmmu-target
>>> @@ -2,6 +2,8 @@
>>>   # PowerPC64 system tests
>>>   #
>>>
>>> +BIG_ENDIAN ?= 1
>>> +
>>>   # For now, disable tests that are failing
>>>   DISABLED_TESTS := memory
>>>   DISABLED_EXTRA_RUNS := run-gdbstub-memory
>>> diff --git a/tests/tcg/ppc64le/Makefile.softmmu-target b/tests/tcg/ppc64le/Makefile.softmmu-target
>>> new file mode 100644
>>> index 0000000000..d4162160ee
>>> --- /dev/null
>>> +++ b/tests/tcg/ppc64le/Makefile.softmmu-target
>>> @@ -0,0 +1,7 @@
>>> +#
>>> +# PowerPC64 LE system tests
>>> +#
>>> +
>>> +BIG_ENDIAN = 0
>>> +
>>> +include $(SRC_PATH)/tests/tcg/ppc64/Makefile.softmmu-target
>> --
>> Alex Bennée


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction
  2022-03-24 19:08 ` [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction Leandro Lupori
@ 2022-03-25 15:11   ` Fabiano Rosas
  2022-03-26  3:15     ` David Gibson
  2022-03-26 13:04   ` Richard Henderson
  1 sibling, 1 reply; 19+ messages in thread
From: Fabiano Rosas @ 2022-03-25 15:11 UTC (permalink / raw)
  To: Leandro Lupori, qemu-devel, qemu-ppc
  Cc: Leandro Lupori, danielhb413, richard.henderson, groug, clg,
	pbonzini, alex.bennee, david

Leandro Lupori <leandro.lupori@eldorado.org.br> writes:

> From: Cédric Le Goater <clg@kaod.org>
>
> Check the HID0 bit to send signal, currently modeled as a checkstop.
> The QEMU implementation adds an exit using the GPR[3] value (that's a
> hack for tests)
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
> ---
>  target/ppc/cpu.h         |  8 ++++++++
>  target/ppc/excp_helper.c | 27 +++++++++++++++++++++++++++
>  target/ppc/helper.h      |  1 +
>  target/ppc/translate.c   | 14 ++++++++++++++
>  4 files changed, 50 insertions(+)
>
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 047b24ba50..12f9f3a880 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -173,6 +173,12 @@ enum {
>      POWERPC_EXCP_PRIV_REG      = 0x02,  /* Privileged register exception     */
>      /* Trap                                                                  */
>      POWERPC_EXCP_TRAP          = 0x40,
> +    /* Processor Attention                                                   */
> +    POWERPC_EXCP_ATTN          = 0x100,
> +    /*
> +     * NOTE: POWERPC_EXCP_ATTN uses values from 0x100 to 0x1ff to return
> +     *       error codes.
> +     */
>  };
>  
>  #define PPC_INPUT(env) ((env)->bus_model)
> @@ -2089,6 +2095,8 @@ void ppc_compat_add_property(Object *obj, const char *name,
>  #define HID0_DOZE           (1 << 23)           /* pre-2.06 */
>  #define HID0_NAP            (1 << 22)           /* pre-2.06 */
>  #define HID0_HILE           PPC_BIT(19) /* POWER8 */
> +#define HID0_ATTN           PPC_BIT(31) /* Processor Attention */
> +#define HID0_POWER9_ATTN    PPC_BIT(3)
>  #define HID0_POWER9_HILE    PPC_BIT(4)
>  
>  /*****************************************************************************/
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index d3e2cfcd71..b0c629905c 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -1379,6 +1379,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
>              }
>              cs->halted = 1;
>              cpu_interrupt_exittb(cs);
> +            if ((env->error_code & ~0xff) == POWERPC_EXCP_ATTN) {
> +                exit(env->error_code & 0xff);
> +            }
>          }
>          if (env->msr_mask & MSR_HVB) {
>              /*
> @@ -1971,6 +1974,30 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
>      env->resume_as_sreset = (insn != PPC_PM_STOP) ||
>          (env->spr[SPR_PSSCR] & PSSCR_EC);
>  }
> +
> +/*
> + * Processor Attention instruction (Implementation dependent)
> + */
> +void helper_attn(CPUPPCState *env, target_ulong r3)
> +{
> +    bool attn = false;
> +
> +    if (env->excp_model == POWERPC_EXCP_POWER8) {
> +        attn = !!(env->spr[SPR_HID0] & HID0_ATTN);
> +    } else if (env->excp_model == POWERPC_EXCP_POWER9 ||
> +               env->excp_model == POWERPC_EXCP_POWER10) {
> +        attn = !!(env->spr[SPR_HID0] & HID0_POWER9_ATTN);
> +    }

The excp_model is not a CPU identifier. This should ideally be a flag
set during init_proc. Something like HID0_ATTN_P8/HID0_ATTN_P9.

Maybe we should consider adding a hid0_mask similar to lpcr_mask.

> +
> +    if (attn) {
> +        raise_exception_err(env, POWERPC_EXCP_MCHECK,
> +                            POWERPC_EXCP_ATTN | (r3 & 0xff));
> +    } else {
> +        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +                               POWERPC_EXCP_INVAL |
> +                               POWERPC_EXCP_INVAL_INVAL, GETPC());
> +    }
> +}
>  #endif /* defined(TARGET_PPC64) */
>  
>  static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index 57da11c77e..9a2497569b 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -14,6 +14,7 @@ DEF_HELPER_1(rfmci, void, env)
>  #if defined(TARGET_PPC64)
>  DEF_HELPER_2(scv, noreturn, env, i32)
>  DEF_HELPER_2(pminsn, void, env, i32)
> +DEF_HELPER_2(attn, void, env, tl)
>  DEF_HELPER_1(rfid, void, env)
>  DEF_HELPER_1(rfscv, void, env)
>  DEF_HELPER_1(hrfid, void, env)
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 408ae26173..5ace6f3a29 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -4123,6 +4123,19 @@ static void gen_rvwinkle(DisasContext *ctx)
>      gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
>  #endif /* defined(CONFIG_USER_ONLY) */
>  }
> +
> +static void gen_attn(DisasContext *ctx)
> +{
> + #if defined(CONFIG_USER_ONLY)
> +    GEN_PRIV;
> +#else
> +    CHK_SV;
> +
> +    gen_helper_attn(cpu_env, cpu_gpr[3]);
> +    ctx->base.is_jmp = DISAS_NORETURN;
> +#endif
> +}
> +
>  #endif /* #if defined(TARGET_PPC64) */
>  
>  static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
> @@ -6844,6 +6857,7 @@ GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
>  GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
>  GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
>  GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
> +GEN_HANDLER(attn, 0x0, 0x00, 0x8, 0xfffffdff, PPC_FLOW),
>  #endif
>  /* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
>  GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW),


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction
  2022-03-25 15:11   ` Fabiano Rosas
@ 2022-03-26  3:15     ` David Gibson
  0 siblings, 0 replies; 19+ messages in thread
From: David Gibson @ 2022-03-26  3:15 UTC (permalink / raw)
  To: Fabiano Rosas
  Cc: Leandro Lupori, danielhb413, richard.henderson, qemu-devel,
	groug, qemu-ppc, clg, pbonzini, alex.bennee

[-- Attachment #1: Type: text/plain, Size: 4018 bytes --]

On Fri, Mar 25, 2022 at 12:11:47PM -0300, Fabiano Rosas wrote:
> Leandro Lupori <leandro.lupori@eldorado.org.br> writes:
> 
> > From: Cédric Le Goater <clg@kaod.org>
> >
> > Check the HID0 bit to send signal, currently modeled as a checkstop.
> > The QEMU implementation adds an exit using the GPR[3] value (that's a
> > hack for tests)
> >
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
> > ---
> >  target/ppc/cpu.h         |  8 ++++++++
> >  target/ppc/excp_helper.c | 27 +++++++++++++++++++++++++++
> >  target/ppc/helper.h      |  1 +
> >  target/ppc/translate.c   | 14 ++++++++++++++
> >  4 files changed, 50 insertions(+)
> >
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index 047b24ba50..12f9f3a880 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -173,6 +173,12 @@ enum {
> >      POWERPC_EXCP_PRIV_REG      = 0x02,  /* Privileged register exception     */
> >      /* Trap                                                                  */
> >      POWERPC_EXCP_TRAP          = 0x40,
> > +    /* Processor Attention                                                   */
> > +    POWERPC_EXCP_ATTN          = 0x100,
> > +    /*
> > +     * NOTE: POWERPC_EXCP_ATTN uses values from 0x100 to 0x1ff to return
> > +     *       error codes.
> > +     */
> >  };
> >  
> >  #define PPC_INPUT(env) ((env)->bus_model)
> > @@ -2089,6 +2095,8 @@ void ppc_compat_add_property(Object *obj, const char *name,
> >  #define HID0_DOZE           (1 << 23)           /* pre-2.06 */
> >  #define HID0_NAP            (1 << 22)           /* pre-2.06 */
> >  #define HID0_HILE           PPC_BIT(19) /* POWER8 */
> > +#define HID0_ATTN           PPC_BIT(31) /* Processor Attention */
> > +#define HID0_POWER9_ATTN    PPC_BIT(3)
> >  #define HID0_POWER9_HILE    PPC_BIT(4)
> >  
> >  /*****************************************************************************/
> > diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> > index d3e2cfcd71..b0c629905c 100644
> > --- a/target/ppc/excp_helper.c
> > +++ b/target/ppc/excp_helper.c
> > @@ -1379,6 +1379,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
> >              }
> >              cs->halted = 1;
> >              cpu_interrupt_exittb(cs);
> > +            if ((env->error_code & ~0xff) == POWERPC_EXCP_ATTN) {
> > +                exit(env->error_code & 0xff);
> > +            }
> >          }
> >          if (env->msr_mask & MSR_HVB) {
> >              /*
> > @@ -1971,6 +1974,30 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
> >      env->resume_as_sreset = (insn != PPC_PM_STOP) ||
> >          (env->spr[SPR_PSSCR] & PSSCR_EC);
> >  }
> > +
> > +/*
> > + * Processor Attention instruction (Implementation dependent)
> > + */
> > +void helper_attn(CPUPPCState *env, target_ulong r3)
> > +{
> > +    bool attn = false;
> > +
> > +    if (env->excp_model == POWERPC_EXCP_POWER8) {
> > +        attn = !!(env->spr[SPR_HID0] & HID0_ATTN);
> > +    } else if (env->excp_model == POWERPC_EXCP_POWER9 ||
> > +               env->excp_model == POWERPC_EXCP_POWER10) {
> > +        attn = !!(env->spr[SPR_HID0] & HID0_POWER9_ATTN);
> > +    }
> 
> The excp_model is not a CPU identifier. This should ideally be a flag
> set during init_proc. Something like HID0_ATTN_P8/HID0_ATTN_P9.
> 
> Maybe we should consider adding a hid0_mask similar to lpcr_mask.

I don't think that's a good idea.  By definition, the meaning of the
HID registers is model specific - having a hid0_mask would imply it
always has the same meaning, just different bits that are present or
not.  I think you want to explicitly dispath to cpu family specific
functions for this.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction
  2022-03-24 19:08 ` [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction Leandro Lupori
  2022-03-25 15:11   ` Fabiano Rosas
@ 2022-03-26 13:04   ` Richard Henderson
  2022-03-28 15:46     ` Cédric Le Goater
  1 sibling, 1 reply; 19+ messages in thread
From: Richard Henderson @ 2022-03-26 13:04 UTC (permalink / raw)
  To: Leandro Lupori, qemu-devel, qemu-ppc
  Cc: danielhb413, groug, clg, pbonzini, alex.bennee, david

On 3/24/22 13:08, Leandro Lupori wrote:
> +    /* Processor Attention                                                   */
> +    POWERPC_EXCP_ATTN          = 0x100,
> +    /*
> +     * NOTE: POWERPC_EXCP_ATTN uses values from 0x100 to 0x1ff to return
> +     *       error codes.
> +     */

As used below, this is not an exception -- the exception is POWERPC_EXCP_MCHECK.  This is 
something else, for env->error_code.  You could probably come up with a better name, but 
see below.

> +            if ((env->error_code & ~0xff) == POWERPC_EXCP_ATTN) {
> +                exit(env->error_code & 0xff);
> +            }

This will want gdb_exit(value) as well; see e.g. semihosting/arm-compat-semi.c.

In this and the next patch, I do not see anything that makes support for attn conditional, 
and importantly, off by default.  Otherwise this seems to have the potential for denial of 
service.

> +void helper_attn(CPUPPCState *env, target_ulong r3)
> +{
> +    bool attn = false;
> +
> +    if (env->excp_model == POWERPC_EXCP_POWER8) {
> +        attn = !!(env->spr[SPR_HID0] & HID0_ATTN);
> +    } else if (env->excp_model == POWERPC_EXCP_POWER9 ||
> +               env->excp_model == POWERPC_EXCP_POWER10) {
> +        attn = !!(env->spr[SPR_HID0] & HID0_POWER9_ATTN);
> +    }
> +
> +    if (attn) {
> +        raise_exception_err(env, POWERPC_EXCP_MCHECK,
> +                            POWERPC_EXCP_ATTN | (r3 & 0xff));
> +    } else {
> +        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +                               POWERPC_EXCP_INVAL |
> +                               POWERPC_EXCP_INVAL_INVAL, GETPC());
> +    }
> +}

Why did you decide to raise an exception instead of exiting right here?

I suggest syncing env state before calling the helper, so that you don't need to unwind 
here, and so that state is up-to-date for the debugger before exiting.

> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 408ae26173..5ace6f3a29 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -4123,6 +4123,19 @@ static void gen_rvwinkle(DisasContext *ctx)
>       gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
>   #endif /* defined(CONFIG_USER_ONLY) */
>   }
> +
> +static void gen_attn(DisasContext *ctx)
> +{
> + #if defined(CONFIG_USER_ONLY)
> +    GEN_PRIV;
> +#else
> +    CHK_SV;
> +
> +    gen_helper_attn(cpu_env, cpu_gpr[3]);
> +    ctx->base.is_jmp = DISAS_NORETURN;
> +#endif
> +}

You want gen_update_nip(ctx, ctx->cia) in there, like gen_exception_err.


> +GEN_HANDLER(attn, 0x0, 0x00, 0x8, 0xfffffdff, PPC_FLOW),

New insns into insns32.decode, I would expect.


r~


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU
  2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
                   ` (5 preceding siblings ...)
  2022-03-24 19:08 ` [RFC PATCH 6/6] tests/tcg/ppc64: add rules to build PowerNV tests Leandro Lupori
@ 2022-03-26 13:13 ` Richard Henderson
  2022-03-28 14:54   ` Fabiano Rosas
  2022-03-28 16:24   ` Cédric Le Goater
  6 siblings, 2 replies; 19+ messages in thread
From: Richard Henderson @ 2022-03-26 13:13 UTC (permalink / raw)
  To: Leandro Lupori, qemu-devel, qemu-ppc
  Cc: danielhb413, groug, clg, pbonzini, alex.bennee, david

On 3/24/22 13:08, Leandro Lupori wrote:
> To be able to finish the test and return an exit code to the
> calling process, the Processor Attention instruction is used.
> As its behavior is implementation dependent, in QEMU PowerNV
> it just calls exit with GPR[3] value, truncated to an uint8_t.

I think you're simply thinking too small here, and should consider using the attn 
instruction to implement a full -semihosting interface.  You might as well join arm and 
riscv with CONFIG_ARM_COMPATIBLE_SEMIHOSTING.


r~


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU
  2022-03-26 13:13 ` [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Richard Henderson
@ 2022-03-28 14:54   ` Fabiano Rosas
  2022-03-28 14:59     ` Richard Henderson
  2022-03-28 16:24   ` Cédric Le Goater
  1 sibling, 1 reply; 19+ messages in thread
From: Fabiano Rosas @ 2022-03-28 14:54 UTC (permalink / raw)
  To: Richard Henderson, Leandro Lupori, qemu-devel, qemu-ppc
  Cc: danielhb413, groug, clg, pbonzini, alex.bennee, david

Richard Henderson <richard.henderson@linaro.org> writes:

> On 3/24/22 13:08, Leandro Lupori wrote:
>> To be able to finish the test and return an exit code to the
>> calling process, the Processor Attention instruction is used.
>> As its behavior is implementation dependent, in QEMU PowerNV
>> it just calls exit with GPR[3] value, truncated to an uint8_t.
>
> I think you're simply thinking too small here, and should consider using the attn 
> instruction to implement a full -semihosting interface.  You might as well join arm and 
> riscv with CONFIG_ARM_COMPATIBLE_SEMIHOSTING.

I can't reach the semihosting docs at:
https://static.docs.arm.com/100863/0200/semihosting.pdf

Do we need to replace that URL with something else?

>
>
> r~


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU
  2022-03-28 14:54   ` Fabiano Rosas
@ 2022-03-28 14:59     ` Richard Henderson
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Henderson @ 2022-03-28 14:59 UTC (permalink / raw)
  To: Fabiano Rosas, Leandro Lupori, qemu-devel, qemu-ppc
  Cc: danielhb413, groug, clg, pbonzini, alex.bennee, david

On 3/28/22 08:54, Fabiano Rosas wrote:
> I can't reach the semihosting docs at:
> https://static.docs.arm.com/100863/0200/semihosting.pdf
> 
> Do we need to replace that URL with something else?

It has been moved to

https://developer.arm.com/documentation/100863/latest


r~


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction
  2022-03-26 13:04   ` Richard Henderson
@ 2022-03-28 15:46     ` Cédric Le Goater
  0 siblings, 0 replies; 19+ messages in thread
From: Cédric Le Goater @ 2022-03-28 15:46 UTC (permalink / raw)
  To: Richard Henderson, Leandro Lupori, qemu-devel, qemu-ppc
  Cc: pbonzini, danielhb413, alex.bennee, groug, david

On 3/26/22 14:04, Richard Henderson wrote:
> On 3/24/22 13:08, Leandro Lupori wrote:
>> +    /* Processor Attention                                                   */
>> +    POWERPC_EXCP_ATTN          = 0x100,
>> +    /*
>> +     * NOTE: POWERPC_EXCP_ATTN uses values from 0x100 to 0x1ff to return
>> +     *       error codes.
>> +     */
> 
> As used below, this is not an exception -- the exception is POWERPC_EXCP_MCHECK.  This is something else, for env->error_code.  

Yes. I hacked my way through.

> You could probably come up with a better name, but see below.
> 
>> +            if ((env->error_code & ~0xff) == POWERPC_EXCP_ATTN) {
>> +                exit(env->error_code & 0xff);
>> +            }
> 
> This will want gdb_exit(value) as well; see e.g. semihosting/arm-compat-semi.c.
> 
> In this and the next patch, I do not see anything that makes support for attn conditional, and importantly, off by default.  Otherwise this seems to have the potential for denial of service.

Indeed.

>> +void helper_attn(CPUPPCState *env, target_ulong r3)
>> +{
>> +    bool attn = false;
>> +
>> +    if (env->excp_model == POWERPC_EXCP_POWER8) {
>> +        attn = !!(env->spr[SPR_HID0] & HID0_ATTN);
>> +    } else if (env->excp_model == POWERPC_EXCP_POWER9 ||
>> +               env->excp_model == POWERPC_EXCP_POWER10) {
>> +        attn = !!(env->spr[SPR_HID0] & HID0_POWER9_ATTN);
>> +    }
>> +
>> +    if (attn) {
>> +        raise_exception_err(env, POWERPC_EXCP_MCHECK,
>> +                            POWERPC_EXCP_ATTN | (r3 & 0xff));
>> +    } else {
>> +        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
>> +                               POWERPC_EXCP_INVAL |
>> +                               POWERPC_EXCP_INVAL_INVAL, GETPC());
>> +    }
>> +}
> 
> Why did you decide to raise an exception instead of exiting right here?

attn quiesce the thread/core but it can generate an 'host attn'
interrupt event for the service processor, it behaves like a
checkstop.

I think my idea was to raise an interrupt in the instruction model,
and then from the exception model, reach the machine through some
QOM Interface to take action. pSeries would do nothing or exit
depending on some machine option, PowerNV could raise a PSI IRQ
line to signal the embedded BMC simulator to do poweroff

I took a shortcut and introduced an exit() call when I saw the
complexity increase.

But really, the need in this series is to be able to exit from
QEMU after some test has run.
   
> 
> I suggest syncing env state before calling the helper, so that you don't need to unwind here, and so that state is up-to-date for the debugger before exiting.

ok.

>> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
>> index 408ae26173..5ace6f3a29 100644
>> --- a/target/ppc/translate.c
>> +++ b/target/ppc/translate.c
>> @@ -4123,6 +4123,19 @@ static void gen_rvwinkle(DisasContext *ctx)
>>       gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
>>   #endif /* defined(CONFIG_USER_ONLY) */
>>   }
>> +
>> +static void gen_attn(DisasContext *ctx)
>> +{
>> + #if defined(CONFIG_USER_ONLY)
>> +    GEN_PRIV;
>> +#else
>> +    CHK_SV;
>> +
>> +    gen_helper_attn(cpu_env, cpu_gpr[3]);
>> +    ctx->base.is_jmp = DISAS_NORETURN;
>> +#endif
>> +}
> 
> You want gen_update_nip(ctx, ctx->cia) in there, like gen_exception_err.
> 
> 
>> +GEN_HANDLER(attn, 0x0, 0x00, 0x8, 0xfffffdff, PPC_FLOW),
> 
> New insns into insns32.decode, I would expect.
> 

Thanks,

C.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU
  2022-03-26 13:13 ` [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Richard Henderson
  2022-03-28 14:54   ` Fabiano Rosas
@ 2022-03-28 16:24   ` Cédric Le Goater
  1 sibling, 0 replies; 19+ messages in thread
From: Cédric Le Goater @ 2022-03-28 16:24 UTC (permalink / raw)
  To: Richard Henderson, Leandro Lupori, qemu-devel, qemu-ppc
  Cc: pbonzini, danielhb413, alex.bennee, groug, david

On 3/26/22 14:13, Richard Henderson wrote:
> On 3/24/22 13:08, Leandro Lupori wrote:
>> To be able to finish the test and return an exit code to the
>> calling process, the Processor Attention instruction is used.
>> As its behavior is implementation dependent, in QEMU PowerNV
>> it just calls exit with GPR[3] value, truncated to an uint8_t.
> 
> I think you're simply thinking too small here, and should consider using the attn instruction to implement a full -semihosting interface.  You might as well join arm and riscv with CONFIG_ARM_COMPATIBLE_SEMIHOSTING.

yes. This looks like a good interface. We need an instruction
to generate the semihosting calls.

Thanks,

C.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests
  2022-03-25  9:50       ` Alex Bennée
@ 2022-03-31 14:27         ` Leandro Lupori
  0 siblings, 0 replies; 19+ messages in thread
From: Leandro Lupori @ 2022-03-31 14:27 UTC (permalink / raw)
  To: Alex Bennée
  Cc: danielhb413, richard.henderson, groug, qemu-devel, qemu-ppc, clg,
	pbonzini, david

On 3/25/22 06:50, Alex Bennée wrote:

> Leandro Lupori <leandro.lupori@eldorado.org.br> writes:
> 
>> On 24/03/2022 17:34, Alex Bennée wrote:
>>> Leandro Lupori <leandro.lupori@eldorado.org.br> writes:
>>>
>>>> Adding a new, "virtual" TCG test target, ppc64le-softmmu, seems to
>>>> be the cleanest way to support both BE and LE tests for
>>>> ppc64-softmmu.
>>>>
>>>> Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
>>>> ---
>>>>    tests/Makefile.include                    |  7 ++++---
>>>>    tests/tcg/configure.sh                    | 11 ++++++++++-
>>>>    tests/tcg/ppc64/Makefile.softmmu-target   |  2 ++
>>>>    tests/tcg/ppc64le/Makefile.softmmu-target |  7 +++++++
> 
> Don't forget to add new files to MAINTAINERS by the way ;-)

Right.

> 
>>>>    4 files changed, 23 insertions(+), 4 deletions(-)
>>>>    create mode 100644 tests/tcg/ppc64le/Makefile.softmmu-target
>>>>
>>>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>>>> index e7153c8e91..4001fedbc3 100644
>>>> --- a/tests/Makefile.include
>>>> +++ b/tests/Makefile.include
>>>> @@ -40,9 +40,10 @@ SPEED = quick
>>>>    TARGETS=$(patsubst libqemu-%.fa, %, $(filter libqemu-%.fa, $(ninja-targets)))
>>>>
>>>>    # Per guest TCG tests
>>>> -BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGETS))
>>>> -CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TARGETS))
>>>> -RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGETS))
>>>> +TCG_TARGETS=$(patsubst tests/tcg/config-%.mak, %, $(wildcard tests/tcg/config-*.mak))
>>>> +BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TCG_TARGETS))
>>>> +CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TCG_TARGETS))
>>>> +RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TCG_TARGETS))
>>> I'm not following what is going on here. Are we creating a new
>>> target
>>> type? Is this just to avoid duplication in tests/tcg subdirs?
>>>
>> Yes, together with the change in test/tcg/configure.sh, a new
>> ppc64le-softmmu target is created, in the context of TCG tests only.
>> But it isn't just to avoid duplication in tests/tcg subdirs.
>>
>> Without a ppc64le-softmmu target, the tcg tests' makefiles will only
>> include tests/tcg/ppc64/Makefile.softmmu-target file. They won't try
>> to include tests/tcg/ppc64le/Makefile.softmmu-target, because there is
>> no ppc64le-softmmu target.
> 
> So according to IRC this is because the ppc64-softmmu target can support
> dynamically switching between BE/LE modes so there is only needs to be
> one 64 bit ppc system binary.
> 
>> I've actually tried to do everything in
>> tests/tcg/ppc64/Makefile.softmmu-target. But when it is included,
>> everything is already setup to build for ppc64 (BE), such as CC,
>> EXTRA_CFLAGS and other variables. So it seems that, to be able to also
>> build and run the same tests for ppc64le, I would need to somehow
>> change CC, EXTRA_CFLAGS, etc, to setup them for a ppc64le build and
>> write another set of rules for the LE tests. Then I would also need to
>> handle output file conflicts, to be able have both BE and LE binaries
>> coexisting in the same ppc64-softmmu output directory.
> 
> There is another approach you can take which is to generate alternative
> binaries from the same sources in the build. For example we build the
> sha512 test with a couple of different compiler options and run with
> slightly different QEMU_OPTS:
> 
>    sha512-vector: CFLAGS +=-mcpu=power10 -O3
>    sha512-vector: sha512.c
>            $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
> 
>    run-sha512-vector: QEMU_OPTS+=-cpu POWER10
>    run-plugin-sha512-vector-with-%: QEMU_OPTS+=-cpu POWER10
> 
>    PPC64LE_TESTS += sha512-vector
> 
> So you could do something similar for le versions of the tests.
> > I'm ambivalent to which makes the best approach. I only worry the
> "pseudo target" approach might break something else down the line.
> However as long as the ppc maintainers are happy with the tests you can
> have my:
> 
> Acked-by: Alex Bennée <alex.bennee@linaro.org>
> 
> for the check-tcg plumbing changes.
> 

Ok, this approach worked too. It ended up being a bit more complex, 
mainly because LE versions of CRT and MINILIB objects must be used, but 
it should be ok, if it helps to avoid breaking something else.
I'll send a V2 with this new approach.

Thanks,
Leandro


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2022-03-31 14:54 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-24 19:08 [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Leandro Lupori
2022-03-24 19:08 ` [RFC PATCH 1/6] target/ppc: Add support for the Processor Attention instruction Leandro Lupori
2022-03-25 15:11   ` Fabiano Rosas
2022-03-26  3:15     ` David Gibson
2022-03-26 13:04   ` Richard Henderson
2022-03-28 15:46     ` Cédric Le Goater
2022-03-24 19:08 ` [RFC PATCH 2/6] ppc/pnv: Activate " Leandro Lupori
2022-03-24 19:08 ` [RFC PATCH 3/6] tests/tcg/ppc64: add basic softmmu test support Leandro Lupori
2022-03-24 19:08 ` [RFC PATCH 4/6] tests/tcg: add support for ppc64le softmmu tests Leandro Lupori
2022-03-24 20:34   ` Alex Bennée
2022-03-24 21:11     ` Leandro Lupori
2022-03-25  9:50       ` Alex Bennée
2022-03-31 14:27         ` Leandro Lupori
2022-03-24 19:08 ` [RFC PATCH 5/6] tests/tcg/ppc64: add MMU test sources Leandro Lupori
2022-03-24 19:08 ` [RFC PATCH 6/6] tests/tcg/ppc64: add rules to build PowerNV tests Leandro Lupori
2022-03-26 13:13 ` [RFC PATCH 0/6] Port PPC64/PowerNV MMU tests to QEMU Richard Henderson
2022-03-28 14:54   ` Fabiano Rosas
2022-03-28 14:59     ` Richard Henderson
2022-03-28 16:24   ` Cédric Le Goater

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.