[Add] laos base boot
This commit is contained in:
@@ -19,14 +19,15 @@ BIN := neula-os
|
|||||||
BINARY := $(BUILD_DIR)/$(BIN)
|
BINARY := $(BUILD_DIR)/$(BIN)
|
||||||
|
|
||||||
TOP_SRC_DIR := src
|
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))
|
MK_DIRS := $(addprefix MAKE/,$(SOURCE_DIRS))
|
||||||
ALL_SRCS := $(shell find . -name '*.c')
|
ALL_SRCS := $(shell find . -name '*.c')
|
||||||
LD_CSRIPT := kernel.ld
|
LD_CSRIPT := kernel.ld
|
||||||
|
|
||||||
EXTRA_MACRO := # NDEBUG
|
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 += -MD
|
||||||
EXTRA_FLAGS += -ffreestanding -fno-common -nostdlib
|
EXTRA_FLAGS += -ffreestanding -fno-common -nostdlib
|
||||||
EXTRA_FLAGS += -I.
|
EXTRA_FLAGS += -I.
|
||||||
@@ -57,4 +58,15 @@ build: $(MK_DIRS)
|
|||||||
@$(OC) $(BINARY) -O binary $(BINARY).bin
|
@$(OC) $(BINARY) -O binary $(BINARY).bin
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
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)
|
||||||
|
|||||||
@@ -3,6 +3,36 @@
|
|||||||
#ifndef ASM_H__
|
#ifndef ASM_H__
|
||||||
#define 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
|
#endif
|
||||||
6
laos/include/console.h
Normal file
6
laos/include/console.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef CONSOLE_H__
|
||||||
|
#define CONSOLE_H__
|
||||||
|
|
||||||
|
void consputc(int c);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
#ifndef DEFS_H__
|
#ifndef DEFS_H__
|
||||||
#define DEFS_H__
|
#define DEFS_H__
|
||||||
|
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
|
||||||
#define NCPU 1
|
#define NCPU 1
|
||||||
|
#define NPROC 64
|
||||||
|
#define NOFILE 16
|
||||||
|
|
||||||
|
|
||||||
|
#define SERIAL_TX_BUF_SIZE 32
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
10
laos/include/fcntl.h
Normal file
10
laos/include/fcntl.h
Normal file
@@ -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
|
||||||
0
laos/include/filesys.h
Normal file
0
laos/include/filesys.h
Normal file
@@ -1,10 +1,11 @@
|
|||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
#ifndef COMMON_H__
|
#ifndef KERNEL_H__
|
||||||
#define COMMON_H__
|
#define KERNEL_H__
|
||||||
|
|
||||||
void main();
|
|
||||||
void start();
|
|
||||||
void _entry() __attribute__ ((section (".entry")));
|
void _entry() __attribute__ ((section (".entry")));
|
||||||
|
|
||||||
#endif // COMMON_H__
|
void start();
|
||||||
|
void main();
|
||||||
|
|
||||||
|
#endif
|
||||||
8
laos/include/kprintf.h
Normal file
8
laos/include/kprintf.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef KPRINTF_H__
|
||||||
|
#define KPRINTF_H__
|
||||||
|
|
||||||
|
|
||||||
|
void kprintf(char *fmt, ...);
|
||||||
|
void panic(char *s);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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
|
||||||
22
laos/include/latype.h
Normal file
22
laos/include/latype.h
Normal file
@@ -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
|
||||||
7
laos/include/macro.h
Normal file
7
laos/include/macro.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef MACRO_H__
|
||||||
|
#define MACRO_H__
|
||||||
|
|
||||||
|
#define TOSTRING_(x) #x
|
||||||
|
#define TOSTRING(x) TOSTRING_(x)
|
||||||
|
|
||||||
|
#endif
|
||||||
11
laos/include/memio.h
Normal file
11
laos/include/memio.h
Normal file
@@ -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
|
||||||
9
laos/include/memlayout.h
Normal file
9
laos/include/memlayout.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef MEMLAYOUT_H__
|
||||||
|
#define MEMLAYOUT_H__
|
||||||
|
|
||||||
|
#define DEV_BASE_ADDR 0xa0000000
|
||||||
|
|
||||||
|
|
||||||
|
#define SERIAL_ADDR (DEV_BASE_ADDR + 0x00000000)
|
||||||
|
|
||||||
|
#endif
|
||||||
117
laos/include/proc.h
Normal file
117
laos/include/proc.h
Normal file
@@ -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
|
||||||
23
laos/include/spinlock.h
Normal file
23
laos/include/spinlock.h
Normal file
@@ -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
|
||||||
16
laos/include/string.h
Normal file
16
laos/include/string.h
Normal file
@@ -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
|
||||||
9
laos/include/unistd.h
Normal file
9
laos/include/unistd.h
Normal file
@@ -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
|
||||||
21
laos/src/dev/Makefile
Normal file
21
laos/src/dev/Makefile
Normal file
@@ -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)"
|
||||||
31
laos/src/dev/serial.c
Normal file
31
laos/src/dev/serial.c
Normal file
@@ -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);
|
||||||
|
}
|
||||||
28
laos/src/kernel/console.c
Normal file
28
laos/src/kernel/console.c
Normal file
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
@@ -8,13 +8,13 @@ _entry:
|
|||||||
# with a 4096-byte stack per CPU.
|
# with a 4096-byte stack per CPU.
|
||||||
# sp = stack0 + (hartid * 4096)
|
# sp = stack0 + (hartid * 4096)
|
||||||
la.global $sp, stack0
|
la.global $sp, stack0
|
||||||
lu12i.w $a0, (1024*4 >> 12) & 0xfffff
|
lu12i.w $a0, (1024*4 >> 12) & 0xfffff
|
||||||
addi.w $a0, $a0, 1024*4 & 0xfff
|
addi.w $a0, $a0, 1024*4 & 0xfff
|
||||||
csrrd $a1, CPUID
|
csrrd $a1, CPUID
|
||||||
addi.w $a1, $a1, 1
|
addi.w $a1, $a1, 1
|
||||||
mul.w $a0, $a0, $a1
|
mul.w $a0, $a0, $a1
|
||||||
add.w $sp, $sp, $a0
|
add.w $sp, $sp, $a0
|
||||||
# jump to start() in start.c
|
# jump to start() in start.c
|
||||||
bl start
|
bl start
|
||||||
spin:
|
spin:
|
||||||
b spin
|
b spin
|
||||||
116
laos/src/kernel/kprintf.c
Normal file
116
laos/src/kernel/kprintf.c
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
@@ -1,3 +1,25 @@
|
|||||||
|
#include "la32r.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
|
|
||||||
|
volatile static int started = 0;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
struct spinlock lck[1];
|
||||||
|
initlock(lck, "main");
|
||||||
|
acquire(lck);
|
||||||
|
|
||||||
|
if (r_cpuid() == 0) {
|
||||||
|
|
||||||
|
|
||||||
|
synchronize();
|
||||||
|
started = 1;
|
||||||
|
} else {
|
||||||
|
// 当前假定只有一个 hart
|
||||||
|
while (started == 0)
|
||||||
|
;
|
||||||
|
synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
24
laos/src/kernel/proc.c
Normal file
24
laos/src/kernel/proc.c
Normal file
@@ -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;
|
||||||
|
}
|
||||||
54
laos/src/kernel/spinlock.c
Normal file
54
laos/src/kernel/spinlock.c
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,7 +1,20 @@
|
|||||||
#include "common.h"
|
#include "kernel.h"
|
||||||
|
#include "la32r.h"
|
||||||
|
|
||||||
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
|
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
|
||||||
|
|
||||||
void start() {
|
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");
|
||||||
}
|
}
|
||||||
21
laos/src/lib/Makefile
Normal file
21
laos/src/lib/Makefile
Normal file
@@ -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)"
|
||||||
0
laos/src/lib/path.c
Normal file
0
laos/src/lib/path.c
Normal file
29
laos/src/user/Makefile
Normal file
29
laos/src/user/Makefile
Normal file
@@ -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)
|
||||||
16
laos/src/user/echo.c
Normal file
16
laos/src/user/echo.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
0
laos/src/user/shell.c
Normal file
0
laos/src/user/shell.c
Normal file
49
laos/src/user/xargs.c
Normal file
49
laos/src/user/xargs.c
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
93
laos/src/util/string.c
Normal file
93
laos/src/util/string.c
Normal file
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user