All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v2 0/5] Check emulation
@ 2016-03-21 11:33 ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

This series adds exception handler to be able to test instruction
emulation. We test then invalid instruction, lswx instruction, and
check that lswx instruction triggers an alignment interrupt in
little-endian mode. During the development of this series, I've seen
that processor is not running in 64bit mode, so I've added a test
to check that is the case now.

This has been tested with KVM PR, HV, TCG in big and little-endian mode.

KVM-PR needs a fix to be able to manage correctly invalid instruction.
    http://patchwork.ozlabs.org/patch/597855/

QEMU needs a fix to initialize correctly the 64bit mode:
    http://patchwork.ozlabs.org/patch/598198/

With TCG, some lswx tests fail because it needs some fixes... I'm working
on this.

v2: 
    clearly restore r1 in call_handler
    use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"
    check program check type (invalid instruction)
    add "-v" parameter to display invalid instruction address
    use "mtxer" instead of "mtspr"
    Fix comments in lswx asm()
    add "memory" in clobber list
    add Thomas' Rb on patches 3 and 5.

Laurent Vivier (5):
  powerpc: add exception handler
  powerpc: add test to check invalid instruction trap
  powerpc: check 64bit mode
  powerpc: check lswx
  powerpc: Check lswx in little-endian mode.

 lib/powerpc/asm/hcall.h     |   1 +
 lib/powerpc/asm/ppc_asm.h   |   5 +
 lib/powerpc/asm/processor.h |  11 ++
 lib/powerpc/processor.c     |  38 +++++++
 lib/powerpc/setup.c         |  19 ++++
 lib/ppc64/asm-offsets.c     |  42 ++++++++
 lib/ppc64/asm/processor.h   |   1 +
 lib/ppc64/asm/ptrace.h      |  24 +++++
 powerpc/Makefile.common     |   6 +-
 powerpc/cstart64.S          | 140 +++++++++++++++++++++++++
 powerpc/emulator.c          | 241 ++++++++++++++++++++++++++++++++++++++++++++
 powerpc/unittests.cfg       |   3 +
 12 files changed, 530 insertions(+), 1 deletion(-)
 create mode 100644 lib/powerpc/asm/processor.h
 create mode 100644 lib/powerpc/processor.c
 create mode 100644 lib/ppc64/asm/processor.h
 create mode 100644 lib/ppc64/asm/ptrace.h
 create mode 100644 powerpc/emulator.c

-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 0/5] Check emulation
@ 2016-03-21 11:33 ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

This series adds exception handler to be able to test instruction
emulation. We test then invalid instruction, lswx instruction, and
check that lswx instruction triggers an alignment interrupt in
little-endian mode. During the development of this series, I've seen
that processor is not running in 64bit mode, so I've added a test
to check that is the case now.

This has been tested with KVM PR, HV, TCG in big and little-endian mode.

KVM-PR needs a fix to be able to manage correctly invalid instruction.
    http://patchwork.ozlabs.org/patch/597855/

QEMU needs a fix to initialize correctly the 64bit mode:
    http://patchwork.ozlabs.org/patch/598198/

With TCG, some lswx tests fail because it needs some fixes... I'm working
on this.

v2: 
    clearly restore r1 in call_handler
    use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"
    check program check type (invalid instruction)
    add "-v" parameter to display invalid instruction address
    use "mtxer" instead of "mtspr"
    Fix comments in lswx asm()
    add "memory" in clobber list
    add Thomas' Rb on patches 3 and 5.

Laurent Vivier (5):
  powerpc: add exception handler
  powerpc: add test to check invalid instruction trap
  powerpc: check 64bit mode
  powerpc: check lswx
  powerpc: Check lswx in little-endian mode.

 lib/powerpc/asm/hcall.h     |   1 +
 lib/powerpc/asm/ppc_asm.h   |   5 +
 lib/powerpc/asm/processor.h |  11 ++
 lib/powerpc/processor.c     |  38 +++++++
 lib/powerpc/setup.c         |  19 ++++
 lib/ppc64/asm-offsets.c     |  42 ++++++++
 lib/ppc64/asm/processor.h   |   1 +
 lib/ppc64/asm/ptrace.h      |  24 +++++
 powerpc/Makefile.common     |   6 +-
 powerpc/cstart64.S          | 140 +++++++++++++++++++++++++
 powerpc/emulator.c          | 241 ++++++++++++++++++++++++++++++++++++++++++++
 powerpc/unittests.cfg       |   3 +
 12 files changed, 530 insertions(+), 1 deletion(-)
 create mode 100644 lib/powerpc/asm/processor.h
 create mode 100644 lib/powerpc/processor.c
 create mode 100644 lib/ppc64/asm/processor.h
 create mode 100644 lib/ppc64/asm/ptrace.h
 create mode 100644 powerpc/emulator.c

-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 1/5] powerpc: add exception handler
  2016-03-21 11:33 ` Laurent Vivier
@ 2016-03-21 11:33   ` Laurent Vivier
  -1 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
v2:
    clearly restore r1 in call_handler
    use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"

 lib/powerpc/asm/hcall.h     |   1 +
 lib/powerpc/asm/ppc_asm.h   |   5 ++
 lib/powerpc/asm/processor.h |  11 ++++
 lib/powerpc/processor.c     |  38 ++++++++++++
 lib/powerpc/setup.c         |  19 ++++++
 lib/ppc64/asm-offsets.c     |  42 +++++++++++++
 lib/ppc64/asm/processor.h   |   1 +
 lib/ppc64/asm/ptrace.h      |  24 ++++++++
 powerpc/Makefile.common     |   1 +
 powerpc/cstart64.S          | 140 ++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 282 insertions(+)
 create mode 100644 lib/powerpc/asm/processor.h
 create mode 100644 lib/powerpc/processor.c
 create mode 100644 lib/ppc64/asm/processor.h
 create mode 100644 lib/ppc64/asm/ptrace.h

diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h
index f6f9ea8..99bce79 100644
--- a/lib/powerpc/asm/hcall.h
+++ b/lib/powerpc/asm/hcall.h
@@ -20,6 +20,7 @@
 #define H_PAGE_INIT		0x2c
 #define H_PUT_TERM_CHAR		0x58
 #define H_RANDOM		0x300
+#define H_SET_MODE		0x31C
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/lib/powerpc/asm/ppc_asm.h b/lib/powerpc/asm/ppc_asm.h
index f18100e..39620a3 100644
--- a/lib/powerpc/asm/ppc_asm.h
+++ b/lib/powerpc/asm/ppc_asm.h
@@ -1,6 +1,11 @@
 #ifndef _ASMPOWERPC_PPC_ASM_H
 #define _ASMPOWERPC_PPC_ASM_H
 
+#include <asm/asm-offsets.h>
+
+#define SAVE_GPR(n, base)	std	n,GPR0+8*(n)(base)
+#define REST_GPR(n, base)	ld	n,GPR0+8*(n)(base)
+
 #define LOAD_REG_IMMEDIATE(reg,expr)		\
 	lis	reg,(expr)@highest;		\
 	ori	reg,reg,(expr)@higher;		\
diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
new file mode 100644
index 0000000..09692bd
--- /dev/null
+++ b/lib/powerpc/asm/processor.h
@@ -0,0 +1,11 @@
+#ifndef _ASMPOWERPC_PROCESSOR_H_
+#define _ASMPOWERPC_PROCESSOR_H_
+
+#include <asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+void handle_exception(int trap, void (*func)(struct pt_regs *, void *), void *);
+void do_handle_exception(struct pt_regs *regs);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASMPOWERPC_PROCESSOR_H_ */
diff --git a/lib/powerpc/processor.c b/lib/powerpc/processor.c
new file mode 100644
index 0000000..a78bc3c
--- /dev/null
+++ b/lib/powerpc/processor.c
@@ -0,0 +1,38 @@
+/*
+ * processor control and status function
+ */
+
+#include <libcflat.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+
+static struct {
+	void (*func)(struct pt_regs *, void *data);
+	void *data;
+} handlers[16];
+
+void handle_exception(int trap, void (*func)(struct pt_regs *, void *),
+		      void * data)
+{
+	trap >>= 8;
+
+	if (trap < 16) {
+		handlers[trap].func = func;
+		handlers[trap].data = data;
+	}
+}
+
+void do_handle_exception(struct pt_regs *regs)
+{
+	unsigned char v;
+
+	v = regs->trap >> 8;
+
+	if (v < 16 && handlers[v].func) {
+		handlers[v].func(regs, handlers[v].data);
+		return;
+	}
+
+	printf("unhandled cpu exception 0x%lx\n", regs->trap);
+	abort();
+}
diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
index 0c0c882..e3cf952 100644
--- a/lib/powerpc/setup.c
+++ b/lib/powerpc/setup.c
@@ -16,6 +16,8 @@
 #include <alloc.h>
 #include <asm/setup.h>
 #include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/hcall.h>
 
 extern unsigned long stacktop;
 extern void io_init(void);
@@ -33,6 +35,10 @@ struct cpu_set_params {
 	unsigned dcache_bytes;
 };
 
+#define EXCEPTION_STACK_SIZE	(32*1024) /* 32kB */
+
+static char exception_stack[NR_CPUS][EXCEPTION_STACK_SIZE];
+
 static void cpu_set(int fdtnode, u32 regval, void *info)
 {
 	static bool read_common_info = false;
@@ -46,6 +52,11 @@ static void cpu_set(int fdtnode, u32 regval, void *info)
 	}
 	cpus[cpu] = regval;
 
+	/* set exception stack address for this CPU (in SPGR0) */
+
+	asm volatile ("mtsprg0 %[addr]" ::
+		      [addr] "r" (exception_stack[cpu + 1]));
+
 	if (!read_common_info) {
 		const struct fdt_property *prop;
 		u32 *data;
@@ -76,6 +87,14 @@ static void cpu_init(void)
 	assert(ret == 0);
 	__icache_bytes = params.icache_bytes;
 	__dcache_bytes = params.dcache_bytes;
+
+	/* Interrupt Endianness */
+
+#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+        hcall(H_SET_MODE, 1, 4, 0, 0);
+#else
+        hcall(H_SET_MODE, 0, 4, 0, 0);
+#endif
 }
 
 static void mem_init(phys_addr_t freemem_start)
diff --git a/lib/ppc64/asm-offsets.c b/lib/ppc64/asm-offsets.c
index 2d38a71..7843a20 100644
--- a/lib/ppc64/asm-offsets.c
+++ b/lib/ppc64/asm-offsets.c
@@ -5,8 +5,50 @@
  */
 #include <libcflat.h>
 #include <kbuild.h>
+#include <asm/ptrace.h>
 
 int main(void)
 {
+	DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
+
+	DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
+	DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
+	DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
+	DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
+	DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
+	DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
+	DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
+	DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
+	DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
+	DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
+	DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
+	DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
+	DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
+	DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
+	DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
+	DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
+	DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
+	DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
+	DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
+	DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
+	DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
+	DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
+	DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
+	DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
+	DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
+	DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
+	DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
+	DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
+	DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
+	DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
+	DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
+	DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
+	DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
+	DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
+	DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
+	DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
+	DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
+	DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
+	DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
 	return 0;
 }
diff --git a/lib/ppc64/asm/processor.h b/lib/ppc64/asm/processor.h
new file mode 100644
index 0000000..066a51a
--- /dev/null
+++ b/lib/ppc64/asm/processor.h
@@ -0,0 +1 @@
+#include "../../powerpc/asm/processor.h"
diff --git a/lib/ppc64/asm/ptrace.h b/lib/ppc64/asm/ptrace.h
new file mode 100644
index 0000000..076c9d9
--- /dev/null
+++ b/lib/ppc64/asm/ptrace.h
@@ -0,0 +1,24 @@
+#ifndef _ASMPPC64_PTRACE_H_
+#define _ASMPPC64_PTRACE_H_
+
+#define KERNEL_REDZONE_SIZE	288
+#define STACK_FRAME_OVERHEAD    112     /* size of minimum stack frame */
+
+#ifndef __ASSEMBLY__
+struct pt_regs {
+	unsigned long gpr[32];
+	unsigned long nip;
+	unsigned long msr;
+	unsigned long ctr;
+	unsigned long link;
+	unsigned long xer;
+	unsigned long ccr;
+	unsigned long trap;
+};
+
+#define STACK_INT_FRAME_SIZE    (sizeof(struct pt_regs) + \
+				 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASMPPC64_PTRACE_H_ */
diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
index 424983e..ab2caf6 100644
--- a/powerpc/Makefile.common
+++ b/powerpc/Makefile.common
@@ -31,6 +31,7 @@ cflatobjs += lib/powerpc/io.o
 cflatobjs += lib/powerpc/hcall.o
 cflatobjs += lib/powerpc/setup.o
 cflatobjs += lib/powerpc/rtas.o
+cflatobjs += lib/powerpc/processor.o
 
 FLATLIBS = $(libcflat) $(LIBFDT_archive)
 %.elf: CFLAGS += $(arch_CFLAGS)
diff --git a/powerpc/cstart64.S b/powerpc/cstart64.S
index c87e3d6..ceb6397 100644
--- a/powerpc/cstart64.S
+++ b/powerpc/cstart64.S
@@ -9,6 +9,7 @@
 #include <asm/hcall.h>
 #include <asm/ppc_asm.h>
 #include <asm/rtas.h>
+#include <asm/ptrace.h>
 
 .section .init
 
@@ -45,6 +46,34 @@ start:
 	add	r4, r4, r31
 	bl	relocate
 
+	/* relocate vector table to base address 0x0 (MSR_IP = 0) */
+
+	/* source: r4, dest end: r5, destination: r6 */
+
+	LOAD_REG_ADDR(r4, __start_interrupts)
+	LOAD_REG_ADDR(r5, __end_interrupts)
+	sub	r5,r5,r4
+	li	r6,0x100
+
+	sub	r4,r4,r6
+	add	r5,r5,r6
+	addi	r6,r6,-8
+2:	li	r0,8
+	mtctr	r0
+	/* copy a cache line size */
+3:	addi	r6,r6,8
+	ldx	r0,r6,r4
+	stdx	r0,0,r6
+	bdnz	3b
+	dcbst	0,r6
+	/* flush icache */
+	sync
+	icbi	0,r6
+	cmpld	0,r6,r5
+	blt	2b
+	sync
+	isync
+
 	/* patch sc1 if needed */
 	bl	hcall_have_broken_sc1
 	cmpwi	r3, 0
@@ -105,3 +134,114 @@ rtas_return_loc:
 	ld	r0, 16(r1)
 	mtlr	r0
 	blr
+
+call_handler:
+	/* save context */
+
+	/* GPRs */
+
+	.irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
+	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+		SAVE_GPR(\i, r1)
+	.endr
+	mfsprg1	r0
+	std	r0,GPR1(r1)
+
+	/* lr, xer, ccr */
+
+	mflr	r0
+	std	r0,_LINK(r1)
+
+	mfxer	r0
+	std	r0,_XER(r1)
+
+	mfcr	r0
+	std	r0,_CCR(r1)
+
+	/* nip and msr */
+
+	mfsrr0	r0
+	std	r0, _NIP(r1)
+
+	mfsrr1	r0
+	std	r0, _MSR(r1)
+
+	/* FIXME: build stack frame */
+
+	/* call generic handler */
+
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	do_handle_exception
+
+	/* restore context */
+
+	ld	r0,_CTR(r1)
+	mtctr	r0
+
+	ld	r0,_LINK(r1)
+	mtlr	r0
+
+	ld	r0,_XER(r1)
+	mtxer	r0
+
+	ld	r0,_CCR(r1)
+	mtcr	r0
+
+	ld	r0, _NIP(r1)
+	mtsrr0	r0
+
+	ld	r0, _MSR(r1)
+	mtsrr1	r0
+
+	.irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
+	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+		REST_GPR(\i, r1)
+	.endr
+
+	/* restore r1, as we don't need it anymore */
+
+	REST_GPR(1,r1)
+
+	rfid
+	b .
+
+.section .text.ex
+
+.macro VECTOR vec
+	. = \vec
+
+	mtsprg1	r1	/* save r1 */
+	mfsprg0	r1	/* get exception stack address */
+	subi	r1,r1, INT_FRAME_SIZE
+
+	/* save r0 and ctr to call generic handler */
+
+	SAVE_GPR(0,r1)
+
+	mfctr	r0
+	std	r0,_CTR(r1)
+
+	LOAD_REG_ADDR(r0, call_handler)
+	mtctr	r0
+
+	li	r0,\vec
+	std	r0,_TRAP(r1)
+
+	bctr
+.endm
+
+	. = 0x100
+	.globl __start_interrupts
+__start_interrupts:
+
+VECTOR(0x300)
+VECTOR(0x400)
+VECTOR(0x500)
+VECTOR(0x600)
+VECTOR(0x700)
+VECTOR(0x800)
+VECTOR(0x900)
+
+	.align 7
+	.globl __end_interrupts
+__end_interrupts:
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 1/5] powerpc: add exception handler
@ 2016-03-21 11:33   ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
v2:
    clearly restore r1 in call_handler
    use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"

 lib/powerpc/asm/hcall.h     |   1 +
 lib/powerpc/asm/ppc_asm.h   |   5 ++
 lib/powerpc/asm/processor.h |  11 ++++
 lib/powerpc/processor.c     |  38 ++++++++++++
 lib/powerpc/setup.c         |  19 ++++++
 lib/ppc64/asm-offsets.c     |  42 +++++++++++++
 lib/ppc64/asm/processor.h   |   1 +
 lib/ppc64/asm/ptrace.h      |  24 ++++++++
 powerpc/Makefile.common     |   1 +
 powerpc/cstart64.S          | 140 ++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 282 insertions(+)
 create mode 100644 lib/powerpc/asm/processor.h
 create mode 100644 lib/powerpc/processor.c
 create mode 100644 lib/ppc64/asm/processor.h
 create mode 100644 lib/ppc64/asm/ptrace.h

diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h
index f6f9ea8..99bce79 100644
--- a/lib/powerpc/asm/hcall.h
+++ b/lib/powerpc/asm/hcall.h
@@ -20,6 +20,7 @@
 #define H_PAGE_INIT		0x2c
 #define H_PUT_TERM_CHAR		0x58
 #define H_RANDOM		0x300
+#define H_SET_MODE		0x31C
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/lib/powerpc/asm/ppc_asm.h b/lib/powerpc/asm/ppc_asm.h
index f18100e..39620a3 100644
--- a/lib/powerpc/asm/ppc_asm.h
+++ b/lib/powerpc/asm/ppc_asm.h
@@ -1,6 +1,11 @@
 #ifndef _ASMPOWERPC_PPC_ASM_H
 #define _ASMPOWERPC_PPC_ASM_H
 
+#include <asm/asm-offsets.h>
+
+#define SAVE_GPR(n, base)	std	n,GPR0+8*(n)(base)
+#define REST_GPR(n, base)	ld	n,GPR0+8*(n)(base)
+
 #define LOAD_REG_IMMEDIATE(reg,expr)		\
 	lis	reg,(expr)@highest;		\
 	ori	reg,reg,(expr)@higher;		\
diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
new file mode 100644
index 0000000..09692bd
--- /dev/null
+++ b/lib/powerpc/asm/processor.h
@@ -0,0 +1,11 @@
+#ifndef _ASMPOWERPC_PROCESSOR_H_
+#define _ASMPOWERPC_PROCESSOR_H_
+
+#include <asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+void handle_exception(int trap, void (*func)(struct pt_regs *, void *), void *);
+void do_handle_exception(struct pt_regs *regs);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASMPOWERPC_PROCESSOR_H_ */
diff --git a/lib/powerpc/processor.c b/lib/powerpc/processor.c
new file mode 100644
index 0000000..a78bc3c
--- /dev/null
+++ b/lib/powerpc/processor.c
@@ -0,0 +1,38 @@
+/*
+ * processor control and status function
+ */
+
+#include <libcflat.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+
+static struct {
+	void (*func)(struct pt_regs *, void *data);
+	void *data;
+} handlers[16];
+
+void handle_exception(int trap, void (*func)(struct pt_regs *, void *),
+		      void * data)
+{
+	trap >>= 8;
+
+	if (trap < 16) {
+		handlers[trap].func = func;
+		handlers[trap].data = data;
+	}
+}
+
+void do_handle_exception(struct pt_regs *regs)
+{
+	unsigned char v;
+
+	v = regs->trap >> 8;
+
+	if (v < 16 && handlers[v].func) {
+		handlers[v].func(regs, handlers[v].data);
+		return;
+	}
+
+	printf("unhandled cpu exception 0x%lx\n", regs->trap);
+	abort();
+}
diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
index 0c0c882..e3cf952 100644
--- a/lib/powerpc/setup.c
+++ b/lib/powerpc/setup.c
@@ -16,6 +16,8 @@
 #include <alloc.h>
 #include <asm/setup.h>
 #include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/hcall.h>
 
 extern unsigned long stacktop;
 extern void io_init(void);
@@ -33,6 +35,10 @@ struct cpu_set_params {
 	unsigned dcache_bytes;
 };
 
+#define EXCEPTION_STACK_SIZE	(32*1024) /* 32kB */
+
+static char exception_stack[NR_CPUS][EXCEPTION_STACK_SIZE];
+
 static void cpu_set(int fdtnode, u32 regval, void *info)
 {
 	static bool read_common_info = false;
@@ -46,6 +52,11 @@ static void cpu_set(int fdtnode, u32 regval, void *info)
 	}
 	cpus[cpu] = regval;
 
+	/* set exception stack address for this CPU (in SPGR0) */
+
+	asm volatile ("mtsprg0 %[addr]" ::
+		      [addr] "r" (exception_stack[cpu + 1]));
+
 	if (!read_common_info) {
 		const struct fdt_property *prop;
 		u32 *data;
@@ -76,6 +87,14 @@ static void cpu_init(void)
 	assert(ret = 0);
 	__icache_bytes = params.icache_bytes;
 	__dcache_bytes = params.dcache_bytes;
+
+	/* Interrupt Endianness */
+
+#if  __BYTE_ORDER__ = __ORDER_LITTLE_ENDIAN__
+        hcall(H_SET_MODE, 1, 4, 0, 0);
+#else
+        hcall(H_SET_MODE, 0, 4, 0, 0);
+#endif
 }
 
 static void mem_init(phys_addr_t freemem_start)
diff --git a/lib/ppc64/asm-offsets.c b/lib/ppc64/asm-offsets.c
index 2d38a71..7843a20 100644
--- a/lib/ppc64/asm-offsets.c
+++ b/lib/ppc64/asm-offsets.c
@@ -5,8 +5,50 @@
  */
 #include <libcflat.h>
 #include <kbuild.h>
+#include <asm/ptrace.h>
 
 int main(void)
 {
+	DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
+
+	DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
+	DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
+	DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
+	DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
+	DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
+	DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
+	DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
+	DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
+	DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
+	DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
+	DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
+	DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
+	DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
+	DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
+	DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
+	DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
+	DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
+	DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
+	DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
+	DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
+	DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
+	DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
+	DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
+	DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
+	DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
+	DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
+	DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
+	DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
+	DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
+	DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
+	DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
+	DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
+	DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
+	DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
+	DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
+	DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
+	DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
+	DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
+	DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
 	return 0;
 }
diff --git a/lib/ppc64/asm/processor.h b/lib/ppc64/asm/processor.h
new file mode 100644
index 0000000..066a51a
--- /dev/null
+++ b/lib/ppc64/asm/processor.h
@@ -0,0 +1 @@
+#include "../../powerpc/asm/processor.h"
diff --git a/lib/ppc64/asm/ptrace.h b/lib/ppc64/asm/ptrace.h
new file mode 100644
index 0000000..076c9d9
--- /dev/null
+++ b/lib/ppc64/asm/ptrace.h
@@ -0,0 +1,24 @@
+#ifndef _ASMPPC64_PTRACE_H_
+#define _ASMPPC64_PTRACE_H_
+
+#define KERNEL_REDZONE_SIZE	288
+#define STACK_FRAME_OVERHEAD    112     /* size of minimum stack frame */
+
+#ifndef __ASSEMBLY__
+struct pt_regs {
+	unsigned long gpr[32];
+	unsigned long nip;
+	unsigned long msr;
+	unsigned long ctr;
+	unsigned long link;
+	unsigned long xer;
+	unsigned long ccr;
+	unsigned long trap;
+};
+
+#define STACK_INT_FRAME_SIZE    (sizeof(struct pt_regs) + \
+				 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASMPPC64_PTRACE_H_ */
diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
index 424983e..ab2caf6 100644
--- a/powerpc/Makefile.common
+++ b/powerpc/Makefile.common
@@ -31,6 +31,7 @@ cflatobjs += lib/powerpc/io.o
 cflatobjs += lib/powerpc/hcall.o
 cflatobjs += lib/powerpc/setup.o
 cflatobjs += lib/powerpc/rtas.o
+cflatobjs += lib/powerpc/processor.o
 
 FLATLIBS = $(libcflat) $(LIBFDT_archive)
 %.elf: CFLAGS += $(arch_CFLAGS)
diff --git a/powerpc/cstart64.S b/powerpc/cstart64.S
index c87e3d6..ceb6397 100644
--- a/powerpc/cstart64.S
+++ b/powerpc/cstart64.S
@@ -9,6 +9,7 @@
 #include <asm/hcall.h>
 #include <asm/ppc_asm.h>
 #include <asm/rtas.h>
+#include <asm/ptrace.h>
 
 .section .init
 
@@ -45,6 +46,34 @@ start:
 	add	r4, r4, r31
 	bl	relocate
 
+	/* relocate vector table to base address 0x0 (MSR_IP = 0) */
+
+	/* source: r4, dest end: r5, destination: r6 */
+
+	LOAD_REG_ADDR(r4, __start_interrupts)
+	LOAD_REG_ADDR(r5, __end_interrupts)
+	sub	r5,r5,r4
+	li	r6,0x100
+
+	sub	r4,r4,r6
+	add	r5,r5,r6
+	addi	r6,r6,-8
+2:	li	r0,8
+	mtctr	r0
+	/* copy a cache line size */
+3:	addi	r6,r6,8
+	ldx	r0,r6,r4
+	stdx	r0,0,r6
+	bdnz	3b
+	dcbst	0,r6
+	/* flush icache */
+	sync
+	icbi	0,r6
+	cmpld	0,r6,r5
+	blt	2b
+	sync
+	isync
+
 	/* patch sc1 if needed */
 	bl	hcall_have_broken_sc1
 	cmpwi	r3, 0
@@ -105,3 +134,114 @@ rtas_return_loc:
 	ld	r0, 16(r1)
 	mtlr	r0
 	blr
+
+call_handler:
+	/* save context */
+
+	/* GPRs */
+
+	.irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
+	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+		SAVE_GPR(\i, r1)
+	.endr
+	mfsprg1	r0
+	std	r0,GPR1(r1)
+
+	/* lr, xer, ccr */
+
+	mflr	r0
+	std	r0,_LINK(r1)
+
+	mfxer	r0
+	std	r0,_XER(r1)
+
+	mfcr	r0
+	std	r0,_CCR(r1)
+
+	/* nip and msr */
+
+	mfsrr0	r0
+	std	r0, _NIP(r1)
+
+	mfsrr1	r0
+	std	r0, _MSR(r1)
+
+	/* FIXME: build stack frame */
+
+	/* call generic handler */
+
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	do_handle_exception
+
+	/* restore context */
+
+	ld	r0,_CTR(r1)
+	mtctr	r0
+
+	ld	r0,_LINK(r1)
+	mtlr	r0
+
+	ld	r0,_XER(r1)
+	mtxer	r0
+
+	ld	r0,_CCR(r1)
+	mtcr	r0
+
+	ld	r0, _NIP(r1)
+	mtsrr0	r0
+
+	ld	r0, _MSR(r1)
+	mtsrr1	r0
+
+	.irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
+	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+		REST_GPR(\i, r1)
+	.endr
+
+	/* restore r1, as we don't need it anymore */
+
+	REST_GPR(1,r1)
+
+	rfid
+	b .
+
+.section .text.ex
+
+.macro VECTOR vec
+	. = \vec
+
+	mtsprg1	r1	/* save r1 */
+	mfsprg0	r1	/* get exception stack address */
+	subi	r1,r1, INT_FRAME_SIZE
+
+	/* save r0 and ctr to call generic handler */
+
+	SAVE_GPR(0,r1)
+
+	mfctr	r0
+	std	r0,_CTR(r1)
+
+	LOAD_REG_ADDR(r0, call_handler)
+	mtctr	r0
+
+	li	r0,\vec
+	std	r0,_TRAP(r1)
+
+	bctr
+.endm
+
+	. = 0x100
+	.globl __start_interrupts
+__start_interrupts:
+
+VECTOR(0x300)
+VECTOR(0x400)
+VECTOR(0x500)
+VECTOR(0x600)
+VECTOR(0x700)
+VECTOR(0x800)
+VECTOR(0x900)
+
+	.align 7
+	.globl __end_interrupts
+__end_interrupts:
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 2/5] powerpc: add test to check invalid instruction trap
  2016-03-21 11:33 ` Laurent Vivier
@ 2016-03-21 11:33   ` Laurent Vivier
  -1 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
v2:
    check program check type (invalid instruction)
    add "-v" parameter to display invalid instruction address

 powerpc/Makefile.common |  5 +++-
 powerpc/emulator.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
 powerpc/unittests.cfg   |  3 +++
 3 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 powerpc/emulator.c

diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
index ab2caf6..257e3fb 100644
--- a/powerpc/Makefile.common
+++ b/powerpc/Makefile.common
@@ -7,7 +7,8 @@
 tests-common = \
 	$(TEST_DIR)/selftest.elf \
 	$(TEST_DIR)/spapr_hcall.elf \
-	$(TEST_DIR)/rtas.elf
+	$(TEST_DIR)/rtas.elf \
+	$(TEST_DIR)/emulator.elf
 
 all: $(TEST_DIR)/boot_rom.bin test_cases
 
@@ -70,3 +71,5 @@ $(TEST_DIR)/selftest.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/selftest.o
 $(TEST_DIR)/spapr_hcall.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/spapr_hcall.o
 
 $(TEST_DIR)/rtas.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/rtas.o
+
+$(TEST_DIR)/emulator.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/emulator.o
diff --git a/powerpc/emulator.c b/powerpc/emulator.c
new file mode 100644
index 0000000..1d4f164
--- /dev/null
+++ b/powerpc/emulator.c
@@ -0,0 +1,65 @@
+/*
+ * Test some powerpc instructions
+ */
+
+#include <libcflat.h>
+#include <asm/processor.h>
+
+static int verbose;
+static int volatile is_invalid;
+
+static void program_check_handler(struct pt_regs *regs, void *opaque)
+{
+	int *data = opaque;
+
+	if (verbose) {
+		printf("Detected invalid instruction 0x%016lx: %08x\n",
+		       regs->nip, *(uint32_t*)regs->nip);
+	}
+
+	/* the result is bit 16 to 19 of SRR1
+	 * bit 0: SRR0 contains the address of the next instruction
+	 * bit 1: Trap
+	 * bit 2: Privileged instruction
+	 * bit 3: Illegal instruction
+	 * bit 4: FP enabled exception type
+	 */
+
+	*data = regs->msr >> 16;
+
+	regs->nip += 4;
+}
+
+static void test_illegal(void)
+{
+	report_prefix_push("invalid");
+
+	is_invalid = 0;
+
+	asm volatile (".long 0");
+
+	report("exception", is_invalid == 8); /* illegal instruction */
+
+	report_prefix_pop();
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
+
+	for (i = 0; i < argc; i++) {
+		if (strcmp(argv[i], "-v") == 0) {
+			verbose = 1;
+		}
+	}
+
+	report_prefix_push("emulator");
+
+	test_illegal();
+
+	report_prefix_pop();
+
+	return report_summary();
+}
diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg
index 02b21c7..ed4fdbe 100644
--- a/powerpc/unittests.cfg
+++ b/powerpc/unittests.cfg
@@ -47,3 +47,6 @@ file = rtas.elf
 extra_params = -append "set-time-of-day"
 timeout = 5
 groups = rtas
+
+[emulator]
+file = emulator.elf
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 2/5] powerpc: add test to check invalid instruction trap
@ 2016-03-21 11:33   ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
v2:
    check program check type (invalid instruction)
    add "-v" parameter to display invalid instruction address

 powerpc/Makefile.common |  5 +++-
 powerpc/emulator.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
 powerpc/unittests.cfg   |  3 +++
 3 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 powerpc/emulator.c

diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
index ab2caf6..257e3fb 100644
--- a/powerpc/Makefile.common
+++ b/powerpc/Makefile.common
@@ -7,7 +7,8 @@
 tests-common = \
 	$(TEST_DIR)/selftest.elf \
 	$(TEST_DIR)/spapr_hcall.elf \
-	$(TEST_DIR)/rtas.elf
+	$(TEST_DIR)/rtas.elf \
+	$(TEST_DIR)/emulator.elf
 
 all: $(TEST_DIR)/boot_rom.bin test_cases
 
@@ -70,3 +71,5 @@ $(TEST_DIR)/selftest.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/selftest.o
 $(TEST_DIR)/spapr_hcall.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/spapr_hcall.o
 
 $(TEST_DIR)/rtas.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/rtas.o
+
+$(TEST_DIR)/emulator.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/emulator.o
diff --git a/powerpc/emulator.c b/powerpc/emulator.c
new file mode 100644
index 0000000..1d4f164
--- /dev/null
+++ b/powerpc/emulator.c
@@ -0,0 +1,65 @@
+/*
+ * Test some powerpc instructions
+ */
+
+#include <libcflat.h>
+#include <asm/processor.h>
+
+static int verbose;
+static int volatile is_invalid;
+
+static void program_check_handler(struct pt_regs *regs, void *opaque)
+{
+	int *data = opaque;
+
+	if (verbose) {
+		printf("Detected invalid instruction 0x%016lx: %08x\n",
+		       regs->nip, *(uint32_t*)regs->nip);
+	}
+
+	/* the result is bit 16 to 19 of SRR1
+	 * bit 0: SRR0 contains the address of the next instruction
+	 * bit 1: Trap
+	 * bit 2: Privileged instruction
+	 * bit 3: Illegal instruction
+	 * bit 4: FP enabled exception type
+	 */
+
+	*data = regs->msr >> 16;
+
+	regs->nip += 4;
+}
+
+static void test_illegal(void)
+{
+	report_prefix_push("invalid");
+
+	is_invalid = 0;
+
+	asm volatile (".long 0");
+
+	report("exception", is_invalid = 8); /* illegal instruction */
+
+	report_prefix_pop();
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
+
+	for (i = 0; i < argc; i++) {
+		if (strcmp(argv[i], "-v") = 0) {
+			verbose = 1;
+		}
+	}
+
+	report_prefix_push("emulator");
+
+	test_illegal();
+
+	report_prefix_pop();
+
+	return report_summary();
+}
diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg
index 02b21c7..ed4fdbe 100644
--- a/powerpc/unittests.cfg
+++ b/powerpc/unittests.cfg
@@ -47,3 +47,6 @@ file = rtas.elf
 extra_params = -append "set-time-of-day"
 timeout = 5
 groups = rtas
