Skip to content

Commit

Permalink
Adding Local APIC handling code to support multiprocessor, irq handle…
Browse files Browse the repository at this point in the history
…r for Local APIC, enabling interrupts in ISR code so that high priority IRQ can be served while low priority interrupts are being served, added tick count, fixed VGA buffer overflow, added wait function using PIT channel 2, fixed itoa routine handling MSB, added print_msg routine.
  • Loading branch information
shoily committed Aug 8, 2020
1 parent 43ef756 commit 0933463
Show file tree
Hide file tree
Showing 9 changed files with 327 additions and 89 deletions.
97 changes: 97 additions & 0 deletions apic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*****************************************************************************/
/* File: apic.c */
/* */
/* Description: Source file for IOAPIC and Local APIC code. */
/* */
/* Author: Shoily O Rahman <[email protected]> */
/* */
/* Date: Aug 2, 2020 */
/* */
/*****************************************************************************/

#include "apic.h"
#include "page32.h"
#include "util.h"

int lapic_present = 0;
int lapic_base_register;
int lapic_id;

#define ADD2PTR(x, y) ((int)(x) + (int)(y))

extern int _kernel_pg_dir;

char __attribute__((aligned(4096))) lapic_pg_table[4096];

void read_msr(int msr, int *eax, int *edx) {

__asm__ __volatile__("rdmsr;"
: "=a" (*eax), "=d" (*edx)
: "c" (msr)
: );
}

int read_lapic_register(int lapic_register) {

return *((int*)(lapic_base_register+lapic_register));
}

void write_lapic_register(int lapic_register, int value) {

*((int*)(lapic_base_register+lapic_register)) = value;
}

void init_lapic() {

int eax, edx;
pte_t *pgtable[1];

__asm__ __volatile__("movl $1, %%eax;"
"cpuid;"
"andl $0x200, %%edx;"
"shrl $9, %%edx;"
"movl %%edx, %0;"
: "=r" (lapic_present)
:
: "%eax", "%edx"
);

print_msg("Local APIC present", lapic_present, 10, true);

if (!lapic_present) {

return;
}

memset(lapic_pg_table, sizeof(lapic_pg_table), 0);
pgtable[0] = (pte_t*)lapic_pg_table;

read_msr(0x1b, &eax, &edx);
lapic_base_register = eax & 0xfffff000;

build_pagetable((pgd_t*)&_kernel_pg_dir, pgtable, lapic_base_register, lapic_base_register, PAGE_SIZE, PGD_PRESENT | PGD_WRITE, PTE_PRESENT | PTE_WRITE);

print_msg("Local APIC address", eax, 16, false);

lapic_id = read_lapic_register(LAPIC_ID_REG) >> 24;

print_msg("Local APIC id", lapic_id, 16, true);

// enable receiving interrupt
//write_lapic_register(LAPIC_SPURIOUS_REG, read_lapic_register(LAPIC_SPURIOUS_REG)| 0x100);
}

void lapic_switch(bool enable) {

int value;

value = read_lapic_register(LAPIC_SPURIOUS_REG);
if (enable)
value |= 0x1ff;
else
value &= ~0x1ff;

print_msg("lapic_switch", value, 16, true);

write_lapic_register(LAPIC_SPURIOUS_REG, value);
}
41 changes: 41 additions & 0 deletions apic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*****************************************************************************/
/* File: apic.c */
/* */
/* Description: Source file for IOAPIC and Local APIC code. */
/* */
/* Author: Shoily O Rahman <[email protected]> */
/* */
/* Date: Aug 2, 2020 */
/* */
/*****************************************************************************/

#ifndef APIC_H
#define APIC_H

#include "type.h"

#define LAPIC_ID_REG 0x20
#define LAPIC_VERSION_REG 0x30
#define LAPIC_TPR 0x80
#define LAPIC_APR 0x90
#define LAPIC_PPR 0xa0
#define LAPIC_EOI_REG 0xb0
#define LAPIC_SPURIOUS_REG 0xf0
#define ISR_0_31 0x100
#define TMR_0_31 0x180
#define IRR_0_31 0x200
#define ERROR_STATUS_REG 0x280
#define ICR_1 0x300
#define ICR_2 0x310
#define LVT_TIMER_REG 0x320
#define LVT_LINT_0_REG 0x350
#define LVT_LINT_1_REG 0x360
#define LVT_ERROR_REG 0x370
#define INITIAL_COUNTER_REG 0x380
#define CURRENT_COUNTER_REG 0x390
#define DIVIDE_CONFIGURATION_REG 0x3e0

void init_lapic();
void lapic_switch(bool enable);

#endif
63 changes: 55 additions & 8 deletions handlr32.S
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@
.globl irq_handler_14
.globl irq_handler_15

.globl lapic_irq_handler_0
.globl lapic_irq_handler_1

// macro for defining IRQ handler

// macro for defining IRQ handler using PIC
.macro DEFINE_IRQ_HANDLER irqn

irq_handler_\irqn:
Expand All @@ -54,21 +57,20 @@
movl %eax, %fs
movl %eax, %gs

sti

push %ebp
call common_interrupt_handler
addl $4, %esp

movb $0x20,%al

movb $\irqn, %ah
cmpb $8, %ah
jl 1f

outb %al,$0xa0
1:

outb %al,$0x20

push %ebp
call common_interrupt_handler
addl $4, %esp

pop %gs
pop %fs
pop %es
Expand Down Expand Up @@ -171,3 +173,48 @@ common_trap_handler:
popa

iret


