Skip to content

Commit

Permalink
Local APIC timer first draft
Browse files Browse the repository at this point in the history
  • Loading branch information
phaubertin committed Jan 19, 2025
1 parent b118e64 commit bd85468
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 2 deletions.
118 changes: 118 additions & 0 deletions include/kernel/infrastructure/i686/drivers/asm/lapic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2025 Philippe Aubertin.
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the author nor the names of other contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_LAPIC_H
#define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_LAPIC_H

#define APIC_REG_ID 0x20

#define APIC_REG_VERSION 0x30

#define APIC_REG_TPR 0x80

#define APIC_REG_APR 0x90

#define APIC_REG_PPR 0xa0

#define APIC_REG_EOI 0xb0

#define APIC_REG_RRD 0xc0

#define APIC_REG_LOGICAL_DEST 0xd0

#define APIC_REG_DEST_FORMAT 0xe0

#define APIC_REG_SPURIOUS_VECT 0xf0

#define APIC_REG_ISR 0x100

#define APIC_REG_TMR 0x180

#define APIC_REG_IRR 0x200

#define APIC_REG_ERROR_STATUS 0x280

#define APIC_REG_LVT_CMCI 0x2f0

#define APIC_REG_LVT_TIMER 0x320

#define APIC_REG_LVT_THERMAL 0x330

#define APIC_REG_LVT_PERF_MON 0x340

#define APIC_REG_LVT_LINT0 0x350

#define APIC_REG_LVT_LINT1 0x360

#define APIC_REG_LVT_ERROR 0x370

#define APIC_REG_INITIAL_COUNT 0x380

#define APIC_REG_CURRENT_COUNT 0x390

#define APIC_REG_DIVIDE_CONF 0x3e0


#define APIC_LVT_DELIVERY_FIXED 0

#define APIC_LVT_DELIVERY_SMI 0x200

#define APIC_LVT_DELIVERY_NMI 0x400

#define APIC_LVT_DELIVERY_INIT 0x600

#define APIC_LVT_DELIVERY_EXTINT 0x700


#define APIC_LVT_PENDING (1 << 12)

#define APIC_LVT_POLARITY_HIGH 0

#define APIC_LVT_POLARITY_LOW (1 << 13)

#define APIC_LVT_TRIGGER_EDGE 0

#define APIC_LVT_TRIGGER_LEVEL (1 << 15)

#define APIC_LVT_MASKED (1 << 16)

#define APIC_LVT_TIMER_ONE_SHOT 0

#define APIC_LVT_TIMER_PERIODIC (1 << 17)

#define APIC_LVT_TIMER_TSC_DEADLINE (2 << 17)


#define APIC_SVR_ENABLED 0

#define APIC_SVR_DISABLED (1 << 8)

#endif
41 changes: 41 additions & 0 deletions include/kernel/infrastructure/i686/drivers/lapic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2025 Philippe Aubertin.
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the author nor the names of other contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_LAPIC_H
#define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_LAPIC_H

#include <kernel/infrastructure/i686/drivers/asm/lapic.h>

void local_apic_init(void);

void local_apic_eoi(void);

#endif
8 changes: 8 additions & 0 deletions include/kernel/interface/i686/asm/idt.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,12 @@

#define IDT_PIC8259_BASE (IDT_LAST_EXCEPTION + 1)

#define IDT_APIC_TIMER 0xfe

/**
* spurious interrupt vector for local APIC
* Bits 3..0 must be 1 for compatibility with Pentium and P6 processors.
*/
#define IDT_APIC_SPURIOUS 0xff

#endif
1 change: 1 addition & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ sources.kernel.c = \
domain/config.c \
infrastructure/acpi/acpi.c \
infrastructure/i686/drivers/acpi.c \
infrastructure/i686/drivers/lapic.c \
infrastructure/i686/drivers/pic8259.c \
infrastructure/i686/drivers/pit8253.c \
infrastructure/i686/drivers/uart16550a.c \
Expand Down
107 changes: 107 additions & 0 deletions kernel/infrastructure/i686/drivers/lapic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (C) 2025 Philippe Aubertin.
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the author nor the names of other contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <jinue/shared/asm/mman.h>
#include <kernel/application/asm/ticks.h>
#include <kernel/domain/services/mman.h>
#include <kernel/infrastructure/i686/drivers/lapic.h>
#include <kernel/infrastructure/i686/cpuinfo.h>
#include <kernel/interface/i686/asm/idt.h>
#include <kernel/types.h>
#include <stdbool.h>

static void *mmio_addr;

