Compare commits
12 Commits
010e261dc7
...
50201fe6df
Author | SHA1 | Date |
---|---|---|
|
50201fe6df | |
|
a2fd14a9a8 | |
|
56789400d7 | |
|
71a601362d | |
|
20dd43cdfb | |
|
bd32e85164 | |
|
3e1e37bf03 | |
|
4bd7f972c1 | |
|
53ff49b265 | |
|
add533071b | |
|
7c9d1075eb | |
|
6f81520918 |
|
@ -9,16 +9,20 @@ 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)
|
||||
|
||||
set(QEMU_CMD qemu-system-x86_64 -d guest_errors -m 1G -serial stdio -hda disk.img)
|
||||
# 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)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT disk.img
|
||||
COMMAND sudo sh ../scripts/build_image.sh disk.img
|
||||
DEPENDS zion test test2
|
||||
DEPENDS zion yellowstone test2
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
|
||||
add_library(libc STATIC
|
||||
add_library(c STATIC
|
||||
src/malloc.cpp
|
||||
src/stdio.cpp
|
||||
)
|
||||
|
||||
target_include_directories(libc
|
||||
target_include_directories(c
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
target_link_libraries(libc
|
||||
target_link_libraries(c
|
||||
zion_lib
|
||||
)
|
||||
|
||||
set_target_properties(libc PROPERTIES
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -mgeneral-regs-only")
|
||||
set_target_properties(c PROPERTIES
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}")
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#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);
|
|
@ -0,0 +1,116 @@
|
|||
#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;
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
add_library(libcxx STATIC
|
||||
add_library(cxx STATIC
|
||||
src/new.cpp
|
||||
)
|
||||
|
||||
target_include_directories(libcxx
|
||||
target_include_directories(cxx
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
target_link_libraries(libcxx
|
||||
libc
|
||||
target_link_libraries(cxx
|
||||
c
|
||||
zion_lib
|
||||
)
|
||||
|
||||
set_target_properties(libcxx PROPERTIES
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -mgeneral-regs-only")
|
||||
set_target_properties(cxx PROPERTIES
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}")
|
||||
|
|
|
@ -10,12 +10,10 @@ 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 "${_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${_LINK_FLAGS}"
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <stdint.h>
|
||||
#include <zerrors.h>
|
||||
|
||||
void dbgln(const char*);
|
||||
void dbgln(const char* fmt, ...);
|
||||
|
||||
// Checks that the code is ok.
|
||||
// if not exits the process.
|
||||
|
|
|
@ -1,13 +1,29 @@
|
|||
#include "include/mammoth/debug.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <zcall.h>
|
||||
#include <zerrors.h>
|
||||
|
||||
void dbgln(const char* str) {
|
||||
// Safe to ignore the result since right now this doesn't throw.
|
||||
void dbgln_internal(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:
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "mammoth/channel.h"
|
||||
#include "mammoth/debug.h"
|
||||
|
||||
#define MAM_PROC_DEBUG 0
|
||||
|
||||
namespace {
|
||||
|
||||
typedef struct {
|
||||
|
@ -63,19 +65,27 @@ 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;
|
||||
|
@ -87,7 +97,9 @@ 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;
|
||||
|
@ -95,11 +107,15 @@ 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!");
|
||||
|
|
|
@ -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/test efi/sys/test
|
||||
cp sys/yellowstone/yellowstone efi/sys/yellowstone
|
||||
cp sys/test2 efi/sys/test2
|
||||
|
||||
chown drew:drew $1
|
||||
|
|
|
@ -1,30 +1,16 @@
|
|||
|
||||
set(_COMPILE_FLAGS "-ffreestanding -fno-exceptions -mgeneral-regs-only")
|
||||
set(_LINK_FLAGS "-nostdlib")
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||
|
||||
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_subdirectory(yellowstone)
|
||||
|
||||
add_executable(test2
|
||||
test2.cpp)
|
||||
|
||||
target_link_libraries(test2
|
||||
libcxx
|
||||
cxx
|
||||
mammoth_lib)
|
||||
|
||||
set_target_properties(test2
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${_LINK_FLAGS}"
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# System Processes
|
||||
|
||||
Current Processes;
|
||||
|
||||
- **yellowstone**: System Initialization
|
|
@ -0,0 +1,16 @@
|
|||
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}"
|
||||
)
|
|
@ -0,0 +1,100 @@
|
|||
#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");
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void DumpPciEDevices();
|
|
@ -2,11 +2,16 @@
|
|||
#include <mammoth/process.h>
|
||||
#include <zcall.h>
|
||||
|
||||
int main() {
|
||||
dbgln("Testing");
|
||||
#include "hw/pcie.h"
|
||||
|
||||
uint64_t main() {
|
||||
dbgln("Yellowstone Initializing.");
|
||||
uint64_t vaddr;
|
||||
check(ZAddressSpaceMap(Z_INIT_VMAS_SELF, 0, Z_INIT_BOOT_VMMO, &vaddr));
|
||||
check(SpawnProcessFromElfRegion(vaddr));
|
||||
dbgln("Return");
|
||||
|
||||
DumpPciEDevices();
|
||||
|
||||
dbgln("Yellowstone Finished Successfully.");
|
||||
return 0;
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
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
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
#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;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "include/zerrors.h"
|
||||
|
||||
void ProbeRsdp();
|
||||
|
||||
z_err_t GetPciExtendedConfiguration(uint64_t* base, uint64_t* offset);
|
|
@ -36,4 +36,15 @@ 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
|
||||
|
|
|
@ -9,4 +9,6 @@ uint64_t GetHigherHalfDirectMap();
|
|||
|
||||
const limine_module_response& GetModules();
|
||||
|
||||
void* GetRsdpAddr();
|
||||
|
||||
} // namespace boot
|
||||
|
|
|
@ -6,5 +6,5 @@ TIMEOUT=0
|
|||
PROTOCOL=limine
|
||||
|
||||
KERNEL_PATH=boot:///zion
|
||||
MODULE_PATH=boot:///sys/test
|
||||
MODULE_PATH=boot:///sys/yellowstone
|
||||
MODULE_PATH=boot:///sys/test2
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#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));
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint64_t GetMSR(uint32_t msr);
|
||||
void SetMSR(uint32_t msr, uint64_t val);
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#define Z_MEMORY_OBJECT_CREATE 0x30
|
||||
|
||||
#define Z_TEMP_PCIE_CONFIG_OBJECT_CREATE 0x3F
|
||||
|
||||
#define Z_INIT_BOOT_VMMO 0x31
|
||||
|
||||
// IPC Calls
|
||||
|
@ -65,6 +67,8 @@ 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,
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
#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);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
void InspectApic();
|
||||
|
||||
void EnableApic();
|
||||
|
||||
void SignalEOI();
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "common/port.h"
|
||||
#include "debug/debug.h"
|
||||
#include "interrupt/apic.h"
|
||||
#include "memory/kernel_heap.h"
|
||||
#include "scheduler/scheduler.h"
|
||||
|
||||
|
@ -42,6 +43,7 @@ InterruptDescriptor CreateDescriptor(void isr(void)) {
|
|||
}
|
||||
|
||||
struct InterruptFrame {
|
||||
uint64_t cr2;
|
||||
uint64_t rax;
|
||||
uint64_t rbx;
|
||||
uint64_t rcx;
|
||||
|
@ -89,16 +91,14 @@ extern "C" void interrupt_protection_fault(InterruptFrame* frame) {
|
|||
|
||||
extern "C" void isr_page_fault();
|
||||
extern "C" void interrupt_page_fault(InterruptFrame* frame) {
|
||||
dbgln("Page Fault - trying to resolve");
|
||||
uint64_t cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
|
||||
if (gScheduler->CurrentProcess().vmas()->HandlePageFault(cr2)) {
|
||||
dbgln("Handled");
|
||||
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("Unable to handle:");
|
||||
uint64_t err = frame->error_code;
|
||||
}
|
||||
dbgln("Unhandled Page Fault:");
|
||||
if (err & 0x1) {
|
||||
dbgln("Page Protection");
|
||||
} else {
|
||||
|
@ -120,14 +120,10 @@ extern "C" void interrupt_page_fault(InterruptFrame* frame) {
|
|||
}
|
||||
|
||||
dbgln("rip: %m", frame->rip);
|
||||
dbgln("addr: %m", cr2);
|
||||
dbgln("addr: %m", frame->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*) {
|
||||
|
@ -138,20 +134,10 @@ extern "C" void interrupt_timer(InterruptFrame*) {
|
|||
}
|
||||
dbgln("timer: %us", cnt * 50 / 1000);
|
||||
}
|
||||
outb(PIC1_COMMAND, PIC_EOI);
|
||||
SignalEOI();
|
||||
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);
|
||||
|
@ -163,5 +149,5 @@ void InitIdt() {
|
|||
};
|
||||
asm volatile("lidt %0" ::"m"(idtp));
|
||||
|
||||
EnablePic();
|
||||
EnableApic();
|
||||
}
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
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
|
||||
|
@ -26,11 +29,11 @@
|
|||
pop %r8
|
||||
pop %r9
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r10
|
||||
pop %r11
|
||||
pop %r12
|
||||
pop %r13
|
||||
pop %r14
|
||||
pop %r15
|
||||
pop %rbp
|
||||
|
||||
add $8, %rsp # Remove error code.
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "object/thread.h"
|
||||
#include "scheduler/process_manager.h"
|
||||
|
||||
#define K_INIT_DEBUG 0
|
||||
|
||||
namespace {
|
||||
|
||||
typedef struct {
|
||||
|
@ -54,16 +56,20 @@ 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);
|
||||
|
@ -86,12 +92,14 @@ 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) {
|
||||
|
@ -107,7 +115,7 @@ const limine_file& GetInitProgram(const char* path) {
|
|||
|
||||
void LoadInitProgram() {
|
||||
DumpModules();
|
||||
const limine_file& init_prog = GetInitProgram("/sys/test");
|
||||
const limine_file& init_prog = GetInitProgram("/sys/yellowstone");
|
||||
|
||||
RefPtr<Process> proc = Process::Create();
|
||||
gProcMan->InsertProcess(proc);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "boot/boot_info.h"
|
||||
#include "debug/debug.h"
|
||||
|
||||
#define K_PHYS_DEBUG 0
|
||||
|
||||
namespace phys_mem {
|
||||
namespace {
|
||||
|
||||
|
@ -23,13 +25,18 @@ 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);
|
||||
|
@ -109,7 +116,9 @@ 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) {
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "memory/paging_util.h"
|
||||
#include "memory/physical_memory.h"
|
||||
|
||||
#define K_VMAS_DEBUG 0
|
||||
|
||||
extern KernelStackManager* gKernelStackManager;
|
||||
|
||||
RefPtr<AddressSpace> AddressSpace::ForRoot() {
|
||||
|
@ -50,6 +52,9 @@ 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;
|
||||
|
@ -60,7 +65,9 @@ bool AddressSpace::HandlePageFault(uint64_t vaddr) {
|
|||
dbgln("WARN: Memory object returned invalid physical addr.");
|
||||
return false;
|
||||
}
|
||||
dbgln("Mapping P(%m) at V(%m)", physical_addr, vaddr);
|
||||
#if K_VMAS_DEBUG
|
||||
dbgln("[VMAS] Mapping P(%m) at V(%m)", physical_addr, vaddr);
|
||||
#endif
|
||||
MapPage(cr3_, vaddr, physical_addr);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,14 @@
|
|||
#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;
|
||||
|
@ -56,7 +60,9 @@ 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;
|
||||
|
|
|
@ -20,11 +20,28 @@ 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_;
|
||||
|
||||
uint64_t PageNumberToPhysAddr(uint64_t page_num);
|
||||
virtual 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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#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,
|
||||
|
@ -53,14 +55,18 @@ 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() {
|
||||
dbgln("Exiting", pid(), id_);
|
||||
#if K_THREAD_DEBUG
|
||||
dbgln("Exiting");
|
||||
#endif
|
||||
state_ = FINISHED;
|
||||
process_.CheckState();
|
||||
gScheduler->Yield();
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "boot/acpi.h"
|
||||
#include "common/msr.h"
|
||||
#include "debug/debug.h"
|
||||
#include "include/zcall.h"
|
||||
#include "include/zerrors.h"
|
||||
|
@ -15,24 +17,8 @@
|
|||
#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();
|
||||
|
@ -144,6 +130,20 @@ 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,6 +201,9 @@ 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:
|
||||
|
|
|
@ -83,6 +83,14 @@ 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);
|
||||
|
|
|
@ -46,6 +46,11 @@ 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;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "boot/acpi.h"
|
||||
#include "common/gdt.h"
|
||||
#include "debug/debug.h"
|
||||
#include "interrupt/interrupt.h"
|
||||
|
@ -25,6 +26,9 @@ extern "C" void zion() {
|
|||
|
||||
dbgln("[boot] Memory allocations available now.");
|
||||
|
||||
dbgln("[boot] Probing Hardware");
|
||||
ProbeRsdp();
|
||||
|
||||
dbgln("[boot] Init Kernel Stack Manager.");
|
||||
KernelStackManager::Init();
|
||||
|
||||
|
|
Loading…
Reference in New Issue