add riscv32-nemu

This commit is contained in:
Zihao Yu 2019-01-30 17:44:56 +08:00
parent c9544eab37
commit 0f0b9b9f42
14 changed files with 315 additions and 0 deletions

View File

@ -7,6 +7,10 @@ ifeq ($(ISA), mips32)
CROSS_COMPILE = mips-linux-gnu-
endif
ifeq ($(ISA), riscv32)
CROSS_COMPILE = riscv-none-embed-
endif
ifeq ($(PLATFORM), navy)
NAVY_LIBS = libndl libos libc
INC_DIR += $(addsuffix /include/, $(addprefix $(NAVY_HOME)/libs/, $(NAVY_LIBS)))
@ -45,6 +49,11 @@ CFLAGS_COMMON += -m32 -fno-pic -fno-omit-frame-pointer -march=i386 -mstringop-st
ASFLAGS += -m32
endif
ifeq ($(ISA), riscv32)
CFLAGS_COMMON += -fno-pic -static -march=rv32im -mabi=ilp32
ASFLAGS += -march=rv32im -mabi=ilp32 -O0 -fno-pic
endif
ifeq ($(ISA), am_native)
CFLAGS_COMMON += -fno-omit-frame-pointer -fno-reorder-functions
endif

View File

@ -0,0 +1 @@
# RISCV32-NEMU

View File

@ -0,0 +1,4 @@
start.o: start.S
riscv-none-embed-gcc -I$(AM_HOME)/am/arch/riscv32-nemu/include -march=rv32im -mabi=ilp32 -fno-pic -MMD -c start.S -o start.o
-include start.d

View File

@ -0,0 +1,7 @@
.globl _start
.type _start, function
_start:
mv s0, zero
la sp, _stack_pointer
jal _trm_init

13
am/arch/riscv32-nemu/img/build Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
DIR=${AM_HOME}/am/arch/riscv32-nemu/img
DEST=$1
shift
CROSS_COMPILE=riscv-none-embed-
make -C $DIR/boot -s
${CROSS_COMPILE}ld --gc-sections -melf32lriscv -T $DIR/loader.ld -e _start -o $DEST $DIR/boot/start.o --start-group $@ --end-group
${CROSS_COMPILE}objdump -d $DEST > $DEST.txt
${CROSS_COMPILE}objcopy -S --set-section-flags .bss=alloc,contents -O binary $DEST $DEST.bin

View File

@ -0,0 +1,29 @@
SECTIONS {
. = 0x80100000;
.text : {
*(.text)
}
etext = .;
_etext = .;
.rodata : {
*(.rodata*)
}
.data : {
*(.data)
}
edata = .;
_data = .;
.bss : {
_bss_start = .;
*(.bss*)
*(.sbss*)
*(.scommon)
}
_stack_top = ALIGN(4096);
. = _stack_top + 0x8000;
_stack_pointer = .;
end = .;
_end = .;
_heap_start = ALIGN(4096);
_heap_end = 0x88000000;
}

3
am/arch/riscv32-nemu/img/run Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
make -C $NEMU_HOME ISA=riscv32 run ARGS="-b -l `dirname $1`/nemu-log.txt $1.bin"

View File

@ -0,0 +1,27 @@
#ifndef __ARCH_H__
#define __ARCH_H__
#include <am.h>
#define PMEM_SIZE (128 * 1024 * 1024)
#define PGSIZE 4096
struct _Context {
struct _Protect *prot;
uint32_t gpr[31];
};
#define GPR1 //gpr[3]
#define GPR2 //gpr[4]
#define GPR3 //gpr[5]
#define GPR4 //gpr[6]
#define GPRx //gpr[1]
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,44 @@
#ifndef __RISCV32_H__
#define __RISCV32_H__
#ifndef __ASSEMBLER__
#include <arch.h>
#define MMIO_OFFSET(addr) (addr)
static inline uint8_t inb(uintptr_t addr) { return *(volatile uint8_t *)MMIO_OFFSET(addr); }
static inline uint16_t inw(uintptr_t addr) { return *(volatile uint16_t *)MMIO_OFFSET(addr); }
static inline uint32_t inl(uintptr_t addr) { return *(volatile uint32_t *)MMIO_OFFSET(addr); }
static inline void outb(uintptr_t addr, uint8_t data) { *(volatile uint8_t *)MMIO_OFFSET(addr) = data; }
static inline void outw(uintptr_t addr, uint16_t data) { *(volatile uint16_t *)MMIO_OFFSET(addr) = data; }
static inline void outl(uintptr_t addr, uint32_t data) { *(volatile uint32_t *)MMIO_OFFSET(addr) = data; }
#define PTE_V 0x2
#define PTE_D 0x4
// Page directory and page table constants
#define NR_PDE 1024 // # directory entries per page directory
#define NR_PTE 1024 // # PTEs per page table
#define PGSHFT 12 // log2(PGSIZE)
#define PTXSHFT 12 // Offset of PTX in a linear address
#define PDXSHFT 22 // Offset of PDX in a linear address
// +--------10------+-------10-------+---------12----------+
// | Page Directory | Page Table | Offset within Page |
// | Index | Index | |
// +----------------+----------------+---------------------+
// \--- PDX(va) --/ \--- PTX(va) --/\------ OFF(va) ------/
typedef uint32_t PTE;
typedef uint32_t PDE;
#define PDX(va) (((uint32_t)(va) >> PDXSHFT) & 0x3ff)
#define PTX(va) (((uint32_t)(va) >> PTXSHFT) & 0x3ff)
#define OFF(va) ((uint32_t)(va) & 0xfff)
// Address in page table or page directory entry
#define PTE_ADDR(pte) ((uint32_t)(pte) & ~0xfff)
#endif
#endif

