Message ID | 1458141183-27207-2-git-send-email-lvivier@redhat.com |
---|---|
State | Superseded |
Headers | show |
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. > + 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) > + .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 >
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 >> > > -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 16.03.2016 16:12, Laurent Vivier 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/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)); Maybe use "exception_stack[cpu + 1]" instead? That's easier to read. Thomas -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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..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 + REST_GPR(\i, r1) + .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:
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