summaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/PrimaryInit.cpp264
-rw-r--r--arch/x86/idt/Idt.cpp46
-rw-r--r--arch/x86/idt/Idt.h10
-rw-r--r--arch/x86/io/VGADisplay.cpp9
-rw-r--r--arch/x86/io/VGADisplay.h2
-rw-r--r--arch/x86/msr/Msr.cpp106
-rw-r--r--arch/x86/msr/Msr.h58
7 files changed, 483 insertions, 12 deletions
diff --git a/arch/x86/PrimaryInit.cpp b/arch/x86/PrimaryInit.cpp
index 5359978..498a22b 100644
--- a/arch/x86/PrimaryInit.cpp
+++ b/arch/x86/PrimaryInit.cpp
@@ -1,13 +1,170 @@
#include "PrimaryInit.h"
#include "idt/Idt.h"
+#include "io/VGADisplay.h"
-// Function to test idt work. Should remove
-void isr()
+struct InterruptFrame
{
- out::display << "The kernel has finished" << '\n';
+#ifdef X86_64
+ const uint64 ip;
+ const uint64 cs;
+ const uint64 flags;
+#else
+ const uint32 ip;
+ const uint32 cs;
+ const uint32 flags;
+#endif
};
+// Test ISRs define start
+__attribute__((interrupt)) void isr0(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Divide error" << '\n';
+};
+
+__attribute__((interrupt)) void isr1(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Debug exception" << '\n';
+};
+
+__attribute__((interrupt)) void isr2(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "NMI interrupt" << '\n';
+};
+
+__attribute__((interrupt)) void isr3(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Breakpoint" << '\n';
+};
+
+__attribute__((interrupt)) void isr4(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Overflow" << '\n';
+};
+
+__attribute__((interrupt)) void isr5(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Bound range exceed" << '\n';
+};
+
+__attribute__((interrupt)) void isr6(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Invalid opcode" << '\n';
+};
+
+__attribute__((interrupt)) void isr7(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "No math coprocessor" << '\n';
+};
+
+__attribute__((interrupt)) void isr8(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "Double fault" << '\n';
+};
+
+__attribute__((interrupt)) void isr10(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "Invalid TSS" << "\n";
+};
+
+__attribute__((interrupt)) void isr11(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "Segment not present" << "\n";
+};
+
+__attribute__((interrupt)) void isr12(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "Stack segment fault" << "\n";
+};
+
+__attribute__((interrupt)) void isr13(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "#GP" << "\n";
+};
+
+__attribute__((interrupt)) void isr14(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "Page fault" << "\n";
+};
+
+__attribute__((interrupt)) void isr16(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Math fault" << "\n";
+};
+
+__attribute__((interrupt)) void isr17(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "Alignment check" << "\n";
+};
+
+__attribute__((interrupt)) void isr18(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Machine check" << "\n";
+};
+
+__attribute__((interrupt)) void isr19(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "SIMD point exception" << "\n";
+};
+
+__attribute__((interrupt)) void isr20(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Virtualization exception" << "\n";
+};
+
+__attribute__((interrupt)) void isr21(struct InterruptFrame *frame, uword errorCode)
+{
+ asm("cli\n\t");
+ out::display << "Control protection exception" << "\n";
+};
+
+__attribute__((interrupt)) void isrUser(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "User-defined interrupt" << "\n";
+};
+
+__attribute__((interrupt)) void isrKeyboard(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "KINT ";
+ uint8 buff[2];
+
+ // PIC write EOI
+ asm("in $0x60, %al");
+ asm("mov %%al, %0" : "=r"(buff[0]));
+ asm("in $0x64, %al");
+ asm("mov %%al, %0" : "=r"(buff[1]));
+ asm("mov $0x20, %al\n\t");
+ asm("outb %al, $0x20\n\t");
+ out::display << (uint32)buff[0] << ' ' << (uint32)buff[1] << '\n';
+};
+__attribute__((interrupt)) void isrTimer(struct InterruptFrame *frame)
+{
+ asm("cli\n\t");
+ out::display << "Timer interrupt" << "\n";
+};
+//Test ISRs define end -------------------
+
void PrimaryInitialization::processorInitialize()
{
MngIdt &mngIdt = MngIdt::getInstance();
@@ -17,12 +174,103 @@ void PrimaryInitialization::processorInitialize()
mngGdt.addDescriptor(DescSeg32::flatDataKernel());
mngGdt.loadGdt();
- mngIdt.setDescriptor(
- DescInterrupt32::InterruptKernelLong(
- (uint32)isr,
- mngGdt.getCodeSegmentKernel()),
- 0x20);
+// Filling IDT start !!!REWRITE!!
+ DescInterrupt32 descInt = DescInterrupt32::TrapKernelLong
+ (
+ (uint32)isr0,
+ mngGdt.getCodeSegmentKernel()
+ );
+ // Int 0
+ mngIdt.addDescriptor(descInt);
+
+ // Int 1
+ descInt.setOffset((uint32)isr1);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 2
+ descInt.setOffset((uint32)isr2);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 3
+ descInt.setOffset((uint32)isr3);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 4
+ descInt.setOffset((uint32)isr4);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 5
+ descInt.setOffset((uint32)isr5);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 6
+ descInt.setOffset((uint32)isr6);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 7
+ descInt.setOffset((uint32)isr7);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 8
+ descInt.setOffset((uint32)isr8);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 10
+ descInt.setOffset((uint32)isr10);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 11
+ descInt.setOffset((uint32)isr11);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 12
+ descInt.setOffset((uint32)isr12);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 13
+ descInt.setOffset((uint32)isr13);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 14
+ descInt.setOffset((uint32)isr14);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 16
+ descInt.setOffset((uint32)isr16);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 17
+ descInt.setOffset((uint32)isr17);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 18
+ descInt.setOffset((uint32)isr18);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 19
+ descInt.setOffset((uint32)isr19);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 20
+ descInt.setOffset((uint32)isr20);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 21
+ descInt.setOffset((uint32)isr21);
+ mngIdt.addDescriptor(descInt);
+
+ // Int 32
+ descInt.setOffset((uint32)isrTimer);
+ mngIdt.setDescriptor(descInt, 32);
+
+ // Int 33
+ descInt.setOffset((uint32)isrKeyboard);
+ mngIdt.setDescriptor(descInt, 33);
+//Filling IDT end ------------------------------
+
mngIdt.loadIdt();
+
+//------------
};
void PrimaryInitialization::devicesInitialize()
diff --git a/arch/x86/idt/Idt.cpp b/arch/x86/idt/Idt.cpp
index d489f0e..cd263fb 100644
--- a/arch/x86/idt/Idt.cpp
+++ b/arch/x86/idt/Idt.cpp
@@ -69,6 +69,15 @@ DescInterrupt32 DescInterrupt32::TaskKernel(uint16 selector)
);
};
+bool MngIdt::isIntReserved(uint8 interrupt)
+{
+ for(uint8 indx = 0; indx < reservedIntSize; indx++)
+ {
+ if(reservedInts[indx] == interrupt) return true;
+ }
+ return false;
+};
+
MngIdt::MngIdt()
{
if(!isInitialize)
@@ -88,9 +97,10 @@ bool MngIdt::canDescriptorWrite(uint8 idx)
bool MngIdt::addDescriptor(DescInterrupt32 desc)
{
- if(!canDescriptorWrite(currIdx)) return false;
+ if(!canDescriptorWrite(currIdx) or isIntReserved(currIdx)) return false;
- idt[currIdx++] = desc.getDescriptor();
+ idt[currIdx] = desc.getDescriptor();
+ while(isIntReserved(++currIdx));
return true;
};
@@ -108,7 +118,7 @@ bool MngIdt::loadIdt()
//Set descriptor
uint64 descriptor = 0;
- uint16 size = sizeof(uint64) * size - 1;
+ uint16 size = sizeof(uint64) * this->size - 1;
uint32 offset = (uint32)(&idt);
descriptor |= offset;
@@ -128,3 +138,33 @@ MngIdt &MngIdt::getInstance()
if(!isInitialize) mngIdt = MngIdt();
return mngIdt;
};
+
+void DescInterrupt32::setOffset(uint32 offset)
+{
+ uint8 gateType = attributes & 0x0f;
+
+ if(!(gateType == TSK_GATE and offset != 0))
+ {
+ offsetLow = offset & 0xffff;
+ offsetHight = (offset & 0xffff0000) >> 16;
+ }
+};
+void DescInterrupt32::setGateType(uint8 gateType)
+{
+ if(gateType < TSK_GATE
+ or (gateType > TRAP_GATE_16 and gateType < INT_GATE_32)
+ or gateType > TRAP_GATE_32
+ ) return;
+ else if(gateType == TSK_GATE)
+ {
+ offsetLow = offsetHight = 0;
+ }
+
+ attributes &= 0xfff0;
+ attributes |= (gateType & 0x0f);
+};
+
+void DescInterrupt32::setDpl(uint8 dpl)
+{
+ attributes = (dpl & 0x03) << 5;
+};
diff --git a/arch/x86/idt/Idt.h b/arch/x86/idt/Idt.h
index c90b674..7370526 100644
--- a/arch/x86/idt/Idt.h
+++ b/arch/x86/idt/Idt.h
@@ -32,6 +32,9 @@ class DescInterrupt32
DescInterrupt32() = default;
DescInterrupt32(const DescInterrupt32 &) = default;
DescInterrupt32(uint32 offset, uint16 selector, uint8 attr);
+ void setOffset(uint32 offset);
+ void setGateType(uint8 gateType);
+ void setDpl(uint8 dpl);
uint64 getDescriptor();
static DescInterrupt32 InterruptKernelLong(uint32 offset,
uint16 selector);
@@ -43,6 +46,13 @@ class DescInterrupt32
class MngIdt
{
private:
+ const static uint8 reservedIntSize = 12;
+ constexpr static uint8 reservedInts[reservedIntSize] =
+ {
+ 9, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+ };
+ // If false interrupt number isn't reserved, true - reserved
+ bool isIntReserved(uint8 interrupt);
const static uint8 size = 255;
static uint64 idt[size];
static bool isInitialize;
diff --git a/arch/x86/io/VGADisplay.cpp b/arch/x86/io/VGADisplay.cpp
index ceb4862..7246102 100644
--- a/arch/x86/io/VGADisplay.cpp
+++ b/arch/x86/io/VGADisplay.cpp
@@ -137,3 +137,12 @@ bool VGADisplay::printChar(const char &c)
}
}
};
+
+void VGADisplay::clearScreen()
+{
+ xCurr = yCurr = 0;
+ videoMem = (dchar *)VGADisplayInfo::videoMemAddr;
+ uint16 maxPos = VGADisplayInfo::height * VGADisplayInfo::width * 2;
+
+ for(uint16 pos = 0; pos < maxPos; pos++) *this << ' ';
+};
diff --git a/arch/x86/io/VGADisplay.h b/arch/x86/io/VGADisplay.h
index 326ae95..562b1ae 100644
--- a/arch/x86/io/VGADisplay.h
+++ b/arch/x86/io/VGADisplay.h
@@ -35,10 +35,10 @@ class VGADisplay
void setColor(char colorAttr);
void setBlink(bool blinkAttr);
void setBright(bool brigthAttr);
+ void clearScreen();
};
// Global variables
-
namespace out
{
extern VGADisplay display;
diff --git a/arch/x86/msr/Msr.cpp b/arch/x86/msr/Msr.cpp
new file mode 100644
index 0000000..6d21b54
--- /dev/null
+++ b/arch/x86/msr/Msr.cpp
@@ -0,0 +1,106 @@
+#include "Msr.h"
+
+Msr::Msr()
+{
+ Cpuinfo cpuinfo;
+ cpuinfo.cpuid(Cpuinfo::VersionInfo);
+
+ msrSupport = cpuinfo.getRegs().edx & Cpuinfo::MSR;
+};
+
+bool Msr::rdmsr(MsrCommand *cmd)
+{
+ if(!msrSupport or cmd == nullptr) return true;
+
+ uint64 rdmsrResult = 0;
+ uint32 regs[2];
+ asm(
+ "mov %2, %%ecx\n\t"
+ "rdmsr\n\t"
+ "mov %%eax, %0\n\t"
+ "mov %%edx, %1\n\t"
+ : "=&r"(regs[0]), "=&r"(regs[1])
+ : "r"(cmd->getCommand()));
+
+ MemoryOperations::copy(regs, &rdmsrResult, sizeof(uint64));
+ cmd->decode(rdmsrResult);
+
+ return false;
+};
+
+bool Msr::wrmsr(MsrCommand *cmd)
+{
+ if(!msrSupport or cmd == nullptr) return true;
+
+ uint32 regs[2];
+ uint64 msr = cmd->getMsr();
+
+ MemoryOperations::copy(&msr, regs, sizeof(uint64));
+
+ asm(
+ "mov %0, %%eax\n\t"
+ "mov %1, %%edx\n\t"
+ "mov %2, %%ecx\n\t"
+ "wrmsr\n\t"
+ : "=r"(regs[0]), "=r"(regs[1])
+ : "r"(cmd->getCommand()));
+
+ return false;
+};
+
+Ia32ApicBase::Ia32ApicBase()
+{
+ Cpuinfo cpuinfo;
+ bool cpuidAddrSzNotSupport = cpuinfo.cpuid(Cpuinfo::AddressSize);
+ cpuidOutputRegisters AddrSzRegs = cpuinfo.getRegs();
+
+ cpuinfo.cpuid(Cpuinfo::VersionInfo);
+ if(cpuinfo.getRegs().edx & Cpuinfo::PAE
+ and cpuidAddrSzNotSupport) maxPhyAddr = 36;
+ else if(cpuidAddrSzNotSupport) maxPhyAddr = 32;
+ else if(!cpuidAddrSzNotSupport) maxPhyAddr = (uint8)AddrSzRegs.edx;
+
+ bspFlag = enableFlag = false;
+ baseField = NULL;
+};
+
+uint32 Ia32ApicBase::getCommand()
+{
+ return 0x1b;
+};
+
+void Ia32ApicBase::decode(uint64 rdmsrResult)
+{
+ bspFlag = rdmsrResult & BSP_FLAG;
+ enableFlag = rdmsrResult & APIC_ENABLE_FLAG;
+ setBaseField(rdmsrResult);
+};
+
+uint64 Ia32ApicBase::getMsr()
+{
+ uint64 msr = 0;
+
+ MemoryOperations::copy(&baseField, &msr, sizeof(uint64));
+ msr |= bspFlag << 8;
+ msr |= enableFlag << 11;
+
+ return msr;
+};
+
+void Ia32ApicBase::setBaseField(uint64 fieldAddr)
+{
+ uint64 mask = BASE_FIELD_MASK_LOW |
+ ((UINT64_HIGH<< (maxPhyAddr - 32)) ^ UINT64_HIGH);
+
+ baseField = fieldAddr & mask;
+};
+
+void Ia32ApicBase::setBspFlag(bool flag)
+{
+ bspFlag = flag;
+};
+
+void Ia32ApicBase::setEnableFlag(bool flag)
+{
+ enableFlag = flag;
+};
diff --git a/arch/x86/msr/Msr.h b/arch/x86/msr/Msr.h
new file mode 100644
index 0000000..98c1b02
--- /dev/null
+++ b/arch/x86/msr/Msr.h
@@ -0,0 +1,58 @@
+// Tasks:
+// 1) Implement msr write and save functions
+// 2) Ia32ApicBase field
+
+#include "../cpuinfo/Cpuinfo.h"
+#include <MemoryOperations.h>
+
+#ifndef MSR_H
+#define MSR_H
+
+// defines for Ia32ApicBase
+
+#define BSP_FLAG 0x100
+#define APIC_ENABLE_FLAG 0x800
+#define BASE_FIELD_MASK_LOW 0xfffff000
+#define UINT64_HIGH 0xffffffff00000000
+
+//------------------------
+
+class MsrCommand
+{
+ public:
+ virtual uint32 getCommand() = 0;
+ virtual void decode(uint64 rdmsrResult) = 0;
+ virtual uint64 getMsr() = 0;
+};
+
+class Ia32ApicBase : public MsrCommand
+{
+ private:
+ // Get through Cpuinfo instance
+ uint8 maxPhyAddr;
+ bool bspFlag, enableFlag;
+ uint64 baseField;
+
+ public:
+ Ia32ApicBase();
+ virtual uint32 getCommand() override final;
+ virtual void decode(uint64 rdmrResult) override final;
+ virtual uint64 getMsr() override final;
+ void setBspFlag(bool flag);
+ void setEnableFlag(bool flag);
+ void setBaseField(uint64 fieldAddr);
+};
+
+class Msr
+{
+ private:
+ bool msrSupport;
+ public:
+ Msr();
+ // Return true if MSR not supported (CPUID.01H:EDX[5] = 0)
+ bool rdmsr(MsrCommand *cmd);
+ // Return value same as rdmsr method
+ bool wrmsr(MsrCommand *cmd);
+};
+
+#endif