Skip to content

Commit

Permalink
Calibrate LAPIC timer and use this timer for handling interrupt inste…
Browse files Browse the repository at this point in the history
…ad of using PIT.
  • Loading branch information
shoily committed Oct 5, 2020
1 parent 8059bd6 commit 4ac3206
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 22 deletions.
31 changes: 31 additions & 0 deletions apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "apic.h"
#include "page32.h"
#include "util.h"
#include "system.h"
#include "setup32.h"

int lapic_present = 0;
int lapic_base_register;
Expand Down Expand Up @@ -41,6 +43,33 @@ void write_lapic_register(int lapic_register, int value) {
*((int*)(lapic_base_register+lapic_register)) = value;
}

extern int lapic_calibration_tick;
extern bool lapic_calibration_mode;
extern bool lapic_timer_enabled;

void lapic_irq_handler_0();

void calibrate_lapic_timer() {

CLI;
write_lapic_register(LAPIC_LVT_TIMER_REG, 32 | 0x20000); // Periodic timer on vector 32.
write_lapic_register(LAPIC_DIVIDE_CONFIGURATION_REG, 0xa); // Divide by 128
set_idt(32, lapic_irq_handler_0);

STI;
lapic_calibration_mode = true;
write_lapic_register(LAPIC_INITIAL_COUNTER_REG, 1024);
pit_wait_ms(1);
write_lapic_register(LAPIC_INITIAL_COUNTER_REG, 0);
lapic_calibration_mode = false;
CLI;
print_msg("lapic_calibration_tick", lapic_calibration_tick, 10, true);

//STI;
lapic_timer_enabled = true;
write_lapic_register(LAPIC_INITIAL_COUNTER_REG, 1024);
}

void init_lapic() {

int eax, edx;
Expand Down Expand Up @@ -79,6 +108,8 @@ void init_lapic() {

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

calibrate_lapic_timer();
}

void lapic_switch(bool enable) {
Expand Down
28 changes: 23 additions & 5 deletions setup32.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,22 @@ __attribute__((regparm(0))) void trap_handler(struct regs_frame *rf) {
__asm__ __volatile__("1: hlt; jmp 1b;" : : : );
}

int lapic_calibration_tick = 0;
bool lapic_calibration_mode = false;
bool lapic_timer_enabled = false;

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

if (rf->code_nr == 0) {

sched_tick++;

if (lapic_calibration_mode) {

lapic_calibration_tick++;

} else if (lapic_timer_enabled) {
}
}
}

Expand Down Expand Up @@ -230,18 +241,25 @@ void setupIDT32() {
);
}

void set_idt(int vector, idt_function_type idt_function) {

SET_INTERRUPT_GATE(idt, vector, idt_function);
}

void setup32() {

setupGDT32();
setupLDT32();
setupIDT32();
setupTSS32();

mask_pic_8259();
init_lapic();

init_pic_8259();
init_pit_frequency();

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

smp_start();

Expand Down
3 changes: 3 additions & 0 deletions setup32.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ struct regs_frame {
unsigned int ss;
}__attribute__((packed));

typedef void (*idt_function_type)();

void setup32();
void set_idt(int vector, idt_function_type idt_function);

#endif
18 changes: 2 additions & 16 deletions smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ void copy_smp_init_to_low_mem() {

void smp_start() {

int status;

copy_smp_init_to_low_mem();

// initialize AP processor count with 0
Expand All @@ -44,24 +42,12 @@ void smp_start() {
// send INIT IPI to APs
write_lapic_register(LAPIC_ICR_1, 0x000c4500);
write_lapic_register(LAPIC_ICR_2, 0);
for(int i=0;i<10;i++) {
status = read_lapic_register(LAPIC_ICR_1) & 0x1000;
if (!status)
break;
pit_wait(0xffff);
}
pit_wait_ms(10);

// send Startup IPI to APs
write_lapic_register(LAPIC_ICR_1, 0x000c4600 | (AP_INIT_PHYS_TEXT >> 12));
write_lapic_register(LAPIC_ICR_2, 0);
for(int i=0;i<30;i++) {
status = read_lapic_register(LAPIC_ICR_1) & 0x1000;
if (!status)
break;
pit_wait(0xffff);
}

pit_wait(0xffff);
pit_wait_ms(200);

print_msg("Number of APs", *(int*)(AP_COUNT_PHYS_ADDR+KERNEL_VIRT_ADDR), 10, true);
}
39 changes: 38 additions & 1 deletion system.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,25 @@ void print_vga(char *c, bool newline) {
}
}

void print_vga_fixed(char *c, int col, int row) {

unsigned short *p = (unsigned short *)((char*)VIDEO_BUFFER+col+(row*160));

while(*c) {

if (row > 25) break;

*p = ((0xF << 8) | *c);
c++;
col += 2;
p++;
if (col == 160) {
row++;
col = 0;
}
}
}

//
// Dumps E820 map
//
Expand Down Expand Up @@ -80,6 +99,16 @@ void dump_e820() {
}
}

void mask_pic_8259() {

__asm__ __volatile__("movb $0xff, %%al;" // mask master and slave PICs
"outb %%al, $0x21;"
"outb %%al, $0xa1;"
:
:
: );
}

void init_pic_8259() {

__asm__ __volatile__("movb $0xff, %%al;" // mask master and slave PICs
Expand Down Expand Up @@ -151,7 +180,7 @@ void pit_wait(int cycles) {
"outb %%al, $0x43;" // writing to command register
"inb $0x42, %%al;" // read status from channel 2
"movb %%al, %b1;"
"andb $0x80, %%al;" // check if GATE is high
"andb $0x80, %%al;" // check if OUT is high
"sti;"
"jnz 1f;"
"nop;nop;nop;nop;" // give chance to PIC to handle interrupts
Expand All @@ -170,3 +199,11 @@ void pit_wait(int cycles) {
STI;
#endif
}

void pit_wait_ms(int ms) {

for(int i = 0; i < ms; i++) {

pit_wait(PIT_HZ);
}
}
6 changes: 6 additions & 0 deletions system.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#define E820_MAP_ADDRESS (KERNEL_VIRT_ADDR+0x1008)
#define E820_MAP_COUNT (KERNEL_VIRT_ADDR+0x1004)

#define PIT_CRYSTAL_FREQUENCY 1193182
#define PIT_HZ (PIT_CRYSTAL_FREQUENCY/1000)

#define MFENCE __asm__ __volatile__("mfence;" \
: \
: \
Expand Down Expand Up @@ -48,8 +51,11 @@ struct e820_map {

void dump_e820();
void print_vga(char *c, bool newline);
void mask_pic_8259();
void init_pic_8259();
void init_pit_frequency();
void pit_wait(int cycles);
void pit_wait_ms(int ms);
void print_vga_fixed(char *c, int col, int row);

#endif

0 comments on commit 4ac3206

Please sign in to comment.