mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-29 00:27:52 +01:00
pretty up GDT a little, and other stuff
also thanks internet for the boilerplate
This commit is contained in:
@@ -2,7 +2,26 @@
|
|||||||
BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
AccessModifierOffset: -4
|
AccessModifierOffset: -4
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: None
|
AlignConsecutiveAssignments:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveBitFields:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: true
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: false
|
||||||
|
AlignTrailingComments:
|
||||||
|
Kind: Always
|
||||||
|
OverEmptyLines: 2
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
AlignOperands: Align
|
AlignOperands: Align
|
||||||
AlignEscapedNewlines: Right
|
AlignEscapedNewlines: Right
|
||||||
AllowAllArgumentsOnNextLine: false
|
AllowAllArgumentsOnNextLine: false
|
||||||
@@ -57,7 +76,6 @@ SpaceBeforeInheritanceColon: true
|
|||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
SpaceBeforeRangeBasedForLoopColon: false
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 0
|
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
SpacesInCStyleCastParentheses: false
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInContainerLiterals: false
|
SpacesInContainerLiterals: false
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "idt.hpp"
|
#include "idt.hpp"
|
||||||
#include "io.hpp"
|
#include "io.hpp"
|
||||||
|
|
||||||
#define PORT 0x3f8// COM1
|
#define PORT 0x3f8 // COM1
|
||||||
|
|
||||||
void SerialTty::putchar(char c) {
|
void SerialTty::putchar(char c) {
|
||||||
LockGuard guard(mutex);
|
LockGuard guard(mutex);
|
||||||
@@ -27,7 +27,7 @@ void SerialTty::this_pooler() {
|
|||||||
mutex.lock();
|
mutex.lock();
|
||||||
while (true) {
|
while (true) {
|
||||||
bool read_something = false;
|
bool read_something = false;
|
||||||
int r = read();
|
int r = read();
|
||||||
while (r != -1) {
|
while (r != -1) {
|
||||||
read_something = true;
|
read_something = true;
|
||||||
buf.push_back((char) r);
|
buf.push_back((char) r);
|
||||||
@@ -41,10 +41,10 @@ void SerialTty::this_pooler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SerialTty::SerialTty() : Tty() {
|
SerialTty::SerialTty() : Tty() {
|
||||||
outb(PORT + 3, 0x00);// Disable DLAB
|
outb(PORT + 3, 0x00); // Disable DLAB
|
||||||
outb(PORT + 1, 0x01);// Enable data available interrupt
|
outb(PORT + 1, 0x01); // Enable data available interrupt
|
||||||
|
|
||||||
Task *task = new_ktask((void (*)(void))(&SerialTty::this_pooler), "serialpooler", false);
|
Task *task = new_ktask((void (*)(void))(&SerialTty::this_pooler), "serialpooler", false);
|
||||||
task->frame.rdi = reinterpret_cast<uint64_t>(this);
|
task->frame.rdi = reinterpret_cast<uint64_t>(this);
|
||||||
start_task(task);
|
start_task(task);
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,13 @@
|
|||||||
|
|
||||||
class SerialTty : public Tty {
|
class SerialTty : public Tty {
|
||||||
// TODO: Possibly there should be 2 mutexes?
|
// TODO: Possibly there should be 2 mutexes?
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
CV readercv;
|
CV readercv;
|
||||||
CV isrcv;
|
CV isrcv;
|
||||||
static void isr(void *tty);
|
static void isr(void *tty);
|
||||||
|
|
||||||
void this_isr();
|
void this_isr();
|
||||||
void this_pooler();
|
void this_pooler();
|
||||||
CircularBuffer<char, 512> buf;
|
CircularBuffer<char, 512> buf;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -28,4 +28,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_SERIALTTY_HPP
|
#endif //OS2_SERIALTTY_HPP
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ real_start() {
|
|||||||
extern "C" void _start(void) {
|
extern "C" void _start(void) {
|
||||||
_sse_setup();
|
_sse_setup();
|
||||||
barrier();
|
barrier();
|
||||||
gdt_setup();
|
Arch::GDT::gdt_setup();
|
||||||
barrier();
|
barrier();
|
||||||
idt_init();
|
idt_init();
|
||||||
barrier();
|
barrier();
|
||||||
@@ -71,9 +71,9 @@ extern "C" void _start(void) {
|
|||||||
KERN_AddressSpace->map((void *) (kernel_virt_base + i * PAGE_SIZE), (void *) (kernel_phys_base + i * PAGE_SIZE), PAGE_RW | PAGE_USER);
|
KERN_AddressSpace->map((void *) (kernel_virt_base + i * PAGE_SIZE), (void *) (kernel_phys_base + i * PAGE_SIZE), PAGE_RW | PAGE_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t real_new_cr3 = (uint64_t) HHDM_V2P(KERN_AddressSpace_PML4);
|
uint64_t real_new_cr3 = (uint64_t) HHDM_V2P(KERN_AddressSpace_PML4);
|
||||||
uint64_t *new_stack_top = &KERN_stack[KERN_STACK_SIZE - 1]; // Don't forget in which direction the stack grows...
|
uint64_t *new_stack_top = &KERN_stack[KERN_STACK_SIZE - 1]; // Don't forget in which direction the stack grows...
|
||||||
new_stack_top = reinterpret_cast<uint64_t *>(((uint64_t) new_stack_top) & (~0xFULL));// correct alignment for sse
|
new_stack_top = reinterpret_cast<uint64_t *>(((uint64_t) new_stack_top) & (~0xFULL)); // correct alignment for sse
|
||||||
|
|
||||||
barrier();
|
barrier();
|
||||||
__asm__ volatile("movq %[new_stack_top], %%rsp; movq %[real_new_cr3], %%cr3; call real_start"
|
__asm__ volatile("movq %[new_stack_top], %%rsp; movq %[real_new_cr3], %%cr3; call real_start"
|
||||||
|
|||||||
@@ -74,16 +74,19 @@ gdt_code_user:
|
|||||||
db PRESENT | USER | NOT_SYS | EXEC | RW ; Access
|
db PRESENT | USER | NOT_SYS | EXEC | RW ; Access
|
||||||
db GRAN_4K | LONG_MODE | 0xF ; Flags & Limit (high, bits 16-19)
|
db GRAN_4K | LONG_MODE | 0xF ; Flags & Limit (high, bits 16-19)
|
||||||
db 0 ; Base (high, bits 24-31)
|
db 0 ; Base (high, bits 24-31)
|
||||||
|
|
||||||
global gdt_tss:data
|
global gdt_tss:data
|
||||||
gdt_tss:
|
gdt_tss:
|
||||||
dq 0x00000000 ;TODO
|
dq 0x00000000
|
||||||
dq 0x00000000
|
dq 0x00000000
|
||||||
global gdt_tss_user:data
|
global gdt_tss_user:data
|
||||||
gdt_tss_user:
|
gdt_tss_user:
|
||||||
dq 0x00000000 ;TODO
|
|
||||||
dq 0x00000000
|
dq 0x00000000
|
||||||
|
dq 0x00000000
|
||||||
|
|
||||||
global gdt_end:data
|
global gdt_end:data
|
||||||
gdt_end:
|
gdt_end:
|
||||||
|
|
||||||
global gdtr:data
|
global gdtr:data
|
||||||
gdtr:
|
gdtr:
|
||||||
dw gdt_end - gdt_null - 1
|
dw gdt_end - gdt_null - 1
|
||||||
@@ -93,20 +96,23 @@ section .text
|
|||||||
global _gdt_setup:function (_gdt_setup.end - _gdt_setup)
|
global _gdt_setup:function (_gdt_setup.end - _gdt_setup)
|
||||||
_gdt_setup:
|
_gdt_setup:
|
||||||
LGDT [gdtr]
|
LGDT [gdtr]
|
||||||
; Reload CS register:
|
; Reload CS register
|
||||||
PUSH (gdt_code - gdt_null); Push code segment to stack, 0x08 is a stand-in for your code segment
|
PUSH (gdt_code - gdt_null) ; Push code segment to stack
|
||||||
LEA RAX, [rel .flush] ; Load address of .reload_CS into RAX
|
LEA RAX, [rel .flush] ; Load address of .flush into RAX
|
||||||
PUSH RAX ; Push this value to the stack
|
PUSH RAX ; Push this value to the stack
|
||||||
RETFQ ; Perform a far return, RETFQ or LRETQ depending on syntax
|
RETFQ ; Perform a far return, RETFQ or LRETQ depending on syntax
|
||||||
|
|
||||||
.flush:
|
.flush:
|
||||||
|
|
||||||
; Reload data segment registers
|
; Reload data segment registers
|
||||||
MOV AX, (gdt_data - gdt_null) ; 0x10 is a stand-in for your data segment
|
MOV AX, (gdt_data - gdt_null)
|
||||||
MOV DS, AX
|
MOV DS, AX
|
||||||
MOV ES, AX
|
MOV ES, AX
|
||||||
MOV FS, AX
|
MOV FS, AX
|
||||||
MOV GS, AX
|
MOV GS, AX
|
||||||
MOV SS, AX
|
MOV SS, AX
|
||||||
MOV AX, (gdt_tss - gdt_null)
|
MOV AX, (gdt_tss - gdt_null)
|
||||||
|
|
||||||
ltr AX
|
ltr AX
|
||||||
RET
|
RET
|
||||||
.end:
|
.end:
|
||||||
|
|||||||
@@ -3,37 +3,45 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "gdt.hpp"
|
#include "gdt.hpp"
|
||||||
|
#include "asserts.hpp"
|
||||||
#include "misc.hpp"
|
#include "misc.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
namespace Arch::GDT {
|
||||||
|
static tss_entry_struct tss_entry;
|
||||||
|
static tss_entry_struct tss_entry_user;
|
||||||
|
|
||||||
static struct tss_entry_struct tss_entry;
|
static constexpr size_t INT_STACK_SIZE = 16384;
|
||||||
static struct tss_entry_struct tss_entry_user;
|
static constexpr size_t RSP_STACK_SIZE = 16384;
|
||||||
|
|
||||||
#define INT_STACK_SIZE 16384
|
static uint64_t int_stack[INT_STACK_SIZE];
|
||||||
#define RSP_STACK_SIZE 16384
|
static uint64_t rsp_stack[RSP_STACK_SIZE];
|
||||||
static uint64_t int_stack[INT_STACK_SIZE];
|
|
||||||
static uint64_t rsp_stack[RSP_STACK_SIZE];
|
|
||||||
|
|
||||||
void gdt_setup() {
|
//
|
||||||
uint32_t tss_limit = sizeof(tss_entry);
|
void gdt_setup() {
|
||||||
uint64_t tss_base = (uint64_t) &tss_entry;
|
uint32_t tss_limit = sizeof(tss_entry);
|
||||||
|
uint64_t tss_base = (uint64_t) &tss_entry;
|
||||||
|
|
||||||
gdt_tss.limit_low = tss_limit & 0xFFFF;
|
gdt_tss.limit_low = tss_limit & 0xFFFF;
|
||||||
gdt_tss.base_low = tss_base & 0xFFFFFF;
|
gdt_tss.base_low = tss_base & 0xFFFFFF;
|
||||||
gdt_tss.type = 0b1001;// Available 64 bit TSS
|
gdt_tss.type = 0b1001; // Available 64 bit TSS
|
||||||
gdt_tss.zero = 0;
|
gdt_tss.zero = 0;
|
||||||
gdt_tss.DPL = 0;
|
gdt_tss.DPL = 0;
|
||||||
gdt_tss.present = 1;
|
gdt_tss.present = 1;
|
||||||
gdt_tss.limit_high = (tss_limit >> 16) & 0xF;
|
gdt_tss.limit_high = (tss_limit >> 16) & 0xF;
|
||||||
gdt_tss.available = 0;
|
gdt_tss.available = 0;
|
||||||
gdt_tss.unused = 0;
|
gdt_tss.unused = 0;
|
||||||
gdt_tss.gran = 0;
|
gdt_tss.gran = 0;
|
||||||
gdt_tss.base_high = (tss_base >> 24) & 0xFFFFFFFFFF;
|
gdt_tss.base_high = (tss_base >> 24) & 0xFFFFFFFFFF;
|
||||||
|
|
||||||
tss_entry.ist1 = (((uintptr_t) int_stack + (INT_STACK_SIZE - 9) - 1) & (~0xFULL)) + 8;
|
tss_entry.ist1 = (((uintptr_t) int_stack + (INT_STACK_SIZE - 9) - 1) & (~0xFULL)) + 8;
|
||||||
if ((tss_entry.ist1 & 0xFULL) != 8) _hcf();
|
assert((tss_entry.ist1 & 0xFULL) == 8);
|
||||||
tss_entry.rsp0 = (((uintptr_t) rsp_stack + (RSP_STACK_SIZE - 9) - 1) & (~0xFULL)) + 8;
|
|
||||||
if ((tss_entry.rsp0 & 0xFULL) != 8) _hcf();
|
|
||||||
|
|
||||||
barrier();// The asm function might clobber registers
|
tss_entry.rsp0 = (((uintptr_t) rsp_stack + (RSP_STACK_SIZE - 9) - 1) & (~0xFULL)) + 8;
|
||||||
_gdt_setup();
|
assert((tss_entry.rsp0 & 0xFULL) == 8);
|
||||||
}
|
|
||||||
|
barrier(); // The asm function might clobber registers
|
||||||
|
_gdt_setup();
|
||||||
|
barrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Arch::GDT
|
||||||
@@ -3,78 +3,89 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
struct gdt_entry_bits {
|
namespace Arch::GDT {
|
||||||
unsigned int limit_low : 16;
|
struct gdt_entry_bits {
|
||||||
unsigned int base_low : 24;
|
unsigned int limit_low : 16;
|
||||||
unsigned int accessed : 1;
|
unsigned int base_low : 24;
|
||||||
unsigned int read_write : 1; // readable for code, writable for data
|
unsigned int accessed : 1;
|
||||||
unsigned int conforming_expand_down : 1;// conforming for code, expand down for data
|
unsigned int read_write : 1; // readable for code, writable for data
|
||||||
unsigned int code : 1; // 1 for code, 0 for data
|
unsigned int conforming_expand_down : 1; // conforming for code, expand down for data
|
||||||
unsigned int code_data_segment : 1; // should be 1 for everything but TSS and LDT
|
unsigned int code : 1; // 1 for code, 0 for data
|
||||||
unsigned int DPL : 2; // privilege level
|
unsigned int code_data_segment : 1; // should be 1 for everything but TSS and LDT
|
||||||
unsigned int present : 1;
|
unsigned int DPL : 2; // privilege level
|
||||||
unsigned int limit_high : 4;
|
unsigned int present : 1;
|
||||||
unsigned int available : 1;// only used in software; has no effect on hardware
|
unsigned int limit_high : 4;
|
||||||
unsigned int long_mode : 1;
|
unsigned int available : 1; // only used in software; has no effect on hardware
|
||||||
unsigned int big : 1; // 32-bit opcodes for code, uint32_t stack for data
|
unsigned int long_mode : 1;
|
||||||
unsigned int gran : 1;// 1 to use 4k page addressing, 0 for byte addressing
|
unsigned int big : 1; // 32-bit opcodes for code, uint32_t stack for data
|
||||||
unsigned int base_high : 8;
|
unsigned int gran : 1; // 1 to use 4k page addressing, 0 for byte addressing
|
||||||
} __attribute__((packed));
|
unsigned int base_high : 8;
|
||||||
|
|
||||||
struct gdt_tss_entry_bits {
|
//
|
||||||
unsigned int limit_low : 16;
|
uint64_t selector() volatile;
|
||||||
unsigned int base_low : 24;
|
} __attribute__((packed));
|
||||||
unsigned int type : 4;
|
|
||||||
unsigned int zero : 1;
|
|
||||||
unsigned int DPL : 2;
|
|
||||||
unsigned int present : 1;
|
|
||||||
unsigned int limit_high : 4;
|
|
||||||
unsigned int available : 1;
|
|
||||||
unsigned int unused : 2;
|
|
||||||
unsigned int gran : 1;
|
|
||||||
uint64_t base_high : 40;
|
|
||||||
unsigned int zeros : 32;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct tss_entry_struct {
|
struct gdt_tss_entry_bits {
|
||||||
uint32_t reserved;
|
unsigned int limit_low : 16;
|
||||||
uint64_t rsp0;
|
unsigned int base_low : 24;
|
||||||
uint64_t rsp1;
|
unsigned int type : 4;
|
||||||
uint64_t rsp2;
|
unsigned int zero : 1;
|
||||||
uint64_t reserved2;
|
unsigned int DPL : 2;
|
||||||
uint64_t ist1;
|
unsigned int present : 1;
|
||||||
uint64_t ist2;
|
unsigned int limit_high : 4;
|
||||||
uint64_t ist3;
|
unsigned int available : 1;
|
||||||
uint64_t ist4;
|
unsigned int unused : 2;
|
||||||
uint64_t ist5;
|
unsigned int gran : 1;
|
||||||
uint64_t ist6;
|
uint64_t base_high : 40;
|
||||||
uint64_t ist7;
|
unsigned int zeros : 32;
|
||||||
uint64_t reserved3;
|
} __attribute__((packed));
|
||||||
uint32_t reserved4;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
extern "C" void _gdt_setup();
|
struct tss_entry_struct {
|
||||||
void gdt_setup();
|
uint32_t reserved;
|
||||||
|
uint64_t rsp0;
|
||||||
|
uint64_t rsp1;
|
||||||
|
uint64_t rsp2;
|
||||||
|
uint64_t reserved2;
|
||||||
|
uint64_t ist1;
|
||||||
|
uint64_t ist2;
|
||||||
|
uint64_t ist3;
|
||||||
|
uint64_t ist4;
|
||||||
|
uint64_t ist5;
|
||||||
|
uint64_t ist6;
|
||||||
|
uint64_t ist7;
|
||||||
|
uint64_t reserved3;
|
||||||
|
uint32_t reserved4;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
extern volatile struct gdt_entry_bits gdt_null;
|
void gdt_setup();
|
||||||
extern volatile struct gdt_entry_bits gdt_code_16;
|
|
||||||
extern volatile struct gdt_entry_bits gdt_data_16;
|
|
||||||
extern volatile struct gdt_entry_bits gdt_code_32;
|
|
||||||
extern volatile struct gdt_entry_bits gdt_data_32;
|
|
||||||
extern volatile struct gdt_entry_bits gdt_code;
|
|
||||||
extern volatile struct gdt_entry_bits gdt_data;
|
|
||||||
extern volatile struct gdt_entry_bits gdt_code_user;
|
|
||||||
extern volatile struct gdt_entry_bits gdt_data_user;
|
|
||||||
extern volatile struct gdt_tss_entry_bits gdt_tss;
|
|
||||||
extern volatile struct gdt_tss_entry_bits gdt_tss_user;
|
|
||||||
|
|
||||||
extern volatile struct gdt_entry_bits gdt_end;/// It is not a pointer!
|
extern "C" {
|
||||||
|
void _gdt_setup();
|
||||||
|
extern volatile struct gdt_entry_bits gdt_null;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_code_16;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_data_16;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_code_32;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_data_32;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_code;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_data;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_code_user;
|
||||||
|
extern volatile struct gdt_entry_bits gdt_data_user;
|
||||||
|
extern volatile struct gdt_tss_entry_bits gdt_tss;
|
||||||
|
extern volatile struct gdt_tss_entry_bits gdt_tss_user;
|
||||||
|
|
||||||
extern struct {
|
extern volatile struct gdt_entry_bits gdt_end; // It is not a pointer!
|
||||||
uint16_t limit;
|
|
||||||
uint64_t base;
|
extern struct {
|
||||||
} gdtr;
|
uint16_t limit;
|
||||||
|
uint64_t base;
|
||||||
|
} __attribute__((packed)) gdtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t gdt_entry_bits::selector() volatile {
|
||||||
|
return (((uint64_t) this) - ((uint64_t) &gdt_null));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Arch::GDT
|
||||||
|
|
||||||
#define GDTSEL(x) (((uint64_t) &x) - ((uint64_t) &gdt_null))
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -12,4 +12,4 @@ extern uint64_t KERN_stack[KERN_STACK_SIZE] __attribute__((aligned(16)));
|
|||||||
|
|
||||||
#define TASK_POINTER 0x10000
|
#define TASK_POINTER 0x10000
|
||||||
|
|
||||||
#endif//OS1_GLOBALS_H
|
#endif //OS1_GLOBALS_H
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
#include "task.hpp"
|
#include "task.hpp"
|
||||||
#include "timer.hpp"
|
#include "timer.hpp"
|
||||||
|
|
||||||
__attribute__((aligned(0x10))) static idt_entry_t idt[256];// Create an array of IDT entries; aligned for performance
|
__attribute__((aligned(0x10))) static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance
|
||||||
static idtr_t idtr;
|
static idtr_t idtr;
|
||||||
|
|
||||||
extern "C" __attribute__((noreturn)) void exception_handler(void) {
|
extern "C" __attribute__((noreturn)) void exception_handler(void) {
|
||||||
_hcf();
|
_hcf();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,20 +33,20 @@ extern "C" void pic2_irq_6();
|
|||||||
extern "C" void pic2_irq_7();
|
extern "C" void pic2_irq_7();
|
||||||
|
|
||||||
|
|
||||||
void idt_set_descriptor(uint8_t vector, void (*isr)(), uint8_t flags) {
|
void idt_set_descriptor(uint8_t vector, void (*isr)(), uint8_t flags) {
|
||||||
idt_entry_t *descriptor = &idt[vector];
|
idt_entry_t *descriptor = &idt[vector];
|
||||||
|
|
||||||
descriptor->isr_low = (uint64_t) isr & 0xFFFF;
|
descriptor->isr_low = (uint64_t) isr & 0xFFFF;
|
||||||
descriptor->kernel_cs = GDTSEL(gdt_code);
|
descriptor->kernel_cs = Arch::GDT::gdt_code.selector();
|
||||||
descriptor->ist = 1;
|
descriptor->ist = 1;
|
||||||
descriptor->attributes = flags;
|
descriptor->attributes = flags;
|
||||||
descriptor->isr_mid = ((uint64_t) isr >> 16) & 0xFFFF;
|
descriptor->isr_mid = ((uint64_t) isr >> 16) & 0xFFFF;
|
||||||
descriptor->isr_high = ((uint64_t) isr >> 32) & 0xFFFFFFFF;
|
descriptor->isr_high = ((uint64_t) isr >> 32) & 0xFFFFFFFF;
|
||||||
descriptor->reserved = 0;
|
descriptor->reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_init() {
|
void idt_init() {
|
||||||
idtr.base = (uintptr_t) &idt[0];
|
idtr.base = (uintptr_t) &idt[0];
|
||||||
idtr.limit = (uint16_t) ((uint64_t) &idt[255] - (uint64_t) &idt[0]);
|
idtr.limit = (uint16_t) ((uint64_t) &idt[255] - (uint64_t) &idt[0]);
|
||||||
|
|
||||||
for (uint8_t vector = 0; vector < 32; vector++) {
|
for (uint8_t vector = 0; vector < 32; vector++) {
|
||||||
@@ -74,8 +74,8 @@ void idt_init() {
|
|||||||
barrier();
|
barrier();
|
||||||
__asm__ volatile("lidt %0"
|
__asm__ volatile("lidt %0"
|
||||||
:
|
:
|
||||||
: "m"(idtr));// load the new IDT
|
: "m"(idtr)); // load the new IDT
|
||||||
__asm__ volatile("sti"); // set the interrupt flag
|
__asm__ volatile("sti"); // set the interrupt flag
|
||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
PIC_init();
|
PIC_init();
|
||||||
@@ -91,33 +91,33 @@ void PIC_sendEOI(unsigned char irq) {
|
|||||||
void PIC_init() {
|
void PIC_init() {
|
||||||
unsigned char a1, a2;
|
unsigned char a1, a2;
|
||||||
|
|
||||||
a1 = inb(PIC1_DATA);// save masks
|
a1 = inb(PIC1_DATA); // save masks
|
||||||
a2 = inb(PIC2_DATA);
|
a2 = inb(PIC2_DATA);
|
||||||
|
|
||||||
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);// starts the initialization sequence (in cascade mode)
|
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode)
|
||||||
io_wait();
|
io_wait();
|
||||||
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
|
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||||
io_wait();
|
io_wait();
|
||||||
outb(PIC1_DATA, PIC1_OFFSET);// ICW2: Master PIC vector offset
|
outb(PIC1_DATA, PIC1_OFFSET); // ICW2: Master PIC vector offset
|
||||||
io_wait();
|
io_wait();
|
||||||
outb(PIC2_DATA, PIC2_OFFSET);// ICW2: Slave PIC vector offset
|
outb(PIC2_DATA, PIC2_OFFSET); // ICW2: Slave PIC vector offset
|
||||||
io_wait();
|
io_wait();
|
||||||
outb(PIC1_DATA, 4);// ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
|
outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
|
||||||
io_wait();
|
io_wait();
|
||||||
outb(PIC2_DATA, 2);// ICW3: tell Slave PIC its cascade identity (0000 0010)
|
outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
|
||||||
io_wait();
|
io_wait();
|
||||||
|
|
||||||
outb(PIC1_DATA, ICW4_8086);// ICW4: have the PICs use 8086 mode (and not 8080 mode)
|
outb(PIC1_DATA, ICW4_8086); // ICW4: have the PICs use 8086 mode (and not 8080 mode)
|
||||||
io_wait();
|
io_wait();
|
||||||
outb(PIC2_DATA, ICW4_8086);
|
outb(PIC2_DATA, ICW4_8086);
|
||||||
io_wait();
|
io_wait();
|
||||||
|
|
||||||
outb(PIC1_DATA, a1);// restore saved masks.
|
outb(PIC1_DATA, a1); // restore saved masks.
|
||||||
outb(PIC2_DATA, a2);
|
outb(PIC2_DATA, a2);
|
||||||
}
|
}
|
||||||
void IRQ_set_mask(unsigned char IRQline) {
|
void IRQ_set_mask(unsigned char IRQline) {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
if (IRQline < 8) {
|
if (IRQline < 8) {
|
||||||
port = PIC1_DATA;
|
port = PIC1_DATA;
|
||||||
@@ -131,7 +131,7 @@ void IRQ_set_mask(unsigned char IRQline) {
|
|||||||
|
|
||||||
void IRQ_clear_mask(unsigned char IRQline) {
|
void IRQ_clear_mask(unsigned char IRQline) {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
if (IRQline < 8) {
|
if (IRQline < 8) {
|
||||||
port = PIC1_DATA;
|
port = PIC1_DATA;
|
||||||
@@ -164,9 +164,9 @@ uint16_t pic_get_isr(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int_handler_t handlers[256];
|
static int_handler_t handlers[256];
|
||||||
static void *handlers_args[256];
|
static void *handlers_args[256];
|
||||||
|
|
||||||
extern "C" void pic1_irq_real_0(struct task_frame *frame) {
|
extern "C" void pic1_irq_real_0(struct task_frame *frame) {
|
||||||
timer_tick();
|
timer_tick();
|
||||||
switch_task(frame);
|
switch_task(frame);
|
||||||
PIC_sendEOI(0);
|
PIC_sendEOI(0);
|
||||||
@@ -232,6 +232,6 @@ extern "C" void pic2_irq_real_7() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void attach_interrupt(unsigned num, int_handler_t handler, void *firstarg) {
|
void attach_interrupt(unsigned num, int_handler_t handler, void *firstarg) {
|
||||||
handlers[num] = handler;
|
handlers[num] = handler;
|
||||||
handlers_args[num] = firstarg;
|
handlers_args[num] = firstarg;
|
||||||
}
|
}
|
||||||
@@ -4,47 +4,47 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define PIC1 0x20 /* IO base address for master PIC */
|
#define PIC1 0x20 /* IO base address for master PIC */
|
||||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||||
#define PIC1_COMMAND PIC1
|
#define PIC1_COMMAND PIC1
|
||||||
#define PIC1_DATA (PIC1 + 1)
|
#define PIC1_DATA (PIC1 + 1)
|
||||||
#define PIC2_COMMAND PIC2
|
#define PIC2_COMMAND PIC2
|
||||||
#define PIC2_DATA (PIC2 + 1)
|
#define PIC2_DATA (PIC2 + 1)
|
||||||
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||||
|
|
||||||
#define ICW1_ICW4 0x01 /* Indicates that ICW4 will be present */
|
#define ICW1_ICW4 0x01 /* Indicates that ICW4 will be present */
|
||||||
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||||
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||||
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||||
#define ICW1_INIT 0x10 /* Initialization - required! */
|
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||||
|
|
||||||
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||||
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||||
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||||
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
|
|
||||||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
||||||
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
||||||
|
|
||||||
#define PIC1_OFFSET 0x20
|
#define PIC1_OFFSET 0x20
|
||||||
#define PIC2_OFFSET 0x28
|
#define PIC2_OFFSET 0x28
|
||||||
|
|
||||||
void PIC_sendEOI(unsigned char irq);
|
void PIC_sendEOI(unsigned char irq);
|
||||||
void PIC_init();
|
void PIC_init();
|
||||||
void IRQ_set_mask(unsigned char IRQline);
|
void IRQ_set_mask(unsigned char IRQline);
|
||||||
void IRQ_clear_mask(unsigned char IRQline);
|
void IRQ_clear_mask(unsigned char IRQline);
|
||||||
uint16_t pic_get_irr(void);
|
uint16_t pic_get_irr(void);
|
||||||
uint16_t pic_get_isr(void);
|
uint16_t pic_get_isr(void);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||||
uint16_t kernel_cs;// The GDT segment selector that the CPU will load into CS before calling the ISR
|
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
|
||||||
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to zero for now
|
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to zero for now
|
||||||
uint8_t attributes;// Type and attributes; see the IDT page
|
uint8_t attributes; // Type and attributes; see the IDT page
|
||||||
uint16_t isr_mid; // The higher 16 bits of the lower 32 bits of the ISR's address
|
uint16_t isr_mid; // The higher 16 bits of the lower 32 bits of the ISR's address
|
||||||
uint32_t isr_high; // The higher 32 bits of the ISR's address
|
uint32_t isr_high; // The higher 32 bits of the ISR's address
|
||||||
uint32_t reserved; // Set to zero
|
uint32_t reserved; // Set to zero
|
||||||
} __attribute__((packed)) idt_entry_t;
|
} __attribute__((packed)) idt_entry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -57,7 +57,7 @@ typedef struct {
|
|||||||
// Assuming the compiler understands that this is pushed on the stack in the correct order
|
// Assuming the compiler understands that this is pushed on the stack in the correct order
|
||||||
struct task_frame {
|
struct task_frame {
|
||||||
uint64_t guard;
|
uint64_t guard;
|
||||||
uint64_t guard2;// To keep stack aligned after pushaq
|
uint64_t guard2; // To keep stack aligned after pushaq
|
||||||
|
|
||||||
uint64_t r15;
|
uint64_t r15;
|
||||||
uint64_t r14;
|
uint64_t r14;
|
||||||
@@ -84,16 +84,16 @@ struct task_frame {
|
|||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
extern "C" void exception_handler(void);
|
extern "C" void exception_handler(void);
|
||||||
|
|
||||||
void idt_set_descriptor(uint8_t vector, void (*isr)(), uint8_t flags);
|
void idt_set_descriptor(uint8_t vector, void (*isr)(), uint8_t flags);
|
||||||
|
|
||||||
void idt_init(void);
|
void idt_init(void);
|
||||||
|
|
||||||
extern void (*isr_stub_table[])();
|
extern void (*isr_stub_table[])();
|
||||||
|
|
||||||
using int_handler_t = void (*)(void *);
|
using int_handler_t = void (*)(void *);
|
||||||
|
|
||||||
void attach_interrupt(unsigned num, int_handler_t handler, void *arg);
|
void attach_interrupt(unsigned num, int_handler_t handler, void *arg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -27,4 +27,4 @@ static inline void io_wait(void) {
|
|||||||
outb(0x80, 0);
|
outb(0x80, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif//OS1_IO_H
|
#endif //OS1_IO_H
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ void ktask2() {
|
|||||||
// Note: we assume the framebuffer model is RGB with 32-bit pixels.
|
// Note: we assume the framebuffer model is RGB with 32-bit pixels.
|
||||||
for (size_t i = 0; i < 100; i++) {
|
for (size_t i = 0; i < 100; i++) {
|
||||||
sleep_self(25000);
|
sleep_self(25000);
|
||||||
uint32_t *fb_ptr = static_cast<uint32_t *>(framebuffer->address);
|
uint32_t *fb_ptr = static_cast<uint32_t *>(framebuffer->address);
|
||||||
fb_ptr[i * (framebuffer->pitch / 4) + i + 100] = c ? 0 : 0xFFFFFF;
|
fb_ptr[i * (framebuffer->pitch / 4) + i + 100] = c ? 0 : 0xFFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ void ktask() {
|
|||||||
// Note: we assume the framebuffer model is RGB with 32-bit pixels.
|
// Note: we assume the framebuffer model is RGB with 32-bit pixels.
|
||||||
for (size_t i = 0; i < 100; i++) {
|
for (size_t i = 0; i < 100; i++) {
|
||||||
sleep_self(25000);
|
sleep_self(25000);
|
||||||
uint32_t *fb_ptr = static_cast<uint32_t *>(framebuffer->address);
|
uint32_t *fb_ptr = static_cast<uint32_t *>(framebuffer->address);
|
||||||
fb_ptr[i * (framebuffer->pitch / 4) + i] = c ? 0 : 0xFFFFFF;
|
fb_ptr[i * (framebuffer->pitch / 4) + i] = c ? 0 : 0xFFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,16 +94,16 @@ void freeprinter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void statprinter() {
|
void statprinter() {
|
||||||
SkipList<uint64_t, std::pair<String, uint64_t>> last_times = getTaskTimePerPid();
|
SkipList<uint64_t, std::pair<String, uint64_t>> last_times = getTaskTimePerPid();
|
||||||
std::atomic<uint64_t> last_print_time = micros;
|
std::atomic<uint64_t> last_print_time = micros;
|
||||||
while (1) {
|
while (1) {
|
||||||
sleep_self(1000000);
|
sleep_self(1000000);
|
||||||
uint64_t prev_print_time = last_print_time;
|
uint64_t prev_print_time = last_print_time;
|
||||||
last_print_time = micros;
|
last_print_time = micros;
|
||||||
SkipList<uint64_t, std::pair<String, uint64_t>> prev_times = std::move(last_times);
|
SkipList<uint64_t, std::pair<String, uint64_t>> prev_times = std::move(last_times);
|
||||||
last_times = getTaskTimePerPid();
|
last_times = getTaskTimePerPid();
|
||||||
|
|
||||||
uint64_t slice = last_print_time - prev_print_time;
|
uint64_t slice = last_print_time - prev_print_time;
|
||||||
if (slice == 0) continue;
|
if (slice == 0) continue;
|
||||||
|
|
||||||
for (const auto &t: prev_times) {
|
for (const auto &t: prev_times) {
|
||||||
@@ -134,7 +134,7 @@ void statprinter() {
|
|||||||
|
|
||||||
static Mutex testmutex;
|
static Mutex testmutex;
|
||||||
|
|
||||||
void mtest1() {
|
void mtest1() {
|
||||||
{
|
{
|
||||||
LockGuard l(testmutex);
|
LockGuard l(testmutex);
|
||||||
GlobalTtyManager.all_tty_putstr("Locked1\n");
|
GlobalTtyManager.all_tty_putstr("Locked1\n");
|
||||||
@@ -165,8 +165,8 @@ void mtest3() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stress() {
|
void stress() {
|
||||||
static std::atomic<int> i = 0;
|
static std::atomic<int> i = 0;
|
||||||
int curi = i++;
|
int curi = i++;
|
||||||
if (curi > 1500) remove_self();
|
if (curi > 1500) remove_self();
|
||||||
|
|
||||||
sleep_self(100000 - curi * 10);
|
sleep_self(100000 - curi * 10);
|
||||||
@@ -252,13 +252,13 @@ void dummy_task() {
|
|||||||
extern void (*ctors_begin[])();
|
extern void (*ctors_begin[])();
|
||||||
extern void (*ctors_end[])();
|
extern void (*ctors_end[])();
|
||||||
|
|
||||||
void kmain() {
|
void kmain() {
|
||||||
for (void (**ctor)() = ctors_begin; ctor < ctors_end; ctor++)
|
for (void (**ctor)() = ctors_begin; ctor < ctors_end; ctor++)
|
||||||
(*ctor)();
|
(*ctor)();
|
||||||
|
|
||||||
init_timer();
|
init_timer();
|
||||||
|
|
||||||
srand(micros);// NOLINT
|
srand(micros); // NOLINT
|
||||||
|
|
||||||
new_ktask(ktask_main, "ktask_main");
|
new_ktask(ktask_main, "ktask_main");
|
||||||
new_ktask(dummy_task, "dummy");
|
new_ktask(dummy_task, "dummy");
|
||||||
|
|||||||
@@ -11,15 +11,15 @@
|
|||||||
#include "mutex.hpp"
|
#include "mutex.hpp"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
struct HeapEntry *KERN_HeapBegin;
|
struct HeapEntry *KERN_HeapBegin;
|
||||||
uintptr_t KERN_HeapEnd;// Past the end
|
uintptr_t KERN_HeapEnd; // Past the end
|
||||||
|
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
|
|
||||||
std::atomic<uint64_t> allocated = 0;
|
std::atomic<uint64_t> allocated = 0;
|
||||||
std::atomic<uint64_t> used = 0;
|
std::atomic<uint64_t> used = 0;
|
||||||
|
|
||||||
uint64_t get_heap_allocated() {
|
uint64_t get_heap_allocated() {
|
||||||
return allocated;
|
return allocated;
|
||||||
}
|
}
|
||||||
uint64_t get_heap_used() {
|
uint64_t get_heap_used() {
|
||||||
@@ -28,17 +28,17 @@ uint64_t get_heap_used() {
|
|||||||
|
|
||||||
static Mutex kmem_lock;
|
static Mutex kmem_lock;
|
||||||
|
|
||||||
void init_kern_heap() {
|
void init_kern_heap() {
|
||||||
KERN_HeapBegin = static_cast<HeapEntry *>(get4k());
|
KERN_HeapBegin = static_cast<HeapEntry *>(get4k());
|
||||||
allocated.fetch_add(PAGE_SIZE);
|
allocated.fetch_add(PAGE_SIZE);
|
||||||
KERN_HeapBegin->magic = KERN_HeapMagicFree;
|
KERN_HeapBegin->magic = KERN_HeapMagicFree;
|
||||||
KERN_HeapBegin->len = PAGE_SIZE - (sizeof(struct HeapEntry));
|
KERN_HeapBegin->len = PAGE_SIZE - (sizeof(struct HeapEntry));
|
||||||
KERN_HeapBegin->next = NULL;
|
KERN_HeapBegin->next = NULL;
|
||||||
KERN_HeapBegin->prev = NULL;
|
KERN_HeapBegin->prev = NULL;
|
||||||
KERN_AddressSpace->map((void *) KERN_HeapVirtBegin, (void *) HHDM_V2P(KERN_HeapBegin), PAGE_RW);
|
KERN_AddressSpace->map((void *) KERN_HeapVirtBegin, (void *) HHDM_V2P(KERN_HeapBegin), PAGE_RW);
|
||||||
KERN_HeapBegin = (struct HeapEntry *) KERN_HeapVirtBegin;
|
KERN_HeapBegin = (struct HeapEntry *) KERN_HeapVirtBegin;
|
||||||
KERN_HeapEnd = (KERN_HeapVirtBegin + PAGE_SIZE);
|
KERN_HeapEnd = (KERN_HeapVirtBegin + PAGE_SIZE);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void extend_heap(size_t n_pages) {
|
static void extend_heap(size_t n_pages) {
|
||||||
@@ -67,10 +67,10 @@ struct HeapEntry *split_entry(struct HeapEntry *what, size_t n) {
|
|||||||
assert(what->len <= allocated);
|
assert(what->len <= allocated);
|
||||||
|
|
||||||
new_entry->magic = KERN_HeapMagicFree;
|
new_entry->magic = KERN_HeapMagicFree;
|
||||||
new_entry->next = what->next;
|
new_entry->next = what->next;
|
||||||
new_entry->prev = what;
|
new_entry->prev = what;
|
||||||
new_entry->len = what->len - n - sizeof(struct HeapEntry);
|
new_entry->len = what->len - n - sizeof(struct HeapEntry);
|
||||||
what->len = n;
|
what->len = n;
|
||||||
|
|
||||||
if (new_entry->next)
|
if (new_entry->next)
|
||||||
new_entry->next->prev = new_entry;
|
new_entry->next->prev = new_entry;
|
||||||
@@ -96,7 +96,7 @@ void *kmalloc(size_t n) {
|
|||||||
|
|
||||||
struct HeapEntry *res = NULL;
|
struct HeapEntry *res = NULL;
|
||||||
{
|
{
|
||||||
LockGuard l(kmem_lock);
|
LockGuard l(kmem_lock);
|
||||||
struct HeapEntry *entry = KERN_HeapBegin;
|
struct HeapEntry *entry = KERN_HeapBegin;
|
||||||
assert2(entry->magic == KERN_HeapMagicFree, "Bad heap!");
|
assert2(entry->magic == KERN_HeapMagicFree, "Bad heap!");
|
||||||
|
|
||||||
@@ -119,28 +119,28 @@ void *kmalloc(size_t n) {
|
|||||||
entry->next->prev = prev;
|
entry->next->prev = prev;
|
||||||
} else {
|
} else {
|
||||||
if (entry->next) {
|
if (entry->next) {
|
||||||
KERN_HeapBegin = entry->next;
|
KERN_HeapBegin = entry->next;
|
||||||
entry->next->prev = NULL;
|
entry->next->prev = NULL;
|
||||||
} else {
|
} else {
|
||||||
KERN_HeapBegin = (struct HeapEntry *) KERN_HeapEnd;
|
KERN_HeapBegin = (struct HeapEntry *) KERN_HeapEnd;
|
||||||
extend_heap(1);
|
extend_heap(1);
|
||||||
KERN_HeapBegin->next = NULL;
|
KERN_HeapBegin->next = NULL;
|
||||||
KERN_HeapBegin->prev = NULL;
|
KERN_HeapBegin->prev = NULL;
|
||||||
KERN_HeapBegin->magic = KERN_HeapMagicFree;
|
KERN_HeapBegin->magic = KERN_HeapMagicFree;
|
||||||
KERN_HeapBegin->len = PAGE_SIZE - (sizeof(struct HeapEntry));
|
KERN_HeapBegin->len = PAGE_SIZE - (sizeof(struct HeapEntry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (entry->len > n + sizeof(struct HeapEntry)) {
|
if (entry->len > n + sizeof(struct HeapEntry)) {
|
||||||
res = entry;
|
res = entry;
|
||||||
struct HeapEntry *new_split_entry = split_entry(res, n);
|
struct HeapEntry *new_split_entry = split_entry(res, n);
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev->next = new_split_entry;
|
prev->next = new_split_entry;
|
||||||
new_split_entry->prev = prev;
|
new_split_entry->prev = prev;
|
||||||
} else {
|
} else {
|
||||||
KERN_HeapBegin = new_split_entry;
|
KERN_HeapBegin = new_split_entry;
|
||||||
new_split_entry->prev = NULL;
|
new_split_entry->prev = NULL;
|
||||||
}
|
}
|
||||||
if (new_split_entry->prev)
|
if (new_split_entry->prev)
|
||||||
@@ -148,7 +148,7 @@ void *kmalloc(size_t n) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = entry;
|
prev = entry;
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
} while (entry);
|
} while (entry);
|
||||||
|
|
||||||
@@ -158,24 +158,24 @@ void *kmalloc(size_t n) {
|
|||||||
assert2(entry->magic == KERN_HeapMagicFree, "Expected last tried entry to be free");
|
assert2(entry->magic == KERN_HeapMagicFree, "Expected last tried entry to be free");
|
||||||
assert2(entry->next == NULL, "Expected last tried entry to be the last");
|
assert2(entry->next == NULL, "Expected last tried entry to be the last");
|
||||||
|
|
||||||
size_t data_needed = n + (2 * sizeof(struct HeapEntry));
|
size_t data_needed = n + (2 * sizeof(struct HeapEntry));
|
||||||
|
|
||||||
size_t pages_needed = ((data_needed & 0xFFF) == 0)
|
size_t pages_needed = ((data_needed & 0xFFF) == 0)
|
||||||
? data_needed >> 12
|
? data_needed >> 12
|
||||||
: ((data_needed & (~0xFFF)) + 0x1000) >> 12;
|
: ((data_needed & (~0xFFF)) + 0x1000) >> 12;
|
||||||
|
|
||||||
struct HeapEntry *new_entry = (struct HeapEntry *) KERN_HeapEnd;
|
struct HeapEntry *new_entry = (struct HeapEntry *) KERN_HeapEnd;
|
||||||
extend_heap(pages_needed);
|
extend_heap(pages_needed);
|
||||||
new_entry->next = NULL;
|
new_entry->next = NULL;
|
||||||
new_entry->prev = entry;
|
new_entry->prev = entry;
|
||||||
new_entry->magic = KERN_HeapMagicFree;
|
new_entry->magic = KERN_HeapMagicFree;
|
||||||
new_entry->len = (pages_needed * PAGE_SIZE) - (sizeof(struct HeapEntry));
|
new_entry->len = (pages_needed * PAGE_SIZE) - (sizeof(struct HeapEntry));
|
||||||
assert2(new_entry->len >= n, "Expected allocated heap entry to fit what we wanted");
|
assert2(new_entry->len >= n, "Expected allocated heap entry to fit what we wanted");
|
||||||
res = new_entry;
|
res = new_entry;
|
||||||
if (new_entry->len > n) {
|
if (new_entry->len > n) {
|
||||||
struct HeapEntry *new_split_entry = split_entry(res, n);
|
struct HeapEntry *new_split_entry = split_entry(res, n);
|
||||||
entry->next = new_split_entry;
|
entry->next = new_split_entry;
|
||||||
new_split_entry->prev = entry;
|
new_split_entry->prev = entry;
|
||||||
if (new_split_entry->prev)
|
if (new_split_entry->prev)
|
||||||
assert(new_split_entry->prev->magic == KERN_HeapMagicFree);
|
assert(new_split_entry->prev->magic == KERN_HeapMagicFree);
|
||||||
}
|
}
|
||||||
@@ -188,8 +188,8 @@ void *kmalloc(size_t n) {
|
|||||||
// if (res->next) res->next->prev = res->prev;
|
// if (res->next) res->next->prev = res->prev;
|
||||||
// if (res->prev) res->prev->next = res->next;
|
// if (res->prev) res->prev->next = res->next;
|
||||||
|
|
||||||
res->next = NULL;
|
res->next = NULL;
|
||||||
res->prev = NULL;
|
res->prev = NULL;
|
||||||
res->magic = KERN_HeapMagicTaken;
|
res->magic = KERN_HeapMagicTaken;
|
||||||
}
|
}
|
||||||
assert((((uintptr_t) res->data) & 0xFULL) == 0);
|
assert((((uintptr_t) res->data) & 0xFULL) == 0);
|
||||||
@@ -211,21 +211,21 @@ static void try_merge_fwd(struct HeapEntry *entry) {
|
|||||||
|
|
||||||
if (nextEntry == entry->next) {
|
if (nextEntry == entry->next) {
|
||||||
nextEntry->next->prev = entry;
|
nextEntry->next->prev = entry;
|
||||||
entry->next = nextEntry->next;
|
entry->next = nextEntry->next;
|
||||||
} else {
|
} else {
|
||||||
assert(nextEntry->prev && nextEntry->prev->magic == KERN_HeapMagicFree);
|
assert(nextEntry->prev && nextEntry->prev->magic == KERN_HeapMagicFree);
|
||||||
|
|
||||||
struct HeapEntry *victimR = nextEntry->next;
|
struct HeapEntry *victimR = nextEntry->next;
|
||||||
if (victimR) {
|
if (victimR) {
|
||||||
assert(victimR->magic == KERN_HeapMagicFree);
|
assert(victimR->magic == KERN_HeapMagicFree);
|
||||||
victimR->prev = nextEntry->prev;
|
victimR->prev = nextEntry->prev;
|
||||||
nextEntry->prev->next = victimR;
|
nextEntry->prev->next = victimR;
|
||||||
} else {
|
} else {
|
||||||
nextEntry->prev->next = NULL;
|
nextEntry->prev->next = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry->len = entry->len + sizeof(struct HeapEntry) + nextEntry->len;
|
entry->len = entry->len + sizeof(struct HeapEntry) + nextEntry->len;
|
||||||
nextEntry = (struct HeapEntry *) ((uint64_t) entry + sizeof(struct HeapEntry) + entry->len);
|
nextEntry = (struct HeapEntry *) ((uint64_t) entry + sizeof(struct HeapEntry) + entry->len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,18 +248,18 @@ static struct HeapEntry *try_shrink_heap(struct HeapEntry *entry) {
|
|||||||
// But also check if it's enough...
|
// But also check if it's enough...
|
||||||
if (diff <= sizeof(struct HeapEntry)) diff += 0x1000ULL;
|
if (diff <= sizeof(struct HeapEntry)) diff += 0x1000ULL;
|
||||||
|
|
||||||
entry = split_entry(entry, diff - sizeof(struct HeapEntry));
|
entry = split_entry(entry, diff - sizeof(struct HeapEntry));
|
||||||
ret = entry->prev;
|
ret = entry->prev;
|
||||||
ret->next = entry->next;
|
ret->next = entry->next;
|
||||||
if (entry->next)
|
if (entry->next)
|
||||||
entry->next->prev = ret;
|
entry->next->prev = ret;
|
||||||
} else {
|
} else {
|
||||||
ret = entry->next;
|
ret = entry->next;
|
||||||
ret->prev = NULL;
|
ret->prev = NULL;
|
||||||
}
|
}
|
||||||
assert(((uint64_t) entry & 0xFFF) == 0);
|
assert(((uint64_t) entry & 0xFFF) == 0);
|
||||||
|
|
||||||
KERN_HeapEnd = (uintptr_t) entry;
|
KERN_HeapEnd = (uintptr_t) entry;
|
||||||
uint64_t totallen = entry->len + sizeof(struct HeapEntry);
|
uint64_t totallen = entry->len + sizeof(struct HeapEntry);
|
||||||
assert(((uint64_t) totallen & 0xFFF) == 0);
|
assert(((uint64_t) totallen & 0xFFF) == 0);
|
||||||
uint64_t total_pages = totallen / PAGE_SIZE;
|
uint64_t total_pages = totallen / PAGE_SIZE;
|
||||||
@@ -276,7 +276,7 @@ static struct HeapEntry *try_shrink_heap(struct HeapEntry *entry) {
|
|||||||
|
|
||||||
void kfree(void *addr) {
|
void kfree(void *addr) {
|
||||||
assert(initialized);
|
assert(initialized);
|
||||||
LockGuard l(kmem_lock);
|
LockGuard l(kmem_lock);
|
||||||
|
|
||||||
struct HeapEntry *freed = (struct HeapEntry *) (addr - (sizeof(struct HeapEntry)));
|
struct HeapEntry *freed = (struct HeapEntry *) (addr - (sizeof(struct HeapEntry)));
|
||||||
used.fetch_sub(freed->len);
|
used.fetch_sub(freed->len);
|
||||||
@@ -288,10 +288,10 @@ void kfree(void *addr) {
|
|||||||
assert2(entry->magic == KERN_HeapMagicFree, "Bad free!");
|
assert2(entry->magic == KERN_HeapMagicFree, "Bad free!");
|
||||||
assert2(entry->prev == NULL, "Bad free!");
|
assert2(entry->prev == NULL, "Bad free!");
|
||||||
|
|
||||||
freed->next = entry;
|
freed->next = entry;
|
||||||
entry->prev = freed;
|
entry->prev = freed;
|
||||||
KERN_HeapBegin = freed;
|
KERN_HeapBegin = freed;
|
||||||
freed->magic = KERN_HeapMagicFree;
|
freed->magic = KERN_HeapMagicFree;
|
||||||
|
|
||||||
try_merge_fwd(freed);
|
try_merge_fwd(freed);
|
||||||
assert2(freed->prev == NULL, "Bad free!");
|
assert2(freed->prev == NULL, "Bad free!");
|
||||||
|
|||||||
@@ -4,28 +4,28 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define KERN_HeapVirtBegin (0xffffc00000000000ULL)
|
#define KERN_HeapVirtBegin (0xffffc00000000000ULL)
|
||||||
#define KERN_HeapMagicFree 0xDEDE
|
#define KERN_HeapMagicFree 0xDEDE
|
||||||
#define KERN_HeapMagicTaken 0xADAD
|
#define KERN_HeapMagicTaken 0xADAD
|
||||||
|
|
||||||
void init_kern_heap();
|
void init_kern_heap();
|
||||||
|
|
||||||
struct HeapEntry {
|
struct HeapEntry {
|
||||||
uint_fast16_t magic;
|
uint_fast16_t magic;
|
||||||
struct HeapEntry *next;
|
struct HeapEntry *next;
|
||||||
struct HeapEntry *prev;
|
struct HeapEntry *prev;
|
||||||
uint64_t len;
|
uint64_t len;
|
||||||
char data[] __attribute__((aligned(16)));
|
char data[] __attribute__((aligned(16)));
|
||||||
} __attribute__((packed, aligned(32)));
|
} __attribute__((packed, aligned(32)));
|
||||||
|
|
||||||
extern struct HeapEntry *KERN_HeapBegin;
|
extern struct HeapEntry *KERN_HeapBegin;
|
||||||
extern uintptr_t KERN_HeapEnd;// Past the end
|
extern uintptr_t KERN_HeapEnd; // Past the end
|
||||||
|
|
||||||
void *kmalloc(size_t n);
|
void *kmalloc(size_t n);
|
||||||
void kfree(void *addr);
|
void kfree(void *addr);
|
||||||
void *krealloc(void *addr, size_t newsize);
|
void *krealloc(void *addr, size_t newsize);
|
||||||
|
|
||||||
uint64_t get_heap_allocated();
|
uint64_t get_heap_allocated();
|
||||||
uint64_t get_heap_used();
|
uint64_t get_heap_used();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -26,22 +26,22 @@ extern "C" {
|
|||||||
/* Misc */
|
/* Misc */
|
||||||
|
|
||||||
#ifdef LIMINE_NO_POINTERS
|
#ifdef LIMINE_NO_POINTERS
|
||||||
# define LIMINE_PTR(TYPE) uint64_t
|
#define LIMINE_PTR(TYPE) uint64_t
|
||||||
#else
|
#else
|
||||||
# define LIMINE_PTR(TYPE) TYPE
|
#define LIMINE_PTR(TYPE) TYPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# define LIMINE_DEPRECATED __attribute__((__deprecated__))
|
#define LIMINE_DEPRECATED __attribute__((__deprecated__))
|
||||||
# define LIMINE_DEPRECATED_IGNORE_START \
|
#define LIMINE_DEPRECATED_IGNORE_START \
|
||||||
_Pragma("GCC diagnostic push") \
|
_Pragma("GCC diagnostic push") \
|
||||||
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||||
# define LIMINE_DEPRECATED_IGNORE_END \
|
#define LIMINE_DEPRECATED_IGNORE_END \
|
||||||
_Pragma("GCC diagnostic pop")
|
_Pragma("GCC diagnostic pop")
|
||||||
#else
|
#else
|
||||||
# define LIMINE_DEPRECATED
|
#define LIMINE_DEPRECATED
|
||||||
# define LIMINE_DEPRECATED_IGNORE_START
|
#define LIMINE_DEPRECATED_IGNORE_START
|
||||||
# define LIMINE_DEPRECATED_IGNORE_END
|
#define LIMINE_DEPRECATED_IGNORE_END
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b
|
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b
|
||||||
@@ -50,25 +50,28 @@ struct limine_uuid {
|
|||||||
uint32_t a;
|
uint32_t a;
|
||||||
uint16_t b;
|
uint16_t b;
|
||||||
uint16_t c;
|
uint16_t c;
|
||||||
uint8_t d[8];
|
uint8_t d[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LIMINE_MEDIA_TYPE_GENERIC 0
|
#define LIMINE_MEDIA_TYPE_GENERIC 0
|
||||||
#define LIMINE_MEDIA_TYPE_OPTICAL 1
|
#define LIMINE_MEDIA_TYPE_OPTICAL 1
|
||||||
#define LIMINE_MEDIA_TYPE_TFTP 2
|
#define LIMINE_MEDIA_TYPE_TFTP 2
|
||||||
|
|
||||||
struct limine_file {
|
struct limine_file {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(void *) address;
|
LIMINE_PTR(void *)
|
||||||
|
address;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
LIMINE_PTR(char *) path;
|
LIMINE_PTR(char *)
|
||||||
LIMINE_PTR(char *) cmdline;
|
path;
|
||||||
uint32_t media_type;
|
LIMINE_PTR(char *)
|
||||||
uint32_t unused;
|
cmdline;
|
||||||
uint32_t tftp_ip;
|
uint32_t media_type;
|
||||||
uint32_t tftp_port;
|
uint32_t unused;
|
||||||
uint32_t partition_index;
|
uint32_t tftp_ip;
|
||||||
uint32_t mbr_disk_id;
|
uint32_t tftp_port;
|
||||||
|
uint32_t partition_index;
|
||||||
|
uint32_t mbr_disk_id;
|
||||||
struct limine_uuid gpt_disk_uuid;
|
struct limine_uuid gpt_disk_uuid;
|
||||||
struct limine_uuid gpt_part_uuid;
|
struct limine_uuid gpt_part_uuid;
|
||||||
struct limine_uuid part_uuid;
|
struct limine_uuid part_uuid;
|
||||||
@@ -76,23 +79,28 @@ struct limine_file {
|
|||||||
|
|
||||||
/* Boot info */
|
/* Boot info */
|
||||||
|
|
||||||
#define LIMINE_BOOTLOADER_INFO_REQUEST { LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740 }
|
#define LIMINE_BOOTLOADER_INFO_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740 }
|
||||||
|
|
||||||
struct limine_bootloader_info_response {
|
struct limine_bootloader_info_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(char *) name;
|
LIMINE_PTR(char *)
|
||||||
LIMINE_PTR(char *) version;
|
name;
|
||||||
|
LIMINE_PTR(char *)
|
||||||
|
version;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_bootloader_info_request {
|
struct limine_bootloader_info_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_bootloader_info_response *) response;
|
LIMINE_PTR(struct limine_bootloader_info_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stack size */
|
/* Stack size */
|
||||||
|
|
||||||
#define LIMINE_STACK_SIZE_REQUEST { LIMINE_COMMON_MAGIC, 0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d }
|
#define LIMINE_STACK_SIZE_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d }
|
||||||
|
|
||||||
struct limine_stack_size_response {
|
struct limine_stack_size_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
@@ -101,13 +109,15 @@ struct limine_stack_size_response {
|
|||||||
struct limine_stack_size_request {
|
struct limine_stack_size_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_stack_size_response *) response;
|
LIMINE_PTR(struct limine_stack_size_response *)
|
||||||
|
response;
|
||||||
uint64_t stack_size;
|
uint64_t stack_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* HHDM */
|
/* HHDM */
|
||||||
|
|
||||||
#define LIMINE_HHDM_REQUEST { LIMINE_COMMON_MAGIC, 0x48dcf1cb8ad2b852, 0x63984e959a98244b }
|
#define LIMINE_HHDM_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x48dcf1cb8ad2b852, 0x63984e959a98244b }
|
||||||
|
|
||||||
struct limine_hhdm_response {
|
struct limine_hhdm_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
@@ -117,12 +127,14 @@ struct limine_hhdm_response {
|
|||||||
struct limine_hhdm_request {
|
struct limine_hhdm_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_hhdm_response *) response;
|
LIMINE_PTR(struct limine_hhdm_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Framebuffer */
|
/* Framebuffer */
|
||||||
|
|
||||||
#define LIMINE_FRAMEBUFFER_REQUEST { LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75, 0xa3148604f6fab11b }
|
#define LIMINE_FRAMEBUFFER_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75, 0xa3148604f6fab11b }
|
||||||
|
|
||||||
#define LIMINE_FRAMEBUFFER_RGB 1
|
#define LIMINE_FRAMEBUFFER_RGB 1
|
||||||
|
|
||||||
@@ -131,128 +143,140 @@ struct limine_video_mode {
|
|||||||
uint64_t width;
|
uint64_t width;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
uint16_t bpp;
|
uint16_t bpp;
|
||||||
uint8_t memory_model;
|
uint8_t memory_model;
|
||||||
uint8_t red_mask_size;
|
uint8_t red_mask_size;
|
||||||
uint8_t red_mask_shift;
|
uint8_t red_mask_shift;
|
||||||
uint8_t green_mask_size;
|
uint8_t green_mask_size;
|
||||||
uint8_t green_mask_shift;
|
uint8_t green_mask_shift;
|
||||||
uint8_t blue_mask_size;
|
uint8_t blue_mask_size;
|
||||||
uint8_t blue_mask_shift;
|
uint8_t blue_mask_shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_framebuffer {
|
struct limine_framebuffer {
|
||||||
LIMINE_PTR(void *) address;
|
LIMINE_PTR(void *)
|
||||||
|
address;
|
||||||
uint64_t width;
|
uint64_t width;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
uint64_t pitch;
|
uint64_t pitch;
|
||||||
uint16_t bpp;
|
uint16_t bpp;
|
||||||
uint8_t memory_model;
|
uint8_t memory_model;
|
||||||
uint8_t red_mask_size;
|
uint8_t red_mask_size;
|
||||||
uint8_t red_mask_shift;
|
uint8_t red_mask_shift;
|
||||||
uint8_t green_mask_size;
|
uint8_t green_mask_size;
|
||||||
uint8_t green_mask_shift;
|
uint8_t green_mask_shift;
|
||||||
uint8_t blue_mask_size;
|
uint8_t blue_mask_size;
|
||||||
uint8_t blue_mask_shift;
|
uint8_t blue_mask_shift;
|
||||||
uint8_t unused[7];
|
uint8_t unused[7];
|
||||||
uint64_t edid_size;
|
uint64_t edid_size;
|
||||||
LIMINE_PTR(void *) edid;
|
LIMINE_PTR(void *)
|
||||||
|
edid;
|
||||||
/* Response revision 1 */
|
/* Response revision 1 */
|
||||||
uint64_t mode_count;
|
uint64_t mode_count;
|
||||||
LIMINE_PTR(struct limine_video_mode **) modes;
|
LIMINE_PTR(struct limine_video_mode **)
|
||||||
|
modes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_framebuffer_response {
|
struct limine_framebuffer_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
uint64_t framebuffer_count;
|
uint64_t framebuffer_count;
|
||||||
LIMINE_PTR(struct limine_framebuffer **) framebuffers;
|
LIMINE_PTR(struct limine_framebuffer **)
|
||||||
|
framebuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_framebuffer_request {
|
struct limine_framebuffer_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_framebuffer_response *) response;
|
LIMINE_PTR(struct limine_framebuffer_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Terminal */
|
/* Terminal */
|
||||||
|
|
||||||
#define LIMINE_TERMINAL_REQUEST { LIMINE_COMMON_MAGIC, 0xc8ac59310c2b0844, 0xa68d0c7265d38878 }
|
#define LIMINE_TERMINAL_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0xc8ac59310c2b0844, 0xa68d0c7265d38878 }
|
||||||
|
|
||||||
#define LIMINE_TERMINAL_CB_DEC 10
|
#define LIMINE_TERMINAL_CB_DEC 10
|
||||||
#define LIMINE_TERMINAL_CB_BELL 20
|
#define LIMINE_TERMINAL_CB_BELL 20
|
||||||
#define LIMINE_TERMINAL_CB_PRIVATE_ID 30
|
#define LIMINE_TERMINAL_CB_PRIVATE_ID 30
|
||||||
#define LIMINE_TERMINAL_CB_STATUS_REPORT 40
|
#define LIMINE_TERMINAL_CB_STATUS_REPORT 40
|
||||||
#define LIMINE_TERMINAL_CB_POS_REPORT 50
|
#define LIMINE_TERMINAL_CB_POS_REPORT 50
|
||||||
#define LIMINE_TERMINAL_CB_KBD_LEDS 60
|
#define LIMINE_TERMINAL_CB_KBD_LEDS 60
|
||||||
#define LIMINE_TERMINAL_CB_MODE 70
|
#define LIMINE_TERMINAL_CB_MODE 70
|
||||||
#define LIMINE_TERMINAL_CB_LINUX 80
|
#define LIMINE_TERMINAL_CB_LINUX 80
|
||||||
|
|
||||||
#define LIMINE_TERMINAL_CTX_SIZE ((uint64_t)(-1))
|
#define LIMINE_TERMINAL_CTX_SIZE ((uint64_t) (-1))
|
||||||
#define LIMINE_TERMINAL_CTX_SAVE ((uint64_t)(-2))
|
#define LIMINE_TERMINAL_CTX_SAVE ((uint64_t) (-2))
|
||||||
#define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t)(-3))
|
#define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t) (-3))
|
||||||
#define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t)(-4))
|
#define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t) (-4))
|
||||||
|
|
||||||
/* Response revision 1 */
|
/* Response revision 1 */
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t)(-10))
|
#define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t) (-10))
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t)(-11))
|
#define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t) (-11))
|
||||||
|
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0)
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1)
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2)
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3)
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4)
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5)
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6)
|
||||||
#define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7)
|
#define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7)
|
||||||
|
|
||||||
LIMINE_DEPRECATED_IGNORE_START
|
LIMINE_DEPRECATED_IGNORE_START
|
||||||
|
|
||||||
struct LIMINE_DEPRECATED limine_terminal;
|
struct LIMINE_DEPRECATED limine_terminal;
|
||||||
|
|
||||||
typedef void (*limine_terminal_write)(struct limine_terminal *, const char *, uint64_t);
|
typedef void (*limine_terminal_write)(struct limine_terminal *, const char *, uint64_t);
|
||||||
typedef void (*limine_terminal_callback)(struct limine_terminal *, uint64_t, uint64_t, uint64_t, uint64_t);
|
typedef void (*limine_terminal_callback)(struct limine_terminal *, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||||
|
|
||||||
struct LIMINE_DEPRECATED limine_terminal {
|
struct LIMINE_DEPRECATED limine_terminal {
|
||||||
uint64_t columns;
|
uint64_t columns;
|
||||||
uint64_t rows;
|
uint64_t rows;
|
||||||
LIMINE_PTR(struct limine_framebuffer *) framebuffer;
|
LIMINE_PTR(struct limine_framebuffer *)
|
||||||
|
framebuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LIMINE_DEPRECATED limine_terminal_response {
|
struct LIMINE_DEPRECATED limine_terminal_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
uint64_t terminal_count;
|
uint64_t terminal_count;
|
||||||
LIMINE_PTR(struct limine_terminal **) terminals;
|
LIMINE_PTR(struct limine_terminal **)
|
||||||
LIMINE_PTR(limine_terminal_write) write;
|
terminals;
|
||||||
|
LIMINE_PTR(limine_terminal_write)
|
||||||
|
write;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LIMINE_DEPRECATED limine_terminal_request {
|
struct LIMINE_DEPRECATED limine_terminal_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_terminal_response *) response;
|
LIMINE_PTR(struct limine_terminal_response *)
|
||||||
LIMINE_PTR(limine_terminal_callback) callback;
|
response;
|
||||||
|
LIMINE_PTR(limine_terminal_callback)
|
||||||
|
callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
LIMINE_DEPRECATED_IGNORE_END
|
LIMINE_DEPRECATED_IGNORE_END
|
||||||
|
|
||||||
/* Paging mode */
|
/* Paging mode */
|
||||||
|
|
||||||
#define LIMINE_PAGING_MODE_REQUEST { LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a }
|
#define LIMINE_PAGING_MODE_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a }
|
||||||
|
|
||||||
#if defined (__x86_64__) || defined (__i386__)
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
#define LIMINE_PAGING_MODE_X86_64_4LVL 0
|
#define LIMINE_PAGING_MODE_X86_64_4LVL 0
|
||||||
#define LIMINE_PAGING_MODE_X86_64_5LVL 1
|
#define LIMINE_PAGING_MODE_X86_64_5LVL 1
|
||||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_X86_64_5LVL
|
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_X86_64_5LVL
|
||||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL
|
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL
|
||||||
#elif defined (__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#define LIMINE_PAGING_MODE_AARCH64_4LVL 0
|
#define LIMINE_PAGING_MODE_AARCH64_4LVL 0
|
||||||
#define LIMINE_PAGING_MODE_AARCH64_5LVL 1
|
#define LIMINE_PAGING_MODE_AARCH64_5LVL 1
|
||||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_AARCH64_5LVL
|
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_AARCH64_5LVL
|
||||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL
|
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL
|
||||||
#elif defined (__riscv) && (__riscv_xlen == 64)
|
#elif defined(__riscv) && (__riscv_xlen == 64)
|
||||||
#define LIMINE_PAGING_MODE_RISCV_SV39 0
|
#define LIMINE_PAGING_MODE_RISCV_SV39 0
|
||||||
#define LIMINE_PAGING_MODE_RISCV_SV48 1
|
#define LIMINE_PAGING_MODE_RISCV_SV48 1
|
||||||
#define LIMINE_PAGING_MODE_RISCV_SV57 2
|
#define LIMINE_PAGING_MODE_RISCV_SV57 2
|
||||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_RISCV_SV57
|
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_RISCV_SV57
|
||||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
|
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
|
||||||
#else
|
#else
|
||||||
#error Unknown architecture
|
#error Unknown architecture
|
||||||
#endif
|
#endif
|
||||||
@@ -266,14 +290,16 @@ struct limine_paging_mode_response {
|
|||||||
struct limine_paging_mode_request {
|
struct limine_paging_mode_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_paging_mode_response *) response;
|
LIMINE_PTR(struct limine_paging_mode_response *)
|
||||||
|
response;
|
||||||
uint64_t mode;
|
uint64_t mode;
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 5-level paging */
|
/* 5-level paging */
|
||||||
|
|
||||||
#define LIMINE_5_LEVEL_PAGING_REQUEST { LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888 }
|
#define LIMINE_5_LEVEL_PAGING_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888 }
|
||||||
|
|
||||||
LIMINE_DEPRECATED_IGNORE_START
|
LIMINE_DEPRECATED_IGNORE_START
|
||||||
|
|
||||||
@@ -284,20 +310,22 @@ struct LIMINE_DEPRECATED limine_5_level_paging_response {
|
|||||||
struct LIMINE_DEPRECATED limine_5_level_paging_request {
|
struct LIMINE_DEPRECATED limine_5_level_paging_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_5_level_paging_response *) response;
|
LIMINE_PTR(struct limine_5_level_paging_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
LIMINE_DEPRECATED_IGNORE_END
|
LIMINE_DEPRECATED_IGNORE_END
|
||||||
|
|
||||||
/* SMP */
|
/* SMP */
|
||||||
|
|
||||||
#define LIMINE_SMP_REQUEST { LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0 }
|
#define LIMINE_SMP_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0 }
|
||||||
|
|
||||||
struct limine_smp_info;
|
struct limine_smp_info;
|
||||||
|
|
||||||
typedef void (*limine_goto_address)(struct limine_smp_info *);
|
typedef void (*limine_goto_address)(struct limine_smp_info *);
|
||||||
|
|
||||||
#if defined (__x86_64__) || defined (__i386__)
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
|
|
||||||
#define LIMINE_SMP_X2APIC (1 << 0)
|
#define LIMINE_SMP_X2APIC (1 << 0)
|
||||||
|
|
||||||
@@ -305,7 +333,8 @@ struct limine_smp_info {
|
|||||||
uint32_t processor_id;
|
uint32_t processor_id;
|
||||||
uint32_t lapic_id;
|
uint32_t lapic_id;
|
||||||
uint64_t reserved;
|
uint64_t reserved;
|
||||||
LIMINE_PTR(limine_goto_address) goto_address;
|
LIMINE_PTR(limine_goto_address)
|
||||||
|
goto_address;
|
||||||
uint64_t extra_argument;
|
uint64_t extra_argument;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -314,17 +343,19 @@ struct limine_smp_response {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t bsp_lapic_id;
|
uint32_t bsp_lapic_id;
|
||||||
uint64_t cpu_count;
|
uint64_t cpu_count;
|
||||||
LIMINE_PTR(struct limine_smp_info **) cpus;
|
LIMINE_PTR(struct limine_smp_info **)
|
||||||
|
cpus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined (__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
|
||||||
struct limine_smp_info {
|
struct limine_smp_info {
|
||||||
uint32_t processor_id;
|
uint32_t processor_id;
|
||||||
uint32_t gic_iface_no;
|
uint32_t gic_iface_no;
|
||||||
uint64_t mpidr;
|
uint64_t mpidr;
|
||||||
uint64_t reserved;
|
uint64_t reserved;
|
||||||
LIMINE_PTR(limine_goto_address) goto_address;
|
LIMINE_PTR(limine_goto_address)
|
||||||
|
goto_address;
|
||||||
uint64_t extra_argument;
|
uint64_t extra_argument;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -333,16 +364,18 @@ struct limine_smp_response {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint64_t bsp_mpidr;
|
uint64_t bsp_mpidr;
|
||||||
uint64_t cpu_count;
|
uint64_t cpu_count;
|
||||||
LIMINE_PTR(struct limine_smp_info **) cpus;
|
LIMINE_PTR(struct limine_smp_info **)
|
||||||
|
cpus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined (__riscv) && (__riscv_xlen == 64)
|
#elif defined(__riscv) && (__riscv_xlen == 64)
|
||||||
|
|
||||||
struct limine_smp_info {
|
struct limine_smp_info {
|
||||||
uint32_t processor_id;
|
uint32_t processor_id;
|
||||||
uint64_t hartid;
|
uint64_t hartid;
|
||||||
uint64_t reserved;
|
uint64_t reserved;
|
||||||
LIMINE_PTR(limine_goto_address) goto_address;
|
LIMINE_PTR(limine_goto_address)
|
||||||
|
goto_address;
|
||||||
uint64_t extra_argument;
|
uint64_t extra_argument;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -351,7 +384,8 @@ struct limine_smp_response {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint64_t bsp_hartid;
|
uint64_t bsp_hartid;
|
||||||
uint64_t cpu_count;
|
uint64_t cpu_count;
|
||||||
LIMINE_PTR(struct limine_smp_info **) cpus;
|
LIMINE_PTR(struct limine_smp_info **)
|
||||||
|
cpus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -361,13 +395,15 @@ struct limine_smp_response {
|
|||||||
struct limine_smp_request {
|
struct limine_smp_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_smp_response *) response;
|
LIMINE_PTR(struct limine_smp_response *)
|
||||||
|
response;
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Memory map */
|
/* Memory map */
|
||||||
|
|
||||||
#define LIMINE_MEMMAP_REQUEST { LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62 }
|
#define LIMINE_MEMMAP_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62 }
|
||||||
|
|
||||||
#define LIMINE_MEMMAP_USABLE 0
|
#define LIMINE_MEMMAP_USABLE 0
|
||||||
#define LIMINE_MEMMAP_RESERVED 1
|
#define LIMINE_MEMMAP_RESERVED 1
|
||||||
@@ -387,18 +423,21 @@ struct limine_memmap_entry {
|
|||||||
struct limine_memmap_response {
|
struct limine_memmap_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
uint64_t entry_count;
|
uint64_t entry_count;
|
||||||
LIMINE_PTR(struct limine_memmap_entry **) entries;
|
LIMINE_PTR(struct limine_memmap_entry **)
|
||||||
|
entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_memmap_request {
|
struct limine_memmap_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_memmap_response *) response;
|
LIMINE_PTR(struct limine_memmap_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Entry point */
|
/* Entry point */
|
||||||
|
|
||||||
#define LIMINE_ENTRY_POINT_REQUEST { LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a }
|
#define LIMINE_ENTRY_POINT_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a }
|
||||||
|
|
||||||
typedef void (*limine_entry_point)(void);
|
typedef void (*limine_entry_point)(void);
|
||||||
|
|
||||||
@@ -409,117 +448,141 @@ struct limine_entry_point_response {
|
|||||||
struct limine_entry_point_request {
|
struct limine_entry_point_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_entry_point_response *) response;
|
LIMINE_PTR(struct limine_entry_point_response *)
|
||||||
LIMINE_PTR(limine_entry_point) entry;
|
response;
|
||||||
|
LIMINE_PTR(limine_entry_point)
|
||||||
|
entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Kernel File */
|
/* Kernel File */
|
||||||
|
|
||||||
#define LIMINE_KERNEL_FILE_REQUEST { LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69 }
|
#define LIMINE_KERNEL_FILE_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69 }
|
||||||
|
|
||||||
struct limine_kernel_file_response {
|
struct limine_kernel_file_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_file *) kernel_file;
|
LIMINE_PTR(struct limine_file *)
|
||||||
|
kernel_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_kernel_file_request {
|
struct limine_kernel_file_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_kernel_file_response *) response;
|
LIMINE_PTR(struct limine_kernel_file_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Module */
|
/* Module */
|
||||||
|
|
||||||
#define LIMINE_MODULE_REQUEST { LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee }
|
#define LIMINE_MODULE_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee }
|
||||||
|
|
||||||
#define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0)
|
#define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0)
|
||||||
|
|
||||||
struct limine_internal_module {
|
struct limine_internal_module {
|
||||||
LIMINE_PTR(const char *) path;
|
LIMINE_PTR(const char *)
|
||||||
LIMINE_PTR(const char *) cmdline;
|
path;
|
||||||
|
LIMINE_PTR(const char *)
|
||||||
|
cmdline;
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_module_response {
|
struct limine_module_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
uint64_t module_count;
|
uint64_t module_count;
|
||||||
LIMINE_PTR(struct limine_file **) modules;
|
LIMINE_PTR(struct limine_file **)
|
||||||
|
modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_module_request {
|
struct limine_module_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_module_response *) response;
|
LIMINE_PTR(struct limine_module_response *)
|
||||||
|
response;
|
||||||
|
|
||||||
/* Request revision 1 */
|
/* Request revision 1 */
|
||||||
uint64_t internal_module_count;
|
uint64_t internal_module_count;
|
||||||
LIMINE_PTR(struct limine_internal_module **) internal_modules;
|
LIMINE_PTR(struct limine_internal_module **)
|
||||||
|
internal_modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* RSDP */
|
/* RSDP */
|
||||||
|
|
||||||
#define LIMINE_RSDP_REQUEST { LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43, 0x27637845accdcf3c }
|
#define LIMINE_RSDP_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43, 0x27637845accdcf3c }
|
||||||
|
|
||||||
struct limine_rsdp_response {
|
struct limine_rsdp_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(void *) address;
|
LIMINE_PTR(void *)
|
||||||
|
address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_rsdp_request {
|
struct limine_rsdp_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_rsdp_response *) response;
|
LIMINE_PTR(struct limine_rsdp_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SMBIOS */
|
/* SMBIOS */
|
||||||
|
|
||||||
#define LIMINE_SMBIOS_REQUEST { LIMINE_COMMON_MAGIC, 0x9e9046f11e095391, 0xaa4a520fefbde5ee }
|
#define LIMINE_SMBIOS_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x9e9046f11e095391, 0xaa4a520fefbde5ee }
|
||||||
|
|
||||||
struct limine_smbios_response {
|
struct limine_smbios_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(void *) entry_32;
|
LIMINE_PTR(void *)
|
||||||
LIMINE_PTR(void *) entry_64;
|
entry_32;
|
||||||
|
LIMINE_PTR(void *)
|
||||||
|
entry_64;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_smbios_request {
|
struct limine_smbios_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_smbios_response *) response;
|
LIMINE_PTR(struct limine_smbios_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* EFI system table */
|
/* EFI system table */
|
||||||
|
|
||||||
#define LIMINE_EFI_SYSTEM_TABLE_REQUEST { LIMINE_COMMON_MAGIC, 0x5ceba5163eaaf6d6, 0x0a6981610cf65fcc }
|
#define LIMINE_EFI_SYSTEM_TABLE_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x5ceba5163eaaf6d6, 0x0a6981610cf65fcc }
|
||||||
|
|
||||||
struct limine_efi_system_table_response {
|
struct limine_efi_system_table_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(void *) address;
|
LIMINE_PTR(void *)
|
||||||
|
address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_efi_system_table_request {
|
struct limine_efi_system_table_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_efi_system_table_response *) response;
|
LIMINE_PTR(struct limine_efi_system_table_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Boot time */
|
/* Boot time */
|
||||||
|
|
||||||
#define LIMINE_BOOT_TIME_REQUEST { LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893 }
|
#define LIMINE_BOOT_TIME_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893 }
|
||||||
|
|
||||||
struct limine_boot_time_response {
|
struct limine_boot_time_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
int64_t boot_time;
|
int64_t boot_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_boot_time_request {
|
struct limine_boot_time_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_boot_time_response *) response;
|
LIMINE_PTR(struct limine_boot_time_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Kernel address */
|
/* Kernel address */
|
||||||
|
|
||||||
#define LIMINE_KERNEL_ADDRESS_REQUEST { LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487 }
|
#define LIMINE_KERNEL_ADDRESS_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487 }
|
||||||
|
|
||||||
struct limine_kernel_address_response {
|
struct limine_kernel_address_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
@@ -530,22 +593,26 @@ struct limine_kernel_address_response {
|
|||||||
struct limine_kernel_address_request {
|
struct limine_kernel_address_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_kernel_address_response *) response;
|
LIMINE_PTR(struct limine_kernel_address_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Device Tree Blob */
|
/* Device Tree Blob */
|
||||||
|
|
||||||
#define LIMINE_DTB_REQUEST { LIMINE_COMMON_MAGIC, 0xb40ddb48fb54bac7, 0x545081493f81ffb7 }
|
#define LIMINE_DTB_REQUEST \
|
||||||
|
{ LIMINE_COMMON_MAGIC, 0xb40ddb48fb54bac7, 0x545081493f81ffb7 }
|
||||||
|
|
||||||
struct limine_dtb_response {
|
struct limine_dtb_response {
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(void *) dtb_ptr;
|
LIMINE_PTR(void *)
|
||||||
|
dtb_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct limine_dtb_request {
|
struct limine_dtb_request {
|
||||||
uint64_t id[4];
|
uint64_t id[4];
|
||||||
uint64_t revision;
|
uint64_t revision;
|
||||||
LIMINE_PTR(struct limine_dtb_response *) response;
|
LIMINE_PTR(struct limine_dtb_response *)
|
||||||
|
response;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||||
.revision = 0};
|
.revision = 0};
|
||||||
|
|
||||||
int framebuffer_count = 0;
|
int framebuffer_count = 0;
|
||||||
struct limine_framebuffer framebuffers[10];
|
struct limine_framebuffer framebuffers[10];
|
||||||
struct {
|
struct {
|
||||||
void *base;
|
void *base;
|
||||||
uint64_t len;
|
uint64_t len;
|
||||||
} framebufferAddrs[10];
|
} framebufferAddrs[10];
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ void limine_fb_save_response(AddressSpace *boot_address_space) {
|
|||||||
|
|
||||||
void limine_fb_remap(AddressSpace *space) {
|
void limine_fb_remap(AddressSpace *space) {
|
||||||
for (int i = 0; i < framebuffer_count; i++) {
|
for (int i = 0; i < framebuffer_count; i++) {
|
||||||
void *base = framebuffers[i].address;
|
void *base = framebuffers[i].address;
|
||||||
void *realbase = framebufferAddrs[i].base;
|
void *realbase = framebufferAddrs[i].base;
|
||||||
// TODO: Proper map
|
// TODO: Proper map
|
||||||
for (int i = 0; i < 100000; i++) {
|
for (int i = 0; i < 100000; i++) {
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
|
|
||||||
#include "paging.hpp"
|
#include "paging.hpp"
|
||||||
|
|
||||||
void limine_fb_save_response(struct AddressSpace *boot_address_space);
|
void limine_fb_save_response(struct AddressSpace *boot_address_space);
|
||||||
void limine_fb_remap(struct AddressSpace *space);
|
void limine_fb_remap(struct AddressSpace *space);
|
||||||
|
|
||||||
extern int framebuffer_count;
|
extern int framebuffer_count;
|
||||||
extern struct limine_framebuffer framebuffers[10];
|
extern struct limine_framebuffer framebuffers[10];
|
||||||
|
|
||||||
|
|
||||||
#endif//OS1_LIMINE_FB_H
|
#endif //OS1_LIMINE_FB_H
|
||||||
|
|||||||
@@ -9,17 +9,17 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
static volatile struct limine_memmap_request memmap_request = {
|
static volatile struct limine_memmap_request memmap_request = {
|
||||||
.id = LIMINE_MEMMAP_REQUEST,
|
.id = LIMINE_MEMMAP_REQUEST,
|
||||||
.revision = 0};
|
.revision = 0};
|
||||||
|
|
||||||
unsigned int limine_mm_count;
|
unsigned int limine_mm_count;
|
||||||
struct limine_memmap_entry limine_mm_entries[LIMINE_MM_MAX];
|
struct limine_memmap_entry limine_mm_entries[LIMINE_MM_MAX];
|
||||||
unsigned int limine_mm_overflow;
|
unsigned int limine_mm_overflow;
|
||||||
|
|
||||||
void limine_mm_save_response() {
|
void limine_mm_save_response() {
|
||||||
limine_mm_count = memmap_request.response->entry_count;
|
limine_mm_count = memmap_request.response->entry_count;
|
||||||
if (limine_mm_count > LIMINE_MM_MAX) {
|
if (limine_mm_count > LIMINE_MM_MAX) {
|
||||||
limine_mm_count = LIMINE_MM_MAX;
|
limine_mm_count = LIMINE_MM_MAX;
|
||||||
limine_mm_overflow = 1;
|
limine_mm_overflow = 1;
|
||||||
} else {
|
} else {
|
||||||
limine_mm_overflow = 0;
|
limine_mm_overflow = 0;
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
#define LIMINE_MM_MAX 256
|
#define LIMINE_MM_MAX 256
|
||||||
|
|
||||||
extern unsigned int limine_mm_count;
|
extern unsigned int limine_mm_count;
|
||||||
extern struct limine_memmap_entry limine_mm_entries[LIMINE_MM_MAX];
|
extern struct limine_memmap_entry limine_mm_entries[LIMINE_MM_MAX];
|
||||||
extern unsigned int limine_mm_overflow;
|
extern unsigned int limine_mm_overflow;
|
||||||
|
|
||||||
void limine_mm_save_response();
|
void limine_mm_save_response();
|
||||||
|
|
||||||
#endif//OS1_LIMINE_MM_H
|
#endif //OS1_LIMINE_MM_H
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
static volatile struct limine_module_request module_request = {
|
static volatile struct limine_module_request module_request = {
|
||||||
.id = LIMINE_MODULE_REQUEST,
|
.id = LIMINE_MODULE_REQUEST,
|
||||||
.revision = 0};
|
.revision = 0};
|
||||||
|
|
||||||
|
|
||||||
limine_file saved_modules[max_saved_modules];
|
limine_file saved_modules[max_saved_modules];
|
||||||
char saved_modules_data[max_saved_modules][max_saved_module_file_size] __attribute__((aligned(4096)));
|
char saved_modules_data[max_saved_modules][max_saved_module_file_size] __attribute__((aligned(4096)));
|
||||||
char saved_modules_names[max_saved_modules][max_saved_module_name] __attribute__((aligned(4096)));
|
char saved_modules_names[max_saved_modules][max_saved_module_name] __attribute__((aligned(4096)));
|
||||||
unsigned saved_modules_size = 0;
|
unsigned saved_modules_size = 0;
|
||||||
|
|
||||||
void limine_modules_save() {
|
void limine_modules_save() {
|
||||||
for (int i = 0; i < module_request.response->module_count; i++) {
|
for (int i = 0; i < module_request.response->module_count; i++) {
|
||||||
assert(i < max_saved_modules);
|
assert(i < max_saved_modules);
|
||||||
saved_modules_size++;
|
saved_modules_size++;
|
||||||
|
|||||||
@@ -7,15 +7,15 @@
|
|||||||
|
|
||||||
#include "limine.hpp"
|
#include "limine.hpp"
|
||||||
|
|
||||||
void limine_modules_save();
|
void limine_modules_save();
|
||||||
|
|
||||||
static constexpr unsigned max_saved_modules = 2;
|
static constexpr unsigned max_saved_modules = 2;
|
||||||
static constexpr unsigned max_saved_module_file_size = 1024 * 1024;
|
static constexpr unsigned max_saved_module_file_size = 1024 * 1024;
|
||||||
static constexpr unsigned max_saved_module_name = 256;
|
static constexpr unsigned max_saved_module_name = 256;
|
||||||
|
|
||||||
extern unsigned saved_modules_size;
|
extern unsigned saved_modules_size;
|
||||||
extern limine_file saved_modules[max_saved_modules];
|
extern limine_file saved_modules[max_saved_modules];
|
||||||
extern char saved_modules_data[max_saved_modules][max_saved_module_file_size] __attribute__((aligned(4096)));
|
extern char saved_modules_data[max_saved_modules][max_saved_module_file_size] __attribute__((aligned(4096)));
|
||||||
extern char saved_modules_names[max_saved_modules][max_saved_module_name] __attribute__((aligned(4096)));
|
extern char saved_modules_names[max_saved_modules][max_saved_module_name] __attribute__((aligned(4096)));
|
||||||
|
|
||||||
#endif//OS2_LIMINE_MODULES_HPP
|
#endif //OS2_LIMINE_MODULES_HPP
|
||||||
|
|||||||
@@ -12,19 +12,19 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
#define MAXGB 32ULL
|
#define MAXGB 32ULL
|
||||||
#define BITMAP_SIZE (((MAXGB) *1024ULL * 1024ULL) / (16ULL))
|
#define BITMAP_SIZE (((MAXGB) * 1024ULL * 1024ULL) / (16ULL))
|
||||||
#define MAX_PID (((BITMAP_SIZE) *4) - 4)
|
#define MAX_PID (((BITMAP_SIZE) * 4) - 4)
|
||||||
// Expected to be nulled by the bootloader
|
// Expected to be nulled by the bootloader
|
||||||
static struct FourPages used_bitmap[BITMAP_SIZE];
|
static struct FourPages used_bitmap[BITMAP_SIZE];
|
||||||
|
|
||||||
static Mutex memman_lock;
|
static Mutex memman_lock;
|
||||||
|
|
||||||
static uint64_t maxPid = 0;// Past the end
|
static uint64_t maxPid = 0; // Past the end
|
||||||
static uint64_t minPid = 0;
|
static uint64_t minPid = 0;
|
||||||
static uint64_t totalMem = 0;// Past the end
|
static uint64_t totalMem = 0; // Past the end
|
||||||
|
|
||||||
static uint64_t roundup4k(uint64_t addr) {
|
static uint64_t roundup4k(uint64_t addr) {
|
||||||
if ((addr & 0xFFF) == 0) return addr;
|
if ((addr & 0xFFF) == 0) return addr;
|
||||||
else {
|
else {
|
||||||
return (addr + 0x1000) & (~(0xFFFULL));
|
return (addr + 0x1000) & (~(0xFFFULL));
|
||||||
@@ -40,7 +40,7 @@ static uint64_t rounddown4k(uint64_t addr) {
|
|||||||
|
|
||||||
void setSts(uint64_t pid, enum PageStatus sts) {
|
void setSts(uint64_t pid, enum PageStatus sts) {
|
||||||
uint64_t rounddown = pid & (~(0b11ULL));
|
uint64_t rounddown = pid & (~(0b11ULL));
|
||||||
uint64_t idx = rounddown >> 2;
|
uint64_t idx = rounddown >> 2;
|
||||||
switch (pid & 0b11ULL) {
|
switch (pid & 0b11ULL) {
|
||||||
case 0:
|
case 0:
|
||||||
used_bitmap[idx].first = sts;
|
used_bitmap[idx].first = sts;
|
||||||
@@ -59,7 +59,7 @@ void setSts(uint64_t pid, enum PageStatus sts) {
|
|||||||
|
|
||||||
enum PageStatus getSts(uint64_t pid) {
|
enum PageStatus getSts(uint64_t pid) {
|
||||||
uint64_t rounddown = pid & (~(0b11ULL));
|
uint64_t rounddown = pid & (~(0b11ULL));
|
||||||
uint64_t idx = rounddown >> 2;
|
uint64_t idx = rounddown >> 2;
|
||||||
switch (pid & 0b11ULL) {
|
switch (pid & 0b11ULL) {
|
||||||
case 0:
|
case 0:
|
||||||
return used_bitmap[idx].first;
|
return used_bitmap[idx].first;
|
||||||
|
|||||||
@@ -7,23 +7,23 @@
|
|||||||
|
|
||||||
#include "limine.h"
|
#include "limine.h"
|
||||||
enum PageStatus {
|
enum PageStatus {
|
||||||
MEMMAN_STATE_FREE = 1,
|
MEMMAN_STATE_FREE = 1,
|
||||||
MEMMAN_STATE_USED = 2,
|
MEMMAN_STATE_USED = 2,
|
||||||
MEMMAN_STATE_RESERVED = 0,
|
MEMMAN_STATE_RESERVED = 0,
|
||||||
MEMMAN_STATE_RECLAIMABLE = 3,
|
MEMMAN_STATE_RECLAIMABLE = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FourPages {
|
struct FourPages {
|
||||||
enum PageStatus first : 2;
|
enum PageStatus first : 2;
|
||||||
enum PageStatus second : 2;
|
enum PageStatus second : 2;
|
||||||
enum PageStatus third : 2;
|
enum PageStatus third : 2;
|
||||||
enum PageStatus fourth : 2;
|
enum PageStatus fourth : 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
void parse_limine_memmap(struct limine_memmap_entry *entries, unsigned int num, uint64_t what_is_considered_free);
|
void parse_limine_memmap(struct limine_memmap_entry *entries, unsigned int num, uint64_t what_is_considered_free);
|
||||||
|
|
||||||
void *get4k();
|
void *get4k();
|
||||||
void free4k(void *page);
|
void free4k(void *page);
|
||||||
uint64_t get_free();
|
uint64_t get_free();
|
||||||
|
|
||||||
#endif//OS1_MEMMAN_H
|
#endif //OS1_MEMMAN_H
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ char *itoa(int value, char *str, int base) {
|
|||||||
// Invert the numbers.
|
// Invert the numbers.
|
||||||
while (low < ptr) {
|
while (low < ptr) {
|
||||||
char tmp = *low;
|
char tmp = *low;
|
||||||
*low++ = *ptr;
|
*low++ = *ptr;
|
||||||
*ptr-- = tmp;
|
*ptr-- = tmp;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ static inline void irqrestore(unsigned long flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void wrmsr(uint64_t msr, uint64_t value) {
|
static inline void wrmsr(uint64_t msr, uint64_t value) {
|
||||||
uint32_t low = value & 0xFFFFFFFF;
|
uint32_t low = value & 0xFFFFFFFF;
|
||||||
uint32_t high = value >> 32;
|
uint32_t high = value >> 32;
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"wrmsr"
|
"wrmsr"
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ void *AddressSpace::virt2real(void *virt) {
|
|||||||
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
|
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
|
||||||
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
|
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
|
||||||
|
|
||||||
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
||||||
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
||||||
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
|
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
|
||||||
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
|
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
|
||||||
|
|
||||||
uint64_t *pml4e = PML4 + pml4i;
|
uint64_t *pml4e = PML4 + pml4i;
|
||||||
if (!((*pml4e) & PAGE_PRESENT)) return 0;
|
if (!((*pml4e) & PAGE_PRESENT)) return 0;
|
||||||
@@ -82,10 +82,10 @@ int AddressSpace::map(void *virt, void *real, uint32_t flags) {
|
|||||||
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
|
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
|
||||||
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
|
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
|
||||||
|
|
||||||
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
||||||
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
||||||
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
|
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
|
||||||
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
|
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
|
||||||
|
|
||||||
|
|
||||||
uint64_t *pml4e = PML4 + pml4i;
|
uint64_t *pml4e = PML4 + pml4i;
|
||||||
@@ -125,7 +125,7 @@ int AddressSpace::map(void *virt, void *real, uint32_t flags) {
|
|||||||
|
|
||||||
uint64_t *ptsb = (uint64_t *) HHDM_P2V((*pdee & 0x000FFFFFFFFFF000ULL));
|
uint64_t *ptsb = (uint64_t *) HHDM_P2V((*pdee & 0x000FFFFFFFFFF000ULL));
|
||||||
uint64_t *ptse = &ptsb[ptsi];
|
uint64_t *ptse = &ptsb[ptsi];
|
||||||
*ptse = ((uint64_t) real & 0x000FFFFFFFFFF000ULL) | (flags & 0xFFF) | PAGE_PRESENT;
|
*ptse = ((uint64_t) real & 0x000FFFFFFFFFF000ULL) | (flags & 0xFFF) | PAGE_PRESENT;
|
||||||
invlpg((void *) ((uint64_t) virt & 0x000FFFFFFFFFF000ULL));
|
invlpg((void *) ((uint64_t) virt & 0x000FFFFFFFFFF000ULL));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -136,10 +136,10 @@ int AddressSpace::unmap(void *virt) {
|
|||||||
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
|
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
|
||||||
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
|
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
|
||||||
|
|
||||||
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
||||||
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
||||||
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
|
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
|
||||||
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
|
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
|
||||||
|
|
||||||
uint64_t *pml4e = PML4 + pml4i;
|
uint64_t *pml4e = PML4 + pml4i;
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ FDT *AddressSpace::getFdt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static volatile struct limine_kernel_address_request kernel_address_request = {
|
static volatile struct limine_kernel_address_request kernel_address_request = {
|
||||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||||
.revision = 0};
|
.revision = 0};
|
||||||
|
|
||||||
void limine_kern_save_response() {
|
void limine_kern_save_response() {
|
||||||
@@ -180,10 +180,10 @@ void limine_kern_save_response() {
|
|||||||
static uint64_t early_pages[EARLY_PAGES_SIZE][512] __attribute__((aligned(PAGE_SIZE)));
|
static uint64_t early_pages[EARLY_PAGES_SIZE][512] __attribute__((aligned(PAGE_SIZE)));
|
||||||
static uint64_t early_pages_used = 0;
|
static uint64_t early_pages_used = 0;
|
||||||
|
|
||||||
uintptr_t kernel_phys_base;
|
uintptr_t kernel_phys_base;
|
||||||
uintptr_t kernel_virt_base;
|
uintptr_t kernel_virt_base;
|
||||||
|
|
||||||
void map_hddm(uint64_t *pml4) {
|
void map_hddm(uint64_t *pml4) {
|
||||||
assert2(kernel_virt_base != 0, "Kernel virt address not loaded!");
|
assert2(kernel_virt_base != 0, "Kernel virt address not loaded!");
|
||||||
assert2(kernel_phys_base != 0, "Kernel phys address not loaded!");
|
assert2(kernel_phys_base != 0, "Kernel phys address not loaded!");
|
||||||
|
|
||||||
@@ -191,8 +191,8 @@ void map_hddm(uint64_t *pml4) {
|
|||||||
// Which is true if the first bytes of memory, where the kernel is are identity mapped,
|
// Which is true if the first bytes of memory, where the kernel is are identity mapped,
|
||||||
// Which is true if we're using Limine
|
// Which is true if we're using Limine
|
||||||
for (uint64_t i = 0; i < HHDM_SIZE; i++) {
|
for (uint64_t i = 0; i < HHDM_SIZE; i++) {
|
||||||
void *virt = (void *) (HHDM_BEGIN + i * 1024ULL * 1024ULL * 1024ULL);
|
void *virt = (void *) (HHDM_BEGIN + i * 1024ULL * 1024ULL * 1024ULL);
|
||||||
void *real = (void *) (i * 1024ULL * 1024ULL * 1024ULL);
|
void *real = (void *) (i * 1024ULL * 1024ULL * 1024ULL);
|
||||||
|
|
||||||
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
|
||||||
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
|
|
||||||
#include "PointersCollection.hpp"
|
#include "PointersCollection.hpp"
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
#define KERN_V2P(a) ((((uintptr_t) (a) + kernel_phys_base) & ~kernel_virt_base))
|
#define KERN_V2P(a) ((((uintptr_t) (a) + kernel_phys_base) & ~kernel_virt_base))
|
||||||
#define KERN_P2V(a) ((((uintptr_t) (a) -kernel_phys_base) | kernel_virt_base))
|
#define KERN_P2V(a) ((((uintptr_t) (a) -kernel_phys_base) | kernel_virt_base))
|
||||||
|
|
||||||
#define HHDM_BEGIN 0xfffff80000000000ULL
|
#define HHDM_BEGIN 0xfffff80000000000ULL
|
||||||
#define HHDM_SIZE 32ULL// In GB
|
#define HHDM_SIZE 32ULL // In GB
|
||||||
#define HHDM_V2P(a) ((((uintptr_t) (a)) & ~HHDM_BEGIN))
|
#define HHDM_V2P(a) ((((uintptr_t) (a)) & ~HHDM_BEGIN))
|
||||||
#define HHDM_P2V(a) ((((uintptr_t) (a)) | HHDM_BEGIN))
|
#define HHDM_P2V(a) ((((uintptr_t) (a)) | HHDM_BEGIN))
|
||||||
|
|
||||||
@@ -28,9 +28,9 @@ public:
|
|||||||
AddressSpace(uint64_t *PML4);
|
AddressSpace(uint64_t *PML4);
|
||||||
~AddressSpace();
|
~AddressSpace();
|
||||||
|
|
||||||
void *virt2real(void *virt);
|
void *virt2real(void *virt);
|
||||||
int map(void *virt, void *real, uint32_t flags);
|
int map(void *virt, void *real, uint32_t flags);
|
||||||
int unmap(void *virt);
|
int unmap(void *virt);
|
||||||
|
|
||||||
uint64_t *get_cr3() {
|
uint64_t *get_cr3() {
|
||||||
return PML4;
|
return PML4;
|
||||||
@@ -46,22 +46,22 @@ private:
|
|||||||
// Pointer to PML4 in HDDM
|
// Pointer to PML4 in HDDM
|
||||||
uint64_t *PML4;
|
uint64_t *PML4;
|
||||||
|
|
||||||
FDT *_fdt = nullptr;
|
FDT *_fdt = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern AddressSpace *KERN_AddressSpace;
|
extern AddressSpace *KERN_AddressSpace;
|
||||||
|
|
||||||
extern uintptr_t kernel_phys_base;
|
extern uintptr_t kernel_phys_base;
|
||||||
extern uintptr_t kernel_virt_base;
|
extern uintptr_t kernel_virt_base;
|
||||||
void limine_kern_save_response();
|
void limine_kern_save_response();
|
||||||
|
|
||||||
#define PAGE_PS (1 << 7)
|
#define PAGE_PS (1 << 7)
|
||||||
#define PAGE_RW (1 << 1)
|
#define PAGE_RW (1 << 1)
|
||||||
#define PAGE_USER (1 << 2)
|
#define PAGE_USER (1 << 2)
|
||||||
#define PAGE_PRESENT (0x01ULL)
|
#define PAGE_PRESENT (0x01ULL)
|
||||||
|
|
||||||
void map_hddm(uint64_t *pml4);
|
void map_hddm(uint64_t *pml4);
|
||||||
|
|
||||||
extern "C" void _tlb_flush();
|
extern "C" void _tlb_flush();
|
||||||
|
|
||||||
#endif//OS1_PAGING_H
|
#endif //OS1_PAGING_H
|
||||||
|
|||||||
@@ -9,18 +9,18 @@
|
|||||||
#include "io.hpp"
|
#include "io.hpp"
|
||||||
#include "task.hpp"
|
#include "task.hpp"
|
||||||
|
|
||||||
#define PORT 0x3f8// COM1
|
#define PORT 0x3f8 // COM1
|
||||||
|
|
||||||
int init_serial() {
|
int init_serial() {
|
||||||
outb(PORT + 1, 0x00);// Disable all interrupts
|
outb(PORT + 1, 0x00); // Disable all interrupts
|
||||||
outb(PORT + 3, 0x80);// Enable DLAB (set baud rate divisor)
|
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||||
outb(PORT + 0, 0x03);// Set divisor to 3 (lo byte) 38400 baud
|
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||||
outb(PORT + 1, 0x00);// (hi byte)
|
outb(PORT + 1, 0x00); // (hi byte)
|
||||||
outb(PORT + 3, 0x03);// 8 bits, no parity, one stop bit
|
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||||
outb(PORT + 2, 0xC7);// Enable FIFO, clear them, with 14-byte threshold
|
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||||
outb(PORT + 4, 0x0B);// IRQs enabled, RTS/DSR set
|
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||||
outb(PORT + 4, 0x1E);// Set in loopback mode, test the serial chip
|
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||||
outb(PORT + 0, 0xAE);// Test serial chip (send byte 0xAE and check if serial returns same byte)
|
outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||||
|
|
||||||
// Check if serial is faulty (i.e: not same byte as sent)
|
// Check if serial is faulty (i.e: not same byte as sent)
|
||||||
if (inb(PORT + 0) != 0xAE) {
|
if (inb(PORT + 0) != 0xAE) {
|
||||||
|
|||||||
@@ -7,15 +7,15 @@
|
|||||||
|
|
||||||
#include "misc.hpp"
|
#include "misc.hpp"
|
||||||
|
|
||||||
int init_serial();
|
int init_serial();
|
||||||
|
|
||||||
int serial_received();
|
int serial_received();
|
||||||
char read_serial();
|
char read_serial();
|
||||||
|
|
||||||
int is_transmit_empty();
|
int is_transmit_empty();
|
||||||
void write_serial(char a);
|
void write_serial(char a);
|
||||||
void writestr(const char *a);
|
void writestr(const char *a);
|
||||||
void write_serial_no_yield(char a);
|
void write_serial_no_yield(char a);
|
||||||
void writestr_no_yield(const char *a);
|
void writestr_no_yield(const char *a);
|
||||||
|
|
||||||
#endif//OS1_SERIAL_H
|
#endif //OS1_SERIAL_H
|
||||||
|
|||||||
@@ -20,30 +20,30 @@
|
|||||||
// even with completely broken 16-bit segments somehow
|
// even with completely broken 16-bit segments somehow
|
||||||
// But what happens with something more complex is completely bonkers
|
// But what happens with something more complex is completely bonkers
|
||||||
struct STAR {
|
struct STAR {
|
||||||
unsigned unused : 32;
|
unsigned unused : 32;
|
||||||
unsigned call_cs_ss : 16;
|
unsigned call_cs_ss : 16;
|
||||||
unsigned ret_cs_ss : 16;
|
unsigned ret_cs_ss : 16;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
static_assert(sizeof(STAR) == 8);
|
static_assert(sizeof(STAR) == 8);
|
||||||
|
|
||||||
void setup_syscalls() {
|
void setup_syscalls() {
|
||||||
union {
|
union {
|
||||||
STAR star;
|
STAR star;
|
||||||
uint64_t bytes;
|
uint64_t bytes;
|
||||||
} __attribute__((__packed__)) newstar{};
|
} __attribute__((__packed__)) newstar{};
|
||||||
|
|
||||||
newstar.star.ret_cs_ss = (GDTSEL(gdt_data_user) - 8) | 0x3;
|
newstar.star.ret_cs_ss = (Arch::GDT::gdt_data_user.selector() - 8) | 0x3;
|
||||||
assert(newstar.star.ret_cs_ss + 8 == (GDTSEL(gdt_data_user) | 0x3));
|
assert(newstar.star.ret_cs_ss + 8 == (Arch::GDT::gdt_data_user.selector() | 0x3));
|
||||||
assert(newstar.star.ret_cs_ss + 16 == (GDTSEL(gdt_code_user) | 0x3));
|
assert(newstar.star.ret_cs_ss + 16 == (Arch::GDT::gdt_code_user.selector() | 0x3));
|
||||||
|
|
||||||
newstar.star.call_cs_ss = (GDTSEL(gdt_code));
|
newstar.star.call_cs_ss = (Arch::GDT::gdt_code.selector());
|
||||||
assert(newstar.star.call_cs_ss == GDTSEL(gdt_code));
|
assert(newstar.star.call_cs_ss == Arch::GDT::gdt_code.selector());
|
||||||
assert(newstar.star.call_cs_ss + 8 == GDTSEL(gdt_data));
|
assert(newstar.star.call_cs_ss + 8 == Arch::GDT::gdt_data.selector());
|
||||||
|
|
||||||
wrmsr(0xc0000081, newstar.bytes);
|
wrmsr(0xc0000081, newstar.bytes);
|
||||||
wrmsr(0xc0000082, reinterpret_cast<uint64_t>(&_syscall_entrypoint));
|
wrmsr(0xc0000082, reinterpret_cast<uint64_t>(&_syscall_entrypoint));
|
||||||
wrmsr(0xc0000084, (1 << 9));// IA32_FMASK, mask interrupts
|
wrmsr(0xc0000084, (1 << 9)); // IA32_FMASK, mask interrupts
|
||||||
|
|
||||||
wrmsr(0xC0000080, rdmsr(0xC0000080) | 0b1);
|
wrmsr(0xC0000080, rdmsr(0xC0000080) | 0b1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
void setup_syscalls();
|
void setup_syscalls();
|
||||||
|
|
||||||
extern "C" void _syscall_entrypoint();
|
extern "C" void _syscall_entrypoint();
|
||||||
extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx);
|
extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx);
|
||||||
|
|
||||||
#endif//OS2_SYSCALLS_HPP
|
#endif //OS2_SYSCALLS_HPP
|
||||||
|
|||||||
@@ -30,32 +30,32 @@ void sanity_check_frame(struct task_frame *cur_frame) {
|
|||||||
assert(cur_frame->ss != 0);
|
assert(cur_frame->ss != 0);
|
||||||
assert(cur_frame->cs != 0);
|
assert(cur_frame->cs != 0);
|
||||||
assert(cur_frame->sp != 0);
|
assert(cur_frame->sp != 0);
|
||||||
assert2((cur_frame->ss == GDTSEL(gdt_data) || (cur_frame->ss == GDTSEL(gdt_data_user)) | 0x3), "SS wrong!");
|
assert2((cur_frame->ss == Arch::GDT::gdt_data.selector() || (cur_frame->ss == Arch::GDT::gdt_data_user.selector()) | 0x3), "SS wrong!");
|
||||||
assert2((cur_frame->cs == GDTSEL(gdt_code) || (cur_frame->ss == GDTSEL(gdt_code_user)) | 0x3), "CS wrong!");
|
assert2((cur_frame->cs == Arch::GDT::gdt_code.selector() || (cur_frame->ss == Arch::GDT::gdt_code_user.selector()) | 0x3), "CS wrong!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::atomic<uint64_t> max_pid = 0;
|
std::atomic<uint64_t> max_pid = 0;
|
||||||
Mutex AllTasks_lock;
|
Mutex AllTasks_lock;
|
||||||
SkipList<uint64_t, Task *> AllTasks;
|
SkipList<uint64_t, Task *> AllTasks;
|
||||||
|
|
||||||
static List<Task *>::Node *RunningTask;
|
static List<Task *>::Node *RunningTask;
|
||||||
|
|
||||||
static Spinlock NextTasks_lock;
|
static Spinlock NextTasks_lock;
|
||||||
static List<Task *> NextTasks;
|
static List<Task *> NextTasks;
|
||||||
|
|
||||||
// Task freer
|
// Task freer
|
||||||
Mutex TasksToFree_lock;
|
Mutex TasksToFree_lock;
|
||||||
CV TasksToFree_cv;
|
CV TasksToFree_cv;
|
||||||
List<List<Task *>::Node *> TasksToFree;
|
List<List<Task *>::Node *> TasksToFree;
|
||||||
|
|
||||||
// Waiting
|
// Waiting
|
||||||
Mutex WaitingTasks_mlock;
|
Mutex WaitingTasks_mlock;
|
||||||
CV WaitingTasks_cv;
|
CV WaitingTasks_cv;
|
||||||
SkipList<uint64_t, List<Task *>::Node *> WaitingTasks;
|
SkipList<uint64_t, List<Task *>::Node *> WaitingTasks;
|
||||||
|
|
||||||
static std::atomic<bool> initialized = false;
|
static std::atomic<bool> initialized = false;
|
||||||
|
|
||||||
static void free_task(struct Task *t) {
|
static void free_task(struct Task *t) {
|
||||||
kfree(t->kstack);
|
kfree(t->kstack);
|
||||||
kfree(t->name);
|
kfree(t->name);
|
||||||
kfree(t->fxsave);
|
kfree(t->fxsave);
|
||||||
@@ -110,28 +110,28 @@ static void task_freer() {
|
|||||||
|
|
||||||
struct Task *new_ktask(void (*fn)(), const char *name, bool start) {
|
struct Task *new_ktask(void (*fn)(), const char *name, bool start) {
|
||||||
struct Task *newt = static_cast<Task *>(kmalloc(sizeof(struct Task)));
|
struct Task *newt = static_cast<Task *>(kmalloc(sizeof(struct Task)));
|
||||||
newt->kstack = static_cast<uint64_t *>(kmalloc(TASK_SS));
|
newt->kstack = static_cast<uint64_t *>(kmalloc(TASK_SS));
|
||||||
newt->name = static_cast<char *>(kmalloc(strlen(name) + 1));
|
newt->name = static_cast<char *>(kmalloc(strlen(name) + 1));
|
||||||
newt->fxsave = static_cast<char *>(kmalloc(512));
|
newt->fxsave = static_cast<char *>(kmalloc(512));
|
||||||
strcpy(name, newt->name);
|
strcpy(name, newt->name);
|
||||||
|
|
||||||
newt->frame.sp = ((((uintptr_t) newt->kstack) + (TASK_SS - 9) - 1) & (~0xFULL)) + 8;// Ensure 16byte alignment
|
newt->frame.sp = ((((uintptr_t) newt->kstack) + (TASK_SS - 9) - 1) & (~0xFULL)) + 8; // Ensure 16byte alignment
|
||||||
// It should be aligned before call, therefore on function entry it should be misaligned by 8 bytes
|
// It should be aligned before call, therefore on function entry it should be misaligned by 8 bytes
|
||||||
assert((newt->frame.sp & 0xFULL) == 8);
|
assert((newt->frame.sp & 0xFULL) == 8);
|
||||||
|
|
||||||
newt->frame.ip = (uint64_t) fn;
|
newt->frame.ip = (uint64_t) fn;
|
||||||
newt->frame.cs = GDTSEL(gdt_code);
|
newt->frame.cs = Arch::GDT::gdt_code.selector();
|
||||||
newt->frame.ss = GDTSEL(gdt_data);
|
newt->frame.ss = Arch::GDT::gdt_data.selector();
|
||||||
|
|
||||||
for (int i = 0; i < 512; i++) newt->fxsave[i] = 0;
|
for (int i = 0; i < 512; i++) newt->fxsave[i] = 0;
|
||||||
|
|
||||||
newt->frame.flags = flags();
|
newt->frame.flags = flags();
|
||||||
newt->frame.guard = IDT_GUARD;
|
newt->frame.guard = IDT_GUARD;
|
||||||
newt->addressSpace = KERN_AddressSpace;
|
newt->addressSpace = KERN_AddressSpace;
|
||||||
newt->state = start ? TS_RUNNING : TS_BLOCKED;
|
newt->state = start ? TS_RUNNING : TS_BLOCKED;
|
||||||
newt->mode = TASKMODE_KERN;
|
newt->mode = TASKMODE_KERN;
|
||||||
newt->pid = max_pid.fetch_add(1);
|
newt->pid = max_pid.fetch_add(1);
|
||||||
newt->used_time = 0;
|
newt->used_time = 0;
|
||||||
|
|
||||||
sanity_check_frame(&newt->frame);
|
sanity_check_frame(&newt->frame);
|
||||||
if (start) {
|
if (start) {
|
||||||
@@ -150,45 +150,45 @@ struct Task *new_ktask(void (*fn)(), const char *name, bool start) {
|
|||||||
return newt;
|
return newt;
|
||||||
}
|
}
|
||||||
struct Task *new_utask(void (*entrypoint)(), const char *name) {
|
struct Task *new_utask(void (*entrypoint)(), const char *name) {
|
||||||
Task *newt = static_cast<Task *>(kmalloc(sizeof(struct Task)));
|
Task *newt = static_cast<Task *>(kmalloc(sizeof(struct Task)));
|
||||||
newt->kstack = static_cast<uint64_t *>(kmalloc(TASK_SS));
|
newt->kstack = static_cast<uint64_t *>(kmalloc(TASK_SS));
|
||||||
newt->name = static_cast<char *>(kmalloc(strlen(name) + 1));
|
newt->name = static_cast<char *>(kmalloc(strlen(name) + 1));
|
||||||
newt->fxsave = static_cast<char *>(kmalloc(512));
|
newt->fxsave = static_cast<char *>(kmalloc(512));
|
||||||
strcpy(name, newt->name);
|
strcpy(name, newt->name);
|
||||||
|
|
||||||
newt->frame.ip = (uint64_t) entrypoint;
|
newt->frame.ip = (uint64_t) entrypoint;
|
||||||
newt->frame.cs = GDTSEL(gdt_code_user) | 0x3;
|
newt->frame.cs = Arch::GDT::gdt_code_user.selector() | 0x3;
|
||||||
newt->frame.ss = GDTSEL(gdt_data_user) | 0x3;
|
newt->frame.ss = Arch::GDT::gdt_data_user.selector() | 0x3;
|
||||||
|
|
||||||
for (int i = 0; i < 512; i++) newt->fxsave[i] = 0;
|
for (int i = 0; i < 512; i++) newt->fxsave[i] = 0;
|
||||||
|
|
||||||
newt->frame.flags = flags();
|
newt->frame.flags = flags();
|
||||||
newt->frame.guard = IDT_GUARD;
|
newt->frame.guard = IDT_GUARD;
|
||||||
newt->addressSpace = new AddressSpace();
|
newt->addressSpace = new AddressSpace();
|
||||||
newt->vma = new VMA(newt->addressSpace);
|
newt->vma = new VMA(newt->addressSpace);
|
||||||
newt->state = TS_BLOCKED;
|
newt->state = TS_BLOCKED;
|
||||||
newt->mode = TASKMODE_USER;
|
newt->mode = TASKMODE_USER;
|
||||||
newt->pid = max_pid.fetch_add(1);
|
newt->pid = max_pid.fetch_add(1);
|
||||||
newt->used_time = 0;
|
newt->used_time = 0;
|
||||||
|
|
||||||
task_pointer *taskptr = static_cast<task_pointer *>(
|
task_pointer *taskptr = static_cast<task_pointer *>(
|
||||||
newt->vma->mmap_mem(reinterpret_cast<void *>(TASK_POINTER),
|
newt->vma->mmap_mem(reinterpret_cast<void *>(TASK_POINTER),
|
||||||
sizeof(task_pointer), 0, PAGE_RW | PAGE_USER));// FIXME: this is probably unsafe
|
sizeof(task_pointer), 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe
|
||||||
assert((uintptr_t) taskptr == TASK_POINTER);
|
assert((uintptr_t) taskptr == TASK_POINTER);
|
||||||
|
|
||||||
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(newt->addressSpace->virt2real(taskptr)));
|
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(newt->addressSpace->virt2real(taskptr)));
|
||||||
|
|
||||||
newt->entry_ksp_val = ((((uintptr_t) newt->kstack) + (TASK_SS - 9) - 1) & (~0xFULL));// Ensure 16byte alignment
|
newt->entry_ksp_val = ((((uintptr_t) newt->kstack) + (TASK_SS - 9) - 1) & (~0xFULL)); // Ensure 16byte alignment
|
||||||
// It should be aligned before call, therefore it actually should be aligned here
|
// It should be aligned before call, therefore it actually should be aligned here
|
||||||
assert((newt->entry_ksp_val & 0xFULL) == 0);
|
assert((newt->entry_ksp_val & 0xFULL) == 0);
|
||||||
|
|
||||||
taskptr_real->taskptr = newt;
|
taskptr_real->taskptr = newt;
|
||||||
taskptr_real->entry_ksp_val = newt->entry_ksp_val;
|
taskptr_real->entry_ksp_val = newt->entry_ksp_val;
|
||||||
taskptr_real->ret_sp = 0x0;
|
taskptr_real->ret_sp = 0x0;
|
||||||
|
|
||||||
void *ustack = newt->vma->mmap_mem(NULL, TASK_SS, 0, PAGE_RW | PAGE_USER);
|
void *ustack = newt->vma->mmap_mem(NULL, TASK_SS, 0, PAGE_RW | PAGE_USER);
|
||||||
|
|
||||||
newt->frame.sp = ((((uintptr_t) ustack) + (TASK_SS - 17) - 1) & (~0xFULL)) + 8;// Ensure 16byte alignment
|
newt->frame.sp = ((((uintptr_t) ustack) + (TASK_SS - 17) - 1) & (~0xFULL)) + 8; // Ensure 16byte alignment
|
||||||
// It should be aligned before call, therefore on function entry it should be misaligned by 8 bytes
|
// It should be aligned before call, therefore on function entry it should be misaligned by 8 bytes
|
||||||
assert((newt->frame.sp & 0xFULL) == 8);
|
assert((newt->frame.sp & 0xFULL) == 8);
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ struct Task *new_utask(void (*entrypoint)(), const char *name) {
|
|||||||
|
|
||||||
List<Task *>::Node *start_task(struct Task *task) {
|
List<Task *>::Node *start_task(struct Task *task) {
|
||||||
assert(task->state != TS_RUNNING);
|
assert(task->state != TS_RUNNING);
|
||||||
task->state = TS_RUNNING;
|
task->state = TS_RUNNING;
|
||||||
auto new_node = NextTasks.create_node(task);
|
auto new_node = NextTasks.create_node(task);
|
||||||
{
|
{
|
||||||
SpinlockLockNoInt l(NextTasks_lock);
|
SpinlockLockNoInt l(NextTasks_lock);
|
||||||
@@ -267,7 +267,7 @@ static void task_waker() {
|
|||||||
|
|
||||||
while (WaitingTasks.begin() != WaitingTasks.end() && WaitingTasks.begin()->key <= micros && WaitingTasks.begin()->data->val->state != TS_RUNNING) {
|
while (WaitingTasks.begin() != WaitingTasks.end() && WaitingTasks.begin()->key <= micros && WaitingTasks.begin()->data->val->state != TS_RUNNING) {
|
||||||
auto *node = &*WaitingTasks.begin();
|
auto *node = &*WaitingTasks.begin();
|
||||||
auto task = WaitingTasks.begin()->data;
|
auto task = WaitingTasks.begin()->data;
|
||||||
|
|
||||||
// TODO this is all ugly
|
// TODO this is all ugly
|
||||||
uint64_t l1 = 0;
|
uint64_t l1 = 0;
|
||||||
@@ -282,7 +282,7 @@ static void task_waker() {
|
|||||||
|
|
||||||
assert(l1 - l2 == 1);
|
assert(l1 - l2 == 1);
|
||||||
task->val->sleep_until = 0;
|
task->val->sleep_until = 0;
|
||||||
task->val->state = TS_RUNNING;
|
task->val->state = TS_RUNNING;
|
||||||
|
|
||||||
{
|
{
|
||||||
SpinlockLockNoInt l(NextTasks_lock);
|
SpinlockLockNoInt l(NextTasks_lock);
|
||||||
@@ -325,15 +325,15 @@ extern "C" void switch_task(struct task_frame *cur_frame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressSpace *oldspace = nullptr;
|
AddressSpace *oldspace = nullptr;
|
||||||
List<Task *>::Node *next;
|
List<Task *>::Node *next;
|
||||||
|
|
||||||
{
|
{
|
||||||
SpinlockLockNoIntAssert ntl(NextTasks_lock);
|
SpinlockLockNoIntAssert ntl(NextTasks_lock);
|
||||||
|
|
||||||
static uint64_t lastSwitchMicros = 0;
|
static uint64_t lastSwitchMicros = 0;
|
||||||
uint64_t prevSwitchMicros = lastSwitchMicros;
|
uint64_t prevSwitchMicros = lastSwitchMicros;
|
||||||
lastSwitchMicros = micros;
|
lastSwitchMicros = micros;
|
||||||
|
|
||||||
if (RunningTask) {
|
if (RunningTask) {
|
||||||
RunningTask->val->frame = *cur_frame;
|
RunningTask->val->frame = *cur_frame;
|
||||||
@@ -352,7 +352,7 @@ extern "C" void switch_task(struct task_frame *cur_frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RunningTask = next;
|
RunningTask = next;
|
||||||
*cur_frame = RunningTask->val->frame;
|
*cur_frame = RunningTask->val->frame;
|
||||||
__builtin_memcpy(temp_fxsave, RunningTask->val->fxsave, 512);
|
__builtin_memcpy(temp_fxsave, RunningTask->val->fxsave, 512);
|
||||||
|
|
||||||
AddressSpace *newspace = RunningTask->val->addressSpace;
|
AddressSpace *newspace = RunningTask->val->addressSpace;
|
||||||
|
|||||||
@@ -28,43 +28,43 @@ struct AddressSpace;
|
|||||||
class VMA;
|
class VMA;
|
||||||
|
|
||||||
struct Task {
|
struct Task {
|
||||||
uint64_t entry_ksp_val;
|
uint64_t entry_ksp_val;
|
||||||
struct task_frame frame;
|
struct task_frame frame;
|
||||||
uint64_t pid;
|
uint64_t pid;
|
||||||
std::atomic<uint64_t> used_time;
|
std::atomic<uint64_t> used_time;
|
||||||
AddressSpace *addressSpace;
|
AddressSpace *addressSpace;
|
||||||
VMA *vma;
|
VMA *vma;
|
||||||
uint64_t *kstack;
|
uint64_t *kstack;
|
||||||
char *fxsave;
|
char *fxsave;
|
||||||
char *name;
|
char *name;
|
||||||
enum TaskMode mode;
|
enum TaskMode mode;
|
||||||
uint64_t sleep_until;
|
uint64_t sleep_until;
|
||||||
enum TaskState state;
|
enum TaskState state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct task_pointer {
|
struct task_pointer {
|
||||||
Task *taskptr;
|
Task *taskptr;
|
||||||
uint64_t entry_ksp_val;
|
uint64_t entry_ksp_val;
|
||||||
uint64_t ret_sp;
|
uint64_t ret_sp;
|
||||||
uint64_t ret_flags;
|
uint64_t ret_flags;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct Task *cur_task();
|
struct Task *cur_task();
|
||||||
List<Task *>::Node *extract_running_task_node();
|
List<Task *>::Node *extract_running_task_node();
|
||||||
|
|
||||||
void init_tasks();
|
void init_tasks();
|
||||||
struct Task *new_ktask(void (*fn)(), const char *name, bool start = true);
|
struct Task *new_ktask(void (*fn)(), const char *name, bool start = true);
|
||||||
struct Task *new_utask(void (*entrypoint)(), const char *name);
|
struct Task *new_utask(void (*entrypoint)(), const char *name);
|
||||||
List<Task *>::Node *start_task(struct Task *task);
|
List<Task *>::Node *start_task(struct Task *task);
|
||||||
void remove_self();
|
void remove_self();
|
||||||
void sleep_self(uint64_t diff);
|
void sleep_self(uint64_t diff);
|
||||||
|
|
||||||
void self_block();
|
void self_block();
|
||||||
|
|
||||||
class Spinlock;
|
class Spinlock;
|
||||||
void self_block(Spinlock &to_unlock);
|
void self_block(Spinlock &to_unlock);
|
||||||
void unblock(Task *what);
|
void unblock(Task *what);
|
||||||
void unblock(List<Task *>::Node *what);
|
void unblock(List<Task *>::Node *what);
|
||||||
|
|
||||||
extern "C" void switch_task(struct task_frame *cur_frame);
|
extern "C" void switch_task(struct task_frame *cur_frame);
|
||||||
|
|
||||||
@@ -73,8 +73,8 @@ using TaskPID = uint64_t;
|
|||||||
// TODO: that's quite inefficient!
|
// TODO: that's quite inefficient!
|
||||||
SkipList<uint64_t, std::pair<String, TaskPID>> getTaskTimePerPid();
|
SkipList<uint64_t, std::pair<String, TaskPID>> getTaskTimePerPid();
|
||||||
|
|
||||||
void yield_self();
|
void yield_self();
|
||||||
|
|
||||||
extern "C" void _yield_self_kern();// Expects the caller to save interrupt state
|
extern "C" void _yield_self_kern(); // Expects the caller to save interrupt state
|
||||||
|
|
||||||
#endif//OS1_TASK_H
|
#endif //OS1_TASK_H
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
volatile std::atomic<uint64_t> ticks;
|
volatile std::atomic<uint64_t> ticks;
|
||||||
volatile std::atomic<uint64_t> micros;
|
volatile std::atomic<uint64_t> micros;
|
||||||
|
|
||||||
unsigned read_pit_count(void) {
|
unsigned read_pit_count(void) {
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
// Disable interrupts
|
// Disable interrupts
|
||||||
@@ -19,8 +19,8 @@ unsigned read_pit_count(void) {
|
|||||||
// al = channel in bits 6 and 7, remaining bits clear
|
// al = channel in bits 6 and 7, remaining bits clear
|
||||||
outb(0x43, 0b0000000);
|
outb(0x43, 0b0000000);
|
||||||
|
|
||||||
count = inb(0x40); // Low byte
|
count = inb(0x40); // Low byte
|
||||||
count |= inb(0x40) << 8;// High byte
|
count |= inb(0x40) << 8; // High byte
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@@ -30,15 +30,15 @@ void set_pit_count(unsigned count) {
|
|||||||
// cli();
|
// cli();
|
||||||
|
|
||||||
// Set low byte
|
// Set low byte
|
||||||
outb(0x40, count & 0xFF); // Low byte
|
outb(0x40, count & 0xFF); // Low byte
|
||||||
outb(0x40, (count & 0xFF00) >> 8);// High byte
|
outb(0x40, (count & 0xFF00) >> 8); // High byte
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Very rough but I don't care right now
|
// Very rough but I don't care right now
|
||||||
// About 1000 HZ freq
|
// About 1000 HZ freq
|
||||||
#define RELOAD_VAL 1193
|
#define RELOAD_VAL 1193
|
||||||
#define FREQ (1193182 / (RELOAD_VAL))
|
#define FREQ (1193182 / (RELOAD_VAL))
|
||||||
#define MICROS_PER_TICK (1000000 / (FREQ))
|
#define MICROS_PER_TICK (1000000 / (FREQ))
|
||||||
|
|
||||||
void init_timer() {
|
void init_timer() {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
extern volatile std::atomic<uint64_t> ticks;
|
extern volatile std::atomic<uint64_t> ticks;
|
||||||
extern volatile std::atomic<uint64_t> micros;
|
extern volatile std::atomic<uint64_t> micros;
|
||||||
|
|
||||||
void init_timer();
|
void init_timer();
|
||||||
void timer_tick();
|
void timer_tick();
|
||||||
|
|
||||||
#endif//OS1_TIMER_H
|
#endif //OS1_TIMER_H
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ BytesFormatter::BytesFormat BytesFormatter::format(unsigned long long int bytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
String BytesFormatter::formatStr(unsigned long long int bytes) {
|
String BytesFormatter::formatStr(unsigned long long int bytes) {
|
||||||
auto fmt = format(bytes);
|
auto fmt = format(bytes);
|
||||||
String out;
|
String out;
|
||||||
out += fmt.number;
|
out += fmt.number;
|
||||||
out += " ";
|
out += " ";
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ class BytesFormatter {
|
|||||||
public:
|
public:
|
||||||
/// Structure for returning the processed byte value
|
/// Structure for returning the processed byte value
|
||||||
struct BytesFormat {
|
struct BytesFormat {
|
||||||
String number;///< Number part of the value
|
String number; ///< Number part of the value
|
||||||
String prefix;///< Unit of measure
|
String prefix; ///< Unit of measure
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Formats the bytes in BytesFormat format
|
/// Formats the bytes in BytesFormat format
|
||||||
@@ -28,4 +28,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_BYTESFORMATTER_HPP
|
#endif //OS2_BYTESFORMATTER_HPP
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T *_lock;
|
T *_lock;
|
||||||
bool suc;
|
bool suc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_LOCKGUARD_H
|
#endif //OS2_LOCKGUARD_H
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
|
|
||||||
void spinlock() {
|
void spinlock() {
|
||||||
assert2(!are_interrupts_enabled(), "Assuming all spinlocks are without interrupts");
|
assert2(!are_interrupts_enabled(), "Assuming all spinlocks are without interrupts");
|
||||||
while (!try_lock()) { yield_self(); }// FIXME: Should be pause!
|
while (!try_lock()) { yield_self(); } // FIXME: Should be pause!
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock() {
|
void unlock() {
|
||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<bool> locked = false;
|
std::atomic<bool> locked = false;
|
||||||
Task *owner;
|
Task *owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(std::is_trivially_copyable_v<Spinlock> == true);
|
static_assert(std::is_trivially_copyable_v<Spinlock> == true);
|
||||||
@@ -80,8 +80,8 @@ public:
|
|||||||
SpinlockLockNoInt(SpinlockLockNoInt const &d) = delete;
|
SpinlockLockNoInt(SpinlockLockNoInt const &d) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Spinlock *lock;
|
Spinlock *lock;
|
||||||
unsigned long f;
|
unsigned long f;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif//OS2_SPINLOCK_H
|
#endif //OS2_SPINLOCK_H
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
#include "mutex.hpp"
|
#include "mutex.hpp"
|
||||||
class Tty {
|
class Tty {
|
||||||
public:
|
public:
|
||||||
virtual void putchar(char c) = 0;
|
virtual void putchar(char c) = 0;
|
||||||
virtual void putstr(const char *str) = 0;
|
virtual void putstr(const char *str) = 0;
|
||||||
virtual char readchar() = 0;
|
virtual char readchar() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_TTY_HPP
|
#endif //OS2_TTY_HPP
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
#include "Vector.hpp"
|
#include "Vector.hpp"
|
||||||
#include "mutex.hpp"
|
#include "mutex.hpp"
|
||||||
|
|
||||||
TtyManager GlobalTtyManager;
|
TtyManager GlobalTtyManager;
|
||||||
|
|
||||||
Vector<TtyManager> ttys;
|
Vector<TtyManager> ttys;
|
||||||
|
|
||||||
void TtyManager::add_tty(Tty *tty) {
|
void TtyManager::add_tty(Tty *tty) {
|
||||||
LockGuard l(lock);
|
LockGuard l(lock);
|
||||||
ttys.emplace_back(tty);
|
ttys.emplace_back(tty);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,19 +10,19 @@
|
|||||||
#include "Vector.hpp"
|
#include "Vector.hpp"
|
||||||
|
|
||||||
class TtyManager {
|
class TtyManager {
|
||||||
Mutex lock;
|
Mutex lock;
|
||||||
Vector<Tty *> ttys;
|
Vector<Tty *> ttys;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void add_tty(Tty *tty);
|
void add_tty(Tty *tty);
|
||||||
|
|
||||||
void all_tty_putchar(char c);
|
void all_tty_putchar(char c);
|
||||||
void all_tty_putstr(const char *str);
|
void all_tty_putstr(const char *str);
|
||||||
|
|
||||||
unsigned get_num_ttys();
|
unsigned get_num_ttys();
|
||||||
Tty *get_tty(unsigned n);
|
Tty *get_tty(unsigned n);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TtyManager GlobalTtyManager;
|
extern TtyManager GlobalTtyManager;
|
||||||
|
|
||||||
#endif//OS1_TTY_H
|
#endif //OS1_TTY_H
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ void *VMA::mmap_mem(void *v_addr, size_t length, int prot, int flags) {
|
|||||||
length &= ~(PAGE_SIZE - 1);
|
length &= ~(PAGE_SIZE - 1);
|
||||||
}
|
}
|
||||||
assert((length & (PAGE_SIZE - 1)) == 0);
|
assert((length & (PAGE_SIZE - 1)) == 0);
|
||||||
uint64_t page_len = length / PAGE_SIZE;
|
uint64_t page_len = length / PAGE_SIZE;
|
||||||
|
|
||||||
std::optional<ListEntry> found;
|
std::optional<ListEntry> found;
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,24 +21,24 @@ public:
|
|||||||
|
|
||||||
/// Map all higher-half pages into the address space
|
/// Map all higher-half pages into the address space
|
||||||
/// By linking them to same entries as kernel
|
/// By linking them to same entries as kernel
|
||||||
void map_kern();
|
void map_kern();
|
||||||
void *mmap_phys(void *v_addr, void *real_addr, size_t length, int flags);
|
void *mmap_phys(void *v_addr, void *real_addr, size_t length, int flags);
|
||||||
void *mmap_mem(void *v_addr, size_t length, int prot, int flags);
|
void *mmap_mem(void *v_addr, size_t length, int prot, int flags);
|
||||||
int munmap(void *addr, size_t length);
|
int munmap(void *addr, size_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AddressSpace *space = nullptr;
|
AddressSpace *space = nullptr;
|
||||||
Mutex space_lock;
|
Mutex space_lock;
|
||||||
|
|
||||||
struct ListEntry {
|
struct ListEntry {
|
||||||
uintptr_t begin;
|
uintptr_t begin;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
bool available;
|
bool available;
|
||||||
};
|
};
|
||||||
|
|
||||||
SkipList<uintptr_t, ListEntry> regions;
|
SkipList<uintptr_t, ListEntry> regions;
|
||||||
Mutex regions_lock;
|
Mutex regions_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_VMA_HPP
|
#endif //OS2_VMA_HPP
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ static inline void _assert2(int val, const char *msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define assert2(x, y) _assert2(x, y)
|
#define assert2(x, y) _assert2(x, y)
|
||||||
#define assert(x) _assert2(x, "Assertion failed")
|
#define assert(x) _assert2(x, "Assertion failed")
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_ASSERTS_HPP
|
#endif //OS2_ASSERTS_HPP
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#define STACK_CHK_GUARD 0x2e61e13e4d5ae23c
|
#define STACK_CHK_GUARD 0x2e61e13e4d5ae23c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uintptr_t __stack_chk_guard = STACK_CHK_GUARD;
|
uintptr_t __stack_chk_guard = STACK_CHK_GUARD;
|
||||||
|
|
||||||
extern "C" __attribute__((noreturn)) void __stack_chk_fail(void) {
|
extern "C" __attribute__((noreturn)) void __stack_chk_fail(void) {
|
||||||
assert2(false, "Stack protection triggered!");
|
assert2(false, "Stack protection triggered!");
|
||||||
@@ -32,11 +32,11 @@ namespace __cxxabiv1 {
|
|||||||
/* The ABI requires a 64-bit type. */
|
/* The ABI requires a 64-bit type. */
|
||||||
__extension__ typedef int __guard __attribute__((mode(__DI__)));
|
__extension__ typedef int __guard __attribute__((mode(__DI__)));
|
||||||
|
|
||||||
extern "C" int __cxa_guard_acquire(__guard *);
|
extern "C" int __cxa_guard_acquire(__guard *);
|
||||||
extern "C" void __cxa_guard_release(__guard *);
|
extern "C" void __cxa_guard_release(__guard *);
|
||||||
extern "C" void __cxa_guard_abort(__guard *);
|
extern "C" void __cxa_guard_abort(__guard *);
|
||||||
|
|
||||||
extern "C" int __cxa_guard_acquire(__guard *g) {
|
extern "C" int __cxa_guard_acquire(__guard *g) {
|
||||||
return !*(char *) (g);
|
return !*(char *) (g);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ namespace __cxxabiv1 {
|
|||||||
extern "C" void __cxa_guard_abort(__guard *) {
|
extern "C" void __cxa_guard_abort(__guard *) {
|
||||||
_hcf();
|
_hcf();
|
||||||
}
|
}
|
||||||
}// namespace __cxxabiv1
|
} // namespace __cxxabiv1
|
||||||
|
|
||||||
void *operator new(size_t size) {
|
void *operator new(size_t size) {
|
||||||
return kmalloc(size);
|
return kmalloc(size);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ struct Task;
|
|||||||
// This is probably broken in some way
|
// This is probably broken in some way
|
||||||
class CV {
|
class CV {
|
||||||
List<Task *> waiters;
|
List<Task *> waiters;
|
||||||
Spinlock waiters_lock;
|
Spinlock waiters_lock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename Lockable>
|
template<typename Lockable>
|
||||||
@@ -55,4 +55,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_CV_HPP
|
#endif //OS2_CV_HPP
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void Mutex::lock() {
|
|||||||
|
|
||||||
void Mutex::unlock() {
|
void Mutex::unlock() {
|
||||||
bool expected = true;
|
bool expected = true;
|
||||||
_owner = nullptr;
|
_owner = nullptr;
|
||||||
if (!locked.compare_exchange_strong(expected, false))
|
if (!locked.compare_exchange_strong(expected, false))
|
||||||
assert2(false, "Unlocking an unlocked mutex!\n");
|
assert2(false, "Unlocking an unlocked mutex!\n");
|
||||||
List<Task *>::Node *t = nullptr;
|
List<Task *>::Node *t = nullptr;
|
||||||
|
|||||||
@@ -21,20 +21,20 @@ public:
|
|||||||
|
|
||||||
void lock();
|
void lock();
|
||||||
// void spin_lock();
|
// void spin_lock();
|
||||||
bool try_lock();
|
bool try_lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
bool test();
|
bool test();
|
||||||
Task *owner() { return _owner; }
|
Task *owner() { return _owner; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<bool> locked = false;
|
std::atomic<bool> locked = false;
|
||||||
|
|
||||||
List<Task *> waiters;
|
List<Task *> waiters;
|
||||||
Spinlock waiters_lock;
|
Spinlock waiters_lock;
|
||||||
|
|
||||||
Task *_owner = nullptr;
|
Task *_owner = nullptr;
|
||||||
uint8_t spin_success = 127;
|
uint8_t spin_success = 127;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS1_MUTEX_H
|
#endif //OS1_MUTEX_H
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
// The following functions define a portable implementation of rand and srand.
|
// The following functions define a portable implementation of rand and srand.
|
||||||
|
|
||||||
static std::atomic<unsigned long int> next = 1;// NB: "unsigned long int" is assumed to be 32 bits wide
|
static std::atomic<unsigned long int> next = 1; // NB: "unsigned long int" is assumed to be 32 bits wide
|
||||||
|
|
||||||
extern "C" int rand(void)// RAND_MAX assumed to be 32767
|
extern "C" int rand(void) // RAND_MAX assumed to be 32767
|
||||||
{
|
{
|
||||||
next = next * 1103515245 + 12345;
|
next = next * 1103515245 + 12345;
|
||||||
return (unsigned int) (next / 65536ULL) % 32768;
|
return (unsigned int) (next / 65536ULL) % 32768;
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ extern "C" {
|
|||||||
|
|
||||||
// The following functions define a portable implementation of rand and srand.
|
// The following functions define a portable implementation of rand and srand.
|
||||||
#define RAND_MAX 32767
|
#define RAND_MAX 32767
|
||||||
int rand(void);
|
int rand(void);
|
||||||
void srand(unsigned int seed);
|
void srand(unsigned int seed);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif//OS2_RAND_H
|
#endif //OS2_RAND_H
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
inline void *memcpy(void *dest, const void *src, size_t n) {
|
inline void *memcpy(void *dest, const void *src, size_t n) {
|
||||||
uint8_t *pdest = (uint8_t *) dest;
|
uint8_t *pdest = (uint8_t *) dest;
|
||||||
const uint8_t *psrc = (const uint8_t *) src;
|
const uint8_t *psrc = (const uint8_t *) src;
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
pdest[i] = psrc[i];
|
pdest[i] = psrc[i];
|
||||||
@@ -34,8 +34,8 @@ inline void *memset(void *s, int c, size_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void *memmove(void *dest, const void *src, size_t n) {
|
inline void *memmove(void *dest, const void *src, size_t n) {
|
||||||
uint8_t *pdest = (uint8_t *) dest;
|
uint8_t *pdest = (uint8_t *) dest;
|
||||||
const uint8_t *psrc = (const uint8_t *) src;
|
const uint8_t *psrc = (const uint8_t *) src;
|
||||||
|
|
||||||
if (src > dest) {
|
if (src > dest) {
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
@@ -106,4 +106,4 @@ inline void strcpy(const char *src, char *dst) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif//OS2_STRING_H
|
#endif //OS2_STRING_H
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
// FIXME
|
// FIXME
|
||||||
template<typename T, auto S>
|
template<typename T, auto S>
|
||||||
class CircularBuffer {
|
class CircularBuffer {
|
||||||
T data[S];
|
T data[S];
|
||||||
int front, back;
|
int front, back;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CircularBuffer() {
|
CircularBuffer() {
|
||||||
front = -1;
|
front = -1;
|
||||||
back = -1;
|
back = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool full() {
|
bool full() {
|
||||||
@@ -41,7 +41,7 @@ public:
|
|||||||
assert(false);
|
assert(false);
|
||||||
} else {
|
} else {
|
||||||
if (front == -1) front = 0;
|
if (front == -1) front = 0;
|
||||||
back = (back + 1) % S;
|
back = (back + 1) % S;
|
||||||
data[back] = what;
|
data[back] = what;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
T ret = data[front];
|
T ret = data[front];
|
||||||
if (front == back) {
|
if (front == back) {
|
||||||
front = -1;
|
front = -1;
|
||||||
back = -1;
|
back = -1;
|
||||||
} else {
|
} else {
|
||||||
front = (front + 1) % S;
|
front = (front + 1) % S;
|
||||||
}
|
}
|
||||||
@@ -62,4 +62,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif//OS2_CIRCULARBUFFER_HPP
|
#endif //OS2_CIRCULARBUFFER_HPP
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ template<typename T>
|
|||||||
class List {
|
class List {
|
||||||
public:
|
public:
|
||||||
struct Node {
|
struct Node {
|
||||||
T val;
|
T val;
|
||||||
Node *next;
|
Node *next;
|
||||||
List *list;
|
List *list;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Node *head = nullptr;
|
Node *head = nullptr;
|
||||||
Node *tail = nullptr;
|
Node *tail = nullptr;
|
||||||
|
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
assert(tail != nullptr);
|
assert(tail != nullptr);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
head->next = new_node;
|
head->next = new_node;
|
||||||
head = new_node;
|
head = new_node;
|
||||||
} else {
|
} else {
|
||||||
assert(size == 0);
|
assert(size == 0);
|
||||||
head = new_node;
|
head = new_node;
|
||||||
@@ -63,7 +63,7 @@ public:
|
|||||||
bool empty() const {
|
bool empty() const {
|
||||||
return tail == nullptr;
|
return tail == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
T &back() {
|
T &back() {
|
||||||
if (tail != nullptr) {
|
if (tail != nullptr) {
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto old_tail = tail;
|
auto old_tail = tail;
|
||||||
tail = tail->next;
|
tail = tail->next;
|
||||||
delete old_tail;
|
delete old_tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,15 +113,15 @@ public:
|
|||||||
size--;
|
size--;
|
||||||
if (tail == head) {
|
if (tail == head) {
|
||||||
assert(size == 0);
|
assert(size == 0);
|
||||||
auto b = tail;
|
auto b = tail;
|
||||||
tail = nullptr;
|
tail = nullptr;
|
||||||
head = nullptr;
|
head = nullptr;
|
||||||
b->list = nullptr;
|
b->list = nullptr;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto old_tail = tail;
|
auto old_tail = tail;
|
||||||
tail = tail->next;
|
tail = tail->next;
|
||||||
old_tail->list = nullptr;
|
old_tail->list = nullptr;
|
||||||
return old_tail;
|
return old_tail;
|
||||||
}
|
}
|
||||||
@@ -133,4 +133,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_LIST_HPP
|
#endif //OS2_LIST_HPP
|
||||||
|
|||||||
@@ -22,18 +22,18 @@ public:
|
|||||||
delete ptr;
|
delete ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtr(UniquePtr const &other) = delete;
|
UniquePtr(UniquePtr const &other) = delete;
|
||||||
UniquePtr &operator=(UniquePtr const &other) = delete;
|
UniquePtr &operator=(UniquePtr const &other) = delete;
|
||||||
|
|
||||||
UniquePtr(UniquePtr &&other) {
|
UniquePtr(UniquePtr &&other) {
|
||||||
delete ptr;
|
delete ptr;
|
||||||
ptr = other.ptr;
|
ptr = other.ptr;
|
||||||
other.ptr = nullptr;
|
other.ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtr &operator=(UniquePtr &&other) {
|
UniquePtr &operator=(UniquePtr &&other) {
|
||||||
delete ptr;
|
delete ptr;
|
||||||
ptr = other.ptr;
|
ptr = other.ptr;
|
||||||
other.ptr = nullptr;
|
other.ptr = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
|
|
||||||
T *release() noexcept {
|
T *release() noexcept {
|
||||||
auto b = ptr;
|
auto b = ptr;
|
||||||
ptr = nullptr;
|
ptr = nullptr;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,10 +77,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr(SharedPtr &&other) {
|
SharedPtr(SharedPtr &&other) {
|
||||||
uses = other.uses;
|
uses = other.uses;
|
||||||
ptr = other.ptr;
|
ptr = other.ptr;
|
||||||
other.uses = nullptr;
|
other.uses = nullptr;
|
||||||
other.ptr = nullptr;
|
other.ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr &operator=(SharedPtr other) {
|
SharedPtr &operator=(SharedPtr other) {
|
||||||
@@ -89,16 +89,16 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() const { return ptr; }
|
T *operator->() const { return ptr; }
|
||||||
|
|
||||||
T &operator*() const { return *ptr; }
|
T &operator*() const { return *ptr; }
|
||||||
|
|
||||||
T *get() const noexcept { return ptr; }
|
T *get() const noexcept { return ptr; }
|
||||||
|
|
||||||
[[nodiscard]] int useCount() const { return *uses; }
|
[[nodiscard]] int useCount() const { return *uses; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T *ptr = nullptr;
|
T *ptr = nullptr;
|
||||||
int *uses = nullptr;
|
int *uses = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ private:
|
|||||||
friend COWTester;
|
friend COWTester;
|
||||||
SharedPtr<T> ptr;
|
SharedPtr<T> ptr;
|
||||||
|
|
||||||
void copy() {
|
void copy() {
|
||||||
if (ptr.get() && ptr.useCount() > 1) {
|
if (ptr.get() && ptr.useCount() > 1) {
|
||||||
ptr = SharedPtr<T>(new T(*ptr));
|
ptr = SharedPtr<T>(new T(*ptr));
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
|
|
||||||
explicit COWPointer(SharedPtr<T> data) : ptr(std::move(data)) {}
|
explicit COWPointer(SharedPtr<T> data) : ptr(std::move(data)) {}
|
||||||
|
|
||||||
COWPointer(COWPointer &&other) = default;
|
COWPointer(COWPointer &&other) = default;
|
||||||
|
|
||||||
COWPointer(COWPointer const &data) = default;
|
COWPointer(COWPointer const &data) = default;
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public:
|
|||||||
return ptr.get();
|
return ptr.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int useCount() { return ptr.useCount(); };
|
int useCount() { return ptr.useCount(); };
|
||||||
|
|
||||||
const T &operator*() const {
|
const T &operator*() const {
|
||||||
return *ptr;
|
return *ptr;
|
||||||
|
|||||||
@@ -16,18 +16,18 @@ class SkipList {
|
|||||||
public:
|
public:
|
||||||
struct Node {
|
struct Node {
|
||||||
Node *next[maxL + 1] = {nullptr};
|
Node *next[maxL + 1] = {nullptr};
|
||||||
Node *before = nullptr;
|
Node *before = nullptr;
|
||||||
bool end = false;
|
bool end = false;
|
||||||
K key = K();
|
K key = K();
|
||||||
|
|
||||||
V data = V();
|
V data = V();
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class NodeAllocator {
|
class NodeAllocator {
|
||||||
static constexpr int size{64};
|
static constexpr int size{64};
|
||||||
Node *nodes[size];
|
Node *nodes[size];
|
||||||
int top = -1;
|
int top = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NodeAllocator() noexcept = default;
|
NodeAllocator() noexcept = default;
|
||||||
@@ -52,12 +52,12 @@ private:
|
|||||||
return new Node;
|
return new Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *node = nodes[top--];
|
Node *node = nodes[top--];
|
||||||
|
|
||||||
node->end = false;
|
node->end = false;
|
||||||
node->before = nullptr;
|
node->before = nullptr;
|
||||||
node->next[0] = nullptr;
|
node->next[0] = nullptr;
|
||||||
node->key = K();
|
node->key = K();
|
||||||
// node->data = V();
|
// node->data = V();
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@@ -67,23 +67,23 @@ private:
|
|||||||
static int randomL() {
|
static int randomL() {
|
||||||
int ret = __builtin_ffs(rand());
|
int ret = __builtin_ffs(rand());
|
||||||
assert(ret >= 0);
|
assert(ret >= 0);
|
||||||
return ret;// NOLINT
|
return ret; // NOLINT
|
||||||
}
|
}
|
||||||
|
|
||||||
// static inline NodeAllocator nodeAllocator;
|
// static inline NodeAllocator nodeAllocator;
|
||||||
NodeAllocator nodeAllocator;
|
NodeAllocator nodeAllocator;
|
||||||
|
|
||||||
Node *root;
|
Node *root;
|
||||||
Node *endnode;
|
Node *endnode;
|
||||||
mutable Node *toUpdate[maxL + 1];
|
mutable Node *toUpdate[maxL + 1];
|
||||||
size_t curL = 0;
|
size_t curL = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SkipList() noexcept {
|
SkipList() noexcept {
|
||||||
root = (Node *) nodeAllocator.get();
|
root = (Node *) nodeAllocator.get();
|
||||||
root->end = true;
|
root->end = true;
|
||||||
endnode = (Node *) nodeAllocator.get();
|
endnode = (Node *) nodeAllocator.get();
|
||||||
endnode->end = true;
|
endnode->end = true;
|
||||||
endnode->before = root;
|
endnode->before = root;
|
||||||
|
|
||||||
for (size_t i = 0; i <= maxL; i++) {
|
for (size_t i = 0; i <= maxL; i++) {
|
||||||
@@ -95,7 +95,7 @@ public:
|
|||||||
auto cur = root;
|
auto cur = root;
|
||||||
while (cur != nullptr) {
|
while (cur != nullptr) {
|
||||||
auto prev = cur;
|
auto prev = cur;
|
||||||
cur = cur->next[0];
|
cur = cur->next[0];
|
||||||
nodeAllocator.push(prev);
|
nodeAllocator.push(prev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,27 +112,27 @@ public:
|
|||||||
curL = newLevel;
|
curL = newLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newNode = (Node *) nodeAllocator.get();
|
auto newNode = (Node *) nodeAllocator.get();
|
||||||
newNode->key = n->key;
|
newNode->key = n->key;
|
||||||
newNode->data = n->data;
|
newNode->data = n->data;
|
||||||
newNode->before = toUpdate[0];
|
newNode->before = toUpdate[0];
|
||||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||||
|
|
||||||
for (size_t i = 0; i <= newLevel; i++) {
|
for (size_t i = 0; i <= newLevel; i++) {
|
||||||
newNode->next[i] = toUpdate[i]->next[i];
|
newNode->next[i] = toUpdate[i]->next[i];
|
||||||
toUpdate[i]->next[i] = newNode;
|
toUpdate[i]->next[i] = newNode;
|
||||||
toUpdate[i] = newNode;
|
toUpdate[i] = newNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SkipList(SkipList &&l) noexcept {
|
SkipList(SkipList &&l) noexcept {
|
||||||
this->root = l.root;
|
this->root = l.root;
|
||||||
l.root = nullptr;
|
l.root = nullptr;
|
||||||
this->endnode = l.endnode;
|
this->endnode = l.endnode;
|
||||||
l.endnode = nullptr;
|
l.endnode = nullptr;
|
||||||
this->curL = l.curL;
|
this->curL = l.curL;
|
||||||
l.curL = 0;
|
l.curL = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkipList &operator=(SkipList l) noexcept {
|
SkipList &operator=(SkipList l) noexcept {
|
||||||
@@ -237,17 +237,17 @@ public:
|
|||||||
curL = newLevel;
|
curL = newLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newNode = (Node *) nodeAllocator.get();
|
auto newNode = (Node *) nodeAllocator.get();
|
||||||
newNode->key = k;
|
newNode->key = k;
|
||||||
newNode->data = std::move(v);
|
newNode->data = std::move(v);
|
||||||
|
|
||||||
newNode->before = toUpdate[0];
|
newNode->before = toUpdate[0];
|
||||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||||
|
|
||||||
for (size_t i = 0; i <= newLevel; i++) {
|
for (size_t i = 0; i <= newLevel; i++) {
|
||||||
newNode->next[i] = toUpdate[i]->next[i];
|
newNode->next[i] = toUpdate[i]->next[i];
|
||||||
toUpdate[i]->next[i] = newNode;
|
toUpdate[i]->next[i] = newNode;
|
||||||
toUpdate[i] = newNode;
|
toUpdate[i] = newNode;
|
||||||
}
|
}
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
@@ -336,12 +336,12 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
bool operator==(SkipList const &r) const {
|
bool operator==(SkipList const &r) const {
|
||||||
auto n = root->next[0];
|
auto n = root->next[0];
|
||||||
auto n2 = r.root->next[0];
|
auto n2 = r.root->next[0];
|
||||||
|
|
||||||
while (!n->end && !n2->end) {
|
while (!n->end && !n2->end) {
|
||||||
if (!(n->data == n2->data)) return false;
|
if (!(n->data == n2->data)) return false;
|
||||||
n = n->next[0];
|
n = n->next[0];
|
||||||
n2 = n2->next[0];
|
n2 = n2->next[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,15 +355,15 @@ public:
|
|||||||
struct SkipListIterator {
|
struct SkipListIterator {
|
||||||
// using iterator_category = std::forward_iterator_tag;
|
// using iterator_category = std::forward_iterator_tag;
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
using value_type = Node;
|
using value_type = Node;
|
||||||
using pointer = value_type *;
|
using pointer = value_type *;
|
||||||
using reference = value_type &;
|
using reference = value_type &;
|
||||||
|
|
||||||
explicit SkipListIterator(Node *n) : n(std::move(n)){};
|
explicit SkipListIterator(Node *n) : n(std::move(n)){};
|
||||||
|
|
||||||
reference operator*() const { return *n; }
|
reference operator*() const { return *n; }
|
||||||
|
|
||||||
pointer operator->() const { return n; }
|
pointer operator->() const { return n; }
|
||||||
|
|
||||||
SkipListIterator &operator--() {
|
SkipListIterator &operator--() {
|
||||||
if (!n->end)
|
if (!n->end)
|
||||||
|
|||||||
@@ -8,16 +8,16 @@ class SkipListSet {
|
|||||||
public:
|
public:
|
||||||
struct Node {
|
struct Node {
|
||||||
Node *next[maxL + 1] = {nullptr};
|
Node *next[maxL + 1] = {nullptr};
|
||||||
Node *before = nullptr;
|
Node *before = nullptr;
|
||||||
bool end = false;
|
bool end = false;
|
||||||
K key = K();
|
K key = K();
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class NodeAllocator {
|
class NodeAllocator {
|
||||||
static constexpr int size{64};
|
static constexpr int size{64};
|
||||||
Node *nodes[size];
|
Node *nodes[size];
|
||||||
int top = -1;
|
int top = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NodeAllocator() noexcept = default;
|
NodeAllocator() noexcept = default;
|
||||||
@@ -42,12 +42,12 @@ private:
|
|||||||
return new Node;
|
return new Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *node = nodes[top--];
|
Node *node = nodes[top--];
|
||||||
|
|
||||||
node->end = false;
|
node->end = false;
|
||||||
node->before = nullptr;
|
node->before = nullptr;
|
||||||
node->next[0] = nullptr;
|
node->next[0] = nullptr;
|
||||||
node->key = K();
|
node->key = K();
|
||||||
// node->data = V();
|
// node->data = V();
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@@ -57,22 +57,22 @@ private:
|
|||||||
static int randomL() {
|
static int randomL() {
|
||||||
int ret = __builtin_ffs(rand());
|
int ret = __builtin_ffs(rand());
|
||||||
assert(ret >= 0);
|
assert(ret >= 0);
|
||||||
return ret;// NOLINT
|
return ret; // NOLINT
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeAllocator nodeAllocator;
|
NodeAllocator nodeAllocator;
|
||||||
|
|
||||||
Node *root;
|
Node *root;
|
||||||
Node *endnode;
|
Node *endnode;
|
||||||
mutable Node *toUpdate[maxL + 1];
|
mutable Node *toUpdate[maxL + 1];
|
||||||
size_t curL = 0;
|
size_t curL = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SkipListSet() noexcept {
|
SkipListSet() noexcept {
|
||||||
root = (Node *) nodeAllocator.get();
|
root = (Node *) nodeAllocator.get();
|
||||||
root->end = true;
|
root->end = true;
|
||||||
endnode = (Node *) nodeAllocator.get();
|
endnode = (Node *) nodeAllocator.get();
|
||||||
endnode->end = true;
|
endnode->end = true;
|
||||||
endnode->before = root;
|
endnode->before = root;
|
||||||
|
|
||||||
for (size_t i = 0; i <= maxL; i++) {
|
for (size_t i = 0; i <= maxL; i++) {
|
||||||
@@ -84,7 +84,7 @@ public:
|
|||||||
auto cur = root;
|
auto cur = root;
|
||||||
while (cur != nullptr) {
|
while (cur != nullptr) {
|
||||||
auto prev = cur;
|
auto prev = cur;
|
||||||
cur = cur->next[0];
|
cur = cur->next[0];
|
||||||
nodeAllocator.push(prev);
|
nodeAllocator.push(prev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,27 +101,27 @@ public:
|
|||||||
curL = newLevel;
|
curL = newLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newNode = (Node *) nodeAllocator.get();
|
auto newNode = (Node *) nodeAllocator.get();
|
||||||
newNode->key = n->key;
|
newNode->key = n->key;
|
||||||
newNode->data = n->data;
|
newNode->data = n->data;
|
||||||
newNode->before = toUpdate[0];
|
newNode->before = toUpdate[0];
|
||||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||||
|
|
||||||
for (size_t i = 0; i <= newLevel; i++) {
|
for (size_t i = 0; i <= newLevel; i++) {
|
||||||
newNode->next[i] = toUpdate[i]->next[i];
|
newNode->next[i] = toUpdate[i]->next[i];
|
||||||
toUpdate[i]->next[i] = newNode;
|
toUpdate[i]->next[i] = newNode;
|
||||||
toUpdate[i] = newNode;
|
toUpdate[i] = newNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SkipListSet(SkipListSet &&l) noexcept {
|
SkipListSet(SkipListSet &&l) noexcept {
|
||||||
this->root = l.root;
|
this->root = l.root;
|
||||||
l.root = nullptr;
|
l.root = nullptr;
|
||||||
this->endnode = l.endnode;
|
this->endnode = l.endnode;
|
||||||
l.endnode = nullptr;
|
l.endnode = nullptr;
|
||||||
this->curL = l.curL;
|
this->curL = l.curL;
|
||||||
l.curL = 0;
|
l.curL = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkipListSet &operator=(SkipListSet l) noexcept {
|
SkipListSet &operator=(SkipListSet l) noexcept {
|
||||||
@@ -191,16 +191,16 @@ public:
|
|||||||
curL = newLevel;
|
curL = newLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newNode = (Node *) nodeAllocator.get();
|
auto newNode = (Node *) nodeAllocator.get();
|
||||||
newNode->key = k;
|
newNode->key = k;
|
||||||
|
|
||||||
newNode->before = toUpdate[0];
|
newNode->before = toUpdate[0];
|
||||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||||
|
|
||||||
for (size_t i = 0; i <= newLevel; i++) {
|
for (size_t i = 0; i <= newLevel; i++) {
|
||||||
newNode->next[i] = toUpdate[i]->next[i];
|
newNode->next[i] = toUpdate[i]->next[i];
|
||||||
toUpdate[i]->next[i] = newNode;
|
toUpdate[i]->next[i] = newNode;
|
||||||
toUpdate[i] = newNode;
|
toUpdate[i] = newNode;
|
||||||
}
|
}
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
@@ -288,12 +288,12 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
bool operator==(SkipListSet const &r) const {
|
bool operator==(SkipListSet const &r) const {
|
||||||
auto n = root->next[0];
|
auto n = root->next[0];
|
||||||
auto n2 = r.root->next[0];
|
auto n2 = r.root->next[0];
|
||||||
|
|
||||||
while (!n->end && !n2->end) {
|
while (!n->end && !n2->end) {
|
||||||
if (!(n->data == n2->data)) return false;
|
if (!(n->data == n2->data)) return false;
|
||||||
n = n->next[0];
|
n = n->next[0];
|
||||||
n2 = n2->next[0];
|
n2 = n2->next[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,35 +11,35 @@
|
|||||||
class String {
|
class String {
|
||||||
public:
|
public:
|
||||||
String() noexcept {
|
String() noexcept {
|
||||||
_data = static_cast<char *>(kmalloc(1 * sizeof(char)));
|
_data = static_cast<char *>(kmalloc(1 * sizeof(char)));
|
||||||
curLen = 0;
|
curLen = 0;
|
||||||
_data[0] = '\0';
|
_data[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
String(const char *in) noexcept {
|
String(const char *in) noexcept {
|
||||||
curLen = strlen(in);
|
curLen = strlen(in);
|
||||||
|
|
||||||
_data = static_cast<char *>(kmalloc((curLen + 1) * sizeof(char)));
|
_data = static_cast<char *>(kmalloc((curLen + 1) * sizeof(char)));
|
||||||
_data[0] = '\0';
|
_data[0] = '\0';
|
||||||
|
|
||||||
strcat(_data, in);
|
strcat(_data, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
String(String const &str) noexcept {
|
String(String const &str) noexcept {
|
||||||
curLen = str.curLen;
|
curLen = str.curLen;
|
||||||
|
|
||||||
_data = static_cast<char *>(kmalloc((curLen + 1) * sizeof(char)));
|
_data = static_cast<char *>(kmalloc((curLen + 1) * sizeof(char)));
|
||||||
_data[0] = '\0';
|
_data[0] = '\0';
|
||||||
|
|
||||||
strcat(_data, str._data);
|
strcat(_data, str._data);
|
||||||
}
|
}
|
||||||
|
|
||||||
String(String &&str) noexcept {
|
String(String &&str) noexcept {
|
||||||
_data = str._data;
|
_data = str._data;
|
||||||
curLen = str.curLen;
|
curLen = str.curLen;
|
||||||
|
|
||||||
str._data = static_cast<char *>(kmalloc(1 * sizeof(char)));
|
str._data = static_cast<char *>(kmalloc(1 * sizeof(char)));
|
||||||
str.curLen = 0;
|
str.curLen = 0;
|
||||||
str._data[0] = '\0';
|
str._data[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
~String() noexcept {
|
~String() noexcept {
|
||||||
if (_data == nullptr) return;
|
if (_data == nullptr) return;
|
||||||
kfree(_data);
|
kfree(_data);
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
curLen = 0;
|
curLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ public:
|
|||||||
_data = static_cast<char *>(krealloc(_data, sizeof(char) * (curLen + 2)));
|
_data = static_cast<char *>(krealloc(_data, sizeof(char) * (curLen + 2)));
|
||||||
assert(_data != nullptr);
|
assert(_data != nullptr);
|
||||||
|
|
||||||
_data[curLen] = c;
|
_data[curLen] = c;
|
||||||
_data[curLen + 1] = '\0';
|
_data[curLen + 1] = '\0';
|
||||||
curLen++;
|
curLen++;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
const char *c_str() const {
|
const char *c_str() const {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *data() {
|
char *data() {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t curLen = 0;
|
size_t curLen = 0;
|
||||||
char *_data;
|
char *_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -7,4 +7,4 @@
|
|||||||
|
|
||||||
int test_templates();
|
int test_templates();
|
||||||
|
|
||||||
#endif//OS2_TESTTEMPLATES_HPP
|
#endif //OS2_TESTTEMPLATES_HPP
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector(std::initializer_list<T> l) noexcept {
|
Vector(std::initializer_list<T> l) noexcept {
|
||||||
curSize = l.size();
|
curSize = l.size();
|
||||||
capacity = curSize > 0 ? curSize : 2;
|
capacity = curSize > 0 ? curSize : 2;
|
||||||
|
|
||||||
data = static_cast<T *>(kmalloc(capacity * sizeof(T)));
|
data = static_cast<T *>(kmalloc(capacity * sizeof(T)));
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto const &el: l) {
|
for (auto const &el: l) {
|
||||||
@@ -31,20 +31,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector(Vector const &vec) noexcept {
|
Vector(Vector const &vec) noexcept {
|
||||||
curSize = vec.curSize;
|
curSize = vec.curSize;
|
||||||
capacity = curSize > 0 ? curSize : 2;
|
capacity = curSize > 0 ? curSize : 2;
|
||||||
|
|
||||||
data = static_cast<T *>(kmalloc(capacity * sizeof(T)));
|
data = static_cast<T *>(kmalloc(capacity * sizeof(T)));
|
||||||
|
|
||||||
for (size_t i = 0; i < curSize; i++)
|
for (size_t i = 0; i < curSize; i++)
|
||||||
new (data + i) T(vec.data[i]);
|
new (data + i) T(vec.data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(Vector &&v) noexcept {
|
Vector(Vector &&v) noexcept {
|
||||||
curSize = v.curSize;
|
curSize = v.curSize;
|
||||||
capacity = v.capacity;
|
capacity = v.capacity;
|
||||||
data = v.data;
|
data = v.data;
|
||||||
v.data = nullptr;
|
v.data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector &operator=(Vector vec) noexcept {
|
Vector &operator=(Vector vec) noexcept {
|
||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void compact() {
|
void compact() {
|
||||||
data = (T *) krealloc(reinterpret_cast<char *>(data), curSize * sizeof(T));
|
data = (T *) krealloc(reinterpret_cast<char *>(data), curSize * sizeof(T));
|
||||||
capacity = curSize;
|
capacity = curSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,8 +141,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t capacity = 2;
|
size_t capacity = 2;
|
||||||
size_t curSize = 0;
|
size_t curSize = 0;
|
||||||
T *data;
|
T *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -15,30 +15,30 @@
|
|||||||
class FDT {
|
class FDT {
|
||||||
public:
|
public:
|
||||||
using FD = int64_t;
|
using FD = int64_t;
|
||||||
FD open(const Path &p, FileOpts opts);
|
FD open(const Path &p, FileOpts opts);
|
||||||
void close(FD fd);
|
void close(FD fd);
|
||||||
File *get(FD fd) const;
|
File *get(FD fd) const;
|
||||||
|
|
||||||
static FDT *current();
|
static FDT *current();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkipList<FD, UniquePtr<File>> _files;
|
SkipList<FD, UniquePtr<File>> _files;
|
||||||
int64_t _cur_fd = 10;
|
int64_t _cur_fd = 10;
|
||||||
mutable Mutex _mtx;
|
mutable Mutex _mtx;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FDHandle {
|
class FDHandle {
|
||||||
public:
|
public:
|
||||||
FDHandle(FDT::FD fd);
|
FDHandle(FDT::FD fd);
|
||||||
~FDHandle();
|
~FDHandle();
|
||||||
FDHandle(const File &f) = delete;
|
FDHandle(const File &f) = delete;
|
||||||
FDHandle &operator=(const File &o) = delete;
|
FDHandle &operator=(const File &o) = delete;
|
||||||
|
|
||||||
FDT::FD get() { return _fd; }
|
FDT::FD get() { return _fd; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FDT::FD _fd;
|
FDT::FD _fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_FDT_HPP
|
#endif //OS2_FDT_HPP
|
||||||
|
|||||||
@@ -16,22 +16,22 @@ class File {
|
|||||||
public:
|
public:
|
||||||
File(Node *n, FileOpts opts);
|
File(Node *n, FileOpts opts);
|
||||||
~File();
|
~File();
|
||||||
File(const File &f) = delete;
|
File(const File &f) = delete;
|
||||||
File &operator=(const File &o) = delete;
|
File &operator=(const File &o) = delete;
|
||||||
|
|
||||||
Node *node();
|
Node *node();
|
||||||
NodeDir *dir();
|
NodeDir *dir();
|
||||||
NodeFile *file() const;
|
NodeFile *file() const;
|
||||||
|
|
||||||
uint64_t seek(uint64_t pos);
|
uint64_t seek(uint64_t pos);
|
||||||
uint64_t read(char *buf, uint64_t size);
|
uint64_t read(char *buf, uint64_t size);
|
||||||
uint64_t write(const char *buf, uint64_t size);
|
uint64_t write(const char *buf, uint64_t size);
|
||||||
uint64_t size();
|
uint64_t size();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Node *const _n;
|
Node *const _n;
|
||||||
uint64_t _pos = 0;
|
uint64_t _pos = 0;
|
||||||
FileOpts _opts;
|
FileOpts _opts;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif//OS2_FILE_HPP
|
#endif //OS2_FILE_HPP
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ public:
|
|||||||
Filesystem(NodeDir *mounted_on);
|
Filesystem(NodeDir *mounted_on);
|
||||||
|
|
||||||
virtual NodeDir *root() = 0;
|
virtual NodeDir *root() = 0;
|
||||||
virtual ~Filesystem() = 0;
|
virtual ~Filesystem() = 0;
|
||||||
|
|
||||||
NodeDir *_mounted_on;
|
NodeDir *_mounted_on;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_FILESYSTEM_HPP
|
#endif //OS2_FILESYSTEM_HPP
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "LockGuard.hpp"
|
#include "LockGuard.hpp"
|
||||||
|
|
||||||
Vector<Node *> MemFs::MemFsNodeDir::children() {
|
Vector<Node *> MemFs::MemFsNodeDir::children() {
|
||||||
LockGuard l(_lock);
|
LockGuard l(_lock);
|
||||||
|
|
||||||
Vector<Node *> out;
|
Vector<Node *> out;
|
||||||
for (auto c: _children) {
|
for (auto c: _children) {
|
||||||
@@ -17,14 +17,14 @@ Vector<Node *> MemFs::MemFsNodeDir::children() {
|
|||||||
|
|
||||||
NodeDir *MemFs::MemFsNodeDir::mkdir(const String &name) {
|
NodeDir *MemFs::MemFsNodeDir::mkdir(const String &name) {
|
||||||
LockGuard l(_lock);
|
LockGuard l(_lock);
|
||||||
auto newnode = new MemFsNodeDir();
|
auto newnode = new MemFsNodeDir();
|
||||||
newnode->_name = name;
|
newnode->_name = name;
|
||||||
_children.add(name, newnode);
|
_children.add(name, newnode);
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
NodeFile *MemFs::MemFsNodeDir::mkfile(const String &name) {
|
NodeFile *MemFs::MemFsNodeDir::mkfile(const String &name) {
|
||||||
LockGuard l(_lock);
|
LockGuard l(_lock);
|
||||||
auto newfile = new MemFsNodeFile(name);
|
auto newfile = new MemFsNodeFile(name);
|
||||||
_children.add(name, newfile);
|
_children.add(name, newfile);
|
||||||
return newfile;
|
return newfile;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ class MemFs : public Filesystem {
|
|||||||
struct MemFsNodeDir : public NodeDir {
|
struct MemFsNodeDir : public NodeDir {
|
||||||
public:
|
public:
|
||||||
Vector<Node *> children() override;
|
Vector<Node *> children() override;
|
||||||
NodeDir *mkdir(const String &name) override;
|
NodeDir *mkdir(const String &name) override;
|
||||||
NodeFile *mkfile(const String &name) override;
|
NodeFile *mkfile(const String &name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkipList<String, Node *> _children;
|
SkipList<String, Node *> _children;
|
||||||
@@ -26,8 +26,8 @@ class MemFs : public Filesystem {
|
|||||||
public:
|
public:
|
||||||
MemFsNodeFile(const String &name) { _name = name; }
|
MemFsNodeFile(const String &name) { _name = name; }
|
||||||
|
|
||||||
bool read(char *buf, size_t start, size_t num) override;
|
bool read(char *buf, size_t start, size_t num) override;
|
||||||
bool write(const char *buf, size_t start, size_t num) override;
|
bool write(const char *buf, size_t start, size_t num) override;
|
||||||
size_t size() override;
|
size_t size() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -44,4 +44,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_MEMFS_HPP
|
#endif //OS2_MEMFS_HPP
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_MOUNTTABLE_HPP
|
#endif //OS2_MOUNTTABLE_HPP
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
Node::~Node() = default;
|
Node::~Node() = default;
|
||||||
Node *Node::traverse(const Path &path) {
|
Node *Node::traverse(const Path &path) {
|
||||||
NodeDir &nodeDir = static_cast<NodeDir &>(*this);
|
NodeDir &nodeDir = static_cast<NodeDir &>(*this);
|
||||||
|
|
||||||
Filesystem *mnt;
|
Filesystem *mnt;
|
||||||
{
|
{
|
||||||
LockGuard l(_lock);
|
LockGuard l(_lock);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
};
|
};
|
||||||
virtual ~Node() = 0;
|
virtual ~Node() = 0;
|
||||||
|
|
||||||
Type type() const { return _type; }
|
Type type() const { return _type; }
|
||||||
const String &name() const {
|
const String &name() const {
|
||||||
LockGuard l(_lock);
|
LockGuard l(_lock);
|
||||||
return _name;
|
return _name;
|
||||||
@@ -38,18 +38,18 @@ protected:
|
|||||||
// This is uuugly
|
// This is uuugly
|
||||||
mutable Mutex _lock;
|
mutable Mutex _lock;
|
||||||
|
|
||||||
String _name;
|
String _name;
|
||||||
Filesystem *_mount = nullptr;
|
Filesystem *_mount = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NodeFile;
|
class NodeFile;
|
||||||
|
|
||||||
class NodeDir : public Node {
|
class NodeDir : public Node {
|
||||||
public:
|
public:
|
||||||
virtual Vector<Node *> children() = 0;
|
virtual Vector<Node *> children() = 0;
|
||||||
virtual NodeDir *mkdir(const String &name) = 0;
|
virtual NodeDir *mkdir(const String &name) = 0;
|
||||||
virtual NodeFile *mkfile(const String &name) = 0;
|
virtual NodeFile *mkfile(const String &name) = 0;
|
||||||
virtual void set_mounted(Filesystem *mount);
|
virtual void set_mounted(Filesystem *mount);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NodeDir() : Node(Type::DIR) {}
|
NodeDir() : Node(Type::DIR) {}
|
||||||
@@ -57,13 +57,13 @@ protected:
|
|||||||
|
|
||||||
class NodeFile : public Node {
|
class NodeFile : public Node {
|
||||||
public:
|
public:
|
||||||
virtual bool read(char *buf, size_t start, size_t num) = 0;
|
virtual bool read(char *buf, size_t start, size_t num) = 0;
|
||||||
virtual bool write(const char *buf, size_t start, size_t num) = 0;
|
virtual bool write(const char *buf, size_t start, size_t num) = 0;
|
||||||
virtual size_t size() = 0;
|
virtual size_t size() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NodeFile() : Node(Type::FILE) {}
|
NodeFile() : Node(Type::FILE) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_NODE_HPP
|
#endif //OS2_NODE_HPP
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
Path StrToPath(const String &str) {
|
Path StrToPath(const String &str) {
|
||||||
if (str.length() == 0) return Path();
|
if (str.length() == 0) return Path();
|
||||||
Path out;
|
Path out;
|
||||||
String buf;
|
String buf;
|
||||||
for (size_t i = 0; i < str.length(); i++) {
|
for (size_t i = 0; i < str.length(); i++) {
|
||||||
if (str.c_str()[i] == '/') {
|
if (str.c_str()[i] == '/') {
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ using Path = Vector<String>;
|
|||||||
|
|
||||||
Path StrToPath(const String &str);
|
Path StrToPath(const String &str);
|
||||||
|
|
||||||
#endif//OS2_PATH_HPP
|
#endif //OS2_PATH_HPP
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "Node.hpp"
|
#include "Node.hpp"
|
||||||
|
|
||||||
bool VFSApi::mkdir(const Path &path) {
|
bool VFSApi::mkdir(const Path &path) {
|
||||||
auto root = path.subvector(0, path.size() - 1);
|
auto root = path.subvector(0, path.size() - 1);
|
||||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
||||||
if (root_fd.get() == -1) return false;
|
if (root_fd.get() == -1) return false;
|
||||||
File *root_f = FDT::current()->get(root_fd.get());
|
File *root_f = FDT::current()->get(root_fd.get());
|
||||||
@@ -17,7 +17,7 @@ bool VFSApi::mkdir(const Path &path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool VFSApi::touch(const Path &path) {
|
bool VFSApi::touch(const Path &path) {
|
||||||
auto root = path.subvector(0, path.size() - 1);
|
auto root = path.subvector(0, path.size() - 1);
|
||||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
||||||
if (root_fd.get() == -1) return false;
|
if (root_fd.get() == -1) return false;
|
||||||
File *root_f = FDT::current()->get(root_fd.get());
|
File *root_f = FDT::current()->get(root_fd.get());
|
||||||
|
|||||||
@@ -10,14 +10,14 @@
|
|||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
|
|
||||||
namespace VFSApi {
|
namespace VFSApi {
|
||||||
bool mkdir(const Path &path);
|
bool mkdir(const Path &path);
|
||||||
bool touch(const Path &path);
|
bool touch(const Path &path);
|
||||||
|
|
||||||
FDT::FD open(const Path &path);
|
FDT::FD open(const Path &path);
|
||||||
File *get(FDT::FD fd);
|
File *get(FDT::FD fd);
|
||||||
void close(FDT::FD fd);
|
void close(FDT::FD fd);
|
||||||
|
|
||||||
};// namespace VFSApi
|
}; // namespace VFSApi
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_VFSAPI_HPP
|
#endif //OS2_VFSAPI_HPP
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ NodeFile *RootNode::mkfile(const String &name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RootNode VFSGlobals::root;
|
RootNode VFSGlobals::root;
|
||||||
MountTable VFSGlobals::mounts;
|
MountTable VFSGlobals::mounts;
|
||||||
|
|||||||
@@ -11,14 +11,14 @@
|
|||||||
class RootNode : public NodeDir {
|
class RootNode : public NodeDir {
|
||||||
public:
|
public:
|
||||||
Vector<Node *> children() override;
|
Vector<Node *> children() override;
|
||||||
NodeDir *mkdir(const String &name) override;
|
NodeDir *mkdir(const String &name) override;
|
||||||
NodeFile *mkfile(const String &name) override;
|
NodeFile *mkfile(const String &name) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace VFSGlobals {
|
namespace VFSGlobals {
|
||||||
extern RootNode root;
|
extern RootNode root;
|
||||||
extern MountTable mounts;
|
extern MountTable mounts;
|
||||||
};// namespace VFSGlobals
|
}; // namespace VFSGlobals
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_VFSGLOBALS_HPP
|
#endif //OS2_VFSGLOBALS_HPP
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void VFSTester::test() {
|
|||||||
FDT::FD d = VFSApi::open(StrToPath("/hello/f2"));
|
FDT::FD d = VFSApi::open(StrToPath("/hello/f2"));
|
||||||
{
|
{
|
||||||
String t("hello wooooorld");
|
String t("hello wooooorld");
|
||||||
File *cf = VFSApi::get(c);
|
File *cf = VFSApi::get(c);
|
||||||
cf->write(t.c_str(), t.length() + 1);
|
cf->write(t.c_str(), t.length() + 1);
|
||||||
}
|
}
|
||||||
assert(a != -1);
|
assert(a != -1);
|
||||||
@@ -35,13 +35,13 @@ void VFSTester::test() {
|
|||||||
assert(c != -1);
|
assert(c != -1);
|
||||||
{
|
{
|
||||||
String t("aaaaaaaaaaaaaaaaaaaa");
|
String t("aaaaaaaaaaaaaaaaaaaa");
|
||||||
File *cf = VFSApi::get(c);
|
File *cf = VFSApi::get(c);
|
||||||
cf->read(t.data(), cf->size());
|
cf->read(t.data(), cf->size());
|
||||||
assert(t == "hello wooooorld");
|
assert(t == "hello wooooorld");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
String t("aaaaaaaaaaaaaaaaaaaa");
|
String t("aaaaaaaaaaaaaaaaaaaa");
|
||||||
File *cf = VFSApi::get(c);
|
File *cf = VFSApi::get(c);
|
||||||
cf->seek(0);
|
cf->seek(0);
|
||||||
cf->read(t.data(), 9);
|
cf->read(t.data(), 9);
|
||||||
cf->read(t.data() + 9, cf->size() - 9);
|
cf->read(t.data() + 9, cf->size() - 9);
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_VFSTESTER_HPP
|
#endif //OS2_VFSTESTER_HPP
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ void _start() {
|
|||||||
// putchar('h');
|
// putchar('h');
|
||||||
// putchar('i');
|
// putchar('i');
|
||||||
// putchar('\n');
|
// putchar('\n');
|
||||||
uint64_t test123 = open("/test123", O_CREAT | O_RDWR);
|
uint64_t test123 = open("/test123", O_CREAT | O_RDWR);
|
||||||
const char *teststr = "test str";
|
const char *teststr = "test str";
|
||||||
write(test123, teststr, 9);
|
write(test123, teststr, 9);
|
||||||
close(test123);
|
close(test123);
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum FileOpts : uint8_t {
|
enum FileOpts : uint8_t {
|
||||||
O_RDONLY = 1 << 1,// Read
|
O_RDONLY = 1 << 1, // Read
|
||||||
O_WRONLY = 1 << 2,// Write
|
O_WRONLY = 1 << 2, // Write
|
||||||
O_RDWR = O_RDONLY | O_WRONLY,
|
O_RDWR = O_RDONLY | O_WRONLY,
|
||||||
O_CREAT = 1 << 3,// Create
|
O_CREAT = 1 << 3, // Create
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -24,4 +24,4 @@ enum FileOpts : uint8_t {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_FILEOPTS_HPP
|
#endif //OS2_FILEOPTS_HPP
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct dirent {
|
struct dirent {
|
||||||
uint64_t inode_n;
|
uint64_t inode_n;
|
||||||
char d_name[];
|
char d_name[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -23,4 +23,4 @@ struct dirent {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif//OS2_DIRENT_H
|
#endif //OS2_DIRENT_H
|
||||||
|
|||||||
@@ -14,25 +14,25 @@ extern "C" {
|
|||||||
|
|
||||||
#include "FileOpts.h"
|
#include "FileOpts.h"
|
||||||
|
|
||||||
#define SYSCALL_PUTCHAR_ID 1
|
#define SYSCALL_PUTCHAR_ID 1
|
||||||
#define SYSCALL_SLEEP_ID 2
|
#define SYSCALL_SLEEP_ID 2
|
||||||
#define SYSCALL_READCHAR_ID 3
|
#define SYSCALL_READCHAR_ID 3
|
||||||
|
|
||||||
#define SYSCALL_OPEN_ID 4
|
#define SYSCALL_OPEN_ID 4
|
||||||
#define SYSCALL_CLOSE_ID 5
|
#define SYSCALL_CLOSE_ID 5
|
||||||
|
|
||||||
#define SYSCALL_READ_ID 6
|
#define SYSCALL_READ_ID 6
|
||||||
#define SYSCALL_WRITE_ID 7
|
#define SYSCALL_WRITE_ID 7
|
||||||
#define SYSCALL_LSEEK_ID 8
|
#define SYSCALL_LSEEK_ID 8
|
||||||
|
|
||||||
#define SYSCALL_OPENDIR_ID 9
|
#define SYSCALL_OPENDIR_ID 9
|
||||||
#define SYSCALL_READDIR_ID 10
|
#define SYSCALL_READDIR_ID 10
|
||||||
#define SYSCALL_CLOSEDIR_ID 11
|
#define SYSCALL_CLOSEDIR_ID 11
|
||||||
#define SYSCALL_MKDIR_ID 12
|
#define SYSCALL_MKDIR_ID 12
|
||||||
#define SYSCALL_UNLINK_ID 13
|
#define SYSCALL_UNLINK_ID 13
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif//OS2_SYSCALLS_DEFS_H
|
#endif //OS2_SYSCALLS_DEFS_H
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
uint64_t do_syscall(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx) {
|
uint64_t do_syscall(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx) {
|
||||||
uint64_t res;
|
uint64_t res;
|
||||||
asm volatile("syscall; mov (0x10016), %%rsp"// TASK_POINTER->ret_sp_val
|
asm volatile("syscall; mov (0x10016), %%rsp" // TASK_POINTER->ret_sp_val
|
||||||
: "=r"(res)
|
: "=r"(res)
|
||||||
: "D"(id_rdi), "S"(a1_rsi), "d"(a2_rdx), "a"(a3_rcx)
|
: "D"(id_rdi), "S"(a1_rsi), "d"(a2_rdx), "a"(a3_rcx)
|
||||||
: "cc", "rcx", "r8",
|
: "cc", "rcx", "r8",
|
||||||
|
|||||||
@@ -31,4 +31,4 @@ uint64_t lseek(uint64_t fd, uint64_t off, uint64_t whence);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif//OS2_SYSCALLS_INTERFACE_H
|
#endif //OS2_SYSCALLS_INTERFACE_H
|
||||||
|
|||||||
Reference in New Issue
Block a user