summaryrefslogtreecommitdiff
path: root/include/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'include/kernel')
-rw-r--r--include/kernel/buf.h30
-rw-r--r--include/kernel/cpu.h19
-rw-r--r--include/kernel/elf.h46
-rw-r--r--include/kernel/exec.h6
-rw-r--r--include/kernel/mm.h31
-rw-r--r--include/kernel/pmm.h47
-rw-r--r--include/kernel/proc.h55
-rw-r--r--include/kernel/proc_def.h69
-rw-r--r--include/kernel/riscv.h4
-rw-r--r--include/kernel/runqueue.h16
-rw-r--r--include/kernel/slab.h10
-rw-r--r--include/kernel/spinlock.h52
-rw-r--r--include/kernel/sync.h38
-rw-r--r--include/kernel/syscall.h2
-rw-r--r--include/kernel/trap.h7
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