changelog
play

Changelog Changes made in this version not seen in fjrst lecture: - PowerPoint PPT Presentation

Changelog Changes made in this version not seen in fjrst lecture: sz is one past the end of the heap 0 2 November: Correct space on demand from to < and > to since Virtual Memory 1 1 last time deadlock thread A holding a


  1. all even processes send messages each process stores cells message passing game of life send messages with cells every iteration (while even receives) (while odd receives), then all even processes send messages one possible pseudocode: (while even receives) all odd processes send messages (while odd receives), then one possible pseudocode: so process 3 also sends messages also needed by process 2/4 some of process 3’s cells solution: process 2, 4 process 4 other process’s cells needed small slivers of the ones it computes) (values of cells adjacent to of cells around its area process 3 only needs values (no shared memory!) in that part of grid like you would for normal threads divide grid process 2 process 3 10 all odd processes send messages

  2. toy program memory virtual page# 1 rest of address is called page ofgset (because page size is power of two) page number is upper bits of address “virtual” = addresses the program sees bytes in this case) divide memory into pages ( virtual page# 3 virtual page# 2 virtual page# 0 code 11 1111 1111 = 0x3FF 11 0000 0000 = 0x300 10 0000 0000 = 0x200 01 0000 0000 = 0x100 00 0000 0000 = 0x000 stack empty/more heap? data/heap 11

  3. toy program memory virtual page# 1 rest of address is called page ofgset (because page size is power of two) page number is upper bits of address “virtual” = addresses the program sees bytes in this case) divide memory into pages ( virtual page# 3 virtual page# 2 virtual page# 0 code 11 1111 1111 = 0x3FF 11 0000 0000 = 0x300 10 0000 0000 = 0x200 01 0000 0000 = 0x100 00 0000 0000 = 0x000 stack empty/more heap? data/heap 11

  4. toy program memory code rest of address is called page ofgset (because page size is power of two) page number is upper bits of address “virtual” = addresses the program sees virtual page# 3 virtual page# 2 virtual page# 1 virtual page# 0 11 1111 1111 = 0x3FF 11 0000 0000 = 0x300 10 0000 0000 = 0x200 01 0000 0000 = 0x100 00 0000 0000 = 0x000 stack empty/more heap? data/heap 11 divide memory into pages ( 2 8 bytes in this case)

  5. toy program memory virtual page# 1 rest of address is called page ofgset (because page size is power of two) page number is upper bits of address “virtual” = addresses the program sees bytes in this case) divide memory into pages ( virtual page# 3 virtual page# 2 virtual page# 0 code 11 1111 1111 = 0x3FF 11 0000 0000 = 0x300 10 0000 0000 = 0x200 01 0000 0000 = 0x100 00 0000 0000 = 0x000 stack empty/more heap? data/heap 11

  6. toy program memory virtual page# 1 rest of address is called page ofgset (because page size is power of two) page number is upper bits of address “virtual” = addresses the program sees bytes in this case) divide memory into pages ( virtual page# 3 virtual page# 2 virtual page# 0 code 11 1111 1111 = 0x3FF 11 0000 0000 = 0x300 10 0000 0000 = 0x200 01 0000 0000 = 0x100 00 0000 0000 = 0x000 stack empty/more heap? data/heap 11

  7. toy physical memory 010 (2) physical page 7 virtual page # physical page # 00 01 physical page 0 111 (7) 10 none 11 000 (0) page table! physical page 1 111 1111 1111 program memory 10 1111 1111 virtual addresses 00 0000 0000 to 00 1111 1111 01 0000 0000 to 01 1111 1111 10 0000 0000 to 11 0000 0000 to 111 0000 0000 to 11 1111 1111 real memory physical addresses 000 0000 0000 to 000 1111 1111 001 0000 0000 to 001 1111 1111 12

  8. toy physical memory 010 (2) physical page 7 virtual page # physical page # 00 01 physical page 0 111 (7) 10 none 11 000 (0) page table! physical page 1 111 1111 1111 program memory 10 1111 1111 virtual addresses 00 0000 0000 to 00 1111 1111 01 0000 0000 to 01 1111 1111 10 0000 0000 to 11 0000 0000 to 111 0000 0000 to 11 1111 1111 real memory physical addresses 000 0000 0000 to 000 1111 1111 001 0000 0000 to 001 1111 1111 12

  9. toy physical memory 010 (2) physical page 7 virtual page # physical page # 00 01 physical page 0 111 (7) 10 none 11 000 (0) page table! physical page 1 111 1111 1111 program memory 10 1111 1111 virtual addresses 00 0000 0000 to 00 1111 1111 01 0000 0000 to 01 1111 1111 10 0000 0000 to 11 0000 0000 to 111 0000 0000 to 11 1111 1111 real memory physical addresses 000 0000 0000 to 000 1111 1111 001 0000 0000 to 001 1111 1111 12

  10. toy physical memory 010 (2) physical page 7 virtual page # physical page # 00 01 physical page 0 111 (7) 10 none 11 000 (0) page table! physical page 1 111 1111 1111 program memory 10 1111 1111 virtual addresses 00 0000 0000 to 00 1111 1111 01 0000 0000 to 01 1111 1111 10 0000 0000 to 11 0000 0000 to 111 0000 0000 to 11 1111 1111 real memory physical addresses 000 0000 0000 to 000 1111 1111 001 0000 0000 to 001 1111 1111 12

  11. toy physical memory 010 (2) physical page 7 virtual page # physical page # 00 01 physical page 0 111 (7) 10 none 11 000 (0) page table! physical page 1 111 1111 1111 program memory 10 1111 1111 virtual addresses 00 0000 0000 to 00 1111 1111 01 0000 0000 to 01 1111 1111 10 0000 0000 to 11 0000 0000 to 111 0000 0000 to 11 1111 1111 real memory physical addresses 000 0000 0000 to 000 1111 1111 001 0000 0000 to 001 1111 1111 12

  12. 01 1101 0010 — address from CPU toy page table lookup 111 1101 0010 1 000 (0, stack) 1 1 trigger exception if 0? to cache (data or instruction) 0 “page table entry” “virtual page number” “physical page number” “page ofgset” “page ofgset” 11 0 virtual 1 OK? write OK? 00 1 010 (2, code) 0 ??? (ignored) 01 1 111 (7, data) 1 1 10 0 13 page # valid? physical page # read

  13. toy page table lookup 111 1101 0010 11 1 000 (0, stack) 1 1 trigger exception if 0? to cache (data or instruction) virtual “page table entry” “virtual page number” “physical page number” “page ofgset” “page ofgset” 0 0 ??? (ignored) 1 OK? write OK? 00 1 010 (2, code) 0 0 01 1 111 (7, data) 1 1 10 13 01 1101 0010 — address from CPU page # valid? physical page # read

  14. toy page table lookup 111 1101 0010 11 1 000 (0, stack) 1 1 trigger exception if 0? to cache (data or instruction) virtual “page table entry” “virtual page number” “physical page number” “page ofgset” “page ofgset” 0 0 ??? (ignored) 1 OK? write OK? 00 1 010 (2, code) 0 0 01 1 111 (7, data) 1 1 10 13 01 1101 0010 — address from CPU page # valid? physical page # read

  15. toy page table lookup 111 1101 0010 11 1 000 (0, stack) 1 1 trigger exception if 0? to cache (data or instruction) virtual “page table entry” “virtual page number” “physical page number” “page ofgset” “page ofgset” 0 0 ??? (ignored) 1 OK? write OK? 00 1 010 (2, code) 0 0 01 1 111 (7, data) 1 1 10 13 01 1101 0010 — address from CPU page # valid? physical page # read

  16. toy page table lookup 111 1101 0010 11 1 000 (0, stack) 1 1 trigger exception if 0? to cache (data or instruction) virtual “page table entry” “virtual page number” “physical page number” “page ofgset” “page ofgset” 0 0 ??? (ignored) 1 OK? write OK? 00 1 010 (2, code) 0 0 01 1 111 (7, data) 1 1 10 13 01 1101 0010 — address from CPU page # valid? physical page # read

  17. toy page table lookup 111 1101 0010 11 1 000 (0, stack) 1 1 trigger exception if 0? to cache (data or instruction) virtual “page table entry” “virtual page number” “physical page number” “page ofgset” “page ofgset” 0 0 ??? (ignored) 1 OK? write OK? 00 1 010 (2, code) 0 0 01 1 111 (7, data) 1 1 10 13 01 1101 0010 — address from CPU page # valid? physical page # read

  18. valid user? write? physical page # valid user? write? physical page # 0x4A9DE 0 1 1 0xC01 0x42443 0 1 1 0xC00 two-level page tables (of data) VPN fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … 0xC02 1 … … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 0xFF043 … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 for VPN 0x0-0x3FF PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range (of next page table) 0x0-0x3FF 1 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 14 two-level page table; 2 20 pages total; 2 10 entries per table

  19. valid user? write? physical page # valid user? write? physical page # 0x4A9DE 0 1 1 0xC01 0x42443 0 1 1 0xC00 two-level page tables (of data) VPN fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … 0xC02 1 … … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 0xFF043 … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 for VPN 0x0-0x3FF PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range (of next page table) 0x0-0x3FF 1 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 14 two-level page table; 2 20 pages total; 2 10 entries per table

  20. valid user? write? physical page # two-level page tables 0 1 1 0xC01 0x42443 0 1 1 0xC00 (of data) VPN 0xC02 fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … … 0x4A9DE 1 0xFF043 … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 for VPN 0x0-0x3FF … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 1 PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range 14 (of next page table) 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 0x0-0x3FF two-level page table; 2 20 pages total; 2 10 entries per table valid user? write? physical page #

  21. valid user? write? physical page # two-level page tables 0 1 1 0xC01 0x42443 0 1 1 0xC00 (of data) VPN 0xC02 fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … … 0x4A9DE 1 0xFF043 … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 for VPN 0x0-0x3FF … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 1 PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range 14 0 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 0x0-0x3FF two-level page table; 2 20 pages total; 2 10 entries per table valid user? write? physical page # (of next page table)

  22. valid user? write? physical page # two-level page tables 0 1 1 0xC01 0x42443 0 1 1 0xC00 (of data) VPN 0xC02 fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … … 0x4A9DE 1 0xFF043 … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 for VPN 0x0-0x3FF … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 1 PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range 14 (of next page table) 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 0x0-0x3FF two-level page table; 2 20 pages total; 2 10 entries per table valid user? write? physical page #

  23. valid user? write? physical page # two-level page tables 0x4A9DE 0 1 1 0xC01 0x42443 0 1 1 0xC00 VPN (of data) fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … … 0xC02 1 0xFF043 … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 for VPN 0x0-0x3FF … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 1 PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range (of next page table) 0x0-0x3FF 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 14 two-level page table; 2 20 pages total; 2 10 entries per table valid user? write? physical page #

  24. valid user? write? physical page # two-level page tables 0x4A9DE 0 1 1 0xC01 0x42443 0 1 1 0xC00 VPN (of data) fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … … 0xC02 1 0xFF043 … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 for VPN 0x0-0x3FF … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 1 PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range (of next page table) 0x0-0x3FF 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 14 two-level page table; 2 20 pages total; 2 10 entries per table valid user? write? physical page #

  25. valid user? write? physical page # valid user? write? physical page # 0x4A9DE 0 1 1 0xC01 0x42443 0 1 1 0xC00 two-level page tables (of data) VPN fjrst-level page table 0xFF045 0 1 1 0xFFC00-0xFFFFF … … … 0xC02 1 … … a second-level page table 0x00000 0 0 0 0xFFF … … … … 0x6C223 1 0 1 1 0xC04 0x00000 0 0 0 0xC03 0x5C001 0 … 0 0xFF043 … PTE for VPN 0xFFF … PTE for VPN 0xC03 PTE for VPN 0xC02 PTE for VPN 0xC01 PTE for VPN 0xC00 (if PTE valid) actual data second-level page tables PTE for VPN 0x3FF PTE for VPN 0x003 for VPN 0x0-0x3FF PTE for VPN 0x002 PTE for VPN 0x001 PTE for VPN 0x000 fjrst-level page table for VPN 0xFFC00-0xFFFFF for VPN 0xFF800-0xFFBFF … for VPN 0xC00-0xFFF for VPN 0x800-0xBFF for VPN 0x400-0x7FF invalid entries represent big holes VPN range (of next page table) 0x0-0x3FF 1 1 0x1000-0x13FF 0x33454 0 1 1 0xC00-0xFFF 0x00000 0 0 0 0x800-0xBFF 0x00000 1 0 0 0x400-0x7FF 0x22343 1 1 1 14 two-level page table; 2 20 pages total; 2 10 entries per table

  26. x86-32 pagetables: overall structure | #define PGADDR(d, t, o) ((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) // construct virtual address from indexes and offset (((uint)(va) >> PTXSHIFT) & 0x3FF) #define PTX(va) // page table index (((uint)(va) >> PDXSHIFT) & 0x3FF) #define PDX(va) // page directory index \--- PDX(va) --/ \--- PTX(va) --/ // // +----------------+----------------+---------------------+ | xv6 header: mmu.h Index | Index // | | | Offset within Page Page Table // | Page Directory | // +--------10------+-------10-------+---------12----------+ // // A virtual address 'la' has a three-part structure as follows: 15

  27. another view VPN part 1 VPN part 2 page ofgset fjrst-level page table page table base register page table entry second-level page table page table entry physical page 16

  28. 32-bit x86 paging 4-byte page table entries — stored in memory two-level table: fjrst 10 bits lookup in fjrst level (“page directory”) second 10 bits lookup in second level remaining 12 bits: which byte of 4096 in page? 17 4096 ( = 2 12 ) byte pages

  29. exercise 4-byte page table entries — stored in memory two-level table: fjrst 10 bits lookup in fjrst level (“page directory”) second 10 bits lookup in second level exercise: how big is… a process’s x86-32 page tables with 1 valid 4K page? a process’s x86-32 page table with all 4K pages populated? 18 4096 ( = 2 12 ) byte pages

  30. x86-32 page table entries page table base register (CR3) fjrst-level page table entries second-level page table entries 19

  31. x86-32 page table entries page table base register (CR3) fjrst-level page table entries second-level page table entries 19

  32. x86-32 page table entries page table base register (CR3) fjrst-level page table entries second-level page table entries 19

  33. x86-32 page table entries page table base register (CR3) fjrst-level page table entries second-level page table entries 19

  34. x86-32 page table entries trick: page table entry with lower bits zeroed = physical byte address makes constructing page table entries simpler: physicalAddress | flagsBits 20 page # is address of page ( 2 12 byte units)

  35. x86-32 pagetables: page table entries #define PTE_MBZ #define PTE_D 0x040 // Dirty #define PTE_PS 0x080 // Page Size 0x180 0x020 // Bits must be zero // Address in page table or page directory entry #define PTE_ADDR(pte) ((uint)(pte) & ~0xFFF) #define PTE_FLAGS(pte) ((uint)(pte) & 0xFFF) // Accessed #define PTE_A xv6 header: mmu.h // Writeable // Page table/directory entry flags. #define PTE_P 0x001 // Present #define PTE_W 0x002 #define PTE_U // Cache-Disable 0x004 // User #define PTE_PWT 0x008 // Write-Through #define PTE_PCD 0x010 21

  36. xv6 memory layout 0x80000000 (KERNBASE) same in every process = PA VA 0x8000000 + kernel-only memory 22 Virtual 4 Gig Device memory RW- 0xFE000000 Unused if less than 2 Gig of physical memory Free memory RW-- end Kernel data RW- Kernel text R-- + 0x100000 Physical RW- 4 Gig KERNBASE Memory-mapped 32-bit I/O devices PHYSTOP Unused if less than 2 Gig of physical memory Program data & heap At most 2 Gig Extended memory PAGESIZE User stack RWU 0x100000 User data RWU I/O space 640K User text RWU Base memory 0 0

  37. xv6 memory layout 0x80000000 (KERNBASE) same in every process = PA VA 0x8000000 + kernel-only memory 22 Virtual 4 Gig Device memory RW- 0xFE000000 Unused if less than 2 Gig of physical memory Free memory RW-- end Kernel data RW- Kernel text R-- + 0x100000 Physical RW- 4 Gig KERNBASE Memory-mapped 32-bit I/O devices PHYSTOP Unused if less than 2 Gig of physical memory Program data & heap At most 2 Gig Extended memory PAGESIZE User stack RWU 0x100000 User data RWU I/O space 640K User text RWU Base memory 0 0

  38. xv6 memory layout 0x80000000 (KERNBASE) same in every process kernel-only memory 22 Virtual 4 Gig Device memory RW- 0xFE000000 Unused if less than 2 Gig of physical memory VA 0x8000000 + x = PA x Free memory RW-- end Kernel data RW- Kernel text R-- + 0x100000 Physical RW- 4 Gig KERNBASE Memory-mapped 32-bit I/O devices PHYSTOP Unused if less than 2 Gig of physical memory Program data & heap At most 2 Gig Extended memory PAGESIZE User stack RWU 0x100000 User data RWU I/O space 640K User text RWU Base memory 0 0

  39. xv6 kernel memory always mapped as kernel-mode only protection fault for user-mode programs to access not done by hardware — just page table entries OS sets up on boot very convenient for manipulating page tables with physical addresses kernel code loaded into contiguous physical addresses 23 virtual memory > KERNBASE ( 0x8000 0000 ) is for kernel physical memory address 0 is mapped to KERNBASE +0 physical memory address N is mapped to KERNBASE + N

  40. P2V/V2P subtract KERNBASE (0x8000 0000) add KERNBASE (0x8000 0000) 24 V2P ( x ) (virtual to physical) convert kernel address x to physical address P2V ( x ) (physical to virtual) convert physical address x to kernel address

  41. xv6 program memory invalid adjusted by sbrk() system call myproc()->sz initial stack pointer 25 KERNBASE argument 0 ... heap argument N nul-terminated string 0 address of argument 0 argv[argc] ... address of argument N argv[0] stack PAGESIZE address of address of argv argument of main guard page argument 0 argc argument of main argc data 0xFFFFFFF return PC for main (empty) text 0

  42. xv6: fjnding page table entries P2V — physical address to virtual addresss PTX(va) pde_t — page directory entry pte_t — page table entry both aliases for uint (32-bit unsigned int) PDX(va) — extract top 10 bits of va used to index into fjrst-level page table PTE_ADDR(*pde) — return second-level page table address from fjrst-level page table entry *pde returns physical address by convention, kernel maps physical memory at address page# KERNBASE (will show setup later) result is address that can access second-level page table lookup in second-level page table PTX retrieves second-level page table index (= bits 10-20 of va ) if no second-level page table (present bit in fjrst-level = 0) create one (if alloc=1 ) or return null (if alloc=0 ) pgtab phys. // Return the address of the PTE in page table pgdir second-level PT // that corresponds to virtual address va. If alloc!=0, // create any required page table pages. { pde = &pgdir[PDX(va)]; if (*pde & PTE_P){ pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); } return &pgtab[PTX(va)]; } fjrst-level PT PDX(va) 26 static pte_t * walkpgdir(pde_t *pgdir, const void *va, int alloc) pde_t *pde; pgdir → pte_t *pgtab; pde → } else { ... /* create new second-level page table */

  43. xv6: fjnding page table entries P2V — physical address to virtual addresss PTX(va) pde_t — page directory entry pte_t — page table entry both aliases for uint (32-bit unsigned int) PDX(va) — extract top 10 bits of va used to index into fjrst-level page table PTE_ADDR(*pde) — return second-level page table address from fjrst-level page table entry *pde returns physical address by convention, kernel maps physical memory at address page# KERNBASE (will show setup later) result is address that can access second-level page table lookup in second-level page table PTX retrieves second-level page table index (= bits 10-20 of va ) if no second-level page table (present bit in fjrst-level = 0) create one (if alloc=1 ) or return null (if alloc=0 ) pgtab phys. // Return the address of the PTE in page table pgdir second-level PT // that corresponds to virtual address va. If alloc!=0, // create any required page table pages. { pde = &pgdir[PDX(va)]; if (*pde & PTE_P){ pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); } return &pgtab[PTX(va)]; } fjrst-level PT PDX(va) 26 static pte_t * walkpgdir(pde_t *pgdir, const void *va, int alloc) pde_t *pde; pgdir → pte_t *pgtab; pde → } else { ... /* create new second-level page table */

  44. xv6: fjnding page table entries P2V — physical address to virtual addresss PTX(va) pde_t — page directory entry pte_t — page table entry both aliases for uint (32-bit unsigned int) PDX(va) — extract top 10 bits of va used to index into fjrst-level page table PTE_ADDR(*pde) — return second-level page table address from fjrst-level page table entry *pde returns physical address by convention, kernel maps physical memory at address page# KERNBASE (will show setup later) result is address that can access second-level page table lookup in second-level page table PTX retrieves second-level page table index (= bits 10-20 of va ) if no second-level page table (present bit in fjrst-level = 0) create one (if alloc=1 ) or return null (if alloc=0 ) pgtab phys. // Return the address of the PTE in page table pgdir second-level PT // that corresponds to virtual address va. If alloc!=0, // create any required page table pages. { pde = &pgdir[PDX(va)]; if (*pde & PTE_P){ pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); } return &pgtab[PTX(va)]; } fjrst-level PT PDX(va) 26 static pte_t * walkpgdir(pde_t *pgdir, const void *va, int alloc) pde_t *pde; pgdir → pte_t *pgtab; pde → } else { ... /* create new second-level page table */

  45. xv6: fjnding page table entries P2V — physical address to virtual addresss PTX(va) pde_t — page directory entry pte_t — page table entry both aliases for uint (32-bit unsigned int) PDX(va) — extract top 10 bits of va used to index into fjrst-level page table PTE_ADDR(*pde) — return second-level page table address from fjrst-level page table entry *pde returns physical address by convention, kernel maps physical memory at address page# KERNBASE (will show setup later) result is address that can access second-level page table lookup in second-level page table PTX retrieves second-level page table index (= bits 10-20 of va ) if no second-level page table (present bit in fjrst-level = 0) create one (if alloc=1 ) or return null (if alloc=0 ) pgtab phys. // Return the address of the PTE in page table pgdir second-level PT // that corresponds to virtual address va. If alloc!=0, // create any required page table pages. { pde = &pgdir[PDX(va)]; if (*pde & PTE_P){ pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); } return &pgtab[PTX(va)]; } fjrst-level PT PDX(va) 26 static pte_t * walkpgdir(pde_t *pgdir, const void *va, int alloc) pde_t *pde; pgdir → pte_t *pgtab; pde → } else { ... /* create new second-level page table */

  46. xv6: fjnding page table entries P2V — physical address to virtual addresss PTX(va) pde_t — page directory entry pte_t — page table entry both aliases for uint (32-bit unsigned int) PDX(va) — extract top 10 bits of va used to index into fjrst-level page table PTE_ADDR(*pde) — return second-level page table address from fjrst-level page table entry *pde returns physical address by convention, kernel maps physical memory at address page# KERNBASE (will show setup later) result is address that can access second-level page table lookup in second-level page table PTX retrieves second-level page table index (= bits 10-20 of va ) if no second-level page table (present bit in fjrst-level = 0) create one (if alloc=1 ) or return null (if alloc=0 ) pgtab phys. // Return the address of the PTE in page table pgdir second-level PT // that corresponds to virtual address va. If alloc!=0, // create any required page table pages. { pde = &pgdir[PDX(va)]; if (*pde & PTE_P){ pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); } return &pgtab[PTX(va)]; } fjrst-level PT PDX(va) 26 static pte_t * walkpgdir(pde_t *pgdir, const void *va, int alloc) pde_t *pde; pgdir → pte_t *pgtab; pde → } else { ... /* create new second-level page table */

  47. xv6: fjnding page table entries P2V — physical address to virtual addresss PTX(va) pde_t — page directory entry pte_t — page table entry both aliases for uint (32-bit unsigned int) PDX(va) — extract top 10 bits of va used to index into fjrst-level page table PTE_ADDR(*pde) — return second-level page table address from fjrst-level page table entry *pde returns physical address by convention, kernel maps physical memory at address page# KERNBASE (will show setup later) result is address that can access second-level page table lookup in second-level page table PTX retrieves second-level page table index (= bits 10-20 of va ) if no second-level page table (present bit in fjrst-level = 0) create one (if alloc=1 ) or return null (if alloc=0 ) pgtab phys. // Return the address of the PTE in page table pgdir second-level PT // that corresponds to virtual address va. If alloc!=0, // create any required page table pages. { pde = &pgdir[PDX(va)]; if (*pde & PTE_P){ pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); } return &pgtab[PTX(va)]; } fjrst-level PT PDX(va) 26 static pte_t * walkpgdir(pde_t *pgdir, const void *va, int alloc) pde_t *pde; pgdir → pte_t *pgtab; pde → } else { ... /* create new second-level page table */

  48. xv6: fjnding page table entries P2V — physical address to virtual addresss PTX(va) pde_t — page directory entry pte_t — page table entry both aliases for uint (32-bit unsigned int) PDX(va) — extract top 10 bits of va used to index into fjrst-level page table PTE_ADDR(*pde) — return second-level page table address from fjrst-level page table entry *pde returns physical address by convention, kernel maps physical memory at address page# KERNBASE (will show setup later) result is address that can access second-level page table lookup in second-level page table PTX retrieves second-level page table index (= bits 10-20 of va ) if no second-level page table (present bit in fjrst-level = 0) create one (if alloc=1 ) or return null (if alloc=0 ) pgtab phys. // Return the address of the PTE in page table pgdir second-level PT // that corresponds to virtual address va. If alloc!=0, // create any required page table pages. { pde = &pgdir[PDX(va)]; if (*pde & PTE_P){ pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); } return &pgtab[PTX(va)]; } fjrst-level PT PDX(va) 26 static pte_t * walkpgdir(pde_t *pgdir, const void *va, int alloc) pde_t *pde; pgdir → pte_t *pgtab; pde → } else { ... /* create new second-level page table */

  49. xv6: creating second-level page tables return NULL if not trying to make new page table second-level permission bits can restrict further U for “user-mode” (in addition to kernel) W for “writable” (pages access via may be writable) P for “present” (valid) with physical address of second-level page table create a fjrst-level page entry present = 0 PTE = 0 clear the page table otherwise use kalloc to allocate it } ... *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U; // entries, if necessary. // be further restricted by the permissions in the page table // The permissions here are overly generous, but they can memset(pgtab, 0, PGSIZE); // Make sure all those PTE_P bits are zero. return 0; if (!alloc || (pgtab = (pte_t*)kalloc()) == 0) pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); if (*pde & PTE_P){ 27 } else {

  50. xv6: creating second-level page tables return NULL if not trying to make new page table second-level permission bits can restrict further U for “user-mode” (in addition to kernel) W for “writable” (pages access via may be writable) P for “present” (valid) with physical address of second-level page table create a fjrst-level page entry present = 0 PTE = 0 clear the page table otherwise use kalloc to allocate it } ... *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U; // entries, if necessary. // be further restricted by the permissions in the page table // The permissions here are overly generous, but they can memset(pgtab, 0, PGSIZE); // Make sure all those PTE_P bits are zero. return 0; if (!alloc || (pgtab = (pte_t*)kalloc()) == 0) pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); if (*pde & PTE_P){ 27 } else {

  51. xv6: creating second-level page tables } second-level permission bits can restrict further U for “user-mode” (in addition to kernel) W for “writable” (pages access via may be writable) P for “present” (valid) with physical address of second-level page table create a fjrst-level page entry clear the page table otherwise use kalloc to allocate it return NULL if not trying to make new page table *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U; ... // entries, if necessary. // be further restricted by the permissions in the page table // The permissions here are overly generous, but they can memset(pgtab, 0, PGSIZE); // Make sure all those PTE_P bits are zero. return 0; if (!alloc || (pgtab = (pte_t*)kalloc()) == 0) pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); if (*pde & PTE_P){ 28 PTE = 0 → present = 0 } else {

  52. xv6: creating second-level page tables return NULL if not trying to make new page table second-level permission bits can restrict further U for “user-mode” (in addition to kernel) W for “writable” (pages access via may be writable) P for “present” (valid) with physical address of second-level page table create a fjrst-level page entry present = 0 PTE = 0 clear the page table otherwise use kalloc to allocate it } ... // entries, if necessary. // be further restricted by the permissions in the page table // The permissions here are overly generous, but they can memset(pgtab, 0, PGSIZE); // Make sure all those PTE_P bits are zero. return 0; if (!alloc || (pgtab = (pte_t*)kalloc()) == 0) pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); if (*pde & PTE_P){ 28 } else { *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U;

  53. xv6: creating second-level page tables return NULL if not trying to make new page table second-level permission bits can restrict further U for “user-mode” (in addition to kernel) W for “writable” (pages access via may be writable) P for “present” (valid) with physical address of second-level page table create a fjrst-level page entry present = 0 PTE = 0 clear the page table otherwise use kalloc to allocate it } ... *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U; // entries, if necessary. // be further restricted by the permissions in the page table // The permissions here are overly generous, but they can memset(pgtab, 0, PGSIZE); // Make sure all those PTE_P bits are zero. return 0; if (!alloc || (pgtab = (pte_t*)kalloc()) == 0) pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); if (*pde & PTE_P){ 28 } else {

  54. xv6: setting last-level page entries pa += PGSIZE; and next virtual page ( va ) advance to next physical page ( pa ) and P for present with specifjed permission bits (write and/or user-mode) pointing to physical page at pa create page table entry make sure it’s not already set (or fail if out of memory) get its page table entry for each virtual page in range (va to va + size) } return 0; } a += PGSIZE; static int break ; if (a == last) *pte = pa | perm | PTE_P; panic("remap"); if (*pte & PTE_P) if ((pte = walkpgdir(pgdir, a, 1)) == 0) for (;;){ a = ( char *)PGROUNDDOWN((uint)va); { 29 mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm) char *a, *last; pte_t *pte; last = ( char *)PGROUNDDOWN(((uint)va) + size − 1); return − 1;

  55. xv6: setting last-level page entries pa += PGSIZE; and next virtual page ( va ) advance to next physical page ( pa ) and P for present with specifjed permission bits (write and/or user-mode) pointing to physical page at pa create page table entry make sure it’s not already set (or fail if out of memory) get its page table entry for each virtual page in range (va to va + size) } return 0; } a += PGSIZE; static int break ; if (a == last) *pte = pa | perm | PTE_P; panic("remap"); if (*pte & PTE_P) if ((pte = walkpgdir(pgdir, a, 1)) == 0) for (;;){ a = ( char *)PGROUNDDOWN((uint)va); { 29 mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm) char *a, *last; pte_t *pte; last = ( char *)PGROUNDDOWN(((uint)va) + size − 1); return − 1;

  56. xv6: setting last-level page entries pa += PGSIZE; and next virtual page ( va ) advance to next physical page ( pa ) and P for present with specifjed permission bits (write and/or user-mode) pointing to physical page at pa create page table entry make sure it’s not already set (or fail if out of memory) get its page table entry for each virtual page in range (va to va + size) } return 0; } a += PGSIZE; static int break ; if (a == last) *pte = pa | perm | PTE_P; panic("remap"); if (*pte & PTE_P) if ((pte = walkpgdir(pgdir, a, 1)) == 0) for (;;){ a = ( char *)PGROUNDDOWN((uint)va); { 29 mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm) char *a, *last; pte_t *pte; last = ( char *)PGROUNDDOWN(((uint)va) + size − 1); return − 1;

  57. xv6: setting last-level page entries pa += PGSIZE; and next virtual page ( va ) advance to next physical page ( pa ) and P for present with specifjed permission bits (write and/or user-mode) pointing to physical page at pa create page table entry make sure it’s not already set (or fail if out of memory) get its page table entry for each virtual page in range (va to va + size) } return 0; } a += PGSIZE; static int break ; if (a == last) *pte = pa | perm | PTE_P; panic("remap"); if (*pte & PTE_P) if ((pte = walkpgdir(pgdir, a, 1)) == 0) for (;;){ a = ( char *)PGROUNDDOWN((uint)va); { 29 mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm) char *a, *last; pte_t *pte; last = ( char *)PGROUNDDOWN(((uint)va) + size − 1); return − 1;

  58. xv6: setting last-level page entries pa += PGSIZE; and next virtual page ( va ) advance to next physical page ( pa ) and P for present with specifjed permission bits (write and/or user-mode) pointing to physical page at pa create page table entry make sure it’s not already set (or fail if out of memory) get its page table entry for each virtual page in range (va to va + size) } return 0; } a += PGSIZE; static int break ; if (a == last) *pte = pa | perm | PTE_P; panic("remap"); if (*pte & PTE_P) if ((pte = walkpgdir(pgdir, a, 1)) == 0) for (;;){ a = ( char *)PGROUNDDOWN((uint)va); { 29 mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm) char *a, *last; pte_t *pte; last = ( char *)PGROUNDDOWN(((uint)va) + size − 1); return − 1;

  59. xv6: setting process page tables step 1: create new page table with kernel mappings kernel code runs unchanged in every process’s address space mappings unaccessible in user mode step 2: load executable pages from executable fjle executable contains list of parts of fjle to load allocate new pages ( kalloc ) step 3: allocate pages for heap, stack 30

  60. xv6: setting process page tables step 1: create new page table with kernel mappings kernel code runs unchanged in every process’s address space mappings unaccessible in user mode step 2: load executable pages from executable fjle executable contains list of parts of fjle to load allocate new pages ( kalloc ) step 3: allocate pages for heap, stack 31

  61. create new page table (kernel mappings) pde_t* free everything on failure (no space for new second-level page tales) everything above address 0x8000 0000 iterate through list of kernel-space mappings initialize to 0 — every page invalid (“page directory”) allocate fjrst-level page table } return pgdir; } return 0; freevm(pgdir); for (k = kmap; k < &kmap[NELEM(kmap)]; k++) high"); too panic("PHYSTOP if (P2V(PHYSTOP) > ( void *)DEVSPACE) memset(pgdir, 0, PGSIZE); return 0; if ((pgdir = (pde_t*)kalloc()) == 0) { setupkvm( void ) 32 pde_t *pgdir; struct kmap *k; ␣ ␣ if (mappages(pgdir, k − >virt, k − >phys_end − k − >phys_start, (uint)k − >phys_start, k − >perm) < 0) {

  62. create new page table (kernel mappings) pde_t* free everything on failure (no space for new second-level page tales) everything above address 0x8000 0000 iterate through list of kernel-space mappings initialize to 0 — every page invalid (“page directory”) allocate fjrst-level page table } return pgdir; } return 0; freevm(pgdir); for (k = kmap; k < &kmap[NELEM(kmap)]; k++) high"); too panic("PHYSTOP if (P2V(PHYSTOP) > ( void *)DEVSPACE) memset(pgdir, 0, PGSIZE); return 0; if ((pgdir = (pde_t*)kalloc()) == 0) { setupkvm( void ) 32 pde_t *pgdir; struct kmap *k; ␣ ␣ if (mappages(pgdir, k − >virt, k − >phys_end − k − >phys_start, (uint)k − >phys_start, k − >perm) < 0) {

  63. create new page table (kernel mappings) pde_t* free everything on failure (no space for new second-level page tales) everything above address 0x8000 0000 iterate through list of kernel-space mappings initialize to 0 — every page invalid (“page directory”) allocate fjrst-level page table } return pgdir; } return 0; freevm(pgdir); for (k = kmap; k < &kmap[NELEM(kmap)]; k++) high"); too panic("PHYSTOP if (P2V(PHYSTOP) > ( void *)DEVSPACE) memset(pgdir, 0, PGSIZE); return 0; if ((pgdir = (pde_t*)kalloc()) == 0) { setupkvm( void ) 32 pde_t *pgdir; struct kmap *k; ␣ ␣ if (mappages(pgdir, k − >virt, k − >phys_end − k − >phys_start, (uint)k − >phys_start, k − >perm) < 0) {

  64. create new page table (kernel mappings) pde_t* free everything on failure (no space for new second-level page tales) everything above address 0x8000 0000 iterate through list of kernel-space mappings initialize to 0 — every page invalid (“page directory”) allocate fjrst-level page table } return pgdir; } return 0; freevm(pgdir); for (k = kmap; k < &kmap[NELEM(kmap)]; k++) high"); too panic("PHYSTOP if (P2V(PHYSTOP) > ( void *)DEVSPACE) memset(pgdir, 0, PGSIZE); return 0; if ((pgdir = (pde_t*)kalloc()) == 0) { setupkvm( void ) 32 pde_t *pgdir; struct kmap *k; ␣ ␣ if (mappages(pgdir, k − >virt, k − >phys_end − k − >phys_start, (uint)k − >phys_start, k − >perm) < 0) {

  65. create new page table (kernel mappings) pde_t* free everything on failure (no space for new second-level page tales) everything above address 0x8000 0000 iterate through list of kernel-space mappings initialize to 0 — every page invalid (“page directory”) allocate fjrst-level page table } return pgdir; } return 0; freevm(pgdir); for (k = kmap; k < &kmap[NELEM(kmap)]; k++) high"); too panic("PHYSTOP if (P2V(PHYSTOP) > ( void *)DEVSPACE) memset(pgdir, 0, PGSIZE); return 0; if ((pgdir = (pde_t*)kalloc()) == 0) { setupkvm( void ) 32 pde_t *pgdir; struct kmap *k; ␣ ␣ if (mappages(pgdir, k − >virt, k − >phys_end − k − >phys_start, (uint)k − >phys_start, k − >perm) < 0) {

  66. xv6: setting process page tables step 1: create new page table with kernel mappings kernel code runs unchanged in every process’s address space mappings unaccessible in user mode executable contains list of parts of fjle to load allocate new pages ( kalloc ) step 3: allocate pages for heap, stack 33 step 2: load executable pages from executable fjle

  67. reading executables (headers) uint paddr; }; uint align; uint flags; uint memsz; uint filesz; xv6 executables contain list of sections to load, represented by: 34 uint vaddr; uint off; uint type; struct proghdr { /* <-- debugging-only or not? */ /* <-- location in file */ /* <-- location in memory */ /* <-- confusing ignored field */ /* <-- amount to load */ /* <-- amount to allocate */ /* <-- readable/writeable (ignored) */

  68. reading executables (headers) xv6 executables contain list of sections to load, represented by: goto bad; if (loaduvm(pgdir, ( char *)ph.vaddr, ip, ph.off, ph.filesz) < 0) ... goto bad; if ((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) ... }; uint align; uint flags; uint memsz; uint filesz; uint paddr; uint vaddr; uint off; uint type; struct proghdr { 34 /* <-- debugging-only or not? */ /* <-- location in file */ /* <-- location in memory */ /* <-- confusing ignored field */ /* <-- amount to load */ /* <-- amount to allocate */ /* <-- readable/writeable (ignored) */

  69. allocating user pages } same function used to allocate memory for heap add page to second-level page table allocate a new, zero page } } return 0; kfree(mem); deallocuvm(pgdir, newsz, oldsz); (2)\n"); memory of out cprintf("allocuvm memset(mem, 0, PGSIZE); if (mappages(pgdir, ( char *)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){ return 0; out { ... a = PGROUNDUP(oldsz); for (; a < newsz; a += PGSIZE){ mem = kalloc(); if (mem == 0){ cprintf("allocuvm 35 deallocuvm(pgdir, newsz, oldsz); of memory\n"); allocuvm(pde_t *pgdir, uint oldsz, uint newsz) ␣ ␣ ␣ ␣ ␣ ␣ ␣

  70. allocating user pages } same function used to allocate memory for heap add page to second-level page table allocate a new, zero page } } return 0; kfree(mem); deallocuvm(pgdir, newsz, oldsz); (2)\n"); memory of out cprintf("allocuvm memset(mem, 0, PGSIZE); if (mappages(pgdir, ( char *)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){ return 0; out { ... a = PGROUNDUP(oldsz); for (; a < newsz; a += PGSIZE){ mem = kalloc(); if (mem == 0){ cprintf("allocuvm 35 deallocuvm(pgdir, newsz, oldsz); of memory\n"); allocuvm(pde_t *pgdir, uint oldsz, uint newsz) ␣ ␣ ␣ ␣ ␣ ␣ ␣

  71. allocating user pages } same function used to allocate memory for heap add page to second-level page table allocate a new, zero page } } return 0; kfree(mem); deallocuvm(pgdir, newsz, oldsz); (2)\n"); memory of out cprintf("allocuvm memset(mem, 0, PGSIZE); if (mappages(pgdir, ( char *)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){ return 0; out { ... a = PGROUNDUP(oldsz); for (; a < newsz; a += PGSIZE){ mem = kalloc(); if (mem == 0){ cprintf("allocuvm 35 deallocuvm(pgdir, newsz, oldsz); of memory\n"); allocuvm(pde_t *pgdir, uint oldsz, uint newsz) ␣ ␣ ␣ ␣ ␣ ␣ ␣

  72. allocating user pages } same function used to allocate memory for heap add page to second-level page table allocate a new, zero page } } return 0; kfree(mem); deallocuvm(pgdir, newsz, oldsz); (2)\n"); memory of out cprintf("allocuvm memset(mem, 0, PGSIZE); if (mappages(pgdir, ( char *)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){ return 0; out { ... a = PGROUNDUP(oldsz); for (; a < newsz; a += PGSIZE){ mem = kalloc(); if (mem == 0){ cprintf("allocuvm 35 deallocuvm(pgdir, newsz, oldsz); of memory\n"); allocuvm(pde_t *pgdir, uint oldsz, uint newsz) ␣ ␣ ␣ ␣ ␣ ␣ ␣

  73. reading executables (headers) xv6 executables contain list of sections to load, represented by: goto bad; if (loaduvm(pgdir, ( char *)ph.vaddr, ip, ph.off, ph.filesz) < 0) ... goto bad; if ((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) ... }; uint align; uint flags; uint memsz; uint filesz; uint paddr; uint vaddr; uint off; uint type; struct proghdr { 36 /* <-- debugging-only or not? */ /* <-- location in file */ /* <-- location in memory */ /* <-- confusing ignored field */ /* <-- amount to load */ /* <-- amount to allocate */ /* <-- readable/writeable (ignored) */

  74. loading user pages from executable n = PGSIZE; P2V(pa) — mapping of physical addresss in kernel memory copy from fjle (represented by struct inode ) into memory then into a virtual address again) (instead of turning it into a physical address, exercise: why don’t we just use addr directly? look up address to load into already allocated earlier get page table entry being loaded } return 0; } if (readi(ip, P2V(pa), offset+i, n) != n) else 37 if ((pte = walkpgdir(pgdir, addr+i, 0)) == 0) { pa = PTE_ADDR(*pte); ... exist"); for (i = 0; i < sz; i += PGSIZE){ should address panic("loaduvm: loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) ␣ ␣ ␣ if (sz − i < PGSIZE) n = sz − i; return − 1;

  75. loading user pages from executable n = PGSIZE; P2V(pa) — mapping of physical addresss in kernel memory copy from fjle (represented by struct inode ) into memory then into a virtual address again) (instead of turning it into a physical address, exercise: why don’t we just use addr directly? look up address to load into already allocated earlier get page table entry being loaded } return 0; } if (readi(ip, P2V(pa), offset+i, n) != n) else 37 if ((pte = walkpgdir(pgdir, addr+i, 0)) == 0) { pa = PTE_ADDR(*pte); ... exist"); for (i = 0; i < sz; i += PGSIZE){ should address panic("loaduvm: loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) ␣ ␣ ␣ if (sz − i < PGSIZE) n = sz − i; return − 1;

  76. loading user pages from executable n = PGSIZE; P2V(pa) — mapping of physical addresss in kernel memory copy from fjle (represented by struct inode ) into memory then into a virtual address again) (instead of turning it into a physical address, exercise: why don’t we just use addr directly? look up address to load into already allocated earlier get page table entry being loaded } return 0; } if (readi(ip, P2V(pa), offset+i, n) != n) else 37 if ((pte = walkpgdir(pgdir, addr+i, 0)) == 0) { pa = PTE_ADDR(*pte); ... exist"); for (i = 0; i < sz; i += PGSIZE){ should address panic("loaduvm: loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) ␣ ␣ ␣ if (sz − i < PGSIZE) n = sz − i; return − 1;

  77. loading user pages from executable n = PGSIZE; P2V(pa) — mapping of physical addresss in kernel memory copy from fjle (represented by struct inode ) into memory then into a virtual address again) (instead of turning it into a physical address, exercise: why don’t we just use addr directly? look up address to load into already allocated earlier get page table entry being loaded } return 0; } if (readi(ip, P2V(pa), offset+i, n) != n) else 37 if ((pte = walkpgdir(pgdir, addr+i, 0)) == 0) { pa = PTE_ADDR(*pte); ... exist"); for (i = 0; i < sz; i += PGSIZE){ should address panic("loaduvm: loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) ␣ ␣ ␣ if (sz − i < PGSIZE) n = sz − i; return − 1;

  78. kalloc/kfree kalloc/kfree — xv6’s physical memory allocator keep linked list of free pages list nodes — stored in corresponding free page itself kalloc — return fjrst page in list kfree — add page to list linked list created at boot usuable memory fjxed size (224MB) determined by PHYSTOP in memlayout.h 38 allocates/deallocates whole pages only

  79. xv6 program memory invalid adjusted by sbrk() system call myproc()->sz initial stack pointer 39 KERNBASE argument 0 ... heap argument N nul-terminated string 0 address of argument 0 argv[argc] ... address of argument N argv[0] stack PAGESIZE address of address of argv argument of main guard page argument 0 argc argument of main argc data 0xFFFFFFF return PC for main (empty) text 0

  80. xv6 program memory invalid myproc()->sz initial stack pointer 39 KERNBASE argument 0 ← adjusted by sbrk() system call ... heap argument N nul-terminated string 0 address of argument 0 argv[argc] ... address of argument N argv[0] stack PAGESIZE address of address of argv argument of main guard page argument 0 argc argument of main argc data 0xFFFFFFF return PC for main (empty) text 0

  81. xv6 heap allocation xv6: every process has a heap at the top of its address space yes, this is unlike Linux where heap is below stack tracked in struct proc with sz = last valid address in process position changed via sbrk(amount) system call sets sz += amount same call exists in Linux, etc. — but also others 40

  82. sbrk sys_sbrk() { if (argint(0, &n) < 0) if (growproc(n) < 0) return addr; } sz : current top of heap sbrk(N) : grow heap by (shrink if negative) returns old top of heap (or -1 on out-of-memory) 41 return − 1; addr = myproc() − >sz; return − 1;

Recommend


More recommend