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