coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pgtbl.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <cbfs.h>
4 #include <commonlib/helpers.h>
5 #include <console/console.h>
6 #include <arch/cpu.h>
7 #include <cpu/x86/cr.h>
8 #include <cpu/x86/msr.h>
9 #include <cpu/x86/pae.h>
10 #include <string.h>
11 #include <symbols.h>
12 #include <assert.h>
13 
14 #define PDPTE_PRES (1ULL << 0)
15 #define PDPTE_ADDR_MASK (~((1ULL << 12) - 1))
16 
17 #define PDE_PRES (1ULL << 0)
18 #define PDE_RW (1ULL << 1)
19 #define PDE_US (1ULL << 2)
20 #define PDE_PWT (1ULL << 3)
21 #define PDE_PCD (1ULL << 4)
22 #define PDE_A (1ULL << 5)
23 #define PDE_D (1ULL << 6) // only valid with PS=1
24 #define PDE_PS (1ULL << 7)
25 #define PDE_G (1ULL << 8) // only valid with PS=1
26 #define PDE_PAT (1ULL << 12) // only valid with PS=1
27 #define PDE_XD (1ULL << 63)
28 #define PDE_ADDR_MASK (~((1ULL << 12) - 1))
29 
30 #define PTE_PRES (1ULL << 0)
31 #define PTE_RW (1ULL << 1)
32 #define PTE_US (1ULL << 2)
33 #define PTE_PWT (1ULL << 3)
34 #define PTE_PCD (1ULL << 4)
35 #define PTE_A (1ULL << 5)
36 #define PTE_D (1ULL << 6)
37 #define PTE_PAT (1ULL << 7)
38 #define PTE_G (1ULL << 8)
39 #define PTE_XD (1ULL << 63)
40 
41 #define PDPTE_IDX_SHIFT 30
42 #define PDPTE_IDX_MASK 0x3
43 
44 #define PDE_IDX_SHIFT 21
45 #define PDE_IDX_MASK 0x1ff
46 
47 #define PTE_IDX_SHIFT 12
48 #define PTE_IDX_MASK 0x1ff
49 
50 #define OVERLAP(a, b, s, e) ((b) > (s) && (a) < (e))
51 
52 static const size_t s2MiB = 2 * MiB;
53 static const size_t s4KiB = 4 * KiB;
54 
55 struct pde {
59 struct pg_table {
60  struct pde pd[2048];
61  struct pde pdp[512];
62 } __packed;
63 
65 {
66  /* Load the page table address */
67  write_cr3(cr3);
69 }
70 
72 {
73  CRx_TYPE cr0;
74  CRx_TYPE cr4;
75 
76  /* Enable PAE */
77  cr4 = read_cr4();
78  cr4 |= CR4_PAE;
79  write_cr4(cr4);
80 
81  /* Enable Paging */
82  cr0 = read_cr0();
83  cr0 |= CR0_PG;
84  write_cr0(cr0);
85 }
86 
88 {
89  CRx_TYPE cr0;
90  CRx_TYPE cr4;
91 
92  /* Disable Paging */
93  cr0 = read_cr0();
94  cr0 &= ~(CRx_TYPE)CR0_PG;
95  write_cr0(cr0);
96 
97  /* Disable PAE */
98  cr4 = read_cr4();
99  cr4 &= ~(CRx_TYPE)CR4_PAE;
100  write_cr4(cr4);
101 }
102 
103 /*
104  * Use PAE to map a page and then memset it with the pattern specified.
105  * In order to use PAE pagetables for virtual addressing are set up and reloaded
106  * on a 2MiB boundary. After the function is done, virtual addressing mode is
107  * disabled again. The PAT are set to all cacheable, but MTRRs still apply.
108  *
109  * Requires a scratch memory for pagetables and a virtual address for
110  * non identity mapped memory.
111  *
112  * The scratch memory area containing pagetables must not overlap with the
113  * memory range to be cleared.
114  * The scratch memory area containing pagetables must not overlap with the
115  * virtual address for non identity mapped memory.
116  *
117  * @param vmem_addr Where the virtual non identity mapped page resides, must
118  * be 2 aligned MiB and at least 2 MiB in size.
119  * Content at physical address is preserved.
120  * @param pgtbl Where pagetables reside, must be 4 KiB aligned and 20 KiB in
121  * size.
122  * Must not overlap memory range pointed to by dest.
123  * Must not overlap memory range pointed to by vmem_addr.
124  * Content at physical address isn't preserved.
125  * @param length The length of the memory segment to memset
126  * @param dest Physical memory address to memset
127  * @param pat The pattern to write to the physical memory
128  * @return 0 on success, 1 on error
129  */
130 int memset_pae(uint64_t dest, unsigned char pat, uint64_t length, void *pgtbl,
131  void *vmem_addr)
132 {
133  struct pg_table *pgtbl_buf = (struct pg_table *)pgtbl;
134  ssize_t offset;
135 
136  printk(BIOS_DEBUG, "%s: Using virtual address %p as scratchpad\n",
137  __func__, vmem_addr);
138  printk(BIOS_DEBUG, "%s: Using address %p for page tables\n",
139  __func__, pgtbl_buf);
140 
141  /* Cover some basic error conditions */
142  if (!IS_ALIGNED((uintptr_t)pgtbl_buf, s4KiB) ||
143  !IS_ALIGNED((uintptr_t)vmem_addr, s2MiB)) {
144  printk(BIOS_ERR, "%s: Invalid alignment\n", __func__);
145  return 1;
146  }
147  const uintptr_t pgtbl_s = (uintptr_t)pgtbl_buf;
148  const uintptr_t pgtbl_e = pgtbl_s + sizeof(struct pg_table);
149 
150  if (OVERLAP(dest, dest + length, pgtbl_s, pgtbl_e)) {
151  printk(BIOS_ERR, "%s: destination overlaps page tables\n",
152  __func__);
153  return 1;
154  }
155 
156  if (OVERLAP((uintptr_t)vmem_addr, (uintptr_t)vmem_addr + s2MiB,
157  pgtbl_s, pgtbl_e)) {
158  printk(BIOS_ERR, "%s: vmem address overlaps page tables\n",
159  __func__);
160  return 1;
161  }
162 
164 
165  struct pde *pd = pgtbl_buf->pd, *pdp = pgtbl_buf->pdp;
166  /* Point the page directory pointers at the page directories. */
167  memset(pgtbl_buf->pdp, 0, sizeof(pgtbl_buf->pdp));
168 
169  pdp[0].addr_lo = ((uintptr_t)&pd[512*0]) | PDPTE_PRES;
170  pdp[1].addr_lo = ((uintptr_t)&pd[512*1]) | PDPTE_PRES;
171  pdp[2].addr_lo = ((uintptr_t)&pd[512*2]) | PDPTE_PRES;
172  pdp[3].addr_lo = ((uintptr_t)&pd[512*3]) | PDPTE_PRES;
173 
174  offset = dest - ALIGN_DOWN(dest, s2MiB);
175  dest = ALIGN_DOWN(dest, s2MiB);
176 
177  /* Identity map the whole 32-bit address space */
178  for (size_t i = 0; i < 2048; i++) {
179  pd[i].addr_lo = (i << PDE_IDX_SHIFT) | PDE_PS | PDE_PRES | PDE_RW;
180  pd[i].addr_hi = 0;
181  }
182 
183  /* Get pointer to PD that's not identity mapped */
184  pd = &pgtbl_buf->pd[((uintptr_t)vmem_addr) >> PDE_IDX_SHIFT];
185 
187 
188  do {
189  const size_t len = MIN(length, s2MiB - offset);
190 
191  /*
192  * Map a page using PAE at virtual address vmem_addr.
193  * dest is already 2 MiB aligned.
194  */
195  pd->addr_lo = dest | PDE_PS | PDE_PRES | PDE_RW;
196  pd->addr_hi = dest >> 32;
197 
198  /* Update page tables */
199  asm volatile ("invlpg (%0)" :: "b"(vmem_addr) : "memory");
200 
201  printk(BIOS_SPEW, "%s: Clearing %llx[%lx] - %zx\n", __func__,
202  dest + offset, (uintptr_t)vmem_addr + offset, len);
203 
204  memset(vmem_addr + offset, pat, len);
205 
206  dest += s2MiB;
207  length -= len;
208  offset = 0;
209  } while (length > 0);
210 
212 
213  return 0;
214 }
215 
216 #if ENV_RAMSTAGE
217 void *map_2M_page(unsigned long page)
218 {
219  struct pde {
222  } __packed;
223  struct pg_table {
224  struct pde pd[2048];
225  struct pde pdp[512];
226  } __packed;
227 
228  static struct pg_table pgtbl[CONFIG_MAX_CPUS]
229  __attribute__((aligned(4096)));
230  static unsigned long mapped_window[CONFIG_MAX_CPUS];
231  int index;
232  unsigned long window;
233  void *result;
234  int i;
235  index = cpu_index();
236  if (index < 0)
237  return MAPPING_ERROR;
238  window = page >> 10;
239  if (window != mapped_window[index]) {
241  if (window > 1) {
242  struct pde *pd, *pdp;
243  /* Point the page directory pointers at the page
244  * directories
245  */
246  memset(&pgtbl[index].pdp, 0, sizeof(pgtbl[index].pdp));
247  pd = pgtbl[index].pd;
248  pdp = pgtbl[index].pdp;
249  pdp[0].addr_lo = ((uintptr_t)&pd[512*0])|1;
250  pdp[1].addr_lo = ((uintptr_t)&pd[512*1])|1;
251  pdp[2].addr_lo = ((uintptr_t)&pd[512*2])|1;
252  pdp[3].addr_lo = ((uintptr_t)&pd[512*3])|1;
253  /* The first half of the page table is identity mapped
254  */
255  for (i = 0; i < 1024; i++) {
256  pd[i].addr_lo = ((i & 0x3ff) << 21) | 0xE3;
257  pd[i].addr_hi = 0;
258  }
259  /* The second half of the page table holds the mapped
260  * page
261  */
262  for (i = 1024; i < 2048; i++) {
263  pd[i].addr_lo = ((window & 1) << 31)
264  | ((i & 0x3ff) << 21) | 0xE3;
265  pd[i].addr_hi = (window >> 1);
266  }
268  }
269  mapped_window[index] = window;
270  }
271  if (window == 0)
272  result = (void *)(page << 21);
273  else
274  result = (void *)(0x80000000 | ((page & 0x3ff) << 21));
275  return result;
276 }
277 #endif
278 
279 void paging_set_nxe(int enable)
280 {
281  msr_t msr = rdmsr(IA32_EFER);
282 
283  if (enable)
284  msr.lo |= EFER_NXE;
285  else
286  msr.lo &= ~EFER_NXE;
287 
288  wrmsr(IA32_EFER, msr);
289 }
290 
292 {
293  msr_t msr;
294  msr.lo = pat;
295  msr.hi = pat >> 32;
296  wrmsr(IA32_PAT, msr);
297 }
298 
299 /* PAT encoding used in util/x86/x86_page_tables.go. It matches the linux
300  * kernel settings:
301  * PTE encoding:
302  * PAT
303  * |PCD
304  * ||PWT PAT
305  * ||| slot
306  * 000 0 WB : _PAGE_CACHE_MODE_WB
307  * 001 1 WC : _PAGE_CACHE_MODE_WC
308  * 010 2 UC-: _PAGE_CACHE_MODE_UC_MINUS
309  * 011 3 UC : _PAGE_CACHE_MODE_UC
310  * 100 4 WB : Reserved
311  * 101 5 WP : _PAGE_CACHE_MODE_WP
312  * 110 6 UC-: Reserved
313  * 111 7 WT : _PAGE_CACHE_MODE_WT
314  */
316 {
317  uint64_t pat = PAT_ENCODE(WB, 0) | PAT_ENCODE(WC, 1) |
318  PAT_ENCODE(UC_MINUS, 2) | PAT_ENCODE(UC, 3) |
319  PAT_ENCODE(WB, 4) | PAT_ENCODE(WP, 5) |
320  PAT_ENCODE(UC_MINUS, 6) | PAT_ENCODE(WT, 7);
321  paging_set_pat(pat);
322 }
323 
324 int paging_enable_for_car(const char *pdpt_name, const char *pt_name)
325 {
327  return -1;
328 
329  if (!cbfs_load(pdpt_name, _pdpt, REGION_SIZE(pdpt))) {
330  printk(BIOS_ERR, "Couldn't load pdpt\n");
331  return -1;
332  }
333 
334  if (!cbfs_load(pt_name, _pagetables, REGION_SIZE(pagetables))) {
335  printk(BIOS_ERR, "Couldn't load page tables\n");
336  return -1;
337  }
338 
340 
341  return 0;
342 }
343 
344 static void *get_pdpt_addr(void)
345 {
347  return _pdpt;
348  return (void *)(uintptr_t)read_cr3();
349 }
350 
351 static uint64_t pde_pat_flags(int pat)
352 {
353  switch (pat) {
354  case PAT_UC:
355  return 0 | PDE_PCD | PDE_PWT;
356  case PAT_WC:
357  return 0 | 0 | PDE_PWT;
358  case PAT_WT:
359  return PDE_PAT | PDE_PCD | PDE_PWT;
360  case PAT_WP:
361  return PDE_PAT | 0 | PDE_PWT;
362  case PAT_WB:
363  return 0 | 0 | 0;
364  case PAT_UC_MINUS:
365  return 0 | PDE_PCD | 0;
366  default:
367  printk(BIOS_ERR, "PDE PAT defaulting to WB: %x\n", pat);
368  return pde_pat_flags(PAT_WB);
369  }
370 }
371 
372 static uint64_t pde_page_flags(int pat)
373 {
374  uint64_t flags = PDE_PS | PDE_PRES | PDE_RW | PDE_A | PDE_D;
375 
376  return flags | pde_pat_flags(pat);
377 }
378 
379 static uint64_t pte_pat_flags(int pat)
380 {
381  switch (pat) {
382  case PAT_UC:
383  return 0 | PTE_PCD | PTE_PWT;
384  case PAT_WC:
385  return 0 | 0 | PTE_PWT;
386  case PAT_WT:
387  return PTE_PAT | PTE_PCD | PTE_PWT;
388  case PAT_WP:
389  return PTE_PAT | 0 | PTE_PWT;
390  case PAT_WB:
391  return 0 | 0 | 0;
392  case PAT_UC_MINUS:
393  return 0 | PTE_PCD | 0;
394  default:
395  printk(BIOS_ERR, "PTE PAT defaulting to WB: %x\n", pat);
396  return pte_pat_flags(PAT_WB);
397  }
398 }
399 
400 static uint64_t pte_page_flags(int pat)
401 {
402  uint64_t flags = PTE_PRES | PTE_RW | PTE_A | PTE_D;
403  return flags | pte_pat_flags(pat);
404 }
405 
406 /* Identity map an address. This function does not handle splitting or adding
407  * new pages to the page tables. It's assumed all the page tables are already
408  * seeded with the correct amount and topology. */
409 static int identity_map_one_page(uintptr_t base, size_t size, int pat,
410  int commit)
411 {
412  uint64_t (*pdpt)[4];
413  uint64_t pdpte;
414  uint64_t (*pd)[512];
415  uint64_t pde;
416 
417  pdpt = get_pdpt_addr();
418 
419  pdpte = (*pdpt)[(base >> PDPTE_IDX_SHIFT) & PDPTE_IDX_MASK];
420 
421  /* No page table page allocation. */
422  if (!(pdpte & PDPTE_PRES))
423  return -1;
424 
425  pd = (void *)(uintptr_t)(pdpte & PDPTE_ADDR_MASK);
426 
427  /* Map in a 2MiB page. */
428  if (size == s2MiB) {
429  if (!commit)
430  return 0;
431  pde = base;
432  pde |= pde_page_flags(pat);
433  (*pd)[(base >> PDE_IDX_SHIFT) & PDE_IDX_MASK] = pde;
434  return 0;
435  }
436 
437  if (size == s4KiB) {
438  uint64_t (*pt)[512];
439  uint64_t pte;
440 
441  pde = (*pd)[(base >> PDE_IDX_SHIFT) & PDE_IDX_MASK];
442 
443  /* No page table page allocation. */
444  if (!(pde & PDE_PRES)) {
445  printk(BIOS_ERR, "Cannot allocate page table for pde %p\n",
446  (void *)base);
447  return -1;
448  }
449 
450  /* No splitting pages */
451  if (pde & PDE_PS) {
452  printk(BIOS_ERR, "Cannot split pde %p\n", (void *)base);
453  return -1;
454  }
455 
456  if (!commit)
457  return 0;
458 
459  pt = (void *)(uintptr_t)(pde & PDE_ADDR_MASK);
460  pte = base;
461  pte |= pte_page_flags(pat);
462  (*pt)[(base >> PTE_IDX_SHIFT) & PTE_IDX_MASK] = pte;
463 
464  return 0;
465  }
466 
467  return -1;
468 }
469 
470 static int _paging_identity_map_addr(uintptr_t base, size_t size, int pat,
471  int commit)
472 {
473  while (size != 0) {
474  size_t map_size;
475 
476  map_size = IS_ALIGNED(base, s2MiB) ? s2MiB : s4KiB;
477  map_size = MIN(size, map_size);
478 
479  if (identity_map_one_page(base, map_size, pat, commit) < 0)
480  return -1;
481 
482  base += map_size;
483  size -= map_size;
484  }
485 
486  return 0;
487 }
488 
489 static int paging_is_enabled(void)
490 {
491  return !!(read_cr0() & CR0_PG);
492 }
493 
494 int paging_identity_map_addr(uintptr_t base, size_t size, int pat)
495 {
496  if (!paging_is_enabled()) {
497  printk(BIOS_ERR, "Paging is not enabled.\n");
498  return -1;
499  }
500 
501  if (!IS_ALIGNED(base, s2MiB) && !IS_ALIGNED(base, s4KiB)) {
502  printk(BIOS_ERR, "base %p is not aligned.\n", (void *)base);
503  return -1;
504  }
505 
506  if (!IS_ALIGNED(size, s2MiB) && !IS_ALIGNED(size, s4KiB)) {
507  printk(BIOS_ERR, "size %zx is not aligned.\n", size);
508  return -1;
509  }
510 
511  /* First try without committing. If success commit. */
512  if (_paging_identity_map_addr(base, size, pat, 0))
513  return -1;
514 
515  return _paging_identity_map_addr(base, size, pat, 1);
516 }
#define WT
Definition: StmApi.h:294
#define WP
Definition: StmApi.h:295
#define WC
Definition: StmApi.h:293
#define UC
Definition: StmApi.h:297
int cpu_index(void)
Definition: cpu.c:332
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
#define IS_ALIGNED(x, a)
Definition: helpers.h:19
#define MIN(a, b)
Definition: helpers.h:37
#define ALIGN_DOWN(x, a)
Definition: helpers.h:18
#define MiB
Definition: helpers.h:76
#define KiB
Definition: helpers.h:75
static size_t cbfs_load(const char *name, void *buf, size_t size)
Definition: cbfs.h:282
#define printk(level,...)
Definition: stdlib.h:16
#define CR4_PAE
Definition: cr.h:119
static __always_inline void write_cr3(CRx_TYPE data)
Definition: cr.h:67
#define CR0_PG
Definition: cr.h:111
static __always_inline CRx_TYPE read_cr3(void)
Definition: cr.h:55
static __always_inline void write_cr4(CRx_TYPE data)
Definition: cr.h:88
static __always_inline CRx_TYPE read_cr4(void)
Definition: cr.h:76
#define CRx_TYPE
Definition: cr.h:17
static __always_inline void write_cr0(CRx_TYPE data)
Definition: cr.h:33
static __always_inline CRx_TYPE read_cr0(void)
Definition: cr.h:21
static size_t offset
Definition: flashconsole.c:16
uint64_t length
Definition: fw_cfg_if.h:1
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define IA32_EFER
Definition: msr.h:10
#define IA32_PAT
Definition: msr.h:58
#define EFER_NXE
Definition: msr.h:11
static __always_inline void wrmsr(unsigned int index, msr_t msr)
Definition: msr.h:157
static int preram_symbols_available(void)
Definition: symbols.h:83
#define REGION_SIZE(name)
Definition: symbols.h:10
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
@ WB
Definition: mdssreg.h:365
result
Definition: mrc_cache.c:35
#define PAT_ENCODE(type, idx)
Definition: pae.h:26
#define PAT_UC
Definition: pae.h:20
#define PAT_UC_MINUS
Definition: pae.h:25
#define PAT_WP
Definition: pae.h:23
void * map_2M_page(unsigned long page)
#define PAT_WT
Definition: pae.h:22
#define PAT_WB
Definition: pae.h:24
#define MAPPING_ERROR
Definition: pae.h:43
#define PAT_WC
Definition: pae.h:21
#define PDPTE_PRES
Definition: pgtbl.c:14
static int _paging_identity_map_addr(uintptr_t base, size_t size, int pat, int commit)
Definition: pgtbl.c:470
#define PDE_D
Definition: pgtbl.c:23
#define PDE_IDX_SHIFT
Definition: pgtbl.c:44
void paging_set_default_pat(void)
Definition: pgtbl.c:315
#define PTE_PCD
Definition: pgtbl.c:34
static void * get_pdpt_addr(void)
Definition: pgtbl.c:344
#define PTE_PAT
Definition: pgtbl.c:37
static uint64_t pde_pat_flags(int pat)
Definition: pgtbl.c:351
static uint64_t pte_pat_flags(int pat)
Definition: pgtbl.c:379
#define PDE_PWT
Definition: pgtbl.c:20
#define PTE_RW
Definition: pgtbl.c:31
#define PDE_PS
Definition: pgtbl.c:24
#define PDE_PAT
Definition: pgtbl.c:26
#define PTE_PRES
Definition: pgtbl.c:30
static const size_t s4KiB
Definition: pgtbl.c:53
struct pde __packed
#define PDPTE_IDX_SHIFT
Definition: pgtbl.c:41
void paging_enable_pae_cr3(uintptr_t cr3)
Definition: pgtbl.c:64
#define PTE_IDX_SHIFT
Definition: pgtbl.c:47
#define PDE_A
Definition: pgtbl.c:22
#define OVERLAP(a, b, s, e)
Definition: pgtbl.c:50
void paging_set_nxe(int enable)
Definition: pgtbl.c:279
#define PTE_PWT
Definition: pgtbl.c:33
#define PDE_PRES
Definition: pgtbl.c:17
static uint64_t pte_page_flags(int pat)
Definition: pgtbl.c:400
void paging_set_pat(uint64_t pat)
Definition: pgtbl.c:291
int memset_pae(uint64_t dest, unsigned char pat, uint64_t length, void *pgtbl, void *vmem_addr)
Definition: pgtbl.c:130
int paging_identity_map_addr(uintptr_t base, size_t size, int pat)
Definition: pgtbl.c:494
static int paging_is_enabled(void)
Definition: pgtbl.c:489
static uint64_t pde_page_flags(int pat)
Definition: pgtbl.c:372
#define PDPTE_ADDR_MASK
Definition: pgtbl.c:15
#define PDPTE_IDX_MASK
Definition: pgtbl.c:42
#define PDE_ADDR_MASK
Definition: pgtbl.c:28
#define PDE_RW
Definition: pgtbl.c:18
static const size_t s2MiB
Definition: pgtbl.c:52
void paging_disable_pae(void)
Definition: pgtbl.c:87
#define PDE_IDX_MASK
Definition: pgtbl.c:45
#define PDE_PCD
Definition: pgtbl.c:21
#define PTE_IDX_MASK
Definition: pgtbl.c:48
#define PTE_D
Definition: pgtbl.c:36
int paging_enable_for_car(const char *pdpt_name, const char *pt_name)
Definition: pgtbl.c:324
#define PTE_A
Definition: pgtbl.c:35
void paging_enable_pae(void)
Definition: pgtbl.c:71
static int identity_map_one_page(uintptr_t base, size_t size, int pat, int commit)
Definition: pgtbl.c:409
uintptr_t base
Definition: uart.c:17
__SIZE_TYPE__ ssize_t
Definition: stddef.h:13
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned long long uint64_t
Definition: stdint.h:17
unsigned int hi
Definition: msr.h:112
unsigned int lo
Definition: msr.h:111
Definition: pgtbl.c:55
uint32_t addr_lo
Definition: pgtbl.c:56
uint32_t addr_hi
Definition: pgtbl.c:57
Definition: pgtbl.c:59
struct pde pdp[512]
Definition: pgtbl.c:61
struct pde pd[2048]
Definition: pgtbl.c:60