Added TSS and code to enter user mode (kind of).
This commit is contained in:
parent
355b1641bd
commit
d711938821
@ -1,4 +1,6 @@
|
||||
|
||||
extern "C" void main()
|
||||
{
|
||||
// __asm__ __volatile__("cli");
|
||||
while(true);
|
||||
}
|
||||
|
@ -85,6 +85,35 @@ __reloadSegments:
|
||||
movw %ax, %ss
|
||||
ret
|
||||
|
||||
.global __flushTSS
|
||||
.type __flushTSS @function
|
||||
// void __flushTSS(uint16_t segment [%di])
|
||||
__flushTSS:
|
||||
ltr %di
|
||||
ret
|
||||
|
||||
.global __enterUsermode
|
||||
.type __enterUsermode @function
|
||||
// void __enterUsermode(uint16_t codeSegment [%di], uint16_t dataSegment [%si], void* rsp [%rdx], void* function [%rcx])
|
||||
__enterUsermode:
|
||||
orw $0x3, %di // we are switching to ring 3, therefore set the bottom 2 bits to 3
|
||||
orw $0x3, %si // same for the data segment
|
||||
movw %si, %ds
|
||||
movw %si, %es
|
||||
movw %si, %fs
|
||||
movw %si, %gs
|
||||
|
||||
movq %rsp, (%rdx)
|
||||
movq %rsp, %rax
|
||||
pushq %rsi // data segment
|
||||
pushq %rax
|
||||
pushf // flags
|
||||
pushq %rdi // code segment
|
||||
pushq %rcx
|
||||
iretq
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Set the size of the _start symbol to the current location '.' minus its start.
|
||||
This is useful when debugging or when you implement call tracing.
|
||||
|
@ -46,15 +46,24 @@ inline constexpr std::uint8_t INTERRUPT_VIRTUALIZATION_EXCEPTION = 0x14;
|
||||
inline constexpr std::uint8_t INTERRUPT_CONTROL_PROTECTION_EXCEPTION = 0x15;
|
||||
inline constexpr std::uint8_t INTERRUPT_KEYBOARD = irqToInterrupt(1);
|
||||
|
||||
TaskStateSegment tss alignas(16);
|
||||
|
||||
constinit std::array GDT alignas(16) = {
|
||||
SEGMENT_NULL,
|
||||
SEGMENT_KERNEL_CODE,
|
||||
SEGMENT_KERNEL_DATA,
|
||||
SEGMENT_USER_CODE,
|
||||
SEGMENT_USER_DATA,
|
||||
SEGMENT_NULL
|
||||
SEGMENT_NULL, // TSS lower
|
||||
SEGMENT_NULL // TSS higher
|
||||
};
|
||||
|
||||
inline constexpr std::uint16_t SEGIDX_KERNEL_CODE = 1 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_KERNEL_DATA = 2 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_USER_CODE = 3 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_USER_DATA = 4 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_TSS = 5 << 3;
|
||||
|
||||
constinit std::array<InterruptDescriptor, 256> IDT alignas(16);
|
||||
|
||||
void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept
|
||||
@ -133,6 +142,8 @@ void initGlobals()
|
||||
extern "C" void __setGDT(uint16_t limit, void* base);
|
||||
extern "C" void __setIDT(uint16_t limit, void* base);
|
||||
extern "C" void __reloadSegments(uint64_t code, uint64_t data);
|
||||
extern "C" void __flushTSS(uint16_t segment);
|
||||
extern "C" void __enterUsermode(uint16_t codeSegment, uint16_t dataSegment, void* rsp, void (*function)());
|
||||
|
||||
template<typename THandler>
|
||||
void setupInterrupt(std::uint8_t index, THandler handler) noexcept
|
||||
@ -180,9 +191,11 @@ void kernel_main()
|
||||
setupInterrupt(INTERRUPT_CONTROL_PROTECTION_EXCEPTION, &baos::isrControlProtectionException);
|
||||
setupInterrupt(INTERRUPT_KEYBOARD, &ps2::isrKeyboard);
|
||||
|
||||
makeTSSSegment(&tss, &GDT[5]);
|
||||
__setGDT(sizeof(GDT), &GDT);
|
||||
__setIDT(sizeof(IDT), &IDT);
|
||||
__reloadSegments(0x08, 0x10);
|
||||
__reloadSegments(SEGIDX_KERNEL_CODE, SEGIDX_KERNEL_DATA);
|
||||
__flushTSS(SEGIDX_TSS);
|
||||
|
||||
const bool picsInited = initPICs(MASTER_PIC_OFFSET, SLAVE_PIC_OFFSET);
|
||||
unmaskIRQ(1);
|
||||
@ -229,6 +242,8 @@ void kernel_main()
|
||||
}
|
||||
|
||||
std::puts("This is BadAppleOS and everything is fine!\n");
|
||||
|
||||
__enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &main);
|
||||
while (true)
|
||||
{
|
||||
ps2::KeyEvent event;
|
||||
@ -240,12 +255,8 @@ void kernel_main()
|
||||
event.down ? "true" : "false",
|
||||
event.repeat ? "true" : "false"
|
||||
);
|
||||
if (event.down && event.scancode == ps2::Scancode::ESCAPE)
|
||||
{
|
||||
int x = 1 / 0;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
}
|
||||
} // extern "C"
|
||||
|
@ -5,6 +5,7 @@
|
||||
#define BAD_APPLE_OS_X86_64_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
// --- Segments --- //
|
||||
|
||||
@ -78,6 +79,30 @@ struct SegmentDescriptor
|
||||
/* 56 */ unsigned baseHigh : 8 = 0;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum class SystemSegmentDescriptorType
|
||||
{
|
||||
TSS = 0,
|
||||
LDT = 1
|
||||
};
|
||||
|
||||
struct SystemSegmentDescriptor
|
||||
{
|
||||
/* 0 */ unsigned limitLow : 16 = 0;
|
||||
/* 16 */ unsigned baseLow : 24 = 0;
|
||||
/* 40 */ unsigned type : 4 = 0;
|
||||
/* 44 */ SystemSegmentDescriptorType descType : 1 = SystemSegmentDescriptorType::TSS;
|
||||
/* 45 */ unsigned privilegeLevel : 2 = 0;
|
||||
/* 47 */ bool present : 1 = false;
|
||||
/* 48 */ unsigned limitHigh : 4 = 0;
|
||||
/* 52 */ bool available : 1 = 0;
|
||||
/* 53 */ bool long_ : 1 = 0;
|
||||
/* 54 */ bool big : 1 = 0;
|
||||
/* 55 */ SegmentGranularity granularity : 1 = SegmentGranularity::BYTE;
|
||||
/* 56 */ unsigned long baseHigh : 40 = 0;
|
||||
/* 96 */ unsigned reserved : 32 = 0;
|
||||
} __attribute__((packed));
|
||||
static_assert(2 * sizeof(SegmentDescriptor) == sizeof(SystemSegmentDescriptor));
|
||||
|
||||
inline constexpr const SegmentDescriptor SEGMENT_NULL = {};
|
||||
|
||||
inline constexpr const SegmentDescriptor SEGMENT_KERNEL_CODE = {
|
||||
@ -175,4 +200,43 @@ struct InterruptDescriptor
|
||||
/* 96 */ unsigned reserved2_ : 32 = 0;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct TaskStateSegment
|
||||
{
|
||||
/* 0 */ std::uint32_t reserved0 = 0;
|
||||
/* 32 */ std::uint64_t rsp0 = 0;
|
||||
/* 96 */ std::uint64_t rsp1 = 0;
|
||||
/* 160 */ std::uint64_t rsp2 = 0;
|
||||
/* 224 */ std::uint64_t reserved1 = 0;
|
||||
/* 288 */ std::uint64_t ist1 = 0;
|
||||
/* 352 */ std::uint64_t ist2 = 0;
|
||||
/* 416 */ std::uint64_t ist3 = 0;
|
||||
/* 480 */ std::uint64_t ist4 = 0;
|
||||
/* 544 */ std::uint64_t ist5 = 0;
|
||||
/* 608 */ std::uint64_t ist6 = 0;
|
||||
/* 672 */ std::uint64_t ist7 = 0;
|
||||
/* 736 */ std::uint64_t reserved2 = 0;
|
||||
/* 800 */ std::uint16_t reserved3 = 0;
|
||||
/* 816 */ std::uint16_t iobpOffset = 0;
|
||||
} __attribute__((packed));
|
||||
|
||||
inline void makeTSSSegment(TaskStateSegment* tssEntry, SegmentDescriptor* outSegments) noexcept
|
||||
{
|
||||
const std::uint64_t base = std::bit_cast<std::uint64_t>(tssEntry);
|
||||
SystemSegmentDescriptor descriptor {
|
||||
.limitLow = sizeof(TaskStateSegment),
|
||||
.baseLow = static_cast<unsigned>(base) & 0xFFFFFF,
|
||||
.type = static_cast<unsigned>(SystemSegmentType::TSS_32_AVAILABLE),
|
||||
.descType = SystemSegmentDescriptorType::TSS,
|
||||
.privilegeLevel = 0,
|
||||
.present = true,
|
||||
.limitHigh = 0,
|
||||
.available = false,
|
||||
.long_ = false,
|
||||
.big = false,
|
||||
.granularity = SegmentGranularity::BYTE,
|
||||
.baseHigh = (base & 0xFFFFFFFFFF000000) >> 24
|
||||
};
|
||||
std::memcpy(outSegments, &descriptor, 2 * sizeof(SegmentDescriptor));
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_X86_64_HPP_INCLUDED)
|
||||
|
Loading…
x
Reference in New Issue
Block a user