static void set_register(int offset, uint32_t value) {
uint32_t *reg = (uint32_t *)((addr_t)mmio_addr + offset);
*reg = value;
}

static void set_divider(int divider) {
uint32_t value;

switch(divider) {
case 128:
value = 0xa;
break;
case 64:
value = 9;
break;
case 32:
value = 8;
break;
case 16:
value = 3;
break;
case 8:
value = 2;
break;
case 4:
value = 1;
break;
case 2:
value = 0;
break;
case 1:
default:
value = 0xb;
}

set_register(APIC_REG_DIVIDE_CONF, value);
}

void local_apic_init(void) {
if(!cpu_has_feature(CPUINFO_FEATURE_LOCAL_APIC)) {
return;
}

// TODO figure out address from firmware table or MSR
// TODO some APICs are controlled through MSRs instead of MMIO?
// TODO ensure caheability attributes are appropriate (MTRRs?)
mmio_addr = map_in_kernel(0xfee00000, 4096, JINUE_PROT_READ | JINUE_PROT_WRITE);

/* TODO get frequency from CPUID and/or MSRs and/or calibrate
*
* This is QEMU's hardcoded frequency */
const uint32_t clock_freq_hz = 1000000000;
const uint32_t initial_count = (clock_freq_hz / TICKS_PER_SECOND) - 1;

/* Configure and start timer. */
set_divider(1);
set_register(APIC_REG_INITIAL_COUNT, initial_count);

set_register(APIC_REG_LVT_TIMER, APIC_LVT_TIMER_PERIODIC | IDT_APIC_TIMER);
set_register(APIC_REG_SPURIOUS_VECT, APIC_SVR_ENABLED | IDT_APIC_SPURIOUS);
}

void local_apic_eoi(void) {
set_register(APIC_REG_EOI, 0);
}
1 change: 0 additions & 1 deletion kernel/infrastructure/i686/drivers/pit8253.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include <kernel/infrastructure/i686/drivers/iodelay.h>
#include <kernel/infrastructure/i686/drivers/pit8253.h>
#include <kernel/infrastructure/i686/isa/io.h>
#include <kernel/infrastructure/i686/isa/io.h>
#include <kernel/utils/utils.h>

void pit8253_init(void) {
Expand Down
9 changes: 8 additions & 1 deletion kernel/infrastructure/i686/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <kernel/domain/services/panic.h>
#include <kernel/infrastructure/i686/asm/msr.h>
#include <kernel/infrastructure/i686/drivers/acpi.h>
#include <kernel/infrastructure/i686/drivers/lapic.h>
#include <kernel/infrastructure/i686/drivers/pic8259.h>
#include <kernel/infrastructure/i686/drivers/pit8253.h>
#include <kernel/infrastructure/i686/drivers/uart16550a.h>
Expand Down Expand Up @@ -380,7 +381,13 @@ void machine_init(const config_t *config) {
* Interrupts are disabled during initialization so the CPU won't actually
* be interrupted until the first user space thread starts. */
pit8253_init();
pic8259_unmask(IRQ_TIMER);

if(!cpu_has_feature(CPUINFO_FEATURE_LOCAL_APIC)) {
pic8259_unmask(IRQ_TIMER);
}

/* Initializa local APIC, including local APIC timer. */
local_apic_init();

/* choose a system call implementation */
select_syscall_implementation();
Expand Down
6 changes: 6 additions & 0 deletions kernel/interface/i686/interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <kernel/application/interrupts.h>
#include <kernel/domain/services/logging.h>
#include <kernel/domain/services/panic.h>
#include <kernel/infrastructure/i686/drivers/lapic.h>
#include <kernel/infrastructure/i686/drivers/pic8259.h>
#include <kernel/infrastructure/i686/isa/regs.h>
#include <kernel/interface/i686/asm/exceptions.h>
Expand Down Expand Up @@ -82,6 +83,11 @@ void handle_interrupt(trapframe_t *trapframe) {

if(ivt <= IDT_LAST_EXCEPTION) {
handle_exception(ivt, trapframe->eip, trapframe->errcode);
} else if(ivt == IDT_APIC_TIMER) {
tick_interrupt();
local_apic_eoi();
} else if(ivt == IDT_APIC_SPURIOUS) {
spurious_interrupt();
} else if(ivt >= IDT_PIC8259_BASE && ivt < IDT_PIC8259_BASE + PIC8259_IRQ_COUNT) {
handle_hardware_interrupt(ivt);
} else {
Expand Down

0 comments on commit bd85468

Please sign in to comment.