+
+[emulator]
+file = emulator.elf
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 3/5] powerpc: check 64bit mode
  2016-03-21 11:33 ` Laurent Vivier
@ 2016-03-21 11:33   ` Laurent Vivier
  -1 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Check in MSR if the SF bit is set (64bit mode is enabled)

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 powerpc/emulator.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index 1d4f164..d97090c 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -43,6 +43,19 @@ static void test_illegal(void)
 	report_prefix_pop();
 }
 
+static void test_64bit(void)
+{
+	uint64_t msr;
+
+	report_prefix_push("64bit");
+
+	asm("mfmsr %[msr]": [msr] "=r" (msr));
+
+	report("detected", msr & 0x8000000000000000UL);
+
+	report_prefix_pop();
+}
+
 int main(int argc, char **argv)
 {
 	int i;
@@ -57,6 +70,7 @@ int main(int argc, char **argv)
 
 	report_prefix_push("emulator");
 
+	test_64bit();
 	test_illegal();
 
 	report_prefix_pop();
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 3/5] powerpc: check 64bit mode
@ 2016-03-21 11:33   ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Check in MSR if the SF bit is set (64bit mode is enabled)

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 powerpc/emulator.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index 1d4f164..d97090c 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -43,6 +43,19 @@ static void test_illegal(void)
 	report_prefix_pop();
 }
 
+static void test_64bit(void)
+{
+	uint64_t msr;
+
+	report_prefix_push("64bit");
+
+	asm("mfmsr %[msr]": [msr] "=r" (msr));
+
+	report("detected", msr & 0x8000000000000000UL);
+
+	report_prefix_pop();
+}
+
 int main(int argc, char **argv)
 {
 	int i;
@@ -57,6 +70,7 @@ int main(int argc, char **argv)
 
 	report_prefix_push("emulator");
 
+	test_64bit();
 	test_illegal();
 
 	report_prefix_pop();
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
  2016-03-21 11:33 ` Laurent Vivier
@ 2016-03-21 11:33   ` Laurent Vivier
  -1 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
v2:
    use "mtxer" instead of "mtspr"
    Fix comments in lswx asm()
    add "memory" in clobber list

 powerpc/emulator.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index d97090c..8d0dde2 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -56,6 +56,145 @@ static void test_64bit(void)
 	report_prefix_pop();
 }
 
+/*
+ * lswx: Load String Word Indexed X-form
+ *
+ *     lswx RT,RA,RB
+ *
+ * EA = (RA|0) + RB
+ * n  = XER
+ *
+ * Load n bytes from address EA into (n / 4) consecutive registers,
+ * throught RT -> RT + (n / 4) - 1.
+ * - Data are loaded into 4 low order bytes of registers (Word).
+ * - The unfilled bytes are set to 0.
+ * - The sequence of registers wraps around to GPR0.
+ * - if n == 0, content of RT is undefined
+ * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
+ * - RT == RA == 0 is invalid
+ *
+ */
+
+static void test_lswx(void)
+{
+	int i;
+	char addr[128];
+	uint64_t regs[32];
+
+	report_prefix_push("lswx");
+
+	/* fill memory with sequence */
+
+	for (i = 0; i < 128; i++)
+		addr[i] = 1 + i;
+
+	/* check incomplete register filling */
+
+	asm volatile ("mtxer %[len];"
+		      "li r12,-1;"
+		      "mr r11, r12;"
+		      "lswx r11, 0, %[addr];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      ::
+		      [len] "r" (3),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      "xer", "r11", "r12", "memory");
+
+	report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
+
+	/* check an old know bug: the number of bytes is used as
+	 * the number of registers, so try 32 bytes.
+	 */
+
+	asm volatile ("mtxer %[len];"
+		      "li r19,-1;"
+		      "mr r11, r19; mr r12, r19; mr r13, r19;"
+		      "mr r14, r19; mr r15, r19; mr r16, r19;"
+		      "mr r17, r19; mr r18, r19;"
+		      "lswx r11, 0, %[addr];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      "std r13, 2*8(%[regs]);"
+		      "std r14, 3*8(%[regs]);"
+		      "std r15, 4*8(%[regs]);"
+		      "std r16, 5*8(%[regs]);"
+		      "std r17, 6*8(%[regs]);"
+		      "std r18, 7*8(%[regs]);"
+		      "std r19, 8*8(%[regs]);"
+		      ::
+		      [len] "r" (32),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* as 32 is the number of bytes,
+		       * we should modify 32/4 = 8 regs, from r11 to r18
+		       * We check r19 is unmodified by filling it with 1s
+		       * before the instruction.
+		       */
+		      "xer", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
+		      "r18", "r19", "memory");
+
+	report("length", regs[0] == 0x01020304 && regs[1] == 0x05060708 &&
+			 regs[2] == 0x090a0b0c && regs[3] == 0x0d0e0f10 &&
+			 regs[4] == 0x11121314 && regs[5] == 0x15161718 &&
+			 regs[6] == 0x191a1b1c && regs[7] == 0x1d1e1f20 &&
+			 regs[8] == (uint64_t)-1);
+
+	/* check wrap around to r0 */
+
+	asm volatile ("mtxer %[len];"
+		      "li r31,-1;"
+		      "mr r0, r31;"
+		      "lswx r31, 0, %[addr];"
+		      "std r31, 0*8(%[regs]);"
+		      "std r0, 1*8(%[regs]);"
+		      ::
+		      [len] "r" (8),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* modify two registers from r31, wrap around to r0 */
+		      "xer", "r31", "r0", "memory");
+
+	report("wrap around to r0", regs[0] == 0x01020304 &&
+			            regs[1] == 0x05060708);
+
+	/* check wrap around to r0 over RB doesn't break RB */
+
+	asm volatile ("mtxer %[len];"
+		      /* adding r1 in the clobber list doesn't protect it... */
+		      "mr r29,r1;"
+		      "li r31,-1;"
+		      "mr r1,r31;"
+		      "mr r0, %[addr];"
+		      "lswx r31, 0, r0;"
+		      "std r31, 0*8(%[regs]);"
+		      "std r0, 1*8(%[regs]);"
+		      "std r1, 2*8(%[regs]);"
+		      "mr r1,r29;"
+		      ::
+		      [len] "r" (12),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* three registers from r31, wrap arount to r1,
+		       * r1 is saved to r29, as adding it to the clobber
+		       * list doesn't protect it
+		       */
+		      "xer", "r31", "r0", "r29", "memory");
+
+	/* doc says it is invalid, real proc stops when it comes to
+	 * overwrite the register.
+	 * In all the cases, the register must stay untouched
+	 */
+	report("Don't overwrite Rb", regs[1] == (uint64_t)addr);
+
+	report_prefix_pop();
+}
+
 int main(int argc, char **argv)
 {
 	int i;
@@ -72,6 +211,7 @@ int main(int argc, char **argv)
 
 	test_64bit();
 	test_illegal();
+	test_lswx();
 
 	report_prefix_pop();
 
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
@ 2016-03-21 11:33   ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
v2:
    use "mtxer" instead of "mtspr"
    Fix comments in lswx asm()
    add "memory" in clobber list

 powerpc/emulator.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index d97090c..8d0dde2 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -56,6 +56,145 @@ static void test_64bit(void)
 	report_prefix_pop();
 }
 
+/*
+ * lswx: Load String Word Indexed X-form
+ *
+ *     lswx RT,RA,RB
+ *
+ * EA = (RA|0) + RB
+ * n  = XER
+ *
+ * Load n bytes from address EA into (n / 4) consecutive registers,
+ * throught RT -> RT + (n / 4) - 1.
+ * - Data are loaded into 4 low order bytes of registers (Word).
+ * - The unfilled bytes are set to 0.
+ * - The sequence of registers wraps around to GPR0.
+ * - if n = 0, content of RT is undefined
+ * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
+ * - RT = RA = 0 is invalid
+ *
+ */
+
+static void test_lswx(void)
+{
+	int i;
+	char addr[128];
+	uint64_t regs[32];
+
+	report_prefix_push("lswx");
+
+	/* fill memory with sequence */
+
+	for (i = 0; i < 128; i++)
+		addr[i] = 1 + i;
+
+	/* check incomplete register filling */
+
+	asm volatile ("mtxer %[len];"
+		      "li r12,-1;"
+		      "mr r11, r12;"
+		      "lswx r11, 0, %[addr];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      ::
+		      [len] "r" (3),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      "xer", "r11", "r12", "memory");
+
+	report("partial", regs[0] = 0x01020300 && regs[1] = (uint64_t)-1);
+
+	/* check an old know bug: the number of bytes is used as
+	 * the number of registers, so try 32 bytes.
+	 */
+
+	asm volatile ("mtxer %[len];"
+		      "li r19,-1;"
+		      "mr r11, r19; mr r12, r19; mr r13, r19;"
+		      "mr r14, r19; mr r15, r19; mr r16, r19;"
+		      "mr r17, r19; mr r18, r19;"
+		      "lswx r11, 0, %[addr];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      "std r13, 2*8(%[regs]);"
+		      "std r14, 3*8(%[regs]);"
+		      "std r15, 4*8(%[regs]);"
+		      "std r16, 5*8(%[regs]);"
+		      "std r17, 6*8(%[regs]);"
+		      "std r18, 7*8(%[regs]);"
+		      "std r19, 8*8(%[regs]);"
+		      ::
+		      [len] "r" (32),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* as 32 is the number of bytes,
+		       * we should modify 32/4 = 8 regs, from r11 to r18
+		       * We check r19 is unmodified by filling it with 1s
+		       * before the instruction.
+		       */
+		      "xer", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
+		      "r18", "r19", "memory");
+
+	report("length", regs[0] = 0x01020304 && regs[1] = 0x05060708 &&
+			 regs[2] = 0x090a0b0c && regs[3] = 0x0d0e0f10 &&
+			 regs[4] = 0x11121314 && regs[5] = 0x15161718 &&
+			 regs[6] = 0x191a1b1c && regs[7] = 0x1d1e1f20 &&
+			 regs[8] = (uint64_t)-1);
+
+	/* check wrap around to r0 */
+
+	asm volatile ("mtxer %[len];"
+		      "li r31,-1;"
+		      "mr r0, r31;"
+		      "lswx r31, 0, %[addr];"
+		      "std r31, 0*8(%[regs]);"
+		      "std r0, 1*8(%[regs]);"
+		      ::
+		      [len] "r" (8),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* modify two registers from r31, wrap around to r0 */
+		      "xer", "r31", "r0", "memory");
+
+	report("wrap around to r0", regs[0] = 0x01020304 &&
+			            regs[1] = 0x05060708);
+
+	/* check wrap around to r0 over RB doesn't break RB */
+
+	asm volatile ("mtxer %[len];"
+		      /* adding r1 in the clobber list doesn't protect it... */
+		      "mr r29,r1;"
+		      "li r31,-1;"
+		      "mr r1,r31;"
+		      "mr r0, %[addr];"
+		      "lswx r31, 0, r0;"
+		      "std r31, 0*8(%[regs]);"
+		      "std r0, 1*8(%[regs]);"
+		      "std r1, 2*8(%[regs]);"
+		      "mr r1,r29;"
+		      ::
+		      [len] "r" (12),
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* three registers from r31, wrap arount to r1,
+		       * r1 is saved to r29, as adding it to the clobber
+		       * list doesn't protect it
+		       */
+		      "xer", "r31", "r0", "r29", "memory");
+
+	/* doc says it is invalid, real proc stops when it comes to
+	 * overwrite the register.
+	 * In all the cases, the register must stay untouched
+	 */
+	report("Don't overwrite Rb", regs[1] = (uint64_t)addr);
+
+	report_prefix_pop();
+}
+
 int main(int argc, char **argv)
 {
 	int i;
@@ -72,6 +211,7 @@ int main(int argc, char **argv)
 
 	test_64bit();
 	test_illegal();
+	test_lswx();
 
 	report_prefix_pop();
 
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
  2016-03-21 11:33 ` Laurent Vivier
@ 2016-03-21 11:33   ` Laurent Vivier
  -1 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

For lswx in little-endian mode, an alignment interrupt occurs.

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 powerpc/emulator.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index 8d0dde2..87ef4a9 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -7,6 +7,7 @@
 
 static int verbose;
 static int volatile is_invalid;
+static int volatile alignment;
 
 static void program_check_handler(struct pt_regs *regs, void *opaque)
 {
@@ -30,6 +31,18 @@ static void program_check_handler(struct pt_regs *regs, void *opaque)
 	regs->nip += 4;
 }
 
+static void alignment_handler(struct pt_regs *regs, void *opaque)
+{
+	int *data = opaque;
+
+	printf("Detected alignment exception 0x%016lx: %08x\n",
+	       regs->nip, *(uint32_t*)regs->nip);
+
+	*data = 1;
+
+	regs->nip += 4;
+}
+
 static void test_illegal(void)
 {
 	report_prefix_push("invalid");
@@ -73,6 +86,8 @@ static void test_64bit(void)
  * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
  * - RT == RA == 0 is invalid
  *
+ * For lswx in little-endian mode, an alignment interrupt always occurs.
+ *
  */
 
 static void test_lswx(void)
@@ -90,6 +105,7 @@ static void test_lswx(void)
 
 	/* check incomplete register filling */
 
+	alignment = 0;
 	asm volatile ("mtxer %[len];"
 		      "li r12,-1;"
 		      "mr r11, r12;"
@@ -103,7 +119,12 @@ static void test_lswx(void)
 		      :
 		      "xer", "r11", "r12", "memory");
 
+#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	report("alignment", alignment);
+	return;
+#else
 	report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
+#endif
 
 	/* check an old know bug: the number of bytes is used as
 	 * the number of registers, so try 32 bytes.
@@ -200,6 +221,7 @@ int main(int argc, char **argv)
 	int i;
 
 	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
+	handle_exception(0x600, alignment_handler, (void *)&alignment);
 
 	for (i = 0; i < argc; i++) {
 		if (strcmp(argv[i], "-v") == 0) {
-- 
2.5.0


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

* [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
@ 2016-03-21 11:33   ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 11:33 UTC (permalink / raw)
  To: kvm, kvm-ppc; +Cc: drjones, thuth, dgibson, pbonzini, Laurent Vivier

For lswx in little-endian mode, an alignment interrupt occurs.

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 powerpc/emulator.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index 8d0dde2..87ef4a9 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -7,6 +7,7 @@
 
 static int verbose;
 static int volatile is_invalid;
+static int volatile alignment;
 
 static void program_check_handler(struct pt_regs *regs, void *opaque)
 {
@@ -30,6 +31,18 @@ static void program_check_handler(struct pt_regs *regs, void *opaque)
 	regs->nip += 4;
 }
 
+static void alignment_handler(struct pt_regs *regs, void *opaque)
+{
+	int *data = opaque;
+
+	printf("Detected alignment exception 0x%016lx: %08x\n",
+	       regs->nip, *(uint32_t*)regs->nip);
+
+	*data = 1;
+
+	regs->nip += 4;
+}
+
 static void test_illegal(void)
 {
 	report_prefix_push("invalid");
@@ -73,6 +86,8 @@ static void test_64bit(void)
  * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
  * - RT = RA = 0 is invalid
  *
+ * For lswx in little-endian mode, an alignment interrupt always occurs.
+ *
  */
 
 static void test_lswx(void)
@@ -90,6 +105,7 @@ static void test_lswx(void)
 
 	/* check incomplete register filling */
 
+	alignment = 0;
 	asm volatile ("mtxer %[len];"
 		      "li r12,-1;"
 		      "mr r11, r12;"
@@ -103,7 +119,12 @@ static void test_lswx(void)
 		      :
 		      "xer", "r11", "r12", "memory");
 
+#if  __BYTE_ORDER__ = __ORDER_LITTLE_ENDIAN__
+	report("alignment", alignment);
+	return;
+#else
 	report("partial", regs[0] = 0x01020300 && regs[1] = (uint64_t)-1);
+#endif
 
 	/* check an old know bug: the number of bytes is used as
 	 * the number of registers, so try 32 bytes.
@@ -200,6 +221,7 @@ int main(int argc, char **argv)
 	int i;
 
 	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
+	handle_exception(0x600, alignment_handler, (void *)&alignment);
 
 	for (i = 0; i < argc; i++) {
 		if (strcmp(argv[i], "-v") = 0) {
-- 
2.5.0


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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
  2016-03-21 11:33   ` Laurent Vivier
@ 2016-03-21 12:07     ` Thomas Huth
  -1 siblings, 0 replies; 38+ messages in thread
From: Thomas Huth @ 2016-03-21 12:07 UTC (permalink / raw)
  To: Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, dgibson, pbonzini

On 21.03.2016 12:33, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
> v2:
>     use "mtxer" instead of "mtspr"
>     Fix comments in lswx asm()
>     add "memory" in clobber list
> 
>  powerpc/emulator.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 140 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index d97090c..8d0dde2 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -56,6 +56,145 @@ static void test_64bit(void)
>  	report_prefix_pop();
>  }
>  
> +/*
> + * lswx: Load String Word Indexed X-form
> + *
> + *     lswx RT,RA,RB
> + *
> + * EA = (RA|0) + RB
> + * n  = XER
> + *
> + * Load n bytes from address EA into (n / 4) consecutive registers,
> + * throught RT -> RT + (n / 4) - 1.
> + * - Data are loaded into 4 low order bytes of registers (Word).
> + * - The unfilled bytes are set to 0.
> + * - The sequence of registers wraps around to GPR0.
> + * - if n == 0, content of RT is undefined
> + * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
> + * - RT == RA == 0 is invalid
> + *
> + */
> +
> +static void test_lswx(void)
> +{
> +	int i;
> +	char addr[128];
> +	uint64_t regs[32];
> +
> +	report_prefix_push("lswx");
> +
> +	/* fill memory with sequence */
> +
> +	for (i = 0; i < 128; i++)
> +		addr[i] = 1 + i;
> +
> +	/* check incomplete register filling */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r12,-1;"
> +		      "mr r11, r12;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (3),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      "xer", "r11", "r12", "memory");
> +
> +	report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
> +
> +	/* check an old know bug: the number of bytes is used as
> +	 * the number of registers, so try 32 bytes.
> +	 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r19,-1;"
> +		      "mr r11, r19; mr r12, r19; mr r13, r19;"
> +		      "mr r14, r19; mr r15, r19; mr r16, r19;"
> +		      "mr r17, r19; mr r18, r19;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      "std r13, 2*8(%[regs]);"
> +		      "std r14, 3*8(%[regs]);"
> +		      "std r15, 4*8(%[regs]);"
> +		      "std r16, 5*8(%[regs]);"
> +		      "std r17, 6*8(%[regs]);"
> +		      "std r18, 7*8(%[regs]);"
> +		      "std r19, 8*8(%[regs]);"
> +		      ::
> +		      [len] "r" (32),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* as 32 is the number of bytes,
> +		       * we should modify 32/4 = 8 regs, from r11 to r18
> +		       * We check r19 is unmodified by filling it with 1s
> +		       * before the instruction.
> +		       */
> +		      "xer", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
> +		      "r18", "r19", "memory");
> +
> +	report("length", regs[0] == 0x01020304 && regs[1] == 0x05060708 &&
> +			 regs[2] == 0x090a0b0c && regs[3] == 0x0d0e0f10 &&
> +			 regs[4] == 0x11121314 && regs[5] == 0x15161718 &&
> +			 regs[6] == 0x191a1b1c && regs[7] == 0x1d1e1f20 &&
> +			 regs[8] == (uint64_t)-1);
> +
> +	/* check wrap around to r0 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r31,-1;"
> +		      "mr r0, r31;"
> +		      "lswx r31, 0, %[addr];"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (8),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* modify two registers from r31, wrap around to r0 */
> +		      "xer", "r31", "r0", "memory");
> +
> +	report("wrap around to r0", regs[0] == 0x01020304 &&
> +			            regs[1] == 0x05060708);
> +
> +	/* check wrap around to r0 over RB doesn't break RB */
> +
> +	asm volatile ("mtxer %[len];"
> +		      /* adding r1 in the clobber list doesn't protect it... */

You repeat that again in the comment below, so in case you respin this
series, you could also drop one of the two comments, I think.

> +		      "mr r29,r1;"
> +		      "li r31,-1;"
> +		      "mr r1,r31;"
> +		      "mr r0, %[addr];"
> +		      "lswx r31, 0, r0;"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      "std r1, 2*8(%[regs]);"
> +		      "mr r1,r29;"
> +		      ::
> +		      [len] "r" (12),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* three registers from r31, wrap arount to r1,
> +		       * r1 is saved to r29, as adding it to the clobber
> +		       * list doesn't protect it
> +		       */
> +		      "xer", "r31", "r0", "r29", "memory");
> +
> +	/* doc says it is invalid, real proc stops when it comes to
> +	 * overwrite the register.
> +	 * In all the cases, the register must stay untouched
> +	 */
> +	report("Don't overwrite Rb", regs[1] == (uint64_t)addr);
> +
> +	report_prefix_pop();
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	int i;
> @@ -72,6 +211,7 @@ int main(int argc, char **argv)
>  
>  	test_64bit();
>  	test_illegal();
> +	test_lswx();
>  
>  	report_prefix_pop();
>  
> 

Reviewed-by: Thomas Huth <thuth@redhat.com>


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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
@ 2016-03-21 12:07     ` Thomas Huth
  0 siblings, 0 replies; 38+ messages in thread
From: Thomas Huth @ 2016-03-21 12:07 UTC (permalink / raw)
  To: Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, dgibson, pbonzini

On 21.03.2016 12:33, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
> v2:
>     use "mtxer" instead of "mtspr"
>     Fix comments in lswx asm()
>     add "memory" in clobber list
> 
>  powerpc/emulator.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 140 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index d97090c..8d0dde2 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -56,6 +56,145 @@ static void test_64bit(void)
>  	report_prefix_pop();
>  }
>  
> +/*
> + * lswx: Load String Word Indexed X-form
> + *
> + *     lswx RT,RA,RB
> + *
> + * EA = (RA|0) + RB
> + * n  = XER
> + *
> + * Load n bytes from address EA into (n / 4) consecutive registers,
> + * throught RT -> RT + (n / 4) - 1.
> + * - Data are loaded into 4 low order bytes of registers (Word).
> + * - The unfilled bytes are set to 0.
> + * - The sequence of registers wraps around to GPR0.
> + * - if n = 0, content of RT is undefined
> + * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
> + * - RT = RA = 0 is invalid
> + *
> + */
> +
> +static void test_lswx(void)
> +{
> +	int i;
> +	char addr[128];
> +	uint64_t regs[32];
> +
> +	report_prefix_push("lswx");
> +
> +	/* fill memory with sequence */
> +
> +	for (i = 0; i < 128; i++)
> +		addr[i] = 1 + i;
> +
> +	/* check incomplete register filling */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r12,-1;"
> +		      "mr r11, r12;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (3),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      "xer", "r11", "r12", "memory");
> +
> +	report("partial", regs[0] = 0x01020300 && regs[1] = (uint64_t)-1);
> +
> +	/* check an old know bug: the number of bytes is used as
> +	 * the number of registers, so try 32 bytes.
> +	 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r19,-1;"
> +		      "mr r11, r19; mr r12, r19; mr r13, r19;"
> +		      "mr r14, r19; mr r15, r19; mr r16, r19;"
> +		      "mr r17, r19; mr r18, r19;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      "std r13, 2*8(%[regs]);"
> +		      "std r14, 3*8(%[regs]);"
> +		      "std r15, 4*8(%[regs]);"
> +		      "std r16, 5*8(%[regs]);"
> +		      "std r17, 6*8(%[regs]);"
> +		      "std r18, 7*8(%[regs]);"
> +		      "std r19, 8*8(%[regs]);"
> +		      ::
> +		      [len] "r" (32),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* as 32 is the number of bytes,
> +		       * we should modify 32/4 = 8 regs, from r11 to r18
> +		       * We check r19 is unmodified by filling it with 1s
> +		       * before the instruction.
> +		       */
> +		      "xer", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
> +		      "r18", "r19", "memory");
> +
> +	report("length", regs[0] = 0x01020304 && regs[1] = 0x05060708 &&
> +			 regs[2] = 0x090a0b0c && regs[3] = 0x0d0e0f10 &&
> +			 regs[4] = 0x11121314 && regs[5] = 0x15161718 &&
> +			 regs[6] = 0x191a1b1c && regs[7] = 0x1d1e1f20 &&
> +			 regs[8] = (uint64_t)-1);
> +
> +	/* check wrap around to r0 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r31,-1;"
> +		      "mr r0, r31;"
> +		      "lswx r31, 0, %[addr];"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (8),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* modify two registers from r31, wrap around to r0 */
> +		      "xer", "r31", "r0", "memory");
> +
> +	report("wrap around to r0", regs[0] = 0x01020304 &&
> +			            regs[1] = 0x05060708);
> +
> +	/* check wrap around to r0 over RB doesn't break RB */
> +
> +	asm volatile ("mtxer %[len];"
> +		      /* adding r1 in the clobber list doesn't protect it... */

You repeat that again in the comment below, so in case you respin this
series, you could also drop one of the two comments, I think.

> +		      "mr r29,r1;"
> +		      "li r31,-1;"
> +		      "mr r1,r31;"
> +		      "mr r0, %[addr];"
> +		      "lswx r31, 0, r0;"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      "std r1, 2*8(%[regs]);"
> +		      "mr r1,r29;"
> +		      ::
> +		      [len] "r" (12),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* three registers from r31, wrap arount to r1,
> +		       * r1 is saved to r29, as adding it to the clobber
> +		       * list doesn't protect it
> +		       */
> +		      "xer", "r31", "r0", "r29", "memory");
> +
> +	/* doc says it is invalid, real proc stops when it comes to
> +	 * overwrite the register.
> +	 * In all the cases, the register must stay untouched
> +	 */
> +	report("Don't overwrite Rb", regs[1] = (uint64_t)addr);
> +
> +	report_prefix_pop();
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	int i;
> @@ -72,6 +211,7 @@ int main(int argc, char **argv)
>  
>  	test_64bit();
>  	test_illegal();
> +	test_lswx();
>  
>  	report_prefix_pop();
>  
> 

Reviewed-by: Thomas Huth <thuth@redhat.com>


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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
  2016-03-21 12:07     ` Thomas Huth
@ 2016-03-21 14:25       ` Paolo Bonzini
  -1 siblings, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2016-03-21 14:25 UTC (permalink / raw)
  To: Thomas Huth, Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, dgibson



On 21/03/2016 13:07, Thomas Huth wrote:
>> > +		      /* adding r1 in the clobber list doesn't protect it... */
> You repeat that again in the comment below, so in case you respin this
> series, you could also drop one of the two comments, I think.

I can do it while fixing the typo (arount->around).

Paolo

>> > +		      "mr r29,r1;"
>> > +		      "li r31,-1;"
>> > +		      "mr r1,r31;"
>> > +		      "mr r0, %[addr];"
>> > +		      "lswx r31, 0, r0;"
>> > +		      "std r31, 0*8(%[regs]);"
>> > +		      "std r0, 1*8(%[regs]);"
>> > +		      "std r1, 2*8(%[regs]);"
>> > +		      "mr r1,r29;"
>> > +		      ::
>> > +		      [len] "r" (12),
>> > +		      [addr] "r" (addr),
>> > +		      [regs] "r" (regs)
>> > +		      :
>> > +		      /* three registers from r31, wrap arount to r1,

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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
@ 2016-03-21 14:25       ` Paolo Bonzini
  0 siblings, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2016-03-21 14:25 UTC (permalink / raw)
  To: Thomas Huth, Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, dgibson



On 21/03/2016 13:07, Thomas Huth wrote:
>> > +		      /* adding r1 in the clobber list doesn't protect it... */
> You repeat that again in the comment below, so in case you respin this
> series, you could also drop one of the two comments, I think.

I can do it while fixing the typo (arount->around).

Paolo

>> > +		      "mr r29,r1;"
>> > +		      "li r31,-1;"
>> > +		      "mr r1,r31;"
>> > +		      "mr r0, %[addr];"
>> > +		      "lswx r31, 0, r0;"
>> > +		      "std r31, 0*8(%[regs]);"
>> > +		      "std r0, 1*8(%[regs]);"
>> > +		      "std r1, 2*8(%[regs]);"
>> > +		      "mr r1,r29;"
>> > +		      ::
>> > +		      [len] "r" (12),
>> > +		      [addr] "r" (addr),
>> > +		      [regs] "r" (regs)
>> > +		      :
>> > +		      /* three registers from r31, wrap arount to r1,

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

* Re: [kvm-unit-tests PATCH v2 2/5] powerpc: add test to check invalid instruction trap
  2016-03-21 11:33   ` Laurent Vivier
@ 2016-03-21 14:57     ` Thomas Huth
  -1 siblings, 0 replies; 38+ messages in thread
From: Thomas Huth @ 2016-03-21 14:57 UTC (permalink / raw)
  To: Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, dgibson, pbonzini

On 21.03.2016 12:33, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
> v2:
>     check program check type (invalid instruction)
>     add "-v" parameter to display invalid instruction address
> 
>  powerpc/Makefile.common |  5 +++-
>  powerpc/emulator.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
>  powerpc/unittests.cfg   |  3 +++
>  3 files changed, 72 insertions(+), 1 deletion(-)
>  create mode 100644 powerpc/emulator.c
> 
> diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
> index ab2caf6..257e3fb 100644
> --- a/powerpc/Makefile.common
> +++ b/powerpc/Makefile.common
> @@ -7,7 +7,8 @@
>  tests-common = \
>  	$(TEST_DIR)/selftest.elf \
>  	$(TEST_DIR)/spapr_hcall.elf \
> -	$(TEST_DIR)/rtas.elf
> +	$(TEST_DIR)/rtas.elf \
> +	$(TEST_DIR)/emulator.elf
>  
>  all: $(TEST_DIR)/boot_rom.bin test_cases
>  
> @@ -70,3 +71,5 @@ $(TEST_DIR)/selftest.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/selftest.o
>  $(TEST_DIR)/spapr_hcall.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/spapr_hcall.o
>  
>  $(TEST_DIR)/rtas.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/rtas.o
> +
> +$(TEST_DIR)/emulator.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/emulator.o
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> new file mode 100644
> index 0000000..1d4f164
> --- /dev/null
> +++ b/powerpc/emulator.c
> @@ -0,0 +1,65 @@
> +/*
> + * Test some powerpc instructions
> + */
> +
> +#include <libcflat.h>
> +#include <asm/processor.h>
> +
> +static int verbose;
> +static int volatile is_invalid;
> +
> +static void program_check_handler(struct pt_regs *regs, void *opaque)
> +{
> +	int *data = opaque;
> +
> +	if (verbose) {
> +		printf("Detected invalid instruction 0x%016lx: %08x\n",
> +		       regs->nip, *(uint32_t*)regs->nip);
> +	}
> +
> +	/* the result is bit 16 to 19 of SRR1
> +	 * bit 0: SRR0 contains the address of the next instruction
> +	 * bit 1: Trap
> +	 * bit 2: Privileged instruction
> +	 * bit 3: Illegal instruction
> +	 * bit 4: FP enabled exception type
> +	 */
> +
> +	*data = regs->msr >> 16;
> +
> +	regs->nip += 4;
> +}
> +
> +static void test_illegal(void)
> +{
> +	report_prefix_push("invalid");
> +
> +	is_invalid = 0;
> +
> +	asm volatile (".long 0");
> +
> +	report("exception", is_invalid == 8); /* illegal instruction */
> +
> +	report_prefix_pop();
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	int i;
> +
> +	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +
> +	for (i = 0; i < argc; i++) {
> +		if (strcmp(argv[i], "-v") == 0) {
> +			verbose = 1;
> +		}
> +	}
> +
> +	report_prefix_push("emulator");
> +
> +	test_illegal();
> +
> +	report_prefix_pop();
> +
> +	return report_summary();
> +}
> diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg
> index 02b21c7..ed4fdbe 100644
> --- a/powerpc/unittests.cfg
> +++ b/powerpc/unittests.cfg
> @@ -47,3 +47,6 @@ file = rtas.elf
>  extra_params = -append "set-time-of-day"
>  timeout = 5
>  groups = rtas
> +
> +[emulator]
> +file = emulator.elf
> 

Reviewed-by: Thomas Huth <thuth@redhat.com>


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

* Re: [kvm-unit-tests PATCH v2 2/5] powerpc: add test to check invalid instruction trap
@ 2016-03-21 14:57     ` Thomas Huth
  0 siblings, 0 replies; 38+ messages in thread
From: Thomas Huth @ 2016-03-21 14:57 UTC (permalink / raw)
  To: Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, dgibson, pbonzini

On 21.03.2016 12:33, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
> v2:
>     check program check type (invalid instruction)
>     add "-v" parameter to display invalid instruction address
> 
>  powerpc/Makefile.common |  5 +++-
>  powerpc/emulator.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
>  powerpc/unittests.cfg   |  3 +++
>  3 files changed, 72 insertions(+), 1 deletion(-)
>  create mode 100644 powerpc/emulator.c
> 
> diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
> index ab2caf6..257e3fb 100644
> --- a/powerpc/Makefile.common
> +++ b/powerpc/Makefile.common
> @@ -7,7 +7,8 @@
>  tests-common = \
>  	$(TEST_DIR)/selftest.elf \
>  	$(TEST_DIR)/spapr_hcall.elf \
> -	$(TEST_DIR)/rtas.elf
> +	$(TEST_DIR)/rtas.elf \
> +	$(TEST_DIR)/emulator.elf
>  
>  all: $(TEST_DIR)/boot_rom.bin test_cases
>  
> @@ -70,3 +71,5 @@ $(TEST_DIR)/selftest.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/selftest.o
>  $(TEST_DIR)/spapr_hcall.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/spapr_hcall.o
>  
>  $(TEST_DIR)/rtas.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/rtas.o
> +
> +$(TEST_DIR)/emulator.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/emulator.o
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> new file mode 100644
> index 0000000..1d4f164
> --- /dev/null
> +++ b/powerpc/emulator.c
> @@ -0,0 +1,65 @@
> +/*
> + * Test some powerpc instructions
> + */
> +
> +#include <libcflat.h>
> +#include <asm/processor.h>
> +
> +static int verbose;
> +static int volatile is_invalid;
> +
> +static void program_check_handler(struct pt_regs *regs, void *opaque)
> +{
> +	int *data = opaque;
> +
> +	if (verbose) {
> +		printf("Detected invalid instruction 0x%016lx: %08x\n",
> +		       regs->nip, *(uint32_t*)regs->nip);
> +	}
> +
> +	/* the result is bit 16 to 19 of SRR1
> +	 * bit 0: SRR0 contains the address of the next instruction
> +	 * bit 1: Trap
> +	 * bit 2: Privileged instruction
> +	 * bit 3: Illegal instruction
> +	 * bit 4: FP enabled exception type
> +	 */
> +
> +	*data = regs->msr >> 16;
> +
> +	regs->nip += 4;
> +}
> +
> +static void test_illegal(void)
> +{
> +	report_prefix_push("invalid");
> +
> +	is_invalid = 0;
> +
> +	asm volatile (".long 0");
> +
> +	report("exception", is_invalid = 8); /* illegal instruction */
> +
> +	report_prefix_pop();
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	int i;
> +
> +	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +
> +	for (i = 0; i < argc; i++) {
> +		if (strcmp(argv[i], "-v") = 0) {
> +			verbose = 1;
> +		}
> +	}
> +
> +	report_prefix_push("emulator");
> +
> +	test_illegal();
> +
> +	report_prefix_pop();
> +
> +	return report_summary();
> +}
> diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg
> index 02b21c7..ed4fdbe 100644
> --- a/powerpc/unittests.cfg
> +++ b/powerpc/unittests.cfg
> @@ -47,3 +47,6 @@ file = rtas.elf
>  extra_params = -append "set-time-of-day"
>  timeout = 5
>  groups = rtas
> +
> +[emulator]
> +file = emulator.elf
> 

Reviewed-by: Thomas Huth <thuth@redhat.com>


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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
  2016-03-21 14:25       ` Paolo Bonzini
@ 2016-03-21 15:59         ` Laurent Vivier
  -1 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 15:59 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, kvm, kvm-ppc; +Cc: drjones, dgibson



On 21/03/2016 15:25, Paolo Bonzini wrote:
> 
> 
> On 21/03/2016 13:07, Thomas Huth wrote:
>>>> +		      /* adding r1 in the clobber list doesn't protect it... */
>> You repeat that again in the comment below, so in case you respin this
>> series, you could also drop one of the two comments, I think.
> 
> I can do it while fixing the typo (arount->around).

Yes, please.

Thanks,
Laurent
> 
> Paolo
> 
>>>> +		      "mr r29,r1;"
>>>> +		      "li r31,-1;"
>>>> +		      "mr r1,r31;"
>>>> +		      "mr r0, %[addr];"
>>>> +		      "lswx r31, 0, r0;"
>>>> +		      "std r31, 0*8(%[regs]);"
>>>> +		      "std r0, 1*8(%[regs]);"
>>>> +		      "std r1, 2*8(%[regs]);"
>>>> +		      "mr r1,r29;"
>>>> +		      ::
>>>> +		      [len] "r" (12),
>>>> +		      [addr] "r" (addr),
>>>> +		      [regs] "r" (regs)
>>>> +		      :
>>>> +		      /* three registers from r31, wrap arount to r1,

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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
@ 2016-03-21 15:59         ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-21 15:59 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, kvm, kvm-ppc; +Cc: drjones, dgibson



On 21/03/2016 15:25, Paolo Bonzini wrote:
> 
> 
> On 21/03/2016 13:07, Thomas Huth wrote:
>>>> +		      /* adding r1 in the clobber list doesn't protect it... */
>> You repeat that again in the comment below, so in case you respin this
>> series, you could also drop one of the two comments, I think.
> 
> I can do it while fixing the typo (arount->around).

Yes, please.

Thanks,
Laurent
> 
> Paolo
> 
>>>> +		      "mr r29,r1;"
>>>> +		      "li r31,-1;"
>>>> +		      "mr r1,r31;"
>>>> +		      "mr r0, %[addr];"
>>>> +		      "lswx r31, 0, r0;"
>>>> +		      "std r31, 0*8(%[regs]);"
>>>> +		      "std r0, 1*8(%[regs]);"
>>>> +		      "std r1, 2*8(%[regs]);"
>>>> +		      "mr r1,r29;"
>>>> +		      ::
>>>> +		      [len] "r" (12),
>>>> +		      [addr] "r" (addr),
>>>> +		      [regs] "r" (regs)
>>>> +		      :
>>>> +		      /* three registers from r31, wrap arount to r1,

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

* Re: [kvm-unit-tests PATCH v2 1/5] powerpc: add exception handler
  2016-03-21 11:33   ` Laurent Vivier
@ 2016-03-21 23:47     ` David Gibson
  -1 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:47 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:30 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

I'm still not overly fond of the trap >> 8 trick, but it's something we
can fix later if necessary.

> ---
> v2:
>     clearly restore r1 in call_handler
>     use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"
> 
>  lib/powerpc/asm/hcall.h     |   1 +
>  lib/powerpc/asm/ppc_asm.h   |   5 ++
>  lib/powerpc/asm/processor.h |  11 ++++
>  lib/powerpc/processor.c     |  38 ++++++++++++
>  lib/powerpc/setup.c         |  19 ++++++
>  lib/ppc64/asm-offsets.c     |  42 +++++++++++++
>  lib/ppc64/asm/processor.h   |   1 +
>  lib/ppc64/asm/ptrace.h      |  24 ++++++++
>  powerpc/Makefile.common     |   1 +
>  powerpc/cstart64.S          | 140 ++++++++++++++++++++++++++++++++++++++++++++
>  10 files changed, 282 insertions(+)
>  create mode 100644 lib/powerpc/asm/processor.h
>  create mode 100644 lib/powerpc/processor.c
>  create mode 100644 lib/ppc64/asm/processor.h
>  create mode 100644 lib/ppc64/asm/ptrace.h
> 
> diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h
> index f6f9ea8..99bce79 100644
> --- a/lib/powerpc/asm/hcall.h
> +++ b/lib/powerpc/asm/hcall.h
> @@ -20,6 +20,7 @@
>  #define H_PAGE_INIT		0x2c
>  #define H_PUT_TERM_CHAR		0x58
>  #define H_RANDOM		0x300
> +#define H_SET_MODE		0x31C
>  
>  #ifndef __ASSEMBLY__
>  /*
> diff --git a/lib/powerpc/asm/ppc_asm.h b/lib/powerpc/asm/ppc_asm.h
> index f18100e..39620a3 100644
> --- a/lib/powerpc/asm/ppc_asm.h
> +++ b/lib/powerpc/asm/ppc_asm.h
> @@ -1,6 +1,11 @@
>  #ifndef _ASMPOWERPC_PPC_ASM_H
>  #define _ASMPOWERPC_PPC_ASM_H
>  
> +#include <asm/asm-offsets.h>
> +
> +#define SAVE_GPR(n, base)	std	n,GPR0+8*(n)(base)
> +#define REST_GPR(n, base)	ld	n,GPR0+8*(n)(base)
> +
>  #define LOAD_REG_IMMEDIATE(reg,expr)		\
>  	lis	reg,(expr)@highest;		\
>  	ori	reg,reg,(expr)@higher;		\
> diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
> new file mode 100644
> index 0000000..09692bd
> --- /dev/null
> +++ b/lib/powerpc/asm/processor.h
> @@ -0,0 +1,11 @@
> +#ifndef _ASMPOWERPC_PROCESSOR_H_
> +#define _ASMPOWERPC_PROCESSOR_H_
> +
> +#include <asm/ptrace.h>
> +
> +#ifndef __ASSEMBLY__
> +void handle_exception(int trap, void (*func)(struct pt_regs *, void *), void *);
> +void do_handle_exception(struct pt_regs *regs);
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _ASMPOWERPC_PROCESSOR_H_ */
> diff --git a/lib/powerpc/processor.c b/lib/powerpc/processor.c
> new file mode 100644
> index 0000000..a78bc3c
> --- /dev/null
> +++ b/lib/powerpc/processor.c
> @@ -0,0 +1,38 @@
> +/*
> + * processor control and status function
> + */
> +
> +#include <libcflat.h>
> +#include <asm/processor.h>
> +#include <asm/ptrace.h>
> +
> +static struct {
> +	void (*func)(struct pt_regs *, void *data);
> +	void *data;
> +} handlers[16];
> +
> +void handle_exception(int trap, void (*func)(struct pt_regs *, void *),
> +		      void * data)
> +{
> +	trap >>= 8;
> +
> +	if (trap < 16) {
> +		handlers[trap].func = func;
> +		handlers[trap].data = data;
> +	}
> +}
> +
> +void do_handle_exception(struct pt_regs *regs)
> +{
> +	unsigned char v;
> +
> +	v = regs->trap >> 8;
> +
> +	if (v < 16 && handlers[v].func) {
> +		handlers[v].func(regs, handlers[v].data);
> +		return;
> +	}
> +
> +	printf("unhandled cpu exception 0x%lx\n", regs->trap);
> +	abort();
> +}
> diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> index 0c0c882..e3cf952 100644
> --- a/lib/powerpc/setup.c
> +++ b/lib/powerpc/setup.c
> @@ -16,6 +16,8 @@
>  #include <alloc.h>
>  #include <asm/setup.h>
>  #include <asm/page.h>
> +#include <asm/ppc_asm.h>
> +#include <asm/hcall.h>
>  
>  extern unsigned long stacktop;
>  extern void io_init(void);
> @@ -33,6 +35,10 @@ struct cpu_set_params {
>  	unsigned dcache_bytes;
>  };
>  
> +#define EXCEPTION_STACK_SIZE	(32*1024) /* 32kB */
> +
> +static char exception_stack[NR_CPUS][EXCEPTION_STACK_SIZE];
> +
>  static void cpu_set(int fdtnode, u32 regval, void *info)
>  {
>  	static bool read_common_info = false;
> @@ -46,6 +52,11 @@ static void cpu_set(int fdtnode, u32 regval, void *info)
>  	}
>  	cpus[cpu] = regval;
>  
> +	/* set exception stack address for this CPU (in SPGR0) */
> +
> +	asm volatile ("mtsprg0 %[addr]" ::
> +		      [addr] "r" (exception_stack[cpu + 1]));
> +
>  	if (!read_common_info) {
>  		const struct fdt_property *prop;
>  		u32 *data;
> @@ -76,6 +87,14 @@ static void cpu_init(void)
>  	assert(ret == 0);
>  	__icache_bytes = params.icache_bytes;
>  	__dcache_bytes = params.dcache_bytes;
> +
> +	/* Interrupt Endianness */
> +
> +#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> +        hcall(H_SET_MODE, 1, 4, 0, 0);
> +#else
> +        hcall(H_SET_MODE, 0, 4, 0, 0);
> +#endif
>  }
>  
>  static void mem_init(phys_addr_t freemem_start)
> diff --git a/lib/ppc64/asm-offsets.c b/lib/ppc64/asm-offsets.c
> index 2d38a71..7843a20 100644
> --- a/lib/ppc64/asm-offsets.c
> +++ b/lib/ppc64/asm-offsets.c
> @@ -5,8 +5,50 @@
>   */
>  #include <libcflat.h>
>  #include <kbuild.h>
> +#include <asm/ptrace.h>
>  
>  int main(void)
>  {
> +	DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
> +
> +	DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
> +	DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
> +	DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
> +	DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
> +	DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
> +	DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
> +	DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
> +	DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
> +	DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
> +	DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
> +	DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
> +	DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
> +	DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
> +	DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
> +	DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
> +	DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
> +	DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
> +	DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
> +	DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
> +	DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
> +	DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
> +	DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
> +	DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
> +	DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
> +	DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
> +	DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
> +	DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
> +	DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
> +	DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
> +	DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
> +	DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
> +	DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
> +	DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
> +	DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
> +	DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
> +	DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
> +	DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
> +	DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
> +	DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
>  	return 0;
>  }
> diff --git a/lib/ppc64/asm/processor.h b/lib/ppc64/asm/processor.h
> new file mode 100644
> index 0000000..066a51a
> --- /dev/null
> +++ b/lib/ppc64/asm/processor.h
> @@ -0,0 +1 @@
> +#include "../../powerpc/asm/processor.h"
> diff --git a/lib/ppc64/asm/ptrace.h b/lib/ppc64/asm/ptrace.h
> new file mode 100644
> index 0000000..076c9d9
> --- /dev/null
> +++ b/lib/ppc64/asm/ptrace.h
> @@ -0,0 +1,24 @@
> +#ifndef _ASMPPC64_PTRACE_H_
> +#define _ASMPPC64_PTRACE_H_
> +
> +#define KERNEL_REDZONE_SIZE	288
> +#define STACK_FRAME_OVERHEAD    112     /* size of minimum stack frame */
> +
> +#ifndef __ASSEMBLY__
> +struct pt_regs {
> +	unsigned long gpr[32];
> +	unsigned long nip;
> +	unsigned long msr;
> +	unsigned long ctr;
> +	unsigned long link;
> +	unsigned long xer;
> +	unsigned long ccr;
> +	unsigned long trap;
> +};
> +
> +#define STACK_INT_FRAME_SIZE    (sizeof(struct pt_regs) + \
> +				 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _ASMPPC64_PTRACE_H_ */
> diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
> index 424983e..ab2caf6 100644
> --- a/powerpc/Makefile.common
> +++ b/powerpc/Makefile.common
> @@ -31,6 +31,7 @@ cflatobjs += lib/powerpc/io.o
>  cflatobjs += lib/powerpc/hcall.o
>  cflatobjs += lib/powerpc/setup.o
>  cflatobjs += lib/powerpc/rtas.o
> +cflatobjs += lib/powerpc/processor.o
>  
>  FLATLIBS = $(libcflat) $(LIBFDT_archive)
>  %.elf: CFLAGS += $(arch_CFLAGS)
> diff --git a/powerpc/cstart64.S b/powerpc/cstart64.S
> index c87e3d6..ceb6397 100644
> --- a/powerpc/cstart64.S
> +++ b/powerpc/cstart64.S
> @@ -9,6 +9,7 @@
>  #include <asm/hcall.h>
>  #include <asm/ppc_asm.h>
>  #include <asm/rtas.h>
> +#include <asm/ptrace.h>
>  
>  .section .init
>  
> @@ -45,6 +46,34 @@ start:
>  	add	r4, r4, r31
>  	bl	relocate
>  
> +	/* relocate vector table to base address 0x0 (MSR_IP = 0) */
> +
> +	/* source: r4, dest end: r5, destination: r6 */
> +
> +	LOAD_REG_ADDR(r4, __start_interrupts)
> +	LOAD_REG_ADDR(r5, __end_interrupts)
> +	sub	r5,r5,r4
> +	li	r6,0x100
> +
> +	sub	r4,r4,r6
> +	add	r5,r5,r6
> +	addi	r6,r6,-8
> +2:	li	r0,8
> +	mtctr	r0
> +	/* copy a cache line size */
> +3:	addi	r6,r6,8
> +	ldx	r0,r6,r4
> +	stdx	r0,0,r6
> +	bdnz	3b
> +	dcbst	0,r6
> +	/* flush icache */
> +	sync
> +	icbi	0,r6
> +	cmpld	0,r6,r5
> +	blt	2b
> +	sync
> +	isync
> +
>  	/* patch sc1 if needed */
>  	bl	hcall_have_broken_sc1
>  	cmpwi	r3, 0
> @@ -105,3 +134,114 @@ rtas_return_loc:
>  	ld	r0, 16(r1)
>  	mtlr	r0
>  	blr
> +
> +call_handler:
> +	/* save context */
> +
> +	/* GPRs */
> +
> +	.irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
> +	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
> +		SAVE_GPR(\i, r1)
> +	.endr
> +	mfsprg1	r0
> +	std	r0,GPR1(r1)
> +
> +	/* lr, xer, ccr */
> +
> +	mflr	r0
> +	std	r0,_LINK(r1)
> +
> +	mfxer	r0
> +	std	r0,_XER(r1)
> +
> +	mfcr	r0
> +	std	r0,_CCR(r1)
> +
> +	/* nip and msr */
> +
> +	mfsrr0	r0
> +	std	r0, _NIP(r1)
> +
> +	mfsrr1	r0
> +	std	r0, _MSR(r1)
> +
> +	/* FIXME: build stack frame */
> +
> +	/* call generic handler */
> +
> +	addi	r3,r1,STACK_FRAME_OVERHEAD
> +	bl	do_handle_exception
> +
> +	/* restore context */
> +
> +	ld	r0,_CTR(r1)
> +	mtctr	r0
> +
> +	ld	r0,_LINK(r1)
> +	mtlr	r0
> +
> +	ld	r0,_XER(r1)
> +	mtxer	r0
> +
> +	ld	r0,_CCR(r1)
> +	mtcr	r0
> +
> +	ld	r0, _NIP(r1)
> +	mtsrr0	r0
> +
> +	ld	r0, _MSR(r1)
> +	mtsrr1	r0
> +
> +	.irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
> +	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
> +		REST_GPR(\i, r1)
> +	.endr
> +
> +	/* restore r1, as we don't need it anymore */
> +
> +	REST_GPR(1,r1)
> +
> +	rfid
> +	b .
> +
> +.section .text.ex
> +
> +.macro VECTOR vec
> +	. = \vec
> +
> +	mtsprg1	r1	/* save r1 */
> +	mfsprg0	r1	/* get exception stack address */
> +	subi	r1,r1, INT_FRAME_SIZE
> +
> +	/* save r0 and ctr to call generic handler */
> +
> +	SAVE_GPR(0,r1)
> +
> +	mfctr	r0
> +	std	r0,_CTR(r1)
> +
> +	LOAD_REG_ADDR(r0, call_handler)
> +	mtctr	r0
> +
> +	li	r0,\vec
> +	std	r0,_TRAP(r1)
> +
> +	bctr
> +.endm
> +
> +	. = 0x100
> +	.globl __start_interrupts
> +__start_interrupts:
> +
> +VECTOR(0x300)
> +VECTOR(0x400)
> +VECTOR(0x500)
> +VECTOR(0x600)
> +VECTOR(0x700)
> +VECTOR(0x800)
> +VECTOR(0x900)
> +
> +	.align 7
> +	.globl __end_interrupts
> +__end_interrupts:
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 1/5] powerpc: add exception handler
@ 2016-03-21 23:47     ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:47 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:30 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

I'm still not overly fond of the trap >> 8 trick, but it's something we
can fix later if necessary.

> ---
> v2:
>     clearly restore r1 in call_handler
>     use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"
> 
>  lib/powerpc/asm/hcall.h     |   1 +
>  lib/powerpc/asm/ppc_asm.h   |   5 ++
>  lib/powerpc/asm/processor.h |  11 ++++
>  lib/powerpc/processor.c     |  38 ++++++++++++
>  lib/powerpc/setup.c         |  19 ++++++
>  lib/ppc64/asm-offsets.c     |  42 +++++++++++++
>  lib/ppc64/asm/processor.h   |   1 +
>  lib/ppc64/asm/ptrace.h      |  24 ++++++++
>  powerpc/Makefile.common     |   1 +
>  powerpc/cstart64.S          | 140 ++++++++++++++++++++++++++++++++++++++++++++
>  10 files changed, 282 insertions(+)
>  create mode 100644 lib/powerpc/asm/processor.h
>  create mode 100644 lib/powerpc/processor.c
>  create mode 100644 lib/ppc64/asm/processor.h
>  create mode 100644 lib/ppc64/asm/ptrace.h
> 
> diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h
> index f6f9ea8..99bce79 100644
> --- a/lib/powerpc/asm/hcall.h
> +++ b/lib/powerpc/asm/hcall.h
> @@ -20,6 +20,7 @@
>  #define H_PAGE_INIT		0x2c
>  #define H_PUT_TERM_CHAR		0x58
>  #define H_RANDOM		0x300
> +#define H_SET_MODE		0x31C
>  
>  #ifndef __ASSEMBLY__
>  /*
> diff --git a/lib/powerpc/asm/ppc_asm.h b/lib/powerpc/asm/ppc_asm.h
> index f18100e..39620a3 100644
> --- a/lib/powerpc/asm/ppc_asm.h
> +++ b/lib/powerpc/asm/ppc_asm.h
> @@ -1,6 +1,11 @@
>  #ifndef _ASMPOWERPC_PPC_ASM_H
>  #define _ASMPOWERPC_PPC_ASM_H
>  
> +#include <asm/asm-offsets.h>
> +
> +#define SAVE_GPR(n, base)	std	n,GPR0+8*(n)(base)
> +#define REST_GPR(n, base)	ld	n,GPR0+8*(n)(base)
> +
>  #define LOAD_REG_IMMEDIATE(reg,expr)		\
>  	lis	reg,(expr)@highest;		\
>  	ori	reg,reg,(expr)@higher;		\
> diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
> new file mode 100644
> index 0000000..09692bd
> --- /dev/null
> +++ b/lib/powerpc/asm/processor.h
> @@ -0,0 +1,11 @@
> +#ifndef _ASMPOWERPC_PROCESSOR_H_
> +#define _ASMPOWERPC_PROCESSOR_H_
> +
> +#include <asm/ptrace.h>
> +
> +#ifndef __ASSEMBLY__
> +void handle_exception(int trap, void (*func)(struct pt_regs *, void *), void *);
> +void do_handle_exception(struct pt_regs *regs);
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _ASMPOWERPC_PROCESSOR_H_ */
> diff --git a/lib/powerpc/processor.c b/lib/powerpc/processor.c
> new file mode 100644
> index 0000000..a78bc3c
> --- /dev/null
> +++ b/lib/powerpc/processor.c
> @@ -0,0 +1,38 @@
> +/*
> + * processor control and status function
> + */
> +
> +#include <libcflat.h>
> +#include <asm/processor.h>
> +#include <asm/ptrace.h>
> +
> +static struct {
> +	void (*func)(struct pt_regs *, void *data);
> +	void *data;
> +} handlers[16];
> +
> +void handle_exception(int trap, void (*func)(struct pt_regs *, void *),
> +		      void * data)
> +{
> +	trap >>= 8;
> +
> +	if (trap < 16) {
> +		handlers[trap].func = func;
> +		handlers[trap].data = data;
> +	}
> +}
> +
> +void do_handle_exception(struct pt_regs *regs)
> +{
> +	unsigned char v;
> +
> +	v = regs->trap >> 8;
> +
> +	if (v < 16 && handlers[v].func) {
> +		handlers[v].func(regs, handlers[v].data);
> +		return;
> +	}
> +
> +	printf("unhandled cpu exception 0x%lx\n", regs->trap);
> +	abort();
> +}
> diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> index 0c0c882..e3cf952 100644
> --- a/lib/powerpc/setup.c
> +++ b/lib/powerpc/setup.c
> @@ -16,6 +16,8 @@
>  #include <alloc.h>
>  #include <asm/setup.h>
>  #include <asm/page.h>
> +#include <asm/ppc_asm.h>
> +#include <asm/hcall.h>
>  
>  extern unsigned long stacktop;
>  extern void io_init(void);
> @@ -33,6 +35,10 @@ struct cpu_set_params {
>  	unsigned dcache_bytes;
>  };
>  
> +#define EXCEPTION_STACK_SIZE	(32*1024) /* 32kB */
> +
> +static char exception_stack[NR_CPUS][EXCEPTION_STACK_SIZE];
> +
>  static void cpu_set(int fdtnode, u32 regval, void *info)
>  {
>  	static bool read_common_info = false;
> @@ -46,6 +52,11 @@ static void cpu_set(int fdtnode, u32 regval, void *info)
>  	}
>  	cpus[cpu] = regval;
>  
> +	/* set exception stack address for this CPU (in SPGR0) */
> +
> +	asm volatile ("mtsprg0 %[addr]" ::
> +		      [addr] "r" (exception_stack[cpu + 1]));
> +
>  	if (!read_common_info) {
>  		const struct fdt_property *prop;
>  		u32 *data;
> @@ -76,6 +87,14 @@ static void cpu_init(void)
>  	assert(ret == 0);
>  	__icache_bytes = params.icache_bytes;
>  	__dcache_bytes = params.dcache_bytes;
> +
> +	/* Interrupt Endianness */
> +
> +#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> +        hcall(H_SET_MODE, 1, 4, 0, 0);
> +#else
> +        hcall(H_SET_MODE, 0, 4, 0, 0);
> +#endif
>  }
>  
>  static void mem_init(phys_addr_t freemem_start)
> diff --git a/lib/ppc64/asm-offsets.c b/lib/ppc64/asm-offsets.c
> index 2d38a71..7843a20 100644
> --- a/lib/ppc64/asm-offsets.c
> +++ b/lib/ppc64/asm-offsets.c
> @@ -5,8 +5,50 @@
>   */
>  #include <libcflat.h>
>  #include <kbuild.h>
> +#include <asm/ptrace.h>
>  
>  int main(void)
>  {
> +	DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
> +
> +	DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
> +	DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
> +	DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
> +	DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
> +	DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
> +	DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
> +	DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
> +	DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
> +	DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
> +	DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
> +	DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
> +	DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
> +	DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
> +	DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
> +	DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
> +	DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
> +	DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
> +	DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
> +	DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
> +	DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
> +	DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
> +	DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
> +	DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
> +	DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
> +	DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
> +	DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
> +	DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
> +	DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
> +	DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
> +	DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
> +	DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
> +	DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
> +	DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
> +	DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
> +	DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
> +	DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
> +	DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
> +	DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
> +	DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
>  	return 0;
>  }
> diff --git a/lib/ppc64/asm/processor.h b/lib/ppc64/asm/processor.h
> new file mode 100644
> index 0000000..066a51a
> --- /dev/null
> +++ b/lib/ppc64/asm/processor.h
> @@ -0,0 +1 @@
> +#include "../../powerpc/asm/processor.h"
> diff --git a/lib/ppc64/asm/ptrace.h b/lib/ppc64/asm/ptrace.h
> new file mode 100644
> index 0000000..076c9d9
> --- /dev/null
> +++ b/lib/ppc64/asm/ptrace.h
> @@ -0,0 +1,24 @@
> +#ifndef _ASMPPC64_PTRACE_H_
> +#define _ASMPPC64_PTRACE_H_
> +
> +#define KERNEL_REDZONE_SIZE	288
> +#define STACK_FRAME_OVERHEAD    112     /* size of minimum stack frame */
> +
> +#ifndef __ASSEMBLY__
> +struct pt_regs {
> +	unsigned long gpr[32];
> +	unsigned long nip;
> +	unsigned long msr;
> +	unsigned long ctr;
> +	unsigned long link;
> +	unsigned long xer;
> +	unsigned long ccr;
> +	unsigned long trap;
> +};
> +
> +#define STACK_INT_FRAME_SIZE    (sizeof(struct pt_regs) + \
> +				 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _ASMPPC64_PTRACE_H_ */
> diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
> index 424983e..ab2caf6 100644
> --- a/powerpc/Makefile.common
> +++ b/powerpc/Makefile.common
> @@ -31,6 +31,7 @@ cflatobjs += lib/powerpc/io.o
>  cflatobjs += lib/powerpc/hcall.o
>  cflatobjs += lib/powerpc/setup.o
>  cflatobjs += lib/powerpc/rtas.o
> +cflatobjs += lib/powerpc/processor.o
>  
>  FLATLIBS = $(libcflat) $(LIBFDT_archive)
>  %.elf: CFLAGS += $(arch_CFLAGS)
> diff --git a/powerpc/cstart64.S b/powerpc/cstart64.S
> index c87e3d6..ceb6397 100644
> --- a/powerpc/cstart64.S
> +++ b/powerpc/cstart64.S
> @@ -9,6 +9,7 @@
>  #include <asm/hcall.h>
>  #include <asm/ppc_asm.h>
>  #include <asm/rtas.h>
> +#include <asm/ptrace.h>
>  
>  .section .init
>  
> @@ -45,6 +46,34 @@ start:
>  	add	r4, r4, r31
>  	bl	relocate
>  
> +	/* relocate vector table to base address 0x0 (MSR_IP = 0) */
> +
> +	/* source: r4, dest end: r5, destination: r6 */
> +
> +	LOAD_REG_ADDR(r4, __start_interrupts)
> +	LOAD_REG_ADDR(r5, __end_interrupts)
> +	sub	r5,r5,r4
> +	li	r6,0x100
> +
> +	sub	r4,r4,r6
> +	add	r5,r5,r6
> +	addi	r6,r6,-8
> +2:	li	r0,8
> +	mtctr	r0
> +	/* copy a cache line size */
> +3:	addi	r6,r6,8
> +	ldx	r0,r6,r4
> +	stdx	r0,0,r6
> +	bdnz	3b
> +	dcbst	0,r6
> +	/* flush icache */
> +	sync
> +	icbi	0,r6
> +	cmpld	0,r6,r5
> +	blt	2b
> +	sync
> +	isync
> +
>  	/* patch sc1 if needed */
>  	bl	hcall_have_broken_sc1
>  	cmpwi	r3, 0
> @@ -105,3 +134,114 @@ rtas_return_loc:
>  	ld	r0, 16(r1)
>  	mtlr	r0
>  	blr
> +
> +call_handler:
> +	/* save context */
> +
> +	/* GPRs */
> +
> +	.irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
> +	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
> +		SAVE_GPR(\i, r1)
> +	.endr
> +	mfsprg1	r0
> +	std	r0,GPR1(r1)
> +
> +	/* lr, xer, ccr */
> +
> +	mflr	r0
> +	std	r0,_LINK(r1)
> +
> +	mfxer	r0
> +	std	r0,_XER(r1)
> +
> +	mfcr	r0
> +	std	r0,_CCR(r1)
> +
> +	/* nip and msr */
> +
> +	mfsrr0	r0
> +	std	r0, _NIP(r1)
> +
> +	mfsrr1	r0
> +	std	r0, _MSR(r1)
> +
> +	/* FIXME: build stack frame */
> +
> +	/* call generic handler */
> +
> +	addi	r3,r1,STACK_FRAME_OVERHEAD
> +	bl	do_handle_exception
> +
> +	/* restore context */
> +
> +	ld	r0,_CTR(r1)
> +	mtctr	r0
> +
> +	ld	r0,_LINK(r1)
> +	mtlr	r0
> +
> +	ld	r0,_XER(r1)
> +	mtxer	r0
> +
> +	ld	r0,_CCR(r1)
> +	mtcr	r0
> +
> +	ld	r0, _NIP(r1)
> +	mtsrr0	r0
> +
> +	ld	r0, _MSR(r1)
> +	mtsrr1	r0
> +
> +	.irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
> +	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
> +		REST_GPR(\i, r1)
> +	.endr
> +
> +	/* restore r1, as we don't need it anymore */
> +
> +	REST_GPR(1,r1)
> +
> +	rfid
> +	b .
> +
> +.section .text.ex
> +
> +.macro VECTOR vec
> +	. = \vec
> +
> +	mtsprg1	r1	/* save r1 */
> +	mfsprg0	r1	/* get exception stack address */
> +	subi	r1,r1, INT_FRAME_SIZE
> +
> +	/* save r0 and ctr to call generic handler */
> +
> +	SAVE_GPR(0,r1)
> +
> +	mfctr	r0
> +	std	r0,_CTR(r1)
> +
> +	LOAD_REG_ADDR(r0, call_handler)
> +	mtctr	r0
> +
> +	li	r0,\vec
> +	std	r0,_TRAP(r1)
> +
> +	bctr
> +.endm
> +
> +	. = 0x100
> +	.globl __start_interrupts
> +__start_interrupts:
> +
> +VECTOR(0x300)
> +VECTOR(0x400)
> +VECTOR(0x500)
> +VECTOR(0x600)
> +VECTOR(0x700)
> +VECTOR(0x800)
> +VECTOR(0x900)
> +
> +	.align 7
> +	.globl __end_interrupts
> +__end_interrupts:
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 2/5] powerpc: add test to check invalid instruction trap
  2016-03-21 11:33   ` Laurent Vivier
@ 2016-03-21 23:49     ` David Gibson
  -1 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:49 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:31 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
> v2:
>     check program check type (invalid instruction)
>     add "-v" parameter to display invalid instruction address
> 
>  powerpc/Makefile.common |  5 +++-
>  powerpc/emulator.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
>  powerpc/unittests.cfg   |  3 +++
>  3 files changed, 72 insertions(+), 1 deletion(-)
>  create mode 100644 powerpc/emulator.c
> 
> diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
> index ab2caf6..257e3fb 100644
> --- a/powerpc/Makefile.common
> +++ b/powerpc/Makefile.common
> @@ -7,7 +7,8 @@
>  tests-common = \
>  	$(TEST_DIR)/selftest.elf \
>  	$(TEST_DIR)/spapr_hcall.elf \
> -	$(TEST_DIR)/rtas.elf
> +	$(TEST_DIR)/rtas.elf \
> +	$(TEST_DIR)/emulator.elf
>  
>  all: $(TEST_DIR)/boot_rom.bin test_cases
>  
> @@ -70,3 +71,5 @@ $(TEST_DIR)/selftest.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/selftest.o
>  $(TEST_DIR)/spapr_hcall.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/spapr_hcall.o
>  
>  $(TEST_DIR)/rtas.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/rtas.o
> +
> +$(TEST_DIR)/emulator.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/emulator.o
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> new file mode 100644
> index 0000000..1d4f164
> --- /dev/null
> +++ b/powerpc/emulator.c
> @@ -0,0 +1,65 @@
> +/*
> + * Test some powerpc instructions
> + */
> +
> +#include <libcflat.h>
> +#include <asm/processor.h>
> +
> +static int verbose;
> +static int volatile is_invalid;
> +
> +static void program_check_handler(struct pt_regs *regs, void *opaque)
> +{
> +	int *data = opaque;
> +
> +	if (verbose) {
> +		printf("Detected invalid instruction 0x%016lx: %08x\n",
> +		       regs->nip, *(uint32_t*)regs->nip);
> +	}
> +
> +	/* the result is bit 16 to 19 of SRR1
> +	 * bit 0: SRR0 contains the address of the next instruction
> +	 * bit 1: Trap
> +	 * bit 2: Privileged instruction
> +	 * bit 3: Illegal instruction
> +	 * bit 4: FP enabled exception type
> +	 */
> +
> +	*data = regs->msr >> 16;
> +
> +	regs->nip += 4;
> +}
> +
> +static void test_illegal(void)
> +{
> +	report_prefix_push("invalid");
> +
> +	is_invalid = 0;
> +
> +	asm volatile (".long 0");
> +
> +	report("exception", is_invalid == 8); /* illegal instruction */
> +
> +	report_prefix_pop();
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	int i;
> +
> +	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +
> +	for (i = 0; i < argc; i++) {
> +		if (strcmp(argv[i], "-v") == 0) {
> +			verbose = 1;
> +		}
> +	}
> +
> +	report_prefix_push("emulator");
> +
> +	test_illegal();
> +
> +	report_prefix_pop();
> +
> +	return report_summary();
> +}
> diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg
> index 02b21c7..ed4fdbe 100644
> --- a/powerpc/unittests.cfg
> +++ b/powerpc/unittests.cfg
> @@ -47,3 +47,6 @@ file = rtas.elf
>  extra_params = -append "set-time-of-day"
>  timeout = 5
>  groups = rtas
> +
> +[emulator]
> +file = emulator.elf
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 2/5] powerpc: add test to check invalid instruction trap
@ 2016-03-21 23:49     ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:49 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:31 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
> v2:
>     check program check type (invalid instruction)
>     add "-v" parameter to display invalid instruction address
> 
>  powerpc/Makefile.common |  5 +++-
>  powerpc/emulator.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
>  powerpc/unittests.cfg   |  3 +++
>  3 files changed, 72 insertions(+), 1 deletion(-)
>  create mode 100644 powerpc/emulator.c
> 
> diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
> index ab2caf6..257e3fb 100644
> --- a/powerpc/Makefile.common
> +++ b/powerpc/Makefile.common
> @@ -7,7 +7,8 @@
>  tests-common = \
>  	$(TEST_DIR)/selftest.elf \
>  	$(TEST_DIR)/spapr_hcall.elf \
> -	$(TEST_DIR)/rtas.elf
> +	$(TEST_DIR)/rtas.elf \
> +	$(TEST_DIR)/emulator.elf
>  
>  all: $(TEST_DIR)/boot_rom.bin test_cases
>  
> @@ -70,3 +71,5 @@ $(TEST_DIR)/selftest.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/selftest.o
>  $(TEST_DIR)/spapr_hcall.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/spapr_hcall.o
>  
>  $(TEST_DIR)/rtas.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/rtas.o
> +
> +$(TEST_DIR)/emulator.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/emulator.o
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> new file mode 100644
> index 0000000..1d4f164
> --- /dev/null
> +++ b/powerpc/emulator.c
> @@ -0,0 +1,65 @@
> +/*
> + * Test some powerpc instructions
> + */
> +
> +#include <libcflat.h>
> +#include <asm/processor.h>
> +
> +static int verbose;
> +static int volatile is_invalid;
> +
> +static void program_check_handler(struct pt_regs *regs, void *opaque)
> +{
> +	int *data = opaque;
> +
> +	if (verbose) {
> +		printf("Detected invalid instruction 0x%016lx: %08x\n",
> +		       regs->nip, *(uint32_t*)regs->nip);
> +	}
> +
> +	/* the result is bit 16 to 19 of SRR1
> +	 * bit 0: SRR0 contains the address of the next instruction
> +	 * bit 1: Trap
> +	 * bit 2: Privileged instruction
> +	 * bit 3: Illegal instruction
> +	 * bit 4: FP enabled exception type
> +	 */
> +
> +	*data = regs->msr >> 16;
> +
> +	regs->nip += 4;
> +}
> +
> +static void test_illegal(void)
> +{
> +	report_prefix_push("invalid");
> +
> +	is_invalid = 0;
> +
> +	asm volatile (".long 0");
> +
> +	report("exception", is_invalid == 8); /* illegal instruction */
> +
> +	report_prefix_pop();
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	int i;
> +
> +	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +
> +	for (i = 0; i < argc; i++) {
> +		if (strcmp(argv[i], "-v") == 0) {
> +			verbose = 1;
> +		}
> +	}
> +
> +	report_prefix_push("emulator");
> +
> +	test_illegal();
> +
> +	report_prefix_pop();
> +
> +	return report_summary();
> +}
> diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg
> index 02b21c7..ed4fdbe 100644
> --- a/powerpc/unittests.cfg
> +++ b/powerpc/unittests.cfg
> @@ -47,3 +47,6 @@ file = rtas.elf
>  extra_params = -append "set-time-of-day"
>  timeout = 5
>  groups = rtas
> +
> +[emulator]
> +file = emulator.elf
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 3/5] powerpc: check 64bit mode
  2016-03-21 11:33   ` Laurent Vivier
@ 2016-03-21 23:49     ` David Gibson
  -1 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:49 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:32 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Check in MSR if the SF bit is set (64bit mode is enabled)
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  powerpc/emulator.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index 1d4f164..d97090c 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -43,6 +43,19 @@ static void test_illegal(void)
>  	report_prefix_pop();
>  }
>  
> +static void test_64bit(void)
> +{
> +	uint64_t msr;
> +
> +	report_prefix_push("64bit");
> +
> +	asm("mfmsr %[msr]": [msr] "=r" (msr));
> +
> +	report("detected", msr & 0x8000000000000000UL);
> +
> +	report_prefix_pop();
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	int i;
> @@ -57,6 +70,7 @@ int main(int argc, char **argv)
>  
>  	report_prefix_push("emulator");
>  
> +	test_64bit();
>  	test_illegal();
>  
>  	report_prefix_pop();
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 3/5] powerpc: check 64bit mode
@ 2016-03-21 23:49     ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:49 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:32 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Check in MSR if the SF bit is set (64bit mode is enabled)
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  powerpc/emulator.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index 1d4f164..d97090c 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -43,6 +43,19 @@ static void test_illegal(void)
>  	report_prefix_pop();
>  }
>  
> +static void test_64bit(void)
> +{
> +	uint64_t msr;
> +
> +	report_prefix_push("64bit");
> +
> +	asm("mfmsr %[msr]": [msr] "=r" (msr));
> +
> +	report("detected", msr & 0x8000000000000000UL);
> +
> +	report_prefix_pop();
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	int i;
> @@ -57,6 +70,7 @@ int main(int argc, char **argv)
>  
>  	report_prefix_push("emulator");
>  
> +	test_64bit();
>  	test_illegal();
>  
>  	report_prefix_pop();
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
  2016-03-21 11:33   ` Laurent Vivier
@ 2016-03-21 23:53     ` David Gibson
  -1 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:53 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:33 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

Revieed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
> v2:
>     use "mtxer" instead of "mtspr"
>     Fix comments in lswx asm()
>     add "memory" in clobber list
> 
>  powerpc/emulator.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 140 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index d97090c..8d0dde2 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -56,6 +56,145 @@ static void test_64bit(void)
>  	report_prefix_pop();
>  }
>  
> +/*
> + * lswx: Load String Word Indexed X-form
> + *
> + *     lswx RT,RA,RB
> + *
> + * EA = (RA|0) + RB
> + * n  = XER
> + *
> + * Load n bytes from address EA into (n / 4) consecutive registers,
> + * throught RT -> RT + (n / 4) - 1.
> + * - Data are loaded into 4 low order bytes of registers (Word).
> + * - The unfilled bytes are set to 0.
> + * - The sequence of registers wraps around to GPR0.
> + * - if n == 0, content of RT is undefined
> + * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
> + * - RT == RA == 0 is invalid
> + *
> + */
> +
> +static void test_lswx(void)
> +{
> +	int i;
> +	char addr[128];
> +	uint64_t regs[32];
> +
> +	report_prefix_push("lswx");
> +
> +	/* fill memory with sequence */
> +
> +	for (i = 0; i < 128; i++)
> +		addr[i] = 1 + i;
> +
> +	/* check incomplete register filling */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r12,-1;"
> +		      "mr r11, r12;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (3),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      "xer", "r11", "r12", "memory");
> +
> +	report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
> +
> +	/* check an old know bug: the number of bytes is used as
> +	 * the number of registers, so try 32 bytes.
> +	 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r19,-1;"
> +		      "mr r11, r19; mr r12, r19; mr r13, r19;"
> +		      "mr r14, r19; mr r15, r19; mr r16, r19;"
> +		      "mr r17, r19; mr r18, r19;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      "std r13, 2*8(%[regs]);"
> +		      "std r14, 3*8(%[regs]);"
> +		      "std r15, 4*8(%[regs]);"
> +		      "std r16, 5*8(%[regs]);"
> +		      "std r17, 6*8(%[regs]);"
> +		      "std r18, 7*8(%[regs]);"
> +		      "std r19, 8*8(%[regs]);"
> +		      ::
> +		      [len] "r" (32),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* as 32 is the number of bytes,
> +		       * we should modify 32/4 = 8 regs, from r11 to r18
> +		       * We check r19 is unmodified by filling it with 1s
> +		       * before the instruction.
> +		       */
> +		      "xer", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
> +		      "r18", "r19", "memory");
> +
> +	report("length", regs[0] == 0x01020304 && regs[1] == 0x05060708 &&
> +			 regs[2] == 0x090a0b0c && regs[3] == 0x0d0e0f10 &&
> +			 regs[4] == 0x11121314 && regs[5] == 0x15161718 &&
> +			 regs[6] == 0x191a1b1c && regs[7] == 0x1d1e1f20 &&
> +			 regs[8] == (uint64_t)-1);
> +
> +	/* check wrap around to r0 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r31,-1;"
> +		      "mr r0, r31;"
> +		      "lswx r31, 0, %[addr];"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (8),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* modify two registers from r31, wrap around to r0 */
> +		      "xer", "r31", "r0", "memory");
> +
> +	report("wrap around to r0", regs[0] == 0x01020304 &&
> +			            regs[1] == 0x05060708);
> +
> +	/* check wrap around to r0 over RB doesn't break RB */
> +
> +	asm volatile ("mtxer %[len];"
> +		      /* adding r1 in the clobber list doesn't protect it... */
> +		      "mr r29,r1;"
> +		      "li r31,-1;"
> +		      "mr r1,r31;"
> +		      "mr r0, %[addr];"
> +		      "lswx r31, 0, r0;"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      "std r1, 2*8(%[regs]);"
> +		      "mr r1,r29;"
> +		      ::
> +		      [len] "r" (12),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* three registers from r31, wrap arount to r1,
> +		       * r1 is saved to r29, as adding it to the clobber
> +		       * list doesn't protect it
> +		       */
> +		      "xer", "r31", "r0", "r29", "memory");
> +
> +	/* doc says it is invalid, real proc stops when it comes to
> +	 * overwrite the register.
> +	 * In all the cases, the register must stay untouched
> +	 */
> +	report("Don't overwrite Rb", regs[1] == (uint64_t)addr);
> +
> +	report_prefix_pop();
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	int i;
> @@ -72,6 +211,7 @@ int main(int argc, char **argv)
>  
>  	test_64bit();
>  	test_illegal();
> +	test_lswx();
>  
>  	report_prefix_pop();
>  
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx
@ 2016-03-21 23:53     ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:53 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:33 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

Revieed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
> v2:
>     use "mtxer" instead of "mtspr"
>     Fix comments in lswx asm()
>     add "memory" in clobber list
> 
>  powerpc/emulator.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 140 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index d97090c..8d0dde2 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -56,6 +56,145 @@ static void test_64bit(void)
>  	report_prefix_pop();
>  }
>  
> +/*
> + * lswx: Load String Word Indexed X-form
> + *
> + *     lswx RT,RA,RB
> + *
> + * EA = (RA|0) + RB
> + * n  = XER
> + *
> + * Load n bytes from address EA into (n / 4) consecutive registers,
> + * throught RT -> RT + (n / 4) - 1.
> + * - Data are loaded into 4 low order bytes of registers (Word).
> + * - The unfilled bytes are set to 0.
> + * - The sequence of registers wraps around to GPR0.
> + * - if n == 0, content of RT is undefined
> + * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
> + * - RT == RA == 0 is invalid
> + *
> + */
> +
> +static void test_lswx(void)
> +{
> +	int i;
> +	char addr[128];
> +	uint64_t regs[32];
> +
> +	report_prefix_push("lswx");
> +
> +	/* fill memory with sequence */
> +
> +	for (i = 0; i < 128; i++)
> +		addr[i] = 1 + i;
> +
> +	/* check incomplete register filling */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r12,-1;"
> +		      "mr r11, r12;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (3),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      "xer", "r11", "r12", "memory");
> +
> +	report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
> +
> +	/* check an old know bug: the number of bytes is used as
> +	 * the number of registers, so try 32 bytes.
> +	 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r19,-1;"
> +		      "mr r11, r19; mr r12, r19; mr r13, r19;"
> +		      "mr r14, r19; mr r15, r19; mr r16, r19;"
> +		      "mr r17, r19; mr r18, r19;"
> +		      "lswx r11, 0, %[addr];"
> +		      "std r11, 0*8(%[regs]);"
> +		      "std r12, 1*8(%[regs]);"
> +		      "std r13, 2*8(%[regs]);"
> +		      "std r14, 3*8(%[regs]);"
> +		      "std r15, 4*8(%[regs]);"
> +		      "std r16, 5*8(%[regs]);"
> +		      "std r17, 6*8(%[regs]);"
> +		      "std r18, 7*8(%[regs]);"
> +		      "std r19, 8*8(%[regs]);"
> +		      ::
> +		      [len] "r" (32),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* as 32 is the number of bytes,
> +		       * we should modify 32/4 = 8 regs, from r11 to r18
> +		       * We check r19 is unmodified by filling it with 1s
> +		       * before the instruction.
> +		       */
> +		      "xer", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
> +		      "r18", "r19", "memory");
> +
> +	report("length", regs[0] == 0x01020304 && regs[1] == 0x05060708 &&
> +			 regs[2] == 0x090a0b0c && regs[3] == 0x0d0e0f10 &&
> +			 regs[4] == 0x11121314 && regs[5] == 0x15161718 &&
> +			 regs[6] == 0x191a1b1c && regs[7] == 0x1d1e1f20 &&
> +			 regs[8] == (uint64_t)-1);
> +
> +	/* check wrap around to r0 */
> +
> +	asm volatile ("mtxer %[len];"
> +		      "li r31,-1;"
> +		      "mr r0, r31;"
> +		      "lswx r31, 0, %[addr];"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      ::
> +		      [len] "r" (8),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* modify two registers from r31, wrap around to r0 */
> +		      "xer", "r31", "r0", "memory");
> +
> +	report("wrap around to r0", regs[0] == 0x01020304 &&
> +			            regs[1] == 0x05060708);
> +
> +	/* check wrap around to r0 over RB doesn't break RB */
> +
> +	asm volatile ("mtxer %[len];"
> +		      /* adding r1 in the clobber list doesn't protect it... */
> +		      "mr r29,r1;"
> +		      "li r31,-1;"
> +		      "mr r1,r31;"
> +		      "mr r0, %[addr];"
> +		      "lswx r31, 0, r0;"
> +		      "std r31, 0*8(%[regs]);"
> +		      "std r0, 1*8(%[regs]);"
> +		      "std r1, 2*8(%[regs]);"
> +		      "mr r1,r29;"
> +		      ::
> +		      [len] "r" (12),
> +		      [addr] "r" (addr),
> +		      [regs] "r" (regs)
> +		      :
> +		      /* three registers from r31, wrap arount to r1,
> +		       * r1 is saved to r29, as adding it to the clobber
> +		       * list doesn't protect it
> +		       */
> +		      "xer", "r31", "r0", "r29", "memory");
> +
> +	/* doc says it is invalid, real proc stops when it comes to
> +	 * overwrite the register.
> +	 * In all the cases, the register must stay untouched
> +	 */
> +	report("Don't overwrite Rb", regs[1] == (uint64_t)addr);
> +
> +	report_prefix_pop();
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	int i;
> @@ -72,6 +211,7 @@ int main(int argc, char **argv)
>  
>  	test_64bit();
>  	test_illegal();
> +	test_lswx();
>  
>  	report_prefix_pop();
>  
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
  2016-03-21 11:33   ` Laurent Vivier
@ 2016-03-21 23:56     ` David Gibson
  -1 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:56 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:34 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> For lswx in little-endian mode, an alignment interrupt occurs.
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>

I'm not entirely clear here; will the test fail if the alignment
exception doesn't occur in little endian mode?

The general trend in Power has been for less and less things to trigger
alignment exceptions, so failing to cause an alignment exception
shouldn't cause a test failure (as long as the unaligned case is
correctly processed, of course).

> ---
>  powerpc/emulator.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index 8d0dde2..87ef4a9 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -7,6 +7,7 @@
>  
>  static int verbose;
>  static int volatile is_invalid;
> +static int volatile alignment;
>  
>  static void program_check_handler(struct pt_regs *regs, void *opaque)
>  {
> @@ -30,6 +31,18 @@ static void program_check_handler(struct pt_regs *regs, void *opaque)
>  	regs->nip += 4;
>  }
>  
> +static void alignment_handler(struct pt_regs *regs, void *opaque)
> +{
> +	int *data = opaque;
> +
> +	printf("Detected alignment exception 0x%016lx: %08x\n",
> +	       regs->nip, *(uint32_t*)regs->nip);
> +
> +	*data = 1;
> +
> +	regs->nip += 4;
> +}
> +
>  static void test_illegal(void)
>  {
>  	report_prefix_push("invalid");
> @@ -73,6 +86,8 @@ static void test_64bit(void)
>   * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
>   * - RT == RA == 0 is invalid
>   *
> + * For lswx in little-endian mode, an alignment interrupt always occurs.
> + *
>   */
>  
>  static void test_lswx(void)
> @@ -90,6 +105,7 @@ static void test_lswx(void)
>  
>  	/* check incomplete register filling */
>  
> +	alignment = 0;
>  	asm volatile ("mtxer %[len];"
>  		      "li r12,-1;"
>  		      "mr r11, r12;"
> @@ -103,7 +119,12 @@ static void test_lswx(void)
>  		      :
>  		      "xer", "r11", "r12", "memory");
>  
> +#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> +	report("alignment", alignment);
> +	return;
> +#else
>  	report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
> +#endif
>  
>  	/* check an old know bug: the number of bytes is used as
>  	 * the number of registers, so try 32 bytes.
> @@ -200,6 +221,7 @@ int main(int argc, char **argv)
>  	int i;
>  
>  	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +	handle_exception(0x600, alignment_handler, (void *)&alignment);
>  
>  	for (i = 0; i < argc; i++) {
>  		if (strcmp(argv[i], "-v") == 0) {
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
@ 2016-03-21 23:56     ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-21 23:56 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, thuth, pbonzini

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

On Mon, 21 Mar 2016 12:33:34 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> For lswx in little-endian mode, an alignment interrupt occurs.
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>

I'm not entirely clear here; will the test fail if the alignment
exception doesn't occur in little endian mode?

The general trend in Power has been for less and less things to trigger
alignment exceptions, so failing to cause an alignment exception
shouldn't cause a test failure (as long as the unaligned case is
correctly processed, of course).

> ---
>  powerpc/emulator.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index 8d0dde2..87ef4a9 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -7,6 +7,7 @@
>  
>  static int verbose;
>  static int volatile is_invalid;
> +static int volatile alignment;
>  
>  static void program_check_handler(struct pt_regs *regs, void *opaque)
>  {
> @@ -30,6 +31,18 @@ static void program_check_handler(struct pt_regs *regs, void *opaque)
>  	regs->nip += 4;
>  }
>  
> +static void alignment_handler(struct pt_regs *regs, void *opaque)
> +{
> +	int *data = opaque;
> +
> +	printf("Detected alignment exception 0x%016lx: %08x\n",
> +	       regs->nip, *(uint32_t*)regs->nip);
> +
> +	*data = 1;
> +
> +	regs->nip += 4;
> +}
> +
>  static void test_illegal(void)
>  {
>  	report_prefix_push("invalid");
> @@ -73,6 +86,8 @@ static void test_64bit(void)
>   * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined
>   * - RT == RA == 0 is invalid
>   *
> + * For lswx in little-endian mode, an alignment interrupt always occurs.
> + *
>   */
>  
>  static void test_lswx(void)
> @@ -90,6 +105,7 @@ static void test_lswx(void)
>  
>  	/* check incomplete register filling */
>  
> +	alignment = 0;
>  	asm volatile ("mtxer %[len];"
>  		      "li r12,-1;"
>  		      "mr r11, r12;"
> @@ -103,7 +119,12 @@ static void test_lswx(void)
>  		      :
>  		      "xer", "r11", "r12", "memory");
>  
> +#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> +	report("alignment", alignment);
> +	return;
> +#else
>  	report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
> +#endif
>  
>  	/* check an old know bug: the number of bytes is used as
>  	 * the number of registers, so try 32 bytes.
> @@ -200,6 +221,7 @@ int main(int argc, char **argv)
>  	int i;
>  
>  	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +	handle_exception(0x600, alignment_handler, (void *)&alignment);
>  
>  	for (i = 0; i < argc; i++) {
>  		if (strcmp(argv[i], "-v") == 0) {
> -- 
> 2.5.0
> 


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
  2016-03-21 23:56     ` David Gibson
@ 2016-03-22  8:12       ` Thomas Huth
  -1 siblings, 0 replies; 38+ messages in thread
From: Thomas Huth @ 2016-03-22  8:12 UTC (permalink / raw)
  To: David Gibson, Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, pbonzini

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

On 22.03.2016 00:56, David Gibson wrote:
> On Mon, 21 Mar 2016 12:33:34 +0100
> Laurent Vivier <lvivier@redhat.com> wrote:
> 
>> For lswx in little-endian mode, an alignment interrupt occurs.
>>
>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
>> Reviewed-by: Thomas Huth <thuth@redhat.com>
> 
> I'm not entirely clear here; will the test fail if the alignment
> exception doesn't occur in little endian mode?

I think so, yes.

> The general trend in Power has been for less and less things to trigger
> alignment exceptions, so failing to cause an alignment exception
> shouldn't cause a test failure (as long as the unaligned case is
> correctly processed, of course).

According to the PowerISA 2.07, chapter 6.5.8, lswx should always
trigger an alignment exception in little endian mode. So that's
architected behavior and the test should be OK, as far as I can see...
In case this gets changed with a future CPU, I think the test could be
adapted later, too?

 Thomas



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
@ 2016-03-22  8:12       ` Thomas Huth
  0 siblings, 0 replies; 38+ messages in thread
From: Thomas Huth @ 2016-03-22  8:12 UTC (permalink / raw)
  To: David Gibson, Laurent Vivier; +Cc: kvm, kvm-ppc, drjones, pbonzini

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

On 22.03.2016 00:56, David Gibson wrote:
> On Mon, 21 Mar 2016 12:33:34 +0100
> Laurent Vivier <lvivier@redhat.com> wrote:
> 
>> For lswx in little-endian mode, an alignment interrupt occurs.
>>
>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
>> Reviewed-by: Thomas Huth <thuth@redhat.com>
> 
> I'm not entirely clear here; will the test fail if the alignment
> exception doesn't occur in little endian mode?

I think so, yes.

> The general trend in Power has been for less and less things to trigger
> alignment exceptions, so failing to cause an alignment exception
> shouldn't cause a test failure (as long as the unaligned case is
> correctly processed, of course).

