aboutsummaryrefslogtreecommitdiff
path: root/kernel/main/smp_trampoline.S
blob: 9273f0fa68c281efe4881ffd862f67596d1bd01a (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
76
77
78
79
80
81
#define CR0_PG 0x80000000
#define CR0_PE 0x00000001

#define CR4_PAE 0x00000020
#define CR4_PGE 0x00000080

#define PHYSADDR(x) (x - smp_initialization_start)

# NOTE: THIS CODE REQUIRES THAT IT BE PLACED STARTING AT PHYSICAL ADDRESS 0x0

.file "smp_trampoline.S"
.global smp_initialization_start, smp_initialization_end

smp_initialization_start:

/* When we initialize a processor, it starts in 16-bit real mode */
.code16
.align 0x1000
smp_processor_init:
    cli

    // enable PAE
    mov $(CR4_PAE | CR4_PGE), %eax
    mov %eax, %cr4

    mov $PHYSADDR(pml4), %eax
    mov %eax, %cr3

    // enter long mode
    mov $0xC0000080, %ecx
    rdmsr
    or $0x100, %eax
    wrmsr

    lgdt PHYSADDR(GDTPointer)

    // Enable paging AND protection simultaneously
    movl    %cr0, %eax
    or     $(CR0_PG | CR0_PE), %eax
    movl    %eax, %cr0

    ljmp $0x8, $PHYSADDR(smp_trampoline)

.code64
smp_trampoline:
    movabsq $(0xffff880000000000 + PHYSADDR(stack_pointer)), %rsp
    xor %rbp, %rbp
    movabsq $smp_processor_entry, %rax
    call *%rax


.align 16
GDT64:
    GDTNull:
        .quad 0
    GDTKernelCode:
        // base = 0x0, limit = 0x0
        // flags: present, ring 0, executable, readable, 64bit
        .word 0, 0
        .byte 0, 0x9a, 0x20, 0
    GDTEnd:
    GDTPointer:
        .word GDTEnd - GDT64 - 1 // size of gdt - 1
        .long PHYSADDR(GDT64) // pointer to gdt

.align 0x1000
pml4: // maps first 1GB of RAM to both 0x0000000000000000 and 0xffff800000000000
    .quad PHYSADDR(pdpt) + 3
    .fill 255,8,0
    .quad PHYSADDR(pdpt) + 3
    .fill 15,8,0
    .quad PHYSADDR(pdpt) + 3
    .fill 239,8,0
pdpt:
    .quad 0x0000000000000083
    .fill 511,8,0

.skip 0x1000
stack_pointer:

smp_initialization_end: