diff options
Diffstat (limited to 'include/kernel')
| -rw-r--r-- | include/kernel/buf.h | 30 | ||||
| -rw-r--r-- | include/kernel/cpu.h | 19 | ||||
| -rw-r--r-- | include/kernel/elf.h | 46 | ||||
| -rw-r--r-- | include/kernel/exec.h | 6 | ||||
| -rw-r--r-- | include/kernel/mm.h | 31 | ||||
| -rw-r--r-- | include/kernel/pmm.h | 47 | ||||
| -rw-r--r-- | include/kernel/proc.h | 55 | ||||
| -rw-r--r-- | include/kernel/proc_def.h | 69 | ||||
| -rw-r--r-- | include/kernel/riscv.h | 4 | ||||
| -rw-r--r-- | include/kernel/runqueue.h | 16 | ||||
| -rw-r--r-- | include/kernel/slab.h | 10 | ||||
| -rw-r--r-- | include/kernel/spinlock.h | 52 | ||||
| -rw-r--r-- | include/kernel/sync.h | 38 | ||||
| -rw-r--r-- | include/kernel/syscall.h | 2 | ||||
| -rw-r--r-- | include/kernel/trap.h | 7 |
15 files changed, 347 insertions, 85 deletions
diff --git a/include/kernel/buf.h b/include/kernel/buf.h new file mode 100644 index 0000000..099523d --- /dev/null +++ b/include/kernel/buf.h @@ -0,0 +1,30 @@ +#pragma once +#include "common/types.h" +#include "kernel/spinlock.h" + +#define BSIZE 1024 +#define NBUF 30 + +struct Buf +{ + int valid; // Whether the data has been read from the disk (1=valid, 0=invalid) + int disk; // Whether it has been held by the driver (dirty bit/write-back flag is usually extended here) + uint32 dev; // Device Number + uint32 blockno; // Block number + uint32 refcnt; // Reference Counting + struct Buf *prev; // LRU linked list + struct Buf *next; + uchar data[BSIZE]; + + Mutex lock; // Sleep Lock +}; + +namespace BufferCache +{ + void init(); + struct Buf *bread(uint32 dev, uint32 blockno); + void bwrite(struct Buf *b); + void brelse(struct Buf *b); + void bpin(struct Buf *b); + void bunpin(struct Buf *b); +} // namespace BufferCache diff --git a/include/kernel/cpu.h b/include/kernel/cpu.h new file mode 100644 index 0000000..92890b6 --- /dev/null +++ b/include/kernel/cpu.h @@ -0,0 +1,19 @@ +#pragma once +#include "common/types.h" +#include "kernel/proc_def.h" + +struct RunQueue; + +struct cpu +{ + struct Proc *proc; + struct Context context; + int noff; + int intena; + + struct RunQueue *runqueue; +}; + + +extern struct cpu cpus[]; +struct cpu *mycpu();
\ No newline at end of file diff --git a/include/kernel/elf.h b/include/kernel/elf.h new file mode 100644 index 0000000..c216f1c --- /dev/null +++ b/include/kernel/elf.h @@ -0,0 +1,46 @@ +#pragma once +#include "common/types.h" + +#define ELF_MAGIC 0x464C457F // "\x7FELF" in little endian + +// ELF File Header +struct elfhdr +{ + uint32 magic; // Must equal ELF_MAGIC + uint8 elf[12]; + uint16 type; + uint16 machine; + uint32 version; + uint64 entry; // Program Entry Point (Virtual Address) + uint64 phoff; // File offset of the Program Header Table + uint64 shoff; + uint32 flags; + uint16 ehsize; + uint16 phentsize; + uint16 phnum; // Number of Program Headers + uint16 shentsize; + uint16 shnum; + uint16 shstrndx; +}; + +// Program Header +// Describes how to load segments from a file into memory +struct proghdr +{ + uint32 type; + uint32 flags; + uint64 off; // Offset of the section in the file + uint64 vaddr; // Virtual address of the segment in memory + uint64 paddr; + uint64 filesz; // Size of the section in the file + uint64 memsz; // The size of the segment in memory (memsz >= filesz) + uint64 align; +}; + +// Values for Proghdr type +#define ELF_PROG_LOAD 1 + +// Flag bits for Proghdr flags +#define ELF_PROG_FLAG_EXEC 1 +#define ELF_PROG_FLAG_WRITE 2 +#define ELF_PROG_FLAG_READ 4
\ No newline at end of file diff --git a/include/kernel/exec.h b/include/kernel/exec.h new file mode 100644 index 0000000..964e3bb --- /dev/null +++ b/include/kernel/exec.h @@ -0,0 +1,6 @@ +#pragma once + +namespace Exec +{ + int exec(char *path, char **argv); +}
\ No newline at end of file diff --git a/include/kernel/mm.h b/include/kernel/mm.h index 07d675b..3b59edb 100644 --- a/include/kernel/mm.h +++ b/include/kernel/mm.h @@ -3,20 +3,25 @@ namespace VM { - typedef uint64_t *pagetable_t; - typedef uint64_t pte_t; + extern uint64 *kernel_pagetable; - pte_t *walk(pagetable_t pagetable, uint64 va, int alloc); - int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm); - void kvmmap(uint64 va, uint64 pa, uint64 sz, int perm); void kvminit(); void kvminithart(); - pagetable_t uvmcreate(); - void uvminit(pagetable_t pagetable, uchar *src, uint sz); - void uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free); - void uvmfree(pagetable_t pagetable, uint64 sz); - int uvmcopy(pagetable_t oldpt, pagetable_t newpt, uint64 sz); - uint64 uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz); - uint64 uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz); - int copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len); + + uint64 *uvmcreate(); + void uvminit(uint64 *pagetable, uchar *src, uint64 sz); + uint64 uvmalloc(uint64 *pagetable, uint64 oldsz, uint64 newsz, int xperm); + uint64 uvmdealloc(uint64 *pagetable, uint64 oldsz, uint64 newsz); + void uvmfree(uint64 *pagetable, uint64 sz); + int uvmcopy(uint64 *oldpt, uint64 *newpt, uint64 sz); + void uvmunmap(uint64 *pagetable, uint64 va, uint64 npages, int do_free); + + int copyout(uint64 *pagetable, uint64 dstva, char *src, uint64 len); + int copyin(uint64 *pagetable, char *dst, uint64 srcva, uint64 len); + int copyinstr(uint64 *pagetable, char *dst, uint64 srcva, uint64 max); + + int handle_cow_fault(uint64 *pagetable, uint64 va); + int mappages(uint64 *pagetable, uint64 va, uint64 size, uint64 pa, int perm); + + uint64 walkaddr(uint64 *pagetable, uint64 va); }
\ No newline at end of file diff --git a/include/kernel/pmm.h b/include/kernel/pmm.h index 3328450..d31473f 100644 --- a/include/kernel/pmm.h +++ b/include/kernel/pmm.h @@ -1,13 +1,50 @@ #pragma once #include "common/types.h" +#include "kernel/spinlock.h" -#define PHYSTOP (0x80000000 + 128 * 1024 * 1024) -#define PGSIZE 4096 +// Physical Memory Layout Definition +#define KERNBASE 0x80000000 +// Set the memory size to 128MB +#define PHYSIZE (128 * 1024 * 1024) +#define PHYSTOP (KERNBASE + PHYSIZE) -namespace PMM{ +// Buddy System Max Order +// Order 10 => 2^10 pages = 1024 * 4KB = 4MB contiguous block +// Order 11 => 2^11 pages = 8MB +#define MAX_ORDER 11 + +// Page flag +#define PG_used 0x01 // This page is occupied +#define PG_reserved 0x02 // This page is reserved (kernel code/data, DTB, MemMap) + +// Physical Page Metadata Structure +struct Page +{ + uint8 flags; // Page Status (PG_used, PG_reserved) + uint8 order; // If it is the first page of a free block, record the order of the current block + uint16 refcnt; // Reference Counting + struct Page *next; // Free list pointer (points to the next free block of the same size) + struct Page *prev; // Doubly linked list (easy to remove) +}; + +namespace PMM +{ + // Initialize physical memory management void init(); - void* alloc_page(); + // Core Allocation Interface (Buddy System) + // order: 0 ~ MAX_ORDER-1 + void *alloc_pages(int order); + void free_pages(void *pa, int order); + + // Compatible with old interface (allocate single page with order=0 and automatically reset to zero) + void *alloc_page(); + void free_page(void *pa); + + // Helper function + struct Page *pa_to_page(uint64 pa); + uint64 page_to_pa(struct Page *page); - void free_page(void* pa); + // Debug information + void print_free_lists(); }
\ No newline at end of file diff --git a/include/kernel/proc.h b/include/kernel/proc.h index b557267..cbf2902 100644 --- a/include/kernel/proc.h +++ b/include/kernel/proc.h @@ -1,56 +1,8 @@ #pragma once #include "common/types.h" -#include "kernel/trap.h" +#include "kernel/proc_def.h" #include "kernel/spinlock.h" -struct Context -{ - uint64 ra; - uint64 sp; - - uint64 s0; - uint64 s1; - uint64 s2; - uint64 s3; - uint64 s4; - uint64 s5; - uint64 s6; - uint64 s7; - uint64 s8; - uint64 s9; - uint64 s10; - uint64 s11; -}; - -enum ProcState{ - UNUSED, - USED, - SLEEPING, - RUNNABLE, - RUNNING, - ZOMBIE, -}; - -struct Proc -{ - struct Context context; - struct Trapframe *tf; - - uint64 *pagetable; - - enum ProcState state; - int pid; - - void* kstack; - char name[16]; - uint64 sz; - - struct Proc *parent; - void *chan; - int xstate; -}; - - namespace ProcManager { void init(); @@ -62,8 +14,11 @@ namespace ProcManager void user_init(); void exit(int status); int wait(uint64 addr); - void sleep(void *chan, struct spinlock *lk); + + void sleep(void *chan, Spinlock *lk); void wakeup(void *chan); + + int growproc(int n); } void forkret(); diff --git a/include/kernel/proc_def.h b/include/kernel/proc_def.h new file mode 100644 index 0000000..5ce4c03 --- /dev/null +++ b/include/kernel/proc_def.h @@ -0,0 +1,69 @@ +#pragma once +#include "common/types.h" +#include "common/fcntl.h" + +struct cpu; +struct Trapframe; +class Inode; +struct file; + +enum ProcState +{ + UNUSED, + USED, + SLEEPING, + RUNNABLE, + RUNNING, + ZOMBIE, +}; + +#define PRIO_MAX 0 +#define PRIO_MIN 3 +#define N_PRIO 4 + +// Context structure +struct Context +{ + uint64 ra; + uint64 sp; + uint64 s0; + uint64 s1; + uint64 s2; + uint64 s3; + uint64 s4; + uint64 s5; + uint64 s6; + uint64 s7; + uint64 s8; + uint64 s9; + uint64 s10; + uint64 s11; +}; + +struct Proc +{ + struct Context context; + struct Trapframe *tf; + uint64 *pagetable; + enum ProcState state; + int pid; + void *kstack; + char name[16]; + uint64 sz; + struct Proc *parent; + void *chan; + int xstate; + + Inode *cwd; + struct file *ofile[NOFILE]; + + struct Proc *next; + struct Proc *prev; + + struct Proc *all_next; + struct Proc *all_prev; + + int priority; + int ticks; + struct cpu *cpu; +};
\ No newline at end of file diff --git a/include/kernel/riscv.h b/include/kernel/riscv.h index 4b3d323..0c586a9 100644 --- a/include/kernel/riscv.h +++ b/include/kernel/riscv.h @@ -79,6 +79,7 @@ w_sip(uint64 x) // Supervisor Interrupt Enable #define SIE_SEIE (1L << 9) // external #define SIE_STIE (1L << 5) // timer +#define SIE_SSIE (1L << 1) // software static inline uint64 r_sie() { @@ -375,7 +376,8 @@ typedef uint64 *pagetable_t; // 512 PTEs #define PTE_X (1L << 3) #define PTE_U (1L << 4) // user can access - +// COW Flag (PTE bit 8) +#define PTE_COW (1L << 8) #if defined(LAB_MMAP) || defined(LAB_PGTBL) || defined(LAB_COW) #define PTE_LEAF(pte) (((pte) & PTE_R) | ((pte) & PTE_W) | ((pte) & PTE_X)) diff --git a/include/kernel/runqueue.h b/include/kernel/runqueue.h new file mode 100644 index 0000000..ea6e4cc --- /dev/null +++ b/include/kernel/runqueue.h @@ -0,0 +1,16 @@ +#pragma once +#include "kernel/spinlock.h" +#include "kernel/proc_def.h" + +struct RunQueue +{ + Spinlock lock; + struct Proc *heads[N_PRIO]; + struct Proc *tails[N_PRIO]; + uint64 count; + + void init(const char *name); + void enqueue(struct Proc *p); + struct Proc *dequeue(); + struct Proc *steal(); +};
\ No newline at end of file diff --git a/include/kernel/slab.h b/include/kernel/slab.h new file mode 100644 index 0000000..650f8a9 --- /dev/null +++ b/include/kernel/slab.h @@ -0,0 +1,10 @@ +#pragma once +#include "common/types.h" + +namespace Slab +{ + void init(); + + void *kmalloc(uint64 size); + void kfree(void *ptr); +}
\ No newline at end of file diff --git a/include/kernel/spinlock.h b/include/kernel/spinlock.h index aec4b6a..3102e68 100644 --- a/include/kernel/spinlock.h +++ b/include/kernel/spinlock.h @@ -1,20 +1,48 @@ #pragma once #include "common/types.h" -struct spinlock +struct cpu; + +// Spinlock +// Features: Non-interruptible, busy-wait loop, extremely short hold time. +// Scenario: Protecting core data such as scheduler, interrupt handling, PMM, etc. +class Spinlock { - uint locked; +public: + volatile uint32 locked; // Whether it is locked (0: unlocked, 1: locked) + const char *name; // Lock Name (for debugging) + struct cpu *cpu; // The CPU holding the lock + + // Constructor + Spinlock() : locked(0), name("uninit"), cpu(nullptr) {} + + // Initialize lock name + void init(const char *name); + + // Acquire lock + void acquire(); - char *name; - int cpu_id; + // Release lock + void release(); + + // Check if the current CPU holds the lock + bool holding(); }; -namespace Spinlock +// Mutex +// Features: Allows interruption, allows sleeping (yield CPU), can hold for a long time. +// Scenarios: File system IO, device driver waiting, long-term buffering operations. +class Mutex { - void init(struct spinlock *lk, char *name); - void acquire(struct spinlock *lk); - void release(struct spinlock *lk); - int holding(struct spinlock *lk); - void push_off(); - void pop_off(); -}
\ No newline at end of file +public: + uint32 locked; // Whether it is locked + const char *name; // Lock Name + int pid; // PID of the process holding the lock (for debugging) + + Spinlock lk; // Internal spin lock, protects the state of the Mutex itself + + void init(const char *name); + void acquire(); + void release(); + bool holding(); +};
\ No newline at end of file diff --git a/include/kernel/sync.h b/include/kernel/sync.h new file mode 100644 index 0000000..83d88c8 --- /dev/null +++ b/include/kernel/sync.h @@ -0,0 +1,38 @@ +#pragma once +#include "common/types.h" +#include "kernel/spinlock.h" +#include "kernel/proc_def.h" + + +struct WaitQueue +{ + Spinlock lock; + struct Proc *head; + struct Proc *tail; + + void init(const char *name); + void sleep(); + void wakeup(); + void wakeup_all(); +}; + +struct Semaphore +{ + int value; + WaitQueue wq; + Spinlock lock; + + void init(int val, const char *name); + void wait(); + void post(); +}; + +struct CondVar +{ + WaitQueue wq; + + void init(const char *name); + void wait(Spinlock *mutex_lock); + void signal(); + void broadcast(); +};
\ No newline at end of file diff --git a/include/kernel/syscall.h b/include/kernel/syscall.h index 222f2f4..c0c9082 100644 --- a/include/kernel/syscall.h +++ b/include/kernel/syscall.h @@ -22,6 +22,8 @@ #define SYS_link 20 #define SYS_mkdir 21 #define SYS_close 22 +#define SYS_disk_test 23 +#define SYS_lseek 24 #ifndef __ASSEMBLER__ void syscall(); diff --git a/include/kernel/trap.h b/include/kernel/trap.h index 79bb037..35b225c 100644 --- a/include/kernel/trap.h +++ b/include/kernel/trap.h @@ -45,7 +45,6 @@ struct Trapframe namespace Trap { void init(); - extern "C" void kernelvec(); - extern "C" void kerneltrap(struct Trapframe *tf); -} -extern "C" void usertrap();
\ No newline at end of file + void inithart(); + int devintr(); +}
\ No newline at end of file |