According to the PowerISA 2.07, chapter 6.5.8, lswx should always
trigger an alignment exception in little endian mode. So that's
architected behavior and the test should be OK, as far as I can see...
In case this gets changed with a future CPU, I think the test could be
adapted later, too?

 Thomas



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
  2016-03-22  8:12       ` Thomas Huth
@ 2016-03-22  8:25         ` Laurent Vivier
  -1 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-22  8:25 UTC (permalink / raw)
  To: Thomas Huth, David Gibson; +Cc: kvm, kvm-ppc, drjones, pbonzini



On 22/03/2016 09:12, Thomas Huth wrote:
> On 22.03.2016 00:56, David Gibson wrote:
>> On Mon, 21 Mar 2016 12:33:34 +0100
>> Laurent Vivier <lvivier@redhat.com> wrote:
>>
>>> For lswx in little-endian mode, an alignment interrupt occurs.
>>>
>>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
>>> Reviewed-by: Thomas Huth <thuth@redhat.com>
>>
>> I'm not entirely clear here; will the test fail if the alignment
>> exception doesn't occur in little endian mode?
> 
> I think so, yes.
> 
>> The general trend in Power has been for less and less things to trigger
>> alignment exceptions, so failing to cause an alignment exception
>> shouldn't cause a test failure (as long as the unaligned case is
>> correctly processed, of course).
> 
> According to the PowerISA 2.07, chapter 6.5.8, lswx should always
> trigger an alignment exception in little endian mode. So that's
> architected behavior and the test should be OK, as far as I can see...
> In case this gets changed with a future CPU, I think the test could be
> adapted later, too?

Exactly.

Then in the kernel, the instruction is emulated. It's why I didn't
understand why this test case fails with kvm in little endian mode,
while is was working on a real host or in a guest.

Laurent

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
@ 2016-03-22  8:25         ` Laurent Vivier
  0 siblings, 0 replies; 38+ messages in thread
From: Laurent Vivier @ 2016-03-22  8:25 UTC (permalink / raw)
  To: Thomas Huth, David Gibson; +Cc: kvm, kvm-ppc, drjones, pbonzini



On 22/03/2016 09:12, Thomas Huth wrote:
> On 22.03.2016 00:56, David Gibson wrote:
>> On Mon, 21 Mar 2016 12:33:34 +0100
>> Laurent Vivier <lvivier@redhat.com> wrote:
>>
>>> For lswx in little-endian mode, an alignment interrupt occurs.
>>>
>>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
>>> Reviewed-by: Thomas Huth <thuth@redhat.com>
>>
>> I'm not entirely clear here; will the test fail if the alignment
>> exception doesn't occur in little endian mode?
> 
> I think so, yes.
> 
>> The general trend in Power has been for less and less things to trigger
>> alignment exceptions, so failing to cause an alignment exception
>> shouldn't cause a test failure (as long as the unaligned case is
>> correctly processed, of course).
> 
> According to the PowerISA 2.07, chapter 6.5.8, lswx should always
> trigger an alignment exception in little endian mode. So that's
> architected behavior and the test should be OK, as far as I can see...
> In case this gets changed with a future CPU, I think the test could be
> adapted later, too?

Exactly.

Then in the kernel, the instruction is emulated. It's why I didn't
understand why this test case fails with kvm in little endian mode,
while is was working on a real host or in a guest.

Laurent

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

* Re: [kvm-unit-tests PATCH v2 0/5] Check emulation
  2016-03-21 11:33 ` Laurent Vivier
