mirror of https://github.com/wolfSSL/wolfBoot.git
x86: support cpu exceptions
parent
0833c4b1bf
commit
4bbe43e222
1
arch.mk
1
arch.mk
|
@ -734,6 +734,7 @@ ifeq ("${FSP}", "1")
|
|||
OBJS += src/x86/gpt.o
|
||||
OBJS += src/x86/mptable.o
|
||||
OBJS += src/stage1.o
|
||||
OBJS += src/x86/exceptions.o
|
||||
UPDATE_OBJS := src/update_disk.o
|
||||
ifeq ($(64BIT),1)
|
||||
LDFLAGS += -m elf_x86_64 --oformat elf64-x86-64
|
||||
|
|
|
@ -67,4 +67,5 @@ void cpuid(uint32_t eax_param,
|
|||
int cpuid_is_1gb_page_supported();
|
||||
void switch_to_long_mode(uint64_t *entry, uint32_t page_table);
|
||||
void x86_log_memory_load(uint32_t start, uint32_t end, const char *name);
|
||||
void hlt();
|
||||
#endif /* COMMON_H */
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/* exceptions.h
|
||||
*
|
||||
* Copyright (C) 2023 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfBoot is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfBoot is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef EXCEPTIONS_H
|
||||
#define EXCEPTIONS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int setup_interrupt_gate(int vnum, uintptr_t handler);
|
||||
int setup_interrupts();
|
||||
void deinit_interrupts();
|
||||
void wfi();
|
||||
|
||||
#endif /* EXCEPTIONS_H */
|
|
@ -0,0 +1,216 @@
|
|||
/* exceptions.c
|
||||
*
|
||||
* Copyright (C) 2023 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfBoot is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfBoot is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <x86/common.h>
|
||||
#include <x86/exceptions.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define EXCEPTION_NUM 35
|
||||
#define INTERRUPT_GATE_TYPE (0xe)
|
||||
#define SEGMENT_SELECTOR (0x18)
|
||||
#define TYPE_FLAG (INTERRUPT_GATE_TYPE << 8 | 1 << 15)
|
||||
|
||||
#define LAPIC_DIV_CONF_REG 0xfee003e0
|
||||
#define LAPIC_INITIAL_CNT 0xfee00380
|
||||
#define LAPIC_CURRENT_CNT 0xfee00390
|
||||
#define LAPIC_LVT_TIMER_REG 0xfee00320
|
||||
#define LAPIC_EOI 0xfee000b0
|
||||
#define LAPIC_SVR 0xfee000f0
|
||||
#define LAPIC_SVR_ENABLE (1 << 8)
|
||||
#define LAPIC_DIV_CONF_128 (1 << 1 | 1 << 3)
|
||||
#define TIMER_SPURIOUS_NUMBER (33)
|
||||
#define TIMER_VECTOR_NUMBER (34)
|
||||
#define TIMER_CNT 0xffffff
|
||||
#define IA32_APIC_BASE_MSR (0x1b)
|
||||
#define IA32_APIC_BASE_MSR_ENABLE (0x800)
|
||||
|
||||
#define DEBUG_EXCEPTIONS
|
||||
#if defined(DEBUG_EXCEPTIONS)
|
||||
#include <printf.h>
|
||||
#define EXCEPTIONS_DEBUG_PRINTF(...) wolfBoot_printf(__VA_ARGS__)
|
||||
#else
|
||||
#define EXCEPTIONS_DEBUG_PRINTF(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
struct interrupt_gate {
|
||||
uint16_t offset_0_15;
|
||||
uint16_t seg_sel;
|
||||
uint16_t type_flags;
|
||||
uint16_t offset_31_16;
|
||||
uint32_t offset_63_32;
|
||||
uint32_t reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct idt_descriptor {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed));
|
||||
|
||||
static struct interrupt_gate idt_table[EXCEPTION_NUM];
|
||||
static struct idt_descriptor idt_descriptor;
|
||||
|
||||
#define EXCEPTION_TRAMPOLINE(X) \
|
||||
__attribute__((naked)) void exception_trampoline_##X() { \
|
||||
asm volatile("cli\r\n" \
|
||||
"mov %0, %%rdi\r\n" \
|
||||
"sti\r\n" \
|
||||
"call common_exception_handler\r\n" \
|
||||
"iretq\r\n" \
|
||||
: \
|
||||
: ""(X)); \
|
||||
}
|
||||
|
||||
static void common_exception_handler(uint64_t vector_number)
|
||||
{
|
||||
EXCEPTIONS_DEBUG_PRINTF("CPU exception: %d\r\n", (int)vector_number);
|
||||
}
|
||||
|
||||
EXCEPTION_TRAMPOLINE(0);
|
||||
EXCEPTION_TRAMPOLINE(1);
|
||||
EXCEPTION_TRAMPOLINE(2);
|
||||
EXCEPTION_TRAMPOLINE(3);
|
||||
EXCEPTION_TRAMPOLINE(4);
|
||||
EXCEPTION_TRAMPOLINE(5);
|
||||
EXCEPTION_TRAMPOLINE(6);
|
||||
EXCEPTION_TRAMPOLINE(7);
|
||||
EXCEPTION_TRAMPOLINE(8);
|
||||
EXCEPTION_TRAMPOLINE(9);
|
||||
EXCEPTION_TRAMPOLINE(10);
|
||||
EXCEPTION_TRAMPOLINE(11);
|
||||
EXCEPTION_TRAMPOLINE(12)
|
||||
EXCEPTION_TRAMPOLINE(13);
|
||||
EXCEPTION_TRAMPOLINE(14);
|
||||
EXCEPTION_TRAMPOLINE(15);
|
||||
EXCEPTION_TRAMPOLINE(16);
|
||||
EXCEPTION_TRAMPOLINE(17);
|
||||
EXCEPTION_TRAMPOLINE(18);
|
||||
EXCEPTION_TRAMPOLINE(19);
|
||||
EXCEPTION_TRAMPOLINE(20);
|
||||
EXCEPTION_TRAMPOLINE(21);
|
||||
EXCEPTION_TRAMPOLINE(22);
|
||||
EXCEPTION_TRAMPOLINE(23);
|
||||
EXCEPTION_TRAMPOLINE(24);
|
||||
EXCEPTION_TRAMPOLINE(25);
|
||||
EXCEPTION_TRAMPOLINE(26);
|
||||
EXCEPTION_TRAMPOLINE(27);
|
||||
EXCEPTION_TRAMPOLINE(28);
|
||||
EXCEPTION_TRAMPOLINE(29);
|
||||
EXCEPTION_TRAMPOLINE(30);
|
||||
EXCEPTION_TRAMPOLINE(31);
|
||||
EXCEPTION_TRAMPOLINE(32);
|
||||
/* lapic spurious vector */
|
||||
EXCEPTION_TRAMPOLINE(33);
|
||||
|
||||
int setup_interrupt_gate(int vnum, uintptr_t handler)
|
||||
{
|
||||
struct interrupt_gate *ig;
|
||||
|
||||
ig = &idt_table[vnum];
|
||||
ig->offset_0_15 = (uint16_t)(handler & 0xffff);
|
||||
ig->offset_31_16 = (uint16_t)((handler >> 16) & 0xffff);
|
||||
ig->offset_63_32 = (uint32_t)((handler) >> 32);
|
||||
ig->type_flags = TYPE_FLAG;
|
||||
ig->seg_sel = SEGMENT_SELECTOR;
|
||||
ig->reserved = 0x0;
|
||||
}
|
||||
|
||||
static void _timer_handler()
|
||||
{
|
||||
EXCEPTIONS_DEBUG_PRINTF("In the timer handler\r\n");
|
||||
}
|
||||
|
||||
static void __attribute__((__naked__)) timer_handler() {
|
||||
asm volatile("cli\r\n"
|
||||
"call _timer_handler\r\n"
|
||||
"sti\r\n"
|
||||
"mov %0, %%eax\r\n"
|
||||
"movl $0, (%%eax)\r\n"
|
||||
"iretq\r\n"::""(LAPIC_EOI));
|
||||
}
|
||||
|
||||
static void setup_apic_timer()
|
||||
{
|
||||
mmio_write32(LAPIC_SVR, (LAPIC_SVR_ENABLE));
|
||||
mmio_write32(LAPIC_DIV_CONF_REG, LAPIC_DIV_CONF_128);
|
||||
setup_interrupt_gate(TIMER_VECTOR_NUMBER, (uintptr_t)timer_handler);
|
||||
mmio_write32(LAPIC_LVT_TIMER_REG, TIMER_VECTOR_NUMBER);
|
||||
}
|
||||
|
||||
int setup_interrupts()
|
||||
{
|
||||
setup_interrupt_gate(0,(uintptr_t) exception_trampoline_0);
|
||||
setup_interrupt_gate(1,(uintptr_t) exception_trampoline_1);
|
||||
setup_interrupt_gate(2,(uintptr_t) exception_trampoline_2);
|
||||
setup_interrupt_gate(3,(uintptr_t) exception_trampoline_3);
|
||||
setup_interrupt_gate(4,(uintptr_t) exception_trampoline_4);
|
||||
setup_interrupt_gate(5,(uintptr_t) exception_trampoline_5);
|
||||
setup_interrupt_gate(6,(uintptr_t) exception_trampoline_6);
|
||||
setup_interrupt_gate(7,(uintptr_t) exception_trampoline_7);
|
||||
setup_interrupt_gate(8,(uintptr_t) exception_trampoline_8);
|
||||
setup_interrupt_gate(9,(uintptr_t) exception_trampoline_9);
|
||||
setup_interrupt_gate(10,(uintptr_t) exception_trampoline_10);
|
||||
setup_interrupt_gate(11,(uintptr_t) exception_trampoline_11);
|
||||
setup_interrupt_gate(12,(uintptr_t) exception_trampoline_12);
|
||||
setup_interrupt_gate(13,(uintptr_t) exception_trampoline_13);
|
||||
setup_interrupt_gate(14,(uintptr_t) exception_trampoline_14);
|
||||
setup_interrupt_gate(15,(uintptr_t) exception_trampoline_15);
|
||||
setup_interrupt_gate(16,(uintptr_t) exception_trampoline_16);
|
||||
setup_interrupt_gate(17,(uintptr_t) exception_trampoline_17);
|
||||
setup_interrupt_gate(18,(uintptr_t) exception_trampoline_18);
|
||||
setup_interrupt_gate(19,(uintptr_t) exception_trampoline_19);
|
||||
setup_interrupt_gate(20,(uintptr_t) exception_trampoline_20);
|
||||
setup_interrupt_gate(21,(uintptr_t) exception_trampoline_21);
|
||||
setup_interrupt_gate(22,(uintptr_t) exception_trampoline_22);
|
||||
setup_interrupt_gate(23,(uintptr_t) exception_trampoline_23);
|
||||
setup_interrupt_gate(24,(uintptr_t) exception_trampoline_24);
|
||||
setup_interrupt_gate(25,(uintptr_t) exception_trampoline_25);
|
||||
setup_interrupt_gate(26,(uintptr_t) exception_trampoline_26);
|
||||
setup_interrupt_gate(27,(uintptr_t) exception_trampoline_27);
|
||||
setup_interrupt_gate(28,(uintptr_t) exception_trampoline_28);
|
||||
setup_interrupt_gate(29,(uintptr_t) exception_trampoline_29);
|
||||
setup_interrupt_gate(30,(uintptr_t) exception_trampoline_30);
|
||||
setup_interrupt_gate(31,(uintptr_t) exception_trampoline_31);
|
||||
|
||||
setup_apic_timer();
|
||||
idt_descriptor.base = (uintptr_t)&idt_table;
|
||||
idt_descriptor.limit = sizeof(idt_table) -1;
|
||||
|
||||
asm ("lidt %0\r\n" : : "m"(idt_descriptor));
|
||||
asm ("sti\r\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void deinit_interrupts()
|
||||
{
|
||||
idt_descriptor.base = (uintptr_t)NULL;
|
||||
idt_descriptor.limit = 0xffff;
|
||||
asm ("cli\r\n");
|
||||
asm ("lidt %0\r\n" : : "m"(idt_descriptor));
|
||||
}
|
||||
|
||||
void wfi()
|
||||
{
|
||||
setup_apic_timer();
|
||||
mmio_write32(LAPIC_INITIAL_CNT, TIMER_CNT);
|
||||
hlt();
|
||||
}
|
Loading…
Reference in New Issue