[arch][riscv] port to riscv64
Very little needed to port except to conditionalize some assembly in the context switch and exception code. Mostly needed to move build system stuff around and add a new project.
This commit is contained in:
156
arch/riscv/asm.S
156
arch/riscv/asm.S
@@ -7,43 +7,55 @@
|
||||
*/
|
||||
#include <lk/asm.h>
|
||||
|
||||
/* void riscv32_context_switch(
|
||||
struct riscv32_context_switch_frame *oldcs,
|
||||
struct riscv32_context_switch_frame *newcs); */
|
||||
FUNCTION(riscv32_context_switch)
|
||||
// based on 32 or 64bit register widths, select the 32 or 64 bit
|
||||
// wide load/stores
|
||||
#if __riscv_xlen == 32
|
||||
#define REGOFF(x) ((x) * 4)
|
||||
#define STR sw
|
||||
#define LDR lw
|
||||
#else
|
||||
#define REGOFF(x) ((x) * 8)
|
||||
#define STR sd
|
||||
#define LDR ld
|
||||
#endif
|
||||
|
||||
/* void riscv_context_switch(
|
||||
struct riscv_context_switch_frame *oldcs,
|
||||
struct riscv_context_switch_frame *newcs); */
|
||||
FUNCTION(riscv_context_switch)
|
||||
# a0 = oldcs
|
||||
# a1 = newcs
|
||||
sw ra, 0(a0)
|
||||
sw sp, 4(a0)
|
||||
sw tp, 8(a0)
|
||||
sw s0, 12(a0)
|
||||
sw s1, 16(a0)
|
||||
sw s2, 20(a0)
|
||||
sw s3, 24(a0)
|
||||
sw s4, 28(a0)
|
||||
sw s5, 32(a0)
|
||||
sw s6, 36(a0)
|
||||
sw s7, 40(a0)
|
||||
sw s8, 44(a0)
|
||||
sw s9, 48(a0)
|
||||
sw s10, 52(a0)
|
||||
sw s11, 56(a0)
|
||||
STR ra, REGOFF(0)(a0)
|
||||
STR sp, REGOFF(1)(a0)
|
||||
STR tp, REGOFF(2)(a0)
|
||||
STR s0, REGOFF(3)(a0)
|
||||
STR s1, REGOFF(4)(a0)
|
||||
STR s2, REGOFF(5)(a0)
|
||||
STR s3, REGOFF(6)(a0)
|
||||
STR s4, REGOFF(7)(a0)
|
||||
STR s5, REGOFF(8)(a0)
|
||||
STR s6, REGOFF(9)(a0)
|
||||
STR s7, REGOFF(10)(a0)
|
||||
STR s8, REGOFF(11)(a0)
|
||||
STR s9, REGOFF(12)(a0)
|
||||
STR s10, REGOFF(13)(a0)
|
||||
STR s11, REGOFF(14)(a0)
|
||||
|
||||
lw s11, 56(a1)
|
||||
lw s10, 52(a1)
|
||||
lw s9, 48(a1)
|
||||
lw s8, 44(a1)
|
||||
lw s7, 40(a1)
|
||||
lw s6, 36(a1)
|
||||
lw s5, 32(a1)
|
||||
lw s4, 28(a1)
|
||||
lw s3, 24(a1)
|
||||
lw s2, 20(a1)
|
||||
lw s1, 16(a1)
|
||||
lw s0, 12(a1)
|
||||
lw tp, 8(a1)
|
||||
lw sp, 4(a1)
|
||||
lw ra, 0(a1)
|
||||
LDR s11, REGOFF(14)(a1)
|
||||
LDR s10, REGOFF(13)(a1)
|
||||
LDR s9, REGOFF(12)(a1)
|
||||
LDR s8, REGOFF(11)(a1)
|
||||
LDR s7, REGOFF(10)(a1)
|
||||
LDR s6, REGOFF(9)(a1)
|
||||
LDR s5, REGOFF(8)(a1)
|
||||
LDR s4, REGOFF(7)(a1)
|
||||
LDR s3, REGOFF(6)(a1)
|
||||
LDR s2, REGOFF(5)(a1)
|
||||
LDR s1, REGOFF(4)(a1)
|
||||
LDR s0, REGOFF(3)(a1)
|
||||
LDR tp, REGOFF(2)(a1)
|
||||
LDR sp, REGOFF(1)(a1)
|
||||
LDR ra, REGOFF(0)(a1)
|
||||
|
||||
ret
|
||||
|
||||
@@ -51,54 +63,54 @@ FUNCTION(riscv32_context_switch)
|
||||
.balign 4
|
||||
FUNCTION(riscv_exception_entry)
|
||||
/* dump all the callee trashed regs on the stack */
|
||||
addi sp, sp, -80 // subtract a multiple of 16 to align the stack
|
||||
sw t6, 68(sp)
|
||||
sw t5, 64(sp)
|
||||
sw t4, 60(sp)
|
||||
sw t3, 56(sp)
|
||||
sw t2, 52(sp)
|
||||
sw t1, 48(sp)
|
||||
sw t0, 44(sp)
|
||||
sw a7, 40(sp)
|
||||
sw a6, 36(sp)
|
||||
sw a5, 32(sp)
|
||||
sw a4, 28(sp)
|
||||
sw a3, 24(sp)
|
||||
sw a2, 20(sp)
|
||||
sw a1, 16(sp)
|
||||
sw a0, 12(sp)
|
||||
sw ra, 8(sp)
|
||||
addi sp, sp, -REGOFF(20) // subtract a multiple of 16 to align the stack in 32bit
|
||||
STR t6, REGOFF(17)(sp)
|
||||
STR t5, REGOFF(16)(sp)
|
||||
STR t4, REGOFF(15)(sp)
|
||||
STR t3, REGOFF(14)(sp)
|
||||
STR t2, REGOFF(13)(sp)
|
||||
STR t1, REGOFF(12)(sp)
|
||||
STR t0, REGOFF(11)(sp)
|
||||
STR a7, REGOFF(10)(sp)
|
||||
STR a6, REGOFF(9)(sp)
|
||||
STR a5, REGOFF(8)(sp)
|
||||
STR a4, REGOFF(7)(sp)
|
||||
STR a3, REGOFF(6)(sp)
|
||||
STR a2, REGOFF(5)(sp)
|
||||
STR a1, REGOFF(4)(sp)
|
||||
STR a0, REGOFF(3)(sp)
|
||||
STR ra, REGOFF(2)(sp)
|
||||
csrr t0, mstatus
|
||||
sw t0, 4(sp)
|
||||
STR t0, REGOFF(1)(sp)
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
sw a1, 0(sp)
|
||||
STR a1, REGOFF(0)(sp)
|
||||
mv a2, sp
|
||||
|
||||
jal riscv_exception_handler
|
||||
|
||||
/* put everything back */
|
||||
lw t0, 0(sp)
|
||||
LDR t0, REGOFF(0)(sp)
|
||||
csrw mepc, t0
|
||||
lw t0, 4(sp)
|
||||
LDR t0, REGOFF(1)(sp)
|
||||
csrw mstatus, t0
|
||||
|
||||
lw ra, 8(sp)
|
||||
lw a0, 12(sp)
|
||||
lw a1, 16(sp)
|
||||
lw a2, 20(sp)
|
||||
lw a3, 24(sp)
|
||||
lw a4, 28(sp)
|
||||
lw a5, 32(sp)
|
||||
lw a6, 36(sp)
|
||||
lw a7, 40(sp)
|
||||
lw t0, 44(sp)
|
||||
lw t1, 48(sp)
|
||||
lw t2, 52(sp)
|
||||
lw t3, 56(sp)
|
||||
lw t4, 60(sp)
|
||||
lw t5, 64(sp)
|
||||
lw t6, 68(sp)
|
||||
addi sp, sp, 80
|
||||
LDR ra, REGOFF(2)(sp)
|
||||
LDR a0, REGOFF(3)(sp)
|
||||
LDR a1, REGOFF(4)(sp)
|
||||
LDR a2, REGOFF(5)(sp)
|
||||
LDR a3, REGOFF(6)(sp)
|
||||
LDR a4, REGOFF(7)(sp)
|
||||
LDR a5, REGOFF(8)(sp)
|
||||
LDR a6, REGOFF(9)(sp)
|
||||
LDR a7, REGOFF(10)(sp)
|
||||
LDR t0, REGOFF(11)(sp)
|
||||
LDR t1, REGOFF(12)(sp)
|
||||
LDR t2, REGOFF(13)(sp)
|
||||
LDR t3, REGOFF(14)(sp)
|
||||
LDR t4, REGOFF(15)(sp)
|
||||
LDR t5, REGOFF(16)(sp)
|
||||
LDR t6, REGOFF(17)(sp)
|
||||
addi sp, sp, REGOFF(20)
|
||||
|
||||
mret
|
||||
|
||||
@@ -43,12 +43,15 @@ void riscv_exception_handler(ulong cause, ulong epc, struct riscv_short_iframe *
|
||||
DEBUG_ASSERT(arch_ints_disabled());
|
||||
DEBUG_ASSERT(frame->mstatus & RISCV_STATUS_MPIE);
|
||||
|
||||
// top bit of the cause register determines if it's an interrupt or not
|
||||
const ulong int_bit = (__riscv_xlen == 32) ? (1ul<<31) : (1ul<<63);
|
||||
|
||||
enum handler_return ret = INT_NO_RESCHEDULE;
|
||||
switch (cause) {
|
||||
case 0x80000007: // machine timer interrupt
|
||||
case int_bit | 0x7: // machine timer interrupt
|
||||
ret = riscv_timer_exception();
|
||||
break;
|
||||
case 0x8000000b: // machine external interrupt
|
||||
case int_bit | 0xb: // machine external interrupt
|
||||
ret = riscv_platform_irq();
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -9,30 +9,30 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct riscv32_context_switch_frame {
|
||||
uint32_t ra; // return address (x1)
|
||||
uint32_t sp; // stack pointer (x2)
|
||||
uint32_t tp; // thread pointer (x4)
|
||||
struct riscv_context_switch_frame {
|
||||
unsigned long ra; // return address (x1)
|
||||
unsigned long sp; // stack pointer (x2)
|
||||
unsigned long tp; // thread pointer (x4)
|
||||
|
||||
uint32_t s0; // x8-x9
|
||||
uint32_t s1;
|
||||
unsigned long s0; // x8-x9
|
||||
unsigned long s1;
|
||||
|
||||
uint32_t s2; // x18-x27
|
||||
uint32_t s3;
|
||||
uint32_t s4;
|
||||
uint32_t s5;
|
||||
uint32_t s6;
|
||||
uint32_t s7;
|
||||
uint32_t s8;
|
||||
uint32_t s9;
|
||||
uint32_t s10;
|
||||
uint32_t s11;
|
||||
unsigned long s2; // x18-x27
|
||||
unsigned long s3;
|
||||
unsigned long s4;
|
||||
unsigned long s5;
|
||||
unsigned long s6;
|
||||
unsigned long s7;
|
||||
unsigned long s8;
|
||||
unsigned long s9;
|
||||
unsigned long s10;
|
||||
unsigned long s11;
|
||||
};
|
||||
|
||||
struct arch_thread {
|
||||
struct riscv32_context_switch_frame cs_frame;
|
||||
struct riscv_context_switch_frame cs_frame;
|
||||
};
|
||||
|
||||
void riscv32_context_switch(struct riscv32_context_switch_frame *oldcs,
|
||||
struct riscv32_context_switch_frame *newcs);
|
||||
void riscv_context_switch(struct riscv_context_switch_frame *oldcs,
|
||||
struct riscv_context_switch_frame *newcs);
|
||||
|
||||
|
||||
@@ -13,4 +13,8 @@
|
||||
// XXX is this right?
|
||||
#define CACHE_LINE 32
|
||||
|
||||
#if ARCH_RISCV_EMBEDDED
|
||||
#define ARCH_DEFAULT_STACK_SIZE 1024
|
||||
#else
|
||||
#define ARCH_DEFAULT_STACK_SIZE 4096
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
|
||||
OUTPUT_FORMAT("elf%BITS%-littleriscv", "elf%BITS%-bigriscv", "elf%BITS%-littleriscv")
|
||||
OUTPUT_ARCH(riscv)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
|
||||
OUTPUT_FORMAT("elf%BITS%-littleriscv", "elf%BITS%-bigriscv", "elf%BITS%-littleriscv")
|
||||
OUTPUT_ARCH(riscv)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
@@ -12,30 +12,49 @@ MODULE_SRCS += $(LOCAL_DIR)/thread.c
|
||||
GLOBAL_DEFINES += SMP_MAX_CPUS=1
|
||||
GLOBAL_DEFINES += PLATFORM_HAS_DYNAMIC_TIMER=1
|
||||
|
||||
# set the default toolchain to riscv32 elf and set a #define
|
||||
ifndef TOOLCHAIN_PREFIX
|
||||
TOOLCHAIN_PREFIX := riscv32-elf-
|
||||
endif
|
||||
SUBARCH ?= 32
|
||||
|
||||
WITH_LINKER_GC ?= 0
|
||||
|
||||
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`"; \
|
||||
then echo "$(2)"; else echo "$(3)"; fi ;)
|
||||
|
||||
ARCH_COMPILEFLAGS := -march=rv32imac -mabi=ilp32
|
||||
ARCH_OPTFLAGS := -O2
|
||||
|
||||
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(GLOBAL_COMPILEFLAGS) $(ARCH_COMPILEFLAGS) $(GLOBAL_CFLAGS) -print-libgcc-file-name)
|
||||
$(info LIBGCC = $(LIBGCC))
|
||||
|
||||
KERNEL_BASE ?= $(MEMBASE)
|
||||
KERNEL_LOAD_OFFSET ?= 0
|
||||
ROMBASE ?= 0
|
||||
|
||||
GLOBAL_DEFINES += \
|
||||
ROMBASE=$(ROMBASE) \
|
||||
MEMBASE=$(MEMBASE) \
|
||||
MEMSIZE=$(MEMSIZE)
|
||||
GLOBAL_DEFINES += ROMBASE=$(ROMBASE)
|
||||
GLOBAL_DEFINES += MEMBASE=$(MEMBASE)
|
||||
GLOBAL_DEFINES += MEMSIZE=$(MEMSIZE)
|
||||
|
||||
# based on 32 or 64 bitness, select the right toolchain and some
|
||||
# compiler codegen flags
|
||||
ifeq ($(SUBARCH),32)
|
||||
|
||||
ifndef TOOLCHAIN_PREFIX
|
||||
TOOLCHAIN_PREFIX := riscv32-elf-
|
||||
endif
|
||||
ARCH_COMPILEFLAGS := -march=rv32imac -mabi=ilp32
|
||||
|
||||
else ifeq ($(SUBARCH),64)
|
||||
|
||||
ifndef TOOLCHAIN_PREFIX
|
||||
TOOLCHAIN_PREFIX := riscv64-elf-
|
||||
endif
|
||||
ARCH_COMPILEFLAGS := -march=rv64imafdc -mabi=lp64d -mcmodel=medany
|
||||
|
||||
else
|
||||
$(error SUBARCH not set or set to something unknown)
|
||||
endif
|
||||
|
||||
# embedded switch sets the default compile optimization and passes
|
||||
# a flag to the code to switch other things on
|
||||
ifeq (true,$(call TOBOOL,$(ARCH_RISCV_EMBEDDED)))
|
||||
ARCH_OPTFLAGS ?= -Os
|
||||
GLOBAL_DEFINES += ARCH_RISCV_EMBEDDED=1
|
||||
else
|
||||
ARCH_OPTFLAGS ?= -O2
|
||||
endif
|
||||
|
||||
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(GLOBAL_COMPILEFLAGS) $(ARCH_COMPILEFLAGS) $(GLOBAL_CFLAGS) -print-libgcc-file-name)
|
||||
$(info LIBGCC = $(LIBGCC))
|
||||
|
||||
# potentially generated files that should be cleaned out with clean make rule
|
||||
GENERATED += \
|
||||
@@ -46,7 +65,7 @@ GENERATED += \
|
||||
$(BUILDDIR)/linker-%.ld: $(LOCAL_DIR)/linker-%.ld $(wildcard arch/*.ld) linkerscript.phony
|
||||
@echo generating $@
|
||||
@$(MKDIR)
|
||||
$(NOECHO)sed "s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/;s/%KERNEL_BASE%/$(KERNEL_BASE)/;s/%KERNEL_LOAD_OFFSET%/$(KERNEL_LOAD_OFFSET)/;s/%VECTOR_BASE_PHYS%/$(VECTOR_BASE_PHYS)/" < $< > $@.tmp
|
||||
$(NOECHO)sed "s/%BITS%/$(SUBARCH)/g;s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/;s/%KERNEL_BASE%/$(KERNEL_BASE)/;s/%KERNEL_LOAD_OFFSET%/$(KERNEL_LOAD_OFFSET)/;s/%VECTOR_BASE_PHYS%/$(VECTOR_BASE_PHYS)/" < $< > $@.tmp
|
||||
@$(call TESTANDREPLACEFILE,$@.tmp,$@)
|
||||
|
||||
linkerscript.phony:
|
||||
@@ -54,8 +73,10 @@ linkerscript.phony:
|
||||
|
||||
# select the appropriate linker script based on if we're a one or two segment system
|
||||
ifeq (true,$(call TOBOOL,$(ARCH_RISCV_TWOSEGMENT)))
|
||||
GLOBAL_DEFINES += ARCH_RISCV_TWOSEGMENT=1
|
||||
LINKER_SCRIPT += $(BUILDDIR)/linker-twosegment.ld
|
||||
else
|
||||
GLOBAL_DEFINES += ARCH_RISCV_TWOSEGMENT=0
|
||||
LINKER_SCRIPT += $(BUILDDIR)/linker-onesegment.ld
|
||||
endif
|
||||
|
||||
|
||||
@@ -7,26 +7,6 @@
|
||||
*/
|
||||
#include <lk/asm.h>
|
||||
|
||||
#if 0
|
||||
.section ".vectors", "ax"
|
||||
.globl _vectab
|
||||
_vectab:
|
||||
/* vector table here */
|
||||
# start vector
|
||||
brai start
|
||||
# user exception
|
||||
brai unhandled_exception
|
||||
# interrupt
|
||||
brai microblaze_irq
|
||||
# break
|
||||
brai unhandled_exception
|
||||
# hardware exception
|
||||
brai unhandled_exception
|
||||
|
||||
# reserved for future
|
||||
.fill (0x50 - 0x28)
|
||||
#endif
|
||||
|
||||
.section ".text.boot"
|
||||
FUNCTION(_start)
|
||||
.option push
|
||||
@@ -38,7 +18,7 @@ FUNCTION(_start)
|
||||
# set the default stack
|
||||
la sp, default_stack_top
|
||||
|
||||
#if 1
|
||||
#if ARCH_RISCV_TWOSEGMENT
|
||||
# copy preinitialized data from flash to memory
|
||||
la t0, __data_start_rom
|
||||
la t1, __data_start
|
||||
|
||||
@@ -55,13 +55,13 @@ void arch_context_switch(thread_t *oldthread, thread_t *newthread) {
|
||||
|
||||
LTRACEF("old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
|
||||
|
||||
riscv32_context_switch(&oldthread->arch.cs_frame, &newthread->arch.cs_frame);
|
||||
riscv_context_switch(&oldthread->arch.cs_frame, &newthread->arch.cs_frame);
|
||||
}
|
||||
|
||||
void arch_dump_thread(thread_t *t) {
|
||||
if (t->state != THREAD_RUNNING) {
|
||||
dprintf(INFO, "\tarch: ");
|
||||
dprintf(INFO, "sp 0x%x\n", t->arch.cs_frame.sp);
|
||||
dprintf(INFO, "sp %#lx\n", t->arch.cs_frame.sp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@ static void novm_dump_arena(struct novm_arena *n) {
|
||||
}
|
||||
|
||||
mutex_acquire(&n->lock);
|
||||
printf("name '%s', %d pages, each %zdk (%zdk in all)\n", n->name, n->pages, PAGE_SIZE >> 10, (PAGE_SIZE * n->pages) >> 10);
|
||||
printf("name '%s', %zu pages, each %zdk (%zdk in all)\n", n->name, n->pages, (size_t)PAGE_SIZE >> 10, (size_t)(PAGE_SIZE * n->pages) >> 10);
|
||||
printf(" range: %p-%p\n", (void *)n->base, (char *)n->base + n->size);
|
||||
printf(" unaligned range: %p-%p\n", n->unaligned_area, n->unaligned_area + n->unaligned_size);
|
||||
unsigned i;
|
||||
|
||||
@@ -4,7 +4,6 @@ MODULE := $(LOCAL_DIR)
|
||||
|
||||
ARCH := riscv
|
||||
SUBARCH ?= 32
|
||||
VARIANT ?= sifive_u
|
||||
|
||||
MODULE_DEPS += lib/cbuf
|
||||
|
||||
|
||||
@@ -16,8 +16,12 @@ ROMBASE ?= 0x20400000 # if running from rom, start here
|
||||
MEMBASE ?= 0x80000000
|
||||
MEMSIZE ?= 0x00100000 # default to 1MB
|
||||
|
||||
ifeq ($(VARIANT),sifive_e)
|
||||
# uses a two segment layout, select the appropriate linker script
|
||||
ARCH_RISCV_TWOSEGMENT := 1
|
||||
# sets a few options in the riscv arch
|
||||
ARCH_RISCV_EMBEDDED := 1
|
||||
endif
|
||||
|
||||
# sifive_e or _u?
|
||||
GLOBAL_DEFINES += PLATFORM_${VARIANT}=1
|
||||
|
||||
10
project/qemu-virt-riscv64-test.mk
Normal file
10
project/qemu-virt-riscv64-test.mk
Normal file
@@ -0,0 +1,10 @@
|
||||
# main project for qemu-riscv64
|
||||
MODULES += \
|
||||
app/shell
|
||||
SUBARCH := 64
|
||||
|
||||
include project/virtual/test.mk
|
||||
include project/virtual/fs.mk
|
||||
include project/virtual/minip.mk
|
||||
include project/target/qemu-virt-riscv.mk
|
||||
|
||||
@@ -55,12 +55,10 @@ done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if (( $DO_64BIT )); then
|
||||
echo unsupported now
|
||||
exit 1
|
||||
QEMU="qemu-system-riscv64"
|
||||
#CPU="cortex-a53"
|
||||
CPU="any"
|
||||
MACHINE="virt"
|
||||
_PROJECT="qemu-virt-arm64-test"
|
||||
_PROJECT="qemu-virt-riscv64-test"
|
||||
elif (( $DO_EMBEDDED == 1 )); then
|
||||
QEMU="qemu-system-riscv32"
|
||||
MACHINE="sifive_e"
|
||||
Reference in New Issue
Block a user