mirror of https://github.com/l4ka/pistachio.git
- Introduce supppoprt for APIC error handling
- Start IOAPIC base after LAPIC LVT irqs - Use uncacheable mappings for APIC and ACPI memory -
This commit is contained in:
parent
e029062e4e
commit
997eeb3d4a
|
@ -169,6 +169,24 @@ private:
|
||||||
} x;
|
} x;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class esr_reg_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union {
|
||||||
|
u32_t raw;
|
||||||
|
struct {
|
||||||
|
u32_t tx_csum : 1;
|
||||||
|
u32_t rx_csum : 1;
|
||||||
|
u32_t tx_accept : 1;
|
||||||
|
u32_t rx_accept : 1;
|
||||||
|
u32_t tx_illegal_vector : 1;
|
||||||
|
u32_t rx_illegal_vector : 1;
|
||||||
|
u32_t illegal_reg : 1;
|
||||||
|
u32_t reserved : 25;
|
||||||
|
} x;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
void set_prio(regno_t reg, u8_t prio, u8_t subprio)
|
void set_prio(regno_t reg, u8_t prio, u8_t subprio)
|
||||||
{
|
{
|
||||||
|
@ -233,7 +251,8 @@ public:
|
||||||
bool set_vector(lvt_t lvt, delivery_mode_t del_mode,
|
bool set_vector(lvt_t lvt, delivery_mode_t del_mode,
|
||||||
pin_polarity_t polarity,
|
pin_polarity_t polarity,
|
||||||
trigger_mode_t trigger_mode);
|
trigger_mode_t trigger_mode);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Timer handling */
|
/* Timer handling */
|
||||||
u32_t timer_get() {
|
u32_t timer_get() {
|
||||||
|
@ -299,6 +318,22 @@ public:
|
||||||
void send_ipi(u8_t apic_id, u8_t vector);
|
void send_ipi(u8_t apic_id, u8_t vector);
|
||||||
void broadcast_ipi(u8_t vector, bool self = false);
|
void broadcast_ipi(u8_t vector, bool self = false);
|
||||||
void broadcast_nmi(bool self = false);
|
void broadcast_nmi(bool self = false);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Error handling */
|
||||||
|
void error_setup(u8_t irq)
|
||||||
|
{
|
||||||
|
write_reg((regno_t) APIC_LVT_ERROR, irq);
|
||||||
|
write_reg((regno_t) APIC_ERR_STATUS, 0);
|
||||||
|
write_reg((regno_t) APIC_ERR_STATUS, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
word_t read_error()
|
||||||
|
{
|
||||||
|
write_reg((regno_t) APIC_ERR_STATUS, 0);
|
||||||
|
return read_reg((regno_t) APIC_ERR_STATUS);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -339,7 +374,7 @@ INLINE bool local_apic_t<base>::disable()
|
||||||
spurious_int_vector_reg_t svr;
|
spurious_int_vector_reg_t svr;
|
||||||
svr.raw = read_reg(APIC_SVR);
|
svr.raw = read_reg(APIC_SVR);
|
||||||
bool enabled = svr.x.enabled;
|
bool enabled = svr.x.enabled;
|
||||||
svr.x.enabled = 0;
|
svr.x.enabled = 0;
|
||||||
write_reg(APIC_SVR, svr.raw);
|
write_reg(APIC_SVR, svr.raw);
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
@ -347,15 +382,12 @@ INLINE bool local_apic_t<base>::disable()
|
||||||
template <word_t base>
|
template <word_t base>
|
||||||
INLINE void local_apic_t<base>::send_startup_ipi(u8_t apic_id, void(*startup_func)(void))
|
INLINE void local_apic_t<base>::send_startup_ipi(u8_t apic_id, void(*startup_func)(void))
|
||||||
{
|
{
|
||||||
//ASSERT(((word_t)startup & ~X86_PAGE_MASK) == 0);
|
|
||||||
//ASSERT(((word_t)startup >> (X86_PAGE_BITS + 8)) == 0);
|
|
||||||
|
|
||||||
// destination
|
// destination
|
||||||
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
||||||
command_reg_t reg;
|
command_reg_t reg;
|
||||||
reg.raw = read_reg(APIC_INTR_CMD1);
|
reg.raw = read_reg(APIC_INTR_CMD1);
|
||||||
// the startup-address of the receiving processor is
|
// the startup-address of the receiving processor is
|
||||||
// 0x000VV000, where VV is sent with the SIPI.
|
// 0x000VV000, where VV is sent with the SIPI.
|
||||||
word_t startup_vector = (word_t) startup_func;
|
word_t startup_vector = (word_t) startup_func;
|
||||||
reg.x.vector = ((u32_t)startup_vector) >> 12 & 0xff; ;
|
reg.x.vector = ((u32_t)startup_vector) >> 12 & 0xff; ;
|
||||||
reg.x.delivery_mode = startup;
|
reg.x.delivery_mode = startup;
|
||||||
|
@ -364,30 +396,37 @@ INLINE void local_apic_t<base>::send_startup_ipi(u8_t apic_id, void(*startup_fun
|
||||||
reg.x.level = 0;
|
reg.x.level = 0;
|
||||||
reg.x.trigger_mode = 0;
|
reg.x.trigger_mode = 0;
|
||||||
write_reg(APIC_INTR_CMD1, reg.raw);
|
write_reg(APIC_INTR_CMD1, reg.raw);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <word_t base>
|
template <word_t base>
|
||||||
INLINE void local_apic_t<base>::send_init_ipi(u8_t apic_id, bool assert)
|
INLINE void local_apic_t<base>::send_init_ipi(u8_t apic_id, bool assert)
|
||||||
{
|
{
|
||||||
|
|
||||||
// destination
|
// destination
|
||||||
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
||||||
command_reg_t reg;
|
command_reg_t reg;
|
||||||
reg.raw = read_reg(APIC_INTR_CMD1);
|
reg.raw = read_reg(APIC_INTR_CMD1);
|
||||||
|
|
||||||
reg.x.vector = 0;
|
reg.x.vector = 0;
|
||||||
reg.x.delivery_mode = init;
|
reg.x.delivery_mode = init;
|
||||||
reg.x.destination_mode = 0;
|
reg.x.destination_mode = 0;
|
||||||
reg.x.destination = 0;
|
reg.x.destination = 0;
|
||||||
reg.x.level = assert ? 1 : 0;
|
reg.x.level = assert ? 1 : 0;
|
||||||
reg.x.trigger_mode = 1;
|
reg.x.trigger_mode = 1;
|
||||||
write_reg(APIC_INTR_CMD1, reg.raw);
|
write_reg((regno_t) (APIC_INTR_CMD1), reg.raw);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <word_t base>
|
template <word_t base>
|
||||||
INLINE void local_apic_t<base>::send_nmi(u8_t apic_id)
|
INLINE void local_apic_t<base>::send_nmi(u8_t apic_id)
|
||||||
{
|
{
|
||||||
|
command_reg_t reg;
|
||||||
|
reg.raw = read_reg(APIC_INTR_CMD1);
|
||||||
|
ASSERT(reg.x.delivery_status == 0);
|
||||||
|
|
||||||
// destination
|
// destination
|
||||||
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
||||||
command_reg_t reg;
|
|
||||||
reg.raw = read_reg(APIC_INTR_CMD1);
|
reg.raw = read_reg(APIC_INTR_CMD1);
|
||||||
reg.x.vector = 0;
|
reg.x.vector = 0;
|
||||||
reg.x.delivery_mode = nmi;
|
reg.x.delivery_mode = nmi;
|
||||||
|
@ -396,25 +435,34 @@ INLINE void local_apic_t<base>::send_nmi(u8_t apic_id)
|
||||||
reg.x.level = 1;
|
reg.x.level = 1;
|
||||||
reg.x.trigger_mode = 1;
|
reg.x.trigger_mode = 1;
|
||||||
write_reg(APIC_INTR_CMD1, reg.raw);
|
write_reg(APIC_INTR_CMD1, reg.raw);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <word_t base>
|
template <word_t base>
|
||||||
INLINE void local_apic_t<base>::send_ipi(u8_t apic_id, u8_t vector)
|
INLINE void local_apic_t<base>::send_ipi(u8_t apic_id, u8_t vector)
|
||||||
{
|
{
|
||||||
|
command_reg_t reg;
|
||||||
|
reg.raw = read_reg(APIC_INTR_CMD1);
|
||||||
|
ASSERT(reg.x.delivery_status == 0);
|
||||||
|
|
||||||
// destination
|
// destination
|
||||||
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
write_reg(APIC_INTR_CMD2, ((word_t)apic_id) << (56 - 32));
|
||||||
command_reg_t reg;
|
|
||||||
reg.raw = 0;
|
reg.raw = 0;
|
||||||
reg.x.vector = vector;
|
reg.x.vector = vector;
|
||||||
write_reg(APIC_INTR_CMD1, reg.raw);
|
write_reg(APIC_INTR_CMD1, reg.raw);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <word_t base>
|
template <word_t base>
|
||||||
INLINE void local_apic_t<base>::broadcast_ipi(u8_t vector, bool self)
|
INLINE void local_apic_t<base>::broadcast_ipi(u8_t vector, bool self)
|
||||||
{
|
{
|
||||||
command_reg_t reg;
|
command_reg_t reg;
|
||||||
|
reg.raw = read_reg(APIC_INTR_CMD1);
|
||||||
|
ASSERT(reg.x.delivery_status == 0);
|
||||||
|
|
||||||
reg.raw = 0;
|
reg.raw = 0;
|
||||||
|
reg.x.destination_mode = 1;
|
||||||
reg.x.destination = 2 | (self ? 0 : 1);
|
reg.x.destination = 2 | (self ? 0 : 1);
|
||||||
reg.x.vector = vector;
|
reg.x.vector = vector;
|
||||||
write_reg(APIC_INTR_CMD1, reg.raw);
|
write_reg(APIC_INTR_CMD1, reg.raw);
|
||||||
|
@ -425,6 +473,9 @@ template <word_t base>
|
||||||
INLINE void local_apic_t<base>::broadcast_nmi(bool self)
|
INLINE void local_apic_t<base>::broadcast_nmi(bool self)
|
||||||
{
|
{
|
||||||
command_reg_t reg;
|
command_reg_t reg;
|
||||||
|
reg.raw = read_reg(APIC_INTR_CMD1);
|
||||||
|
ASSERT(reg.x.delivery_status == 0);
|
||||||
|
|
||||||
reg.raw = 0;
|
reg.raw = 0;
|
||||||
reg.x.vector = 0;
|
reg.x.vector = 0;
|
||||||
reg.x.delivery_mode = nmi;
|
reg.x.delivery_mode = nmi;
|
||||||
|
@ -432,7 +483,7 @@ INLINE void local_apic_t<base>::broadcast_nmi(bool self)
|
||||||
reg.x.destination = 2 | (self ? 0 : 1);
|
reg.x.destination = 2 | (self ? 0 : 1);
|
||||||
reg.x.level = 1;
|
reg.x.level = 1;
|
||||||
write_reg(APIC_INTR_CMD1, reg.raw);
|
write_reg(APIC_INTR_CMD1, reg.raw);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* !__ARCH__X86__APIC_H__ */
|
#endif /* !__ARCH__X86__APIC_H__ */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002-2005, 2007, Karlsruhe University
|
* Copyright (C) 2002-2005, 2007-2008, Karlsruhe University
|
||||||
*
|
*
|
||||||
* File path: glue/v4-x86/timer-apic.cc
|
* File path: glue/v4-x86/timer-apic.cc
|
||||||
* Description: implementation of apic timer
|
* Description: implementation of apic timer
|
||||||
|
@ -43,11 +43,7 @@ timer_t timer UNIT("cpulocal");
|
||||||
static local_apic_t<APIC_MAPPINGS_START> local_apic;
|
static local_apic_t<APIC_MAPPINGS_START> local_apic;
|
||||||
|
|
||||||
extern "C" void timer_interrupt(void);
|
extern "C" void timer_interrupt(void);
|
||||||
#if defined(CONFIG_IS_64BIT)
|
|
||||||
X86_EXCNO_ERRORCODE(timer_interrupt, 0)
|
X86_EXCNO_ERRORCODE(timer_interrupt, 0)
|
||||||
#else
|
|
||||||
X86_EXCNO_ERRORCODE(timer_interrupt, 0)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
local_apic.EOI();
|
local_apic.EOI();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002-2005, 2007, Karlsruhe University
|
* Copyright (C) 2002-2005, 2007-2008, Karlsruhe University
|
||||||
*
|
*
|
||||||
* File path: glue/v4-x86/x32/config.h
|
* File path: glue/v4-x86/x32/config.h
|
||||||
* Description: configuration of IA32 architecture
|
* Description: configuration of IA32 architecture
|
||||||
|
@ -183,8 +183,9 @@
|
||||||
#define IDT_LAPIC_TIMER 0x40
|
#define IDT_LAPIC_TIMER 0x40
|
||||||
#define IDT_LAPIC_THERMAL 0x41
|
#define IDT_LAPIC_THERMAL 0x41
|
||||||
#define IDT_LAPIC_XCPU_IPI 0x42
|
#define IDT_LAPIC_XCPU_IPI 0x42
|
||||||
|
#define IDT_LAPIC_ERROR 0x43
|
||||||
#define IDT_IOAPIC_SPURIOUS 0xfb
|
#define IDT_IOAPIC_SPURIOUS 0xfb
|
||||||
#define IDT_IOAPIC_BASE 0x40
|
#define IDT_IOAPIC_BASE 0x44
|
||||||
#define IDT_IOAPIC_MAX 0xf0
|
#define IDT_IOAPIC_MAX 0xf0
|
||||||
|
|
||||||
/* Page size for APIC and ACPI mappings */
|
/* Page size for APIC and ACPI mappings */
|
||||||
|
|
|
@ -132,7 +132,7 @@ addr_t acpi_remap(addr_t addr)
|
||||||
get_kernel_space()->add_mapping(
|
get_kernel_space()->add_mapping(
|
||||||
addr_mask (vaddr, ~page_mask (ACPI_PGENTSZ)),
|
addr_mask (vaddr, ~page_mask (ACPI_PGENTSZ)),
|
||||||
addr_mask (paddr, ~page_mask (ACPI_PGENTSZ)),
|
addr_mask (paddr, ~page_mask (ACPI_PGENTSZ)),
|
||||||
ACPI_PGENTSZ, true, true, false);
|
ACPI_PGENTSZ, true, true, false, false);
|
||||||
|
|
||||||
vaddr = addr_offset(vaddr, page_size(ACPI_PGENTSZ));
|
vaddr = addr_offset(vaddr, page_size(ACPI_PGENTSZ));
|
||||||
paddr = addr_offset(paddr, page_size(ACPI_PGENTSZ));
|
paddr = addr_offset(paddr, page_size(ACPI_PGENTSZ));
|
||||||
|
@ -140,7 +140,7 @@ addr_t acpi_remap(addr_t addr)
|
||||||
get_kernel_space()->add_mapping(
|
get_kernel_space()->add_mapping(
|
||||||
addr_mask (vaddr, ~page_mask (ACPI_PGENTSZ)),
|
addr_mask (vaddr, ~page_mask (ACPI_PGENTSZ)),
|
||||||
addr_mask (paddr, ~page_mask (ACPI_PGENTSZ)),
|
addr_mask (paddr, ~page_mask (ACPI_PGENTSZ)),
|
||||||
ACPI_PGENTSZ, true, true, false);
|
ACPI_PGENTSZ, true, true, false, false);
|
||||||
|
|
||||||
x86_mmu_t::flush_tlb();
|
x86_mmu_t::flush_tlb();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002-2007, Karlsruhe University
|
* Copyright (C) 2002-2008, Karlsruhe University
|
||||||
*
|
*
|
||||||
* File path: glue/v4-x86/x64/config.h
|
* File path: glue/v4-x86/x64/config.h
|
||||||
* Description:
|
* Description:
|
||||||
|
@ -257,6 +257,7 @@
|
||||||
#define IDT_LAPIC_TIMER 0x40
|
#define IDT_LAPIC_TIMER 0x40
|
||||||
#define IDT_LAPIC_THERMAL 0x41
|
#define IDT_LAPIC_THERMAL 0x41
|
||||||
#define IDT_LAPIC_XCPU_IPI 0x42
|
#define IDT_LAPIC_XCPU_IPI 0x42
|
||||||
|
#define IDT_LAPIC_ERROR 0x43
|
||||||
#define IDT_IOAPIC_BASE 0x44
|
#define IDT_IOAPIC_BASE 0x44
|
||||||
#define IDT_IOAPIC_MAX 0xf0
|
#define IDT_IOAPIC_MAX 0xf0
|
||||||
#define IDT_IOAPIC_SPURIOUS 0xfb
|
#define IDT_IOAPIC_SPURIOUS 0xfb
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002-2007, Karlsruhe University
|
* Copyright (C) 2002-2008, Karlsruhe University
|
||||||
*
|
*
|
||||||
* File path: platform/generic/intctrl-apic.cc
|
* File path: platform/generic/intctrl-apic.cc
|
||||||
* Description: Implementation of APIC+IOAPIC intctrl (with ACPI)
|
* Description: Implementation of APIC+IOAPIC intctrl (with ACPI)
|
||||||
|
@ -80,6 +80,13 @@ EXC_INTERRUPT(spurious_interrupt_ioapic)
|
||||||
printf("IO-APIC: spurious interrupt\n");
|
printf("IO-APIC: spurious interrupt\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXC_INTERRUPT(lapic_error_interrupt)
|
||||||
|
{
|
||||||
|
printf("APIC: error interrupt, error %x\n",
|
||||||
|
intctrl_t::local_apic.read_error());
|
||||||
|
enter_kdebug("APIC error");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
typedef void(*hwirqfunc_t)();
|
typedef void(*hwirqfunc_t)();
|
||||||
INLINE hwirqfunc_t get_interrupt_entry(word_t irq)
|
INLINE hwirqfunc_t get_interrupt_entry(word_t irq)
|
||||||
|
@ -158,7 +165,7 @@ void intctrl_t::init_arch()
|
||||||
TRACE_INIT("\tAssuming local APIC defaults");
|
TRACE_INIT("\tAssuming local APIC defaults");
|
||||||
get_kernel_space()->add_mapping(addr_t(APIC_MAPPINGS_START),
|
get_kernel_space()->add_mapping(addr_t(APIC_MAPPINGS_START),
|
||||||
addr_t(0xFEE00000),
|
addr_t(0xFEE00000),
|
||||||
APIC_PGENTSZ, true, true, true);
|
APIC_PGENTSZ, true, true, true, false);
|
||||||
|
|
||||||
if (local_apic.version() >= 0x20)
|
if (local_apic.version() >= 0x20)
|
||||||
panic("no local APIC found--system unusable");
|
panic("no local APIC found--system unusable");
|
||||||
|
@ -222,12 +229,13 @@ void intctrl_t::init_arch()
|
||||||
_madt->local_apic_addr, APIC_MAPPINGS_START);
|
_madt->local_apic_addr, APIC_MAPPINGS_START);
|
||||||
get_kernel_space()->add_mapping(addr_t(APIC_MAPPINGS_START),
|
get_kernel_space()->add_mapping(addr_t(APIC_MAPPINGS_START),
|
||||||
addr_t(_madt->local_apic_addr),
|
addr_t(_madt->local_apic_addr),
|
||||||
APIC_PGENTSZ, true, true, true);
|
APIC_PGENTSZ, true, true, true, false);
|
||||||
|
|
||||||
// reserve in KIP
|
// reserve in KIP
|
||||||
get_kip()->memory_info.insert(memdesc_t::reserved, 0, false,
|
get_kip()->memory_info.insert(memdesc_t::reserved, 0, false,
|
||||||
addr_t(APIC_MAPPINGS_START), addr_t(APIC_MAPPINGS_START + X86_PAGE_SIZE));
|
addr_t(APIC_MAPPINGS_START), addr_t(APIC_MAPPINGS_START + X86_PAGE_SIZE));
|
||||||
|
|
||||||
|
x86_mmu_t::flush_tlb();
|
||||||
|
|
||||||
/* local apic */
|
/* local apic */
|
||||||
{
|
{
|
||||||
|
@ -444,6 +452,11 @@ void intctrl_t::init_local_apic()
|
||||||
local_apic.mask(local_apic_t<APIC_MAPPINGS_START>::lvt_thermal_monitor);
|
local_apic.mask(local_apic_t<APIC_MAPPINGS_START>::lvt_thermal_monitor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TRACE_INIT("\tlocal APIC error trap gate %d \n", IDT_LAPIC_ERROR);
|
||||||
|
idt.add_int_gate(IDT_LAPIC_ERROR, lapic_error_interrupt);
|
||||||
|
local_apic.error_setup(IDT_LAPIC_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue