[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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
107
arch/riscv/linker-onesegment.ld
Normal file
107
arch/riscv/linker-onesegment.ld
Normal file
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
24
platform/qemu-virt-riscv/include/platform/virt.h
Normal file
24
platform/qemu-virt-riscv/include/platform/virt.h
Normal file
@@ -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
|
||||
|
||||
28
platform/qemu-virt-riscv/platform.c
Normal file
28
platform/qemu-virt-riscv/platform.c
Normal file
@@ -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 <lk/reg.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform.h>
|
||||
#include <platform/interrupts.h>
|
||||
#include <platform/debug.h>
|
||||
#include <platform/timer.h>
|
||||
#include <platform/virt.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "platform_p.h"
|
||||
|
||||
void platform_early_init(void) {
|
||||
plic_early_init();
|
||||
}
|
||||
|
||||
void platform_init(void) {
|
||||
plic_init();
|
||||
uart_init();
|
||||
}
|
||||
|
||||
|
||||
17
platform/qemu-virt-riscv/platform_p.h
Normal file
17
platform/qemu-virt-riscv/platform_p.h
Normal file
@@ -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 <stdbool.h>
|
||||
|
||||
void uart_init(void);
|
||||
|
||||
void plic_early_init(void);
|
||||
void plic_init(void);
|
||||
|
||||
|
||||
94
platform/qemu-virt-riscv/plic.c
Normal file
94
platform/qemu-virt-riscv/plic.c
Normal file
@@ -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 <assert.h>
|
||||
#include <lk/err.h>
|
||||
#include <lk/debug.h>
|
||||
#include <lk/reg.h>
|
||||
#include <lk/trace.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform/interrupts.h>
|
||||
#include <platform/virt.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
26
platform/qemu-virt-riscv/rules.mk
Normal file
26
platform/qemu-virt-riscv/rules.mk
Normal file
@@ -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
|
||||
81
platform/qemu-virt-riscv/uart.c
Normal file
81
platform/qemu-virt-riscv/uart.c
Normal file
@@ -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 <lk/reg.h>
|
||||
#include <lk/trace.h>
|
||||
#include <lib/cbuf.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform.h>
|
||||
#include <platform/interrupts.h>
|
||||
#include <platform/debug.h>
|
||||
#include <platform/virt.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <lk/debug.h>
|
||||
#include <lk/reg.h>
|
||||
#include <lk/trace.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform/interrupts.h>
|
||||
#include <platform/sifive.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
10
project/qemu-virt-riscv32-test.mk
Normal file
10
project/qemu-virt-riscv32-test.mk
Normal file
@@ -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
|
||||
|
||||
2
project/target/qemu-virt-riscv.mk
Normal file
2
project/target/qemu-virt-riscv.mk
Normal file
@@ -0,0 +1,2 @@
|
||||
TARGET := qemu-virt-riscv
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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 <memory in MB>"
|
||||
echo "-s <number of cpus>"
|
||||
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 $@
|
||||
|
||||
7
target/qemu-virt-riscv/rules.mk
Normal file
7
target/qemu-virt-riscv/rules.mk
Normal file
@@ -0,0 +1,7 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
PLATFORM := qemu-virt-riscv
|
||||
|
||||
MEMSIZE ?= 0x01000000 # 16MB
|
||||
Reference in New Issue
Block a user