Compare commits

..

No commits in common. "50201fe6dfe9dfd055ccb33484a49183b14f9168" and "010e261dc7a2a2357c3ed2b0b4cdd9f2ddb6525d" have entirely different histories.

39 changed files with 95 additions and 787 deletions

View File

@ -9,20 +9,16 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_EXPORT_COMPILE_COMMANDS True)
set(BASE_COMPILE_FLAGS "-ffreestanding -fno-exceptions -mgeneral-regs-only")
set(BASE_LINK_FLAGS "-nostdlib")
add_subdirectory(zion)
add_subdirectory(lib)
add_subdirectory(sys)
# Use machine q35 to access PCI devices.
set(QEMU_CMD qemu-system-x86_64 -machine q35 -d guest_errors -m 1G -serial stdio -hda disk.img)
set(QEMU_CMD qemu-system-x86_64 -d guest_errors -m 1G -serial stdio -hda disk.img)
add_custom_command(
OUTPUT disk.img
COMMAND sudo sh ../scripts/build_image.sh disk.img
DEPENDS zion yellowstone test2
DEPENDS zion test test2
USES_TERMINAL
)

View File

@ -1,16 +1,15 @@
add_library(c STATIC
add_library(libc STATIC
src/malloc.cpp
src/stdio.cpp
)
target_include_directories(c
target_include_directories(libc
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(c
target_link_libraries(libc
zion_lib
)
set_target_properties(c PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}")
set_target_properties(libc PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -mgeneral-regs-only")

View File

@ -1,10 +0,0 @@
#pragma once
#include <stdarg.h>
// int fprintf(FILE *stream, const char *format, ...);
int printf(const char *format, ...);
int sprintf(char *str, const char *format, ...);
// int vfprintf(FILE *stream, const char *format, va_list arg);
int vprintf(const char *format, va_list arg);
int vsprintf(char *str, const char *format, va_list arg);

View File

@ -1,116 +0,0 @@
#include "stdio.h"
#include <stdint.h>
namespace {
uint32_t num_chars(uint64_t num, uint8_t base) {
uint32_t width = 0;
while (num > 0) {
num /= base;
width++;
}
return width;
}
int sprint_base(char *str, uint64_t num, uint32_t base) {
uint32_t width = num_chars(num, base);
if (width == 0) {
*str = '0';
return 1;
}
uint64_t place = 1;
while (num > 0) {
// FIXME: We seem to have an issue with loading globals.
const char *kHexChars = "0123456789abcdef";
str[width - place] = kHexChars[num % base];
place++;
num /= base;
}
return width;
}
} // namespace
int sprintf(char *str, const char *format, ...) {
va_list arg;
va_start(arg, format);
int ret = vsprintf(str, format, arg);
va_end(arg);
return ret;
}
int vsprintf(char *str, const char *format, va_list arg) {
uint32_t chars = 0;
while (*format != '\0') {
if (*format != '%') {
*str = *format;
chars++;
str++;
format++;
continue;
}
format++;
switch (*format) {
case '%':
*(str++) = *(format++);
chars++;
break;
case 'l': {
switch (*(++format)) {
case 'x': {
int width = sprint_base(str, va_arg(arg, uint64_t), 16);
if (width == -1) {
return -1;
}
chars += width;
str += width;
format++;
break;
}
case 'u': {
int width = sprint_base(str, va_arg(arg, uint64_t), 10);
if (width == -1) {
return -1;
}
chars += width;
str += width;
format++;
break;
}
}
break;
}
case 'x': {
int width = sprint_base(str, va_arg(arg, uint32_t), 16);
if (width == -1) {
return -1;
}
chars += width;
str += width;
format++;
break;
}
case 'u': {
int width = sprint_base(str, va_arg(arg, uint32_t), 10);
if (width == -1) {
return -1;
}
chars += width;
str += width;
format++;
break;
}
default:
*(str++) = *(format++);
chars++;
}
}
*str = '\0';
chars++;
return chars;
}

View File

@ -1,15 +1,15 @@
add_library(cxx STATIC
add_library(libcxx STATIC
src/new.cpp
)
target_include_directories(cxx
target_include_directories(libcxx
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(cxx
c
target_link_libraries(libcxx
libc
zion_lib
)
set_target_properties(cxx PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}")
set_target_properties(libcxx PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -mgeneral-regs-only")

View File

@ -10,10 +10,12 @@ target_include_directories(mammoth_lib
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(mammoth_lib
c
zion_lib)
set(_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -c -ffreestanding -fno-rtti -fno-exceptions -nostdlib -mabi=sysv -mgeneral-regs-only")
set(_LINK_FLAGS "-nostdlib")
set_target_properties(mammoth_lib PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
COMPILE_FLAGS "${_COMPILE_FLAGS}"
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${_LINK_FLAGS}"
)

View File

@ -3,7 +3,7 @@
#include <stdint.h>
#include <zerrors.h>
void dbgln(const char* fmt, ...);
void dbgln(const char*);
// Checks that the code is ok.
// if not exits the process.

View File

@ -1,29 +1,13 @@
#include "include/mammoth/debug.h"
#include <stdarg.h>
#include <stdio.h>
#include <zcall.h>
#include <zerrors.h>
void dbgln_internal(const char* str) { // Safe to ignore the result since right
// now this doesn't throw.
void dbgln(const char* str) {
// Safe to ignore the result since right now this doesn't throw.
uint64_t _ = ZDebug(str);
}
void dbgln(const char* fmt, ...) {
char str[1024];
va_list arg;
va_start(arg, fmt);
int ret = vsprintf(str, fmt, arg);
va_end(arg);
if (ret == -1 || ret > 1024) {
crash("Bad vsprintf", 1);
}
dbgln_internal(str);
}
void check(uint64_t code) {
switch (code) {
case Z_OK:

View File

@ -6,8 +6,6 @@
#include "mammoth/channel.h"
#include "mammoth/debug.h"
#define MAM_PROC_DEBUG 0
namespace {
typedef struct {
@ -65,27 +63,19 @@ uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) {
reinterpret_cast<Elf64ProgramHeader*>(base + header->phoff);
for (uint64_t i = 0; i < header->phnum; i++) {
Elf64ProgramHeader& program = programs[i];
#if MAM_PROC_DEBUG
dbgln("Create mem object");
#endif
uint64_t mem_cap;
uint64_t size = program.filesz;
check(ZMemoryObjectCreate(size, &mem_cap));
#if MAM_PROC_DEBUG
dbgln("Map Local");
#endif
uint64_t vaddr;
check(ZAddressSpaceMap(Z_INIT_VMAS_SELF, 0, mem_cap, &vaddr));
#if MAM_PROC_DEBUG
dbgln("Copy");
#endif
memcpy(base + program.offset, program.filesz, vaddr);
#if MAM_PROC_DEBUG
dbgln("Map Foreign");
#endif
check(ZAddressSpaceMap(as_cap, program.vaddr, mem_cap, &vaddr));
}
return header->entry;
@ -97,9 +87,7 @@ uint64_t SpawnProcessFromElfRegion(uint64_t program) {
Channel local, foreign;
check(CreateChannels(local, foreign));
#if MAM_PROC_DEBUG
dbgln("Spawn");
#endif
uint64_t proc_cap;
uint64_t as_cap;
uint64_t foreign_chan_id;
@ -107,15 +95,11 @@ uint64_t SpawnProcessFromElfRegion(uint64_t program) {
&as_cap, &foreign_chan_id));
uint64_t entry_point = LoadElfProgram(program, as_cap);
#if MAM_PROC_DEBUG
dbgln("Thread Create");
#endif
uint64_t thread_cap;
check(ZThreadCreate(proc_cap, &thread_cap));
#if MAM_PROC_DEBUG
dbgln("Thread start");
#endif
check(ZThreadStart(thread_cap, entry_point, foreign_chan_id, 0));
local.WriteStr("Hello!");

View File

@ -37,7 +37,7 @@ cp /usr/share/limine/limine.sys efi/
cp ../zion/boot/limine.cfg efi/
cp zion/zion efi/
mkdir -p efi/sys
cp sys/yellowstone/yellowstone efi/sys/yellowstone
cp sys/test efi/sys/test
cp sys/test2 efi/sys/test2
chown drew:drew $1

View File

@ -1,16 +1,30 @@
set(_COMPILE_FLAGS "-ffreestanding -fno-exceptions -mgeneral-regs-only")
set(_LINK_FLAGS "-nostdlib")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
add_subdirectory(yellowstone)
add_executable(test
test.cpp
)
target_link_libraries(test
mammoth_lib)
set_target_properties(test
PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${_COMPILE_FLAGS}"
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${_LINK_FLAGS}"
)
add_executable(test2
test2.cpp)
target_link_libraries(test2
cxx
libcxx
mammoth_lib)
set_target_properties(test2
PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${_COMPILE_FLAGS}"
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${_LINK_FLAGS}"
)

View File

@ -1,5 +0,0 @@
# System Processes
Current Processes;
- **yellowstone**: System Initialization

View File

@ -2,16 +2,11 @@
#include <mammoth/process.h>
#include <zcall.h>
#include "hw/pcie.h"
uint64_t main() {
dbgln("Yellowstone Initializing.");
int main() {
dbgln("Testing");
uint64_t vaddr;
check(ZAddressSpaceMap(Z_INIT_VMAS_SELF, 0, Z_INIT_BOOT_VMMO, &vaddr));
check(SpawnProcessFromElfRegion(vaddr));
DumpPciEDevices();
dbgln("Yellowstone Finished Successfully.");
dbgln("Return");
return 0;
}

View File

@ -1,16 +0,0 @@
add_executable(yellowstone
hw/pcie.cpp
yellowstone.cpp
)
target_include_directories(yellowstone
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(yellowstone
cxx
mammoth_lib
)
set_target_properties(yellowstone PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
)

View File

@ -1,100 +0,0 @@
#include "hw/pcie.h"
#include <mammoth/debug.h>
#include <zcall.h>
namespace {
struct PciDeviceHeader {
uint16_t vendor_id;
uint16_t device_id;
uint16_t command_reg;
uint16_t status_reg;
uint8_t revision;
uint8_t prog_interface;
uint8_t subclass;
uint8_t class_code;
uint8_t cache_line_size;
uint8_t latency_timer;
uint8_t header_type;
uint8_t bist;
} __attribute__((packed));
PciDeviceHeader* PciHeader(uint64_t base, uint64_t bus, uint64_t dev,
uint64_t fun) {
return reinterpret_cast<PciDeviceHeader*>(base + (bus << 20) + (dev << 15) +
(fun << 12));
}
void FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, uint64_t fun) {
PciDeviceHeader* hdr = PciHeader(base, bus, dev, fun);
if (hdr->vendor_id == 0xFFFF) {
return;
}
dbgln(
"[%u.%u.%u] (Vendor, Device): (%x, %x), (Type, Class, Sub, PIF): (%u, "
"%x, %x, %x)",
bus, dev, fun, hdr->vendor_id, hdr->device_id, hdr->header_type,
hdr->class_code, hdr->subclass, hdr->prog_interface);
if ((hdr->class_code == 0x6) && (hdr->subclass == 0x4)) {
dbgln("FIXME: Handle PCI to PCI bridge.");
}
if (hdr->class_code == 0x1) {
dbgln("SATA Device at: %lx", reinterpret_cast<uint64_t>(hdr) - base);
}
}
void DeviceDump(uint64_t base, uint64_t bus, uint64_t dev) {
PciDeviceHeader* hdr = PciHeader(base, bus, dev, 0);
if (hdr->vendor_id == 0xFFFF) {
return;
}
FunctionDump(base, bus, dev, 0);
// Device is multifunction.
if (hdr->header_type & 0x80) {
for (uint64_t f = 1; f < 0x8; f++) {
FunctionDump(base, bus, dev, f);
}
}
}
void BusDump(uint64_t base, uint64_t bus) {
for (uint64_t dev = 0; dev < 0x20; dev++) {
DeviceDump(base, bus, dev);
}
}
void PciDump(uint64_t base) {
PciDeviceHeader* hdr = PciHeader(base, 0, 0, 0);
if ((hdr->header_type & 0x80) == 0) {
// Single bus system.
BusDump(base, 0);
} else {
for (uint64_t f = 0; f < 8; f++) {
PciDeviceHeader* f_hdr = PciHeader(base, 0, 0, f);
if (f_hdr->vendor_id != 0xFFFF) {
BusDump(base, f);
}
}
}
}
} // namespace
void DumpPciEDevices() {
dbgln("Creating PCI obj");
uint64_t vmmo_cap, vmmo_size;
check(ZTempPcieConfigObjectCreate(&vmmo_cap, &vmmo_size));
dbgln("Creating addr space");
uint64_t vaddr;
check(ZAddressSpaceMap(Z_INIT_VMAS_SELF, 0, vmmo_cap, &vaddr));
dbgln("Addr %lx", vaddr);
dbgln("Dumping PCI");
PciDump(vaddr);
dbgln("Done");
}

View File

@ -1,3 +0,0 @@
#pragma once
void DumpPciEDevices();

View File

@ -1,12 +1,9 @@
add_executable(zion
boot/acpi.cpp
boot/boot_info.cpp
capability/capability.cpp
common/gdt.cpp
common/load_gdt.s
common/msr.cpp
debug/debug.cpp
interrupt/apic.cpp
interrupt/interrupt.cpp
interrupt/interrupt_enter.s
interrupt/timer.cpp

View File

@ -1,171 +0,0 @@
#include "boot/acpi.h"
#include "boot/boot_info.h"
#include "debug/debug.h"
#define K_ACPI_DEBUG 0
namespace {
static uint64_t gPcieEcBase = 0x0;
static uint64_t gPcieEcSize = 0x0;
struct RsdpDescriptor {
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t rsdt_addr;
uint32_t length;
uint64_t xsdt_addr;
uint8_t ext_checksum;
uint8_t reserved[3];
} __attribute__((packed));
struct SdtHeader {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __attribute__((packed));
bool streq(const char* a, const char* b, uint8_t len) {
for (uint8_t i = 0; i < len; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
bool checksum(uint8_t* addr, uint8_t num_bytes) {
uint8_t check_cnt = 0;
for (uint8_t i = 0; i < num_bytes; i++) {
check_cnt += addr[i];
}
return check_cnt == 0;
}
void dbgsz(const char* c, uint8_t cnt) {
char cl[cnt + 1];
for (uint8_t i = 0; i < cnt; i++) {
cl[i] = c[i];
}
cl[cnt] = '\0';
dbgln(cl);
}
uint8_t* SdtDataStart(SdtHeader* sdt) {
return reinterpret_cast<uint8_t*>(sdt) + sizeof(SdtHeader);
}
void ParseMcfg(SdtHeader* rsdt) {
#if K_ACPI_DEBUG
dbgsz(rsdt->signature, 4);
#endif
uint32_t size = (rsdt->length - sizeof(SdtHeader)) / 16;
uint64_t* entries = reinterpret_cast<uint64_t*>(SdtDataStart(rsdt));
// There are 8 reserved bytes at the end of the table.
entries++;
for (uint32_t i = 0; i < size; i++) {
uint64_t base_ecm_addr = entries[2 * i];
uint64_t bus_info = entries[2 * i + 1];
if (bus_info != 0xff000000) {
#if K_ACPI_DEBUG
dbgln("WARN: Unexpected bus-info for PCI EC. Mem region will be wrong.")
#endif
}
gPcieEcBase = base_ecm_addr;
uint64_t num_busses = 0x100;
uint64_t dev_per_bus = 0x20;
uint64_t fns_per_dev = 0x8;
uint64_t bytes_per_fn = 0x1000;
gPcieEcSize = num_busses * dev_per_bus * fns_per_dev * bytes_per_fn;
#if K_ACPI_DEBUG
dbgln("PCI Map: %m:%x", gPcieEcBase, gPcieEcSize);
#endif
}
}
void ParseSdt(SdtHeader* rsdt) {
if (!checksum((uint8_t*)rsdt, rsdt->length)) {
dbgln("Bad RSDT checksum.");
return;
}
if (streq(rsdt->signature, "MCFG", 4)) {
ParseMcfg(rsdt);
} else {
#if K_ACPI_DEBUG
dbgln("Unhandled:");
dbgsz(rsdt->signature, 4);
#endif
}
}
void ProbeRsdt(SdtHeader* rsdt) {
if (!checksum((uint8_t*)rsdt, rsdt->length)) {
dbgln("Bad RSDT checksum.");
return;
}
#if K_ACPI_DEBUG
dbgsz(rsdt->signature, 4);
#endif
uint32_t size = (rsdt->length - sizeof(SdtHeader)) / 4;
uint32_t* entries = reinterpret_cast<uint32_t*>(SdtDataStart(rsdt));
for (uint32_t i = 0; i < size; i++) {
SdtHeader* table = reinterpret_cast<SdtHeader*>(entries[i]);
ParseSdt(table);
}
}
} // namespace
void ProbeRsdp() {
void* rsdp_addr = boot::GetRsdpAddr();
RsdpDescriptor* rsdp = static_cast<RsdpDescriptor*>(rsdp_addr);
if (!streq(rsdp->signature, "RSD PTR ", 8)) {
dbgln("Invalid Rsdp!");
return;
}
// Checks V1 up to rsdt_addr.
if (!checksum((uint8_t*)rsdp_addr, 20)) {
dbgln("Rsdp Check failed");
return;
}
#if K_ACPI_DEBUG
dbgln("ACPI Ver %u", rsdp->revision);
dbgln("RSDT Addr: %m", rsdp->rsdt_addr);
#endif
ProbeRsdt(reinterpret_cast<SdtHeader*>(rsdp->rsdt_addr));
if (rsdp->revision == 0) {
return;
}
// Checks V2 (entire structure).
if (!checksum((uint8_t*)rsdp_addr, rsdp->length)) {
dbgln("Rsdp ext checksum failed");
return;
}
#if K_ACPI_DEBUG
dbgln("XSDT Addr: %m", rsdp->xsdt_addr);
#endif
}
z_err_t GetPciExtendedConfiguration(uint64_t* base, uint64_t* offset) {
if (gPcieEcSize == 0) {
return Z_ERR_NOT_FOUND;
}
*base = gPcieEcBase;
*offset = gPcieEcSize;
return Z_OK;
}

View File

@ -1,9 +0,0 @@
#pragma once
#include <stdint.h>
#include "include/zerrors.h"
void ProbeRsdp();
z_err_t GetPciExtendedConfiguration(uint64_t* base, uint64_t* offset);

View File

@ -36,15 +36,4 @@ const limine_module_response& GetModules() {
return *gModuleRequest.response;
}
static volatile struct limine_rsdp_request gRsdpRequest {
.id = LIMINE_RSDP_REQUEST, .revision = 0, .response = 0,
};
void* GetRsdpAddr() {
if (!gRsdpRequest.response) {
panic("No rsdp response from limine");
}
return gRsdpRequest.response->address;
}
} // namespace boot

View File

@ -9,6 +9,4 @@ uint64_t GetHigherHalfDirectMap();
const limine_module_response& GetModules();
void* GetRsdpAddr();
} // namespace boot

View File

@ -6,5 +6,5 @@ TIMEOUT=0
PROTOCOL=limine
KERNEL_PATH=boot:///zion
MODULE_PATH=boot:///sys/yellowstone
MODULE_PATH=boot:///sys/test
MODULE_PATH=boot:///sys/test2

View File

@ -1,13 +0,0 @@
#include "common/msr.h"
uint64_t GetMSR(uint32_t msr) {
uint32_t lo, hi;
asm("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return (static_cast<uint64_t>(hi) << 32) | lo;
}
void SetMSR(uint32_t msr, uint64_t val) {
uint32_t lo = static_cast<uint32_t>(val);
uint32_t hi = val >> 32;
asm("wrmsr" ::"a"(lo), "d"(hi), "c"(msr));
}

View File

@ -1,6 +0,0 @@
#pragma once
#include <stdint.h>
uint64_t GetMSR(uint32_t msr);
void SetMSR(uint32_t msr, uint64_t val);

View File

@ -32,8 +32,6 @@
#define Z_MEMORY_OBJECT_CREATE 0x30
#define Z_TEMP_PCIE_CONFIG_OBJECT_CREATE 0x3F
#define Z_INIT_BOOT_VMMO 0x31
// IPC Calls
@ -67,8 +65,6 @@ void ZThreadExit();
[[nodiscard]] z_err_t ZAddressSpaceMap(uint64_t vmas_cap, uint64_t vmas_offset,
uint64_t vmmo_cap, uint64_t* vaddr);
[[nodiscard]] z_err_t ZMemoryObjectCreate(uint64_t size, uint64_t* vmmo_cap);
[[nodiscard]] z_err_t ZTempPcieConfigObjectCreate(uint64_t* vmmo_cap,
uint64_t* vmmo_size);
[[nodiscard]] z_err_t ZChannelCreate(uint64_t* channel1, uint64_t* channel2);
[[nodiscard]] z_err_t ZChannelSend(uint64_t chan_cap, uint64_t type,

View File

@ -1,128 +0,0 @@
#include "interrupt/apic.h"
#include <stdint.h>
#include "boot/boot_info.h"
#include "common/msr.h"
#include "common/port.h"
#include "debug/debug.h"
#define APIC_DEBUG 0
namespace {
#define IA32_APIC_BASE_MSR 0x1B
#define IA32_APIC_BASE_MSR_BSP 0x100 // Processor is a BSP
#define IA32_APIC_BASE_MSR_ENABLE 0x800
const uint64_t kEoiOffset = 0xB0;
constexpr uint64_t kLApicBase = 0xFEE0'0000;
constexpr uint64_t kIoApicAddr = 0xFEC0'0000;
constexpr uint64_t kIoApicData = 0xFEC0'0010;
uint32_t volatile* GetPhys(uint64_t base, uint64_t offset = 0) {
return reinterpret_cast<uint32_t*>(boot::GetHigherHalfDirectMap() + base +
offset);
}
uint32_t GetLocalReg(uint64_t offset) {
uint32_t volatile* reg = GetPhys(kLApicBase, offset);
return *reg;
}
void WriteLocalReg(uint64_t offset, uint32_t value) {
*GetPhys(kLApicBase, offset) = value;
}
uint32_t GetIoReg(uint8_t reg) {
*GetPhys(kIoApicAddr) = reg;
return *GetPhys(kIoApicData);
}
uint64_t GetIoEntry(uint8_t reg) {
*GetPhys(kIoApicAddr) = reg;
uint64_t entry = *GetPhys(kIoApicData);
*GetPhys(kIoApicAddr) = reg + 1;
entry |= ((uint64_t)*GetPhys(kIoApicData)) << 32;
return entry;
}
void SetIoEntry(uint8_t reg, uint64_t value) {
*GetPhys(kIoApicAddr) = reg;
*GetPhys(kIoApicData) = value & 0xFFFFFFFF;
*GetPhys(kIoApicAddr) = reg + 1;
*GetPhys(kIoApicData) = value >> 32;
}
#define PIC1_COMMAND 0x20
#define PIC2_COMMAND 0xA0
#define PIC1_DATA 0x21
#define PIC2_DATA 0xA1
void MaskPic() {
outb(PIC1_DATA, 0xFF);
outb(PIC2_DATA, 0xFF);
outb(PIC1_COMMAND, 0x11);
outb(PIC2_COMMAND, 0x11);
// Potential spurious interrupts at 0x87
outb(PIC1_DATA, 0x80); // PIC1 offset (high and dry).
outb(PIC2_DATA, 0x80); // PIC2 offset (high and dry).
outb(PIC1_DATA, 0x4);
outb(PIC2_DATA, 0x2);
outb(PIC1_DATA, 0x1);
outb(PIC2_DATA, 0x1);
// Mask all.
outb(PIC1_DATA, 0xFF);
outb(PIC2_DATA, 0xFF);
}
} // namespace
void InspectApic() {
#if APIC_DEBUG
dbgln("APIC:");
dbgln("ID: %x", GetLocalReg(0x20));
dbgln("VER: %x", GetLocalReg(0x30));
dbgln("TPR: %x", GetLocalReg(0x80));
dbgln("APR: %x", GetLocalReg(0x90));
dbgln("PPR: %x", GetLocalReg(0xA0));
dbgln("RRD: %x", GetLocalReg(0xC0));
dbgln("LDR: %x", GetLocalReg(0xD0));
dbgln("DFR: %x", GetLocalReg(0xE0));
dbgln("SIV: %x", GetLocalReg(0xF0));
for (uint64_t i = 0; i < 8; i++) {
dbgln("ISR(%u): %x", i, GetLocalReg(0x100 + (0x10 * i)));
}
for (uint64_t i = 0; i < 8; i++) {
dbgln("TMR(%u): %x", i, GetLocalReg(0x180 + (0x10 * i)));
}
for (uint64_t i = 0; i < 8; i++) {
dbgln("IRR(%u): %x", i, GetLocalReg(0x200 + (0x10 * i)));
}
dbgln("ESR: %x", GetLocalReg(0x280));
dbgln("IO ID: %x", GetIoReg(0x0));
dbgln("IO VER: %x", GetIoReg(0x1));
dbgln("IO ARB: %x", GetIoReg(0x2));
for (uint8_t i = 0x10; i < 0x3F; i += 2) {
dbgln("IO (%u): %x", i, GetIoEntry(i));
}
dbgln("APIC MSR: %x", GetMSR(0x1B));
#endif
}
void EnableApic() {
MaskPic();
// Map Timer.
SetIoEntry(0x14, 0x20);
// Skip Keyboard for now.
// SetIoEntry(0x12, 0x21);
InspectApic();
}
void SignalEOI() {
// Value doesn't matter.
WriteLocalReg(kEoiOffset, 0x1);
}

View File

@ -1,7 +0,0 @@
#pragma once
void InspectApic();
void EnableApic();
void SignalEOI();

View File

@ -4,7 +4,6 @@
#include "common/port.h"
#include "debug/debug.h"
#include "interrupt/apic.h"
#include "memory/kernel_heap.h"
#include "scheduler/scheduler.h"
@ -43,7 +42,6 @@ InterruptDescriptor CreateDescriptor(void isr(void)) {
}
struct InterruptFrame {
uint64_t cr2;
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
@ -91,14 +89,16 @@ extern "C" void interrupt_protection_fault(InterruptFrame* frame) {
extern "C" void isr_page_fault();
extern "C" void interrupt_page_fault(InterruptFrame* frame) {
uint64_t err = frame->error_code;
if ((err & 0x1) == 0) {
// Page not present error may be resolveable.
if (gScheduler->CurrentProcess().vmas()->HandlePageFault(frame->cr2)) {
return;
}
dbgln("Page Fault - trying to resolve");
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));
if (gScheduler->CurrentProcess().vmas()->HandlePageFault(cr2)) {
dbgln("Handled");
return;
}
dbgln("Unhandled Page Fault:");
dbgln("Unable to handle:");
uint64_t err = frame->error_code;
if (err & 0x1) {
dbgln("Page Protection");
} else {
@ -120,10 +120,14 @@ extern "C" void interrupt_page_fault(InterruptFrame* frame) {
}
dbgln("rip: %m", frame->rip);
dbgln("addr: %m", frame->cr2);
dbgln("addr: %m", cr2);
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*) {
@ -134,10 +138,20 @@ extern "C" void interrupt_timer(InterruptFrame*) {
}
dbgln("timer: %us", cnt * 50 / 1000);
}
SignalEOI();
outb(PIC1_COMMAND, PIC_EOI);
gScheduler->Preempt();
}
void EnablePic() {
outb(PIC1_COMMAND, 0x11);
outb(PIC1_DATA, 0x20); // PIC1 offset.
outb(PIC1_DATA, 0x4);
outb(PIC1_DATA, 0x1);
// Mask all except the timer.
outb(PIC1_DATA, 0xE);
}
void InitIdt() {
gIdt[0] = CreateDescriptor(isr_divide_by_zero);
gIdt[13] = CreateDescriptor(isr_protection_fault);
@ -149,5 +163,5 @@ void InitIdt() {
};
asm volatile("lidt %0" ::"m"(idtp));
EnableApic();
EnablePic();
}

View File

@ -14,12 +14,9 @@
push %rcx # (Return Address)
push %rbx
push %rax
mov %cr2, %rax
push %rax
.endm
.macro interrupt_exit
add $8, %rsp
pop %rax
pop %rbx
pop %rcx
@ -29,11 +26,11 @@
pop %r8
pop %r9
pop %r10
pop %r11
pop %r12
pop %r13
pop %r14
pop %r15
pop %r10
pop %r10
pop %r10
pop %r10
pop %r10
pop %rbp
add $8, %rsp # Remove error code.

View File

@ -9,8 +9,6 @@
#include "object/thread.h"
#include "scheduler/process_manager.h"
#define K_INIT_DEBUG 0
namespace {
typedef struct {
@ -56,20 +54,16 @@ typedef struct {
uint64_t LoadElfProgram(Process& dest_proc, uint64_t base, uint64_t offset) {
Elf64Header* header = reinterpret_cast<Elf64Header*>(base);
#if K_INIT_DEBUG
dbgln("phoff: %u phnum: %u", header->phoff, header->phnum);
#endif
Elf64ProgramHeader* programs =
reinterpret_cast<Elf64ProgramHeader*>(base + header->phoff);
for (uint64_t i = 0; i < header->phnum; i++) {
Elf64ProgramHeader& program = programs[i];
#if K_INIT_DEBUG
dbgln(
"prog: type: %u, flags: %u, offset: %u\n vaddr: %m, paddr: %m\n "
"filesz: %x, memsz: %x, align: %x",
program.type, program.flags, program.offset, program.vaddr,
program.paddr, program.filesz, program.memsz, program.align);
#endif
auto mem_obj = MakeRefCounted<MemoryObject>(program.filesz);
mem_obj->CopyBytesToObject(base + program.offset, program.filesz);
dest_proc.vmas()->MapInMemoryObject(program.vaddr, mem_obj);
@ -92,14 +86,12 @@ bool streq(const char* a, const char* b) {
}
void DumpModules() {
#if K_INIT_DEBUG
const limine_module_response& resp = boot::GetModules();
dbgln("[boot] Dumping bootloader modules.");
for (uint64_t i = 0; i < resp.module_count; i++) {
const limine_file& file = *resp.modules[i];
dbgln(" %s,%m,%x", file.path, file.address, file.size);
}
#endif
}
const limine_file& GetInitProgram(const char* path) {
@ -115,7 +107,7 @@ const limine_file& GetInitProgram(const char* path) {
void LoadInitProgram() {
DumpModules();
const limine_file& init_prog = GetInitProgram("/sys/yellowstone");
const limine_file& init_prog = GetInitProgram("/sys/test");
RefPtr<Process> proc = Process::Create();
gProcMan->InsertProcess(proc);

View File

@ -3,8 +3,6 @@
#include "boot/boot_info.h"
#include "debug/debug.h"
#define K_PHYS_DEBUG 0
namespace phys_mem {
namespace {
@ -25,18 +23,13 @@ class PhysicalMemoryManager {
const limine_memmap_response& memmap = boot::GetMemoryMap();
for (uint64_t i = 0; i < memmap.entry_count; i++) {
const limine_memmap_entry& entry = *memmap.entries[i];
#if K_PHYS_DEBUG
dbgln("Region(%u) at %m:%x", entry.type, entry.base, entry.length);
#endif
if (entry.type == 0) {
uint64_t base = entry.base;
uint64_t size = entry.length;
if (base == gBootstrap.init_page) {
base = gBootstrap.next_page;
uint64_t bootstrap_used = gBootstrap.next_page - gBootstrap.init_page;
#if K_PHYS_DEBUG
dbgln("[PMM] Taking over from bootstrap, used: %x", bootstrap_used);
#endif
size -= bootstrap_used;
}
AddMemoryRegion(base, size);
@ -116,9 +109,7 @@ uint64_t AllocatePage() {
panic("No Bootstrap Memory Manager");
}
#if K_PHYS_DEBUG
dbgln("[PMM] Boostrap Alloc!");
#endif
uint64_t page = gBootstrap.next_page;
if (page == gBootstrap.max_page) {

View File

@ -4,8 +4,6 @@
#include "memory/paging_util.h"
#include "memory/physical_memory.h"
#define K_VMAS_DEBUG 0
extern KernelStackManager* gKernelStackManager;
RefPtr<AddressSpace> AddressSpace::ForRoot() {
@ -52,9 +50,6 @@ uint64_t* AddressSpace::AllocateKernelStack() {
}
bool AddressSpace::HandlePageFault(uint64_t vaddr) {
#if K_VMAS_DEBUG
dbgln("[VMAS] Page Fault!");
#endif
MemoryMapping* mapping = GetMemoryMappingForAddr(vaddr);
if (mapping == nullptr) {
return false;
@ -65,9 +60,7 @@ bool AddressSpace::HandlePageFault(uint64_t vaddr) {
dbgln("WARN: Memory object returned invalid physical addr.");
return false;
}
#if K_VMAS_DEBUG
dbgln("[VMAS] Mapping P(%m) at V(%m)", physical_addr, vaddr);
#endif
dbgln("Mapping P(%m) at V(%m)", physical_addr, vaddr);
MapPage(cr3_, vaddr, physical_addr);
return true;
}

View File

@ -4,14 +4,10 @@
#include "debug/debug.h"
#include "memory/physical_memory.h"
#define K_MEM_DEBUG 0
MemoryObject::MemoryObject(uint64_t size) : size_(size) {
if ((size & 0xFFF) != 0) {
size_ = (size & ~0xFFF) + 0x1000;
#if K_MEM_DEBUG
dbgln("MemoryObject: aligned %x to %x", size, size_);
#endif
}
// FIXME: Do this lazily.
uint64_t num_pages = size_ / 0x1000;
@ -60,9 +56,7 @@ uint64_t MemoryObject::PageNumberToPhysAddr(uint64_t page_num) {
}
if (*iter == 0) {
#if K_MEM_DEBUG
dbgln("Allocating page num %u for mem object", page_num);
#endif
*iter = phys_mem::AllocatePage();
}
return *iter;

View File

@ -20,28 +20,11 @@ class MemoryObject : public KernelObject {
void CopyBytesToObject(uint64_t source, uint64_t length);
protected:
// Hacky to avoid linked_list creation.
MemoryObject(uint64_t size, bool) : size_(size) {}
private:
// Always stores the full page-aligned size.
uint64_t size_;
virtual uint64_t PageNumberToPhysAddr(uint64_t page_num);
uint64_t PageNumberToPhysAddr(uint64_t page_num);
LinkedList<uint64_t> phys_page_list_;
};
class FixedMemoryObject : public MemoryObject {
public:
FixedMemoryObject(uint64_t physical_addr, uint64_t size)
: MemoryObject(size, true), physical_addr_(physical_addr) {}
private:
uint64_t physical_addr_;
uint64_t PageNumberToPhysAddr(uint64_t page_num) override {
return physical_addr_ + (0x1000 * page_num);
}
};

View File

@ -6,8 +6,6 @@
#include "object/process.h"
#include "scheduler/scheduler.h"
#define K_THREAD_DEBUG 0
namespace {
extern "C" void jump_user_space(uint64_t rip, uint64_t rsp, uint64_t arg1,
@ -55,18 +53,14 @@ void Thread::Start(uint64_t entry, uint64_t arg1, uint64_t arg2) {
}
void Thread::Init() {
#if K_THREAD_DEBUG
dbgln("Thread start.", pid(), id_);
#endif
uint64_t rsp = process_.vmas()->AllocateUserStack();
SetRsp0(rsp0_start_);
jump_user_space(rip_, rsp, arg1_, arg2_);
}
void Thread::Exit() {
#if K_THREAD_DEBUG
dbgln("Exiting");
#endif
dbgln("Exiting", pid(), id_);
state_ = FINISHED;
process_.CheckState();
gScheduler->Yield();

View File

@ -2,8 +2,6 @@
#include <stdint.h>
#include "boot/acpi.h"
#include "common/msr.h"
#include "debug/debug.h"
#include "include/zcall.h"
#include "include/zerrors.h"
@ -17,8 +15,24 @@
#define STAR 0xC0000081
#define LSTAR 0xC0000082
namespace {
uint64_t GetMSR(uint32_t msr) {
uint32_t lo, hi;
asm("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return (static_cast<uint64_t>(hi) << 32) | lo;
}
void SetMSR(uint32_t msr, uint64_t val) {
uint32_t lo = static_cast<uint32_t>(val);
uint32_t hi = val >> 32;
asm("wrmsr" ::"a"(lo), "d"(hi), "c"(msr));
}
extern "C" void syscall_enter();
} // namespace
// Used by syscall_enter.s
extern "C" uint64_t GetKernelRsp() {
return gScheduler->CurrentThread().Rsp0Start();
@ -130,20 +144,6 @@ z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req,
return Z_OK;
}
z_err_t TempPcieConfigObjectCreate(ZTempPcieConfigObjectCreateResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess();
uint64_t pci_base, pci_size;
dbgln("Getting config");
RET_ERR(GetPciExtendedConfiguration(&pci_base, &pci_size));
dbgln("Making obj");
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(pci_base, pci_size);
dbgln("Adding cap");
resp->vmmo_cap =
curr_proc.AddCapability(StaticCastRefPtr<MemoryObject>(vmmo_ref));
resp->vmmo_size = pci_size;
return Z_OK;
}
z_err_t ChannelCreate(ZChannelCreateResp* resp) {
auto& proc = gScheduler->CurrentProcess();
auto chan_pair = Channel::CreateChannelPair();
@ -201,9 +201,6 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) {
return MemoryObjectCreate(
reinterpret_cast<ZMemoryObjectCreateReq*>(req),
reinterpret_cast<ZMemoryObjectCreateResp*>(resp));
case Z_TEMP_PCIE_CONFIG_OBJECT_CREATE:
return TempPcieConfigObjectCreate(
reinterpret_cast<ZTempPcieConfigObjectCreateResp*>(resp));
case Z_CHANNEL_CREATE:
return ChannelCreate(reinterpret_cast<ZChannelCreateResp*>(resp));
case Z_CHANNEL_SEND:

View File

@ -83,14 +83,6 @@ z_err_t ZMemoryObjectCreate(uint64_t size, uint64_t* vmmo_cap) {
return ret;
}
z_err_t ZTempPcieConfigObjectCreate(uint64_t* vmmo_cap, uint64_t* vmmo_size) {
ZTempPcieConfigObjectCreateResp resp;
z_err_t ret = SysCall2(Z_TEMP_PCIE_CONFIG_OBJECT_CREATE, 0, &resp);
*vmmo_cap = resp.vmmo_cap;
*vmmo_size = resp.vmmo_size;
return ret;
}
z_err_t ZChannelCreate(uint64_t* channel1, uint64_t* channel2) {
ZChannelCreateResp resp;
z_err_t ret = SysCall2(Z_CHANNEL_CREATE, 0, &resp);

View File

@ -46,11 +46,6 @@ struct ZMemoryObjectCreateResp {
uint64_t vmmo_cap;
};
struct ZTempPcieConfigObjectCreateResp {
uint64_t vmmo_cap;
uint64_t vmmo_size;
};
struct ZChannelCreateResp {
uint64_t chan_cap1;
uint64_t chan_cap2;

View File

@ -1,6 +1,5 @@
#include <stdint.h>
#include "boot/acpi.h"
#include "common/gdt.h"
#include "debug/debug.h"
#include "interrupt/interrupt.h"
@ -26,9 +25,6 @@ extern "C" void zion() {
dbgln("[boot] Memory allocations available now.");
dbgln("[boot] Probing Hardware");
ProbeRsdp();
dbgln("[boot] Init Kernel Stack Manager.");
KernelStackManager::Init();