Skip to content

Commit b125038

Browse files
committed
ch4
1 parent 3ec22ee commit b125038

File tree

15 files changed

+511
-59
lines changed

15 files changed

+511
-59
lines changed

os/const.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,28 @@ enum {
99
STDERR = 2,
1010
};
1111

12+
// memory layout
13+
14+
// the kernel expects there to be RAM
15+
// for use by the kernel and user pages
16+
// from physical address 0x80000000 to PHYSTOP.
17+
#define KERNBASE 0x80200000L
18+
#define PHYSTOP (0x80000000 + 128 * 1024 * 1024) // we have 128M memroy
19+
20+
// one beyond the highest possible virtual address.
21+
// MAXVA is actually one bit less than the max allowed by
22+
// Sv39, to avoid having to sign-extend virtual addresses
23+
// that have the high bit set.
24+
#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))
25+
26+
// map the trampoline page to the highest address,
27+
// in both user and kernel space.
28+
#define USER_TOP (MAXVA)
29+
#define TRAMPOLINE (USER_TOP - PGSIZE)
30+
#define TRAPFRAME (TRAMPOLINE - PGSIZE)
31+
32+
// memory layout end
33+
34+
#define MAX_STR_LEN (200)
35+
1236
#endif // CONST_H

os/defs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
#define DEFS_H
33

44
#include "const.h"
5+
#include "kalloc.h"
56
#include "log.h"
67
#include "printf.h"
78
#include "proc.h"
89
#include "riscv.h"
910
#include "sbi.h"
1011
#include "string.h"
1112
#include "types.h"
13+
#include "vm.h"
1214

1315
// number of elements in fixed-size array
1416
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))

os/kalloc.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include "kalloc.h"
2+
#include "defs.h"
3+
#include "riscv.h"
4+
5+
extern char ekernel[];
6+
7+
struct linklist {
8+
struct linklist *next;
9+
};
10+
11+
struct {
12+
struct linklist *freelist;
13+
} kmem;
14+
15+
void freerange(void *pa_start, void *pa_end)
16+
{
17+
char *p;
18+
p = (char *)PGROUNDUP((uint64)pa_start);
19+
for (; p + PGSIZE <= (char *)pa_end; p += PGSIZE)
20+
kfree(p);
21+
}
22+
23+
void kinit()
24+
{
25+
freerange(ekernel, (void *)PHYSTOP);
26+
}
27+
28+
// Free the page of physical memory pointed at by v,
29+
// which normally should have been returned by a
30+
// call to kalloc(). (The exception is when
31+
// initializing the allocator; see kinit above.)
32+
void kfree(void *pa)
33+
{
34+
struct linklist *l;
35+
if (((uint64)pa % PGSIZE) != 0 || (char *)pa < ekernel ||
36+
(uint64)pa >= PHYSTOP)
37+
panic("kfree");
38+
// Fill with junk to catch dangling refs.
39+
memset(pa, 1, PGSIZE);
40+
l = (struct linklist *)pa;
41+
l->next = kmem.freelist;
42+
kmem.freelist = l;
43+
}
44+
45+
// Allocate one 4096-byte page of physical memory.
46+
// Returns a pointer that the kernel can use.
47+
// Returns 0 if the memory cannot be allocated.
48+
void *kalloc(void)
49+
{
50+
struct linklist *l;
51+
l = kmem.freelist;
52+
if (l) {
53+
kmem.freelist = l->next;
54+
memset((char *)l, 5, PGSIZE); // fill with junk
55+
}
56+
return (void *)l;
57+
}

os/kalloc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef KALLOC_H
2+
#define KALLOC_H
3+
4+
void *kalloc(void);
5+
void kfree(void *);
6+
void kinit(void);
7+
8+
#endif // KALLOC_H

os/loader.c

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
#include "defs.h"
33
#include "trap.h"
44

5-
static uint64 app_num;
5+
static int app_num;
66
static uint64 *app_info_ptr;
7-
extern char _app_num[], ekernel[];
7+
extern char _app_num[];
88