@ 2016-03-22  9:50   ` Paolo Bonzini
  -1 siblings, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2016-03-22  9:50 UTC (permalink / raw)
  To: Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, thuth, dgibson

On 21/03/2016 12:33, Laurent Vivier wrote:
> This series adds exception handler to be able to test instruction
> emulation. We test then invalid instruction, lswx instruction, and
> check that lswx instruction triggers an alignment interrupt in
> little-endian mode. During the development of this series, I've seen
> that processor is not running in 64bit mode, so I've added a test
> to check that is the case now.
> 
> This has been tested with KVM PR, HV, TCG in big and little-endian mode.
> 
> KVM-PR needs a fix to be able to manage correctly invalid instruction.
>     http://patchwork.ozlabs.org/patch/597855/
> 
> QEMU needs a fix to initialize correctly the 64bit mode:
>     http://patchwork.ozlabs.org/patch/598198/
> 
> With TCG, some lswx tests fail because it needs some fixes... I'm working
> on this.
> 
> v2: 
>     clearly restore r1 in call_handler
>     use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"
>     check program check type (invalid instruction)
>     add "-v" parameter to display invalid instruction address
>     use "mtxer" instead of "mtspr"
>     Fix comments in lswx asm()
>     add "memory" in clobber list
>     add Thomas' Rb on patches 3 and 5.
> 
> Laurent Vivier (5):
>   powerpc: add exception handler
>   powerpc: add test to check invalid instruction trap
>   powerpc: check 64bit mode
>   powerpc: check lswx
>   powerpc: Check lswx in little-endian mode.
> 
>  lib/powerpc/asm/hcall.h     |   1 +
>  lib/powerpc/asm/ppc_asm.h   |   5 +
>  lib/powerpc/asm/processor.h |  11 ++
>  lib/powerpc/processor.c     |  38 +++++++
>  lib/powerpc/setup.c         |  19 ++++
>  lib/ppc64/asm-offsets.c     |  42 ++++++++
>  lib/ppc64/asm/processor.h   |   1 +
>  lib/ppc64/asm/ptrace.h      |  24 +++++
>  powerpc/Makefile.common     |   6 +-
>  powerpc/cstart64.S          | 140 +++++++++++++++++++++++++
>  powerpc/emulator.c          | 241 ++++++++++++++++++++++++++++++++++++++++++++
>  powerpc/unittests.cfg       |   3 +
>  12 files changed, 530 insertions(+), 1 deletion(-)
>  create mode 100644 lib/powerpc/asm/processor.h
>  create mode 100644 lib/powerpc/processor.c
>  create mode 100644 lib/ppc64/asm/processor.h
>  create mode 100644 lib/ppc64/asm/ptrace.h
>  create mode 100644 powerpc/emulator.c
> 

Applied, thanks.

Paolo

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

* Re: [kvm-unit-tests PATCH v2 0/5] Check emulation
@ 2016-03-22  9:50   ` Paolo Bonzini
  0 siblings, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2016-03-22  9:50 UTC (permalink / raw)
  To: Laurent Vivier, kvm, kvm-ppc; +Cc: drjones, thuth, dgibson

