MOS Source Code
Loading...
Searching...
No Matches
x86_platform.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4
9#include "mos/mm/mm.hpp"
11#include "mos/syslog/printk.hpp"
13#include "mos/x86/acpi/acpi.hpp"
15#include "mos/x86/acpi/madt.hpp"
17#include "mos/x86/cpu/cpu.hpp"
24
25#include <mos_stdlib.hpp>
26#include <mos_string.hpp>
27
28typedef enum : u16
29{
30 COM1 = 0x3F8,
31 COM2 = 0x2F8,
32 COM3 = 0x3E8,
33 COM4 = 0x2E8,
34 COM5 = 0x5F8,
35 COM6 = 0x4F8,
36 COM7 = 0x5E8,
37 COM8 = 0x4E8
39
41{
43
44 public:
52
53 public:
54 u8 read_byte() override
55 {
56 return port_inb(port);
57 }
58
59 int write_byte(u8 data) override
60 {
61 port_outb(port, data);
62 return 0;
63 }
64
66 {
67 return port_inb((u16) port + reg);
68 }
69
70 void write_register(serial_register_t reg, u8 data) override
71 {
72 port_outb((u16) port + reg, data);
73 }
74
75 bool get_data_ready() override
76 {
77 return (port_inb(port + 5) & 1) != 0;
78 }
79};
80
83
86
89
93
94static bool x86_keyboard_handler(u32 irq, void *data)
95{
96 MOS_UNUSED(data);
98 int scancode = port_inb(0x60);
99
100 pr_info("Keyboard scancode: %x", scancode);
101 return true;
102}
103
104static bool x86_pit_timer_handler(u32 irq, void *data)
105{
106 MOS_UNUSED(data);
108 spinlock_acquire(&current_thread->state_lock);
109 reschedule();
110 return true;
111}
112
114{
115 lapic_set_timer(1000000);
116}
117
118typedef struct _frame
119{
120 struct _frame *bp;
122} frame_t;
123
124void x86_dump_stack_at(ptr_t this_frame, bool can_access_vmaps)
125{
126 frame_t *frame = (frame_t *) this_frame;
127
128 const bool do_mapped_check = current_cpu->mm_context;
129
130 if (unlikely(!do_mapped_check))
131 pr_warn(" no mm context available, mapping checks are disabled (early-boot panic?)");
132
133 const bool no_relock = do_mapped_check && spinlock_is_locked(&current_cpu->mm_context->mm_lock);
134 if (no_relock)
135 pr_emerg(" mm lock is already held, stack trace may be corrupted");
136
137 pr_info("-- stack trace:");
138 for (u32 i = 0; frame; i++)
139 {
140#define TRACE_FMT " %-3d [" PTR_FMT "]: "
141 if (do_mapped_check)
142 {
143 const pfn_t pfn = mm_get_phys_addr(current_cpu->mm_context, (ptr_t) frame) / MOS_PAGE_SIZE;
144 if (!pfn)
145 {
146 pr_emerg(TRACE_FMT "<corrupted>, aborting backtrace", i, (ptr_t) frame);
147 break;
148 }
149 }
150
151 if (frame->bp == 0)
152 {
153 // end of stack
154 pr_warn(TRACE_FMT "<end>", i, (ptr_t) 0);
155 break;
156 }
157 else if (frame == frame->bp)
158 {
159 pr_emerg(TRACE_FMT "<corrupted>, aborting backtrace", i, (ptr_t) frame);
160 break;
161 }
162 else if (frame->ip >= MOS_KERNEL_START_VADDR)
163 {
164 pr_warn(TRACE_FMT "%ps", i, frame->ip, (void *) frame->ip);
165 }
166 else if (frame->ip == 0)
167 {
168 pr_warn(TRACE_FMT "<end>", i, frame->ip);
169 break;
170 }
171 else if (frame->ip < 1 KB)
172 {
173 pr_emerg(TRACE_FMT "<corrupted?>", i, frame->ip);
174 }
175 else if (can_access_vmaps)
176 {
177 if (!no_relock)
178 spinlock_acquire(&current_cpu->mm_context->mm_lock);
179 vmap_t *const vmap = vmap_obtain(current_cpu->mm_context, (ptr_t) frame->ip, NULL);
180
181 if (vmap && vmap->io)
182 {
183 char filepath[MOS_PATH_MAX_LENGTH];
184 io_get_name(vmap->io, filepath, sizeof(filepath));
185 pr_warn(TRACE_FMT "%s (+" PTR_VLFMT ")", i, frame->ip, filepath, frame->ip - vmap->vaddr + vmap->io_offset);
186 }
187 else
188 {
189 pr_warn(TRACE_FMT "<userspace?, unknown>", i, frame->ip);
190 }
191
192 if (vmap)
193 spinlock_release(&vmap->lock);
194
195 if (!no_relock)
196 spinlock_release(&current_cpu->mm_context->mm_lock);
197 }
198 else
199 {
200 pr_warn(TRACE_FMT "<unknown>", i, frame->ip);
201 }
202 frame = frame->bp;
203 }
204#undef TRACE_FMT
205 pr_info("-- end of stack trace");
206}
207
209{
210 ptr_t frame;
211 __asm__("mov %%rbp, %0" : "=r"(frame));
212 x86_dump_stack_at(frame, true);
213}
214
216{
217 x86_dump_stack_at(regs->bp, true);
218}
219
221{
223 x86_idt_init();
227
228 // happens before setting up the kernel MM
230
231#if MOS_DEBUG_FEATURE(x86_startup)
232 pr_info2("cpu features:");
233
234#define do_print_cpu_feature(feature) \
235 if (cpu_has_feature(CPU_FEATURE_##feature)) \
236 pr_cont(" " #feature);
237 FOR_ALL_CPU_FEATURES(do_print_cpu_feature)
238
239#undef do_print_cpu_feature
240
241#endif
242
244}
245
250
252{
253 pr_dinfo2(x86_startup, "Parsing ACPI tables...");
254
255 if (platform_info->arch_info.rsdp_addr)
256 {
257 pr_dinfo2(x86_startup, "Using RSDP from bootloader: " PTR_FMT, platform_info->arch_info.rsdp_addr);
258 acpi_rsdp = (const acpi_rsdp_t *) platform_info->arch_info.rsdp_addr;
259 }
260 else
261 {
262 pr_dinfo2(x86_startup, "Searching for RSDP in EBDA...");
264 if (!acpi_rsdp)
265 {
266 pr_dinfo2(x86_startup, "Searching for RSDP in BIOS memory region...");
268 if (!acpi_rsdp)
269 mos_panic("RSDP not found");
270 }
271 }
272
273 const pmm_region_t *acpi_region = pmm_find_reserved_region(acpi_rsdp->v1.rsdt_addr);
274 MOS_ASSERT_X(acpi_region && acpi_region->reserved, "ACPI region not found or not reserved");
275
277
278 pr_dinfo2(x86_startup, "Initializing APICs...");
280 lapic_enable(); // enable the local APIC
281 current_cpu->id = x86_platform.boot_cpu_id = lapic_get_id();
282
284 ioapic_init();
285
286 rtc_init();
287
292
296
298
300}
void acpi_parse_rsdt(const acpi_rsdp_t *rsdp)
Definition acpi.cpp:176
const acpi_rsdp_t * acpi_find_rsdp(ptr_t start, size_t size)
Definition acpi.cpp:183
acpi_rsdp_v2_t acpi_rsdp_t
void x86_unblock_aps(void)
Definition ap_entry.cpp:17
void ioapic_init(void)
Definition ioapic.cpp:93
should_inline void ioapic_enable_interrupt(u32 irq, u32 lapic_id)
Definition apic.hpp:71
void lapic_set_timer(u32 initial_count)
Definition lapic.cpp:151
should_inline u8 lapic_get_id(void)
Definition apic.hpp:45
void lapic_enable(void)
Definition lapic.cpp:136
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.hpp:15
#define MOS_ASSERT(cond)
Definition assert.hpp:14
#define MOS_PATH_MAX_LENGTH
Definition autoconf.h:27
#define MOS_PAGE_SIZE
Definition autoconf.h:6
serial_baudrate_t baudrate_divisor
Definition serial.hpp:88
serial_parity_t parity
Definition serial.hpp:91
serial_charlength_t char_length
Definition serial.hpp:89
serial_stopbits_t stop_bits
Definition serial.hpp:90
void write_register(serial_register_t reg, u8 data) override
int write_byte(u8 data) override
u8 read_register(serial_register_t reg) override
u8 read_byte() override
x86SerialDevice(x86ComPort port)
bool get_data_ready() override
void console_register(Console *con)
Definition console.cpp:92
@ CONSOLE_CAP_READ
console supports read
Definition console.hpp:21
void x86_cpu_initialise_caps(void)
Definition cpu.cpp:22
void x86_cpu_setup_xsave_area(void)
Definition cpu.cpp:39
#define FOR_ALL_CPU_FEATURES(M)
Definition cpuid.hpp:64
void x86_init_percpu_gdt()
void x86_init_percpu_tss()
void x86_init_percpu_idt(void)
Definition idt.cpp:36
void x86_idt_init(void)
Definition idt.cpp:41
@ LightBlue
Definition ansi_colors.h:28
@ Black
Definition ansi_colors.h:19
vmap_t * vmap_obtain(MMContext *mmctx, ptr_t vaddr, size_t *out_offset)
Get the vmap object for a virtual address.
Definition mm.cpp:185
#define pa_va(pa)
Definition mm.hpp:81
ptr_t mm_get_phys_addr(MMContext *ctx, ptr_t vaddr)
Definition paging.cpp:180
pmm_region_t * pmm_find_reserved_region(ptr_t needle)
Find a region in the physical memory manager.
Definition pmm.cpp:131
void interrupt_handler_register(u32 irq, irq_serve_t handler, void *data)
Register an interrupt handler.
Definition interrupt.cpp:35
void io_get_name(const io_t *io, char *buf, size_t size)
Definition io.cpp:308
void madt_parse_table()
Definition madt.cpp:25
#define KB
Definition mos_global.h:98
#define MOS_UNUSED(x)
Definition mos_global.h:65
#define unlikely(x)
Definition mos_global.h:40
void x86_paging_setup(void)
Definition paging.cpp:61
#define mos_panic(fmt,...)
Definition panic.hpp:51
#define NULL
Definition pb_syshdr.h:46
#define current_thread
Definition platform.hpp:32
#define current_cpu
Definition platform.hpp:31
should_inline void port_outb(u16 port, u8 value)
Definition port.hpp:31
should_inline u8 port_inb(u16 port)
Definition port.hpp:10
#define pr_info2(fmt,...)
Definition printk.hpp:36
#define pr_warn(fmt,...)
Definition printk.hpp:38
#define pr_emerg(fmt,...)
Definition printk.hpp:39
#define pr_info(fmt,...)
Definition printk.hpp:35
#define pr_dinfo2(feat, fmt,...)
Definition printk.hpp:27
#define MOS_KERNEL_START_VADDR
mos_platform_info_t *const platform_info
bool rtc_irq_handler(u32 irq, void *data)
Definition rtc.cpp:98
void rtc_init()
Definition rtc.cpp:107
void reschedule(void)
reschedule.
Definition schedule.cpp:107
@ STOP_BITS_15_OR_2
Definition serial.hpp:32
serial_register_t
Definition serial.hpp:8
@ CHAR_LENGTH_8
Definition serial.hpp:26
@ BAUD_RATE_115200
Definition serial.hpp:56
@ PARITY_EVEN
Definition serial.hpp:39
bool serial_console_irq_handler(u32 irq, void *data)
should_inline bool spinlock_is_locked(const spinlock_t *lock)
Definition spinlock.hpp:71
#define spinlock_acquire(lock)
Definition spinlock.hpp:64
#define spinlock_release(lock)
Definition spinlock.hpp:65
struct _frame * bp
bool reserved
Definition pmm.hpp:61
Definition mm.hpp:59
ptr_t vaddr
Definition mm.hpp:63
spinlock_t lock
Definition mm.hpp:61
io_t * io
Definition mm.hpp:68
off_t io_offset
Definition mm.hpp:69
#define PTR_VLFMT
Definition types.h:30
unsigned int u32
Definition types.h:17
unsigned long long pfn_t
Definition types.h:37
#define PTR_FMT
Definition types.h:29
unsigned short u16
Definition types.h:16
unsigned long ptr_t
Definition types.h:21
unsigned char u8
Definition types.h:15
@ IRQ_KEYBOARD
@ IRQ_CMOS_RTC
@ IRQ_COM1
@ IRQ_PIT_TIMER
void pic_remap_irq(void)
Definition pic.cpp:25
static bool x86_pit_timer_handler(u32 irq, void *data)
SerialConsole com1_console
x86SerialDevice com1_device
#define TRACE_FMT
void x86_setup_lapic_timer()
static Buffer< MOS_PAGE_SIZE > com2_buf
void platform_startup_setup_kernel_mm()
static Buffer< MOS_PAGE_SIZE > com1_buf
static bool x86_keyboard_handler(u32 irq, void *data)
const acpi_rsdp_t * acpi_rsdp
void platform_startup_late()
void platform_startup_early()
x86SerialDevice com2_device
void platform_dump_current_stack(void)
void x86_dump_stack_at(ptr_t this_frame, bool can_access_vmaps)
void platform_dump_stack(platform_regs_t *regs)
SerialConsole com2_console
x86ComPort
@ COM1
@ COM4
@ COM5
@ COM2
@ COM8
@ COM3
@ COM7
@ COM6
mos_platform_info_t x86_platform
#define EBDA_MEMREGION_SIZE
#define X86_BIOS_MEMREGION_PADDR
#define X86_EBDA_MEMREGION_PADDR
#define BIOS_MEMREGION_SIZE