summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/hal/paging.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/hal/paging.c')
-rw-r--r--arch/x86_64/hal/paging.c112
1 files changed, 88 insertions, 24 deletions
diff --git a/arch/x86_64/hal/paging.c b/arch/x86_64/hal/paging.c
index 535d5b2..d5bcee3 100644
--- a/arch/x86_64/hal/paging.c
+++ b/arch/x86_64/hal/paging.c
@@ -22,6 +22,14 @@ PAGEALIGN page_t _kernel_pml1[512];
PAGEALIGN static page_t ident_pml3[IDENT_MASSIVEPAGES][512];
PAGEALIGN static page_t ident_pml2[IDENT_GIANTPAGES][512];
+virtaddr_t __syscall_stack_guard;
+virtaddr_t __syscall_stack;
+virtaddr_t __interrupt_stack_guard;
+virtaddr_t __interrupt_stack;
+
+virtaddr_t *__syscall_stack_mapping;
+virtaddr_t *__interrupt_stack_mapping;
+
void*
phys_tovirt(uintptr_t phys)
{
@@ -95,7 +103,7 @@ s_pagedir_get_pml1(page_t *pml4, uintptr_t vptr)
return 0;
}
- #define PML_TBL(tbl, i) (page_t*)(((uintptr_t)tbl[i].paddr << 12) | IDENT_VIRT_BASE)
+ #define PML_TBL(tbl, i) (page_t*)(((uintptr_t)tbl[i].pfn << 12) | IDENT_VIRT_BASE)
page_t *pml3 = PML_TBL(pml4, pml4i);
size_t pml3i = PML3I(vptr);
@@ -137,18 +145,48 @@ uintptr_t *pagedir_get_mapping(jove_owned_obj_t *pagedir, uintptr_t vptr)
return (uintptr_t*)mapping;
}
-uintptr_t
+size_t
+pagedir_mapping_get_pfn(virtaddr_t *mapping)
+{
+ return ((page_t*)mapping)->pfn;
+}
+
+virtaddr_t
pagedir_ident_from_mapping(uintptr_t *mapping)
{
- return (((page_t*)mapping)->paddr << 12) | IDENT_VIRT_BASE;
+ return (((page_t*)mapping)->pfn << 12) | IDENT_VIRT_BASE;
+}
+
+inline bool pagedir_mapping_is_present(virtaddr_t *mapping)
+{
+ return ((page_t*)mapping)->p;
+}
+
+inline void pagedir_mapping_set_pfn(virtaddr_t *mapping, size_t pfn)
+{
+ ((page_t*)mapping)->pfn = pfn;
}
-void
-pagedir_mapping_set_present(uintptr_t *mapping, bool present)
+inline void pagedir_mapping_set_present(virtaddr_t *mapping, bool present)
{
((page_t*)mapping)->p = present;
}
+inline void pagedir_mapping_set_writeable(virtaddr_t *mapping, bool rw)
+{
+ ((page_t*)mapping)->rw = rw;
+}
+
+inline void pagedir_mapping_set_user(virtaddr_t *mapping, bool user)
+{
+ ((page_t*)mapping)->u = user;
+}
+
+inline void pagedir_mapping_set_type(virtaddr_t *mapping, int type)
+{
+ ((page_t*)mapping)->mapping_type = type;
+}
+
int pagedir_map_frame(page_t *pml4,
uintptr_t pptr, uintptr_t vptr,
uintmax_t flg)
@@ -165,11 +203,11 @@ int pagedir_map_frame(page_t *pml4,
return 0;
}
-int pagedir_map_shmem(page_t *pml4,
+int pagedir_map_frame_type(page_t *pml4,
uintptr_t pptr, uintptr_t vptr,
- struct syscall_pagedir_flags flg)
+ struct syscall_pagedir_flags flg, int type)
{
- uintmax_t real_flg = PAGE_USER | PAGE_SHMEM;
+ uintmax_t real_flg = PAGE_USER | (type << PAGE_SHL_TYPE);
if(flg.writeable) {
real_flg |= PAGE_WRITEABLE;
}
@@ -191,9 +229,7 @@ int pagedir_map_untyped_frame(
}
uintptr_t frame = obj_getvalue(untyped->obj);
- return pagedir_map_frame(pml4, frame, vptr, PAGE_USER |
- (flg.writeable ? PAGE_WRITEABLE : 0) |
- (flg.executable ? 0 : PAGE_XD));
+ return pagedir_map_frame_type(pml4, frame, vptr, flg, JOVE_MAPPING_TYPE_UNTYPED);
}
int pagedir_map_table(page_t *pml4,
@@ -209,7 +245,7 @@ int pagedir_map_table(page_t *pml4,
goto map_table;
}
- page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].paddr << 12)
+ page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].pfn << 12)
| IDENT_VIRT_BASE);
size_t pml3i = PML3I(vptr);
if(!pml3[pml3i].p) {
@@ -217,7 +253,7 @@ int pagedir_map_table(page_t *pml4,
goto map_table;
}
- page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].paddr << 12)
+ page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].pfn << 12)
| IDENT_VIRT_BASE);
size_t pml2i = PML2I(vptr);
if(!pml2[pml2i].p) {
@@ -265,9 +301,7 @@ int pagedir_map_shmem_frame(
uintptr_t frame = value & ~0xFF;
frame += (uintmax_t)page_offset << 12;
- return pagedir_map_frame(pml4, frame, vptr, PAGE_USER |
- (flg.writeable ? PAGE_WRITEABLE : 0) |
- (flg.executable ? 0 : PAGE_XD));
+ return pagedir_map_frame_type(pml4, frame, vptr, flg, JOVE_MAPPING_TYPE_SHMEM);
}
int pagedir_unmap_untyped_frame(
@@ -276,13 +310,14 @@ int pagedir_unmap_untyped_frame(
page_t *pml4 = obj_deref(tgt);
size_t pml4i = PML4I(vptr);
- if(!pml4[pml4i].p) return ENOMAP;
+ if(!pml4[pml4i].p) return -ENOMAP;
page_t *pml1 = s_pagedir_get_pml1(pml4, vptr);
size_t pml1i = PML1I(vptr);
- if(!pml1[pml1i].p) return ENOMAP;
+ if(!pml1[pml1i].p) return -ENOMAP;
- uintptr_t untyped_pptr = (pml1[pml1i].paddr << 12);
+ if(pml1[pml1i].mapping_type != JOVE_MAPPING_TYPE_UNTYPED) return -ENOMAP;
+ uintptr_t untyped_pptr = (pml1[pml1i].pfn << 12);
obj_settype(dst, JOVE_OBJ_UNTYPED);
obj_setvalue(dst, untyped_pptr);
@@ -294,6 +329,26 @@ int pagedir_unmap_untyped_frame(
return 0;
}
+int pagedir_unmap_shmem_frame(
+ jove_owned_obj_t *tgt, uintptr_t vptr)
+{
+ page_t *pml4 = obj_deref(tgt);
+
+ size_t pml4i = PML4I(vptr);
+ if(!pml4[pml4i].p) return -ENOMAP;
+
+ page_t *pml1 = s_pagedir_get_pml1(pml4, vptr);
+ size_t pml1i = PML1I(vptr);
+ if(!pml1[pml1i].p) return -ENOMAP;
+
+ if(pml1[pml1i].mapping_type != JOVE_MAPPING_TYPE_UNTYPED) return -ENOMAP;
+
+ pml1[pml1i].p = 0;
+ pagedir_invlpg(vptr);
+
+ return 0;
+}
+
int pagedir_unmap_untyped_table(
jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr)
{
@@ -304,12 +359,12 @@ int pagedir_unmap_untyped_table(
//trying to unmap the entire address space. We don't support this.
size_t pml4i = PML4I(vptr);
if(!pml4[pml4i].p) {
- return ENOMAP;
+ return -ENOMAP;
}
target_table = &pml4[pml4i];
//Try to unmap the pml4 entry if the pml3 entry does not exist.
- page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].paddr << 12) | IDENT_VIRT_BASE);
+ page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].pfn << 12) | IDENT_VIRT_BASE);
size_t pml3i = PML3I(vptr);
if(!pml3[pml3i].p) {
goto unmap_table;
@@ -317,7 +372,7 @@ int pagedir_unmap_untyped_table(
target_table = &pml3[pml3i];
//Try to unmap the pml3 entry if the pml2 entry does not exist.
- page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].paddr << 12) | IDENT_VIRT_BASE);
+ page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].pfn << 12) | IDENT_VIRT_BASE);
size_t pml2i = PML2I(vptr);
if(!pml2[pml2i].p) {
goto unmap_table;
@@ -327,13 +382,13 @@ int pagedir_unmap_untyped_table(
unmap_table:
{
- uintptr_t frame = target_table->paddr << 12;
+ uintptr_t frame = target_table->pfn << 12;
page_t *target_vals = (page_t*)(frame | IDENT_VIRT_BASE);
//Check that the page table at our target entry is empty.
//If it's not, we return an error saying that the entry contains a map.
for(size_t i = 0; i < 512; i++) {
- if(target_vals[i].p) return EHASMAP;
+ if(target_vals[i].p) return -EHASMAP;
}
//Populate the none object with an untyped object at the free'd page frame.
@@ -421,6 +476,15 @@ paging_pml4_init(void)
| PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL | PAGE_XD;
}
+ size_t kernel_stack_off = kernel_data_off + kernel_data_pages;
+ __syscall_stack_guard = ((kernel_stack_off) << 12) + KERNEL_VIRT_BASE;
+ __syscall_stack = __syscall_stack_guard + 0x1000;
+ __interrupt_stack_guard = __syscall_stack + 0x1000;
+ __interrupt_stack = __interrupt_stack_guard + 0x1000;
+
+ __syscall_stack_mapping = (virtaddr_t*)&_kernel_pml1[kernel_stack_off + 1];
+ __interrupt_stack_mapping = (virtaddr_t*)&_kernel_pml1[kernel_stack_off + 3];
+
/*Identity pages are mapped as huge pages starting at the 256'th PML3 entry.
*We want to support any range of physical memory up to several TiB, so
*the mapper has to consider multiple heirarchies of huge pages.*/