apic: init apic timer using pit, not precise on qemu

This commit is contained in:
2025-09-01 23:22:33 +03:00
parent 982f1a5fae
commit a459751453
5 changed files with 75 additions and 1 deletions
+5 -1
View File
@@ -17,4 +17,8 @@ uint32_t ioapic_read(void *ioapicaddr, uint32_t reg);
void ioapic_write(void *ioapicaddr, uint32_t reg, uint32_t value);
void ioapic_redirect(int gsi, int vector);
void enable_symmetric_io_mode();
void enable_symmetric_io_mode();
void init_pit_timer_apic(uint32_t reload_value);
void init_apic_timer();
void mask_pit_interrupt();
+4
View File
@@ -1,6 +1,10 @@
#ifndef ISR_H
#define ISR_H
#include <stdint.h>
extern uint32_t timer_ticks;
void isr0();
void isr1();
void isr2();
+55
View File
@@ -125,4 +125,59 @@ void ioapic_redirect(int gsi, int vector) {
void enable_symmetric_io_mode() {
outb(0x22, 0x70); // Select IMCR
outb(0x23, 0x01); // Set to Symmetric I/O mode (bypass PIC)
}
#include "../include/isr.h"
#define APIC_REGISTER_TIMER_DIV 0x3E0
#define APIC_REGISTER_TIMER_INITCNT 0x380
#define APIC_REGISTER_LVT_TIMER 0x320
#define APIC_LVT_INT_MASKED 0x10000
#define APIC_REGISTER_TIMER_CURRCNT 0x390
#define APIC_LVT_TIMER_MODE_PERIODIC (1 << 17)
void init_pit_timer_apic(uint32_t reload_value) {
int timerFrequency = 1193182 / reload_value;
outb(0x43, 0b00110100);
uint8_t l = (uint8_t)(timerFrequency & 0xFF);
uint8_t h = (uint8_t)(timerFrequency >> 8 & 0xFF);
outb(0x40, l);
outb(0x40, h);
}
void init_apic_timer()
{
lapic_write(APIC_REGISTER_TIMER_DIV, 0x3);
// Prepare the PIT to sleep for 10ms (10000µs)
init_pit_timer_apic(1000);
__asm__ __volatile__ ("sti");
// Set APIC init counter to -1
lapic_write(APIC_REGISTER_TIMER_INITCNT, 0xFFFFFFFF);
uint32_t target_ticks = timer_ticks + 10;//+10ms
while(timer_ticks < target_ticks)
{}
// Stop the APIC timer
lapic_write(APIC_REGISTER_LVT_TIMER, APIC_LVT_INT_MASKED);
// Now we know how often the APIC timer has ticked in 10ms
uint32_t ticksIn10ms = 0xFFFFFFFF - lapic_read(APIC_REGISTER_TIMER_CURRCNT);
// Start timer as periodic on IRQ 0, divider 16, with the number of ticks we counted
lapic_write(APIC_REGISTER_LVT_TIMER, 32 | APIC_LVT_TIMER_MODE_PERIODIC);
lapic_write(APIC_REGISTER_TIMER_DIV, 0x3);
lapic_write(APIC_REGISTER_TIMER_INITCNT, ticksIn10ms);
}
void mask_pit_interrupt() {
// Mask PIT interrupt (GSI 0, IRQ 0)
ioapic_write(ioapic_ptr, REG_TABLE + 2 * 0, INT_DISABLED | T_IRQ0);
ioapic_write(ioapic_ptr, REG_TABLE + 2 * 0 + 1, 0); // Clear destination field
}
+3
View File
@@ -110,8 +110,11 @@ __attribute__((interrupt)) void spurious(struct interrupt_frame *frame)
lapic_eoi();
}
uint32_t timer_ticks = 0;
__attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame)
{
timer_ticks++;
if(lapic_enabled)
{
lapic_eoi();
+8
View File
@@ -73,6 +73,9 @@ void kmain(unsigned int magic, unsigned int info)
printf("IOAPIC init done\n");
ioapic_redirect(2, 32);//timer
ioapic_redirect(1, 33);//keyboard
init_apic_timer();
mask_pit_interrupt();
}
printf("done fucking with pages and memory map!\n");
@@ -132,6 +135,11 @@ void kmain(unsigned int magic, unsigned int info)
while(1)
{
if(timer_ticks % 1000 == 0)
{
//printf("a second should have passed!\n");
}
/* if(inportb(0x64) & 0x1)
{
unsigned char key = inportb(0x60);