From ae5200595c23a792f2865dff7ec581650ce6f163 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Sat, 30 Mar 2019 21:31:47 -0700 Subject: [PATCH] [platform][riscv-virt] added support for QEMU's riscv 'virt' machine The virt machine is a generic target, much like the arm virt machine. Intended to be simple to use and a good target to run large systems like linux on. At the moment simply support booting and simple uart and timer support. --- .travis.yml | 1 + arch/riscv/exceptions.c | 2 +- arch/riscv/linker-onesegment.ld | 107 ++++++++++++++++ .../riscv/{linker.ld => linker-twosegment.ld} | 0 arch/riscv/rules.mk | 18 ++- .../qemu-virt-riscv/include/platform/virt.h | 24 ++++ platform/qemu-virt-riscv/platform.c | 28 +++++ platform/qemu-virt-riscv/platform_p.h | 17 +++ platform/qemu-virt-riscv/plic.c | 94 ++++++++++++++ platform/qemu-virt-riscv/rules.mk | 26 ++++ platform/qemu-virt-riscv/uart.c | 81 ++++++++++++ platform/sifive/plic.c | 7 ++ platform/sifive/rules.mk | 3 + project/qemu-virt-riscv32-test.mk | 10 ++ project/target/qemu-virt-riscv.mk | 2 + scripts/do-qemuarm | 4 +- scripts/do-qemuriscv32 | 118 +++++++++++++++++- target/qemu-virt-riscv/rules.mk | 7 ++ 18 files changed, 536 insertions(+), 13 deletions(-) create mode 100644 arch/riscv/linker-onesegment.ld rename arch/riscv/{linker.ld => linker-twosegment.ld} (100%) create mode 100644 platform/qemu-virt-riscv/include/platform/virt.h create mode 100644 platform/qemu-virt-riscv/platform.c create mode 100644 platform/qemu-virt-riscv/platform_p.h create mode 100644 platform/qemu-virt-riscv/plic.c create mode 100644 platform/qemu-virt-riscv/rules.mk create mode 100644 platform/qemu-virt-riscv/uart.c create mode 100644 project/qemu-virt-riscv32-test.mk create mode 100644 project/target/qemu-virt-riscv.mk create mode 100644 target/qemu-virt-riscv/rules.mk diff --git a/.travis.yml b/.travis.yml index 5d2a1c31..d7824e71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ env: - PROJECT=nucleo-f072rb TOOLCHAIN=arm-eabi-7.3.0-Linux-x86_64 - PROJECT=qemu-microblaze-test TOOLCHAIN=microblaze-elf-7.3.0-Linux-x86_64 - PROJECT=qemu-mips-test TOOLCHAIN=mips-elf-7.3.0-Linux-x86_64 + - PROJECT=qemu-virt-riscv32-test TOOLCHAIN=riscv32-elf-7.3.0-Linux-x86_64 - PROJECT=sifive-e-test TOOLCHAIN=riscv32-elf-7.3.0-Linux-x86_64 - PROJECT=pc-x86-test TOOLCHAIN=i386-elf-7.3.0-Linux-x86_64 - PROJECT=pc-x86-64-test TOOLCHAIN=x86_64-elf-7.3.0-Linux-x86_64 diff --git a/arch/riscv/exceptions.c b/arch/riscv/exceptions.c index dfdc678e..8d41c11c 100644 --- a/arch/riscv/exceptions.c +++ b/arch/riscv/exceptions.c @@ -38,7 +38,7 @@ struct riscv_short_iframe { extern enum handler_return riscv_platform_irq(void); void riscv_exception_handler(ulong cause, ulong epc, struct riscv_short_iframe *frame) { - LTRACEF("cause %#lx epc %#lx\n", cause, epc); + LTRACEF("cause %#lx epc %#lx mstatus %#lx\n", cause, epc, frame->mstatus); DEBUG_ASSERT(arch_ints_disabled()); DEBUG_ASSERT(frame->mstatus & RISCV_STATUS_MPIE); diff --git a/arch/riscv/linker-onesegment.ld b/arch/riscv/linker-onesegment.ld new file mode 100644 index 00000000..b0baef67 --- /dev/null +++ b/arch/riscv/linker-onesegment.ld @@ -0,0 +1,107 @@ +OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") +OUTPUT_ARCH(riscv) + +ENTRY(_start) +SECTIONS +{ + . = %KERNEL_BASE% + %KERNEL_LOAD_OFFSET%; + + _start = .; + + /* text/read-only data */ + /* set the load address to physical MEMBASE */ + .text : AT(%MEMBASE% + %KERNEL_LOAD_OFFSET%) { + KEEP(*(.text.boot)) + *(.text .text*) + *(.gnu.linkonce.t.*) + } + + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + + .rodata : ALIGN(4) { + __rodata_start = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.srodata*) + } + + /* + * extra linker scripts tend to insert sections just after .rodata, + * so we want to make sure this symbol comes after anything inserted above, + * but not aligned to the next section necessarily. + */ + .dummy_post_rodata : { + __rodata_end = .; + } + + .data : ALIGN(4) { + __data_start_rom = .; + /* in one segment binaries, the rom data address is on top of the ram data address */ + __data_start = .; + *(.data .data.* .gnu.linkonce.d.*) + PROVIDE( __global_pointer$ = . + (4K / 2) ); + *(.sdata .sdata.*) + __ctor_list = .; + KEEP(*(.ctors .init_array)) + __ctor_end = .; + __dtor_list = .; + KEEP(*(.dtors .fini_array)) + __dtor_end = .; + *(.got*) + *(.dynamic) + } + + /* + * extra linker scripts tend to insert sections just after .data, + * so we want to make sure this symbol comes after anything inserted above, + * but not aligned to the next section necessarily. + */ + .dummy_post_data : { + __data_end = .; + } + + /* uninitialized data (in same segment as writable data) */ + .bss : ALIGN(4) { + __bss_start = .; + /* regular bss */ + *(.bss .bss.*) + *(.sbss .sbss.*) + *(.gnu.linkonce.b.*) + + . = ALIGN(4); + __bss_end = .; + } + + _end = .; + + . = %KERNEL_BASE% + %MEMSIZE%; + _end_of_ram = .; + + /* Strip unnecessary stuff */ + /DISCARD/ : { *(.comment .note .eh_frame) } +} + diff --git a/arch/riscv/linker.ld b/arch/riscv/linker-twosegment.ld similarity index 100% rename from arch/riscv/linker.ld rename to arch/riscv/linker-twosegment.ld diff --git a/arch/riscv/rules.mk b/arch/riscv/rules.mk index cf0ad656..384e149b 100644 --- a/arch/riscv/rules.mk +++ b/arch/riscv/rules.mk @@ -9,8 +9,8 @@ MODULE_SRCS += $(LOCAL_DIR)/clint.c MODULE_SRCS += $(LOCAL_DIR)/exceptions.c MODULE_SRCS += $(LOCAL_DIR)/thread.c -GLOBAL_DEFINES += \ - SMP_MAX_CPUS=1 +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 @@ -39,10 +39,11 @@ GLOBAL_DEFINES += \ # potentially generated files that should be cleaned out with clean make rule GENERATED += \ - $(BUILDDIR)/linker.ld + $(BUILDDIR)/linker-onesegment.ld \ + $(BUILDDIR)/linker-twosegment.ld -# rules for generating the linker -$(BUILDDIR)/linker.ld: $(LOCAL_DIR)/linker.ld $(wildcard arch/*.ld) linkerscript.phony +# rules for generating the linker script +$(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 @@ -51,6 +52,11 @@ $(BUILDDIR)/linker.ld: $(LOCAL_DIR)/linker.ld $(wildcard arch/*.ld) linkerscript linkerscript.phony: .PHONY: linkerscript.phony -LINKER_SCRIPT += $(BUILDDIR)/linker.ld +# select the appropriate linker script based on if we're a one or two segment system +ifeq (true,$(call TOBOOL,$(ARCH_RISCV_TWOSEGMENT))) +LINKER_SCRIPT += $(BUILDDIR)/linker-twosegment.ld +else +LINKER_SCRIPT += $(BUILDDIR)/linker-onesegment.ld +endif include make/module.mk diff --git a/platform/qemu-virt-riscv/include/platform/virt.h b/platform/qemu-virt-riscv/include/platform/virt.h new file mode 100644 index 00000000..03c73892 --- /dev/null +++ b/platform/qemu-virt-riscv/include/platform/virt.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#pragma once + +// memory and irq layout of qemu's riscv virt platform +// +// mostly taken from the top of qemu/hw/riscv/virt.c and similar headers + +#define IRQ_VIRTIO_BASE 1 +#define IRQ_UART0 10 +#define IRQ_PCIE_BASE 0x20 +#define NUM_IRQS 0x35 + +#define CLINT_BASE 0x02000000 +#define PLIC_BASE 0x0c000000 +#define UART0_BASE 0x10000000 +#define VIRTIO_BASE 0x10001000 +#define DRAM_BASE 0x80000000 + diff --git a/platform/qemu-virt-riscv/platform.c b/platform/qemu-virt-riscv/platform.c new file mode 100644 index 00000000..c240fdcf --- /dev/null +++ b/platform/qemu-virt-riscv/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform_p.h" + +void platform_early_init(void) { + plic_early_init(); +} + +void platform_init(void) { + plic_init(); + uart_init(); +} + + diff --git a/platform/qemu-virt-riscv/platform_p.h b/platform/qemu-virt-riscv/platform_p.h new file mode 100644 index 00000000..045accdf --- /dev/null +++ b/platform/qemu-virt-riscv/platform_p.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#pragma once + +#include + +void uart_init(void); + +void plic_early_init(void); +void plic_init(void); + + diff --git a/platform/qemu-virt-riscv/plic.c b/platform/qemu-virt-riscv/plic.c new file mode 100644 index 00000000..527e9177 --- /dev/null +++ b/platform/qemu-virt-riscv/plic.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#include "platform_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOCAL_TRACE 0 + +// Driver for PLIC implementation for qemu riscv virt machine + +#define PLIC_PRIORITY(x) (PLIC_BASE + 4 * (x)) +#define PLIC_PENDING(x) (PLIC_BASE + 0x1000 + 4 * ((x) / 32)) +#define PLIC_ENABLE(x) (PLIC_BASE + 0x2000 + 4 * ((x) / 32)) +#define PLIC_THRESHOLD (PLIC_BASE + 0x200000) +#define PLIC_COMPLETE (PLIC_BASE + 0x200004) +#define PLIC_CLAIM PLIC_COMPLETE + +static struct int_handlers { + int_handler handler; + void *arg; +} handlers[NUM_IRQS]; + +void plic_early_init(void) { + // mask all irqs and set their priority to 1 + for (int i = 1; i < NUM_IRQS; i++) { + *REG32(PLIC_ENABLE(i)) &= ~(1 << (i % 32)); + *REG32(PLIC_PRIORITY(i)) = 1; + } + + // set global priority threshold to 0 + *REG32(PLIC_THRESHOLD) = 0; +} + +void plic_init(void) { +} + +status_t mask_interrupt(unsigned int vector) { + *REG32(PLIC_ENABLE(vector)) &= ~(1 << (vector % 32)); + return NO_ERROR; +} + +status_t unmask_interrupt(unsigned int vector) { + *REG32(PLIC_ENABLE(vector)) |= (1 << (vector % 32)); + return NO_ERROR; +} + +void register_int_handler(unsigned int vector, int_handler handler, void *arg) { + LTRACEF("vector %u handler %p arg %p\n", vector, handler, arg); + + DEBUG_ASSERT(vector < NUM_IRQS); + + handlers[vector].handler = handler; + handlers[vector].arg = arg; +} + +enum handler_return riscv_platform_irq(void) { + // see what irq triggered it + uint32_t vector = *REG32(PLIC_CLAIM); + LTRACEF("vector %u\n", vector); + + if (unlikely(vector == 0)) { + // nothing pending + return INT_NO_RESCHEDULE; + } + + THREAD_STATS_INC(interrupts); + KEVLOG_IRQ_ENTER(vector); + + enum handler_return ret = INT_NO_RESCHEDULE; + if (handlers[vector].handler) { + ret = handlers[vector].handler(handlers[vector].arg); + } + + // ack the interrupt + *REG32(PLIC_COMPLETE) = vector; + + KEVLOG_IRQ_EXIT(vector); + + return ret; +} + diff --git a/platform/qemu-virt-riscv/rules.mk b/platform/qemu-virt-riscv/rules.mk new file mode 100644 index 00000000..73b361e4 --- /dev/null +++ b/platform/qemu-virt-riscv/rules.mk @@ -0,0 +1,26 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +ARCH := riscv +SUBARCH ?= 32 +VARIANT ?= sifive_u + +MODULE_DEPS += lib/cbuf + +MODULE_SRCS += $(LOCAL_DIR)/platform.c +MODULE_SRCS += $(LOCAL_DIR)/plic.c +MODULE_SRCS += $(LOCAL_DIR)/uart.c + +#ROMBASE ?= 0x20400000 # if running from rom, start here +MEMBASE ?= 0x80000000 +MEMSIZE ?= 0x00100000 # default to 1MB + +# sifive_e or _u? +GLOBAL_DEFINES += PLATFORM_${VARIANT}=1 + +# set some global defines based on capability +GLOBAL_DEFINES += ARCH_RISCV_CLINT_BASE=0x02000000 +GLOBAL_DEFINES += ARCH_RISCV_MTIME_RATE=10000000 + +include make/module.mk diff --git a/platform/qemu-virt-riscv/uart.c b/platform/qemu-virt-riscv/uart.c new file mode 100644 index 00000000..a0dd7a0b --- /dev/null +++ b/platform/qemu-virt-riscv/uart.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform_p.h" + +// simple 16550 driver for the emulated serial port on qemu riscv virt machine + +static volatile uint8_t *const uart_base = (uint8_t *)UART0_BASE; + +#define RXBUF_SIZE 128 +static char uart_rx_buf_data[RXBUF_SIZE]; +static cbuf_t uart_rx_buf; + +static inline uint8_t uart_read_8(size_t offset) { + return uart_base[offset]; +} + +static inline void uart_write_8(size_t offset, uint8_t val) { + uart_base[offset] = val; +} + +static enum handler_return uart_irq_handler(void *arg) { + unsigned char c; + bool resched = false; + + while (uart_read_8(5) & (1<<0)) { + c = uart_read_8(0); + cbuf_write_char(&uart_rx_buf, c, false); + resched = true; + } + + return resched ? INT_RESCHEDULE : INT_NO_RESCHEDULE; +} + +void uart_init(void) { + /* finish uart init to get rx going */ + cbuf_initialize_etc(&uart_rx_buf, RXBUF_SIZE, uart_rx_buf_data); + + register_int_handler(IRQ_UART0, uart_irq_handler, NULL); + + uart_write_8(1, 0x1); // enable receive data available interrupt + + unmask_interrupt(IRQ_UART0); +} + +void uart_putc(char c) { + while ((uart_read_8(5) & (1<<6)) == 0) + ; + uart_write_8(0, c); +} + +int uart_getc(char *c, bool wait) { + return cbuf_read_char(&uart_rx_buf, c, wait); +} + +void platform_dputc(char c) { + if (c == '\n') + platform_dputc('\r'); + uart_putc(c); +} + +int platform_dgetc(char *c, bool wait) { + int ret = uart_getc(c, wait); + + return ret; +} + diff --git a/platform/sifive/plic.c b/platform/sifive/plic.c index c7f87837..11978a57 100644 --- a/platform/sifive/plic.c +++ b/platform/sifive/plic.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -74,6 +76,9 @@ enum handler_return riscv_platform_irq(void) { return INT_NO_RESCHEDULE; } + THREAD_STATS_INC(interrupts); + KEVLOG_IRQ_ENTER(vector); + enum handler_return ret = INT_NO_RESCHEDULE; if (handlers[vector].handler) { ret = handlers[vector].handler(handlers[vector].arg); @@ -82,6 +87,8 @@ enum handler_return riscv_platform_irq(void) { // ack the interrupt *REG32(PLIC_COMPLETE) = vector; + KEVLOG_IRQ_EXIT(vector); + return ret; } diff --git a/platform/sifive/rules.mk b/platform/sifive/rules.mk index 82c757b5..f5bc75c6 100644 --- a/platform/sifive/rules.mk +++ b/platform/sifive/rules.mk @@ -16,6 +16,9 @@ ROMBASE ?= 0x20400000 # if running from rom, start here MEMBASE ?= 0x80000000 MEMSIZE ?= 0x00100000 # default to 1MB +# uses a two segment layout, select the appropriate linker script +ARCH_RISCV_TWOSEGMENT := 1 + # sifive_e or _u? GLOBAL_DEFINES += PLATFORM_${VARIANT}=1 diff --git a/project/qemu-virt-riscv32-test.mk b/project/qemu-virt-riscv32-test.mk new file mode 100644 index 00000000..3f98bdd9 --- /dev/null +++ b/project/qemu-virt-riscv32-test.mk @@ -0,0 +1,10 @@ +# main project for qemu-riscv32 +MODULES += \ + app/shell +SUBARCH := 32 + +include project/virtual/test.mk +include project/virtual/fs.mk +include project/virtual/minip.mk +include project/target/qemu-virt-riscv.mk + diff --git a/project/target/qemu-virt-riscv.mk b/project/target/qemu-virt-riscv.mk new file mode 100644 index 00000000..f6f04a25 --- /dev/null +++ b/project/target/qemu-virt-riscv.mk @@ -0,0 +1,2 @@ +TARGET := qemu-virt-riscv + diff --git a/scripts/do-qemuarm b/scripts/do-qemuarm index a3107eb8..62fe8b2b 100755 --- a/scripts/do-qemuarm +++ b/scripts/do-qemuarm @@ -103,9 +103,9 @@ fi MAKE_VARS="" if [ $DO_CMPCTMALLOC == 1 ]; then - MAKE_VARS=LK_HEAP_IMPLEMENTATION=cmpctmalloc + MAKE_VARS=LK_HEAP_IMPLEMENTATION=cmpctmalloc elif [ $DO_MINIHEAP == 1 ]; then - MAKE_VARS=LK_HEAP_IMPLEMENTATION=miniheap + MAKE_VARS=LK_HEAP_IMPLEMENTATION=miniheap fi $DIR/make-parallel $MAKE_VARS $PROJECT && diff --git a/scripts/do-qemuriscv32 b/scripts/do-qemuriscv32 index d2226698..b551914d 100755 --- a/scripts/do-qemuriscv32 +++ b/scripts/do-qemuriscv32 @@ -2,8 +2,118 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -set -e -set -x +function HELP { + echo "help:" + echo "-b a virtio block device" + echo "-c cmpctmalloc instead of dlmalloc" + echo "-M miniheap instead of dlmalloc" + echo "-n a virtio network device" + echo "-t a virtio tap network device" + echo "-d a virtio display" + echo "-e embeded platform" + echo "-6 64bit" + echo "-m " + echo "-s " + echo "-h for help" + echo "all arguments after -- are passed to qemu directly" + exit 1 +} -$DIR/make-parallel sifive-e-test -qemu-system-riscv32 -machine sifive_e -kernel build-sifive-e-test/lk.elf -nographic $@ +DO_NET=0 +DO_NET_TAP=0 +DO_BLOCK=0 +DO_64BIT=0 +DO_EMBEDDED=0 +DO_DISPLAY=0 +DO_CMPCTMALLOC=0 +DO_MINIHEAP=0 +SMP=1 +MEMSIZE=512 +SUDO="" +PROJECT="" + +while getopts bdhm:cMnte6p:s: FLAG; do + case $FLAG in + b) DO_BLOCK=1;; + c) DO_CMPCTMALLOC=1;; + d) DO_DISPLAY=1;; + M) DO_MINIHEAP=1;; + n) DO_NET=1;; + t) DO_NET_TAP=1;; + e) DO_EMBEDDED=1;; + 6) DO_64BIT=1;; + m) MEMSIZE=$OPTARG;; + s) SMP=$OPTARG;; + p) PROJECT=$OPTARG;; + h) HELP;; + \?) + echo unrecognized option + HELP + esac +done + +shift $((OPTIND-1)) + +if (( $DO_64BIT )); then + echo unsupported now + exit 1 + QEMU="qemu-system-riscv64" + #CPU="cortex-a53" + MACHINE="virt" + _PROJECT="qemu-virt-arm64-test" +elif (( $DO_EMBEDDED == 1 )); then + QEMU="qemu-system-riscv32" + MACHINE="sifive_e" + _PROJECT="sifive-e-test" +else + QEMU="qemu-system-riscv32" + CPU="any" + MACHINE="virt" + _PROJECT="qemu-virt-riscv32-test" +fi +if [ "$PROJECT" == "" ]; then + PROJECT=$_PROJECT +fi + +BLOCK_ARGS=" -drive if=none,file=blk.bin,id=blk,format=raw -device virtio-blk-device,drive=blk" +NET_ARGS=" -netdev user,id=vmnic,hostname=qemu -device virtio-net-device,netdev=vmnic" +NET_TAP_ARGS=" -netdev tap,id=vmnic -device virtio-net-device,netdev=vmnic" +NO_DISPLAY_ARGS=" -nographic" +DISPLAY_ARGS=" -device virtio-gpu-device -serial stdio" + +# the following args only really make sense on non embedded versions +if (( ! $DO_EMBEDDED )); then + ARGS=" -cpu $CPU -m $MEMSIZE -smp $SMP -machine $MACHINE -kernel build-${PROJECT}/lk.elf" + ARGS+=" -bios none" + if (( $DO_BLOCK )); then + ARGS+=$BLOCK_ARGS + fi + if (( $DO_NET )); then + ARGS+=$NET_ARGS + fi + if (( $DO_NET_TAP )); then + ARGS+=$NET_TAP_ARGS + SUDO="sudo " + fi + if (( $DO_DISPLAY )); then + ARGS+=$DISPLAY_ARGS + else + ARGS+=$NO_DISPLAY_ARGS + fi +else + # embedded machine is more fixed and only gets these options + ARGS="-machine $MACHINE -kernel build-${PROJECT}/lk.elf" + ARGS+=$NO_DISPLAY_ARGS +fi + +MAKE_VARS="" + +if (( $DO_CMPCTMALLOC )); then + MAKE_VARS=LK_HEAP_IMPLEMENTATION=cmpctmalloc +elif (( $DO_MINIHEAP )); then + MAKE_VARS=LK_HEAP_IMPLEMENTATION=miniheap +fi + +$DIR/make-parallel $MAKE_VARS $PROJECT && +echo $SUDO $QEMU $ARGS $@ && +$SUDO $QEMU $ARGS $@ diff --git a/target/qemu-virt-riscv/rules.mk b/target/qemu-virt-riscv/rules.mk new file mode 100644 index 00000000..2b19b4f3 --- /dev/null +++ b/target/qemu-virt-riscv/rules.mk @@ -0,0 +1,7 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +PLATFORM := qemu-virt-riscv + +MEMSIZE ?= 0x01000000 # 16MB