diff --git a/laos/Makefile b/laos/Makefile index 542cdf4..a783c06 100644 --- a/laos/Makefile +++ b/laos/Makefile @@ -19,14 +19,15 @@ BIN := neula-os BINARY := $(BUILD_DIR)/$(BIN) TOP_SRC_DIR := src -SOURCE_DIRS := $(shell ls $(TOP_SRC_DIR)/* -d) +MODULES := kernel util +SOURCE_DIRS := $(addprefix $(TOP_SRC_DIR)/,$(MODULES)) MK_DIRS := $(addprefix MAKE/,$(SOURCE_DIRS)) ALL_SRCS := $(shell find . -name '*.c') LD_CSRIPT := kernel.ld EXTRA_MACRO := # NDEBUG -EXTRA_FLAGS = -Wall -Werror -O -fno-omit-frame-pointer -ggdb -gdwarf-2 +EXTRA_FLAGS = -Wall -Werror -O0 -fno-omit-frame-pointer -ggdb -gdwarf-2 EXTRA_FLAGS += -MD EXTRA_FLAGS += -ffreestanding -fno-common -nostdlib EXTRA_FLAGS += -I. @@ -57,4 +58,15 @@ build: $(MK_DIRS) @$(OC) $(BINARY) -O binary $(BINARY).bin clean: - rm -rf $(BUILD_DIR) \ No newline at end of file + rm -rf $(BUILD_DIR) + + +# use native + +clean-usr: + rm -rf $(BUILD_DIR)/user + +usr: + @TOP_BUILD_DIR=$(ABS_BUILD) \ + CPPFLAGS="$(CPPFLAGS)" \ + $(MAKE) native -C $(TOP_SRC_DIR)/user -j$(NPROC) diff --git a/laos/include/asm.h b/laos/include/asm.h index b188ff2..99b445f 100644 --- a/laos/include/asm.h +++ b/laos/include/asm.h @@ -3,6 +3,36 @@ #ifndef ASM_H__ #define ASM_H__ -#define CPUID 0x020 +// CSR infos +#define CRMD 0x000 /* 当前模式信息 */ +#define PRMD 0x001 /* 例外前模式信息 */ +#define EUEN 0x002 /* 拓展部件使能 */ +#define ECFG 0x004 /* 例外配置 */ +#define ESTAT 0x005 /* 例外状态 */ +#define ERA 0x006 /* 例外返回地址 */ +#define BADV 0x007 /* 出错虚地址 */ +#define EENTRY 0x00c /* 例外地址入口 */ +#define TLBIDX 0x010 /* TLB 索引 */ +#define TLBEHI 0x011 /* TLB 表项高位 */ +#define TLBELO0 0x012 /* TLB 表项低位 0 */ +#define TLBELO1 0x013 /* TLB 表项低位 1 */ +#define ASID 0x018 /* 地址空间标识符 */ +#define PGDL 0x019 /* 低半地址空间全局目录基址 */ +#define PGDH 0x01a /* 高半地址空间全局目录基址 */ +#define PGD 0x01b /* 全局目录基址 */ +#define CPUID 0x020 /* 处理器编号 */ +#define SAVE0 0x030 /* 数据保存 0*/ +#define SAVE1 0x031 /* 数据保存 1*/ +#define SAVE2 0x032 /* 数据保存 2 */ +#define SAVE3 0x033 /* 数据保存 3 */ +#define TID 0x040 /* 定时器编号 */ +#define TCFG 0x041 /* 定时器配置 */ +#define TVAL 0x042 /* 定时器值 */ +#define TICLR 0x044 /* 定时中断清除 */ +#define LLBCTL 0x060 /* LLBit 控制 */ +#define TLBRENTRY 0x088 /* TLB 重填例外入口 */ +#define CTAG 0x098 /* 高速缓存标签 */ +#define DMW0 0x180 /* 直接映射配置窗口 0 */ +#define DMW1 0x181 /* 直接映射配置窗口 1 */ #endif \ No newline at end of file diff --git a/laos/include/console.h b/laos/include/console.h new file mode 100644 index 0000000..3d140fe --- /dev/null +++ b/laos/include/console.h @@ -0,0 +1,6 @@ +#ifndef CONSOLE_H__ +#define CONSOLE_H__ + +void consputc(int c); + +#endif \ No newline at end of file diff --git a/laos/include/defs.h b/laos/include/defs.h index d87766b..5784ef3 100644 --- a/laos/include/defs.h +++ b/laos/include/defs.h @@ -1,6 +1,14 @@ #ifndef DEFS_H__ #define DEFS_H__ +#define NULL ((void *)0) + #define NCPU 1 +#define NPROC 64 +#define NOFILE 16 + + +#define SERIAL_TX_BUF_SIZE 32 + #endif \ No newline at end of file diff --git a/laos/include/fcntl.h b/laos/include/fcntl.h new file mode 100644 index 0000000..df88ec1 --- /dev/null +++ b/laos/include/fcntl.h @@ -0,0 +1,10 @@ +#ifndef FCNTL_H__ +#define FCNTL_H__ + +#define O_RDONLY 0x000 +#define O_WRONLY 0x001 +#define O_RDWR 0x002 +#define O_CREATE 0x200 +#define O_TRUNC 0x400 + +#endif \ No newline at end of file diff --git a/laos/include/filesys.h b/laos/include/filesys.h new file mode 100644 index 0000000..e69de29 diff --git a/laos/include/common.h b/laos/include/kernel.h similarity index 63% rename from laos/include/common.h rename to laos/include/kernel.h index 9749f1a..1ec981e 100644 --- a/laos/include/common.h +++ b/laos/include/kernel.h @@ -1,10 +1,11 @@ #include "defs.h" -#ifndef COMMON_H__ -#define COMMON_H__ +#ifndef KERNEL_H__ +#define KERNEL_H__ -void main(); -void start(); void _entry() __attribute__ ((section (".entry"))); -#endif // COMMON_H__ \ No newline at end of file +void start(); +void main(); + +#endif \ No newline at end of file diff --git a/laos/include/kprintf.h b/laos/include/kprintf.h new file mode 100644 index 0000000..aa46385 --- /dev/null +++ b/laos/include/kprintf.h @@ -0,0 +1,8 @@ +#ifndef KPRINTF_H__ +#define KPRINTF_H__ + + +void kprintf(char *fmt, ...); +void panic(char *s); + +#endif \ No newline at end of file diff --git a/laos/include/la32r.h b/laos/include/la32r.h index e69de29..5c06a6d 100644 --- a/laos/include/la32r.h +++ b/laos/include/la32r.h @@ -0,0 +1,104 @@ +#include "asm.h" +#include "defs.h" +#include "latype.h" +#include "macro.h" + +#ifndef LA32R_H__ +#define LA32R_H__ + +static inline uint r_crmd() { + uint recv; + asm volatile ("csrrd %0, " TOSTRING(CRMD) : "=r" (recv)); + return recv; +} + +static inline void w_crmd(uint wdata) { + asm volatile ("csrwr %0, " TOSTRING(CRMD) : "=r" (wdata)); +} + +static inline void w_eentry(uint wdata) { + asm volatile ("csrwr %0, " TOSTRING(EENTRY) : "=r" (wdata)); +} + +static inline uint r_cpuid() { + uint recv; + asm volatile ("csrrd %0, " TOSTRING(CPUID) : "=r" (recv)); + return recv; +} + +// +// specified register io +// + +static inline uint r_sp() { + uint recv; + asm volatile ("add.w %0, $sp, $zero" : "=r" (recv)); + return recv; +} + +static inline uint r_tp() { + uint recv; + asm volatile ("add.w %0, $tp, $zero" : "=r" (recv)); + return recv; +} + +static inline void w_tp(uint wdata) { + asm volatile("add.w $tp, %0, $zero" : : "r" (wdata)); +} + +static inline uint r_ra() { + uint recv; + asm volatile ("add.w %0, $ra, $zero" : "=r" (recv)); + return recv; +} + +// +// mem misc +// + +static inline void dbar() { + asm volatile("dbar 0"); +} + +static inline void ibar() { + asm volatile("ibar 0"); +} + +// need to be tested +static inline void synchronize() { + dbar(); + ibar(); +} + + +// +// tlb misc +// + +// +// cache misc +// + + +// +// atomic +// + +static inline uint llw(intptr_t addr) { + uint recv; + asm volatile ("ll.w %0, %1, 0": "=r" (recv) : "r" (addr)); + return recv; +} + +static inline uint scw(uint wdata, intptr_t addr) { + uint recv; + asm volatile ( + "add.w %0, %1, $zero" "\n\t" + "sc.w %0, %2, 0" + : "=r" (recv) + : "r" (wdata), + "r" (addr)); + return recv; +} + +#endif \ No newline at end of file diff --git a/laos/include/latype.h b/laos/include/latype.h new file mode 100644 index 0000000..c996a35 --- /dev/null +++ b/laos/include/latype.h @@ -0,0 +1,22 @@ +#ifndef LATYPE_H__ +#define LATYPE_H__ + +typedef char i8; +typedef unsigned char u8; +typedef unsigned char uchar; + +typedef short i16; +typedef unsigned short u16; +typedef unsigned short ushort; + +typedef int i32; +typedef unsigned int u32; +typedef unsigned int uint; + +typedef unsigned int size_t; +typedef unsigned int intptr_t; + +typedef u32 pte_t; +typedef u32 *pagetable_t; + +#endif \ No newline at end of file diff --git a/laos/include/macro.h b/laos/include/macro.h new file mode 100644 index 0000000..aba4a9a --- /dev/null +++ b/laos/include/macro.h @@ -0,0 +1,7 @@ +#ifndef MACRO_H__ +#define MACRO_H__ + +#define TOSTRING_(x) #x +#define TOSTRING(x) TOSTRING_(x) + +#endif \ No newline at end of file diff --git a/laos/include/memio.h b/laos/include/memio.h new file mode 100644 index 0000000..543342c --- /dev/null +++ b/laos/include/memio.h @@ -0,0 +1,11 @@ +#include "latype.h" + + +#ifndef MEMIO_H__ +#define MEMIO_H__ + +#define memb(addr) (*(u8 *)(addr)) +#define memh(addr) (*(u16 *)(addr)) +#define memw(addr) (*(u32 *)(addr)) + +#endif \ No newline at end of file diff --git a/laos/include/memlayout.h b/laos/include/memlayout.h new file mode 100644 index 0000000..214a31d --- /dev/null +++ b/laos/include/memlayout.h @@ -0,0 +1,9 @@ +#ifndef MEMLAYOUT_H__ +#define MEMLAYOUT_H__ + +#define DEV_BASE_ADDR 0xa0000000 + + +#define SERIAL_ADDR (DEV_BASE_ADDR + 0x00000000) + +#endif \ No newline at end of file diff --git a/laos/include/proc.h b/laos/include/proc.h new file mode 100644 index 0000000..b3f496f --- /dev/null +++ b/laos/include/proc.h @@ -0,0 +1,117 @@ +#include "latype.h" +#include "defs.h" +#include "spinlock.h" + +#ifndef PROC_H__ +#define PROC_H__ + +// Saved registers for kernel context switches. +struct context { + u32 ra; + u32 sp; + + // callee-saved + u32 s0; + u32 s1; + u32 s2; + u32 s3; + u32 s4; + u32 s5; + u32 s6; + u32 s7; + u32 s8; + u32 s9; +}; + +// Per-CPU state. +struct cpu { + struct proc *proc; // The process running on this cpu, or null. + struct context context; // swtch() here to enter scheduler(). + int noff; // Depth of push_off() nesting. + int intena; // Were interrupts enabled before push_off()? +}; + +extern struct cpu cpus[NCPU]; + + +// per-process data for the trap handling code in trampoline.S. +// sits in a page by itself just under the trampoline page in the +// user page table. not specially mapped in the kernel page table. +// uservec in trampoline.S saves user registers in the trapframe, +// then initializes registers from the trapframe's +// kernel_sp, kernel_hartid, kernel_satp, and jumps to kernel_trap. +// usertrapret() and userret in trampoline.S set up +// the trapframe's kernel_*, restore user registers from the +// trapframe, switch to the user page table, and enter user space. +// the trapframe includes callee-saved user registers like s0-s11 because the +// return-to-user path via usertrapret() doesn't return through +// the entire kernel call stack. +struct trapframe { + /* 0 */ u32 kernel_satp; // kernel page table + /* 4 */ u32 kernel_sp; // top of process's kernel stack + /* 8 */ u32 kernel_trap; // usertrap() + /* 12 */ u32 eenrty; // saved user program counter + /* 16 */ u32 kernel_hartid; // saved kernel tp + /* 20 */ u32 ra; + /* 24 */ u32 tp; + /* 28 */ u32 sp; + /* 32 */ u32 a0; + /* 36 */ u32 a1; + /* 40 */ u32 a2; + /* 44 */ u32 a3; + /* 48 */ u32 a4; + /* 52 */ u32 a5; + /* 56 */ u32 a6; + /* 60 */ u32 a7; + /* 64 */ u32 t0; + /* 68 */ u32 t1; + /* 72 */ u32 t2; + /* 76 */ u32 t3; + /* 80 */ u32 t4; + /* 84 */ u32 t5; + /* 88 */ u32 t6; + /* 92 */ u32 t7; + /* 96 */ u32 t8; + /* 100 */ u32 r21; + /* 104 */ u32 s9; + /* 108 */ u32 s0; + /* 112 */ u32 s1; + /* 116 */ u32 s2; + /* 120 */ u32 s3; + /* 124 */ u32 s4; + /* 128 */ u32 s5; + /* 132 */ u32 s6; + /* 136 */ u32 s7; + /* 140 */ u32 s8; +}; + +enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; + +// Per-process state +struct proc { + struct spinlock lock; + + // p->lock must be held when using these: + enum procstate state; // Process state + void *chan; // If non-zero, sleeping on chan + int killed; // If non-zero, have been killed + int xstate; // Exit status to be returned to parent's wait + int pid; // Process ID + + // wait_lock must be held when using this: + struct proc *parent; // Parent process + + // these are private to the process, so p->lock need not be held. + u32 kstack; // Virtual address of kernel stack + u32 sz; // Size of process memory (bytes) + pagetable_t pagetable; // User page table + struct trapframe *trapframe; // data page for trampoline.S + struct context context; // swtch() here to run process + struct file *ofile[NOFILE]; // Open files + struct inode *cwd; // Current directory + char name[16]; // Process name (debugging) +}; + +struct cpu *mycpu(); + +#endif \ No newline at end of file diff --git a/laos/include/spinlock.h b/laos/include/spinlock.h new file mode 100644 index 0000000..193d19f --- /dev/null +++ b/laos/include/spinlock.h @@ -0,0 +1,23 @@ +#include "latype.h" + +#ifndef SPINLOCK_H__ +#define SPINLOCK_H__ + +struct spinlock { + uint locked; + + // debugging + char *name; + struct cpu *cpu; +}; + +void initlock(struct spinlock *lck, char *name); + +void acquire(struct spinlock *lck); +void release(struct spinlock *lck); + +int holding(struct spinlock *lck); +void push_off(); +void pop_off(); + +#endif \ No newline at end of file diff --git a/laos/include/string.h b/laos/include/string.h new file mode 100644 index 0000000..54a1dfd --- /dev/null +++ b/laos/include/string.h @@ -0,0 +1,16 @@ +#include "latype.h" + +#ifndef STRING_H__ +#define STRING_H__ + +void *memset (void *dst , int c, uint n); +int memcmp (const void *m1, const void *m2, uint n); +void *memmove (void *dst, const void *src, uint n); +void *memcpy (void *dst, const void *src, uint n); + +int strncmp (const char *p, const char *q, uint n); +char *strncpy (char *s, const char *t, int n); +char *strcpy_s(char *s, const char *t, int n); +int strlen (const char *s); + +#endif \ No newline at end of file diff --git a/laos/include/unistd.h b/laos/include/unistd.h new file mode 100644 index 0000000..effb9b2 --- /dev/null +++ b/laos/include/unistd.h @@ -0,0 +1,9 @@ +#ifndef UNISTD_H__ +#define UNISTD_H__ + +/* Standard file descriptors. */ +#define STDIN_FILENO 0 /* Standard input. */ +#define STDOUT_FILENO 1 /* Standard output. */ +#define STDERR_FILENO 2 /* Standard error output. */ + +#endif \ No newline at end of file diff --git a/laos/src/dev/Makefile b/laos/src/dev/Makefile new file mode 100644 index 0000000..c332099 --- /dev/null +++ b/laos/src/dev/Makefile @@ -0,0 +1,21 @@ +CURNAME := dev +BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME) + +CSRC := $(wildcard *.c) +OBJS := $(patsubst %.c,%.o,$(CSRC)) +BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS)) + +.PHONY: build all message + +all: message build + +$(BUILD_DIR): + @mkdir -p $(BUILD_DIR) + +$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR) + @$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) + +build: $(BUILD_OBJS) + +message: + @echo "building $(CURNAME)" \ No newline at end of file diff --git a/laos/src/dev/serial.c b/laos/src/dev/serial.c new file mode 100644 index 0000000..3e27f52 --- /dev/null +++ b/laos/src/dev/serial.c @@ -0,0 +1,31 @@ +#include "memlayout.h" +#include "latype.h" +#include "memio.h" +#include "defs.h" + +struct spinlock serial_tx_lock; +char serial_tx_buf[SERIAL_TX_BUF_SIZE]; + +u32 serial_tx_w; // write next to serial_tx_buf[serial_tx_w % SERIAL_TX_BUF_SIZE] +u32 serial_tx_r; // read next from serial_tx_buf[serial_tx_r % SERIAL_TX_BUF_SIZE] + + + +void serial_putc(int c) { + acquire(&serial_tx_lock); + + // if(panicked){ + // for(;;) + // ; + // } + + while(serial_tx_w == serial_tx_r + SERIAL_TX_BUF_SIZE){ + // buffer is full. + // wait for serialstart() to open up space in the buffer. + // sleep(&serial_tx_r, &serial_tx_lock); + } + serial_tx_buf[serial_tx_w % SERIAL_TX_BUF_SIZE] = c; + serial_tx_w += 1; + // serialstart(); + release(&serial_tx_lock); +} \ No newline at end of file diff --git a/laos/src/kernel/console.c b/laos/src/kernel/console.c new file mode 100644 index 0000000..85aadc4 --- /dev/null +++ b/laos/src/kernel/console.c @@ -0,0 +1,28 @@ +#include "console.h" +#include "memio.h" +#include "memlayout.h" +#include "spinlock.h" + +void consputc(int c) { + if (c == '\b') { + memb(SERIAL_ADDR) = '\b'; + memb(SERIAL_ADDR) = ' '; + memb(SERIAL_ADDR) = '\b'; + return; + } + + memb(SERIAL_ADDR) = c; +} + +struct { + struct spinlock lock; + + // input +#define INPUT_BUF_SIZE 128 + char buf[INPUT_BUF_SIZE]; + uint r; // Read index + uint w; // Write index + uint e; // Edit index +} cons; + + diff --git a/laos/src/kernel/entry.S b/laos/src/kernel/entry.S index 268c030..0b73253 100644 --- a/laos/src/kernel/entry.S +++ b/laos/src/kernel/entry.S @@ -8,13 +8,13 @@ _entry: # with a 4096-byte stack per CPU. # sp = stack0 + (hartid * 4096) la.global $sp, stack0 - lu12i.w $a0, (1024*4 >> 12) & 0xfffff - addi.w $a0, $a0, 1024*4 & 0xfff - csrrd $a1, CPUID - addi.w $a1, $a1, 1 - mul.w $a0, $a0, $a1 - add.w $sp, $sp, $a0 + lu12i.w $a0, (1024*4 >> 12) & 0xfffff + addi.w $a0, $a0, 1024*4 & 0xfff + csrrd $a1, CPUID + addi.w $a1, $a1, 1 + mul.w $a0, $a0, $a1 + add.w $sp, $sp, $a0 # jump to start() in start.c - bl start + bl start spin: b spin \ No newline at end of file diff --git a/laos/src/kernel/kprintf.c b/laos/src/kernel/kprintf.c new file mode 100644 index 0000000..a78fad5 --- /dev/null +++ b/laos/src/kernel/kprintf.c @@ -0,0 +1,116 @@ +#include + +#include "latype.h" +#include "console.h" +#include "kprintf.h" +#include "spinlock.h" + +volatile int panicked = 0; + +// lock to avoid interleaving concurrent printf's. +static struct { + struct spinlock lock; + int locking; +} pr; + +static char digits[] = "0123456789abcdef"; + +static void print_int(int xx, int base, int sign) { + char buf[32]; + int i; + uint x; + if (sign && (sign = xx < 0)) { + x = -xx; + } else { + x = xx; + } + + i = 0; + do { + buf[i++] = digits[x % base]; + } while ((x /= base) != 0); + + if(sign) { + buf[i++] = '-'; + } + + while(--i >= 0) + consputc(buf[i]); +} + +static void print_ptr(intptr_t x) { + consputc('0'); + consputc('x'); + for (int i = 0; i < (sizeof(intptr_t) * 2); i++, x <<= 4) + consputc(digits[x >> (sizeof(intptr_t) * 8 - 4)]); +} + +void kprintf(char *fmt, ...) { + va_list ap; + int i, c, locking; + char *s; + + locking = pr.locking; + if(locking) + acquire(&pr.lock); + + if (fmt == 0) + panic("null fmt"); + + va_start(ap, fmt); + for (i = 0; (c = fmt[i] & 0xff) != 0; i++) { + if (c != '%') { + consputc(c); + continue; + } + c = fmt[++i] & 0xff; + if (c == 0) { + break; + } + + switch (c) { + case 'd': + print_int(va_arg(ap, int), 10, 1); + break; + case 'x': + print_int(va_arg(ap, int), 16, 1); + break; + case 'p': + print_ptr(va_arg(ap, intptr_t)); + break; + case 's': + if((s = va_arg(ap, char*)) == 0) + s = "(null)"; + for(; *s; s++) + consputc(*s); + break; + case '%': + consputc('%'); + break; + default: + // Print unknown % sequence to draw attention. + consputc('%'); + consputc(c); + break; + } + } + va_end(ap); + + if(locking) + release(&pr.lock); +} + +void panic(char *s) { + pr.locking = 0; + kprintf("panic: "); + kprintf(s); + kprintf("\n"); + panicked = 1; // freeze serial output from other CPUs + for(;;) + ; +} + +void kprintf_init(void) { + initlock(&pr.lock, "pr"); + pr.locking = 1; +} \ No newline at end of file diff --git a/laos/src/kernel/main.c b/laos/src/kernel/main.c index 52794b1..bfd4b9a 100644 --- a/laos/src/kernel/main.c +++ b/laos/src/kernel/main.c @@ -1,3 +1,25 @@ +#include "la32r.h" +#include "spinlock.h" + + +volatile static int started = 0; + void main() { + struct spinlock lck[1]; + initlock(lck, "main"); + acquire(lck); + + if (r_cpuid() == 0) { + + + synchronize(); + started = 1; + } else { + // 当前假定只有一个 hart + while (started == 0) + ; + synchronize(); + } + } \ No newline at end of file diff --git a/laos/src/kernel/proc.c b/laos/src/kernel/proc.c new file mode 100644 index 0000000..be8cd1d --- /dev/null +++ b/laos/src/kernel/proc.c @@ -0,0 +1,24 @@ +#include "proc.h" +#include "la32r.h" +#include "latype.h" + +struct cpu cpus[NCPU]; + +struct proc proc[NPROC]; + +struct proc *initproc; + +int nextpid = 1; +struct spinlock pid_lock; + +// helps ensure that wakeups of wait()ing +// parents are not lost. helps obey the +// memory model when using p->parent. +// must be acquired before any p->lock. +struct spinlock wait_lock; + +struct cpu *mycpu() { + int id = r_cpuid(); + struct cpu *c = &cpus[id]; + return c; +} \ No newline at end of file diff --git a/laos/src/kernel/spinlock.c b/laos/src/kernel/spinlock.c new file mode 100644 index 0000000..c378221 --- /dev/null +++ b/laos/src/kernel/spinlock.c @@ -0,0 +1,54 @@ +#include "spinlock.h" +#include "la32r.h" +#include "defs.h" +#include "kprintf.h" +#include "proc.h" + +void initlock(struct spinlock *lck, char *name) { + lck->name = name; + lck->locked = 0; + lck->cpu = 0; +} + +void acquire(struct spinlock *lck) { + + if(holding(lck)) { + panic("acquire"); + } + + + do { + // 如果已经上锁了,就等待 + while (llw((intptr_t)&lck->locked) == 1) + ; + // 此时没有上锁,那就开始抢锁 + // 没有抢成功就进入新的循环 + } while (scw(1, (intptr_t)&lck->locked) != 1); + + synchronize(); + lck->cpu = mycpu(); +} + +void release(struct spinlock *lck) { + if (holding(lck) != 1) { + panic("release"); + } + + lck->cpu = NULL; + + synchronize(); + + do { + // 标记上 + llw((intptr_t)&lck->locked); + + // 此时没有 hart 动,那就安全的释放 + // 否则重新循环 + } while (scw(0, (intptr_t)&lck->locked) != 1); +} + +int holding(struct spinlock *lck) { + int r; + r = (lck->locked && lck->cpu == mycpu()); + return r; +} \ No newline at end of file diff --git a/laos/src/kernel/start.c b/laos/src/kernel/start.c index 544d556..d699197 100644 --- a/laos/src/kernel/start.c +++ b/laos/src/kernel/start.c @@ -1,7 +1,20 @@ -#include "common.h" +#include "kernel.h" +#include "la32r.h" __attribute__ ((aligned (16))) char stack0[4096 * NCPU]; void start() { + // 设置特权等级 + volatile u32 crmd_info = r_crmd(); + crmd_info = crmd_info & 0xfffffffc; + w_crmd(crmd_info); + // ERTN 返回地址 + w_eentry((intptr_t)main); + + // 设置 tp + int id = r_cpuid(); + w_tp(id); + + asm volatile("ertn"); } \ No newline at end of file diff --git a/laos/src/lib/Makefile b/laos/src/lib/Makefile new file mode 100644 index 0000000..2bd2ce9 --- /dev/null +++ b/laos/src/lib/Makefile @@ -0,0 +1,21 @@ +CURNAME := lib +BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME) + +CSRC := $(wildcard *.c) +OBJS := $(patsubst %.c,%.o,$(CSRC)) +BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS)) + +.PHONY: build all message + +all: message build + +$(BUILD_DIR): + @mkdir -p $(BUILD_DIR) + +$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR) + @$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) + +build: $(BUILD_OBJS) + +message: + @echo "building $(CURNAME)" \ No newline at end of file diff --git a/laos/src/lib/path.c b/laos/src/lib/path.c new file mode 100644 index 0000000..e69de29 diff --git a/laos/src/user/Makefile b/laos/src/user/Makefile new file mode 100644 index 0000000..4ac8724 --- /dev/null +++ b/laos/src/user/Makefile @@ -0,0 +1,29 @@ +CURNAME := user +BUILD_DIR := $(TOP_BUILD_DIR)/$(CURNAME) + +CSRC := $(wildcard *.c) +OBJS := $(patsubst %.c,%.o,$(CSRC)) +BUILD_OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS)) +BASENAMES := $(basename $(CSRC)) +BUILD_EXE := $(addprefix $(BUILD_DIR)/,$(BASENAMES)) + +.PHONY: build all message + +all: message build + +$(BUILD_DIR): + @mkdir -p $(BUILD_DIR) + +$(BUILD_OBJS): $(BUILD_DIR)/%.o:%.c $(BUILD_DIR) + @$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) + +$(BUILD_EXE): %:%.o + @$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) + +build: $(BUILD_EXE) + +message: + @echo "building $(CURNAME)" + +native: $(BUILD_EXE) + @echo $(BASENAMES) diff --git a/laos/src/user/echo.c b/laos/src/user/echo.c new file mode 100644 index 0000000..974152b --- /dev/null +++ b/laos/src/user/echo.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + for (int i = 1; i < argc; i++) { + write(STDOUT_FILENO, argv[i], strlen(argv[i])); + if(i + 1 < argc){ + write(STDOUT_FILENO, " ", 1); + } else { + write(STDOUT_FILENO, "\n", 1); + } + } + exit(0); +} \ No newline at end of file diff --git a/laos/src/user/shell.c b/laos/src/user/shell.c new file mode 100644 index 0000000..e69de29 diff --git a/laos/src/user/xargs.c b/laos/src/user/xargs.c new file mode 100644 index 0000000..dec1b45 --- /dev/null +++ b/laos/src/user/xargs.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include + +void remove_tail_newline(char *str, int len) { + if (len == 0) { + return; + } + if (str[len - 1] == '\n') { + str[len - 1] = '\0'; + } +} + +int main(int argc, char *argv[]) { + if (argc < 1) { + exit(EXIT_FAILURE); + } + + char **args = malloc(argc * sizeof(char *)); + memcpy(args, &argv[1], (argc - 1) * sizeof(char *)); + argc -= 1; + + const char *filename = argv[1]; + char input[128]; + read(STDIN_FILENO, input, 128); + remove_tail_newline(input, strlen(input)); + + char *tok = strtok(input, " "); + while (tok) { + if (*tok != '\n') { + args = realloc(args, (argc + 1) * sizeof(char *)); + args[argc] = tok; + argc += 1; + } + tok = strtok(NULL, " "); + } + + if (fork() == 0) { + execvp(filename, args); + exit(EXIT_FAILURE); + } + + wait(NULL); + free(args); + + return 0; +} \ No newline at end of file diff --git a/laos/src/util/memops.c b/laos/src/util/memops.c deleted file mode 100644 index 9f55920..0000000 --- a/laos/src/util/memops.c +++ /dev/null @@ -1 +0,0 @@ -#include \ No newline at end of file diff --git a/laos/src/util/string.c b/laos/src/util/string.c new file mode 100644 index 0000000..c758f27 --- /dev/null +++ b/laos/src/util/string.c @@ -0,0 +1,93 @@ +#include "string.h" +#include "latype.h" + +// mem ops could be more better +// use loop unrolling + +void *memset(void *dst, int c, uint n) { + char *cdst = (char *) dst; + for (uint i = 0; i < n; ++i) { + cdst[i] = c; + } + return dst; +} + +int memcmp(const void *m1, const void *m2, uint n) { + const uchar *s1, *s2; + + s1 = m1; + s2 = m2; + + while (n --> 0) { + if(*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + + return 0; +} + +void *memmove(void *dst, const void *src, uint n) { + const char *s; + char *d; + + if(n == 0) + return dst; + + s = src; + d = dst; + if(s < d && s + n > d){ + s += n; + d += n; + while(n-- > 0) + *--d = *--s; + } else + while(n-- > 0) + *d++ = *s++; + + return dst; +} + +void *memcpy(void *dst, const void *src, uint n) { + return memmove(dst, src, n); +} + +int strncmp(const char *p, const char *q, uint n) { + while(n > 0 && *p && *p == *q) + n--, p++, q++; + if(n == 0) + return 0; + return (uchar)*p - (uchar)*q; +} + +char *strncpy(char *s, const char *t, int n) { + char *os; + + os = s; + while(n-- > 0 && (*s++ = *t++) != 0) + ; + while(n-- > 0) + *s++ = 0; + return os; +} + +char *strcpy_s(char *s, const char *t, int n) { + char *os; + + os = s; + if(n <= 0) + return os; + while(--n > 0 && (*s++ = *t++) != 0) + ; + *s = 0; + return os; +} + +int strlen(const char *s) { + int n; + + for(n = 0; s[n]; n++) + ; + return n; +} \ No newline at end of file