Skip to content

Commit

Permalink
hal/ia32: Add support for Local APIC timer
Browse files Browse the repository at this point in the history
- Move code reading and writing to Local APIC to its own functions.
- Add detection of Local APIC Timer's frequency.
- Make Local APIC timer the default timer for scheduling

JIRA: RTOS-530
  • Loading branch information
astalke committed Nov 8, 2023
1 parent 7b8d68b commit 086a5b9
Show file tree
Hide file tree
Showing 6 changed files with 274 additions and 54 deletions.
2 changes: 2 additions & 0 deletions hal/ia32/arch/interrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#define IOAPIC_INTPOL (1u << 13)
#define IOAPIC_DESTMOD (1u << 11)

#define LAPIC_EOI 0

/* Interrupt source override polarity flags */
#define MADT_ISO_POLAR_MASK 0x3
#define MADT_ISO_POLAR_BUS 0x0
Expand Down
26 changes: 12 additions & 14 deletions hal/ia32/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "tlb.h"
#include "init.h"

extern void hal_timerInitCore(const unsigned int id);

struct cpu_feature_t {
const char *name;
s32 eax;
Expand Down Expand Up @@ -302,7 +304,7 @@ unsigned int hal_cpuGetCount(void)
static inline unsigned int _hal_cpuGetID(void)
{
if (hal_isLapicPresent() == 1) {
return (*(volatile u32 *)(hal_config.localApicAddr + LAPIC_ID_REG)) >> 24;
return _hal_lapicRead(LAPIC_ID_REG) >> 24;
}
else {
return 0;
Expand All @@ -326,26 +328,22 @@ unsigned int hal_cpuGetID(void)
/* Sends IPI to everyone but self */
void cpu_broadcastIPI(unsigned int intr)
{
volatile u32 *p;
if (hal_isLapicPresent() == 1) {
p = hal_config.localApicAddr + LAPIC_ICR_REG_0_31;
*p = intr | 0xc4000;
while (*p & (1 << 12)) {
_hal_lapicWrite(LAPIC_ICR_REG_0_31, intr | 0xc4000);
while ((_hal_lapicRead(LAPIC_ICR_REG_0_31) & (1 << 12)) != 0) {
}
}
}


void hal_cpuSendIPI(unsigned int cpu, unsigned int intrAndFlags)
{
volatile u32 *p, *q;
if (hal_isLapicPresent() == 1) {
p = hal_config.localApicAddr + LAPIC_ICR_REG_0_31;
q = hal_config.localApicAddr + LAPIC_ICR_REG_32_63;
/* Set destination */
*q = (cpu & 0xff) << 24;
*p = intrAndFlags & 0xcdfff;
while (*p & (1 << 12)) {
/* TODO: Disable interrupts while we're writing */
_hal_lapicWrite(LAPIC_ICR_REG_32_63, (cpu & 0xff) << 24);
_hal_lapicWrite(LAPIC_ICR_REG_0_31, intrAndFlags & 0xcdfff);
while ((_hal_lapicRead(LAPIC_ICR_REG_0_31) & (1 << 12)) != 0) {
}
}
}
Expand Down Expand Up @@ -377,13 +375,11 @@ static void _cpu_gdtInsert(unsigned int idx, u32 base, u32 limit, u32 type)

void *_cpu_initCore(void)
{
volatile u32 *p;
const unsigned int id = hal_cpuGetID();
hal_cpuAtomAdd(&cpu.readyCount, 1);

if (hal_isLapicPresent() == 1) {
p = hal_config.localApicAddr + LAPIC_SPUR_IRQ_REG;
*p = (*p | 0x11ffu);
_hal_lapicWrite(LAPIC_SPUR_IRQ_REG, _hal_lapicRead(LAPIC_SPUR_IRQ_REG) | 0x11ffu);
}

hal_memset(&cpu.tss[id], 0, sizeof(tss_t));
Expand Down Expand Up @@ -420,6 +416,7 @@ void *_cpu_initCore(void)
/* clang-format on */

hal_tlbInitCore(id);
hal_timerInitCore(id);

return (void *)cpu.tss[id].esp0;
}
Expand All @@ -433,6 +430,7 @@ static void _hal_cpuInitCores(void)

/* Initialize BSP */
cpu.readyCount = 0;
_hal_timerInit(SYSTICK_INTERVAL);
_cpu_initCore();

*(u32 *)(syspage->hs.stack + VADDR_KERNEL - 4) = 0;
Expand Down
1 change: 0 additions & 1 deletion hal/ia32/hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ void _hal_init(void)
_hal_interruptsInit();

_hal_cpuInit();
_hal_timerInit(SYSTICK_INTERVAL);
_hal_pciInit();

hal_common.started = 0;
Expand Down
12 changes: 12 additions & 0 deletions hal/ia32/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ static inline int hal_isLapicPresent(void)
}


static inline void _hal_lapicWrite(u32 reg, u32 value)
{
*(volatile u32 *)(hal_config.localApicAddr + reg) = value;
}


static inline u32 _hal_lapicRead(u32 reg)
{
return *(volatile u32 *)(hal_config.localApicAddr + reg);
}


void _hal_configInit(syspage_t *s);


Expand Down
8 changes: 3 additions & 5 deletions hal/ia32/interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,13 @@ static inline void _hal_ioapicRoundRobin(unsigned int n)

static inline void _hal_interrupts_8259EOI(unsigned int n)
{
volatile u32 *p = hal_config.localApicAddr + LAPIC_EOI_REG;
if ((hal_isLapicPresent() != 0) && (n == TLB_IRQ)) {
*p = 0;
_hal_lapicWrite(LAPIC_EOI_REG, LAPIC_EOI);
return;
}
/* Check for rare case, when we use 8259 PIC with multiple cores and APIC */
if (hal_cpuGetID() != 0) {
*p = 0;
_hal_lapicWrite(LAPIC_EOI_REG, LAPIC_EOI);
return;
}
if (n < 8) {
Expand All @@ -185,9 +184,8 @@ static inline void _hal_interrupts_8259EOI(unsigned int n)

static inline void _hal_interruptsApicEOI(unsigned int n)
{
volatile u32 *p = hal_config.localApicAddr + LAPIC_EOI_REG;
_hal_ioapicRoundRobin(n);
*p = 0;
_hal_lapicWrite(LAPIC_EOI_REG, LAPIC_EOI);
}


Expand Down
Loading

0 comments on commit 086a5b9

Please sign in to comment.