Enable the PIC and add a timer.
This causes a GP fault after the timer runs for some time.
This commit is contained in:
parent
80d2bf1aaa
commit
629dca278b
|
@ -5,6 +5,7 @@ add_executable(zion
|
||||||
debug/debug.cpp
|
debug/debug.cpp
|
||||||
interrupt/interrupt.cpp
|
interrupt/interrupt.cpp
|
||||||
interrupt/interrupt_enter.s
|
interrupt/interrupt_enter.s
|
||||||
|
interrupt/timer.cpp
|
||||||
loader/elf_loader.cpp
|
loader/elf_loader.cpp
|
||||||
loader/init_loader.cpp
|
loader/init_loader.cpp
|
||||||
memory/kernel_heap.cpp
|
memory/kernel_heap.cpp
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "common/port.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
|
|
||||||
#define IDT_INTERRUPT_GATE 0x8E
|
#define IDT_INTERRUPT_GATE 0x8E
|
||||||
|
@ -95,13 +96,37 @@ extern "C" void interrupt_page_fault(InterruptFrame* frame) {
|
||||||
panic("PF");
|
panic("PF");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PIC1_COMMAND 0x20
|
||||||
|
#define PIC1_DATA 0x21
|
||||||
|
#define PIC_EOI 0x20
|
||||||
|
|
||||||
|
uint64_t cnt = 0;
|
||||||
|
extern "C" void isr_timer();
|
||||||
|
extern "C" void interrupt_timer(InterruptFrame*) {
|
||||||
|
cnt++;
|
||||||
|
if (cnt % 1000 == 0) {
|
||||||
|
dbgln("timer: %u", cnt);
|
||||||
|
}
|
||||||
|
outb(PIC1_COMMAND, PIC_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnablePic() {
|
||||||
|
outb(PIC1_COMMAND, 0x11);
|
||||||
|
outb(PIC1_DATA, 0x20); // PIC1 offset.
|
||||||
|
outb(PIC1_DATA, 0x4);
|
||||||
|
outb(PIC1_DATA, 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
void InitIdt() {
|
void InitIdt() {
|
||||||
gIdt[0] = CreateDescriptor(isr_divide_by_zero);
|
gIdt[0] = CreateDescriptor(isr_divide_by_zero);
|
||||||
gIdt[13] = CreateDescriptor(isr_protection_fault);
|
gIdt[13] = CreateDescriptor(isr_protection_fault);
|
||||||
gIdt[14] = CreateDescriptor(isr_page_fault);
|
gIdt[14] = CreateDescriptor(isr_page_fault);
|
||||||
|
gIdt[32] = CreateDescriptor(isr_timer);
|
||||||
InterruptDescriptorTablePointer idtp{
|
InterruptDescriptorTablePointer idtp{
|
||||||
.size = sizeof(gIdt),
|
.size = sizeof(gIdt),
|
||||||
.base = reinterpret_cast<uint64_t>(gIdt),
|
.base = reinterpret_cast<uint64_t>(gIdt),
|
||||||
};
|
};
|
||||||
asm volatile("lidt %0" ::"m"(idtp));
|
asm volatile("lidt %0" ::"m"(idtp));
|
||||||
|
|
||||||
|
EnablePic();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,3 +55,5 @@ isr_\name:
|
||||||
isr_handler divide_by_zero
|
isr_handler divide_by_zero
|
||||||
isr_handler protection_fault,1
|
isr_handler protection_fault,1
|
||||||
isr_handler page_fault,1
|
isr_handler page_fault,1
|
||||||
|
|
||||||
|
isr_handler timer
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include "interrupt/timer.h"
|
||||||
|
|
||||||
|
#include "common/port.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// IO Ports
|
||||||
|
constexpr uint8_t kPit0Ctl = 0x40;
|
||||||
|
constexpr uint8_t kPit1Ctl = 0x41;
|
||||||
|
constexpr uint8_t kPit2Ctl = 0x42;
|
||||||
|
constexpr uint8_t kPitCmd = 0x43;
|
||||||
|
|
||||||
|
// Command Register
|
||||||
|
// Mode
|
||||||
|
constexpr uint8_t kPitMode0 = 0x00;
|
||||||
|
constexpr uint8_t kPitMode1 = 0x02;
|
||||||
|
constexpr uint8_t kPitMode2 = 0x04;
|
||||||
|
constexpr uint8_t kPitMode3 = 0x06;
|
||||||
|
constexpr uint8_t kPitMode4 = 0x08;
|
||||||
|
constexpr uint8_t kPitMode5 = 0x0A;
|
||||||
|
// R/W
|
||||||
|
constexpr uint8_t kCmdLatch = 0x00;
|
||||||
|
constexpr uint8_t kCmdRwLow = 0x10;
|
||||||
|
constexpr uint8_t kCmdRwHi = 0x20;
|
||||||
|
constexpr uint8_t kCmdRwBoth = 0x30;
|
||||||
|
// PIT Select
|
||||||
|
constexpr uint8_t kSelect0 = 0x00;
|
||||||
|
constexpr uint8_t kSelect1 = 0x40;
|
||||||
|
constexpr uint8_t kSelect2 = 0x80;
|
||||||
|
constexpr uint8_t kReadback = 0xC0;
|
||||||
|
|
||||||
|
constexpr uint32_t kPitFrequency = 1193182;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void SetFrequency(uint64_t hertz) {
|
||||||
|
uint16_t reload = kPitFrequency / hertz;
|
||||||
|
outb(kPitCmd, kPitMode3 | kCmdRwBoth | kSelect0);
|
||||||
|
outb(kPit0Ctl, reload & 0xFF);
|
||||||
|
outb(kPit0Ctl, reload >> 8);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void SetFrequency(uint64_t hertz);
|
|
@ -3,6 +3,7 @@
|
||||||
#include "common/gdt.h"
|
#include "common/gdt.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "interrupt/interrupt.h"
|
#include "interrupt/interrupt.h"
|
||||||
|
#include "interrupt/timer.h"
|
||||||
#include "loader/init_loader.h"
|
#include "loader/init_loader.h"
|
||||||
#include "memory/kernel_heap.h"
|
#include "memory/kernel_heap.h"
|
||||||
#include "memory/paging_util.h"
|
#include "memory/paging_util.h"
|
||||||
|
@ -21,6 +22,7 @@ extern "C" void zion() {
|
||||||
|
|
||||||
InitSyscall();
|
InitSyscall();
|
||||||
|
|
||||||
|
SetFrequency(/* hertz= */ 2000);
|
||||||
sched::InitScheduler();
|
sched::InitScheduler();
|
||||||
sched::EnableScheduler();
|
sched::EnableScheduler();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue