25 /* Amount of physical memory, in 4 kB pages. */
28 static void ram_init (void);
29 static void gdt_init (void);
30 static void argv_init (void);
33 main_thread (void *aux UNUSED)
45 /* Initialize prerequisites for calling printk(). */
51 printk ("Booting cnachos86 with %'d kB RAM...\n", ram_pages * 4);
53 /* Initialize memory system. */
62 /* Initialize interrupt handlers. */
67 /* Do everything else in a system thread. */
68 thread_init ("main", main_thread, NULL);
72 make_seg_desc (uint32_t base,
74 enum seg_system system,
77 enum seg_granularity granularity)
79 uint32_t e0 = ((limit & 0xffff) /* Limit 15:0. */
80 | (base << 16)); /* Base 15:0. */
81 uint32_t e1 = (((base >> 16) & 0xff) /* Base 23:16. */
82 | (system << 12) /* 0=system, 1=code/data. */
83 | (type << 8) /* Segment type. */
84 | (dpl << 13) /* Descriptor privilege. */
85 | (1 << 15) /* Present. */
86 | (limit & 0xf0000) /* Limit 16:19. */
87 | (1 << 22) /* 32-bit segment. */
88 | (granularity << 23) /* Byte/page granularity. */
89 | (base & 0xff000000)); /* Base 31:24. */
90 return e0 | ((uint64_t) e1 << 32);
94 make_code_desc (int dpl)
96 return make_seg_desc (0, 0xfffff, SYS_CODE_DATA, TYPE_CODE | TYPE_READABLE,
101 make_data_desc (int dpl)
103 return make_seg_desc (0, 0xfffff, SYS_CODE_DATA, TYPE_WRITABLE,
108 make_tss_desc (void *vaddr)
110 return make_seg_desc ((uint32_t) vaddr,
111 0x67, SYS_SYSTEM, TYPE_TSS_32_A, 0, GRAN_BYTE);
114 static uint64_t gdt[SEL_CNT];
118 /* Sets up a proper GDT. The bootstrap loader's GDT didn't
119 include user-mode selectors or a TSS. */
123 uint64_t gdtr_operand;
125 /* Our TSS is never used in a call gate or task gate, so only a
126 few fields of it are ever referenced, and those are the only
127 ones we initialize. */
128 tss = palloc_get (PAL_ASSERT | PAL_ZERO);
129 tss->esp0 = (uint32_t) ptov(0x20000);
130 tss->ss0 = SEL_KDSEG;
131 tss->bitmap = 0xdfff;
133 /* Initialize GDT. */
134 gdt[SEL_NULL / sizeof *gdt] = 0;
135 gdt[SEL_KCSEG / sizeof *gdt] = make_code_desc (0);
136 gdt[SEL_KDSEG / sizeof *gdt] = make_data_desc (0);
137 gdt[SEL_UCSEG / sizeof *gdt] = make_code_desc (3);
138 gdt[SEL_UDSEG / sizeof *gdt] = make_data_desc (3);
139 gdt[SEL_TSS / sizeof *gdt] = make_tss_desc (tss);
142 gdtr_operand = make_dtr_operand (sizeof gdt - 1, gdt);
143 asm volatile ("lgdt %0" :: "m" (gdtr_operand));
144 asm volatile ("ltr %w0" :: "r" (SEL_TSS));
150 /* The "BSS" is a segment that should be initialized to zeros.
151 It isn't actually stored on disk or zeroed by the kernel
152 loader, so we have to zero it ourselves.
154 The start and end of the BSS segment is recorded by the
155 linker as _start_bss and _end_bss. See kernel.lds. */
156 extern char _start_bss, _end_bss;
157 memset (&_start_bss, 0, &_end_bss - &_start_bss);
159 /* Get RAM size from loader. */
160 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
163 /* This should be sufficient because the command line buffer is
164 only 128 bytes and arguments are space-delimited. */
168 char *argv[ARGC_MAX + 1];
173 char *cmd_line = ptov (LOADER_CMD_LINE);
176 for (arg = strtok_r (cmd_line, " \t\r\n\v", &pos); arg != NULL;
177 arg = strtok_r (NULL, " \t\r\n\v", &pos))
179 ASSERT (argc < ARGC_MAX);