summaryrefslogtreecommitdiff
path: root/kern/kernel.c
blob: 6168224dadcf95e1d53483e8646327e44712d563 (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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/** @file kernel.c
 *
 *  @brief kernel entry.
 *
 *  @author Hanjie Wu (hanjiew)
 *  @bug No functional bugs
 */

#include <common_kern.h>

/* libc includes. */
#include <simics.h> /* lprintf() */
#include <stdio.h>
#include <string.h>

/* multiboot header file */
#include <mptable.h>
#include <multiboot.h> /* boot_info */
#include <smp.h>

/* x86 specific includes */
#include <x86/asm.h> /* enable_interrupts() */
#include <x86/cr.h>

#include <assert.h>
#include <common.h>
#include <interrupt.h>
#include <mm.h>
#include <paging.h>
#include <pts.h>
#include <pv.h>
#include <sched.h>
#include <timer.h>
#include <toad.h>

/**
 * @brief entry for a cpu core
 * @param cpuid cpuid
 */
static void kernel_smp_entry(int cpuid);

/**
 * @brief main function for a cpu core
 */
static void kernel_smp_main();

/** @brief Kernel entrypoint.
 *
 *  This is the entrypoint for the kernel.
 *
 * @return Does not return
 */
int kernel_main(mbinfo_t* mbinfo, int argc, char** argv, char** envp) {
    int smp_good = (smp_init(mbinfo) == 0);
    paging_init();
    setup_pts();
    percpu_t percpu;
    setup_percpu(&percpu);
    thread_t kthread;
    process_t kprocess;
    setup_kth(&kthread, &kprocess);
    set_mapped_phys_page(mapped_phys_pages);
    set_mapped_phys_page_pte(mapped_phys_page_ptes);

    idt_init();
    mm_init();
    pv_init();
    timer_init();

    print_toad();

    const char* init_args[] = {INIT_NAME};
    thread_t* init = create_process(INIT_PID, INIT_NAME, 1, init_args);
    assert(init != NULL);
    init_process = init->process;
    add_thread(init);
    insert_ready_tail(init);

    if (smp_good && smp_num_cpus() > 1) {
        set_cr3((pa_t)&kernel_pd);
        smp_boot(kernel_smp_entry);
    }

    setup_lapic_timer();
    kernel_smp_main();
    return -1;
}

static void kernel_smp_entry(int cpuid) {
    paging_enable();
    percpu_t percpu;
    setup_percpu(&percpu);
    thread_t kthread;
    process_t kprocess;
    setup_kth(&kthread, &kprocess);
    set_mapped_phys_page(mapped_phys_pages + cpuid * PAGE_SIZE);
    set_mapped_phys_page_pte(mapped_phys_page_ptes + cpuid);
    setup_lapic_timer();
    kernel_smp_main();
}

static void kernel_smp_main() {
    const char* idle_args[] = {IDLE_NAME};
    thread_t* idle = create_process(IDLE_PID, IDLE_NAME, 1, idle_args);
    assert(idle != NULL);
    set_idle(idle);

    while (1) {
        int old_if = spl_lock(&ready_lock);
        thread_t* t = select_next();
        yield_to_spl_unlock(t, &ready_lock, old_if);
        /* when a thread borrow kthread's stack and free itself, it will return
         * here and we continue yielding
         */
    }
    panic("kthread should not return");
}