diff --git a/ape/ape.S b/ape/ape.S index e8c12bf4f..5313039db 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -1285,8 +1285,8 @@ lcheck: pushf # check for i8086 / i8088 / i80186 jl 10f mov %edi,%eax cpuid - mov $1<<29,%edi # need nexgen32e long mode support - and %edi,%edx + mov $1<<29|1<<20,%edi # need nexgen32e long mode support + and %edi,%edx # & nx support cmp %edi,%edx jne 10f xor %ax,%ax @@ -1415,7 +1415,7 @@ pinit: push %ds movl $0x79000+PAGE_V+PAGE_RW,0x7b000-SEG # PD←PDT (+) movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PD←PDT (-) mov $512,%cx # PD±2MB - mov $PAGE_V+PAGE_RW,%eax + mov $PAGE_V+PAGE_RSRV+PAGE_RW,%eax xor %di,%di 0: stosl add $0x1000,%eax @@ -1438,7 +1438,7 @@ golong: cli mov %eax,%cr4 movl $EFER,%ecx rdmsr - or $EFER_LME|EFER_SCE,%eax + or $EFER_LME|EFER_SCE|EFER_NXE,%eax wrmsr lgdt REAL(_gdtrphy) mov %cr0,%eax diff --git a/libc/intrin/directmap-metal.c b/libc/intrin/directmap-metal.c index 4616340ff..e4e52b5ac 100644 --- a/libc/intrin/directmap-metal.c +++ b/libc/intrin/directmap-metal.c @@ -43,7 +43,7 @@ noasan struct DirectMap sys_mmap_metal(void *paddr, size_t size, int prot, addr = 4096; for (i = 0; i < size; i += 4096) { pte = __get_virtual(mm, pml4t, addr + i, false); - if (pte && (*pte & PAGE_V)) { + if (pte && (*pte & (PAGE_V | PAGE_RSRV))) { addr = MAX(addr, sys_mmap_metal_break) + i + 4096; i = 0; } @@ -55,7 +55,13 @@ noasan struct DirectMap sys_mmap_metal(void *paddr, size_t size, int prot, pte = __get_virtual(mm, pml4t, addr + i, true); if (pte && page) { __clear_page(BANE + page); - *pte = page | ((prot & PROT_WRITE) ? PAGE_RW : 0) | PAGE_U | PAGE_V; + page |= PAGE_RSRV | PAGE_U; + if ((prot & PROT_WRITE)) + page |= PAGE_V | PAGE_RW; + else if ((prot & (PROT_READ | PROT_EXEC))) + page |= PAGE_V; + if (!(prot & PROT_EXEC)) page |= PAGE_XD; + *pte = page; } else { addr = -1; break; diff --git a/libc/intrin/mman.greg.c b/libc/intrin/mman.greg.c index 2dad09c1f..6c97ba1dc 100644 --- a/libc/intrin/mman.greg.c +++ b/libc/intrin/mman.greg.c @@ -71,7 +71,7 @@ noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t, for (h = 39;; h -= 9) { e = t + ((vaddr >> h) & 511); if (h == 12) return e; - if (!(*e & PAGE_V)) { + if (!(*e & (PAGE_V | PAGE_RSRV))) { if (!maketables) return NULL; if (!(p = __new_page(mm))) return NULL; __clear_page(BANE + p); @@ -123,8 +123,8 @@ noasan textreal void __invert_memory_area(struct mman *mm, uint64_t *pml4t, pe = ROUNDUP(pe, 4096); for (p = ps; p != pe; p += 4096) { m = __get_virtual(mm, pml4t, BANE + p, true); - if (m && !(*m & PAGE_V)) { - *m = p | PAGE_V | pte_flags; + if (m && !(*m & (PAGE_V | PAGE_RSRV))) { + *m = p | PAGE_V | PAGE_RSRV | pte_flags; } } } @@ -139,7 +139,7 @@ static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) { /* ape/ape.S has already mapped the first 2 MiB of physical memory. */ if (ps < 0x200000 && ps + size <= 0x200000) continue; - __invert_memory_area(mm, pml4t, ps, size, PAGE_RW); + __invert_memory_area(mm, pml4t, ps, size, PAGE_RW | PAGE_XD); } } @@ -187,8 +187,12 @@ noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b) { for (p = (struct Elf64_Phdr *)REAL(ape_phdrs), m = 0; p < (struct Elf64_Phdr *)REAL(ape_phdrs_end); ++p) { if (p->p_type == PT_LOAD || p->p_type == PT_GNU_STACK) { - f = PAGE_V | PAGE_U; - if (p->p_flags & PF_W) f |= PAGE_RW; + f = PAGE_RSRV | PAGE_U; + if (p->p_flags & PF_W) + f |= PAGE_V | PAGE_RW; + else if (p->p_flags & (PF_R | PF_X)) + f |= PAGE_V; + if (!(p->p_flags & PF_X)) f |= PAGE_XD; for (i = 0; i < p->p_memsz; i += 4096) { if (i < p->p_filesz) { v = b + p->p_offset + i; diff --git a/libc/runtime/efimain.greg.c b/libc/runtime/efimain.greg.c index 4930fd14b..aa02aa272 100644 --- a/libc/runtime/efimain.greg.c +++ b/libc/runtime/efimain.greg.c @@ -126,7 +126,7 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, pdpt2 = (uint64_t *)0x7c000; pml4t = (uint64_t *)0x7e000; for (i = 0; i < 512; ++i) { - pd[i] = 0x1000 * i + PAGE_V + PAGE_RW; + pd[i] = 0x1000 * i + PAGE_V + PAGE_RSRV + PAGE_RW; } pdt1[0] = (intptr_t)pd + PAGE_V + PAGE_RW; pdt2[0] = (intptr_t)pd + PAGE_V + PAGE_RW; diff --git a/libc/vga/vga-init.greg.c b/libc/vga/vga-init.greg.c index c542cfd59..32b6fed45 100644 --- a/libc/vga/vga-init.greg.c +++ b/libc/vga/vga-init.greg.c @@ -51,7 +51,8 @@ void _vga_reinit(struct Tty *tty, unsigned short starty, unsigned short startx, chr_ht = VGA_ASSUME_CHAR_HEIGHT_PX; chr_wid = VGA_ASSUME_CHAR_WIDTH_PX; /* Make sure the video buffer is mapped into virtual memory. */ - __invert_memory_area(mm, __get_pml4t(), vid_buf_phy, vid_buf_sz, PAGE_RW); + __invert_memory_area(mm, __get_pml4t(), vid_buf_phy, vid_buf_sz, + PAGE_RW | PAGE_XD); /* * Initialize our tty structure from the current screen geometry, screen * contents, cursor position, & character dimensions.