View File

@ -0,0 +1,19 @@
#include <am.h>
#include <riscv32.h>
#include <amdev.h>
#define KBD_DATA_MMIO 0x4060
#define KEYDOWN_MASK 0x8000
size_t input_read(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_INPUT_KBD: {
_KbdReg *kbd = (_KbdReg *)buf;
int k = inl(KBD_DATA_MMIO);
kbd->keydown = (k & KEYDOWN_MASK ? 1 : 0);
kbd->keycode = k & ~KEYDOWN_MASK;
return sizeof(_KbdReg);
}
}
return 0;
}

View File

@ -0,0 +1,32 @@
#include <am.h>
#include <riscv32.h>
#include <amdev.h>
#define RTC_MMIO 0x4048 // Note that this is not standard
static unsigned long boot_time;
size_t timer_read(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_TIMER_UPTIME: {
_UptimeReg *uptime = (_UptimeReg *)buf;
uptime->hi = 0;
uptime->lo = inl(RTC_MMIO) - boot_time;
return sizeof(_UptimeReg);
}
case _DEVREG_TIMER_DATE: {
_RTCReg *rtc = (_RTCReg *)buf;
rtc->second = 0;
rtc->minute = 0;
rtc->hour = 0;
rtc->day = 0;
rtc->month = 0;
rtc->year = 2018;
return sizeof(_RTCReg);
}
}
return 0;
}
void timer_init() {
boot_time = inl(RTC_MMIO);
}

View File

@ -0,0 +1,52 @@
#include <am.h>
#include <riscv32.h>
#include <amdev.h>
#include <klib.h>
#define SCREEN_MMIO 0x4100
static int W, H;
static uint32_t* const fb = (uint32_t *)MMIO_OFFSET(0x40000);
size_t video_read(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_VIDEO_INFO: {
_VideoInfoReg *info = (_VideoInfoReg *)buf;
info->width = W;
info->height = H;
return sizeof(_VideoInfoReg);
}
}
return 0;
}
size_t video_write(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_VIDEO_FBCTL: {
_FBCtlReg *ctl = (_FBCtlReg *)buf;
int x = ctl->x, y = ctl->y, w = ctl->w, h = ctl->h;
uint32_t *pixels = ctl->pixels;
int len = sizeof(uint32_t) * ( (x + w >= W) ? W - x : w );
uint32_t *p_fb = &fb[y * W + x];
int j;
for (j = 0; j < h; j ++) {
if (y + j < H) { memcpy(p_fb, pixels, len); }
else { break; }
p_fb += W;
pixels += w;
}
if (ctl->sync) {
// do nothing, hardware syncs.
}
return size;
}
}
return 0;
}
void vga_init() {
uint32_t data = inl(SCREEN_MMIO);
W = data >> 16;
H = data & 0xffff;
}

View File

@ -0,0 +1,41 @@
#include <am.h>
#include <amdev.h>
#include <klib.h>
static inline size_t no_read(uintptr_t reg, void *buf, size_t size) {
assert(0);
return 0;
}
static inline size_t no_write(uintptr_t reg, void *buf, size_t size) {
assert(0);
return 0;
}
void vga_init();
void timer_init();
int _ioe_init() {
vga_init();
timer_init();
return 0;
}
size_t timer_read(uintptr_t reg, void *buf, size_t size);
size_t video_read(uintptr_t reg, void *buf, size_t size);
size_t video_write(uintptr_t reg, void *buf, size_t size);
size_t input_read(uintptr_t reg, void *buf, size_t size);
static _Device nemu_dev[] = {
{_DEV_TIMER, "NEMU Timer", timer_read, no_write},
{_DEV_INPUT, "NEMU Keyboard Controller", input_read, no_write},
{_DEV_VIDEO, "NEMU VGA Controller", video_read, video_write},
};
#define NR_DEV (sizeof(nemu_dev) / sizeof(nemu_dev[0]))
_Device *_device(int n) {
n --;
return (n >= 0 && (unsigned int)n < NR_DEV) ? &nemu_dev[n] : NULL;
}

View File

@ -0,0 +1,34 @@
#include <am.h>
#include <riscv32.h>
// Define this macro after serial has been implemented
#define HAS_SERIAL
#define SERIAL_PORT 0x43f8
extern char _heap_start;
extern char _heap_end;
extern int main();
_Area _heap = {
.start = &_heap_start,
.end = &_heap_end,
};
void _putc(char ch) {
#ifdef HAS_SERIAL
outb(SERIAL_PORT, ch);
#endif
}
void _halt(int code) {
__asm__ volatile("mv a0, %0; .word 0x0000006b" : :"r"(code));
// should not reach here
while (1);
}
void _trm_init() {
int ret = main();
_halt(ret);
}