summaryrefslogtreecommitdiff
path: root/kern/paging.c
blob: 73c86da11be52e22c1e45f241ce6013b0fd8e5e5 (plain)
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
64
65
66
67
68
69
70
71
72
73
74
75
/** @file paging.c
 *
 *  @brief paging management functions.
 *
 *  @author Hanjie Wu (hanjiew)
 *  @bug No functional bugs
 */

#include <common_kern.h>
#include <malloc_internal.h>
#include <stdio.h>
#include <string.h>

#include <apic.h>
#include <mptable.h>
#include <smp.h>
#include <x86/asm.h>
#include <x86/cr.h>

#include <asm_instr.h>
#include <paging.h>
#include <sched.h>

/** number of page tables for kernel memory */
#define NUM_KERNEL_PT (USER_MEM_START / PAGE_SIZE / NUM_PAGE_ENTRY)

page_directory_t* kernel_pd;
/** page tables for kernel memory */
static page_table_t* kernel_pt;

va_t mapped_phys_pages;
pte_t* mapped_phys_page_ptes;

void paging_init() {
    kernel_pd = (page_directory_t*)_smemalign(PAGE_SIZE, PAGE_SIZE);
    kernel_pt = (page_table_t*)_smemalign(PAGE_SIZE, PAGE_SIZE * NUM_KERNEL_PT);

    int num_cpus = smp_num_cpus();
    mapped_phys_pages = (va_t)_smemalign(PAGE_SIZE, num_cpus * PAGE_SIZE);
    mapped_phys_page_ptes = (pte_t*)kernel_pt + (mapped_phys_pages / PAGE_SIZE);

    if (kernel_pd == NULL || kernel_pt == NULL || mapped_phys_pages == 0 ||
        mapped_phys_page_ptes == NULL) {
        panic("no space for kernel page table");
    }

    int i, j;
    pa_t base = 0;
    memset(kernel_pd, 0, sizeof(page_directory_t));
    for (i = 0; i < (USER_MEM_START / PT_SIZE); i++) {
        (*kernel_pd)[i] =
            make_pde((pa_t)&kernel_pt[i], PTE_SUPERVISOR, PTE_RW, PTE_PRESENT);
        for (j = 0; j < NUM_PAGE_ENTRY; j++) {
            kernel_pt[i][j] =
                make_pte(base, PTE_G, PTE_SUPERVISOR, PTE_RW, PTE_PRESENT);
            base += PAGE_SIZE;
        }
    }

    pa_t lapic_pa = (pa_t)smp_lapic_base();
    pte_t* lapic_pte = (pte_t*)kernel_pt + (LAPIC_VIRT_BASE / PAGE_SIZE);
    *lapic_pte =
        (make_pte(lapic_pa, PTE_G, PTE_SUPERVISOR, PTE_RW, PTE_PRESENT) |
         (PTE_PWT << PTE_PWT_SHIFT) | (PTE_PCD << PTE_PCD_SHIFT));

    set_cr4(get_cr4() | CR4_PSE | CR4_PGE);
    set_cr3((uint32_t)kernel_pd);
    set_cr0(get_cr0() | CR0_PE | CR0_PG | CR0_WP);
}

void paging_enable() {
    set_cr4(get_cr4() | CR4_PSE | CR4_PGE);
    set_cr3((uint32_t)kernel_pd);
    set_cr0(get_cr0() | CR0_PE | CR0_PG | CR0_WP);
}