@@ -8,6 +8,7 @@
#include <linux/const.h>
+#include <bitops.h>
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
@@ -21,11 +22,14 @@
#define LARGE_PAGE_SIZE (1024 * PAGE_SIZE)
#endif
-#define PTE_PRESENT (1ull << 0)
-#define PTE_WRITE (1ull << 1)
-#define PTE_USER (1ull << 2)
-#define PTE_PSE (1ull << 7)
-#define PTE_ADDR (0xffffffffff000ull)
+#define PT_PRESENT_MASK (1ull << 0)
+#define PT_WRITABLE_MASK (1ull << 1)
+#define PT_USER_MASK (1ull << 2)
+#define PT_ACCESSED_MASK (1ull << 5)
+#define PT_DIRTY_MASK (1ull << 6)
+#define PT_PAGE_SIZE_MASK (1ull << 7)
+#define PT64_NX_MASK (1ull << 63)
+#define PT_ADDR_MASK GENMASK_ULL(51, 12)
#ifdef __x86_64__
#define PAGE_LEVEL 4
@@ -49,16 +49,16 @@ unsigned long *install_pte(unsigned long *cr3,
for (level = PAGE_LEVEL; level > pte_level; --level) {
offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK;
- if (!(pt[offset] & PTE_PRESENT)) {
+ if (!(pt[offset] & PT_PRESENT_MASK)) {
unsigned long *new_pt = pt_page;
if (!new_pt)
new_pt = alloc_page();
else
pt_page = 0;
memset(new_pt, 0, PAGE_SIZE);
- pt[offset] = virt_to_phys(new_pt) | PTE_PRESENT | PTE_WRITE | PTE_USER;
+ pt[offset] = virt_to_phys(new_pt) | PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK;
}
- pt = phys_to_virt(pt[offset] & 0xffffffffff000ull);
+ pt = phys_to_virt(pt[offset] & PT_ADDR_MASK);
}
offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK;
pt[offset] = pte;
@@ -74,11 +74,11 @@ unsigned long *get_pte(unsigned long *cr3, void *virt)
for (level = PAGE_LEVEL; level > 1; --level) {
offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK;
pte = pt[offset];
- if (!(pte & PTE_PRESENT))
+ if (!(pte & PT_PRESENT_MASK))
return NULL;
- if (level == 2 && (pte & PTE_PSE))
+ if (level == 2 && (pte & PT_PAGE_SIZE_MASK))
return &pt[offset];
- pt = phys_to_virt(pte & 0xffffffffff000ull);
+ pt = phys_to_virt(pte & PT_ADDR_MASK);
}
offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK;
return &pt[offset];
@@ -89,14 +89,14 @@ unsigned long *install_large_page(unsigned long *cr3,
void *virt)
{
return install_pte(cr3, 2, virt,
- phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0);
+ phys | PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK | PT_PAGE_SIZE_MASK, 0);
}
unsigned long *install_page(unsigned long *cr3,
unsigned long phys,
void *virt)
{
- return install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0);
+ return install_pte(cr3, 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK, 0);
}
@@ -178,7 +178,7 @@ void *vmalloc(unsigned long size)
uint64_t virt_to_phys_cr3(void *mem)
{
- return (*get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR) + ((ulong)mem & (PAGE_SIZE - 1));
+ return (*get_pte(phys_to_virt(read_cr3()), mem) & PT_ADDR_MASK) + ((ulong)mem & (PAGE_SIZE - 1));
}
void vfree(void *mem)
@@ -186,7 +186,7 @@ void vfree(void *mem)
unsigned long size = ((unsigned long *)mem)[-1];
while (size) {
- free_page(phys_to_virt(*get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR));
+ free_page(phys_to_virt(*get_pte(phys_to_virt(read_cr3()), mem) & PT_ADDR_MASK));
mem += PAGE_SIZE;
size -= PAGE_SIZE;
}
@@ -19,14 +19,6 @@ static int invalid_mask;
#define PT_BASE_ADDR_MASK ((pt_element_t)((((pt_element_t)1 << 40) - 1) & PAGE_MASK))
#define PT_PSE_BASE_ADDR_MASK (PT_BASE_ADDR_MASK & ~(1ull << 21))
-#define PT_PRESENT_MASK ((pt_element_t)1 << 0)
-#define PT_WRITABLE_MASK ((pt_element_t)1 << 1)
-#define PT_USER_MASK ((pt_element_t)1 << 2)
-#define PT_ACCESSED_MASK ((pt_element_t)1 << 5)
-#define PT_DIRTY_MASK ((pt_element_t)1 << 6)
-#define PT_PSE_MASK ((pt_element_t)1 << 7)
-#define PT_NX_MASK ((pt_element_t)1 << 63)
-
#define CR0_WP_MASK (1UL << 16)
#define CR4_SMEP_MASK (1UL << 20)
@@ -493,7 +485,7 @@ void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool, u64 pd_page,
pte |= 2ull << 59;
} else {
pte = at->phys & PT_PSE_BASE_ADDR_MASK;
- pte |= PT_PSE_MASK;
+ pte |= PT_PAGE_SIZE_MASK;
if (F(AC_PKU_PKEY))
pte |= 1ull << 59;
}
@@ -508,7 +500,7 @@ void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool, u64 pd_page,
if (F(AC_PDE_DIRTY))
pte |= PT_DIRTY_MASK;
if (F(AC_PDE_NX))
- pte |= PT_NX_MASK;
+ pte |= PT64_NX_MASK;
if (F(AC_PDE_BIT51))
pte |= 1ull << 51;
if (F(AC_PDE_BIT13))
@@ -530,7 +522,7 @@ void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool, u64 pd_page,
if (F(AC_PTE_DIRTY))
pte |= PT_DIRTY_MASK;
if (F(AC_PTE_NX))
- pte |= PT_NX_MASK;
+ pte |= PT64_NX_MASK;
if (F(AC_PTE_BIT51))
pte |= 1ull << 51;
at->ptep = &vroot[index];
@@ -69,7 +69,7 @@ static void pf_isr(struct ex_regs *r)
report("Got present #PF token %x\n", true, read_cr2());
if ((uint32_t)read_cr2() == ~0)
break;
- install_pte(phys_to_virt(read_cr3()), 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0);
+ install_pte(phys_to_virt(read_cr3()), 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0);
write_cr3(read_cr3());
phys = 0;
break;
@@ -52,7 +52,7 @@ void do_pf_tss(void)
{
printf("PF running\n");
install_pte(phys_to_virt(read_cr3()), 1, stack_va,
- stack_phys | PTE_PRESENT | PTE_WRITE, 0);
+ stack_phys | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0);
invlpg(stack_va);
}
@@ -363,7 +363,7 @@ int main()
printf("Try to divide by 0\n");
/* install read only pte */
install_pte(phys_to_virt(read_cr3()), 1, stack_va,
- stack_phys | PTE_PRESENT, 0);
+ stack_phys | PT_PRESENT_MASK, 0);
invlpg(stack_va);
flush_phys_addr(stack_phys);
switch_stack(stack_va + 4095);
@@ -382,7 +382,7 @@ int main()
set_idt_sel(33, NP_SEL);
/* install read only pte */
install_pte(phys_to_virt(read_cr3()), 1, stack_va,
- stack_phys | PTE_PRESENT, 0);
+ stack_phys | PT_PRESENT_MASK, 0);
invlpg(stack_va);
flush_idt_page();
flush_phys_addr(stack_phys);
@@ -398,8 +398,8 @@ int main()
/* use shadowed stack during interrupt delivery */
for (i = 0; i < 4096/sizeof(ulong); i++) {
if (!cr3[i]) {
- cr3[i] = virt_to_phys(pt) | PTE_PRESENT | PTE_WRITE;
- pt[0] = virt_to_phys(pt) | PTE_PRESENT | PTE_WRITE;
+ cr3[i] = virt_to_phys(pt) | PT_PRESENT_MASK | PT_WRITABLE_MASK;
+ pt[0] = virt_to_phys(pt) | PT_PRESENT_MASK | PT_WRITABLE_MASK;
#ifndef __x86_64__
((ulong*)(i<<22))[1] = 0;
#else
@@ -65,7 +65,7 @@ int main(int ac, char **av)
u8 *topmost = (void *) ((1ul << 47) - PAGE_SIZE);
install_pte(phys_to_virt(read_cr3()), 1, topmost,
- virt_to_phys(data1) | PTE_PRESENT | PTE_WRITE, 0);
+ virt_to_phys(data1) | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0);
memset(topmost, 0xcc, PAGE_SIZE);
topmost[4093] = 0x0f;
topmost[4094] = 0x01;
@@ -77,7 +77,7 @@ int main(int ac, char **av)
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_LMA);
for (i = 0; i < USER_BASE; i += PAGE_SIZE) {
- *get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) &= ~PTE_USER;
+ *get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) &= ~PT_USER_MASK;
*get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) |= ((unsigned long)pkey << PTE_PKEY_BIT);
invlpg((void *)i);
}
@@ -36,7 +36,7 @@ int main (void)
virt_addr += PAGE_SIZE;
install_pte(phys_to_virt(read_cr3()), 1, virt_addr,
- 0 | PTE_PRESENT | PTE_WRITE, target_page);
+ 0 | PT_PRESENT_MASK | PT_WRITABLE_MASK, target_page);
*(unsigned long *)virt_addr = 0;
printf("PASS\n");
@@ -62,7 +62,7 @@ static void check_smap_nowp(void)
{
test = 0x99;
- *get_pte(phys_to_virt(read_cr3()), USER_ADDR(test)) &= ~PTE_WRITE;
+ *get_pte(phys_to_virt(read_cr3()), USER_ADDR(test)) &= ~PT_WRITABLE_MASK;
write_cr4(read_cr4() & ~X86_CR4_SMAP);
write_cr0(read_cr0() & ~X86_CR0_WP);
@@ -81,7 +81,7 @@ static void check_smap_nowp(void)
report("read from user page with SMAP=1, AC=0, WP=0, PTE.U=1 && PTE.W=0", pf_count == 1 && save == 0x99);
/* Undo changes */
- *get_pte(phys_to_virt(read_cr3()), USER_ADDR(test)) |= PTE_WRITE;
+ *get_pte(phys_to_virt(read_cr3()), USER_ADDR(test)) |= PT_WRITABLE_MASK;
write_cr0(read_cr0() | X86_CR0_WP);
write_cr3(read_cr3());
@@ -102,7 +102,7 @@ int main(int ac, char **av)
// Map first 16MB as supervisor pages
for (i = 0; i < USER_BASE; i += PAGE_SIZE) {
- *get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) &= ~PTE_USER;
+ *get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) &= ~PT_USER_MASK;
invlpg((void *)i);
}
@@ -67,7 +67,7 @@ void do_pf_tss(ulong *error_code)
if (*error_code == 0x2) /* write access, not present */
test_count++;
install_pte(phys_to_virt(read_cr3()), 1, fault_addr,
- fault_phys | PTE_PRESENT | PTE_WRITE, 0);
+ fault_phys | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0);
}
extern void pf_tss(void);