Implemented syscalls and jump to usermode.
This commit is contained in:
parent
9c70cfa846
commit
edd9ee85c7
@ -49,6 +49,7 @@ any_target_sources = Split('''
|
|||||||
src/os/draw.cpp
|
src/os/draw.cpp
|
||||||
src/os/memory.cpp
|
src/os/memory.cpp
|
||||||
src/os/panic.cpp
|
src/os/panic.cpp
|
||||||
|
src/os/syscall.cpp
|
||||||
src/os/tty.cpp
|
src/os/tty.cpp
|
||||||
src/os/resources/lat9-08.psf.s
|
src/os/resources/lat9-08.psf.s
|
||||||
|
|
||||||
|
57
targets/_any/include/os/cpu.hpp
Normal file
57
targets/_any/include/os/cpu.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(BAD_APPLE_OS_CPU_HPP_INCLUDED)
|
||||||
|
#define BAD_APPLE_OS_CPU_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace baos::cpu
|
||||||
|
{
|
||||||
|
enum class MSR : std::uint32_t
|
||||||
|
{
|
||||||
|
IA32_EFER = 0xC000'0080,
|
||||||
|
STAR = 0xC000'0081, // segments for syscall
|
||||||
|
LSTAR = 0xC000'0082, // instruction pointer for syscall
|
||||||
|
};
|
||||||
|
inline constexpr std::uint64_t IA32_EFER_SYSTEM_CALL_EXTENSIONS_BIT = (1 << 0);
|
||||||
|
inline constexpr std::uint64_t IA32_EFER_LONG_MODE_ENABLE_BIT = (1 << 8);
|
||||||
|
inline constexpr std::uint64_t IA32_EFER_LONG_MODE_ACTIVE_BIT = (1 << 10);
|
||||||
|
inline constexpr std::uint64_t IA32_EFER_NO_EXECUTE_ENABLE_BIT = (1 << 11);
|
||||||
|
// ...
|
||||||
|
|
||||||
|
inline std::uint64_t readMSR(MSR msr) noexcept
|
||||||
|
{
|
||||||
|
std::uint32_t lowHalf = 0;
|
||||||
|
std::uint32_t highHalf = 0;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"rdmsr"
|
||||||
|
: "=a"(lowHalf), "=d"(highHalf)
|
||||||
|
: "c"(msr)
|
||||||
|
);
|
||||||
|
return static_cast<std::uint64_t>(highHalf) << 32 | lowHalf;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void writeMSR(MSR msr, std::uint64_t value) noexcept
|
||||||
|
{
|
||||||
|
std::uint32_t lowHalf = static_cast<std::uint32_t>(value & 0xFFFFFFFF);
|
||||||
|
std::uint32_t highHalf = static_cast<std::uint32_t>(value >> 32);
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"wrmsr"
|
||||||
|
:
|
||||||
|
: "a"(lowHalf), "d"(highHalf), "c"(msr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setMSRBits(MSR msr, std::uint64_t bits) noexcept
|
||||||
|
{
|
||||||
|
writeMSR(msr, readMSR(msr) | bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void unsetMSRBits(MSR msr, std::uint64_t bits) noexcept
|
||||||
|
{
|
||||||
|
writeMSR(msr, readMSR(msr) & ~bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(BAD_APPLE_OS_CPU_HPP_INCLUDED)
|
18
targets/_any/include/os/segments.hpp
Normal file
18
targets/_any/include/os/segments.hpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(BAD_APPLE_OS_SEGMENTS_HPP_INCLUDED)
|
||||||
|
#define BAD_APPLE_OS_SEGMENTS_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace baos
|
||||||
|
{
|
||||||
|
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 = 4 << 3;
|
||||||
|
inline constexpr std::uint16_t SEGIDX_USER_DATA = 3 << 3;
|
||||||
|
inline constexpr std::uint16_t SEGIDX_TSS = 5 << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(BAD_APPLE_OS_SEGMENTS_HPP_INCLUDED)
|
33
targets/_any/include/os/syscall.hpp
Normal file
33
targets/_any/include/os/syscall.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(BAD_APPLE_OS_SYSCALL_HPP_INCLUDED)
|
||||||
|
#define BAD_APPLE_OS_SYSCALL_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace baos
|
||||||
|
{
|
||||||
|
enum class Syscall : std::uint64_t
|
||||||
|
{
|
||||||
|
FILE_READ = 0,
|
||||||
|
FILE_WRITE = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
void setupSyscall() noexcept;
|
||||||
|
|
||||||
|
template<typename TParam0, typename TParam1, typename TParam2>
|
||||||
|
inline void doSyscall(Syscall cmd, TParam0 param0 = 0, TParam1 param1 = 0, TParam2 param2 = 0) noexcept
|
||||||
|
{
|
||||||
|
register std::uint64_t r8 asm("r8") = param2;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"syscall"
|
||||||
|
:
|
||||||
|
: "D"(cmd), "S"(param0), "d"(param1)
|
||||||
|
: "%rcx"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(BAD_APPLE_OS_SYSCALL_HPP_INCLUDED)
|
@ -110,8 +110,6 @@ void cmdDumpPageTable() noexcept
|
|||||||
|
|
||||||
extern "C" void main()
|
extern "C" void main()
|
||||||
{
|
{
|
||||||
|
|
||||||
// __asm__ __volatile__("cli");
|
|
||||||
std::string cmd;
|
std::string cmd;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "os/serial.hpp"
|
#include "os/syscall.hpp"
|
||||||
#include "os/tty.hpp"
|
#include "os/tty.hpp"
|
||||||
#include "os/tools/printf_helper.hpp"
|
#include "os/tools/printf_helper.hpp"
|
||||||
#include "os/tools/ringbuffer.hpp"
|
#include "os/tools/ringbuffer.hpp"
|
||||||
@ -113,6 +113,7 @@ FILE* __stdin = &gStdin;
|
|||||||
|
|
||||||
int putchar(int chr) noexcept
|
int putchar(int chr) noexcept
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
tty::putChar(static_cast<char>(chr));
|
tty::putChar(static_cast<char>(chr));
|
||||||
if (chr == '\n')
|
if (chr == '\n')
|
||||||
{
|
{
|
||||||
@ -124,10 +125,17 @@ int putchar(int chr) noexcept
|
|||||||
serialWrite(PORT_COM1, static_cast<std::uint8_t>(chr));
|
serialWrite(PORT_COM1, static_cast<std::uint8_t>(chr));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
|
char asChar = static_cast<char>(chr);
|
||||||
|
baos::doSyscall(baos::Syscall::FILE_WRITE, 0, &asChar, 1);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int puts(const char* str) noexcept
|
int puts(const char* str) noexcept
|
||||||
{
|
{
|
||||||
|
baos::doSyscall(baos::Syscall::FILE_WRITE, 0, str, std::strlen(str));
|
||||||
|
return 0;
|
||||||
|
#if 0
|
||||||
while (*str)
|
while (*str)
|
||||||
{
|
{
|
||||||
putchar(*str);
|
putchar(*str);
|
||||||
@ -135,6 +143,7 @@ int puts(const char* str) noexcept
|
|||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int printf(const char* format, ...) noexcept
|
int printf(const char* format, ...) noexcept
|
||||||
|
@ -78,6 +78,7 @@ bool initPICs(std::uint8_t masterOffset, std::uint8_t slaveOffset) noexcept
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((no_caller_saved_registers))
|
||||||
void sendEndOfInterrupt(std::uint8_t irq) noexcept
|
void sendEndOfInterrupt(std::uint8_t irq) noexcept
|
||||||
{
|
{
|
||||||
if (irq >= 8) {
|
if (irq >= 8) {
|
||||||
|
@ -24,10 +24,9 @@ struct MemoryRangeAllocationInfo
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(MemoryRangeAllocationInfo) == 4096);
|
static_assert(sizeof(MemoryRangeAllocationInfo) == 4096);
|
||||||
|
|
||||||
inline constexpr unsigned MAX_USABLE_RANGES = 32;
|
inline constexpr unsigned MAX_USABLE_RANGES = 512;
|
||||||
std::array<MemoryRange, MAX_USABLE_RANGES> gUsableMemoryRanges;
|
std::array<MemoryRange, MAX_USABLE_RANGES> gUsableMemoryRanges;
|
||||||
std::array<MemoryRangeAllocationInfo, MAX_USABLE_RANGES> gRangeAllocationInfo;
|
unsigned gNumUsableRanges = 0;
|
||||||
std::uint8_t gNumUsableRanges = 0;
|
|
||||||
|
|
||||||
// initial 2MB page for setting up the page table
|
// initial 2MB page for setting up the page table
|
||||||
// std::array<std::uint8_t, 2ul << 20> gInitPage alignas(2ul << 20);
|
// std::array<std::uint8_t, 2ul << 20> gInitPage alignas(2ul << 20);
|
||||||
@ -75,6 +74,7 @@ PageTableEntry& getOrCreatePageTableEntry(PageTable& pageTable, std::uint16_t in
|
|||||||
entry.address = std::bit_cast<std::uint64_t>(&childTable) >> 12;
|
entry.address = std::bit_cast<std::uint64_t>(&childTable) >> 12;
|
||||||
entry.writable = true;
|
entry.writable = true;
|
||||||
entry.present = true;
|
entry.present = true;
|
||||||
|
entry.user = true;
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@ -111,60 +111,16 @@ void addUsableRange(const MemoryRange& range) noexcept
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gUsableMemoryRanges[gNumUsableRanges] = range;
|
gUsableMemoryRanges[gNumUsableRanges] = range;
|
||||||
gRangeAllocationInfo[gNumUsableRanges].numFreePages = range.numPages;
|
|
||||||
++gNumUsableRanges;
|
++gNumUsableRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint64_t findFreePages(unsigned numConsecutive) noexcept
|
|
||||||
{
|
|
||||||
if (numConsecutive == 0 || numConsecutive > 4086) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (numConsecutive != 1) {
|
|
||||||
return 0; // TODO!!!
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::uint8_t rangeIdx = 0; rangeIdx < gNumUsableRanges; ++rangeIdx)
|
|
||||||
{
|
|
||||||
std::uint64_t page = gUsableMemoryRanges[rangeIdx].pageBase;
|
|
||||||
for (MemoryRangeAllocationInfo* allocInfo = &gRangeAllocationInfo[rangeIdx]; allocInfo != nullptr; page += allocInfo->usedPages.size(), allocInfo = allocInfo->next)
|
|
||||||
{
|
|
||||||
if (allocInfo->numFreePages < numConsecutive) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (unsigned pagesIdx = 0; pagesIdx < allocInfo->usedPages.size(); ++pagesIdx)
|
|
||||||
{
|
|
||||||
if (allocInfo->usedPages[pagesIdx] != 0xFF)
|
|
||||||
{
|
|
||||||
for (unsigned bit = 0; bit < 8; ++bit)
|
|
||||||
{
|
|
||||||
if ((allocInfo->usedPages[pagesIdx] & (1 << bit)) == 0)
|
|
||||||
{
|
|
||||||
allocInfo->usedPages[pagesIdx] |= (1 << bit);
|
|
||||||
return page + (8 * pagesIdx) + bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageTable& setupPageTableEntry(PageTableEntry& entry, std::uint64_t page) noexcept
|
|
||||||
{
|
|
||||||
entry.address = page;
|
|
||||||
entry.present = true;
|
|
||||||
entry.writable = true;
|
|
||||||
return *(::new(std::bit_cast<void*>(entry.address << 12)) PageTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Finds a free memory range using the provided constraints (size and page alignment). */
|
/** Finds a free memory range using the provided constraints (size and page alignment). */
|
||||||
bool findFreeMemory(std::size_t numPages, std::size_t pageAlignment, std::uint64_t& outPage, MemoryRange*& outRange) noexcept
|
bool findFreeMemory(std::size_t numPages, std::size_t pageAlignment, std::uint64_t& outPage, MemoryRange*& outRange) noexcept
|
||||||
{
|
{
|
||||||
// first try to find a range that already is already aligned properly
|
// first try to find a range that already is already aligned properly
|
||||||
for (MemoryRange& range : gUsableMemoryRanges)
|
for (unsigned rangeIdx = 0; rangeIdx < gNumUsableRanges; ++rangeIdx)
|
||||||
{
|
{
|
||||||
|
MemoryRange& range = gUsableMemoryRanges[rangeIdx];
|
||||||
if (range.numPages >= numPages && range.pageBase % pageAlignment == 0)
|
if (range.numPages >= numPages && range.pageBase % pageAlignment == 0)
|
||||||
{
|
{
|
||||||
outPage = range.pageBase;
|
outPage = range.pageBase;
|
||||||
@ -176,8 +132,9 @@ bool findFreeMemory(std::size_t numPages, std::size_t pageAlignment, std::uint64
|
|||||||
return false; // no need to search further, everything is full!
|
return false; // no need to search further, everything is full!
|
||||||
}
|
}
|
||||||
// now just try to find a range that could be used (needs to be split then)
|
// now just try to find a range that could be used (needs to be split then)
|
||||||
for (MemoryRange& range : gUsableMemoryRanges)
|
for (unsigned rangeIdx = 0; rangeIdx < gNumUsableRanges; ++rangeIdx)
|
||||||
{
|
{
|
||||||
|
MemoryRange& range = gUsableMemoryRanges[rangeIdx];
|
||||||
const std::uint64_t possibleBase = std::alignUp(range.pageBase, pageAlignment); // needs to be 2MB aligned
|
const std::uint64_t possibleBase = std::alignUp(range.pageBase, pageAlignment); // needs to be 2MB aligned
|
||||||
if (range.numPages - (possibleBase - range.pageBase) >= numPages)
|
if (range.numPages - (possibleBase - range.pageBase) >= numPages)
|
||||||
{
|
{
|
||||||
@ -239,6 +196,12 @@ bool allocateIdentityMappedPages(std::size_t numPages, std::size_t pageAlignment
|
|||||||
|
|
||||||
bool setupPaging(std::span<const MemoryRange> memoryRanges) noexcept
|
bool setupPaging(std::span<const MemoryRange> memoryRanges) noexcept
|
||||||
{
|
{
|
||||||
|
std::uint32_t eax, ebx, ecx, edx;
|
||||||
|
|
||||||
|
// TODO: apparently it's not supported in Qemu (or on the host CPU, who knows?) so don't waste time on it
|
||||||
|
// __cpuid(0x8000'0001, eax, ebx, ecx, edx);
|
||||||
|
// g1GBPagesSupported = (edx & (1 << 26)) != 0;
|
||||||
|
|
||||||
std::uint64_t firstKernelPage = std::bit_cast<std::uint64_t>(&gKernelStart) / 4096;
|
std::uint64_t firstKernelPage = std::bit_cast<std::uint64_t>(&gKernelStart) / 4096;
|
||||||
std::uint64_t lastKernelPage = std::bit_cast<std::uint64_t>(&gKernelEnd) / 4096 + 1;
|
std::uint64_t lastKernelPage = std::bit_cast<std::uint64_t>(&gKernelEnd) / 4096 + 1;
|
||||||
for (MemoryRange range : memoryRanges)
|
for (MemoryRange range : memoryRanges)
|
||||||
@ -309,18 +272,6 @@ const char* memoryTypeName(MemoryType type) noexcept
|
|||||||
return "<INVALID>";
|
return "<INVALID>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void* allocatePages(unsigned numConsecutive) noexcept
|
|
||||||
{
|
|
||||||
const std::uint64_t firstPage = findFreePages(numConsecutive);
|
|
||||||
if (firstPage == 0)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
setupIdentityPaging(firstPage, firstPage + numConsecutive);
|
|
||||||
return std::bit_cast<void*>(firstPage << 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void setupIdentityPaging(std::uint64_t page) noexcept
|
void setupIdentityPaging(std::uint64_t page) noexcept
|
||||||
{
|
{
|
||||||
PageTableEntry& pageTableEntry = getOrCreatePage(page);
|
PageTableEntry& pageTableEntry = getOrCreatePage(page);
|
||||||
|
50
targets/_any/src/os/syscall.cpp
Normal file
50
targets/_any/src/os/syscall.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
#include "os/syscall.hpp"
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
#include <cstddef>
|
||||||
|
#include "os/cpu.hpp"
|
||||||
|
#include "os/segments.hpp"
|
||||||
|
#include "os/serial.hpp"
|
||||||
|
#include "os/tty.hpp"
|
||||||
|
|
||||||
|
extern "C" void __handleSyscall();
|
||||||
|
|
||||||
|
namespace baos
|
||||||
|
{
|
||||||
|
void setupSyscall() noexcept
|
||||||
|
{
|
||||||
|
// enable syscall/sysexit
|
||||||
|
cpu::setMSRBits(cpu::MSR::IA32_EFER, cpu::IA32_EFER_SYSTEM_CALL_EXTENSIONS_BIT);
|
||||||
|
cpu::writeMSR(cpu::MSR::LSTAR, std::bit_cast<std::uint64_t>(&__handleSyscall));
|
||||||
|
cpu::writeMSR(cpu::MSR::STAR, static_cast<std::uint64_t>(SEGIDX_KERNEL_CODE) << 32 | static_cast<std::uint64_t>(SEGIDX_KERNEL_DATA) << 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysFileRead(unsigned fileDescriptor, char* buffer, std::size_t count) noexcept
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysFileWrite(unsigned fileDescriptor, const char* buffer, std::size_t count) noexcept
|
||||||
|
{
|
||||||
|
for (std::size_t index = 0; index < count; ++index) {
|
||||||
|
serialWrite(PORT_COM1, buffer[index]);
|
||||||
|
}
|
||||||
|
tty::write(buffer, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __baosSyscall(baos::Syscall cmd, std::uint64_t param0, std::uint64_t param1, std::uint64_t param2) noexcept
|
||||||
|
{
|
||||||
|
using namespace baos;
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case Syscall::FILE_READ:
|
||||||
|
sysFileRead(static_cast<unsigned>(param0), std::bit_cast<char*>(param1), param2);
|
||||||
|
break;
|
||||||
|
case Syscall::FILE_WRITE:
|
||||||
|
sysFileWrite(static_cast<unsigned>(param0), std::bit_cast<const char*>(param1), param2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
@ -94,7 +94,7 @@ __flushTSS:
|
|||||||
|
|
||||||
.global __enterUsermode
|
.global __enterUsermode
|
||||||
.type __enterUsermode @function
|
.type __enterUsermode @function
|
||||||
// void __enterUsermode(uint16_t codeSegment [%di], uint16_t dataSegment [%si], void* rsp [%rdx], void* function [%rcx])
|
// void __enterUsermode(uint16_t codeSegment [%di], uint16_t dataSegment [%si], void* rsp [%rdx], void* function [%rcx], void* stackPtr [r8])
|
||||||
__enterUsermode:
|
__enterUsermode:
|
||||||
orw $0x3, %di // we are switching to ring 3, therefore set the bottom 2 bits to 3
|
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
|
orw $0x3, %si // same for the data segment
|
||||||
@ -104,15 +104,25 @@ __enterUsermode:
|
|||||||
movw %si, %gs
|
movw %si, %gs
|
||||||
|
|
||||||
movq %rsp, (%rdx)
|
movq %rsp, (%rdx)
|
||||||
movq %rsp, %rax
|
|
||||||
pushq %rsi // data segment
|
pushq %rsi // data segment
|
||||||
pushq %rax
|
pushq %r8
|
||||||
pushf // flags
|
pushf // flags
|
||||||
pushq %rdi // code segment
|
pushq %rdi // code segment
|
||||||
pushq %rcx
|
pushq %rcx
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
|
.global __handleSyscall
|
||||||
|
.type __handleSyscall @function
|
||||||
|
// void __handleSyscall()
|
||||||
|
__handleSyscall:
|
||||||
|
pushq %rcx // store the original instruction pointer
|
||||||
|
pushq %rsp // also store the original stack pointer
|
||||||
|
movq %r8, %rcx
|
||||||
|
// movq (__kernel_rsp), %rsp
|
||||||
|
call __baosSyscall
|
||||||
|
popq %rsp
|
||||||
|
popq %rcx
|
||||||
|
sysretq
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set the size of the _start symbol to the current location '.' minus its start.
|
Set the size of the _start symbol to the current location '.' minus its start.
|
||||||
|
@ -5,11 +5,12 @@
|
|||||||
#include <bit>
|
#include <bit>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "os/draw.hpp"
|
#include "os/draw.hpp"
|
||||||
#include "os/memory.hpp"
|
#include "os/memory.hpp"
|
||||||
|
#include "os/segments.hpp"
|
||||||
#include "os/serial.hpp"
|
#include "os/serial.hpp"
|
||||||
|
#include "os/syscall.hpp"
|
||||||
#include "os/tty.hpp"
|
#include "os/tty.hpp"
|
||||||
#include "drivers/pci.hpp"
|
#include "drivers/pci.hpp"
|
||||||
#include "drivers/pic.hpp"
|
#include "drivers/pic.hpp"
|
||||||
@ -56,18 +57,12 @@ constinit std::array GDT alignas(16) = {
|
|||||||
SEGMENT_NULL,
|
SEGMENT_NULL,
|
||||||
SEGMENT_KERNEL_CODE,
|
SEGMENT_KERNEL_CODE,
|
||||||
SEGMENT_KERNEL_DATA,
|
SEGMENT_KERNEL_DATA,
|
||||||
SEGMENT_USER_CODE,
|
|
||||||
SEGMENT_USER_DATA,
|
SEGMENT_USER_DATA,
|
||||||
|
SEGMENT_USER_CODE,
|
||||||
SEGMENT_NULL, // TSS lower
|
SEGMENT_NULL, // TSS lower
|
||||||
SEGMENT_NULL // TSS higher
|
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);
|
constinit std::array<InterruptDescriptor, 256> IDT alignas(16);
|
||||||
|
|
||||||
|
|
||||||
@ -153,7 +148,7 @@ extern "C" void __setGDT(uint16_t limit, void* base);
|
|||||||
extern "C" void __setIDT(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 __reloadSegments(uint64_t code, uint64_t data);
|
||||||
extern "C" void __flushTSS(uint16_t segment);
|
extern "C" void __flushTSS(uint16_t segment);
|
||||||
extern "C" void __enterUsermode(uint16_t codeSegment, uint16_t dataSegment, void* rsp, void (*function)());
|
extern "C" void __enterUsermode(uint16_t codeSegment, uint16_t dataSegment, void* rsp, void (*function)(), void* stackPtr);
|
||||||
|
|
||||||
template<typename THandler>
|
template<typename THandler>
|
||||||
void setupInterrupt(std::uint8_t index, THandler handler) noexcept
|
void setupInterrupt(std::uint8_t index, THandler handler) noexcept
|
||||||
@ -222,6 +217,8 @@ void kernel_main()
|
|||||||
__reloadSegments(SEGIDX_KERNEL_CODE, SEGIDX_KERNEL_DATA);
|
__reloadSegments(SEGIDX_KERNEL_CODE, SEGIDX_KERNEL_DATA);
|
||||||
__flushTSS(SEGIDX_TSS);
|
__flushTSS(SEGIDX_TSS);
|
||||||
|
|
||||||
|
setupSyscall();
|
||||||
|
|
||||||
const bool picsInited = initPICs(MASTER_PIC_OFFSET, SLAVE_PIC_OFFSET);
|
const bool picsInited = initPICs(MASTER_PIC_OFFSET, SLAVE_PIC_OFFSET);
|
||||||
unmaskIRQ(1);
|
unmaskIRQ(1);
|
||||||
|
|
||||||
@ -236,7 +233,10 @@ void kernel_main()
|
|||||||
|
|
||||||
// init the heap (required for the double buffer)
|
// init the heap (required for the double buffer)
|
||||||
const std::vector<MemoryRange> ranges = detectMemoryRangesFromEfi(gBootInfo->memoryMap);
|
const std::vector<MemoryRange> ranges = detectMemoryRangesFromEfi(gBootInfo->memoryMap);
|
||||||
setupPaging({ranges.begin(), ranges.end()});
|
if (!setupPaging({ranges.begin(), ranges.end()}))
|
||||||
|
{
|
||||||
|
panic("Error setting up paging.");
|
||||||
|
}
|
||||||
|
|
||||||
// make sure boot info and the frame buffer are accessible
|
// make sure boot info and the frame buffer are accessible
|
||||||
identityMapRegion(gBootInfo, sizeof(*gBootInfo));
|
identityMapRegion(gBootInfo, sizeof(*gBootInfo));
|
||||||
@ -244,8 +244,6 @@ void kernel_main()
|
|||||||
|
|
||||||
initGlobals();
|
initGlobals();
|
||||||
|
|
||||||
// initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
|
|
||||||
|
|
||||||
// initialize the framebuffer
|
// initialize the framebuffer
|
||||||
draw::initializeDefaultFramebuffer({
|
draw::initializeDefaultFramebuffer({
|
||||||
/* base = */ static_cast<draw::Pixel*>(gBootInfo->displayInfo.frameBufferBase),
|
/* base = */ static_cast<draw::Pixel*>(gBootInfo->displayInfo.frameBufferBase),
|
||||||
@ -257,11 +255,6 @@ void kernel_main()
|
|||||||
// initialize terminal interface
|
// initialize terminal interface
|
||||||
tty::initialize();
|
tty::initialize();
|
||||||
|
|
||||||
for (const MemoryRange& range : ranges)
|
|
||||||
{
|
|
||||||
std::printf("Start: 0x%lX, Pages: %ld, Type: %s\n", range.pageBase << 12, range.numPages, memoryTypeName(range.type));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initSerialPort(PORT_COM1))
|
if (!initSerialPort(PORT_COM1))
|
||||||
{
|
{
|
||||||
tty::write("Error initializing serial port.\n");
|
tty::write("Error initializing serial port.\n");
|
||||||
@ -269,6 +262,11 @@ void kernel_main()
|
|||||||
}
|
}
|
||||||
serialWriteString(PORT_COM1, "\r\n\r\n"); // write newlines to separate from UEFI output
|
serialWriteString(PORT_COM1, "\r\n\r\n"); // write newlines to separate from UEFI output
|
||||||
|
|
||||||
|
for (const MemoryRange& range : ranges)
|
||||||
|
{
|
||||||
|
// std::printf("Start: 0x%lX, Pages: %ld, Type: %s\n", range.pageBase << 12, range.numPages, memoryTypeName(range.type));
|
||||||
|
}
|
||||||
|
|
||||||
if (!picsInited)
|
if (!picsInited)
|
||||||
{
|
{
|
||||||
std::puts("Error initializing the PICs!\n");
|
std::puts("Error initializing the PICs!\n");
|
||||||
@ -277,7 +275,7 @@ void kernel_main()
|
|||||||
|
|
||||||
if (!ps2Inited)
|
if (!ps2Inited)
|
||||||
{
|
{
|
||||||
std::puts("Error initializing the PS2 controller!!\n");
|
std::puts("Error initializing the PS2 controller!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,11 +284,7 @@ void kernel_main()
|
|||||||
initializePCIDevice(header);
|
initializePCIDevice(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::puts("This is BadAppleOS and everything is fine!\n");
|
static std::array<std::uint8_t, 16384> usermodeStack;
|
||||||
|
__enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &main, &usermodeStack.back());
|
||||||
// __enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &main);
|
|
||||||
main(); // for now run it in kernel mode, user mode doesn't work yet
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user