Hash table changes
[akaros.git] / kern / arch / i386 / pmap.c
1 #ifdef __SHARC__
2 #pragma nosharc
3 #define SINIT(x) x
4 #endif
5
6 /* See COPYRIGHT for copyright information. */
7 #include <arch/x86.h>
8 #include <arch/arch.h>
9 #include <arch/mmu.h>
10 #include <arch/apic.h>
11
12 #include <ros/error.h>
13 #include <sys/queue.h>
14
15 #include <atomic.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <pmap.h>
19 #include <kclock.h>
20 #include <env.h>
21 #include <stdio.h>
22 #include <kmalloc.h>
23 #include <page_alloc.h>
24
25 // These variables are set in i386_vm_init()
26 pde_t* boot_pgdir;              // Virtual address of boot time page directory
27 physaddr_t RO boot_cr3;         // Physical address of boot time page directory
28
29 // Global variables
30 page_t *RO pages = NULL;          // Virtual address of physical page array
31
32 // Global descriptor table.
33 //
34 // The kernel and user segments are identical (except for the DPL).
35 // To load the SS register, the CPL must equal the DPL.  Thus,
36 // we must duplicate the segments for the user and the kernel.
37 //
38 segdesc_t gdt[] =
39 {
40         // 0x0 - unused (always faults -- for trapping NULL far pointers)
41         SEG_NULL,
42
43         // 0x8 - kernel code segment
44         [GD_KT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 0),
45
46         // 0x10 - kernel data segment
47         [GD_KD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 0),
48
49         // 0x18 - user code segment
50         [GD_UT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 3),
51
52         // 0x20 - user data segment
53         [GD_UD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 3),
54
55         // 0x28 - tss, initialized in idt_init()
56         [GD_TSS >> 3] = SEG_NULL
57 };
58
59 pseudodesc_t gdt_pd = {
60         sizeof(gdt) - 1, (unsigned long) gdt
61 };
62
63 static int
64 nvram_read(int r)
65 {
66         return mc146818_read(r) | (mc146818_read(r + 1) << 8);
67 }
68
69 bool enable_pse(void)
70 {
71         uint32_t edx, cr4;
72         cpuid(1, 0, 0, 0, &edx);
73         if (edx & CPUID_PSE_SUPPORT) {
74                 cr4 = rcr4();
75                 cr4 |= CR4_PSE;
76                 lcr4(cr4);
77                 return 1;
78         } else
79                 return 0;
80 }
81
82 // --------------------------------------------------------------
83 // Set up initial memory mappings and turn on MMU.
84 // --------------------------------------------------------------
85
86 static void check_boot_pgdir(bool pse);
87
88 //
89 // Given pgdir, a pointer to a page directory,
90 // walk the 2-level page table structure to find
91 // the page table entry (PTE) for linear address la.
92 // Return a pointer to this PTE.
93 //
94 // If the relevant page table doesn't exist in the page directory:
95 //      - If create == 0, return 0.
96 //      - Otherwise allocate a new page table, install it into pgdir,
97 //        and return a pointer into it.
98 //        (Questions: What data should the new page table contain?
99 //        And what permissions should the new pgdir entry have?
100 //        Note that we use the 486-only "WP" feature of %cr0, which
101 //        affects the way supervisor-mode writes are checked.)
102 //
103 // This function abstracts away the 2-level nature of
104 // the page directory by allocating new page tables
105 // as needed.
106 // 
107 // boot_pgdir_walk may ONLY be used during initialization,
108 // before the page_free_list has been set up.
109 // It should panic on failure.  (Note that boot_alloc already panics
110 // on failure.)
111 //
112 // Supports returning jumbo (4MB PSE) PTEs.  To create with a jumbo, pass in 2.
113 // 
114 // Maps non-PSE PDEs as U/W.  W so the kernel can, U so the user can read via
115 // UVPT.  UVPT security comes from the UVPT mapping (U/R).  All other kernel pages
116 // protected at the second layer
117 static pte_t*
118 boot_pgdir_walk(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t la, int create)
119 {
120         pde_t* the_pde = &pgdir[PDX(la)];
121         void* new_table;
122
123         if (*the_pde & PTE_P) {
124                 if (*the_pde & PTE_PS)
125                         return (pte_t*)the_pde;
126                 return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(la)];
127         }
128         if (!create)
129                 return NULL;
130         if (create == 2) {
131                 if (JPGOFF(la))
132                         panic("Attempting to find a Jumbo PTE at an unaligned VA!");
133                 *the_pde = PTE_PS | PTE_P;
134                 return (pte_t*)the_pde;
135         }
136         new_table = boot_alloc(PGSIZE, PGSIZE);
137         memset(new_table, 0, PGSIZE);
138         *the_pde = (pde_t)PADDR(new_table) | PTE_P | PTE_W | PTE_U | PTE_G;
139         return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(la)];
140 }
141
142 //
143 // Map [la, la+size) of linear address space to physical [pa, pa+size)
144 // in the page table rooted at pgdir.  Size is a multiple of PGSIZE.
145 // Use permission bits perm|PTE_P for the entries.
146 //
147 // This function may ONLY be used during initialization,
148 // before the page_free_list has been set up.
149 //
150 // To map with Jumbos, set PTE_PS in perm
151 static void
152 boot_map_segment(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t la, size_t size, physaddr_t pa, int perm)
153 {
154         uintptr_t i;
155         pte_t *pte;
156         // la can be page unaligned, but weird things will happen
157         // unless pa has the same offset.  pa always truncates any
158         // possible offset.  will warn.  size can be weird too. 
159         if (PGOFF(la)) {
160                 warn("la not page aligned in boot_map_segment!");
161                 size += PGOFF(la);
162         }
163         if (perm & PTE_PS) {
164                 if (JPGOFF(la) || JPGOFF(pa))
165                         panic("Tried to map a Jumbo page at an unaligned address!");
166                 // need to index with i instead of la + size, in case of wrap-around
167                 for (i = 0; i < size; i += JPGSIZE, la += JPGSIZE, pa += JPGSIZE) {
168                         pte = boot_pgdir_walk(pgdir, la, 2);
169                         *pte = PTE_ADDR(pa) | PTE_P | perm;
170                 }
171         } else {
172                 for (i = 0; i < size; i += PGSIZE, la += PGSIZE, pa += PGSIZE) {
173                         pte = boot_pgdir_walk(pgdir, la, 1);
174                         if (*pte & PTE_PS)
175                                 // if we start using the extra flag for PAT, which we aren't,
176                                 // this will warn, since PTE_PS and PTE_PAT are the same....
177                                 warn("Possibly attempting to map a regular page into a Jumbo PDE");
178                         *pte = PTE_ADDR(pa) | PTE_P | perm;
179                 }
180         }
181 }
182
183 // could consider having an API to allow these to dynamically change
184 // MTRRs are for physical, static ranges.  PAT are linear, more granular, and 
185 // more dynamic
186 void setup_default_mtrrs(barrier_t* smp_barrier)
187 {
188         // disable interrupts
189         int8_t state = 0;
190         disable_irqsave(&state);
191         // barrier - if we're meant to do this for all cores, we'll be 
192         // passed a pointer to an initialized barrier
193         if (smp_barrier)
194                 waiton_barrier(smp_barrier);
195         
196         // disable caching      cr0: set CD and clear NW
197         lcr0((rcr0() | CR0_CD) & ~CR0_NW);
198         // flush caches
199         cache_flush();
200         // flush tlb
201         tlb_flush_global();
202         // disable MTRRs, and sets default type to WB (06)
203         write_msr(IA32_MTRR_DEF_TYPE, 0x00000006);
204
205         // Now we can actually safely adjust the MTRRs
206         // MTRR for IO Holes (note these are 64 bit values we are writing)
207         // 0x000a0000 - 0x000c0000 : VGA - WC 0x01
208         write_msr(IA32_MTRR_PHYSBASE0, PTE_ADDR(VGAPHYSMEM) | 0x01);
209         // if we need to have a full 64bit val, use the UINT64 macro
210         write_msr(IA32_MTRR_PHYSMASK0, 0x0000000ffffe0800);
211         // 0x000c0000 - 0x00100000 : IO devices (and ROM BIOS) - UC 0x00
212         write_msr(IA32_MTRR_PHYSBASE1, PTE_ADDR(DEVPHYSMEM) | 0x00);
213         write_msr(IA32_MTRR_PHYSMASK1, 0x0000000ffffc0800);
214         // APIC/IOAPIC holes
215         /* Going to skip them, since we set their mode using PAT when we 
216          * map them in 
217          */
218         // make sure all other MTRR ranges are disabled (should be unnecessary)
219         write_msr(IA32_MTRR_PHYSMASK2, 0);
220         write_msr(IA32_MTRR_PHYSMASK3, 0);
221         write_msr(IA32_MTRR_PHYSMASK4, 0);
222         write_msr(IA32_MTRR_PHYSMASK5, 0);
223         write_msr(IA32_MTRR_PHYSMASK6, 0);
224         write_msr(IA32_MTRR_PHYSMASK7, 0);
225
226         // keeps default type to WB (06), turns MTRRs on, and turns off fixed ranges
227         write_msr(IA32_MTRR_DEF_TYPE, 0x00000806);
228         // reflush caches and TLB
229         cache_flush();
230         tlb_flush_global();
231         // turn on caching
232         lcr0(rcr0() & ~(CR0_CD | CR0_NW));
233         // barrier
234         if (smp_barrier)
235                 waiton_barrier(smp_barrier);
236         // enable interrupts
237         enable_irqsave(&state);
238 }
239
240
241 // Set up a two-level page table:
242 //    boot_pgdir is its linear (virtual) address of the root
243 //    boot_cr3 is the physical adresss of the root
244 // Then turn on paging.  Then effectively turn off segmentation.
245 // (i.e., the segment base addrs are set to zero).
246 // 
247 // This function only sets up the kernel part of the address space
248 // (ie. addresses >= UTOP).  The user part of the address space
249 // will be setup later.
250 //
251 // From UTOP to ULIM, the user is allowed to read but not write.
252 // Above ULIM the user cannot read (or write). 
253 void
254 vm_init(void)
255 {
256         pde_t* pgdir;
257         uint32_t cr0, edx;
258         size_t n;
259         bool pse;
260
261         pse = enable_pse();
262         if (pse)
263                 cprintf("PSE capability detected.\n");
264
265         // we paniced earlier if we don't support PGE.  turn it on now.
266         // it's used in boot_map_segment, which covers all of the mappings that are
267         // the same for all address spaces.  and also for the VPT mapping below.
268         lcr4(rcr4() | CR4_PGE);
269
270         // set up mtrr's for core0.  other cores will do the same later
271         setup_default_mtrrs(0);
272
273         /*
274          * PSE status: 
275          * - can walk and set up boot_map_segments with jumbos but can't
276          *   insert yet.  need to look at the page_dir and friends.
277          * - anything related to a single struct Page still can't handle 
278          *   jumbos.  will need to think about and adjust Page functions
279          * - do we want to store info like this in the struct Page?  or just check
280          *   by walking the PTE
281          * - when we alloc a page, and we want it to be 4MB, we'll need
282          *   to have contiguous memory, etc
283          * - there's a difference between having 4MB page table entries
284          *   and having 4MB Page tracking structs.  changing the latter will
285          *   break a lot of things
286          * - showmapping and friends work on a 4KB granularity, but map to the
287          *   correct entries
288          * - need to not insert / boot_map a single page into an area that is 
289          *   already holding a jumbo page.  will need to break the jumbo up so that
290          *   we can then insert the lone page.  currently warns.
291          * - some inherent issues with the pgdir_walks returning a PTE, and we
292          *   don't know whether it is a jumbo (PDE) or a regular PTE.
293          */
294
295         //////////////////////////////////////////////////////////////////////
296         // create initial page directory.
297         pgdir = boot_alloc(PGSIZE, PGSIZE);
298         memset(pgdir, 0, PGSIZE);
299         boot_pgdir = pgdir;
300         boot_cr3 = PADDR(pgdir);
301         // helpful if you want to manually walk with kvm / bochs
302         //printk("pgdir va = %08p, pgdir pa = %08p\n\n", pgdir, PADDR(pgdir));
303
304         //////////////////////////////////////////////////////////////////////
305         // Recursively insert PD in itself as a page table, to form
306         // a virtual page table at virtual address VPT.
307         // (For now, you don't have understand the greater purpose of the
308         // following two lines.  Unless you are eagle-eyed, in which case you
309         // should already know.)
310
311         // Permissions: kernel RW, user NONE, Global Page
312         pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_W | PTE_P | PTE_G;
313
314         // same for UVPT
315         // Permissions: kernel R, user R, Global Page
316         pgdir[PDX(UVPT)] = PADDR(pgdir) | PTE_U | PTE_P | PTE_G;
317
318         //////////////////////////////////////////////////////////////////////
319         // Map the kernel stack (symbol name "bootstack").  The complete VA
320         // range of the stack, [KSTACKTOP-PTSIZE, KSTACKTOP), breaks into two
321         // pieces:
322         //     * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory
323         //     * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed => faults
324         //     Permissions: kernel RW, user NONE
325         // Your code goes here:
326
327         // remember that the space for the kernel stack is allocated in the binary.
328         // bootstack and bootstacktop point to symbols in the data section, which 
329         // at this point are like 0xc010b000.  KSTACKTOP is the desired loc in VM
330         boot_map_segment(pgdir, (uintptr_t)KSTACKTOP - KSTKSIZE, 
331                          KSTKSIZE, PADDR(bootstack), PTE_W | PTE_G);
332
333         //////////////////////////////////////////////////////////////////////
334         // Map all of physical memory at KERNBASE. 
335         // Ie.  the VA range [KERNBASE, 2^32) should map to
336         //      the PA range [0, 2^32 - KERNBASE)
337         // We might not have 2^32 - KERNBASE bytes of physical memory, but
338         // we just set up the mapping anyway.
339         // Permissions: kernel RW, user NONE
340         // Your code goes here: 
341         
342         // this maps all of the possible phys memory
343         // note the use of unsigned underflow to get size = 0x40000000
344         //boot_map_segment(pgdir, KERNBASE, -KERNBASE, 0, PTE_W);
345         // but this only maps what is available, and saves memory.  every 4MB of
346         // mapped memory requires a 2nd level page: 2^10 entries, each covering 2^12
347         // need to modify tests below to account for this
348         if (pse) {
349                 // map the first 4MB as regular entries, to support different MTRRs
350                 boot_map_segment(pgdir, KERNBASE, JPGSIZE, 0, PTE_W | PTE_G);
351                 boot_map_segment(pgdir, KERNBASE + JPGSIZE, maxaddrpa - JPGSIZE, JPGSIZE,
352                                  PTE_W | PTE_G | PTE_PS);
353         } else
354                 boot_map_segment(pgdir, KERNBASE, maxaddrpa, 0, PTE_W | PTE_G);
355
356         // APIC mapping: using PAT (but not *the* PAT flag) to make these type UC
357         // IOAPIC
358         boot_map_segment(pgdir, (uintptr_t)IOAPIC_BASE, PGSIZE, IOAPIC_BASE, 
359                          PTE_PCD | PTE_PWT | PTE_W | PTE_G);
360         // Local APIC
361         boot_map_segment(pgdir, (uintptr_t)LAPIC_BASE, PGSIZE, LAPIC_BASE,
362                          PTE_PCD | PTE_PWT | PTE_W | PTE_G);
363
364         //////////////////////////////////////////////////////////////////////
365         // Make 'envs' point to an array of size 'NENV' of 'env_t'.
366         // No longer mapping ENVS into the address space
367         
368         // round up to the nearest page
369         size_t env_array_size = ROUNDUP(NENV*sizeof(env_t), PGSIZE);
370         env_t * tmpenv = (env_t *)boot_calloc(env_array_size, 1, PGSIZE);
371         envs = SINIT(tmpenv);
372         //memset(envs, 0, env_array_size);
373
374         // Check that the initial page directory has been set up correctly.
375         check_boot_pgdir(pse);
376
377         //////////////////////////////////////////////////////////////////////
378         // On x86, segmentation maps a VA to a LA (linear addr) and
379         // paging maps the LA to a PA.  I.e. VA => LA => PA.  If paging is
380         // turned off the LA is used as the PA.  Note: there is no way to
381         // turn off segmentation.  The closest thing is to set the base
382         // address to 0, so the VA => LA mapping is the identity.
383
384         // Current mapping: VA KERNBASE+x => PA x.
385         //     (segmentation base=-KERNBASE and paging is off)
386
387         // From here on down we must maintain this VA KERNBASE + x => PA x
388         // mapping, even though we are turning on paging and reconfiguring
389         // segmentation.
390
391         // Map VA 0:4MB same as VA KERNBASE, i.e. to PA 0:4MB.
392         // (Limits our kernel to <4MB)
393         /* They mean linear address 0:4MB, and the kernel < 4MB is only until 
394          * segmentation is turned off.
395          * once we turn on paging, segmentation is still on, so references to
396          * KERNBASE+x will get mapped to linear address x, which we need to make 
397          * sure can map to phys addr x, until we can turn off segmentation and
398          * KERNBASE+x maps to LA KERNBASE+x, which maps to PA x, via paging
399          */
400         pgdir[0] = pgdir[PDX(KERNBASE)];
401
402         // Install page table.
403         lcr3(boot_cr3);
404
405         // Turn on paging.
406         cr0 = rcr0();
407         // CD and NW should already be on, but just in case these turn on caching
408         cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_MP;
409         cr0 &= ~(CR0_TS|CR0_EM|CR0_CD|CR0_NW);
410         lcr0(cr0);
411
412         // Current mapping: KERNBASE+x => x => x.
413         // (x < 4MB so uses paging pgdir[0])
414
415         // Reload all segment registers.
416         asm volatile("lgdt gdt_pd");
417         asm volatile("movw %%ax,%%gs" :: "a" (GD_UD|3));
418         asm volatile("movw %%ax,%%fs" :: "a" (GD_UD|3));
419         asm volatile("movw %%ax,%%es" :: "a" (GD_KD));
420         asm volatile("movw %%ax,%%ds" :: "a" (GD_KD));
421         asm volatile("movw %%ax,%%ss" :: "a" (GD_KD));
422         asm volatile("ljmp %0,$1f\n 1:\n" :: "i" (GD_KT));  // reload cs
423         asm volatile("lldt %%ax" :: "a" (0));
424
425         // Final mapping: KERNBASE+x => KERNBASE+x => x.
426
427         // This mapping was only used after paging was turned on but
428         // before the segment registers were reloaded.
429         pgdir[0] = 0;
430
431         // Flush the TLB for good measure, to kill the pgdir[0] mapping.
432         tlb_flush_global();
433 }
434
435 //
436 // Checks that the kernel part of virtual address space
437 // has been setup roughly correctly(by i386_vm_init()).
438 //
439 // This function doesn't test every corner case,
440 // in fact it doesn't test the permission bits at all,
441 // but it is a pretty good sanity check. 
442 //
443 static physaddr_t check_va2pa(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t va);
444
445 static void
446 check_boot_pgdir(bool pse)
447 {
448         uint32_t i, n;
449         pde_t *pgdir, pte;
450
451         pgdir = boot_pgdir;
452
453         // check phys mem
454         //for (i = 0; KERNBASE + i != 0; i += PGSIZE)
455         // adjusted check to account for only mapping avail mem
456         if (pse)
457                 for (i = 0; i < maxaddrpa; i += JPGSIZE)
458                         assert(check_va2pa(pgdir, KERNBASE + i) == i);
459         else
460                 for (i = 0; i < maxaddrpa; i += PGSIZE)
461                         assert(check_va2pa(pgdir, KERNBASE + i) == i);
462
463         // check kernel stack
464         for (i = 0; i < KSTKSIZE; i += PGSIZE)
465                 assert(check_va2pa(pgdir, KSTACKTOP - KSTKSIZE + i) == PADDR(bootstack) + i);
466
467         // check for zero/non-zero in PDEs
468         for (i = 0; i < NPDENTRIES; i++) {
469                 switch (i) {
470                 case PDX(VPT):
471                 case PDX(UVPT):
472                 case PDX(KSTACKTOP-1):
473                 case PDX(LAPIC_BASE): // LAPIC mapping.  TODO: remove when MTRRs are up
474                         assert(pgdir[i]);
475                         break;
476                 default:
477                         //if (i >= PDX(KERNBASE))
478                         // adjusted check to account for only mapping avail mem
479                         // and you can't KADDR maxpa (just above legal range)
480                         // maxaddrpa can be up to maxpa, so assume the worst
481                         if (i >= PDX(KERNBASE) && i <= PDX(KADDR(maxaddrpa-1)))
482                                 assert(pgdir[i]);
483                         else
484                                 assert(pgdir[i] == 0);
485                         break;
486                 }
487         }
488
489         /* check permissions
490          * user read-only.  check for user and write, should be only user
491          * eagle-eyed viewers should be able to explain the extra cases.
492          * for the mongoose-eyed, remember that weird shit happens when you loop
493          * through UVPT.  Specifically, you can't loop once, then look at a jumbo
494          * page that is kernel only.  That's the end of the page table for you, so
495          * having a U on the entry doesn't make sense.  Thus we check for a jumbo
496          * page, and special case it.  This will happen at 0xbf701000.  Why is this
497          * magical?  Get your eagle glasses and figure it out. */
498         for (i = UTOP; i < ULIM; i+=PGSIZE) {
499                 pte = get_va_perms(pgdir, (void*SAFE)TC(i));
500                 if (pte & PTE_P) {
501                         if (i == UVPT+(VPT >> 10))
502                                 continue;
503                         if (*pgdir_walk(pgdir, (void*SAFE)TC(i), 0) & PTE_PS) {
504                                 assert((pte & PTE_U) != PTE_U);
505                                 assert((pte & PTE_W) != PTE_W);
506                         } else {
507                                 assert((pte & PTE_U) == PTE_U);
508                                 assert((pte & PTE_W) != PTE_W);
509                         }
510                 }
511         }
512         // kernel read-write.
513         for (i = ULIM; i <= KERNBASE + maxaddrpa - PGSIZE; i+=PGSIZE) {
514                 pte = get_va_perms(pgdir, (void*SAFE)TC(i));
515                 if ((pte & PTE_P) && (i != VPT+(UVPT>>10))) {
516                         assert((pte & PTE_U) != PTE_U);
517                         assert((pte & PTE_W) == PTE_W);
518                 }
519         }
520         // special mappings
521         pte = get_va_perms(pgdir, (void*SAFE)TC(UVPT+(VPT>>10)));
522         assert((pte & PTE_U) != PTE_U);
523         assert((pte & PTE_W) != PTE_W);
524
525         // note this means the kernel cannot directly manipulate this virtual address
526         // convince yourself this isn't a big deal, eagle-eyes!
527         pte = get_va_perms(pgdir, (void*SAFE)TC(VPT+(UVPT>>10)));
528         assert((pte & PTE_U) != PTE_U);
529         assert((pte & PTE_W) != PTE_W);
530
531         cprintf("check_boot_pgdir() succeeded!\n");
532 }
533
534 // This function returns the physical address of the page containing 'va',
535 // defined by the page directory 'pgdir'.  The hardware normally performs
536 // this functionality for us!  We define our own version to help check
537 // the check_boot_pgdir() function; it shouldn't be used elsewhere.
538
539 static physaddr_t
540 check_va2pa(pde_t *COUNT(NPDENTRIES) _pgdir, uintptr_t va)
541 {
542         pte_t *COUNT(NPTENTRIES) p;
543         pde_t *COUNT(1) pgdir;
544
545         pgdir = &_pgdir[PDX(va)];
546         if (!(*pgdir & PTE_P))
547                 return ~0;
548         if (*pgdir & PTE_PS)
549                 return PTE_ADDR(*pgdir);
550         p = (pte_t*COUNT(NPTENTRIES)) KADDR(PTE_ADDR(*pgdir));
551         if (!(p[PTX(va)] & PTE_P))
552                 return ~0;
553         return PTE_ADDR(p[PTX(va)]);
554 }
555
556 /* 
557  * Remove the second level page table associated with virtual address va.
558  * Will 0 out the PDE for that page table.
559  * Panics if the page table has any present entries.
560  * This should be called rarely and with good cause.
561  * Currently errors if the PDE is jumbo or not present.
562  */
563 error_t pagetable_remove(pde_t *pgdir, void *va)
564 {
565         pde_t* the_pde = &pgdir[PDX(va)];
566
567         if (!(*the_pde & PTE_P) || (*the_pde & PTE_PS))
568                 return -EFAULT;
569         pte_t* page_table = (pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde));
570         for (int i = 0; i < NPTENTRIES; i++) 
571                 if (page_table[i] & PTE_P)
572                         panic("Page table not empty during attempted removal!");
573         *the_pde = 0;
574         page_decref(pa2page(PADDR(page_table)));
575         return 0;
576 }
577
578 // Given 'pgdir', a pointer to a page directory, pgdir_walk returns
579 // a pointer to the page table entry (PTE) for linear address 'va'.
580 // This requires walking the two-level page table structure.
581 //
582 // If the relevant page table doesn't exist in the page directory, then:
583 //    - If create == 0, pgdir_walk returns NULL.
584 //    - Otherwise, pgdir_walk tries to allocate a new page table
585 //      with page_alloc.  If this fails, pgdir_walk returns NULL.
586 //    - Otherwise, pgdir_walk returns a pointer into the new page table.
587 //
588 // This is boot_pgdir_walk, but using page_alloc() instead of boot_alloc().
589 // Unlike boot_pgdir_walk, pgdir_walk can fail.
590 //
591 // Hint: you can turn a Page * into the physical address of the
592 // page it refers to with page2pa() from kern/pmap.h.
593 //
594 // Supports returning jumbo (4MB PSE) PTEs.  To create with a jumbo, pass in 2.
595 pte_t*
596 pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
597 {
598         pde_t* the_pde = &pgdir[PDX(va)];
599         page_t *new_table;
600
601         if (*the_pde & PTE_P) {
602                 if (*the_pde & PTE_PS)
603                         return (pte_t*)the_pde;
604                 return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(va)];
605         }
606         if (!create)
607                 return NULL;
608         if (create == 2) {
609                 if (JPGOFF(va))
610                         panic("Attempting to find a Jumbo PTE at an unaligned VA!");
611                 *the_pde = PTE_PS | PTE_P;
612                 return (pte_t*)the_pde;
613         }
614         if (page_alloc(&new_table))
615                 return NULL;
616         page_setref(new_table,1);
617         memset(page2kva(new_table), 0, PGSIZE);
618         *the_pde = (pde_t)page2pa(new_table) | PTE_P | PTE_W | PTE_U;
619         return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(va)];
620 }
621
622 /* Returns the effective permissions for PTE_U, PTE_W, and PTE_P on a given
623  * virtual address.  Note we need to consider the composition of every PTE in
624  * the page table walk. */
625 int get_va_perms(pde_t *pgdir, const void *SNT va)
626 {
627         pde_t the_pde = pgdir[PDX(va)];
628         pte_t the_pte;
629
630         if (!(the_pde & PTE_P))
631                 return 0;
632         if (the_pde & PTE_PS)
633                 return the_pde & (PTE_U | PTE_W | PTE_P);
634         the_pte = ((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(the_pde)))[PTX(va)];
635         if (!(the_pte & PTE_P))
636                 return 0;
637         return the_pte & the_pde & (PTE_U | PTE_W | PTE_P);
638 }
639
640 void *get_free_va_range(pde_t *pgdir, uintptr_t addr, size_t len)
641 {
642 {TRUSTEDBLOCK
643         // want to make sure there aren't mappings already.  will need to do this
644         // later with zones, for when we lazily allocate memory
645
646         uintptr_t startaddr;
647
648         int npages = ROUNDUP(len, PGSIZE) / PGSIZE;
649
650         addr &= ~0xfff;
651         if (!addr)
652                 // some sensible default.  can cache the previous value somewhere
653                 addr = USTACKTOP - PGSIZE; // TODO: not looking down
654         startaddr = addr;       
655         pte_t *pte = pgdir_walk(pgdir, (void*)addr, 0);
656         // what about jumbo pages?
657         // consider looping around, esp if we start from a cached spot
658         // don't map at pg 0, or below brk
659         // consider local memory ranges...
660
661         /*
662         first fit?
663         what if we have a sorted structure of what mem ranges are already in use?
664         */
665
666         return (void*)0xdeadbeef;
667 }
668 }
669
670 /* Flushes a TLB, including global pages.  We should always have the CR4_PGE
671  * flag set, but just in case, we'll check.  Toggling this bit flushes the TLB.
672  */
673 void tlb_flush_global(void)
674 {
675         uint32_t cr4 = rcr4();
676         if (cr4 & CR4_PGE) {
677                 lcr4(cr4 & ~CR4_PGE);
678                 lcr4(cr4);
679         } else 
680                 lcr3(rcr3());
681 }
682
683 void
684 page_check(void)
685 {
686         page_t *pp, *pp0, *pp1, *pp2;
687         page_list_t fl[1024];
688         pte_t *ptep;
689
690         // should be able to allocate three pages
691         pp0 = pp1 = pp2 = 0;
692         assert(page_alloc(&pp0) == 0);
693         assert(page_alloc(&pp1) == 0);
694         assert(page_alloc(&pp2) == 0);
695
696         assert(pp0);
697         assert(pp1 && pp1 != pp0);
698         assert(pp2 && pp2 != pp1 && pp2 != pp0);
699
700         // temporarily steal the rest of the free pages
701         for(int i=0; i<llc_num_colors; i++) {
702                 fl[i] = colored_page_free_list[i];
703                 LIST_INIT(&colored_page_free_list[i]);
704         }
705
706         // should be no free memory
707         assert(page_alloc(&pp) == -ENOMEM);
708
709         // Fill pp1 with bogus data and check for invalid tlb entries
710         memset(page2kva(pp1), 0xFFFFFFFF, PGSIZE);
711
712         // there is no page allocated at address 0
713         assert(page_lookup(boot_pgdir, (void *) 0x0, &ptep) == NULL);
714
715         // there is no free memory, so we can't allocate a page table 
716         assert(page_insert(boot_pgdir, pp1, 0x0, 0) < 0);
717
718         // free pp0 and try again: pp0 should be used for page table
719         page_free(pp0);
720         assert(page_insert(boot_pgdir, pp1, 0x0, 0) == 0);
721         tlb_invalidate(boot_pgdir, 0x0);
722         // DEP Should have shot down invalid TLB entry - let's check
723         { TRUSTEDBLOCK
724           int *x = 0x0;
725           assert(*x == 0xFFFFFFFF);
726         }
727         assert(PTE_ADDR(boot_pgdir[0]) == page2pa(pp0));
728         assert(check_va2pa(boot_pgdir, 0x0) == page2pa(pp1));
729         assert(pp1->page_ref == 1);
730         assert(pp0->page_ref == 1);
731
732         // should be able to map pp2 at PGSIZE because pp0 is already allocated for page table
733         assert(page_insert(boot_pgdir, pp2, (void*SNT) PGSIZE, 0) == 0);
734         assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp2));
735         assert(pp2->page_ref == 1);
736
737         // Make sure that pgdir_walk returns a pointer to the pte and
738         // not the table or some other garbage
739         {
740           pte_t *p = (pte_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(boot_pgdir[PDX(PGSIZE)]));
741           assert(pgdir_walk(boot_pgdir, (void *SNT)PGSIZE, 0) == &p[PTX(PGSIZE)]);
742         }
743
744         // should be no free memory
745         assert(page_alloc(&pp) == -ENOMEM);
746
747         // should be able to map pp2 at PGSIZE because it's already there
748         assert(page_insert(boot_pgdir, pp2, (void*SNT) PGSIZE, PTE_U) == 0);
749         assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp2));
750         assert(pp2->page_ref == 1);
751
752         // Make sure that we actually changed the permission on pp2 when we re-mapped it
753         {
754           pte_t *p = pgdir_walk(boot_pgdir, (void*SNT)PGSIZE, 0);
755           assert(((*p) & PTE_U) == PTE_U);
756         }
757
758         // pp2 should NOT be on the free list
759         // could happen in ref counts are handled sloppily in page_insert
760         assert(page_alloc(&pp) == -ENOMEM);
761
762         // should not be able to map at PTSIZE because need free page for page table
763         assert(page_insert(boot_pgdir, pp0, (void*SNT) PTSIZE, 0) < 0);
764
765         // insert pp1 at PGSIZE (replacing pp2)
766         assert(page_insert(boot_pgdir, pp1, (void*SNT) PGSIZE, 0) == 0);
767
768         // should have pp1 at both 0 and PGSIZE, pp2 nowhere, ...
769         assert(check_va2pa(boot_pgdir, 0) == page2pa(pp1));
770         assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp1));
771         // ... and ref counts should reflect this
772         assert(pp1->page_ref == 2);
773         assert(pp2->page_ref == 0);
774
775         // pp2 should be returned by page_alloc
776         assert(page_alloc(&pp) == 0 && pp == pp2);
777
778         // unmapping pp1 at 0 should keep pp1 at PGSIZE
779         page_remove(boot_pgdir, 0x0);
780         assert(check_va2pa(boot_pgdir, 0x0) == ~0);
781         assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp1));
782         assert(pp1->page_ref == 1);
783         assert(pp2->page_ref == 0);
784
785         // unmapping pp1 at PGSIZE should free it
786         page_remove(boot_pgdir, (void*SNT) PGSIZE);
787         assert(check_va2pa(boot_pgdir, 0x0) == ~0);
788         assert(check_va2pa(boot_pgdir, PGSIZE) == ~0);
789         assert(pp1->page_ref == 0);
790         assert(pp2->page_ref == 0);
791
792         // so it should be returned by page_alloc
793         assert(page_alloc(&pp) == 0 && pp == pp1);
794
795         // should be no free memory
796         assert(page_alloc(&pp) == -ENOMEM);
797
798         // forcibly take pp0 back
799         assert(PTE_ADDR(boot_pgdir[0]) == page2pa(pp0));
800         boot_pgdir[0] = 0;
801         assert(pp0->page_ref == 1);
802         pp0->page_ref = 0;
803
804         // Catch invalid pointer addition in pgdir_walk - i.e. pgdir + PDX(va)
805         {
806           // Give back pp0 for a bit
807           page_free(pp0);
808
809           void *SNT va = (void *SNT)((PGSIZE * NPDENTRIES) + PGSIZE);
810           pte_t *p2 = pgdir_walk(boot_pgdir, va, 1);
811           pte_t *p = (pte_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(boot_pgdir[PDX(va)]));
812           assert(p2 == &p[PTX(va)]);
813
814           // Clean up again
815           boot_pgdir[PDX(va)] = 0;
816           pp0->page_ref = 0;
817         }
818
819         // give free list back
820         for(int i=0; i<llc_num_colors; i++)
821                 colored_page_free_list[i] = fl[i];
822
823         // free the pages we took
824         page_free(pp0);
825         page_free(pp1);
826         page_free(pp2);
827
828         cprintf("page_check() succeeded!\n");
829 }
830
831 /* 
832
833     // testing code for boot_pgdir_walk 
834         pte_t* temp;
835         temp = boot_pgdir_walk(pgdir, VPT + (VPT >> 10), 1);
836         cprintf("pgdir = %p\n", pgdir);
837         cprintf("test recursive walking pte_t* = %p\n", temp);
838         cprintf("test recursive walking entry = %p\n", PTE_ADDR(temp));
839         temp = boot_pgdir_walk(pgdir, 0xc0400000, 1);
840         cprintf("LA = 0xc0400000 = %p\n", temp);
841         temp = boot_pgdir_walk(pgdir, 0xc0400070, 1);
842         cprintf("LA = 0xc0400070 = %p\n", temp);
843         temp = boot_pgdir_walk(pgdir, 0xc0800000, 0);
844         cprintf("LA = 0xc0800000, no create = %p\n", temp);
845         temp = boot_pgdir_walk(pgdir, 0xc0600070, 1);
846         cprintf("LA = 0xc0600070 = %p\n", temp);
847         temp = boot_pgdir_walk(pgdir, 0xc0600090, 0);
848         cprintf("LA = 0xc0600090, nc = %p\n", temp);
849         temp = boot_pgdir_walk(pgdir, 0xc0608070, 0);
850         cprintf("LA = 0xc0608070, nc = %p\n", temp);
851         temp = boot_pgdir_walk(pgdir, 0xc0800070, 1);
852         cprintf("LA = 0xc0800070 = %p\n", temp);
853         temp = boot_pgdir_walk(pgdir, 0xc0b00070, 0);
854         cprintf("LA = 0xc0b00070, nc = %p\n", temp);
855         temp = boot_pgdir_walk(pgdir, 0xc0c00000, 0);
856         cprintf("LA = 0xc0c00000, nc = %p\n", temp);
857
858         // testing for boot_map_seg
859         cprintf("\n");
860         cprintf("before mapping 1 page to 0x00350000\n");
861         cprintf("0xc4000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc4000000, 1));
862         cprintf("0xc4000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc4000000, 1)));
863         boot_map_segment(pgdir, 0xc4000000, 4096, 0x00350000, PTE_W);
864         cprintf("after mapping\n");
865         cprintf("0xc4000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc4000000, 1));
866         cprintf("0xc4000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc4000000, 1)));
867
868         cprintf("\n");
869         cprintf("before mapping 3 pages to 0x00700000\n");
870         cprintf("0xd0000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0000000, 1));
871         cprintf("0xd0000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0000000, 1)));
872         cprintf("0xd0001000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0001000, 1));
873         cprintf("0xd0001000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0001000, 1)));
874         cprintf("0xd0002000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0002000, 1));
875         cprintf("0xd0002000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0002000, 1)));
876         boot_map_segment(pgdir, 0xd0000000, 4096*3, 0x00700000, 0);
877         cprintf("after mapping\n");
878         cprintf("0xd0000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0000000, 1));
879         cprintf("0xd0000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0000000, 1)));
880         cprintf("0xd0001000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0001000, 1));
881         cprintf("0xd0001000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0001000, 1)));
882         cprintf("0xd0002000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0002000, 1));
883         cprintf("0xd0002000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0002000, 1)));
884
885         cprintf("\n");
886         cprintf("before mapping 1 unaligned to 0x00500010\n");
887         cprintf("0xc8000010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8000010, 1));
888         cprintf("0xc8000010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8000010, 1)));
889         cprintf("0xc8001010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8001010, 1));
890         cprintf("0xc8001010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8001010, 1)));
891         boot_map_segment(pgdir, 0xc8000010, 4096, 0x00500010, PTE_W);
892         cprintf("after mapping\n");
893         cprintf("0xc8000010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8000010, 1));
894         cprintf("0xc8000010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8000010, 1)));
895         cprintf("0xc8001010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8001010, 1));
896         cprintf("0xc8001010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8001010, 1)));
897
898         cprintf("\n");
899         boot_map_segment(pgdir, 0xe0000000, 4096, 0x10000000, PTE_W);
900
901 */