Same demo as for other architectures. Signed-off-by: Ralf Ramsauer <ralf.ramsa...@oth-regensburg.de> --- inmates/demos/riscv/Makefile | 3 +- inmates/demos/riscv/timer-demo.c | 57 +++++++++++++++ inmates/lib/riscv/Makefile | 2 +- inmates/lib/riscv/header.S | 29 ++++++++ inmates/lib/riscv/include/inmate.h | 27 +++++++- inmates/lib/riscv/inmate.lds.S | 3 + inmates/lib/riscv/irq.c | 107 +++++++++++++++++++++++++++++ 7 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 inmates/demos/riscv/timer-demo.c create mode 100644 inmates/lib/riscv/irq.c
diff --git a/inmates/demos/riscv/Makefile b/inmates/demos/riscv/Makefile index 2f0bac84..e371a29b 100644 --- a/inmates/demos/riscv/Makefile +++ b/inmates/demos/riscv/Makefile @@ -12,8 +12,9 @@ include $(INMATES_LIB)/Makefile.lib -INMATES := tiny-demo.bin +INMATES := tiny-demo.bin timer-demo.bin tiny-demo-y := tiny-demo.o +timer-demo-y := timer-demo.o $(eval $(call DECLARE_TARGETS,$(INMATES))) diff --git a/inmates/demos/riscv/timer-demo.c b/inmates/demos/riscv/timer-demo.c new file mode 100644 index 00000000..748219b7 --- /dev/null +++ b/inmates/demos/riscv/timer-demo.c @@ -0,0 +1,57 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Copyright (c) OTH Regensburg, 2022 + * + * Authors: + * Ralf Ramsauer <ralf.ramsa...@oth-regensburg.de> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include <inmate.h> + +#include <jailhouse/hypercall.h> + +#define TIMEBASE_FREQ 0x989680 +#define TIMER_DELTA (TIMEBASE_FREQ / 6) + +unsigned long timer_next; + +static inline u64 timer_ticks_to_ns(u64 ticks) +{ + return (1000UL * 1000UL * 1000UL * ticks) / TIMEBASE_FREQ; +} + +unsigned long timer_handler(void) +{ + static u64 min_delta = ~0ULL, max_delta = 0; + unsigned long delta; + + delta = get_cycles() - timer_next; + if (delta < min_delta) + min_delta = delta; + if (delta > max_delta) + max_delta = delta; + + printk("Timer fired, jitter: %6ld ns, min: %6ld ns, max: %6ld ns\n", + (long)timer_ticks_to_ns(delta), + (long)timer_ticks_to_ns(min_delta), + (long)timer_ticks_to_ns(max_delta)); + + timer_next += TIMER_DELTA; + + return timer_next; +} + +void inmate_main(void) +{ + printk("Initializing the timer...\n"); + timer_next = get_cycles() + 0x400000; + sbi_set_timer(timer_next); + timer_enable(); + enable_irqs(); + + halt(); +} diff --git a/inmates/lib/riscv/Makefile b/inmates/lib/riscv/Makefile index 9ff57721..3b796dc3 100644 --- a/inmates/lib/riscv/Makefile +++ b/inmates/lib/riscv/Makefile @@ -41,6 +41,6 @@ include $(INMATES_LIB)/Makefile.lib always-y := lib.a inmate.lds lib-y := $(common-objs-y) -lib-y += header.o printk.o setup.o uart.o +lib-y += header.o irq.o printk.o setup.o uart.o lib-y += ../cmdline.o ../printk.o ../setup.o ../string.o ../uart-8250.o diff --git a/inmates/lib/riscv/header.S b/inmates/lib/riscv/header.S index 3a12f51f..5ddffe79 100644 --- a/inmates/lib/riscv/header.S +++ b/inmates/lib/riscv/header.S @@ -36,9 +36,38 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#define STRUCT_REGISTERS_SIZE (32 * 8) + +.macro context cmd + .irp reg 1, 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 + \cmd x\reg, 8*(\reg - 1)(sp) + .endr +.endm + .section ".boot", "ax" .globl __reset_entry __reset_entry: la sp, __stack_top + addi sp, sp, -STRUCT_REGISTERS_SIZE + + la a5 , __ex_stack_top + csrw sscratch, a5 + + la a5, exception_handler + csrw stvec, a5 + j c_entry + +.text +.align 4 +exception_handler: + csrrw sp, sscratch, sp + context sd + + jal arch_handle_trap + + context ld + csrrw sp, sscratch, sp + sret diff --git a/inmates/lib/riscv/include/inmate.h b/inmates/lib/riscv/include/inmate.h index dac9f146..57338d25 100644 --- a/inmates/lib/riscv/include/inmate.h +++ b/inmates/lib/riscv/include/inmate.h @@ -1,7 +1,7 @@ /* * Jailhouse, a Linux-based partitioning hypervisor * - * Copyright (c) OTH Regensburg + * Copyright (c) OTH Regensburg, 2022 * * Authors: * Ralf Ramsauer <ralf.ramsa...@oth-regensburg.de> @@ -60,6 +60,9 @@ typedef unsigned long long u64; #define SR_SIE 0x00000002UL +#define IRQ_S_TIMER 5 +#define IE_TIE (0x1UL << IRQ_S_TIMER) + #define csr_read(csr) \ ({ \ register unsigned long __v; \ @@ -93,11 +96,31 @@ typedef unsigned long long u64; : "memory"); \ }) +static inline unsigned long get_cycles(void) +{ + return csr_read(time); +} + static inline void disable_irqs(void) { csr_clear(sstatus, SR_SIE); } +static inline void enable_irqs(void) +{ + csr_set(sstatus, SR_SIE); +} + +static inline void timer_enable(void) +{ + csr_set(sie, IE_TIE); +} + +static inline void timer_disable(void) +{ + csr_clear(sie, IE_TIE); +} + static inline void cpu_relax(void) { int dummy; @@ -152,6 +175,8 @@ static inline void mmio_write64(void *address, u64 value) *(volatile u64 *)address = value; } +unsigned long timer_handler(void); + #include <inmate_common.h> #endif /* !_JAILHOUSE_INMATE_H */ diff --git a/inmates/lib/riscv/inmate.lds.S b/inmates/lib/riscv/inmate.lds.S index cb6e7a76..91bc8f22 100644 --- a/inmates/lib/riscv/inmate.lds.S +++ b/inmates/lib/riscv/inmate.lds.S @@ -69,6 +69,9 @@ SECTIONS { . = ALIGN(4096); . = . + 0x1000; __stack_top = .; + + . = . + 0x1000; + __ex_stack_top = .; } ENTRY(__reset_entry) diff --git a/inmates/lib/riscv/irq.c b/inmates/lib/riscv/irq.c new file mode 100644 index 00000000..8f6d0085 --- /dev/null +++ b/inmates/lib/riscv/irq.c @@ -0,0 +1,107 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Copyright (c) OTH Regensburg, 2022 + * + * Authors: + * Ralf Ramsauer <ralf.ramsa...@oth-regensburg.de> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Alternatively, you can use or redistribute this file under the following + * BSD license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <inmate.h> + +#define CAUSE_IRQ_FLAG (1UL << (__riscv_xlen - 1)) + +void arch_handle_trap(void); + +static inline bool is_irq(u64 cause) +{ + return !!(cause & CAUSE_IRQ_FLAG); +} + +static inline unsigned long to_irq(unsigned long cause) +{ + return cause & ~CAUSE_IRQ_FLAG; +} + +static int handle_irq(unsigned int irq) +{ + int err; + struct sbiret ret; + unsigned long tval; + + switch (irq) { + case IRQ_S_TIMER: + tval = timer_handler(); + ret = sbi_set_timer(tval); + err = ret.error; + break; + + default: + err = -1; + break; + } + return err; +} + +/* + * Any positive value will reprogramm the timer, -1 will halt the timer. + */ +unsigned long __attribute__((weak)) timer_handler(void) +{ + return -1; +} + +void arch_handle_trap(void) +{ + unsigned long scause = csr_read(scause); + int err; + + if (is_irq(scause)) { + err = handle_irq(to_irq(scause)); + goto out; + } + + switch (scause) { + default: + /* We don't have any exception handlers at the moment */ + printk("Unhandled exception %lu occured.\n", scause); + err = -1; + break; + } + +out: + if (err) { + printk("FATAL INMATE ERROR. HALTED.\n"); + stop(); + + } +} -- 2.40.1 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to jailhouse-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/jailhouse-dev/20230519204033.643200-54-ralf.ramsauer%40oth-regensburg.de.