Merge branch 'riscv32-emu' of https://git.njuics.cn/syslab17/nexus-am into riscv32-emu
This commit is contained in:
commit
7f81a68a9e
|
@ -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)__
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <am.h>
|
||||
#include <x86-nemu.h>
|
||||
#include <x86.h>
|
||||
|
||||
// Define this macro after serial has been implemented
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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]);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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(¤t->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);
|
||||
}
|
||||
|
|
|
@ -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(¤t->as);
|
||||
return current->tf;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue