-
Notifications
You must be signed in to change notification settings - Fork 1
/
design.txt
115 lines (76 loc) · 5.47 KB
/
design.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Design doc
## Identify an approach to allocate the memory that will become your frame table and implement it.
The frametable has the following fields:
```
struct frame_entry {
int fe_refcount; /* number of references to this frame */
char fe_used; /* flag to indicate if this frame is free */
int fe_next; /* if this frame is free, index of next free */
};
```
## Initialise the frame table (vm_bootstrap is a plausible location to call the code).
One of the first things that the kernel does upon booting is call `vm_bootstrap()`, this inturn calls `frametable_init()` (within vm/frametable.c). Frametable_init uses alloc_kpages indirectly (via kmalloc), which uses ram_stealmem at this point in time while we are setting up the frametable. Once the frametable has been initialised then alloc_kpages uses frames to alloc and dealloc memory, via `push_frame()` and `pop_frame()`.
Frametable_init performs the following steps:
1. Calculate the number of pages available
2. Calculate the size of the frame table
3. Allocate memor for frame table and page table
4. Get the top of the frame table
5. Calculate number of pages already used (by the OS)
6. Set the current free page index
7. Set dirty/clean bits according to what pages are in use
## Write routines in kern/vm/frametable.c to manage free frames and allocate pages. Note: the frame table is a global resource, therefore you'll need to deal with concurrency. It is okay to use the spinlock already in place for stealmem, or you can use interrupt disabling/enabling for this table.
A spinlock is made use of in the following situations:
* Acquiring memory within `alloc_kpages()`
* Freeing a page within `free_kpages()`
Before the frame table is initialised the spinlock surrounds the `ram_stealmem()` call, and after the frame table is initiliased the two aforementioned situations call `pop_frame()` and `push_frame()` respectively. This is to prevent race conditions with the global frame table pointer.
## Understand how the page table works, and its relationship with the TLB.
The page table keeps track of a process id, physical page address, virtual page address, flags and a link to the next entry. Once memory has been allocated then a page entry is created and inserted into the TLB after a fault (when an address which lies within that frame has been requested to be accessed).
TLB keeps track of page table entries for a given address space. The TLB can be flushed, pages can be replaced, or pages can be found via `tlb_probe()`. Pages are found by hashing the virtual address and a page frame mask to look up an entry within the hashed page table.
## Work out a basic design for your page table implementation.
```
struct page_entry {
uint32_t pe_proc; /* the process id */
uint32_t pe_ppn; /* the frame table frame num */
uint32_t pe_vpn; /* the frame table frame num */
char pe_flags; /* page permissions and flags */
struct page_entry *pe_next; /* pointer to collion next entry */
};
```
## Modify kern/vm/vm.c to insert , lookup, and update page table entries, and keep the TLB consistent with the page table.
## Implement the TLB exception handlers in vm.c using your page table.
## Implement the functions in kern/vm/addrspace.c that are required for basic functionality (e.g. as_create(), as_prepare_load(), etc.). Allocating user pages in as_define_region() may also simplify your assignment, however good solution allocate pages in vm_fault().
The following functions were implemented within kern/vm/addrspace.c:
* struct addrspace *as_create(void)
- creates an address space
* int as_copy(struct addrspace *old, struct addrspace **ret)
- allocates a new destination addr space
- adds all the same regions as source
- roughly, for each mapped page in source
- allocate a frame in dest
- copy contents from source frame to dest frame
- add PT entry for dest
* void as_destroy(struct addrspace *as)
- purges the page and frame tables
- frees all regions
* void as_activate(void)
- if there is an address space then flush the tlb
* void as_deactivate(void)
- if there is an address space then flush the tlb
* int as_define_region(struct addrspace *as, vaddr_t vaddr,
size_t memsize, int readable, int writeable,
int executable)
- create a new region within a given address space
* int as_prepare_load(struct addrspace *as)
- store current permissions and then change them to RW
* int as_complete_load(struct addrspace *as)
- restore saved permissions
* int as_define_stack(struct addrspace *as, vaddr_t *stackptr)
- define the stack region within the given address space
* static int append_region(struct addrspace *as,
int permissions, vaddr_t start, size_t size)
- create a region
- append it to the address space regions
* int region_type(struct addrspace *as, vaddr_t addr)
- return what type of region an address lies in
* int region_perms(struct addrspace *as, vaddr_t addr)
- return the permissions of a region