summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/init.c
blob: 4ec771802d71b7d190d5a2e52d26216a52802f70 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "init.h"
#include "arch/x86_64/page.h"
#include "device/processor.h"

uintptr_t 
init_alloc_pageframe()
{
    objdir_entry_t *untyped_dir_entry = &_initDirectory.entries[INIT_OBJECT_UNTYPED_DIR];
    objdir_t *untyped_dir = ko_entry_data(untyped_dir_entry);

    /*Seek to the last member of untyped directory.*/
    uint8_t lastmembi = 1;
    for(; untyped_dir->entries[lastmembi].type == KO_MEMORY_UNTYPED; lastmembi++);
    objdir_entry_t *lastmemb = &untyped_dir->entries[lastmembi];

    objdir_entry_t pageframe;
    ko_untyped_split(lastmemb, &pageframe, 0x1000);
    return pageframe.data;
}

void 
init_map_pageframe(uintptr_t pptr, uintptr_t vptr, uint8_t pflags)
{
    uint64_t pathval;
    uint16_t *path = (uint16_t*)&pathval;
    pml4_get_path(vptr, 4, path);

    processor_t *proc = processor_current();
    pmle_t *pml4 = pptr_tovirt_ident(proc->pdir);
    
    pmle_t *pmld = pml4;
    for(uint8_t d = 0; d < 3; d++) {
        uint16_t pmli = path[d];
        pmle_t *pmle = &pmld[pmli];
        if(!pmle->p) {
            pmle->value = init_alloc_pageframe() | PAGE_PRESENT | PAGE_RW | PAGE_US;
        }
        pmld = pptr_tovirt_ident(pmle->paddr << 12);
    }
    pmld[path[3]].value = pptr | pflags;
    __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory");
}

void
init_ensure_page(uintptr_t vptr, uint8_t pflags)
{
    uint64_t pathval;
    uint16_t *path = (uint16_t*)&pathval;
    pml4_get_path(vptr, 4, path);

    processor_t *proc = processor_current();
    pmle_t *pml4 = pptr_tovirt_ident(proc->pdir);
    
    pmle_t *pmld = pml4, *pmle;
    for(uint8_t d = 0; d < 4; d++) {
        uint16_t pmli = path[d];
        pmle = &pmld[pmli];
        if(!pmle->p) {
            pmle->value = init_alloc_pageframe() | (d == 3 ? pflags : PAGE_PRESENT | PAGE_RW | PAGE_US);
        }
        pmld = pptr_tovirt_ident(pmle->paddr << 12);
    }
}