All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <lvivier@redhat.com>
To: David Gibson <dgibson@redhat.com>
Cc: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org, drjones@redhat.com,
	thuth@redhat.com, pbonzini@redhat.com
Subject: Re: [kvm-unit-tests PATCH 1/5] powerpc: add exception handler
Date: Fri, 18 Mar 2016 08:53:02 +0000	[thread overview]
Message-ID: <56EBC1EE.30805@redhat.com> (raw)
In-Reply-To: <20160318145949.5c35012c@voom.fritz.box>



On 18/03/2016 04:59, David Gibson wrote:
> On Wed, 16 Mar 2016 16:12:59 +0100
> Laurent Vivier <lvivier@redhat.com> wrote:
> 
>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> 
> 
>> ---
>>  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          | 136 ++++++++++++++++++++++++++++++++++++++++++++
>>  10 files changed, 278 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;
> 
> I'm assuming trap starts out as the vector address (e.g. 0x300 for
> DSI).  Using trap >> 8 is going to break when we want to handle, say,
> the SLB miss exceptions at 0x380 and 0x480, which we'll probably want
> to do.
> 
> I think there are a few exceptions with even smaller spacing, but we
> might be able to ignore those for a while.

In fact, the handler is registered on (trap >> 8) (for instance 0x3) but
in regs->trap we have the full value (for instance 0x380), so we can
have sub-handler for these particular values.

> 
>> +	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..afe7fbc 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..bc5aeac 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,110 @@ 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, 1
> 
> The fact that '1' has to go last in this list is pretty subtle.  I
> wonder if it might be clearer to split that out explicitly rather than
> including it in the .irp
> 
>> +		REST_GPR(\i, r1)

If I have to resend the series, I will.

> 
> 
>> +	.endr
>> +
>> +	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
>>
> 
> 

WARNING: multiple messages have this Message-ID (diff)
From: Laurent Vivier <lvivier@redhat.com>
To: David Gibson <dgibson@redhat.com>
Cc: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org, drjones@redhat.com,
	thuth@redhat.com, pbonzini@redhat.com
Subject: Re: [kvm-unit-tests PATCH 1/5] powerpc: add exception handler
Date: Fri, 18 Mar 2016 09:53:02 +0100	[thread overview]
Message-ID: <56EBC1EE.30805@redhat.com> (raw)
In-Reply-To: <20160318145949.5c35012c@voom.fritz.box>



On 18/03/2016 04:59, David Gibson wrote:
> On Wed, 16 Mar 2016 16:12:59 +0100
> Laurent Vivier <lvivier@redhat.com> wrote:
> 
>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> 
> 
>> ---
>>  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          | 136 ++++++++++++++++++++++++++++++++++++++++++++
>>  10 files changed, 278 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;
> 
> I'm assuming trap starts out as the vector address (e.g. 0x300 for
> DSI).  Using trap >> 8 is going to break when we want to handle, say,
> the SLB miss exceptions at 0x380 and 0x480, which we'll probably want
> to do.
> 
> I think there are a few exceptions with even smaller spacing, but we
> might be able to ignore those for a while.

In fact, the handler is registered on (trap >> 8) (for instance 0x3) but
in regs->trap we have the full value (for instance 0x380), so we can
have sub-handler for these particular values.

> 
>> +	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..afe7fbc 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..bc5aeac 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,110 @@ 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, 1
> 
> The fact that '1' has to go last in this list is pretty subtle.  I
> wonder if it might be clearer to split that out explicitly rather than
> including it in the .irp
> 
>> +		REST_GPR(\i, r1)

If I have to resend the series, I will.

> 
> 
>> +	.endr
>> +
>> +	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
>>
> 
> 

  reply	other threads:[~2016-03-18  8:53 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-16 15:12 [kvm-unit-tests PATCH 0/5] Check emulation Laurent Vivier
2016-03-16 15:12 ` Laurent Vivier
2016-03-16 15:12 ` [kvm-unit-tests PATCH 1/5] powerpc: add exception handler Laurent Vivier
2016-03-16 15:12   ` Laurent Vivier
2016-03-18  3:59   ` David Gibson
2016-03-18  3:59     ` David Gibson
2016-03-18  8:53     ` Laurent Vivier [this message]
2016-03-18  8:53       ` Laurent Vivier
2016-03-18  9:42   ` Thomas Huth
2016-03-18  9:42     ` Thomas Huth
2016-03-16 15:13 ` [kvm-unit-tests PATCH 2/5] powerpc: add test to check invalid instruction trap Laurent Vivier
2016-03-16 15:13   ` Laurent Vivier
2016-03-18  9:51   ` Thomas Huth
2016-03-18  9:51     ` Thomas Huth
2016-03-18 10:08     ` Laurent Vivier
2016-03-18 10:08       ` Laurent Vivier
2016-03-18 10:12       ` Thomas Huth
2016-03-18 10:12         ` Thomas Huth
2016-03-16 15:13 ` [kvm-unit-tests PATCH 3/5] powerpc: check 64bit mode Laurent Vivier
2016-03-16 15:13   ` Laurent Vivier
2016-03-18  8:28   ` Thomas Huth
2016-03-18  8:28     ` Thomas Huth
2016-03-18  8:38     ` Paul Mackerras
2016-03-18  8:38       ` Paul Mackerras
2016-03-18  8:41       ` Thomas Huth
2016-03-18  8:41         ` Thomas Huth
2016-03-16 15:13 ` [kvm-unit-tests PATCH 4/5] powerpc: check lswx Laurent Vivier
2016-03-16 15:13   ` Laurent Vivier
2016-03-18  9:09   ` Thomas Huth
2016-03-18  9:09     ` Thomas Huth
2016-03-18 10:01     ` Laurent Vivier
2016-03-18 10:01       ` Laurent Vivier
2016-03-18 10:06       ` Thomas Huth
2016-03-18 10:06         ` Thomas Huth
2016-03-18 10:18         ` Laurent Vivier
2016-03-18 10:18           ` Laurent Vivier
2016-03-18 10:34           ` Thomas Huth
2016-03-18 10:34             ` Thomas Huth
2016-03-16 15:13 ` [kvm-unit-tests PATCH 5/5] powerpc: Check lswx in little-endian mode Laurent Vivier
2016-03-16 15:13   ` Laurent Vivier
2016-03-18  9:54   ` Thomas Huth
2016-03-18  9:54     ` Thomas Huth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56EBC1EE.30805@redhat.com \
    --to=lvivier@redhat.com \
    --cc=dgibson@redhat.com \
    --cc=drjones@redhat.com \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.