Modestus Moon OS  R4
CS 450 project
paging.c
Go to the documentation of this file.
1 /*
2  ----- paging.c -----
3 
4  Description..: Routines used in initializing and
5  maintaining page directories, page tables, pages
6  and frames.
7 */
8 
9 #include <system.h>
10 #include <string.h>
11 
12 #include "mem/heap.h"
13 #include "mem/paging.h"
14 
15 u32int mem_size = 0x4000000; //64MB
16 u32int page_size = 0x1000; //4KB
17 
18 u32int nframes; //number of frames
19 u32int *frames; //bitmap of frames
20 
21 page_dir *kdir = 0; //kernel directory
22 page_dir *cdir = 0; //current directory
23 
24 //defined in heap.c
25 extern u32int phys_alloc_addr;
26 extern heap* kheap;
27 
28 /*
29  Procedure..: set_bit
30  Description..: Marks a page frame bit as in use (1).
31 */
32 void set_bit(u32int addr)
33 {
34  u32int frame = addr/page_size;
35  u32int index = frame/32;
36  u32int offset = frame%32;
37  frames[index] |= (1 << offset);
38 }
39 
40 /*
41  Procedure..: clear_bit
42  Description..: Marks a page frame bit as free (0).
43 */
44 void clear_bit(u32int addr)
45 {
46  u32int frame = addr/page_size;
47  u32int index = frame/32;
48  u32int offset = frame%32;
49  frames[index] &= ~(1 << offset);
50 }
51 
52 /*
53  Procedure..: get_bit
54  Description..: Checks if page frame is in use.
55 */
57 {
58  u32int frame = addr/page_size;
59  u32int index = frame/32;
60  u32int offset = frame%32;
61  return (frames[index] & (1 << offset));
62 }
63 
64 /*
65  Procedure..: find_free
66  Description..: Finds the first free page frame.
67 */
69 {
70  u32int i,j;
71  for (i=0; i<nframes/32; i++)
72  if (frames[i] != 0xFFFFFFFF) //if frame not full
73  for (j=0; j<32; j++) //find first free bit
74  if (!(frames[i] & (1 << j)))
75  return i*32+j;
76 
77  return -1; //no free frames
78 }
79 
80 /*
81  Procedure..: get_page
82  Description..: Finds and returns a page, allocating a new
83  page table if necessary.
84 */
85 page_entry* get_page(u32int addr, page_dir *dir, int make_table)
86 {
87  u32int phys_addr;
88  u32int index = addr / page_size / 1024;
89  u32int offset = addr / page_size % 1024;
90 
91  //return it if it exists
92  if (dir->tables[index])
93  return &dir->tables[index]->pages[offset];
94 
95  //create it
96  else if (make_table){
97  dir->tables[index] = (page_table*)_kmalloc(sizeof(page_table), 1, &phys_addr);
98  dir->tables_phys[index] = phys_addr | 0x7; //enable present, writable
99  return &dir->tables[index]->pages[offset];
100  }
101  else return 0;
102 }
103 
104 /*
105  Procedure..: init_paging
106  Description..: Initializes the kernel page directory and
107  initial kernel heap area. Performs identity mapping of
108  the kernel frames such that the virtual addresses are
109  equivalent to the physical addresses.
110 */
112 {
113  //create frame bitmap
115  frames = (u32int*)kmalloc(nframes/32);
116  memset(frames, 0, nframes/32);
117 
118  //create kernel directory
119  kdir = (page_dir*)_kmalloc(sizeof(page_dir), 1, 0); //page aligned
120  memset(kdir, 0, sizeof(page_dir));
121 
122  //get pages for kernel heap
123  u32int i = 0x0;
124  for(i=KHEAP_BASE; i<(KHEAP_BASE+KHEAP_MIN); i+=1){
125  get_page(i,kdir,1);
126  }
127 
128  //perform identity mapping of used memory
129  //note: placement_addr gets incremented in get_page,
130  //so we're mapping the first frames as well
131  i = 0x0;
132  while (i < (phys_alloc_addr+0x10000)){
133  new_frame(get_page(i,kdir,1));
134  i += page_size;
135  }
136 
137  //allocate heap frames now that the placement addr has increased.
138  //placement addr increases here for heap
139  for(i=KHEAP_BASE; i<(KHEAP_BASE+KHEAP_MIN);i+=PAGE_SIZE){
140  new_frame(get_page(i,kdir,1));
141  }
142 
143  //load the kernel page directory; enable paging
144  load_page_dir(kdir);
145 
146  //setup the kernel heap
148 }
149 
150 /*
151  Procedure..: load_page_dir
152  Description..: Sets a page directory as the current
153  directory and enables paging via the cr0 register.
154  The cr3 register enables address translation from
155  linear to physical addresses.
156  http://en.wikipedia.org/wiki/Control_register#Control_registers_in_x86_series
157 */
158 void load_page_dir(page_dir *new_dir)
159 {
160  cdir = new_dir;
161  asm volatile ("mov %0,%%cr3":: "b"(&cdir->tables_phys[0]));
162  u32int cr0;
163  asm volatile ("mov %%cr0,%0": "=b"(cr0));
164  cr0 |= 0x80000000;
165  asm volatile ("mov %0,%%cr0":: "b"(cr0));
166 }
167 
168 /*
169  Procedure..: new_frame
170  Description..: Marks a frame as in use in the frame bitmap,
171  sets up the page, and saves the frame index in the page.
172 */
174 {
175  u32int index;
176  if (page->frameaddr != 0) return;
177  if ( (u32int)(-1) == (index=find_free()) ) kpanic("Out of memory");
178 
179  //mark a frame as in-use
180  set_bit(index*page_size);
181  page->present = 1;
182  page->frameaddr = index;
183  page->writeable = 1;
184  page->usermode = 0;
185 }
u32int frameaddr
Definition: paging.h:19
page_dir * cdir
Definition: paging.c:22
#define KHEAP_SIZE
Definition: heap.h:8
void kpanic(const char *msg)
Definition: system.c:24
u32int kmalloc(u32int size)
Definition: heap.c:52
void load_page_dir(page_dir *new_dir)
Definition: paging.c:158
Definition: paging.h:12
u32int present
Definition: paging.h:13
u32int mem_size
Definition: paging.c:15
u32int phys_alloc_addr
Definition: heap.c:22
u32int _kmalloc(u32int size, int align, u32int *phys_addr)
Definition: heap.c:24
#define KHEAP_MIN
Definition: heap.h:7
u32int usermode
Definition: paging.h:15
u32int page_size
Definition: paging.c:16
u32int * frames
Definition: paging.c:19
page_entry * get_page(u32int addr, page_dir *dir, int make_table)
Definition: paging.c:85
u32int tables_phys[1024]
Definition: paging.h:36
page_table * tables[1024]
Definition: paging.h:35
u32int get_bit(u32int addr)
Definition: paging.c:56
heap * kheap
Definition: heap.c:14
u32int writeable
Definition: paging.h:14
#define PAGE_SIZE
Definition: paging.h:6
page_dir * kdir
Definition: paging.c:21
u32int nframes
Definition: paging.c:18
void set_bit(u32int addr)
Definition: paging.c:32
void clear_bit(u32int addr)
Definition: paging.c:44
heap * make_heap(u32int base, u32int max, u32int min)
Definition: heap.c:71
Definition: heap.h:33
unsigned long u32int
Definition: system.h:27
u32int find_free()
Definition: paging.c:68
#define KHEAP_BASE
Definition: heap.h:6
void init_paging()
Definition: paging.c:111
void * memset(void *s, int c, size_t n)
memset Set a region of memory.
Definition: string.c:139
page_entry pages[1024]
Definition: paging.h:27
void new_frame(page_entry *page)
Definition: paging.c:173