MOS Source Code
Loading...
Searching...
No Matches
x86_platform.c
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4
8#include "mos/mm/mm.h"
10#include "mos/syslog/printk.h"
11#include "mos/tasks/schedule.h"
12#include "mos/x86/acpi/acpi.h"
14#include "mos/x86/acpi/madt.h"
16#include "mos/x86/cpu/cpu.h"
19#include "mos/x86/devices/rtc.h"
24
25#include <mos_stdlib.h>
26#include <mos_string.h>
27
28static u8 com1_buf[MOS_PAGE_SIZE] __aligned(MOS_PAGE_SIZE) = { 0 };
29static u8 com2_buf[MOS_PAGE_SIZE] __aligned(MOS_PAGE_SIZE) = { 0 };
30
32 .device = { .driver = &x86_serial_driver,
33 .driver_data = (void *) COM1,
34 .baudrate_divisor = BAUD_RATE_115200,
35 .char_length = CHAR_LENGTH_8,
36 .stop_bits = STOP_BITS_15_OR_2,
37 .parity = PARITY_EVEN },
38 .con = { .ops = &(console_ops_t){ .extra_setup = serial_console_setup },
39 .name = "serial_com1",
41 .read.buf = com1_buf,
42 .read.size = MOS_PAGE_SIZE,
43 .default_fg = LightBlue,
44 .default_bg = Black },
45};
46
48 .device = { .driver = &x86_serial_driver,
49 .driver_data = (void *) COM2,
50 .baudrate_divisor = BAUD_RATE_115200,
51 .char_length = CHAR_LENGTH_8,
52 .stop_bits = STOP_BITS_15_OR_2,
53 .parity = PARITY_EVEN },
54 .con = { .ops = &(console_ops_t){ .extra_setup = serial_console_setup },
55 .name = "serial_com2",
57 .read.buf = com2_buf,
58 .read.size = MOS_PAGE_SIZE,
59 .default_fg = LightBlue,
60 .default_bg = Black },
61};
62
66
67static bool x86_keyboard_handler(u32 irq, void *data)
68{
69 MOS_UNUSED(data);
71 int scancode = port_inb(0x60);
72
73 pr_info("Keyboard scancode: %x", scancode);
74 return true;
75}
76
77static bool x86_pit_timer_handler(u32 irq, void *data)
78{
79 MOS_UNUSED(data);
81 spinlock_acquire(&current_thread->state_lock);
82 reschedule();
83 return true;
84}
85
87{
88 lapic_set_timer(1000000);
89}
90
91typedef struct _frame
92{
93 struct _frame *bp;
95} frame_t;
96
97void x86_dump_stack_at(ptr_t this_frame, bool can_access_vmaps)
98{
99 frame_t *frame = (frame_t *) this_frame;
100
101 const bool do_mapped_check = current_cpu->mm_context;
102
103 if (unlikely(!do_mapped_check))
104 pr_warn(" no mm context available, mapping checks are disabled (early-boot panic?)");
105
106 const bool no_relock = do_mapped_check && spinlock_is_locked(&current_cpu->mm_context->mm_lock);
107 if (no_relock)
108 pr_emerg(" mm lock is already held, stack trace may be corrupted");
109
110 pr_info("-- stack trace:");
111 for (u32 i = 0; frame; i++)
112 {
113#define TRACE_FMT " %-3d [" PTR_FMT "]: "
114 if (do_mapped_check)
115 {
116 const pfn_t pfn = mm_get_phys_addr(current_cpu->mm_context, (ptr_t) frame) / MOS_PAGE_SIZE;
117 if (!pfn)
118 {
119 pr_emerg(TRACE_FMT "<corrupted>, aborting backtrace", i, (ptr_t) frame);
120 break;
121 }
122 }
123
124 if (frame->bp == 0)
125 {
126 // end of stack
127 pr_warn(TRACE_FMT "<end>", i, (ptr_t) 0);
128 break;
129 }
130 else if (frame == frame->bp)
131 {
132 pr_emerg(TRACE_FMT "<corrupted>, aborting backtrace", i, (ptr_t) frame);
133 break;
134 }
135 else if (frame->ip >= MOS_KERNEL_START_VADDR)
136 {
137 pr_warn(TRACE_FMT "%ps", i, frame->ip, (void *) frame->ip);
138 }
139 else if (frame->ip == 0)
140 {
141 pr_warn(TRACE_FMT "<end>", i, frame->ip);
142 break;
143 }
144 else if (frame->ip < 1 KB)
145 {
146 pr_emerg(TRACE_FMT "<corrupted?>", i, frame->ip);
147 }
148 else if (can_access_vmaps)
149 {
150 if (!no_relock)
151 spinlock_acquire(&current_cpu->mm_context->mm_lock);
152 vmap_t *const vmap = vmap_obtain(current_cpu->mm_context, (ptr_t) frame->ip, NULL);
153
154 if (vmap && vmap->io)
155 {
156 char filepath[MOS_PATH_MAX_LENGTH];
157 io_get_name(vmap->io, filepath, sizeof(filepath));
158 pr_warn(TRACE_FMT "%s (+" PTR_VLFMT ")", i, frame->ip, filepath, frame->ip - vmap->vaddr + vmap->io_offset);
159 }
160 else
161 {
162 pr_warn(TRACE_FMT "<userspace?, unknown>", i, frame->ip);
163 }
164
165 if (vmap)
166 spinlock_release(&vmap->lock);
167
168 if (!no_relock)
169 spinlock_release(&current_cpu->mm_context->mm_lock);
170 }
171 else
172 {
173 pr_warn(TRACE_FMT "<unknown>", i, frame->ip);
174 }
175 frame = frame->bp;
176 }
177#undef TRACE_FMT
178 pr_info("-- end of stack trace");
179}
180
182{
183 ptr_t frame;
184 __asm__("mov %%rbp, %0" : "=r"(frame));
185 x86_dump_stack_at(frame, true);
186}
187
189{
190 x86_dump_stack_at(regs->bp, true);
191}
192
194{
196 x86_idt_init();
200
201 // happens before setting up the kernel MM
203
204#if MOS_DEBUG_FEATURE(x86_startup)
205 pr_info2("cpu features:");
206
207#define do_print_cpu_feature(feature) \
208 if (cpu_has_feature(CPU_FEATURE_##feature)) \
209 pr_cont(" " #feature);
210 FOR_ALL_CPU_FEATURES(do_print_cpu_feature)
211
212#undef do_print_cpu_feature
213
214#endif
215
217}
218
223
225{
226 pr_dinfo2(x86_startup, "Parsing ACPI tables...");
227
229 {
230 pr_dinfo2(x86_startup, "Using RSDP from bootloader: " PTR_FMT, platform_info->arch_info.rsdp_addr);
232 }
233 else
234 {
235 pr_dinfo2(x86_startup, "Searching for RSDP in EBDA...");
237 if (!acpi_rsdp)
238 {
239 pr_dinfo2(x86_startup, "Searching for RSDP in BIOS memory region...");
241 if (!acpi_rsdp)
242 mos_panic("RSDP not found");
243 }
244 }
245
247 MOS_ASSERT_X(acpi_region && acpi_region->reserved, "ACPI region not found or not reserved");
248
250
251 pr_dinfo2(x86_startup, "Initializing APICs...");
253 lapic_enable(); // enable the local APIC
255
257 ioapic_init();
258
259 rtc_init();
260
265
269
271
273}
void acpi_parse_rsdt(const acpi_rsdp_t *rsdp)
Definition acpi.c:173
const acpi_rsdp_t * acpi_find_rsdp(ptr_t start, size_t size)
Definition acpi.c:180
void x86_unblock_aps(void)
Definition ap_entry.c:17
void ioapic_init(void)
Definition ioapic.c:93
should_inline void ioapic_enable_interrupt(u32 irq, u32 lapic_id)
Definition apic.h:71
void lapic_set_timer(u32 initial_count)
Definition lapic.c:151
should_inline u8 lapic_get_id(void)
Definition apic.h:45
void lapic_enable(void)
Definition lapic.c:136
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.h:15
#define MOS_ASSERT(cond)
Definition assert.h:14
#define MOS_PATH_MAX_LENGTH
Definition autoconf.h:27
#define MOS_PAGE_SIZE
Definition autoconf.h:6
void console_register(console_t *con)
Definition console.c:71
@ CONSOLE_CAP_READ
console supports read
Definition console.h:21
@ CONSOLE_CAP_EXTRA_SETUP
extra setup required
Definition console.h:20
void x86_cpu_initialise_caps(void)
Definition cpu.c:20
void x86_cpu_setup_xsave_area(void)
Definition cpu.c:37
#define FOR_ALL_CPU_FEATURES(M)
Definition cpuid.h:64
void x86_init_percpu_gdt()
Definition descriptors.c:59
void x86_init_percpu_tss()
Definition descriptors.c:86
void x86_init_percpu_idt(void)
Definition idt.c:36
void x86_idt_init(void)
Definition idt.c:41
@ LightBlue
Definition ansi_colors.h:28
@ Black
Definition ansi_colors.h:19
vmap_t * vmap_obtain(mm_context_t *mmctx, ptr_t vaddr, size_t *out_offset)
Get the vmap object for a virtual address.
Definition mm.c:192
#define pa_va(pa)
Definition mm.h:80
ptr_t mm_get_phys_addr(mm_context_t *ctx, ptr_t vaddr)
Definition paging.c:179
pmm_region_t * pmm_find_reserved_region(ptr_t needle)
Find a region in the physical memory manager.
Definition pmm.c:131
void interrupt_handler_register(u32 irq, irq_serve_t handler, void *data)
Register an interrupt handler.
Definition interrupt.c:38
void io_get_name(const io_t *io, char *buf, size_t size)
Definition io.c:307
void madt_parse_table()
Definition madt.c:25
#define KB
Definition mos_global.h:88
#define __aligned(x)
Definition mos_global.h:27
#define MOS_UNUSED(x)
Definition mos_global.h:64
#define unlikely(x)
Definition mos_global.h:40
void x86_paging_setup(void)
Definition paging.c:60
#define mos_panic(fmt,...)
Definition panic.h:55
#define NULL
Definition pb_syshdr.h:46
#define current_thread
Definition platform.h:30
#define current_cpu
Definition platform.h:29
should_inline u8 port_inb(u16 port)
Definition port.h:10
#define pr_info2(fmt,...)
Definition printk.h:36
#define pr_warn(fmt,...)
Definition printk.h:38
#define pr_emerg(fmt,...)
Definition printk.h:39
#define pr_info(fmt,...)
Definition printk.h:35
#define pr_dinfo2(feat, fmt,...)
Definition printk.h:27
#define MOS_KERNEL_START_VADDR
bool rtc_irq_handler(u32 irq, void *data)
Definition rtc.c:99
void rtc_init()
Definition rtc.c:108
void reschedule(void)
reschedule.
Definition schedule.c:107
@ STOP_BITS_15_OR_2
Definition serial.h:32
@ CHAR_LENGTH_8
Definition serial.h:26
@ BAUD_RATE_115200
Definition serial.h:56
@ PARITY_EVEN
Definition serial.h:39
bool serial_console_setup(console_t *console)
bool serial_console_irq_handler(u32 irq, void *data)
const serial_driver_t x86_serial_driver
@ COM1
@ COM2
should_inline bool spinlock_is_locked(const spinlock_t *lock)
Definition spinlock.h:68
#define spinlock_acquire(lock)
Definition spinlock.h:61
#define spinlock_release(lock)
Definition spinlock.h:62
acpi_rsdp_v1_t v1
Definition acpi_types.h:20
ptr_t ip
struct _frame * bp
platform_arch_info_t arch_info
Definition platform.h:132
bool reserved
Definition pmm.h:68
Definition mm.h:58
ptr_t vaddr
Definition mm.h:62
spinlock_t lock
Definition mm.h:60
io_t * io
Definition mm.h:67
off_t io_offset
Definition mm.h:68
#define PTR_VLFMT
Definition types.h:34
unsigned int u32
Definition types.h:21
unsigned long long pfn_t
Definition types.h:41
#define PTR_FMT
Definition types.h:33
unsigned long ptr_t
Definition types.h:25
unsigned char u8
Definition types.h:19
@ IRQ_KEYBOARD
@ IRQ_CMOS_RTC
@ IRQ_COM1
@ IRQ_PIT_TIMER
void pic_remap_irq(void)
Definition pic.c:25
static bool x86_pit_timer_handler(u32 irq, void *data)
mos_platform_info_t x86_platform
#define TRACE_FMT
serial_console_t com1_console
void x86_setup_lapic_timer()
void platform_startup_setup_kernel_mm()
static bool x86_keyboard_handler(u32 irq, void *data)
const acpi_rsdp_t * acpi_rsdp
serial_console_t com2_console
void platform_startup_late()
void platform_startup_early()
void platform_dump_current_stack(void)
void x86_dump_stack_at(ptr_t this_frame, bool can_access_vmaps)
mos_platform_info_t *const platform_info
void platform_dump_stack(platform_regs_t *regs)
#define EBDA_MEMREGION_SIZE
#define X86_BIOS_MEMREGION_PADDR
Definition x86_platform.h:7
#define X86_EBDA_MEMREGION_PADDR
#define BIOS_MEMREGION_SIZE
Definition x86_platform.h:8