Merge branch 'riscv32-emu' of https://git.njuics.cn/syslab17/nexus-am into riscv32-emu

This commit is contained in:
Allen 2017-08-06 11:26:55 +08:00
commit 7f81a68a9e
21 changed files with 240 additions and 214 deletions

View File

@ -20,6 +20,7 @@ CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
READELF = $(CROSS_COMPILE)readelf
ISA_DEF = __ISA_$(shell echo $(ISA) | tr a-z A-Z)__

View File

@ -17,26 +17,6 @@ struct _RegSet {
typedef struct _RegSet TrapFrame;
static inline uint8_t inb(int port) {
char data;
asm volatile("inb %1, %0" : "=a"(data) : "d"((uint16_t)port));
return data;
}
static inline uint32_t inl(int port) {
long data;
asm volatile("inl %1, %0" : "=a"(data) : "d"((uint16_t)port));
return data;
}
static inline void outb(int port, uint8_t data) {
asm volatile("outb %%al, %%dx" : : "a"(data), "d"((uint16_t)port));
}
static inline void outl(int port, uint32_t data) {
asm volatile("outl %%eax, %%dx" : : "a"(data), "d"((uint16_t)port));
}
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -48,14 +48,6 @@
// IDT size
#define NR_IRQ 256 // IDT size
// interrupts
#define T_IRQ0 32
#define IRQ_TIMER 0
#define IRQ_KBD 1
#define IRQ_SPURIOUS 31
#define IRQ_ERROR 19
// The following macros will not be seen by the assembler
#ifndef __ASSEMBLER__
@ -95,24 +87,6 @@ typedef struct GateDesc {
{ (uint32_t)(entry) & 0xffff, (cs), 0, 0, (type), 0, (dpl), \
1, (uint32_t)(entry) >> 16 }
static inline void cli() {
asm volatile("cli");
}
static inline void sti() {
asm volatile("sti");
}
static inline void hlt() {
asm volatile("hlt");
}
static inline uint32_t get_efl() {
volatile uint32_t efl;
asm volatile("pushf; pop %0": "=r"(efl));
return efl;
}
static inline uint32_t get_cr0(void) {
volatile uint32_t val;
asm volatile("movl %%cr0, %0" : "=r"(val));
@ -132,16 +106,29 @@ static inline void set_idt(GateDesc *idt, int size) {
asm volatile("lidt (%0)" : : "r"(data));
}
static inline uint32_t get_cr2() {
volatile uint32_t val;
asm volatile("movl %%cr2, %0" : "=r"(val));
return val;
}
static inline void set_cr3(void *pdir) {
asm volatile("movl %0, %%cr3" : : "r"(pdir));
}
static inline uint8_t inb(int port) {
char data;
asm volatile("inb %1, %0" : "=a"(data) : "d"((uint16_t)port));
return data;
}
static inline uint32_t inl(int port) {
long data;
asm volatile("inl %1, %0" : "=a"(data) : "d"((uint16_t)port));
return data;
}
static inline void outb(int port, uint8_t data) {
asm volatile("outb %%al, %%dx" : : "a"(data), "d"((uint16_t)port));
}
static inline void outl(int port, uint32_t data) {
asm volatile("outl %%eax, %%dx" : : "a"(data), "d"((uint16_t)port));
}
#endif

View File

@ -12,30 +12,33 @@ uintptr_t irq_handle(_RegSet *r) {
_RegSet *next = r;
if (H) {
_Event ev;
intptr_t args[4];
switch (r->irq) {
case 32: ev.event = _EVENT_IRQ_TIME; break;
case 0x80: {
ev.event = _EVENT_SYSCALL;
intptr_t args[4];
args[0] = r->eax;
args[1] = r->edx;
args[1] = r->ebx;
args[2] = r->ecx;
args[3] = r->ebx;
ev.cause = (intptr_t)&args;
args[3] = r->edx;
ev.cause = (intptr_t)args;
break;
}
case 0x81: ev.event = _EVENT_TRAP; break;
default: ev.event = _EVENT_ERROR; break;
}
r->esp = (uintptr_t)r;
r = H(ev, r);
if (r != NULL) {
next = H(ev, r);
if (ev.event == _EVENT_SYSCALL) {
r->eax = args[0];
}
if (next == NULL) {
next = r;
}
}
return next->esp;
return (uintptr_t)next;
}
static GateDesc idt[NR_IRQ];
@ -56,13 +59,12 @@ void _asye_init(_RegSet*(*h)(_Event, _RegSet*)) {
}
_RegSet *_make(_Area stack, void *entry, void *arg) {
// TODO: pass arg
stack.end -= 4 * sizeof(int); // 4 = retaddr + argc + argv + envp
_RegSet *r = (_RegSet*)stack.end - 1;
r->esp = (uintptr_t)r;
r->cs = 0x8;
r->eip = (uintptr_t)entry;
r->eflags = 0;
r->eflags = 0x2 | FL_IF;
return r;
}
@ -71,11 +73,5 @@ void _trap() {
}
int _istatus(int enable) {
int ret = (get_efl() & FL_IF) != 0;
if (enable) {
sti();
} else {
cli();
}
return ret;
return 0;
}

View File

@ -1,5 +1,4 @@
#include <am.h>
#include <x86-nemu.h>
#include <x86.h>
#define RTC_PORT 0x48 // Note that this is not standard
@ -9,22 +8,15 @@ void _ioe_init() {
boot_time = inl(RTC_PORT);
}
// -------------------- cycles and uptime --------------------
unsigned long _uptime() {
return inl(RTC_PORT) - boot_time;
//return 0;
}
// -------------------- video --------------------
uint32_t* const fb = (uint32_t *)0x40000;
#define SCREEN_W 320
#define SCREEN_H 200
_Screen _screen = {
.width = SCREEN_W,
.height = SCREEN_H,
.width = 400,
.height = 300,
};
extern void* memcpy(void *, const void *, int);
@ -47,10 +39,6 @@ void _draw_rect(const uint32_t *pixels, int x, int y, int w, int h) {
void _draw_sync() {
}
// -------------------- keyboard --------------------
#define KEYDOWN_MASK 0x8000
int _read_key() {
int status = inb(0x64);
if ((status & 0x1) == 0) return _KEY_NONE;

View File

@ -1,4 +1,3 @@
#include <x86-nemu.h>
#include <x86.h>
#define PG_ALIGN __attribute((aligned(PGSIZE)))
@ -9,7 +8,7 @@ void* (*palloc_f)();
void (*pfree_f)(void*);
_Area segments[] = { // Kernel memory mappings
{.start = (void*)0, .end = (void*)PMEM_SIZE}, // Low memory: kernel data
{.start = (void*)0, .end = (void*)PMEM_SIZE}
};
#define NR_KSEG_MAP (sizeof(segments) / sizeof(segments[0]))
@ -46,16 +45,11 @@ void _protect(_Protect *p) {
for (int i = 0; i < 1024; i ++)
updir[i] = kpdir[i];
// exact copy of kernel page table
// no user memory is mapped
p->area.start = (void*)0x8000000;
p->area.end = (void*)0xc0000000;
// return [ULOW, UHIGH)
}
void _release(_Protect *p) {
// free all spaces
}
void _switch(_Protect *p) {

View File

@ -1,5 +1,4 @@
#include <am.h>
#include <x86-nemu.h>
#include <x86.h>
// Define this macro after serial has been implemented

View File

@ -3,31 +3,25 @@ SRCS = $(shell find -L ./src/ -name "*.c" -o -name "*.cpp" -o -name "*.S")
LIBS = klib
include $(AM_HOME)/Makefile.app
NANOS_MAX_SIZE = 0 #1048576
FSIMG_PATH = $(NAVY_HOME)/fsimg
FSIMG_FILES = $(shell find $(FSIMG_PATH) -type f)
RAMDISK_FILE = build/ramdisk.img
.PHONY: fsimg update
.PHONY: update
fsimg:
update-fsimg:
$(MAKE) -C $(NAVY_HOME) ISA=$(ISA)
$(FSIMG_FILES): fsimg
#src/files.h: $(FSIMG_FILES)
# wc -c $(FSIMG_FILES) | grep -v 'total$$' | sed -e 's+ $(FSIMG_PATH)+ +' | awk -v sum=$(NANOS_MAX_SIZE) '{print "\x7b\x22" $$2 "\x22\x2c " $$1 "\x2c " sum "\x7d\x2c";sum += $$1}' > $@
src/initrd.S: $(RAMDISK_FILE)
touch $@
for f in $(FSIMG_FILES); do \
if $(READELF) -h $$f 2> /dev/null > /dev/null; then \
$(OBJCOPY) --set-section-flags .bss=alloc,contents -O binary $$f; \
fi \
done
src/syscall.h: $(NAVY_HOME)/libs/libos/src/syscall.h
ln -sf $^ $@
#$(RAMDISK_FILE): $(FSIMG_FILES)
# cat $^ > $@
$(RAMDISK_FILE): $(NAVY_HOME)/tests/hello/build/hello-x86
$(OBJCOPY) --set-section-flags .bss=alloc,contents -O binary $^ $@
update: src/initrd.S src/syscall.h
update: update-fsimg src/syscall.h
@cat $(FSIMG_FILES) > $(RAMDISK_FILE)
# $(OBJCOPY) --set-section-flags .bss=alloc,contents -O binary $(NAVY_HOME)/tests/hello/build/hello-x86 $(RAMDISK_FILE)
@touch src/initrd.S
@wc -c $(FSIMG_FILES) | grep -v 'total$$' | sed -e 's+ $(FSIMG_PATH)+ +' | awk -v sum=0 '{print "\x7b\x22" $$2 "\x22\x2c " $$1 "\x2c " sum "\x7d\x2c";sum += $$1}' > src/files.h

View File

@ -1,9 +1,6 @@
#ifndef __COMMON_H__
#define __COMMON_H__
/* Uncomment the following macro after paging is enabling. */
//#define __PAGE
#include <am.h>
#include <klib.h>
#include "debug.h"

View File

@ -11,4 +11,6 @@ ssize_t fs_write(int, const void *, size_t);
off_t fs_lseek(int, off_t, int);
int fs_close(int);
size_t fs_filesz(int);
#endif

View File

@ -7,6 +7,8 @@
#define PGSIZE 4096
#endif
#define PG_ALIGN __attribute((aligned(PGSIZE)))
#ifndef PMEM_SIZE
#define PMEM_SIZE (128 * 1024 * 1024)
#endif
@ -16,6 +18,5 @@
#define PGROUNDDOWN(a) (((a)) & ~PGMASK)
void* new_page(void);
void* kmalloc(uint32_t);
#endif

View File

@ -0,0 +1,22 @@
#ifndef __PROC_H__
#define __PROC_H__
#include "common.h"
#include "memory.h"
#define STACK_SIZE (128 * PGSIZE)
typedef union {
uint8_t stack[STACK_SIZE] PG_ALIGN;
struct {
_RegSet *tf;
_Protect as;
uintptr_t cur_brk;
// we do not free memory, so use `max_brk' to determine whether to call mm_malloc()
uintptr_t max_brk;
};
} PCB;
extern PCB *current;
#endif

View File

@ -0,0 +1,46 @@
#include "common.h"
#define NAME(key) \
[_KEY_##key] = #key,
const char *names[256] = {
[_KEY_NONE] = "NONE",
_KEYS(NAME)
};
static unsigned long last_time_ms = 0;
size_t read_events(void *buf) {
int key = _read_key();
char keydown_char = (key & 0x8000 ? 'd' : 'u');
key &= ~0x8000;
if (key != _KEY_NONE) {
if (key == _KEY_F12 && keydown_char == 'u') {
extern void change_game(void);
change_game();
}
return sprintf(buf, "k%c %s\n", keydown_char, names[key]) - 1;
}
else {
unsigned long time_ms;
while ( (time_ms = _uptime()) - last_time_ms < 33 );
last_time_ms = time_ms;
return sprintf(buf, "t %d\n", time_ms) - 1;
}
}
static char dispinfo[128];
void dispinfo_read(void *buf, off_t offset, size_t len) {
memcpy(buf, dispinfo + offset, len);
}
void fb_write(const void *buf, off_t offset, size_t len) {
offset /= sizeof(uint32_t);
_draw_rect(buf, offset % _screen.width, offset / _screen.width, len / sizeof(uint32_t), 1);
}
void init_device() {
_ioe_init();
sprintf(dispinfo, "WIDTH: %d\nHEIGHT: %d", _screen.width, _screen.height);
}

View File

@ -1,18 +0,0 @@
#include "common.h"
#define NAME(key) \
[_KEY_##key] = #key,
const char *names[256] = {
[_KEY_NONE] = "NONE",
_KEYS(NAME)
};
size_t read_events(void *buf) {
uint32_t time_ms = _uptime();
int key = _read_key();
char keydown_char = (key & 0x8000 ? 'd' : 'u');
key &= ~0x8000;
return sprintf(buf, "t %d\nk%c %s ", time_ms, keydown_char, names[key]);
}

View File

@ -7,28 +7,43 @@ typedef struct {
} file_info;
typedef struct {
bool used;
uint32_t index;
off_t offset;
} Fstate;
extern uint32_t* const fb;
/* This is the information about all files in disk. */
static const file_info file_table[] __attribute__((used)) = {
{"/dev/fb", 320 * 200 * sizeof(*fb), 0},
static file_info file_table[] __attribute__((used)) = {
{"/dev/fb", 0, 0},
{"/dev/events", 0, 0},
{"/proc/dispinfo", 128, 0},
#include "files.h"
};
#define NR_FILES (sizeof(file_table) / sizeof(file_table[0]))
enum {FD_STDIN, FD_STDOUT, FD_STDERR, FD_FB, FD_EVENTS, FD_NORMAL};
enum {FD_STDIN, FD_STDOUT, FD_STDERR, FD_FB, FD_EVENTS, FD_DISPINFO, FD_NORMAL};
Fstate files[FD_NORMAL + NR_FILES];
void init_fs() {
int i;
for (i = 0; i < NR_FILES; i ++) {
if (strcmp(file_table[i].name, "/dev/fb") == 0) {
file_table[i].size = _screen.width * _screen.height * sizeof(uint32_t);
return;
}
}
}
size_t fs_filesz(int fd) {
return file_table[ files[fd].index ].size;
}
void ramdisk_read(void *, uint32_t, uint32_t);
void ramdisk_write(const void *, uint32_t, uint32_t);
size_t read_events(void *buf);
void dispinfo_read(void *buf, off_t offset, size_t len);
void fb_write(const void *buf, off_t offset, size_t len);
int fs_open(const char *pathname, int flags, int mode) {
int i, fd;
@ -37,10 +52,9 @@ int fs_open(const char *pathname, int flags, int mode) {
switch (i) {
case 0: fd = FD_FB; break;
case 1: fd = FD_EVENTS; break;
case 2: fd = FD_DISPINFO; break;
default: fd = FD_NORMAL + i; break;
}
assert(files[fd].used == false);
files[fd].used = true;
files[fd].index = i;
files[fd].offset = 0;
return fd;
@ -60,7 +74,12 @@ ssize_t fs_read(int fd, void *buf, size_t len) {
int remain_bytes = file_table[ files[fd].index ].size - files[fd].offset;
int bytes_to_read = (remain_bytes > len ? len : remain_bytes);
ramdisk_read(buf, file_table[files[fd].index].disk_offset + files[fd].offset, bytes_to_read);
if (fd == FD_DISPINFO) {
dispinfo_read(buf, file_table[files[fd].index].disk_offset + files[fd].offset, bytes_to_read);
}
else {
ramdisk_read(buf, file_table[files[fd].index].disk_offset + files[fd].offset, bytes_to_read);
}
files[fd].offset += bytes_to_read;
return bytes_to_read;
}
@ -78,7 +97,7 @@ ssize_t fs_write(int fd, const void *buf, size_t len) {
return len;
case FD_FB:
memcpy((void *)fb + files[fd].offset, buf, bytes_to_write);
fb_write(buf, files[fd].offset, bytes_to_write);
break;
default:
@ -112,9 +131,5 @@ off_t fs_lseek(int fd, off_t offset, int whence) {
}
int fs_close(int fd) {
if(fd >= 0 && fd <= 2) return 0;
assert(files[fd].used == true);
files[fd].used = false;
return 0;
}

View File

@ -1,13 +1,14 @@
#include "common.h"
_RegSet* schedule(void);
void do_syscall(_RegSet *);
_RegSet* schedule(_RegSet *);
_RegSet* do_syscall(uintptr_t *);
static _RegSet* do_event(_Event e, _RegSet* r) {
_RegSet *ret = NULL;
switch (e.event) {
case _EVENT_TRAP: ret = schedule(); break;
case _EVENT_SYSCALL: do_syscall(r); break;
case _EVENT_IRQ_TIME: ret = schedule(r); break;
case _EVENT_TRAP: ret = schedule(r); break;
case _EVENT_SYSCALL: ret = do_syscall((uintptr_t *)e.cause); break;
default: panic("Unhandled event ID = %d", e.event);
}

View File

@ -2,18 +2,24 @@
#include "memory.h"
#include "fs.h"
#define INIT_FILE "/bin/pal"
void ramdisk_read(void *, off_t, size_t);
#define STACK_SIZE (128 * PGSIZE)
#define DEFAULT_ENTRY ((void *)0x8048000)
uintptr_t loader() {
Log("Loading user program %s...", INIT_FILE);
uintptr_t loader(_Protect *as, const char *filename) {
Log("Loading user program %s...", filename);
extern uint8_t ramdisk_start;
extern uint8_t ramdisk_end;
ramdisk_read((void *)0x4000000, 0, &ramdisk_end - &ramdisk_start);
int fd = fs_open(filename, 0, 0);
return 0x4000000;
size_t size = fs_filesz(fd);
size_t i;
for (i = 0; i < size; i += PGSIZE) {
void *pa = new_page();
_map(as, DEFAULT_ENTRY + i, pa);
fs_read(fd, pa, PGSIZE);
}
fs_close(fd);
return (uintptr_t)DEFAULT_ENTRY;
}

View File

@ -1,10 +1,14 @@
#include "common.h"
void init_mm(void);
void init_device(void);
void init_irq(void);
void load_first_prog(void);
void init_fs(void);
void load_prog(const char *);
int main() {
init_mm();
Log("'Hello World!' from Nanos-lite");
Log("Build time: %s, %s", __TIME__, __DATE__);
@ -13,12 +17,16 @@ int main() {
Log("ramdisk info: start = %p, end = %p, size = %d bytes",
&ramdisk_start, &ramdisk_end, &ramdisk_end - &ramdisk_start);
_ioe_init();
init_device();
Log("Initializing interrupt/exception handler...");
init_irq();
load_first_prog();
init_fs();
load_prog("/bin/pal");
load_prog("/bin/hello");
load_prog("/bin/litenes");
_trap();

View File

@ -1,10 +1,7 @@
#include "proc.h"
#include "memory.h"
static void *pf = NULL;
static _Protect user_as; // user process address space
_Protect* get_user_as(void) {
return &user_as;
}
void* new_page(void) {
assert(pf < (void *)PMEM_SIZE);
@ -17,37 +14,21 @@ void free_page(void *p) {
panic("not implement yet");
}
void* kmalloc(uint32_t size) {
assert(size > 0);
void *pa = new_page();
uint32_t alloc_size = PGSIZE;
for (; alloc_size < size; alloc_size += PGSIZE) {
new_page();
}
return pa;
}
static uintptr_t cur_brk = 0;
// we do not free memory, so use `max_brk' to determine whether to call mm_malloc()
static uintptr_t max_brk = 0;
/* The brk() system call handler. */
bool mm_brk(uint32_t new_brk) {
if(cur_brk == 0) {
cur_brk = max_brk = new_brk;
if(current->cur_brk == 0) {
current->cur_brk = current->max_brk = new_brk;
}
else {
if (new_brk > max_brk) {
uintptr_t page_start = PGROUNDUP(max_brk);
if (new_brk > current->max_brk) {
uintptr_t page_start = PGROUNDUP(current->max_brk);
uintptr_t page_end = PGROUNDUP(new_brk);
for (; page_start <= page_end; page_start += PGSIZE) {
_map(&user_as, (void *)page_start, new_page());
_map(&current->as, (void *)page_start, new_page());
}
max_brk = new_brk;
current->max_brk = new_brk;
}
cur_brk = new_brk;
current->cur_brk = new_brk;
}
// success
@ -55,9 +36,9 @@ bool mm_brk(uint32_t new_brk) {
}
void init_mm() {
_pte_init(new_page, free_page);
extern char _end;
pf = (void *)PGROUNDUP((uintptr_t)&_end);
Log("free physical pages starting from %p", pf);
_pte_init(new_page, free_page);
}

View File

@ -1,23 +1,48 @@
#include "common.h"
#include "proc.h"
#define NR_PROC 4
#define STACK_SIZE (128 * PGSIZE)
#define MAX_NR_PROC 4
_RegSet* pcb[NR_PROC];
PCB pcb[MAX_NR_PROC];
PCB *current = NULL;
int nr_proc = 0;
uintptr_t loader(void);
uintptr_t loader(_Protect *as, const char *filename);
void load_first_prog() {
uintptr_t entry = loader();
void load_prog(const char *filename) {
int i = nr_proc ++;
_protect(&pcb[i].as);
uintptr_t entry = loader(&pcb[i].as, filename);
_Area stack;
stack.end = _heap.end;
stack.start = stack.end - STACK_SIZE;
stack.start = pcb[i].stack;
stack.end = stack.start + sizeof(pcb[i].stack);
pcb[0] = _make(stack, (void *)entry, NULL);
pcb[i].tf = _make(stack, (void *)entry, NULL);
}
_RegSet* schedule() {
Log("schedule");
return pcb[0];
static int cnt = 0;
static PCB* game_pcb = &pcb[0];
void change_game() {
Log("game change!");
game_pcb = (game_pcb == &pcb[0] ? &pcb[2] : &pcb[0]);
}
_RegSet* schedule(_RegSet *prev) {
// when current == NULL at the very beginning, it will not cover
// any valid data, so it will be safe to write to memory near NULL
current->tf = prev;
if (current == game_pcb) {
cnt ++;
if (cnt == 200) {
current = &pcb[1];
cnt = 0;
}
}
else {
current = game_pcb;
}
_switch(&current->as);
return current->tf;
}

View File

@ -37,18 +37,19 @@ int sys_brk(uintptr_t brk) {
return mm_brk(brk);
}
void do_syscall(_RegSet *r) {
_RegSet* do_syscall(uintptr_t *args) {
int ret = 0;
switch (r->eax) {
case SYS_exit: sys_exit(r->ebx); break;
case SYS_read: ret = sys_read(r->ebx, (void *)r->ecx, r->edx); break;
case SYS_write: ret = sys_write(r->ebx, (const void *)r->ecx, r->edx); break;
case SYS_open: ret = sys_open((const char *)r->ebx, r->ecx, r->edx); break;
case SYS_lseek: ret = sys_lseek(r->ebx, r->ecx, r->edx); break;
case SYS_close: ret = sys_close(r->ebx); break;
case SYS_brk: ret = sys_brk(r->ebx); break;
default: panic("Unhandled syscall ID = %d, eip = 0x%08x", r->eax, r->eip);
switch (args[0]) {
case SYS_exit: sys_exit(args[1]); break;
case SYS_read: ret = sys_read(args[1], (void *)args[2], args[3]); break;
case SYS_write: ret = sys_write(args[1], (const void *)args[2], args[3]); break;
case SYS_open: ret = sys_open((const char *)args[1], args[2], args[3]); break;
case SYS_lseek: ret = sys_lseek(args[1], args[2], args[3]); break;
case SYS_close: ret = sys_close(args[1]); break;
case SYS_brk: ret = sys_brk(args[1]); break;
default: panic("Unhandled syscall ID = %d", args[0]);
}
r->eax = ret;
args[0] = ret;
return NULL;
}