6 /* See COPYRIGHT for copyright information. */
10 #include <arch/apic.h>
13 #include <sys/queue.h>
23 #include <page_alloc.h>
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
30 page_t *RO pages = NULL; // Virtual address of physical page array
32 // Global descriptor table.
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.
40 // 0x0 - unused (always faults -- for trapping NULL far pointers)
43 // 0x8 - kernel code segment
44 [GD_KT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 0),
46 // 0x10 - kernel data segment
47 [GD_KD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 0),
49 // 0x18 - user code segment
50 [GD_UT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 3),
52 // 0x20 - user data segment
53 [GD_UD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 3),
55 // 0x28 - tss, initialized in idt_init()
56 [GD_TSS >> 3] = SEG_NULL,
58 // 0x30 - LDT, set per-process
59 [GD_LDT >> 3] = SEG_NULL
62 pseudodesc_t gdt_pd = {
63 sizeof(gdt) - 1, (unsigned long) gdt
69 return mc146818_read(r) | (mc146818_read(r + 1) << 8);
75 cpuid(1, 0, 0, 0, &edx);
76 if (edx & CPUID_PSE_SUPPORT) {
85 // --------------------------------------------------------------
86 // Set up initial memory mappings and turn on MMU.
87 // --------------------------------------------------------------
89 static void check_boot_pgdir(bool pse);
92 // Given pgdir, a pointer to a page directory,
93 // walk the 2-level page table structure to find
94 // the page table entry (PTE) for linear address la.
95 // Return a pointer to this PTE.
97 // If the relevant page table doesn't exist in the page directory:
98 // - If create == 0, return 0.
99 // - Otherwise allocate a new page table, install it into pgdir,
100 // and return a pointer into it.
101 // (Questions: What data should the new page table contain?
102 // And what permissions should the new pgdir entry have?
103 // Note that we use the 486-only "WP" feature of %cr0, which
104 // affects the way supervisor-mode writes are checked.)
106 // This function abstracts away the 2-level nature of
107 // the page directory by allocating new page tables
110 // boot_pgdir_walk may ONLY be used during initialization,
111 // before the page_free_list has been set up.
112 // It should panic on failure. (Note that boot_alloc already panics
115 // Supports returning jumbo (4MB PSE) PTEs. To create with a jumbo, pass in 2.
117 // Maps non-PSE PDEs as U/W. W so the kernel can, U so the user can read via
118 // UVPT. UVPT security comes from the UVPT mapping (U/R). All other kernel pages
119 // protected at the second layer
121 boot_pgdir_walk(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t la, int create)
123 pde_t* the_pde = &pgdir[PDX(la)];
126 if (*the_pde & PTE_P) {
127 if (*the_pde & PTE_PS)
128 return (pte_t*)the_pde;
129 return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(la)];
135 panic("Attempting to find a Jumbo PTE at an unaligned VA!");
136 *the_pde = PTE_PS | PTE_P;
137 return (pte_t*)the_pde;
139 new_table = boot_alloc(PGSIZE, PGSIZE);
140 memset(new_table, 0, PGSIZE);
141 *the_pde = (pde_t)PADDR(new_table) | PTE_P | PTE_W | PTE_U | PTE_G;
142 return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(la)];
146 // Map [la, la+size) of linear address space to physical [pa, pa+size)
147 // in the page table rooted at pgdir. Size is a multiple of PGSIZE.
148 // Use permission bits perm|PTE_P for the entries.
150 // This function may ONLY be used during initialization,
151 // before the page_free_list has been set up.
153 // To map with Jumbos, set PTE_PS in perm
155 boot_map_segment(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t la, size_t size, physaddr_t pa, int perm)
159 // la can be page unaligned, but weird things will happen
160 // unless pa has the same offset. pa always truncates any
161 // possible offset. will warn. size can be weird too.
163 warn("la not page aligned in boot_map_segment!");
167 if (JPGOFF(la) || JPGOFF(pa))
168 panic("Tried to map a Jumbo page at an unaligned address!");
169 // need to index with i instead of la + size, in case of wrap-around
170 for (i = 0; i < size; i += JPGSIZE, la += JPGSIZE, pa += JPGSIZE) {
171 pte = boot_pgdir_walk(pgdir, la, 2);
172 *pte = PTE_ADDR(pa) | PTE_P | perm;
175 for (i = 0; i < size; i += PGSIZE, la += PGSIZE, pa += PGSIZE) {
176 pte = boot_pgdir_walk(pgdir, la, 1);
178 // if we start using the extra flag for PAT, which we aren't,
179 // this will warn, since PTE_PS and PTE_PAT are the same....
180 warn("Possibly attempting to map a regular page into a Jumbo PDE");
181 *pte = PTE_ADDR(pa) | PTE_P | perm;
186 // could consider having an API to allow these to dynamically change
187 // MTRRs are for physical, static ranges. PAT are linear, more granular, and
189 void setup_default_mtrrs(barrier_t* smp_barrier)
191 // disable interrupts
193 disable_irqsave(&state);
194 // barrier - if we're meant to do this for all cores, we'll be
195 // passed a pointer to an initialized barrier
197 waiton_barrier(smp_barrier);
199 // disable caching cr0: set CD and clear NW
200 lcr0((rcr0() | CR0_CD) & ~CR0_NW);
205 // disable MTRRs, and sets default type to WB (06)
206 #ifdef __CONFIG_NOMTRRS__
207 write_msr(IA32_MTRR_DEF_TYPE, 0x00000006);
209 // Now we can actually safely adjust the MTRRs
210 // MTRR for IO Holes (note these are 64 bit values we are writing)
211 // 0x000a0000 - 0x000c0000 : VGA - WC 0x01
212 write_msr(IA32_MTRR_PHYSBASE0, PTE_ADDR(VGAPHYSMEM) | 0x01);
213 // if we need to have a full 64bit val, use the UINT64 macro
214 write_msr(IA32_MTRR_PHYSMASK0, 0x0000000ffffe0800);
215 // 0x000c0000 - 0x00100000 : IO devices (and ROM BIOS) - UC 0x00
216 write_msr(IA32_MTRR_PHYSBASE1, PTE_ADDR(DEVPHYSMEM) | 0x00);
217 write_msr(IA32_MTRR_PHYSMASK1, 0x0000000ffffc0800);
219 /* Going to skip them, since we set their mode using PAT when we
222 // make sure all other MTRR ranges are disabled (should be unnecessary)
223 write_msr(IA32_MTRR_PHYSMASK2, 0);
224 write_msr(IA32_MTRR_PHYSMASK3, 0);
225 write_msr(IA32_MTRR_PHYSMASK4, 0);
226 write_msr(IA32_MTRR_PHYSMASK5, 0);
227 write_msr(IA32_MTRR_PHYSMASK6, 0);
228 write_msr(IA32_MTRR_PHYSMASK7, 0);
230 // keeps default type to WB (06), turns MTRRs on, and turns off fixed ranges
231 write_msr(IA32_MTRR_DEF_TYPE, 0x00000806);
233 // reflush caches and TLB
237 lcr0(rcr0() & ~(CR0_CD | CR0_NW));
240 waiton_barrier(smp_barrier);
242 enable_irqsave(&state);
246 // Set up a two-level page table:
247 // boot_pgdir is its linear (virtual) address of the root
248 // boot_cr3 is the physical adresss of the root
249 // Then turn on paging. Then effectively turn off segmentation.
250 // (i.e., the segment base addrs are set to zero).
252 // This function only sets up the kernel part of the address space
253 // (ie. addresses >= UTOP). The user part of the address space
254 // will be setup later.
256 // From UTOP to ULIM, the user is allowed to read but not write.
257 // Above ULIM the user cannot read (or write).
268 cprintf("PSE capability detected.\n");
270 // we paniced earlier if we don't support PGE. turn it on now.
271 // it's used in boot_map_segment, which covers all of the mappings that are
272 // the same for all address spaces. and also for the VPT mapping below.
273 lcr4(rcr4() | CR4_PGE);
275 // set up mtrr's for core0. other cores will do the same later
276 setup_default_mtrrs(0);
280 * - can walk and set up boot_map_segments with jumbos but can't
281 * insert yet. need to look at the page_dir and friends.
282 * - anything related to a single struct Page still can't handle
283 * jumbos. will need to think about and adjust Page functions
284 * - do we want to store info like this in the struct Page? or just check
286 * - when we alloc a page, and we want it to be 4MB, we'll need
287 * to have contiguous memory, etc
288 * - there's a difference between having 4MB page table entries
289 * and having 4MB Page tracking structs. changing the latter will
290 * break a lot of things
291 * - showmapping and friends work on a 4KB granularity, but map to the
293 * - need to not insert / boot_map a single page into an area that is
294 * already holding a jumbo page. will need to break the jumbo up so that
295 * we can then insert the lone page. currently warns.
296 * - some inherent issues with the pgdir_walks returning a PTE, and we
297 * don't know whether it is a jumbo (PDE) or a regular PTE.
300 //////////////////////////////////////////////////////////////////////
301 // create initial page directory.
302 pgdir = boot_alloc(PGSIZE, PGSIZE);
303 memset(pgdir, 0, PGSIZE);
305 boot_cr3 = PADDR(pgdir);
306 // helpful if you want to manually walk with kvm / bochs
307 //printk("pgdir va = %08p, pgdir pa = %08p\n\n", pgdir, PADDR(pgdir));
309 //////////////////////////////////////////////////////////////////////
310 // Recursively insert PD in itself as a page table, to form
311 // a virtual page table at virtual address VPT.
312 // (For now, you don't have understand the greater purpose of the
313 // following two lines. Unless you are eagle-eyed, in which case you
314 // should already know.)
316 // Permissions: kernel RW, user NONE, Global Page
317 pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_W | PTE_P | PTE_G;
320 // Permissions: kernel R, user R, Global Page
321 pgdir[PDX(UVPT)] = PADDR(pgdir) | PTE_U | PTE_P | PTE_G;
323 //////////////////////////////////////////////////////////////////////
324 // Map the kernel stack (symbol name "bootstack"). The complete VA
325 // range of the stack, [KSTACKTOP-PTSIZE, KSTACKTOP), breaks into two
327 // * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory
328 // * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed => faults
329 // Permissions: kernel RW, user NONE
330 // Your code goes here:
332 // remember that the space for the kernel stack is allocated in the binary.
333 // bootstack and bootstacktop point to symbols in the data section, which
334 // at this point are like 0xc010b000. KSTACKTOP is the desired loc in VM
335 boot_map_segment(pgdir, (uintptr_t)KSTACKTOP - KSTKSIZE,
336 KSTKSIZE, PADDR(bootstack), PTE_W | PTE_G);
338 //////////////////////////////////////////////////////////////////////
339 // Map all of physical memory at KERNBASE.
340 // Ie. the VA range [KERNBASE, 2^32) should map to
341 // the PA range [0, 2^32 - KERNBASE)
342 // We might not have 2^32 - KERNBASE bytes of physical memory, but
343 // we just set up the mapping anyway.
344 // Permissions: kernel RW, user NONE
345 // Your code goes here:
347 // this maps all of the possible phys memory
348 // note the use of unsigned underflow to get size = 0x40000000
349 //boot_map_segment(pgdir, KERNBASE, -KERNBASE, 0, PTE_W);
350 // but this only maps what is available, and saves memory. every 4MB of
351 // mapped memory requires a 2nd level page: 2^10 entries, each covering 2^12
352 // need to modify tests below to account for this
354 // map the first 4MB as regular entries, to support different MTRRs
355 boot_map_segment(pgdir, KERNBASE, JPGSIZE, 0, PTE_W | PTE_G);
356 boot_map_segment(pgdir, KERNBASE + JPGSIZE, maxaddrpa - JPGSIZE, JPGSIZE,
357 PTE_W | PTE_G | PTE_PS);
359 boot_map_segment(pgdir, KERNBASE, maxaddrpa, 0, PTE_W | PTE_G);
361 // APIC mapping: using PAT (but not *the* PAT flag) to make these type UC
363 boot_map_segment(pgdir, (uintptr_t)IOAPIC_BASE, PGSIZE, IOAPIC_BASE,
364 PTE_PCD | PTE_PWT | PTE_W | PTE_G);
366 boot_map_segment(pgdir, (uintptr_t)LAPIC_BASE, PGSIZE, LAPIC_BASE,
367 PTE_PCD | PTE_PWT | PTE_W | PTE_G);
369 #ifdef __CONFIG_E1000_MMIO_HACK__
371 boot_map_segment(pgdir, (uintptr_t)LAPIC_BASE + PGSIZE, 0x20000,
372 E1000_MMIO_ADDR, PTE_PCD | PTE_PWT | PTE_W | PTE_G);
375 // Check that the initial page directory has been set up correctly.
376 check_boot_pgdir(pse);
378 //////////////////////////////////////////////////////////////////////
379 // On x86, segmentation maps a VA to a LA (linear addr) and
380 // paging maps the LA to a PA. I.e. VA => LA => PA. If paging is
381 // turned off the LA is used as the PA. Note: there is no way to
382 // turn off segmentation. The closest thing is to set the base
383 // address to 0, so the VA => LA mapping is the identity.
385 // Current mapping: VA KERNBASE+x => PA x.
386 // (segmentation base=-KERNBASE and paging is off)
388 // From here on down we must maintain this VA KERNBASE + x => PA x
389 // mapping, even though we are turning on paging and reconfiguring
392 // Map VA 0:4MB same as VA KERNBASE, i.e. to PA 0:4MB.
393 // (Limits our kernel to <4MB)
394 /* They mean linear address 0:4MB, and the kernel < 4MB is only until
395 * segmentation is turned off.
396 * once we turn on paging, segmentation is still on, so references to
397 * KERNBASE+x will get mapped to linear address x, which we need to make
398 * sure can map to phys addr x, until we can turn off segmentation and
399 * KERNBASE+x maps to LA KERNBASE+x, which maps to PA x, via paging
401 pgdir[0] = pgdir[PDX(KERNBASE)];
403 // Install page table.
408 // CD and NW should already be on, but just in case these turn on caching
409 cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_MP;
410 cr0 &= ~(CR0_TS|CR0_EM|CR0_CD|CR0_NW);
413 // Current mapping: KERNBASE+x => x => x.
414 // (x < 4MB so uses paging pgdir[0])
416 // Reload all segment registers.
417 asm volatile("lgdt gdt_pd");
418 asm volatile("movw %%ax,%%gs" :: "a" (GD_UD|3));
419 asm volatile("movw %%ax,%%fs" :: "a" (GD_UD|3));
420 asm volatile("movw %%ax,%%es" :: "a" (GD_KD));
421 asm volatile("movw %%ax,%%ds" :: "a" (GD_KD));
422 asm volatile("movw %%ax,%%ss" :: "a" (GD_KD));
423 asm volatile("ljmp %0,$1f\n 1:\n" :: "i" (GD_KT)); // reload cs
424 asm volatile("lldt %%ax" :: "a" (0));
426 // Final mapping: KERNBASE+x => KERNBASE+x => x.
428 // This mapping was only used after paging was turned on but
429 // before the segment registers were reloaded.
432 // Flush the TLB for good measure, to kill the pgdir[0] mapping.
437 // Checks that the kernel part of virtual address space
438 // has been setup roughly correctly(by i386_vm_init()).
440 // This function doesn't test every corner case,
441 // in fact it doesn't test the permission bits at all,
442 // but it is a pretty good sanity check.
444 static physaddr_t check_va2pa(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t va);
447 check_boot_pgdir(bool pse)
455 //for (i = 0; KERNBASE + i != 0; i += PGSIZE)
456 // adjusted check to account for only mapping avail mem
458 for (i = 0; i < maxaddrpa; i += JPGSIZE)
459 assert(check_va2pa(pgdir, KERNBASE + i) == i);
461 for (i = 0; i < maxaddrpa; i += PGSIZE)
462 assert(check_va2pa(pgdir, KERNBASE + i) == i);
464 // check kernel stack
465 for (i = 0; i < KSTKSIZE; i += PGSIZE)
466 assert(check_va2pa(pgdir, KSTACKTOP - KSTKSIZE + i) == PADDR(bootstack) + i);
468 // check for zero/non-zero in PDEs
469 for (i = 0; i < NPDENTRIES; i++) {
473 case PDX(KSTACKTOP-1):
474 case PDX(LAPIC_BASE): // LAPIC mapping. TODO: remove when MTRRs are up
478 //if (i >= PDX(KERNBASE))
479 // adjusted check to account for only mapping avail mem
480 // and you can't KADDR maxpa (just above legal range)
481 // maxaddrpa can be up to maxpa, so assume the worst
482 if (i >= PDX(KERNBASE) && i <= PDX(KADDR(maxaddrpa-1)))
485 assert(pgdir[i] == 0);
491 * user read-only. check for user and write, should be only user
492 * eagle-eyed viewers should be able to explain the extra cases.
493 * for the mongoose-eyed, remember that weird shit happens when you loop
494 * through UVPT. Specifically, you can't loop once, then look at a jumbo
495 * page that is kernel only. That's the end of the page table for you, so
496 * having a U on the entry doesn't make sense. Thus we check for a jumbo
497 * page, and special case it. This will happen at 0xbf701000. Why is this
498 * magical? Get your eagle glasses and figure it out. */
499 for (i = UTOP; i < ULIM; i+=PGSIZE) {
500 pte = get_va_perms(pgdir, (void*SAFE)TC(i));
502 if (i == UVPT+(VPT >> 10))
504 if (*pgdir_walk(pgdir, (void*SAFE)TC(i), 0) & PTE_PS) {
505 assert((pte & PTE_U) != PTE_U);
506 assert((pte & PTE_W) != PTE_W);
508 assert((pte & PTE_U) == PTE_U);
509 assert((pte & PTE_W) != PTE_W);
513 // kernel read-write.
514 for (i = ULIM; i <= KERNBASE + maxaddrpa - PGSIZE; i+=PGSIZE) {
515 pte = get_va_perms(pgdir, (void*SAFE)TC(i));
516 if ((pte & PTE_P) && (i != VPT+(UVPT>>10))) {
517 assert((pte & PTE_U) != PTE_U);
518 assert((pte & PTE_W) == PTE_W);
522 pte = get_va_perms(pgdir, (void*SAFE)TC(UVPT+(VPT>>10)));
523 assert((pte & PTE_U) != PTE_U);
524 assert((pte & PTE_W) != PTE_W);
526 // note this means the kernel cannot directly manipulate this virtual address
527 // convince yourself this isn't a big deal, eagle-eyes!
528 pte = get_va_perms(pgdir, (void*SAFE)TC(VPT+(UVPT>>10)));
529 assert((pte & PTE_U) != PTE_U);
530 assert((pte & PTE_W) != PTE_W);
532 cprintf("check_boot_pgdir() succeeded!\n");
535 // This function returns the physical address of the page containing 'va',
536 // defined by the page directory 'pgdir'. The hardware normally performs
537 // this functionality for us! We define our own version to help check
538 // the check_boot_pgdir() function; it shouldn't be used elsewhere.
541 check_va2pa(pde_t *COUNT(NPDENTRIES) _pgdir, uintptr_t va)
543 pte_t *COUNT(NPTENTRIES) p;
544 pde_t *COUNT(1) pgdir;
546 pgdir = &_pgdir[PDX(va)];
547 if (!(*pgdir & PTE_P))
550 return PTE_ADDR(*pgdir);
551 p = (pte_t*COUNT(NPTENTRIES)) KADDR(PTE_ADDR(*pgdir));
552 if (!(p[PTX(va)] & PTE_P))
554 return PTE_ADDR(p[PTX(va)]);
558 * Remove the second level page table associated with virtual address va.
559 * Will 0 out the PDE for that page table.
560 * Panics if the page table has any present entries.
561 * This should be called rarely and with good cause.
562 * Currently errors if the PDE is jumbo or not present.
564 error_t pagetable_remove(pde_t *pgdir, void *va)
566 pde_t* the_pde = &pgdir[PDX(va)];
568 if (!(*the_pde & PTE_P) || (*the_pde & PTE_PS))
570 pte_t* page_table = (pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde));
571 for (int i = 0; i < NPTENTRIES; i++)
572 if (page_table[i] & PTE_P)
573 panic("Page table not empty during attempted removal!");
575 page_decref(pa2page(PADDR(page_table)));
579 // Given 'pgdir', a pointer to a page directory, pgdir_walk returns
580 // a pointer to the page table entry (PTE) for linear address 'va'.
581 // This requires walking the two-level page table structure.
583 // If the relevant page table doesn't exist in the page directory, then:
584 // - If create == 0, pgdir_walk returns NULL.
585 // - Otherwise, pgdir_walk tries to allocate a new page table
586 // with page_alloc. If this fails, pgdir_walk returns NULL.
587 // - Otherwise, pgdir_walk returns a pointer into the new page table.
589 // This is boot_pgdir_walk, but using page_alloc() instead of boot_alloc().
590 // Unlike boot_pgdir_walk, pgdir_walk can fail.
592 // Hint: you can turn a Page * into the physical address of the
593 // page it refers to with page2pa() from kern/pmap.h.
595 // Supports returning jumbo (4MB PSE) PTEs. To create with a jumbo, pass in 2.
597 pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
599 pde_t* the_pde = &pgdir[PDX(va)];
602 if (*the_pde & PTE_P) {
603 if (*the_pde & PTE_PS)
604 return (pte_t*)the_pde;
605 return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(va)];
611 panic("Attempting to find a Jumbo PTE at an unaligned VA!");
612 *the_pde = PTE_PS | PTE_P;
613 return (pte_t*)the_pde;
615 if (kpage_alloc(&new_table))
617 page_setref(new_table,1);
618 memset(page2kva(new_table), 0, PGSIZE);
619 *the_pde = (pde_t)page2pa(new_table) | PTE_P | PTE_W | PTE_U;
620 return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(va)];
623 /* Returns the effective permissions for PTE_U, PTE_W, and PTE_P on a given
624 * virtual address. Note we need to consider the composition of every PTE in
625 * the page table walk. */
626 int get_va_perms(pde_t *pgdir, const void *SNT va)
628 pde_t the_pde = pgdir[PDX(va)];
631 if (!(the_pde & PTE_P))
633 if (the_pde & PTE_PS)
634 return the_pde & (PTE_U | PTE_W | PTE_P);
635 the_pte = ((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(the_pde)))[PTX(va)];
636 if (!(the_pte & PTE_P))
638 return the_pte & the_pde & (PTE_U | PTE_W | PTE_P);
641 void *get_free_va_range(pde_t *pgdir, uintptr_t addr, size_t len)
643 addr = ROUNDUP(MAX(addr,BRK_END),PGSIZE);
644 len = ROUNDUP(len,PGSIZE);
646 for(char* a = (char*)addr; a < (char*)USTACKBOT; a += PGSIZE)
648 for(char* b = a; b < a+len; b += PGSIZE)
650 pte_t* pte = pgdir_walk(pgdir,b,0);
651 if(pte && !PAGE_UNMAPPED(*pte))
656 if(b+PGSIZE == a+len)
663 /* Flushes a TLB, including global pages. We should always have the CR4_PGE
664 * flag set, but just in case, we'll check. Toggling this bit flushes the TLB.
666 void tlb_flush_global(void)
668 uint32_t cr4 = rcr4();
670 lcr4(cr4 & ~CR4_PGE);
679 page_t *pp, *pp0, *pp1, *pp2;
680 page_list_t fl[1024];
683 // should be able to allocate three pages
685 assert(kpage_alloc(&pp0) == 0);
686 assert(kpage_alloc(&pp1) == 0);
687 assert(kpage_alloc(&pp2) == 0);
693 assert(pp1 && pp1 != pp0);
694 assert(pp2 && pp2 != pp1 && pp2 != pp0);
696 // temporarily steal the rest of the free pages
697 for(int i=0; i<llc_cache->num_colors; i++) {
698 fl[i] = colored_page_free_list[i];
699 LIST_INIT(&colored_page_free_list[i]);
702 // should be no free memory
703 assert(kpage_alloc(&pp) == -ENOMEM);
705 // Fill pp1 with bogus data and check for invalid tlb entries
706 memset(page2kva(pp1), 0xFFFFFFFF, PGSIZE);
708 // there is no page allocated at address 0
709 assert(page_lookup(boot_pgdir, (void *) 0x0, &ptep) == NULL);
711 // there is no free memory, so we can't allocate a page table
712 assert(page_insert(boot_pgdir, pp1, 0x0, 0) < 0);
714 // free pp0 and try again: pp0 should be used for page table
716 assert(page_insert(boot_pgdir, pp1, 0x0, 0) == 0);
717 tlb_invalidate(boot_pgdir, 0x0);
718 // DEP Should have shot down invalid TLB entry - let's check
721 assert(*x == 0xFFFFFFFF);
723 assert(PTE_ADDR(boot_pgdir[0]) == page2pa(pp0));
724 assert(check_va2pa(boot_pgdir, 0x0) == page2pa(pp1));
725 assert(pp1->page_ref == 1);
726 assert(pp0->page_ref == 1);
728 // should be able to map pp2 at PGSIZE because pp0 is already allocated for page table
729 assert(page_insert(boot_pgdir, pp2, (void*SNT) PGSIZE, 0) == 0);
730 assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp2));
731 assert(pp2->page_ref == 1);
733 // Make sure that pgdir_walk returns a pointer to the pte and
734 // not the table or some other garbage
736 pte_t *p = (pte_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(boot_pgdir[PDX(PGSIZE)]));
737 assert(pgdir_walk(boot_pgdir, (void *SNT)PGSIZE, 0) == &p[PTX(PGSIZE)]);
740 // should be no free memory
741 assert(kpage_alloc(&pp) == -ENOMEM);
743 // should be able to map pp2 at PGSIZE because it's already there
744 assert(page_insert(boot_pgdir, pp2, (void*SNT) PGSIZE, PTE_U) == 0);
745 assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp2));
746 assert(pp2->page_ref == 1);
748 // Make sure that we actually changed the permission on pp2 when we re-mapped it
750 pte_t *p = pgdir_walk(boot_pgdir, (void*SNT)PGSIZE, 0);
751 assert(((*p) & PTE_U) == PTE_U);
754 // pp2 should NOT be on the free list
755 // could happen in ref counts are handled sloppily in page_insert
756 assert(kpage_alloc(&pp) == -ENOMEM);
758 // should not be able to map at PTSIZE because need free page for page table
759 assert(page_insert(boot_pgdir, pp0, (void*SNT) PTSIZE, 0) < 0);
761 // insert pp1 at PGSIZE (replacing pp2)
762 assert(page_insert(boot_pgdir, pp1, (void*SNT) PGSIZE, 0) == 0);
764 // should have pp1 at both 0 and PGSIZE, pp2 nowhere, ...
765 assert(check_va2pa(boot_pgdir, 0) == page2pa(pp1));
766 assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp1));
767 // ... and ref counts should reflect this
768 assert(pp1->page_ref == 2);
769 assert(pp2->page_ref == 0);
771 // pp2 should be returned by page_alloc
772 assert(kpage_alloc(&pp) == 0 && pp == pp2);
775 // unmapping pp1 at 0 should keep pp1 at PGSIZE
776 page_remove(boot_pgdir, 0x0);
777 assert(check_va2pa(boot_pgdir, 0x0) == ~0);
778 assert(check_va2pa(boot_pgdir, PGSIZE) == page2pa(pp1));
779 assert(pp1->page_ref == 1);
780 assert(pp2->page_ref == 0);
782 // unmapping pp1 at PGSIZE should free it
783 page_remove(boot_pgdir, (void*SNT) PGSIZE);
784 assert(check_va2pa(boot_pgdir, 0x0) == ~0);
785 assert(check_va2pa(boot_pgdir, PGSIZE) == ~0);
786 assert(pp1->page_ref == 0);
787 assert(pp2->page_ref == 0);
789 // so it should be returned by page_alloc
790 assert(kpage_alloc(&pp) == 0 && pp == pp1);
793 // should be no free memory
794 assert(kpage_alloc(&pp) == -ENOMEM);
796 // forcibly take pp0 back
797 assert(PTE_ADDR(boot_pgdir[0]) == page2pa(pp0));
799 assert(pp0->page_ref == 1);
802 // Catch invalid pointer addition in pgdir_walk - i.e. pgdir + PDX(va)
804 // Give back pp0 for a bit
807 void *SNT va = (void *SNT)((PGSIZE * NPDENTRIES) + PGSIZE);
808 pte_t *p2 = pgdir_walk(boot_pgdir, va, 1);
809 pte_t *p = (pte_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(boot_pgdir[PDX(va)]));
810 assert(p2 == &p[PTX(va)]);
813 boot_pgdir[PDX(va)] = 0;
817 // give free list back
818 for(int i=0; i<llc_cache->num_colors; i++)
819 colored_page_free_list[i] = fl[i];
821 // free the pages we took
826 cprintf("page_check() succeeded!\n");
831 // testing code for boot_pgdir_walk
833 temp = boot_pgdir_walk(pgdir, VPT + (VPT >> 10), 1);
834 cprintf("pgdir = %p\n", pgdir);
835 cprintf("test recursive walking pte_t* = %p\n", temp);
836 cprintf("test recursive walking entry = %p\n", PTE_ADDR(temp));
837 temp = boot_pgdir_walk(pgdir, 0xc0400000, 1);
838 cprintf("LA = 0xc0400000 = %p\n", temp);
839 temp = boot_pgdir_walk(pgdir, 0xc0400070, 1);
840 cprintf("LA = 0xc0400070 = %p\n", temp);
841 temp = boot_pgdir_walk(pgdir, 0xc0800000, 0);
842 cprintf("LA = 0xc0800000, no create = %p\n", temp);
843 temp = boot_pgdir_walk(pgdir, 0xc0600070, 1);
844 cprintf("LA = 0xc0600070 = %p\n", temp);
845 temp = boot_pgdir_walk(pgdir, 0xc0600090, 0);
846 cprintf("LA = 0xc0600090, nc = %p\n", temp);
847 temp = boot_pgdir_walk(pgdir, 0xc0608070, 0);
848 cprintf("LA = 0xc0608070, nc = %p\n", temp);
849 temp = boot_pgdir_walk(pgdir, 0xc0800070, 1);
850 cprintf("LA = 0xc0800070 = %p\n", temp);
851 temp = boot_pgdir_walk(pgdir, 0xc0b00070, 0);
852 cprintf("LA = 0xc0b00070, nc = %p\n", temp);
853 temp = boot_pgdir_walk(pgdir, 0xc0c00000, 0);
854 cprintf("LA = 0xc0c00000, nc = %p\n", temp);
856 // testing for boot_map_seg
858 cprintf("before mapping 1 page to 0x00350000\n");
859 cprintf("0xc4000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc4000000, 1));
860 cprintf("0xc4000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc4000000, 1)));
861 boot_map_segment(pgdir, 0xc4000000, 4096, 0x00350000, PTE_W);
862 cprintf("after mapping\n");
863 cprintf("0xc4000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc4000000, 1));
864 cprintf("0xc4000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc4000000, 1)));
867 cprintf("before mapping 3 pages to 0x00700000\n");
868 cprintf("0xd0000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0000000, 1));
869 cprintf("0xd0000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0000000, 1)));
870 cprintf("0xd0001000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0001000, 1));
871 cprintf("0xd0001000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0001000, 1)));
872 cprintf("0xd0002000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0002000, 1));
873 cprintf("0xd0002000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0002000, 1)));
874 boot_map_segment(pgdir, 0xd0000000, 4096*3, 0x00700000, 0);
875 cprintf("after mapping\n");
876 cprintf("0xd0000000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0000000, 1));
877 cprintf("0xd0000000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0000000, 1)));
878 cprintf("0xd0001000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0001000, 1));
879 cprintf("0xd0001000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0001000, 1)));
880 cprintf("0xd0002000's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xd0002000, 1));
881 cprintf("0xd0002000's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xd0002000, 1)));
884 cprintf("before mapping 1 unaligned to 0x00500010\n");
885 cprintf("0xc8000010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8000010, 1));
886 cprintf("0xc8000010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8000010, 1)));
887 cprintf("0xc8001010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8001010, 1));
888 cprintf("0xc8001010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8001010, 1)));
889 boot_map_segment(pgdir, 0xc8000010, 4096, 0x00500010, PTE_W);
890 cprintf("after mapping\n");
891 cprintf("0xc8000010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8000010, 1));
892 cprintf("0xc8000010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8000010, 1)));
893 cprintf("0xc8001010's &pte: %08x\n",boot_pgdir_walk(pgdir, 0xc8001010, 1));
894 cprintf("0xc8001010's pte: %08x\n",*(boot_pgdir_walk(pgdir, 0xc8001010, 1)));
897 boot_map_segment(pgdir, 0xe0000000, 4096, 0x10000000, PTE_W);