// macro for defining IRQ handler using Local APIC
.macro DEFINE_IRQ_HANDLER_LAPIC irqn

lapic_irq_handler_\irqn:
pushl $\irqn
pusha
push %ds
push %es
push %fs
push %gs

movl %esp, %ebp

movl $0x28, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs

push %ebp
call common_interrupt_handler
addl $4, %esp

// send EOI
movl lapic_base_register, %eax
addl $0xb0, %eax
movl $0, (%eax)

pop %gs
pop %fs
pop %es
pop %ds
popa

addl $4, %esp

iret

.endm


DEFINE_IRQ_HANDLER_LAPIC 0
DEFINE_IRQ_HANDLER_LAPIC 1
66 changes: 38 additions & 28 deletions setup32.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
#include "util.h"
#include "system.h"
#include "setup32.h"

#define UNUSED(x) (void)(x)
#include "apic.h"

// GDT data
struct gdt_entry __attribute__((aligned(8))) gdt[LAST_SEG/8];
Expand Down Expand Up @@ -42,9 +41,13 @@ struct _idt_desc __attribute__((aligned(8))) idt_desc;
// TSS data
struct tss_entry __attribute__((aligned(4096))) tss;

int sched_tick = 0;

extern int _kernel_stack_0_start;
extern int _kernel_pg_dir;

extern int lapic_present;

void common_trap_handler();
void sys_call_handler_128();

Expand All @@ -65,6 +68,9 @@ void irq_handler_13();
void irq_handler_14();
void irq_handler_15();

void lapic_irq_handler_1();


__attribute__((regparm(0))) void trap_handler(struct regs_frame *rf) {

char str[20];
Expand Down Expand Up @@ -103,17 +109,15 @@ __attribute__((regparm(0))) void trap_handler(struct regs_frame *rf) {

__attribute__((regparm(0))) void common_interrupt_handler(struct regs_frame *rf) {

UNUSED(rf);
if (rf->code_nr == 0) {

sched_tick++;
}
}

__attribute__((regparm(0))) void common_sys_call_handler(struct regs_frame *rf) {

char str[20];
print_vga("System call: ", false);
itoa(rf->code_nr, str, 16);
print_vga(str, true);

UNUSED(rf);
print_msg("System call", rf->code_nr, 16, true);
}

// Initializes LDT for user code and data segment selectors
Expand Down Expand Up @@ -199,21 +203,6 @@ void setupIDT32() {
idt_desc.size = sizeof(idt) - 1;
idt_desc.idt = idt;

SET_TRAP_GATE(idt, 0, common_trap_handler);
SET_TRAP_GATE(idt, 1, common_trap_handler);
SET_TRAP_GATE(idt, 2, common_trap_handler);
SET_TRAP_GATE(idt, 4, common_trap_handler);
SET_TRAP_GATE(idt, 5, common_trap_handler);
SET_TRAP_GATE(idt, 6, common_trap_handler);
SET_TRAP_GATE(idt, 7, common_trap_handler);
SET_TRAP_GATE(idt, 8, common_trap_handler);
SET_TRAP_GATE(idt, 9, common_trap_handler);
SET_TRAP_GATE(idt, 10, common_trap_handler);
SET_TRAP_GATE(idt, 11, common_trap_handler);
SET_TRAP_GATE(idt, 12, common_trap_handler);
SET_TRAP_GATE(idt, 13, common_trap_handler);
SET_TRAP_GATE(idt, 14, common_trap_handler);

SET_INTERRUPT_GATE(idt, 32, irq_handler_0);
SET_INTERRUPT_GATE(idt, 33, irq_handler_1);
SET_INTERRUPT_GATE(idt, 34, irq_handler_2);
Expand All @@ -231,14 +220,28 @@ void setupIDT32() {
SET_INTERRUPT_GATE(idt, 46, irq_handler_14);
SET_INTERRUPT_GATE(idt, 47, irq_handler_15);

SET_TRAP_GATE(idt, 0, common_trap_handler);
SET_TRAP_GATE(idt, 1, common_trap_handler);
SET_TRAP_GATE(idt, 2, common_trap_handler);
SET_TRAP_GATE(idt, 4, common_trap_handler);
SET_TRAP_GATE(idt, 5, common_trap_handler);
SET_TRAP_GATE(idt, 6, common_trap_handler);
SET_TRAP_GATE(idt, 7, common_trap_handler);
SET_TRAP_GATE(idt, 8, common_trap_handler);
SET_TRAP_GATE(idt, 9, common_trap_handler);
SET_TRAP_GATE(idt, 10, common_trap_handler);
SET_TRAP_GATE(idt, 11, common_trap_handler);
SET_TRAP_GATE(idt, 12, common_trap_handler);
SET_TRAP_GATE(idt, 13, common_trap_handler);
SET_TRAP_GATE(idt, 14, common_trap_handler);

SET_TRAP_GATE(idt, 128, sys_call_handler_128);

MFENCE;

// Initialize IDT
__asm__ __volatile__("movl $%0, %%eax;"
"lidt (%%eax);"
"sti;"
:
: "m" (idt_desc)
: "%eax"
Expand All @@ -247,13 +250,20 @@ void setupIDT32() {

void setup32() {

init_pic_8259();
init_pit_frequency();

setupGDT32();
setupLDT32();

if (!lapic_present) {
init_pic_8259();
init_pit_frequency();
}

init_lapic();

setupIDT32();
setupTSS32();

STI;

print_vga("Setup GDT,IDT, LDT and TSS done", true);
}
Loading

0 comments on commit 0933463

Please sign in to comment.