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 <ansi_colors.h>
26#include <mos_stdlib.hpp>
27#include <mos_string.hpp>
28
29typedef enum : u16
30{
31 COM1 = 0x3F8,
32 COM2 = 0x2F8,
33 COM3 = 0x3E8,
34 COM4 = 0x2E8,
35 COM5 = 0x5F8,
36 COM6 = 0x4F8,
37 COM7 = 0x5E8,
38 COM8 = 0x4E8
40
42{
44
45 public:
53
54 public:
55 u8 ReadByte() override
56 {
57 return port_inb(port);
58 }
59
60 int WriteByte(u8 data) override
61 {
62 port_outb(port, data);
63 return 0;
64 }
65
67 {
68 return port_inb((u16) port + reg);
69 }
70
71 void write_register(serial_register_t reg, u8 data) override
72 {
73 port_outb((u16) port + reg, data);
74 }
75
76 bool get_data_ready() override
77 {
78 return (port_inb(port + 5) & 1) != 0;
79 }
80};
81
84
87
90
94
95static bool x86_keyboard_handler(u32 irq, void *data)
96{
97 MOS_UNUSED(data);
99 int scancode = port_inb(0x60);
100
101 pr_info("Keyboard scancode: %x", scancode);
102 return true;
103}
104
105static bool x86_pit_timer_handler(u32 irq, void *data)
106{
107 MOS_UNUSED(data);
109 spinlock_acquire(&current_thread->state_lock);
110 reschedule();
111 return true;
112}
113
115{
116 lapic_set_timer(1000000);
117}
118
119typedef struct _frame
120{
121 struct _frame *bp;
123} frame_t;
124
125void x86_dump_stack_at(ptr_t this_frame, bool can_access_vmaps)
126{
127 frame_t *frame = (frame_t *) this_frame;
128
129 const bool do_mapped_check = current_cpu->mm_context;
130
131 if (unlikely(!do_mapped_check))
132 pr_warn(" no mm context available, mapping checks are disabled (early-boot panic?)");
133
134 const bool no_relock = do_mapped_check && spinlock_is_locked(&current_cpu->mm_context->mm_lock);
135 if (no_relock)
136 pr_emerg(" mm lock is already held, stack trace may be corrupted");
137
138 pr_info("-- stack trace:");
139 for (u32 i = 0; frame; i++)
140 {
141#define TRACE_FMT " %-3d [" PTR_FMT "]: "
142 if (do_mapped_check)
143 {
144 const pfn_t pfn = mm_get_phys_addr(current_cpu->mm_context, (ptr_t) frame) / MOS_PAGE_SIZE;
145 if (!pfn)
146 {
147 pr_emerg(TRACE_FMT "<corrupted>, aborting backtrace", i, (ptr_t) frame);
148 break;
149 }
150 }
151
152 if (frame->bp == 0)
153 {
154 // end of stack
155 pr_warn(TRACE_FMT "<end>", i, (ptr_t) 0);
156 break;
157 }
158 else if (frame == frame->bp)
159 {
160 pr_emerg(TRACE_FMT "<corrupted>, aborting backtrace", i, (ptr_t) frame);
161 break;
162 }
163 else if (frame->ip >= MOS_KERNEL_START_VADDR)
164 {
165 pr_warn(TRACE_FMT "%ps", i, frame->ip, (void *) frame->ip);
166 }
167 else if (frame->ip == 0)
168 {
169 pr_warn(TRACE_FMT "<end>", i, frame->ip);
170 break;
171 }
172 else if (frame->ip < 1 KB)
173 {
174 pr_emerg(TRACE_FMT "<corrupted?>", i, frame->ip);
175 }
176 else if (can_access_vmaps)
177 {
178 if (!no_relock)
179 spinlock_acquire(&current_cpu->mm_context->mm_lock);
180 vmap_t *const vmap = vmap_obtain(current_cpu->mm_context, (ptr_t) frame->ip);
181
182 if (vmap && vmap->io)
183 {
184 const auto name = vmap->io->name();
185 pr_warn(TRACE_FMT "%s (+" PTR_VLFMT ")", i, frame->ip, name.c_str(), 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{
222 COM2Console.Register();
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:195
const acpi_rsdp_t * acpi_find_rsdp(ptr_t start, size_t size)
Definition acpi.cpp:202
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:12
#define MOS_ASSERT(cond)
Definition assert.hpp:19
#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
u8 read_register(serial_register_t reg) override
int WriteByte(u8 data) override
u8 ReadByte() override
x86SerialDevice(x86ComPort port)
bool get_data_ready() override
@ CONSOLE_CAP_READ
console supports read
Definition console.hpp:22
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:65
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=nullptr)
Get the vmap object for a virtual address.
Definition mm.cpp:189
#define pa_va(pa)
Definition mm.hpp:87
ptr_t mm_get_phys_addr(MMContext *ctx, ptr_t vaddr)
Definition paging.cpp:179
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 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:33
#define current_cpu
Definition platform.hpp:32
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:106
@ 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)
const char * name
Definition slab.cpp:33
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
virtual mos::string name() const
Definition io.cpp:45
struct _frame * bp
bool reserved
Definition pmm.hpp:61
Definition mm.hpp:60
ptr_t vaddr
Definition mm.hpp:64
IO * io
Definition mm.hpp:69
spinlock_t lock
Definition mm.hpp:62
off_t io_offset
Definition mm.hpp:70
#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)
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
SerialConsole COM2Console
void platform_dump_current_stack(void)
void x86_dump_stack_at(ptr_t this_frame, bool can_access_vmaps)
void platform_dump_stack(const platform_regs_t *regs)
x86ComPort
@ COM1
@ COM4
@ COM5
@ COM2
@ COM8
@ COM3
@ COM7
@ COM6
SerialConsole COM1Console
mos_platform_info_t x86_platform
#define EBDA_MEMREGION_SIZE
#define X86_BIOS_MEMREGION_PADDR
#define X86_EBDA_MEMREGION_PADDR
#define BIOS_MEMREGION_SIZE