99
// Count finished programs. If all apps exited, shutdown.
1010
int finished()
@@ -18,35 +18,54 @@ int finished()
1818
// Get user progs' infomation through pre-defined symbol in `link_app.S`
1919
void loader_init()
2020
{
21-
if ((uint64)ekernel >= BASE_ADDRESS) {
22-
panic("kernel too large...\n");
23-
}
2421
app_info_ptr = (uint64 *)_app_num;
2522
app_num = *app_info_ptr;
2623
app_info_ptr++;
2724
}
2825

29-
// Load nth user app at
30-
// [BASE_ADDRESS + n * MAX_APP_SIZE, BASE_ADDRESS + (n+1) * MAX_APP_SIZE)
31-
int load_app(int n, uint64 *info)
26+
pagetable_t bin_loader(uint64 start, uint64 end, struct proc *p)
3227
{
33-
uint64 start = info[n], end = info[n + 1], length = end - start;
34-
memset((void *)BASE_ADDRESS + n * MAX_APP_SIZE, 0, MAX_APP_SIZE);
35-
memmove((void *)BASE_ADDRESS + n * MAX_APP_SIZE, (void *)start, length);
36-
return length;
28+
pagetable_t pg = uvmcreate();
29+
if (mappages(pg, TRAPFRAME, PGSIZE, (uint64)p->trapframe,
30+
PTE_R | PTE_W) < 0) {
31+
panic("mappages fail");
32+
}
33+
if (!PGALIGNED(start)) {
34+
panic("user program not aligned, start = %p", start);
35+
}
36+
if (!PGALIGNED(end)) {
37+
// Fix in ch5
38+
warnf("Some kernel data maybe mapped to user, start = %p, end = %p",
39+
start, end);
40+
}
41+
end = PGROUNDUP(end);
42+
uint64 length = end - start;
43+
if (mappages(pg, BASE_ADDRESS, length, start,
44+
PTE_U | PTE_R | PTE_W | PTE_X) != 0) {
45+
panic("mappages fail");
46+
}
47+
p->pagetable = pg;
48+
uint64 ustack_bottom_vaddr = BASE_ADDRESS + length + PAGE_SIZE;
49+
if (USTACK_SIZE != PAGE_SIZE) {
50+
// Fix in ch5
51+
panic("Unsupported");
52+
}
53+
mappages(pg, ustack_bottom_vaddr, USTACK_SIZE, (uint64)kalloc(),
54+
PTE_U | PTE_R | PTE_W | PTE_X);
55+
p->ustack = ustack_bottom_vaddr;
56+
p->trapframe->epc = BASE_ADDRESS;
57+
p->trapframe->sp = p->ustack + USTACK_SIZE;
58+
p->max_page = PGROUNDUP(p->ustack + USTACK_SIZE - 1) / PAGE_SIZE;
59+
return pg;
3760
}
3861

3962
// load all apps and init the corresponding `proc` structure.
4063
int run_all_app()
4164
{
4265
for (int i = 0; i < app_num; ++i) {
4366
struct proc *p = allocproc();
44-
struct trapframe *trapframe = p->trapframe;
45-
load_app(i, app_info_ptr);
46-
uint64 entry = BASE_ADDRESS + i * MAX_APP_SIZE;
47-
tracef("load app %d at %p", i, entry);
48-
trapframe->epc = entry;
49-
trapframe->sp = (uint64)p->ustack + USER_STACK_SIZE;
67+
tracef("load app %d", i);
68+
bin_loader(app_info_ptr[i], app_info_ptr[i + 1], p);
5069
p->state = RUNNABLE;
5170
}
5271
return 0;

os/loader.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ int finished();
88
void loader_init();
99
int run_all_app();
1010

11-
#define BASE_ADDRESS (0x80400000)
12-
#define MAX_APP_SIZE (0x20000)
13-
#define USER_STACK_SIZE (PAGE_SIZE)
11+
#define BASE_ADDRESS (0x1000)
12+
#define USTACK_SIZE (PAGE_SIZE)
13+
#define KSTACK_SIZE (PAGE_SIZE)
1414
#define TRAP_PAGE_SIZE (PAGE_SIZE)
1515

1616
#endif // LOADER_H

os/main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ void clean_bss()
1414
void main()
1515
{
1616
clean_bss();
17+
printf("hello world!\n");
1718
proc_init();
19+
kinit();
20+
kvm_init();
1821
loader_init();
1922
trap_init();
2023
timer_init();
2124
run_all_app();
2225
infof("start scheduler!");
2326
scheduler();
24-
}
27+
}

