9 typedef uintptr_t paddr_t;
10 typedef uintptr_t vaddr_t;
12 extern uintptr_t _kernel_end;
13 extern uintptr_t _kernel_vma;
14 extern uintptr_t _kernel_phys_end;
15 extern uintptr_t _kernel_size;
16 extern uintptr_t _asm_physmap;
18 extern void *bios_ebda;
20 /* These are in memx64.s */
21 extern void flush_tlb(void *va);
22 extern void switch_address_space(uintptr_t cr3);
26 /* map one physical page to a virtual address */
27 #define PHY2VIRTP(pa) ( (void *)(((paddr_t)pa) + memory.physmap) )
28 /* only works for the linear mapped physical memory */
29 #define VIRTP2PHY(va) ( (paddr_t)(((vaddr_t)(va)) - memory.physmap) )
30 #define KB(x) ((x) * (1<<10))
31 #define MB(x) ((x) * (1<<20))
32 #define GB(x) (((uint64_t)x) * (1ULL<<30))
33 #define TB(x) (((uint64_t)x) * (1ULL<<40))
34 uintptr_t mem_align(uintptr_t a, size_t alignment);
37 * kernel is at 0xFFFFFFFF80000000 and up
38 * we will map in all physical memory below that
41 /* structure of physical frames */
44 void *paddr; /* the physical address of the frame */
51 /* TODO fix these types. maybe add a physvend */
53 void *kbase; /* at 0xFFFFFFFF00000000 */
54 void *kstack; /* grow down from -1 ? */
55 uintptr_t kend; /* virtual address of top of kernel */
56 uintptr_t kphysend; /* physical address of top of kernel */
57 uintptr_t phys_max; /* maximum (usable) physical address + 1 */
58 uintptr_t physmap; /* all physical memory is mapped starting here */
59 /* kbase + kernel size ?, then put dynamic kernel structures above that,
60 * growing toward the stack?
64 /* TODO keep track of the kernel virtual address of page, we could
65 * re-alloc it in the same spot
68 paddr_t page_addr[510]; /* physical addresses of frames */
69 size_t pages; /* free pages in this stack frame */
70 struct pstack *next; /* address of next stack frame */
75 * if there is no room in the stack, then
76 * set the phys.stack.next to the new page
77 * map the new page in at phys.stack
78 * then add to phys.stack.pages
79 * the physical address to the stack.pages
82 * if there are no pages free on the stack:
83 * map in the phys.stack.next to phys.stack
84 * hand out the old page, which is on pages[free]
86 * it's probably worth memoizing the virtual address
87 * of the exact place where the stack vm map page is stored
90 extern struct memory memory;
92 /* physical memory manager */
97 int64_t offset; /* paddr = vaddr + offset */
100 vaddr_t kmap; /* physical address of page table entry for *stack */
101 vaddr_t *page_map; /* temporary page map space */
102 struct pstack *stack; /* virtual address of top of page stack */
103 size_t free; /* total number of free pages */
111 extern struct memory memory;
112 extern struct phys phys;
116 * add - add a contiguous chunk of physical memory and a virtual address base.
117 * alloc - get a page of memory
118 * free - free a page of memory
119 * tinyalloc - get a really small page, 256 bytes
123 /* TODO lazy setup of the memory block stack */
124 /* TODO modify phys_init to be "more core" to support
125 * discontiguous memory addresses
128 /* These don't have to be the same as the hardware paging, but
131 /* Hmm, need to map in memory for this to work */
137 uint64_t getcr3(); /* probably in assembly */
139 paddr_t create_addrspace(void);
142 void test_address(void *);
143 void phys_init(struct multiboot_info *mbi);
146 void pfree(paddr_t vmem);
147 void *koalloc(size_t size);
148 void kofree(void *, size_t size);
149 void dumpostacks(int f, int t);
151 uint64_t makecr3(void *pml4) ;
152 void *virt2phys(void *vaddr) ;
154 extern uint64_t kernel_space; /* physical address of kernel space? */
155 #define MEM_KERNEL (kernel_space)
156 #define KERNEL_PML4 ((struct pml4t *)PHY2VIRTP(kernel_space))
158 extern paddr_t pci_start;
161 uint64_t reslow:3; /* should be cleared to zero */
162 uint64_t pwt:1; /* page writethrough */
163 uint64_t pcd:1; /* page cache disable */
164 uint64_t resmed:7; /* clear to zero */
165 uint64_t addr:40; /* pml4 page base physical address shifted right 12 */
166 uint64_t reshigh:12; /* clear to zero */
169 /* TODO last bit (63) is actually a no-execute bit */
180 uint64_t addr:40; /* pml4 page base physical address shifted right 12 */
181 uint64_t reshigh:12; /* clear to zero */
192 uint64_t ps:1; /* I think this is the PS bit: 0 for 4KB or 2MB, 1 for 1GB */
195 uint64_t addr:40; /* pml4 page base physical address shifted right 12 */
196 uint64_t reshigh:12; /* clear to zero */
207 uint64_t ps:1; /* I think this is the PS bit: 0 for 4KB */
210 uint64_t addr:40; /* pml4 page base physical address shifted right 12 */
211 uint64_t reshigh:12; /* clear to zero */
225 uint64_t addr:40; /* pml4 page base physical address shifted right 12 */
226 uint64_t reshigh:12; /* clear to zero */
230 struct pml4e pml4e[512];
234 struct pdpe pdpe[512];
245 struct vaddr_decode {
246 /* broken down virtual address */
247 int pml4offset, pdpoffset, pdoffset, ptoffset;
248 paddr_t offset; /* physical page offset */
250 struct pml4t *pml4t; /* pml4 base address */
251 paddr_t pml4_phys; /* pml4 physical base address */
253 struct pml4e pml4e; /* entry in page map level 4 */
254 /* at pml4 + 8 * pml4offset */
256 struct pdpe pdpe; /* entry in page directory pointer table */
257 /* at virt(pml4e.addr) + 8 * pdpoffset */
258 /* does not exist unless pml4e.present */
259 /* pdpe.ps == 1 means 1 GB pages, and the next level doesn't exist */
260 /* offset = vaddr & 0x3fffffff, physical page = standard - offset */
262 struct pde pde; /* entry in page directory table */
263 /* at virt(pdpe.addr) + 8 * pdoffset */
264 /* does not exist unless pdpe.present */
265 /* pde.ps == 0 means 4 KB pages and the next level exists if present */
266 /* pds.ps == 1 means 2 MB pages, pts doesn't exist and
267 * offset = vaddr & 0x1fffff; i.e. low 21 bits
268 * physical page address = same mask minus offset bits
271 struct pte pte; /* entry in page table */
272 /* at virt(pde.addr) + 8 * ptoffset */
273 /* does not exist unless pde.present */
274 /* offset = vaddr & 0xfff; i.e. low 12 bits */
275 /* physical page address = pde.addr, or vaddr & 0xffffffffff000 */
277 struct pte *pteptr; /* a pointer to the actual entry */
279 /* actual physical addresses */
284 int present; /* physical address actually mapped */
285 paddr_t paddr; /* decoded physical address */
287 paddr_t page; /* physical address of page */
291 void decode_vaddr(struct vaddr_decode *ds, uint64_t space, vaddr_t vaddr);
292 void print_decode(struct vaddr_decode *ds, uint64_t space, vaddr_t vaddr);
294 /* returns addr. addr may be null in which case the function will allocate virtual space */
295 void *map_page(uint64_t space, vaddr_t addr, paddr_t pa, unsigned int flags);
296 void vmapz(uint64_t space, vaddr_t addr, size_t length, unsigned int flags);
298 #define PT_PRESENT 0x1
299 #define MEM_PCD (1<<4)
300 #define MEM_PWT (1<<3)
301 #define MEM_USER (1<<2)
302 #define MEM_RW (1<<1)
303 #define MAP_TRACE (1<<16)
305 #define MEM_NOCACHE (MEM_PCD | MEM_PWT)
306 #define MEM_MMIO (PT_PRESENT|MEM_NOCACHE|MEM_RW)
307 #define MEM_USERSPACE (MEM_USER | MEM_RW)
310 typedef struct page {
311 u32int present : 1; // Page present in memory
312 u32int rw : 1; // Read-only if clear, readwrite if set
313 u32int user : 1; // Supervisor level only if clear
314 u32int accessed : 1; // Has the page been accessed since last refresh?
315 u32int dirty : 1; // Has the page been written to since last refresh?
316 u32int unused : 7; // Amalgamation of unused and reserved bits
317 u32int frame : 20; // Frame address (shifted right 12 bits)
322 struct bios_data_area {
325 uint16_t ebda; /* <<4 to get actual */