Message ID | 7a459ea843d5823ee2c50b0e44dded5bdb554ca6.1674226563.git.oleksii.kurochko@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | RISCV basic exception handling implementation | expand |
On Sat, Jan 21, 2023 at 1:00 AM Oleksii Kurochko <oleksii.kurochko@gmail.com> wrote: > > The patch introduces an implementation of basic exception handlers: > - to save/restore context > - to handle an exception itself. The handler calls wait_for_interrupt > now, nothing more. > > Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > xen/arch/riscv/Makefile | 2 + > xen/arch/riscv/entry.S | 97 ++++++++++++++++++++++++++++++ > xen/arch/riscv/include/asm/traps.h | 13 ++++ > xen/arch/riscv/traps.c | 13 ++++ > 4 files changed, 125 insertions(+) > create mode 100644 xen/arch/riscv/entry.S > create mode 100644 xen/arch/riscv/include/asm/traps.h > create mode 100644 xen/arch/riscv/traps.c > > diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile > index 1a4f1a6015..443f6bf15f 100644 > --- a/xen/arch/riscv/Makefile > +++ b/xen/arch/riscv/Makefile > @@ -1,7 +1,9 @@ > obj-$(CONFIG_EARLY_PRINTK) += early_printk.o > +obj-y += entry.o > obj-$(CONFIG_RISCV_64) += riscv64/ > obj-y += sbi.o > obj-y += setup.o > +obj-y += traps.o > > $(TARGET): $(TARGET)-syms > $(OBJCOPY) -O binary -S $< $@ > diff --git a/xen/arch/riscv/entry.S b/xen/arch/riscv/entry.S > new file mode 100644 > index 0000000000..f7d46f42bb > --- /dev/null > +++ b/xen/arch/riscv/entry.S > @@ -0,0 +1,97 @@ > +#include <asm/asm.h> > +#include <asm/processor.h> > +#include <asm/riscv_encoding.h> > +#include <asm/traps.h> > + > + .global handle_exception > + .align 4 > + > +handle_exception: > + > + /* Exceptions from xen */ > +save_to_stack: > + /* Save context to stack */ > + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - RISCV_CPU_USER_REGS_SIZE) (sp) > + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) > + j save_context > + > +save_context: > + /* Save registers */ > + REG_S ra, RISCV_CPU_USER_REGS_OFFSET(ra)(sp) > + REG_S gp, RISCV_CPU_USER_REGS_OFFSET(gp)(sp) > + REG_S t1, RISCV_CPU_USER_REGS_OFFSET(t1)(sp) > + REG_S t2, RISCV_CPU_USER_REGS_OFFSET(t2)(sp) > + REG_S s0, RISCV_CPU_USER_REGS_OFFSET(s0)(sp) > + REG_S s1, RISCV_CPU_USER_REGS_OFFSET(s1)(sp) > + REG_S a0, RISCV_CPU_USER_REGS_OFFSET(a0)(sp) > + REG_S a1, RISCV_CPU_USER_REGS_OFFSET(a1)(sp) > + REG_S a2, RISCV_CPU_USER_REGS_OFFSET(a2)(sp) > + REG_S a3, RISCV_CPU_USER_REGS_OFFSET(a3)(sp) > + REG_S a4, RISCV_CPU_USER_REGS_OFFSET(a4)(sp) > + REG_S a5, RISCV_CPU_USER_REGS_OFFSET(a5)(sp) > + REG_S a6, RISCV_CPU_USER_REGS_OFFSET(a6)(sp) > + REG_S a7, RISCV_CPU_USER_REGS_OFFSET(a7)(sp) > + REG_S s2, RISCV_CPU_USER_REGS_OFFSET(s2)(sp) > + REG_S s3, RISCV_CPU_USER_REGS_OFFSET(s3)(sp) > + REG_S s4, RISCV_CPU_USER_REGS_OFFSET(s4)(sp) > + REG_S s5, RISCV_CPU_USER_REGS_OFFSET(s5)(sp) > + REG_S s6, RISCV_CPU_USER_REGS_OFFSET(s6)(sp) > + REG_S s7, RISCV_CPU_USER_REGS_OFFSET(s7)(sp) > + REG_S s8, RISCV_CPU_USER_REGS_OFFSET(s8)(sp) > + REG_S s9, RISCV_CPU_USER_REGS_OFFSET(s9)(sp) > + REG_S s10, RISCV_CPU_USER_REGS_OFFSET(s10)(sp) > + REG_S s11, RISCV_CPU_USER_REGS_OFFSET(s11)(sp) > + REG_S t3, RISCV_CPU_USER_REGS_OFFSET(t3)(sp) > + REG_S t4, RISCV_CPU_USER_REGS_OFFSET(t4)(sp) > + REG_S t5, RISCV_CPU_USER_REGS_OFFSET(t5)(sp) > + REG_S t6, RISCV_CPU_USER_REGS_OFFSET(t6)(sp) > + csrr t0, CSR_SEPC > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sepc)(sp) > + csrr t0, CSR_SSTATUS > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sstatus)(sp) > + > + mv a0, sp > + jal __handle_exception > + > +restore_registers: > + /* Restore stack_cpu_regs */ > + REG_L t0, RISCV_CPU_USER_REGS_OFFSET(sepc)(sp) > + csrw CSR_SEPC, t0 > + REG_L t0, RISCV_CPU_USER_REGS_OFFSET(sstatus)(sp) > + csrw CSR_SSTATUS, t0 > + > + REG_L ra, RISCV_CPU_USER_REGS_OFFSET(ra)(sp) > + REG_L gp, RISCV_CPU_USER_REGS_OFFSET(gp)(sp) > + REG_L t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) > + REG_L t1, RISCV_CPU_USER_REGS_OFFSET(t1)(sp) > + REG_L t2, RISCV_CPU_USER_REGS_OFFSET(t2)(sp) > + REG_L s0, RISCV_CPU_USER_REGS_OFFSET(s0)(sp) > + REG_L s1, RISCV_CPU_USER_REGS_OFFSET(s1)(sp) > + REG_L a0, RISCV_CPU_USER_REGS_OFFSET(a0)(sp) > + REG_L a1, RISCV_CPU_USER_REGS_OFFSET(a1)(sp) > + REG_L a2, RISCV_CPU_USER_REGS_OFFSET(a2)(sp) > + REG_L a3, RISCV_CPU_USER_REGS_OFFSET(a3)(sp) > + REG_L a4, RISCV_CPU_USER_REGS_OFFSET(a4)(sp) > + REG_L a5, RISCV_CPU_USER_REGS_OFFSET(a5)(sp) > + REG_L a6, RISCV_CPU_USER_REGS_OFFSET(a6)(sp) > + REG_L a7, RISCV_CPU_USER_REGS_OFFSET(a7)(sp) > + REG_L s2, RISCV_CPU_USER_REGS_OFFSET(s2)(sp) > + REG_L s3, RISCV_CPU_USER_REGS_OFFSET(s3)(sp) > + REG_L s4, RISCV_CPU_USER_REGS_OFFSET(s4)(sp) > + REG_L s5, RISCV_CPU_USER_REGS_OFFSET(s5)(sp) > + REG_L s6, RISCV_CPU_USER_REGS_OFFSET(s6)(sp) > + REG_L s7, RISCV_CPU_USER_REGS_OFFSET(s7)(sp) > + REG_L s8, RISCV_CPU_USER_REGS_OFFSET(s8)(sp) > + REG_L s9, RISCV_CPU_USER_REGS_OFFSET(s9)(sp) > + REG_L s10, RISCV_CPU_USER_REGS_OFFSET(s10)(sp) > + REG_L s11, RISCV_CPU_USER_REGS_OFFSET(s11)(sp) > + REG_L t3, RISCV_CPU_USER_REGS_OFFSET(t3)(sp) > + REG_L t4, RISCV_CPU_USER_REGS_OFFSET(t4)(sp) > + REG_L t5, RISCV_CPU_USER_REGS_OFFSET(t5)(sp) > + REG_L t6, RISCV_CPU_USER_REGS_OFFSET(t6)(sp) > + > + /* Restore sp */ > + REG_L sp, RISCV_CPU_USER_REGS_OFFSET(sp)(sp) > + > + sret > diff --git a/xen/arch/riscv/include/asm/traps.h b/xen/arch/riscv/include/asm/traps.h > new file mode 100644 > index 0000000000..816ab1178a > --- /dev/null > +++ b/xen/arch/riscv/include/asm/traps.h > @@ -0,0 +1,13 @@ > +#ifndef __ASM_TRAPS_H__ > +#define __ASM_TRAPS_H__ > + > +#include <asm/processor.h> > + > +#ifndef __ASSEMBLY__ > + > +void __handle_exception(struct cpu_user_regs *cpu_regs); > +void handle_exception(void); > + > +#endif /* __ASSEMBLY__ */ > + > +#endif /* __ASM_TRAPS_H__ */ > diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c > new file mode 100644 > index 0000000000..3201b851ef > --- /dev/null > +++ b/xen/arch/riscv/traps.c > @@ -0,0 +1,13 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2023 Vates > + * > + * RISC-V Trap handlers > + */ > +#include <asm/processor.h> > +#include <asm/traps.h> > + > +void __handle_exception(struct cpu_user_regs *cpu_regs) > +{ > + wait_for_interrupt(); > +} > -- > 2.39.0 > >
On 20.01.2023 15:59, Oleksii Kurochko wrote: > --- /dev/null > +++ b/xen/arch/riscv/entry.S > @@ -0,0 +1,97 @@ > +#include <asm/asm.h> > +#include <asm/processor.h> > +#include <asm/riscv_encoding.h> > +#include <asm/traps.h> > + > + .global handle_exception > + .align 4 > + > +handle_exception: > + > + /* Exceptions from xen */ > +save_to_stack: > + /* Save context to stack */ > + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - RISCV_CPU_USER_REGS_SIZE) (sp) > + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) > + j save_context > + > +save_context: Just curious: Why not simply fall through here, i.e. why the J which really is a NOP in this case? Jan
On 20/01/2023 2:59 pm, Oleksii Kurochko wrote: > diff --git a/xen/arch/riscv/entry.S b/xen/arch/riscv/entry.S > new file mode 100644 > index 0000000000..f7d46f42bb > --- /dev/null > +++ b/xen/arch/riscv/entry.S > @@ -0,0 +1,97 @@ > +#include <asm/asm.h> > +#include <asm/processor.h> > +#include <asm/riscv_encoding.h> > +#include <asm/traps.h> > + > + .global handle_exception > + .align 4 > + > +handle_exception: ENTRY() which takes care of the global and the align. Also, you want a size and type at the end, just like in head.S (Sorry, we *still* don't have any sane infrastructure for doing that nicely. Opencode it for now.) > + > + /* Exceptions from xen */ > +save_to_stack: This label isn't used at all, is it? > + /* Save context to stack */ > + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - RISCV_CPU_USER_REGS_SIZE) (sp) > + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) Exceptions on RISC-V don't adjust the stack pointer. This logic depends on interrupting Xen code, and Xen not having suffered a stack overflow (and actually, that the space on the stack for all registers also doesn't overflow). Which might be fine for now, but I think it warrants a comment somewhere (probably at handle_exception itself) stating the expectations while it's still a work in progress. So in this case something like: /* Work-in-progress: Depends on interrupting Xen, and the stack being good. */ But, do we want to allocate stemp right away (even with an empty struct), and get tp set up properly? That said, aren't we going to have to rewrite this when enabling H mode anyway? > + j save_context > + > +save_context: I'd drop this. It's a nop right now. > <snip> > + csrr t0, CSR_SEPC > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sepc)(sp) > + csrr t0, CSR_SSTATUS > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sstatus)(sp) So something I've noticed about CSRs through this series. The C CSR macros are set up to use real CSR names, but the CSR_* constants used in C and ASM are raw numbers. If we're using raw numbers, then the C CSR accessors should be static inlines instead, but the advantage of using names is the toolchain can issue an error when we reference a CSR not supported by the current extensions. We ought to use a single form, consistently through Xen. How feasible will it be to use names throughout? ~Andrew
On 23.01.2023 12:50, Andrew Cooper wrote: > On 20/01/2023 2:59 pm, Oleksii Kurochko wrote: >> + csrr t0, CSR_SEPC >> + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sepc)(sp) >> + csrr t0, CSR_SSTATUS >> + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sstatus)(sp) > > So something I've noticed about CSRs through this series. > > The C CSR macros are set up to use real CSR names, but the CSR_* > constants used in C and ASM are raw numbers. > > If we're using raw numbers, then the C CSR accessors should be static > inlines instead, but the advantage of using names is the toolchain can > issue an error when we reference a CSR not supported by the current > extensions. That's a default-off diagnostic iirc, so we'd gain something here only when explicitly turning that on as well. Jan
On Mon, 2023-01-23 at 12:17 +0100, Jan Beulich wrote: > On 20.01.2023 15:59, Oleksii Kurochko wrote: > > --- /dev/null > > +++ b/xen/arch/riscv/entry.S > > @@ -0,0 +1,97 @@ > > +#include <asm/asm.h> > > +#include <asm/processor.h> > > +#include <asm/riscv_encoding.h> > > +#include <asm/traps.h> > > + > > + .global handle_exception > > + .align 4 > > + > > +handle_exception: > > + > > + /* Exceptions from xen */ > > +save_to_stack: > > + /* Save context to stack */ > > + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - > > RISCV_CPU_USER_REGS_SIZE) (sp) > > + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE > > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) > > + j save_context > > + > > +save_context: > > Just curious: Why not simply fall through here, i.e. why the J which > really > is a NOP in this case? > There is no any specific reason. I left it for future. Will remove it in the next patch version. > Jan
On Mon, 2023-01-23 at 11:50 +0000, Andrew Cooper wrote: > On 20/01/2023 2:59 pm, Oleksii Kurochko wrote: > > diff --git a/xen/arch/riscv/entry.S b/xen/arch/riscv/entry.S > > new file mode 100644 > > index 0000000000..f7d46f42bb > > --- /dev/null > > +++ b/xen/arch/riscv/entry.S > > @@ -0,0 +1,97 @@ > > +#include <asm/asm.h> > > +#include <asm/processor.h> > > +#include <asm/riscv_encoding.h> > > +#include <asm/traps.h> > > + > > + .global handle_exception > > + .align 4 > > + > > +handle_exception: > > ENTRY() which takes care of the global and the align. > > Also, you want a size and type at the end, just like in head.S > (Sorry, > we *still* don't have any sane infrastructure for doing that nicely. > Opencode it for now.) > > > + > > + /* Exceptions from xen */ > > +save_to_stack: > > This label isn't used at all, is it? > > > + /* Save context to stack */ > > + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - > > RISCV_CPU_USER_REGS_SIZE) (sp) > > + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE > > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) > > Exceptions on RISC-V don't adjust the stack pointer. This logic > depends > on interrupting Xen code, and Xen not having suffered a stack > overflow > (and actually, that the space on the stack for all registers also > doesn't overflow). > > Which might be fine for now, but I think it warrants a comment > somewhere > (probably at handle_exception itself) stating the expectations while > it's still a work in progress. So in this case something like: > > /* Work-in-progress: Depends on interrupting Xen, and the stack > being > good. */ > > > But, do we want to allocate stemp right away (even with an empty > struct), and get tp set up properly? > I am not sure that I get you here about stemp. Could you please clarify a little bit. > That said, aren't we going to have to rewrite this when enabling H > mode > anyway? I based these code on a code from Bobby's repo ( on top of which with some additional patches I've successfully ran Dom0 ) so I am not sure that it will be re-written. Probably I don't understand about which one part you are talking about. Regarding H mode if to be honest I didn't see where it is switched to it. Maybe Bobby or Alistair can explain me? > > > + j save_context > > + > > +save_context: > > I'd drop this. It's a nop right now. > > > <snip> > > + csrr t0, CSR_SEPC > > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sepc)(sp) > > + csrr t0, CSR_SSTATUS > > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sstatus)(sp) > > So something I've noticed about CSRs through this series. > > The C CSR macros are set up to use real CSR names, but the CSR_* > constants used in C and ASM are raw numbers. > > If we're using raw numbers, then the C CSR accessors should be static > inlines instead, but the advantage of using names is the toolchain > can > issue an error when we reference a CSR not supported by the current > extensions. > > We ought to use a single form, consistently through Xen. How > feasible > will it be to use names throughout? > > ~Andrew
On 23/01/2023 3:17 pm, Oleksii wrote: > On Mon, 2023-01-23 at 11:50 +0000, Andrew Cooper wrote: >> On 20/01/2023 2:59 pm, Oleksii Kurochko wrote: >>> + /* Save context to stack */ >>> + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - >>> RISCV_CPU_USER_REGS_SIZE) (sp) >>> + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE >>> + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) >> Exceptions on RISC-V don't adjust the stack pointer. This logic >> depends >> on interrupting Xen code, and Xen not having suffered a stack >> overflow >> (and actually, that the space on the stack for all registers also >> doesn't overflow). >> >> Which might be fine for now, but I think it warrants a comment >> somewhere >> (probably at handle_exception itself) stating the expectations while >> it's still a work in progress. So in this case something like: >> >> /* Work-in-progress: Depends on interrupting Xen, and the stack >> being >> good. */ >> >> >> But, do we want to allocate stemp right away (even with an empty >> struct), and get tp set up properly? >> > I am not sure that I get you here about stemp. Could you please clarify > a little bit. Sorry - sscratch, not stemp - I got the name wrong. All registers are the interrupted context, not Xen's context. This includes the stack pointer, global pointer, and thread pointer. Trap setup is supposed to stash Xen's tp in sscratch so on an interrupt/exception, it can exchange sscratch with tp and recover the stack pointer. Linux plays games with having sscratch be 0 while in kernel and uses this to determine whether the exception occurred in kernel or user mode. This is massive can of re-entrancy bugs that appears to be baked into the architecture. I genuinely can't figure out a safe way to cope with a stack overflow, or a bad tp, because it is not safe to a pagefault until the exception prologue has completed. If you do, you'll switch back to the interrupted task's tp and use that as if it were Xen's. ~Andrew
On Mon, 2023-01-23 at 11:50 +0000, Andrew Cooper wrote: > > > > + /* Save context to stack */ > > + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - > > RISCV_CPU_USER_REGS_SIZE) (sp) > > + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE > > + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) > > Exceptions on RISC-V don't adjust the stack pointer. This logic > depends > on interrupting Xen code, and Xen not having suffered a stack > overflow > (and actually, that the space on the stack for all registers also > doesn't overflow). > Probably I missed something but an idea of the code above was to reserve memory on a stack to save the registers which can be changed in __handler_expception() as the line of code where exception occurs will expect that registers value weren't changed. Otherwise if we won't reserve memory on stack it will be corrupted by REG_S which basically is SD instruction.
diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index 1a4f1a6015..443f6bf15f 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -1,7 +1,9 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-y += entry.o obj-$(CONFIG_RISCV_64) += riscv64/ obj-y += sbi.o obj-y += setup.o +obj-y += traps.o $(TARGET): $(TARGET)-syms $(OBJCOPY) -O binary -S $< $@ diff --git a/xen/arch/riscv/entry.S b/xen/arch/riscv/entry.S new file mode 100644 index 0000000000..f7d46f42bb --- /dev/null +++ b/xen/arch/riscv/entry.S @@ -0,0 +1,97 @@ +#include <asm/asm.h> +#include <asm/processor.h> +#include <asm/riscv_encoding.h> +#include <asm/traps.h> + + .global handle_exception + .align 4 + +handle_exception: + + /* Exceptions from xen */ +save_to_stack: + /* Save context to stack */ + REG_S sp, (RISCV_CPU_USER_REGS_OFFSET(sp) - RISCV_CPU_USER_REGS_SIZE) (sp) + addi sp, sp, -RISCV_CPU_USER_REGS_SIZE + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) + j save_context + +save_context: + /* Save registers */ + REG_S ra, RISCV_CPU_USER_REGS_OFFSET(ra)(sp) + REG_S gp, RISCV_CPU_USER_REGS_OFFSET(gp)(sp) + REG_S t1, RISCV_CPU_USER_REGS_OFFSET(t1)(sp) + REG_S t2, RISCV_CPU_USER_REGS_OFFSET(t2)(sp) + REG_S s0, RISCV_CPU_USER_REGS_OFFSET(s0)(sp) + REG_S s1, RISCV_CPU_USER_REGS_OFFSET(s1)(sp) + REG_S a0, RISCV_CPU_USER_REGS_OFFSET(a0)(sp) + REG_S a1, RISCV_CPU_USER_REGS_OFFSET(a1)(sp) + REG_S a2, RISCV_CPU_USER_REGS_OFFSET(a2)(sp) + REG_S a3, RISCV_CPU_USER_REGS_OFFSET(a3)(sp) + REG_S a4, RISCV_CPU_USER_REGS_OFFSET(a4)(sp) + REG_S a5, RISCV_CPU_USER_REGS_OFFSET(a5)(sp) + REG_S a6, RISCV_CPU_USER_REGS_OFFSET(a6)(sp) + REG_S a7, RISCV_CPU_USER_REGS_OFFSET(a7)(sp) + REG_S s2, RISCV_CPU_USER_REGS_OFFSET(s2)(sp) + REG_S s3, RISCV_CPU_USER_REGS_OFFSET(s3)(sp) + REG_S s4, RISCV_CPU_USER_REGS_OFFSET(s4)(sp) + REG_S s5, RISCV_CPU_USER_REGS_OFFSET(s5)(sp) + REG_S s6, RISCV_CPU_USER_REGS_OFFSET(s6)(sp) + REG_S s7, RISCV_CPU_USER_REGS_OFFSET(s7)(sp) + REG_S s8, RISCV_CPU_USER_REGS_OFFSET(s8)(sp) + REG_S s9, RISCV_CPU_USER_REGS_OFFSET(s9)(sp) + REG_S s10, RISCV_CPU_USER_REGS_OFFSET(s10)(sp) + REG_S s11, RISCV_CPU_USER_REGS_OFFSET(s11)(sp) + REG_S t3, RISCV_CPU_USER_REGS_OFFSET(t3)(sp) + REG_S t4, RISCV_CPU_USER_REGS_OFFSET(t4)(sp) + REG_S t5, RISCV_CPU_USER_REGS_OFFSET(t5)(sp) + REG_S t6, RISCV_CPU_USER_REGS_OFFSET(t6)(sp) + csrr t0, CSR_SEPC + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sepc)(sp) + csrr t0, CSR_SSTATUS + REG_S t0, RISCV_CPU_USER_REGS_OFFSET(sstatus)(sp) + + mv a0, sp + jal __handle_exception + +restore_registers: + /* Restore stack_cpu_regs */ + REG_L t0, RISCV_CPU_USER_REGS_OFFSET(sepc)(sp) + csrw CSR_SEPC, t0 + REG_L t0, RISCV_CPU_USER_REGS_OFFSET(sstatus)(sp) + csrw CSR_SSTATUS, t0 + + REG_L ra, RISCV_CPU_USER_REGS_OFFSET(ra)(sp) + REG_L gp, RISCV_CPU_USER_REGS_OFFSET(gp)(sp) + REG_L t0, RISCV_CPU_USER_REGS_OFFSET(t0)(sp) + REG_L t1, RISCV_CPU_USER_REGS_OFFSET(t1)(sp) + REG_L t2, RISCV_CPU_USER_REGS_OFFSET(t2)(sp) + REG_L s0, RISCV_CPU_USER_REGS_OFFSET(s0)(sp) + REG_L s1, RISCV_CPU_USER_REGS_OFFSET(s1)(sp) + REG_L a0, RISCV_CPU_USER_REGS_OFFSET(a0)(sp) + REG_L a1, RISCV_CPU_USER_REGS_OFFSET(a1)(sp) + REG_L a2, RISCV_CPU_USER_REGS_OFFSET(a2)(sp) + REG_L a3, RISCV_CPU_USER_REGS_OFFSET(a3)(sp) + REG_L a4, RISCV_CPU_USER_REGS_OFFSET(a4)(sp) + REG_L a5, RISCV_CPU_USER_REGS_OFFSET(a5)(sp) + REG_L a6, RISCV_CPU_USER_REGS_OFFSET(a6)(sp) + REG_L a7, RISCV_CPU_USER_REGS_OFFSET(a7)(sp) + REG_L s2, RISCV_CPU_USER_REGS_OFFSET(s2)(sp) + REG_L s3, RISCV_CPU_USER_REGS_OFFSET(s3)(sp) + REG_L s4, RISCV_CPU_USER_REGS_OFFSET(s4)(sp) + REG_L s5, RISCV_CPU_USER_REGS_OFFSET(s5)(sp) + REG_L s6, RISCV_CPU_USER_REGS_OFFSET(s6)(sp) + REG_L s7, RISCV_CPU_USER_REGS_OFFSET(s7)(sp) + REG_L s8, RISCV_CPU_USER_REGS_OFFSET(s8)(sp) + REG_L s9, RISCV_CPU_USER_REGS_OFFSET(s9)(sp) + REG_L s10, RISCV_CPU_USER_REGS_OFFSET(s10)(sp) + REG_L s11, RISCV_CPU_USER_REGS_OFFSET(s11)(sp) + REG_L t3, RISCV_CPU_USER_REGS_OFFSET(t3)(sp) + REG_L t4, RISCV_CPU_USER_REGS_OFFSET(t4)(sp) + REG_L t5, RISCV_CPU_USER_REGS_OFFSET(t5)(sp) + REG_L t6, RISCV_CPU_USER_REGS_OFFSET(t6)(sp) + + /* Restore sp */ + REG_L sp, RISCV_CPU_USER_REGS_OFFSET(sp)(sp) + + sret diff --git a/xen/arch/riscv/include/asm/traps.h b/xen/arch/riscv/include/asm/traps.h new file mode 100644 index 0000000000..816ab1178a --- /dev/null +++ b/xen/arch/riscv/include/asm/traps.h @@ -0,0 +1,13 @@ +#ifndef __ASM_TRAPS_H__ +#define __ASM_TRAPS_H__ + +#include <asm/processor.h> + +#ifndef __ASSEMBLY__ + +void __handle_exception(struct cpu_user_regs *cpu_regs); +void handle_exception(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_TRAPS_H__ */ diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c new file mode 100644 index 0000000000..3201b851ef --- /dev/null +++ b/xen/arch/riscv/traps.c @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2023 Vates + * + * RISC-V Trap handlers + */ +#include <asm/processor.h> +#include <asm/traps.h> + +void __handle_exception(struct cpu_user_regs *cpu_regs) +{ + wait_for_interrupt(); +}
The patch introduces an implementation of basic exception handlers: - to save/restore context - to handle an exception itself. The handler calls wait_for_interrupt now, nothing more. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> --- xen/arch/riscv/Makefile | 2 + xen/arch/riscv/entry.S | 97 ++++++++++++++++++++++++++++++ xen/arch/riscv/include/asm/traps.h | 13 ++++ xen/arch/riscv/traps.c | 13 ++++ 4 files changed, 125 insertions(+) create mode 100644 xen/arch/riscv/entry.S create mode 100644 xen/arch/riscv/include/asm/traps.h create mode 100644 xen/arch/riscv/traps.c