os/proc.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
#include "defs.h"
33
#include "loader.h"
44
#include "trap.h"
5+
#include "vm.h"
56

67
struct proc pool[NPROC];
7-
char kstack[NPROC][PAGE_SIZE];
8-
__attribute__((aligned(4096))) char ustack[NPROC][PAGE_SIZE];
9-
__attribute__((aligned(4096))) char trapframe[NPROC][PAGE_SIZE];
8+
__attribute__((aligned(16))) char kstack[NPROC][PAGE_SIZE];
9+
__attribute__((aligned(4096))) char trapframe[NPROC][TRAP_PAGE_SIZE];
1010

1111
extern char boot_stack_top[];
1212
struct proc *current_proc;
@@ -29,7 +29,6 @@ void proc_init(void)
2929
for (p = pool; p < &pool[NPROC]; p++) {
3030
p->state = UNUSED;
3131
p->kstack = (uint64)kstack[p - pool];
32-
p->ustack = (uint64)ustack[p - pool];
3332
p->trapframe = (struct trapframe *)trapframe[p - pool];
3433
}
3534
idle.kstack = (uint64)boot_stack_top;
@@ -59,11 +58,14 @@ struct proc *allocproc(void)
5958
found:
6059
p->pid = allocpid();
6160
p->state = USED;
61+
p->pagetable = 0;
62+
p->ustack = 0;
63+
p->max_page = 0;
6264
memset(&p->context, 0, sizeof(p->context));
63-
memset(p->trapframe, 0, PAGE_SIZE);
64-
memset((void *)p->kstack, 0, PAGE_SIZE);
65+
memset((void *)p->kstack, 0, KSTACK_SIZE);
66+
memset((void *)p->trapframe, 0, TRAP_PAGE_SIZE);
6567
p->context.ra = (uint64)usertrapret;
66-
p->context.sp = p->kstack + PAGE_SIZE;
68+
p->context.sp = p->kstack + KSTACK_SIZE;
6769
return p;
6870
}
6971

@@ -108,12 +110,18 @@ void yield(void)
108110
sched();
109111
}
110112

113+
void freeproc(struct proc *p)
114+
{
115+
p->state = UNUSED;
116+
// uvmfree(p->pagetable, p->max_page);
117+
}
118+
111119
// Exit the current process.
112120
void exit(int code)
113121
{
114122
struct proc *p = curr_proc();
115123
infof("proc %d exit with %d", p->pid, code);
116-
p->state = UNUSED;
124+
freeproc(p);
117125
finished();
118126
sched();
119127
}

os/proc.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef PROC_H
22
#define PROC_H
33

4+
#include "riscv.h"
45
#include "types.h"
56

67
#define NPROC (16)
@@ -31,10 +32,12 @@ enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
3132
struct proc {
3233
enum procstate state; // Process state
3334
int pid; // Process ID
34-
uint64 ustack; // Virtual address of user stack
35+
pagetable_t pagetable; // User page table
36+
uint64 ustack;
3537
uint64 kstack; // Virtual address of kernel stack
3638
struct trapframe *trapframe; // data page for trampoline.S
3739
struct context context; // swtch() here to run process
40+
uint64 max_page;
3841
};
3942

4043
struct proc *curr_proc();

os/riscv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ static inline void sfence_vma()
291291

292292
#define PGROUNDUP(sz) (((sz) + PGSIZE - 1) & ~(PGSIZE - 1))
293293
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE - 1))
294+
#define PGALIGNED(a) (((a) & (PGSIZE - 1)) == 0)
294295

295296
#define PTE_V (1L << 0) // valid
296297
#define PTE_R (1L << 1)
@@ -317,6 +318,7 @@ static inline void sfence_vma()
317318
#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))
318319

319320
typedef uint64 pte_t;
321+
typedef uint64 pde_t;
320322
typedef uint64 *pagetable_t; // 512 PTEs
321323

322324
#endif // RISCV_H

0 commit comments

Comments
 (0)