On 21/03/2016 12:33, Laurent Vivier wrote:
> This series adds exception handler to be able to test instruction
> emulation. We test then invalid instruction, lswx instruction, and
> check that lswx instruction triggers an alignment interrupt in
> little-endian mode. During the development of this series, I've seen
> that processor is not running in 64bit mode, so I've added a test
> to check that is the case now.
> 
> This has been tested with KVM PR, HV, TCG in big and little-endian mode.
> 
> KVM-PR needs a fix to be able to manage correctly invalid instruction.
>     http://patchwork.ozlabs.org/patch/597855/
> 
> QEMU needs a fix to initialize correctly the 64bit mode:
>     http://patchwork.ozlabs.org/patch/598198/
> 
> With TCG, some lswx tests fail because it needs some fixes... I'm working
> on this.
> 
> v2: 
>     clearly restore r1 in call_handler
>     use "exception_stack[cpu + 1]" instead of "exception_stack + cpu + 1"
>     check program check type (invalid instruction)
>     add "-v" parameter to display invalid instruction address
>     use "mtxer" instead of "mtspr"
>     Fix comments in lswx asm()
>     add "memory" in clobber list
>     add Thomas' Rb on patches 3 and 5.
> 
> Laurent Vivier (5):
>   powerpc: add exception handler
>   powerpc: add test to check invalid instruction trap
>   powerpc: check 64bit mode
>   powerpc: check lswx
>   powerpc: Check lswx in little-endian mode.
> 
>  lib/powerpc/asm/hcall.h     |   1 +
>  lib/powerpc/asm/ppc_asm.h   |   5 +
>  lib/powerpc/asm/processor.h |  11 ++
>  lib/powerpc/processor.c     |  38 +++++++
>  lib/powerpc/setup.c         |  19 ++++
>  lib/ppc64/asm-offsets.c     |  42 ++++++++
>  lib/ppc64/asm/processor.h   |   1 +
>  lib/ppc64/asm/ptrace.h      |  24 +++++
>  powerpc/Makefile.common     |   6 +-
>  powerpc/cstart64.S          | 140 +++++++++++++++++++++++++
>  powerpc/emulator.c          | 241 ++++++++++++++++++++++++++++++++++++++++++++
>  powerpc/unittests.cfg       |   3 +
>  12 files changed, 530 insertions(+), 1 deletion(-)
>  create mode 100644 lib/powerpc/asm/processor.h
>  create mode 100644 lib/powerpc/processor.c
>  create mode 100644 lib/ppc64/asm/processor.h
>  create mode 100644 lib/ppc64/asm/ptrace.h
>  create mode 100644 powerpc/emulator.c
> 

Applied, thanks.

Paolo

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
  2016-03-22  8:25         ` Laurent Vivier
@ 2016-03-23  0:14           ` David Gibson
  -1 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-23  0:14 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: Thomas Huth, kvm, kvm-ppc, drjones, pbonzini

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

On Tue, 22 Mar 2016 09:25:58 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> On 22/03/2016 09:12, Thomas Huth wrote:
> > On 22.03.2016 00:56, David Gibson wrote:  
> >> On Mon, 21 Mar 2016 12:33:34 +0100
> >> Laurent Vivier <lvivier@redhat.com> wrote:
> >>  
> >>> For lswx in little-endian mode, an alignment interrupt occurs.
> >>>
> >>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> >>> Reviewed-by: Thomas Huth <thuth@redhat.com>  
> >>
> >> I'm not entirely clear here; will the test fail if the alignment
> >> exception doesn't occur in little endian mode?  
> > 
> > I think so, yes.
> >   
> >> The general trend in Power has been for less and less things to trigger
> >> alignment exceptions, so failing to cause an alignment exception
> >> shouldn't cause a test failure (as long as the unaligned case is
> >> correctly processed, of course).  
> > 
> > According to the PowerISA 2.07, chapter 6.5.8, lswx should always
> > trigger an alignment exception in little endian mode. So that's
> > architected behavior and the test should be OK, as far as I can see...
> > In case this gets changed with a future CPU, I think the test could be
> > adapted later, too?  
> 
> Exactly.
> 
> Then in the kernel, the instruction is emulated. It's why I didn't
> understand why this test case fails with kvm in little endian mode,
> while is was working on a real host or in a guest.

Ok, then.


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode.
@ 2016-03-23  0:14           ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-03-23  0:14 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: Thomas Huth, kvm, kvm-ppc, drjones, pbonzini

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

On Tue, 22 Mar 2016 09:25:58 +0100
Laurent Vivier <lvivier@redhat.com> wrote:

> On 22/03/2016 09:12, Thomas Huth wrote:
> > On 22.03.2016 00:56, David Gibson wrote:  
> >> On Mon, 21 Mar 2016 12:33:34 +0100
> >> Laurent Vivier <lvivier@redhat.com> wrote:
> >>  
> >>> For lswx in little-endian mode, an alignment interrupt occurs.
> >>>
> >>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> >>> Reviewed-by: Thomas Huth <thuth@redhat.com>  
> >>
> >> I'm not entirely clear here; will the test fail if the alignment
> >> exception doesn't occur in little endian mode?  
> > 
> > I think so, yes.
> >   
> >> The general trend in Power has been for less and less things to trigger
> >> alignment exceptions, so failing to cause an alignment exception
> >> shouldn't cause a test failure (as long as the unaligned case is
> >> correctly processed, of course).  
> > 
> > According to the PowerISA 2.07, chapter 6.5.8, lswx should always
> > trigger an alignment exception in little endian mode. So that's
> > architected behavior and the test should be OK, as far as I can see...
> > In case this gets changed with a future CPU, I think the test could be
> > adapted later, too?  
> 
> Exactly.
> 
> Then in the kernel, the instruction is emulated. It's why I didn't
> understand why this test case fails with kvm in little endian mode,
> while is was working on a real host or in a guest.

Ok, then.


-- 
David Gibson <dgibson@redhat.com>
Senior Software Engineer, Virtualization, Red Hat

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

end of thread, other threads:[~2016-03-23  0:14 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-21 11:33 [kvm-unit-tests PATCH v2 0/5] Check emulation Laurent Vivier
2016-03-21 11:33 ` Laurent Vivier
2016-03-21 11:33 ` [kvm-unit-tests PATCH v2 1/5] powerpc: add exception handler Laurent Vivier
2016-03-21 11:33   ` Laurent Vivier
2016-03-21 23:47   ` David Gibson
2016-03-21 23:47     ` David Gibson
2016-03-21 11:33 ` [kvm-unit-tests PATCH v2 2/5] powerpc: add test to check invalid instruction trap Laurent Vivier
2016-03-21 11:33   ` Laurent Vivier
2016-03-21 14:57   ` Thomas Huth
2016-03-21 14:57     ` Thomas Huth
2016-03-21 23:49   ` David Gibson
2016-03-21 23:49     ` David Gibson
2016-03-21 11:33 ` [kvm-unit-tests PATCH v2 3/5] powerpc: check 64bit mode Laurent Vivier
2016-03-21 11:33   ` Laurent Vivier
2016-03-21 23:49   ` David Gibson
2016-03-21 23:49     ` David Gibson
2016-03-21 11:33 ` [kvm-unit-tests PATCH v2 4/5] powerpc: check lswx Laurent Vivier
2016-03-21 11:33   ` Laurent Vivier
2016-03-21 12:07   ` Thomas Huth
2016-03-21 12:07     ` Thomas Huth
2016-03-21 14:25     ` Paolo Bonzini
2016-03-21 14:25       ` Paolo Bonzini
2016-03-21 15:59       ` Laurent Vivier
2016-03-21 15:59         ` Laurent Vivier
2016-03-21 23:53   ` David Gibson
2016-03-21 23:53     ` David Gibson
2016-03-21 11:33 ` [kvm-unit-tests PATCH v2 5/5] powerpc: Check lswx in little-endian mode Laurent Vivier
2016-03-21 11:33   ` Laurent Vivier
2016-03-21 23:56   ` David Gibson
2016-03-21 23:56     ` David Gibson
2016-03-22  8:12     ` Thomas Huth
2016-03-22  8:12       ` Thomas Huth
2016-03-22  8:25       ` Laurent Vivier
2016-03-22  8:25         ` Laurent Vivier
2016-03-23  0:14         ` David Gibson
2016-03-23  0:14           ` David Gibson
2016-03-22  9:50 ` [kvm-unit-tests PATCH v2 0/5] Check emulation Paolo Bonzini
2016-03-22  9:50   ` Paolo Bonzini

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.