summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcpplover0 <osdev555@yandex.com>2026-03-15 08:59:16 +0300
committercpplover0 <osdev555@yandex.com>2026-03-15 08:59:16 +0300
commit9361d205de9931d0dbeb63aa621ce66b995eca1a (patch)
treefe57cf12888cae4473aeb50a9199d0894266ae0b
parent76778e2715414a64c6f8abc6682e3727e3c9329a (diff)
pvclock trying to get working ext2
-rw-r--r--.gitignore3
-rw-r--r--kernel/GNUmakefile2
-rw-r--r--kernel/src/arch/aarch64/aarch64.cpp9
-rw-r--r--kernel/src/arch/riscv64/riscv64.cpp10
-rw-r--r--kernel/src/arch/x86_64/cpu_local.hpp1
-rw-r--r--kernel/src/arch/x86_64/drivers/pvclock.cpp79
-rw-r--r--kernel/src/arch/x86_64/drivers/pvclock.hpp30
-rw-r--r--kernel/src/arch/x86_64/drivers/tsc.cpp2
-rw-r--r--kernel/src/arch/x86_64/x86_64.cpp13
-rw-r--r--kernel/src/bg.bmpbin6220938 -> 2851038 bytes
-rw-r--r--kernel/src/drivers/disk.cpp122
-rw-r--r--kernel/src/drivers/disk.hpp24
-rw-r--r--kernel/src/drivers/ext2.cpp47
-rw-r--r--kernel/src/drivers/ext2.hpp82
-rw-r--r--kernel/src/drivers/gpt.hpp4
-rw-r--r--kernel/src/drivers/mbr.hpp21
-rw-r--r--kernel/src/drivers/nvme.cpp54
-rw-r--r--kernel/src/drivers/nvme.hpp5
-rw-r--r--kernel/src/generic/arch.hpp2
-rw-r--r--kernel/src/generic/heap.cpp2
-rw-r--r--kernel/src/generic/lock/mutex.hpp35
-rw-r--r--kernel/src/generic/lock/spinlock.hpp35
-rw-r--r--kernel/src/generic/pmm.cpp4
-rw-r--r--kernel/src/generic/pmm.hpp1
-rw-r--r--kernel/src/generic/vfs.cpp7
-rw-r--r--kernel/src/generic/vfs.hpp74
-rw-r--r--kernel/src/main.cpp1
-rw-r--r--kernel/src/utils/linux.hpp21
28 files changed, 650 insertions, 40 deletions
diff --git a/.gitignore b/.gitignore
index 7df8ca1..4452fe7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
/edk2-ovmf
*.iso
*.hdd
-disk.img \ No newline at end of file
+disk.img
+disk_gpt.img \ No newline at end of file
diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile
index 3061328..538a975 100644
--- a/kernel/GNUmakefile
+++ b/kernel/GNUmakefile
@@ -83,7 +83,7 @@ override SHARED_FLAGS := \
-ffreestanding \
-fno-stack-protector \
-fno-stack-check \
- -fno-lto \
+ -flto \
-fno-PIC -I uacpi/include \
-ffunction-sections \
-fdata-sections
diff --git a/kernel/src/arch/aarch64/aarch64.cpp b/kernel/src/arch/aarch64/aarch64.cpp
index 52003f8..72f6c09 100644
--- a/kernel/src/arch/aarch64/aarch64.cpp
+++ b/kernel/src/arch/aarch64/aarch64.cpp
@@ -56,6 +56,15 @@ namespace arch {
asm volatile("" ::: "memory");
}
+ [[gnu::weak]] bool test_interrupts() {
+ uint64_t daif;
+ __asm__ __volatile__ (
+ "mrs %0, daif"
+ : "=r" (daif)
+ );
+ return (daif & (1 << 7)) == 0;
+ }
+
[[gnu::weak]] void init(int stage) {
switch(stage) {
case ARCH_INIT_EARLY:
diff --git a/kernel/src/arch/riscv64/riscv64.cpp b/kernel/src/arch/riscv64/riscv64.cpp
index 784cc94..8e2fb37 100644
--- a/kernel/src/arch/riscv64/riscv64.cpp
+++ b/kernel/src/arch/riscv64/riscv64.cpp
@@ -20,6 +20,16 @@ namespace arch {
asm volatile("" ::: "memory");
}
+ [[gnu::weak]] bool test_interrupts() {
+ uint64_t status;
+ __asm__ __volatile__ (
+ "csrr %0, mstatus"
+ : "=r" (status)
+ );
+
+ return (status & (1 << 3)) != 0;
+ }
+
[[gnu::weak]] void hcf() {
disable_interrupts();
while(true) {
diff --git a/kernel/src/arch/x86_64/cpu_local.hpp b/kernel/src/arch/x86_64/cpu_local.hpp
index e839413..d5add64 100644
--- a/kernel/src/arch/x86_64/cpu_local.hpp
+++ b/kernel/src/arch/x86_64/cpu_local.hpp
@@ -15,6 +15,7 @@ typedef struct {
std::uint64_t timer_ist_stack;
std::uint32_t cpu;
std::uint64_t tsc_freq;
+ void* pvclock_buffer;
thread* current_thread;
} cpudata_t;
diff --git a/kernel/src/arch/x86_64/drivers/pvclock.cpp b/kernel/src/arch/x86_64/drivers/pvclock.cpp
new file mode 100644
index 0000000..d77ef0f
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/pvclock.cpp
@@ -0,0 +1,79 @@
+#define BILLION 1000000000UL
+#include <cstdint>
+#include <drivers/acpi.hpp>
+#include <arch/x86_64/drivers/pvclock.hpp>
+#include <arch/x86_64/cpu_local.hpp>
+#include <utils/gobject.hpp>
+#include <klibc/stdio.hpp>
+#include <arch/x86_64/assembly.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+
+#include <generic/arch.hpp>
+
+void drivers::pvclock::init() {
+ std::uint32_t a,b,c,d;
+
+ assembly::cpuid(0x40000000,0,&a,&b,&c,&d);
+ if(b != 0x4b4d564b || d != 0x4d || c != 0x564b4d56)
+ return;
+
+ assembly::cpuid(0x40000001,0,&a,&b,&c,&d);
+ if(!(a & (1 << 3)))
+ return;
+
+ x86_64::cpu_data()->pvclock_buffer = (void*)(pmm::freelist::alloc_4k() + etc::hhdm());
+
+ assembly::wrmsr(0x4b564d01,((std::uint64_t)x86_64::cpu_data()->pvclock_buffer - etc::hhdm()) | 1);
+}
+
+void drivers::pvclock::bsp_init() {
+ std::uint32_t a,b,c,d;
+
+ assembly::cpuid(0x40000000,0,&a,&b,&c,&d);
+ if(b != 0x4b4d564b || d != 0x4d || c != 0x564b4d56)
+ return;
+
+ assembly::cpuid(0x40000001,0,&a,&b,&c,&d);
+ if(!(a & (1 << 3)))
+ return;
+
+ pvclock::init();
+
+ drivers::pvclock_timer* timer = new drivers::pvclock_timer;
+ time::setup_timer(timer);
+
+ klibc::printf("pvclock: pointer to buffer 0x%p\r\n",x86_64::cpu_data()->pvclock_buffer);
+}
+
+namespace drivers {
+
+ std::uint64_t pvclock_timer::current_nano() {
+ uint32_t lo, hi;
+ asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
+ std::uint64_t tsc_v = ((uint64_t)hi << 32) | lo;
+ pvclock_vcpu_time_info* kvmclock_info = (pvclock_vcpu_time_info*)(x86_64::cpu_data()->pvclock_buffer);
+ std::uint64_t time0 = tsc_v - kvmclock_info->tsc_timestamp;
+ if(kvmclock_info->tsc_shift >= 0)
+ time0 <<= kvmclock_info->tsc_shift;
+ else
+ time0 >>= -kvmclock_info->tsc_shift;
+ time0 = (time0 * kvmclock_info->tsc_to_system_mul) >> 32;
+ time0 = time0 + kvmclock_info->system_time;
+ return time0;
+ }
+
+ void pvclock_timer::sleep(std::uint64_t us) {
+ std::uint64_t current = this->current_nano();
+ std::uint64_t end_ns = us * 1000;
+ std::uint64_t target = current + end_ns;
+
+ while(this->current_nano() < target) {
+ arch::pause();
+ }
+ }
+
+ int pvclock_timer::get_priority() {
+ return 999999999;
+ }
+} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/pvclock.hpp b/kernel/src/arch/x86_64/drivers/pvclock.hpp
new file mode 100644
index 0000000..6881107
--- /dev/null
+++ b/kernel/src/arch/x86_64/drivers/pvclock.hpp
@@ -0,0 +1,30 @@
+#pragma once
+#include <cstdint>
+#include <generic/time.hpp>
+
+struct pvclock_vcpu_time_info {
+ std::uint32_t version;
+ std::uint32_t pad0;
+ std::uint64_t tsc_timestamp;
+ std::uint64_t system_time;
+ std::uint32_t tsc_to_system_mul;
+ std::int8_t tsc_shift;
+ std::uint8_t flags;
+ std::uint8_t pad[2];
+};
+
+namespace drivers {
+
+ class pvclock_timer final : public time::generic_timer {
+ public:
+ int get_priority() override;
+ std::uint64_t current_nano() override;
+ void sleep(std::uint64_t us) override;
+ };
+
+ class pvclock {
+ public:
+ static void init();
+ static void bsp_init();
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/tsc.cpp b/kernel/src/arch/x86_64/drivers/tsc.cpp
index 0abcf6e..3776144 100644
--- a/kernel/src/arch/x86_64/drivers/tsc.cpp
+++ b/kernel/src/arch/x86_64/drivers/tsc.cpp
@@ -109,6 +109,6 @@ namespace drivers {
}
int tsc_timer::get_priority() {
- return 9999999; // undertale reference
+ return 9999;
}
} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/x86_64.cpp b/kernel/src/arch/x86_64/x86_64.cpp
index 4d272da..1389351 100644
--- a/kernel/src/arch/x86_64/x86_64.cpp
+++ b/kernel/src/arch/x86_64/x86_64.cpp
@@ -15,6 +15,7 @@
#include <arch/x86_64/schedule_timer.hpp>
#include <utils/gobject.hpp>
#include <arch/x86_64/cpu/sse.hpp>
+#include <arch/x86_64/drivers/pvclock.hpp>
namespace arch {
[[gnu::weak]] void disable_interrupts() {
@@ -72,6 +73,7 @@ namespace arch {
x86_64::init_cpu_data();
drivers::hpet::init();
drivers::tsc::init();
+ drivers::pvclock::bsp_init();
x86_64::gdt::init();
x86_64::idt::init();
x86_64::lapic::init(1500);
@@ -84,6 +86,7 @@ namespace arch {
enable_paging(gobject::kernel_root);
x86_64::init_cpu_data();
drivers::tsc::init();
+ drivers::pvclock::init();
x86_64::gdt::init();
x86_64::idt::init();
x86_64::lapic::init(1500);
@@ -108,4 +111,14 @@ namespace arch {
return x86_64::irq::create(irq,type,func,arg,flags);
}
+ [[gnu::weak]] bool test_interrupts() {
+ uint64_t rflags;
+ __asm__ __volatile__ (
+ "pushfq\n\t"
+ "pop %0" : "=rm" (rflags): : "memory"
+ );
+ return (rflags & (1 << 9)) != 0;
+ }
+
+
} \ No newline at end of file
diff --git a/kernel/src/bg.bmp b/kernel/src/bg.bmp
index 4709edd..9aa3900 100644
--- a/kernel/src/bg.bmp
+++ b/kernel/src/bg.bmp
Binary files differ
diff --git a/kernel/src/drivers/disk.cpp b/kernel/src/drivers/disk.cpp
new file mode 100644
index 0000000..78477dd
--- /dev/null
+++ b/kernel/src/drivers/disk.cpp
@@ -0,0 +1,122 @@
+#include <cstdint>
+#include <drivers/disk.hpp>
+#include <generic/hhdm.hpp>
+#include <generic/pmm.hpp>
+#include <drivers/mbr.hpp>
+#include <utils/assert.hpp>
+#include <klibc/string.hpp>
+#include <drivers/gpt.hpp>
+#include <drivers/ext2.hpp>
+
+const char* disk_type_to_str(partition_style disk_type) {
+ switch(disk_type) {
+ case partition_style::err:
+ return "Unknown";
+ case partition_style::mbr:
+ return "MBR";
+ case partition_style::gpt:
+ return "GPT";
+ case partition_style::raw:
+ return "Raw";
+ }
+}
+
+partition_style determine_disk_type(disk* target_disk) {
+
+ char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
+ target_disk->read(target_disk->arg, (char*)buffer, 1, 1);
+
+ if(!klibc::memcmp((const char*)buffer, GPT_SIGNATURE, sizeof(GPT_SIGNATURE))) {
+ pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
+ return partition_style::gpt;
+ }
+
+ target_disk->read(target_disk->arg, (char*)buffer, 0, 1);
+
+ if(((mbr_sector*)buffer)->signature == 0xAA55) {
+ pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
+ return partition_style::mbr;
+ }
+
+ assert(0, "Unknown partition style");
+ return partition_style::err;
+}
+
+bool disk_selftest(disk* target_disk) {
+ char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
+ if(target_disk->read(target_disk->arg, buffer, 0, 1) == true) {
+ pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
+ return true;
+ } else {
+ klibc::printf("Disk: Failed to do disk selftest\r\n");
+ return false;
+ }
+}
+
+const char* mbr_to_str(std::uint8_t type) {
+ switch (type)
+ {
+ case 0x83:
+ return "linux";
+ case 0xb:
+ return "fat32";
+ default:
+ return "unknown";
+ }
+ return "unknown";
+}
+
+void disk_do_mbr_linux(disk* new_disk, std::uint64_t start_lba) {
+
+ bytes_to_block_res b = bytes_to_blocks(1024, 1024, new_disk->lba_size);
+
+ char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
+ new_disk->read(new_disk->arg, buffer, start_lba + b.lba, b.size_in_blocks);
+ ext2_superblock *sb = (ext2_superblock*)buffer;
+
+ if (sb->s_magic == EXT2_MAGIC) {
+#ifdef MBR_ORANGE_TRACE
+ klibc::printf("Disk: Detected ext2\r\n");
+#endif
+ drivers::ext2::init(new_disk, start_lba);
+ }
+ pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
+}
+
+void disk_do_mbr(disk* new_disk) {
+ char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
+ new_disk->read(new_disk->arg, (char*)buffer, 0, 1);
+
+ mbr_sector* mbr = (mbr_sector*)buffer;
+
+ for(int i = 0; i < 4; i++) {
+ if(mbr->partitions[i].partition_type != 0) {
+#ifdef MBR_ORANGE_TRACE
+ klibc::printf("Disk: Detected mbr partition type %s (%d), lba_start %lli\r\n", mbr_to_str(mbr->partitions[i].partition_type), mbr->partitions[i].partition_type, mbr->partitions[i].lba_start);
+#endif
+ if(mbr->partitions[i].partition_type == 0x83) {
+ disk_do_mbr_linux(new_disk, mbr->partitions[i].lba_start);
+ }
+ }
+ }
+
+ pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
+}
+
+void drivers::init_disk(disk* new_disk) {
+ if(disk_selftest(new_disk) == false)
+ return;
+
+ partition_style style = determine_disk_type(new_disk);
+ klibc::printf("Disk: Detected %s partition style\r\n", disk_type_to_str(style));
+
+ switch (style)
+ {
+ case partition_style::mbr:
+ disk_do_mbr(new_disk);
+ break;
+ default:
+ assert(0,"unsupported disk\r\n");
+ break;
+ }
+} \ No newline at end of file
diff --git a/kernel/src/drivers/disk.hpp b/kernel/src/drivers/disk.hpp
index 584d94e..d1ac4b5 100644
--- a/kernel/src/drivers/disk.hpp
+++ b/kernel/src/drivers/disk.hpp
@@ -1,5 +1,13 @@
#pragma once
#include <cstdint>
+#include <klibc/stdio.hpp>
+
+enum class partition_style : std::uint8_t {
+ err = 0,
+ mbr = 1,
+ gpt = 2,
+ raw = 5
+};
struct disk {
void* arg;
@@ -7,4 +15,20 @@ struct disk {
std::size_t disk_size;
bool (*read)(void* arg, char* buffer, std::uint64_t lba, std::size_t len_in_blocks);
bool (*write)(void* arg, char* buffer, std::uint64_t lba, std::size_t len_in_blocks);
+};
+
+struct bytes_to_block_res {
+ std::uint64_t lba;
+ std::uint64_t size_in_blocks;
+};
+
+inline static bytes_to_block_res bytes_to_blocks(std::uint64_t start, std::uint64_t size, std::uint64_t lba_size) {
+ bytes_to_block_res result;
+ result.lba = start / lba_size;
+ result.size_in_blocks = (size / lba_size) == 0 ? 1 : (size / lba_size);
+ return result;
+}
+
+namespace drivers {
+ void init_disk(disk* new_disk);
}; \ No newline at end of file
diff --git a/kernel/src/drivers/ext2.cpp b/kernel/src/drivers/ext2.cpp
new file mode 100644
index 0000000..f153e7a
--- /dev/null
+++ b/kernel/src/drivers/ext2.cpp
@@ -0,0 +1,47 @@
+#include <drivers/ext2.hpp>
+#include <drivers/disk.hpp>
+#include <generic/vfs.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+#include <utils/assert.hpp>
+#include <klibc/stdio.hpp>
+#include <cstdint>
+
+ext2_inode ext2_get_inode(ext2_partition* partition, std::uint64_t inode_num) {
+
+ char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
+
+ ext2_superblock* sb = partition->sb;
+ std::uint32_t group = (inode_num - 1) / sb->s_inodes_per_group;
+ std::uint32_t index = (inode_num - 1) % sb->s_inodes_per_group;
+
+ std::uint32_t bgdt_block = (sb->s_log_block_size == 0) ? 2 : 1;
+ std::uint32_t block_size = 1024 << sb->s_log_block_size;
+
+ bytes_to_block_res result = bytes_to_blocks(block_size * bgdt_block, block_size, partition->target_disk->lba_size);
+ partition->target_disk->read(partition->target_disk->arg, buffer, result.lba, result.size_in_blocks);
+
+ struct ext2_group_desc *gd = (struct ext2_group_desc *)((std::uint64_t)buffer + group);
+
+ uint32_t inode_size = 128;
+ uint32_t byte_offset = index * inode_size;
+ uint32_t block_in_table = gd->bg_inode_table + (byte_offset / block_size);
+ uint32_t internal_offset = byte_offset % block_size;
+
+ result = bytes_to_blocks(block_size * block_in_table, block_size, partition->target_disk->lba_size);
+
+ char* inode_buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
+ partition->target_disk->read(partition->target_disk->arg, inode_buffer, result.lba, result.size_in_blocks);
+
+ pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
+ return *(struct ext2_inode*)((std::uint64_t)inode_buffer + internal_offset);
+}
+
+void drivers::ext2::init(disk* target_disk, std::uint64_t lba_start) {
+ bytes_to_block_res b = bytes_to_blocks(1024, 1024, target_disk->lba_size);
+ char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
+ target_disk->read(target_disk->arg, buffer, lba_start + b.lba, b.size_in_blocks);
+ ext2_superblock *sb = (ext2_superblock*)buffer;
+
+ assert(sb->s_magic == EXT2_MAGIC,"its not ext2 partition !");
+} \ No newline at end of file
diff --git a/kernel/src/drivers/ext2.hpp b/kernel/src/drivers/ext2.hpp
new file mode 100644
index 0000000..bfede39
--- /dev/null
+++ b/kernel/src/drivers/ext2.hpp
@@ -0,0 +1,82 @@
+#pragma once
+#include <cstdint>
+#include <drivers/disk.hpp>
+#include <generic/lock/mutex.hpp>
+
+struct ext2_superblock {
+ uint32_t s_inodes_count;
+ uint32_t s_blocks_count;
+ uint32_t s_r_blocks_count;
+ uint32_t s_free_blocks_count;
+ uint32_t s_free_inodes_count;
+ uint32_t s_first_data_block;
+ uint32_t s_log_block_size;
+ uint32_t s_log_frag_size;
+ uint32_t s_blocks_per_group;
+ uint32_t s_frags_per_group;
+ uint32_t s_inodes_per_group;
+ uint32_t s_mtime;
+ uint32_t s_wtime;
+ uint16_t s_mnt_count;
+ uint16_t s_max_mnt_count;
+ uint16_t s_magic;
+ uint16_t s_state;
+ uint16_t s_errors;
+ uint16_t s_minor_rev_level;
+};
+
+struct ext2_group_desc {
+ uint32_t bg_block_bitmap;
+ uint32_t bg_inode_bitmap;
+ uint32_t bg_inode_table;
+ uint16_t bg_free_blocks_count;
+ uint16_t bg_free_inodes_count;
+ uint16_t bg_used_dirs_count;
+ uint16_t bg_pad;
+ uint32_t bg_reserved[3];
+};
+
+struct ext2_inode {
+ uint16_t i_mode;
+ uint16_t i_uid;
+ uint32_t i_size;
+ uint32_t i_atime;
+ uint32_t i_ctime;
+ uint32_t i_mtime;
+ uint32_t i_dtime;
+ uint16_t i_gid;
+ uint16_t i_links_count;
+ uint32_t i_blocks;
+ uint32_t i_flags;
+ uint32_t i_osd1;
+ uint32_t i_block[15];
+ uint32_t i_generation;
+ uint32_t i_file_acl;
+ uint32_t i_dir_acl;
+ uint32_t i_faddr;
+ uint32_t i_osd2[3];
+};
+
+struct ext2_dir_entry {
+ uint32_t inode;
+ uint16_t rec_len;
+ uint8_t name_len;
+ uint8_t file_type;
+ char name[];
+};
+
+struct ext2_partition {
+ std::uint64_t lba_start;
+ ext2_superblock* sb;
+ locks::mutex lock;
+ disk* target_disk;
+ char* buffer;
+};
+
+#define EXT2_MAGIC 0xEF53
+
+namespace drivers {
+ namespace ext2 {
+ void init(disk* target_disk, std::uint64_t lba_start);
+ }
+} \ No newline at end of file
diff --git a/kernel/src/drivers/gpt.hpp b/kernel/src/drivers/gpt.hpp
new file mode 100644
index 0000000..9f43b54
--- /dev/null
+++ b/kernel/src/drivers/gpt.hpp
@@ -0,0 +1,4 @@
+#pragma once
+#include <cstdint>
+
+#define GPT_SIGNATURE "EFI PART" \ No newline at end of file
diff --git a/kernel/src/drivers/mbr.hpp b/kernel/src/drivers/mbr.hpp
new file mode 100644
index 0000000..4a78a95
--- /dev/null
+++ b/kernel/src/drivers/mbr.hpp
@@ -0,0 +1,21 @@
+#pragma once
+#include <cstdint>
+
+// mbr headers
+
+#define MBR_ORANGE_TRACE
+
+struct __attribute__((packed)) mbr_partition {
+ std::uint8_t drive_status;
+ std::uint8_t chs_start[3];
+ std::uint8_t partition_type;
+ std::uint8_t chs_end[3];
+ std::uint32_t lba_start;
+ std::uint32_t sector_count;
+};
+
+struct __attribute__((packed)) mbr_sector {
+ std::uint8_t bootstrap[446];
+ mbr_partition partitions[4];
+ std::uint16_t signature;
+}; \ No newline at end of file
diff --git a/kernel/src/drivers/nvme.cpp b/kernel/src/drivers/nvme.cpp
index 4be38c6..7ec7a21 100644
--- a/kernel/src/drivers/nvme.cpp
+++ b/kernel/src/drivers/nvme.cpp
@@ -124,7 +124,7 @@ bool nvme_wait_io(nvme_pair_queue* queue, uint64_t timeout_ms) {
uint16_t status_code = (cq[queue->cq_head].status >> 1) & 0xFF;
queue->cq_head++;
- if (queue->cq_head > 63) {
+ if (queue->cq_head > 1) {
queue->cq_head = 0;
queue->phase ^= 1;
}
@@ -215,7 +215,7 @@ bool nvme_write(void* arg, char* buffer, std::uint64_t lba, std::size_t len_in_b
std::size_t lba_size = disk->ctrl->namespaces[disk->nsid - 1].lba_size;
- assert(((std::uint64_t)buffer & PAGE_SIZE) == 0, "Unaligned buffer\r\n");
+ assert(((std::uint64_t)buffer & (PAGE_SIZE - 1)) == 0, "Unaligned buffer\r\n");
std::size_t blocks = len_in_blocks;
std::size_t num_pages = ((blocks * lba_size) + PAGE_SIZE - 1) / PAGE_SIZE;
@@ -265,7 +265,10 @@ bool nvme_read(void* arg, char* buffer, std::uint64_t lba, std::size_t len_in_bl
std::size_t lba_size = disk->ctrl->namespaces[disk->nsid - 1].lba_size;
- assert(((std::uint64_t)buffer & PAGE_SIZE) == 0, "Unaligned buffer\r\n");
+#ifdef NVME_ORANGE_TRACE
+ klibc::printf("NVME Trace: Reading with buffer 0x%p 0x%p %d\r\n",buffer, (std::uint64_t)buffer & PAGE_SIZE, ((std::uint64_t)buffer & PAGE_SIZE) == 0);
+#endif
+ assert(((std::uint64_t)buffer & (PAGE_SIZE - 1)) == 0, "Unaligned buffer\r\n");
std::size_t blocks = len_in_blocks;
std::size_t num_pages = ((blocks * lba_size) + PAGE_SIZE - 1) / PAGE_SIZE;
@@ -302,36 +305,34 @@ bool nvme_read(void* arg, char* buffer, std::uint64_t lba, std::size_t len_in_bl
return status;
}
-static inline int isprint(int c) {
- return (c >= 0x20 && c <= 0x7E);
-}
+// static inline int isprint(int c) {
+// return (c >= 0x20 && c <= 0x7E);
+// }
-static inline void print_buffer(const unsigned char *buffer, std::size_t size) {
- for (std::size_t i = 0; i < size; i++) {
- if (isprint(buffer[i])) {
- klibc::printf("%c ", buffer[i]);
- } else {
- klibc::printf("0x%02X ", buffer[i]);
- }
- }
- klibc::printf("\r\n");
-}
+// static inline void print_buffer(const unsigned char *buffer, std::size_t size) {
+// for (std::size_t i = 0; i < size; i++) {
+// if (isprint(buffer[i])) {
+// klibc::printf("%c ", buffer[i]);
+// } else {
+// klibc::printf("0x%02X ", buffer[i]);
+// }
+// }
+// klibc::printf("\r\n");
+// }
void nvme_init_namespace(nvme_controller* ctrl, std::uint32_t nsid) {
- void* buffer_test = (void*)(pmm::freelist::alloc_4k() + etc::hhdm());
nvme_arg_disk* new_disk = new nvme_arg_disk;
new_disk->ctrl = ctrl;
new_disk->nsid = nsid;
- klibc::memset(buffer_test,'a',4096);
- nvme_write(new_disk, (char*)buffer_test, 0, 2);
- nvme_read(new_disk, (char*)buffer_test, 0, 2);
-
- ((char*)buffer_test)[4095] = '\0';
- klibc::printf("test nvme dumping first 1024 byte \r\n", buffer_test, klibc::strlen((const char*)buffer_test));
- print_buffer((const unsigned char*)buffer_test, 1024);
+ disk* generic_disk = new disk;
+ generic_disk->arg = new_disk;
+ generic_disk->lba_size = ctrl->namespaces[new_disk->nsid - 1].lba_size;
+ generic_disk->read = nvme_read;
+ generic_disk->write = nvme_write;
+ drivers::init_disk(generic_disk);
}
bool nvme_init_namespaces(nvme_controller* ctrl) {
@@ -453,8 +454,6 @@ void nvme_init(std::uint64_t base) {
paging::map_range(gobject::kernel_root, base, base + etc::hhdm(), PAGE_SIZE * 4, PAGING_PRESENT | PAGING_RW | PAGING_NC);
- std::uint64_t start = time::timer->current_nano();
-
nvme_controller* controller = new nvme_controller;
controller->bar0 = (void*)(base + etc::hhdm());
std::uint64_t cap = nvme::read64(controller, NVME_REG_CAP);
@@ -499,9 +498,6 @@ void nvme_init(std::uint64_t base) {
klibc::printf("NVME: Failed to init namespaces\r\n");
}
- std::uint64_t end = time::timer->current_nano();
-
- klibc::printf("NVME: Detected %d namespaces in %lli us\r\n", controller->num_namespaces, (end - start) / 1000);
nvme_controllers[nvme_controller_ptr++] = controller;
}
diff --git a/kernel/src/drivers/nvme.hpp b/kernel/src/drivers/nvme.hpp
index 69d957c..9b66593 100644
--- a/kernel/src/drivers/nvme.hpp
+++ b/kernel/src/drivers/nvme.hpp
@@ -3,9 +3,10 @@
#include <drivers/disk.hpp>
#include <generic/hhdm.hpp>
#include <generic/lock/spinlock.hpp>
+#include <generic/lock/mutex.hpp>
#include <generic/arch.hpp>
-#define NVME_ORANGE_TRACE
+//#define NVME_ORANGE_TRACE
#define NVME_REG_CAP 0x00 // Controller Capabilities
#define NVME_REG_VS 0x08 // Version
@@ -124,7 +125,7 @@ struct nvme_pair_queue {
std::uint8_t qid;
volatile std::uint32_t* sq_doorbell;
volatile std::uint32_t* cq_doorbell;
- locks::spinlock lock;
+ locks::mutex lock;
};
struct nvme_controller {
diff --git a/kernel/src/generic/arch.hpp b/kernel/src/generic/arch.hpp
index b983a1b..b31dda6 100644
--- a/kernel/src/generic/arch.hpp
+++ b/kernel/src/generic/arch.hpp
@@ -34,6 +34,8 @@ namespace arch {
extern void copy_higher_half(std::uintptr_t root, std::uintptr_t src_root);
extern int level_paging();
+ extern bool test_interrupts();
+
extern std::uint64_t current_root();
extern void memory_barrier();
diff --git a/kernel/src/generic/heap.cpp b/kernel/src/generic/heap.cpp
index 6468a8a..e096a68 100644
--- a/kernel/src/generic/heap.cpp
+++ b/kernel/src/generic/heap.cpp
@@ -23,7 +23,7 @@ void kheap::init() {
}
-int is_early = 0;
+int is_early = 1;
void kheap::opt_free(void* ptr) {
if(!is_early) {
diff --git a/kernel/src/generic/lock/mutex.hpp b/kernel/src/generic/lock/mutex.hpp
new file mode 100644
index 0000000..d48b0b4
--- /dev/null
+++ b/kernel/src/generic/lock/mutex.hpp
@@ -0,0 +1,35 @@
+#pragma once
+#include <cstdint>
+#include <atomic>
+
+#include <generic/lock/spinlock.hpp>
+#include <generic/scheduling.hpp>
+
+namespace locks {
+ class mutex {
+ private:
+ std::atomic_flag flag = ATOMIC_FLAG_INIT;
+
+ public:
+ void lock() {
+ if(locks::is_disabled)
+ return;
+
+ while (flag.test_and_set(std::memory_order_acquire)) {
+ process::yield();
+ }
+ }
+
+ void unlock() {
+ flag.clear(std::memory_order_release);
+ }
+
+ bool test() {
+ return flag.test();
+ }
+
+ bool try_lock() {
+ return !flag.test_and_set(std::memory_order_acquire);
+ }
+ };
+}; \ No newline at end of file
diff --git a/kernel/src/generic/lock/spinlock.hpp b/kernel/src/generic/lock/spinlock.hpp
index 782e682..2c2b2a6 100644
--- a/kernel/src/generic/lock/spinlock.hpp
+++ b/kernel/src/generic/lock/spinlock.hpp
@@ -6,6 +6,41 @@
namespace locks {
inline bool is_disabled = 0;
+
+ class preempt_spinlock {
+ private:
+ std::atomic_flag flag = ATOMIC_FLAG_INIT;
+ public:
+ bool lock() {
+ if(is_disabled)
+ return 0;
+
+ bool state = arch::test_interrupts();
+
+ arch::disable_interrupts();
+ while (flag.test_and_set(std::memory_order_acquire)) {
+ arch::pause();
+ }
+
+ return state;
+ }
+
+ void unlock(bool state) {
+ flag.clear(std::memory_order_release);
+
+ if(state)
+ arch::enable_interrupts();
+ }
+
+ bool test() {
+ return flag.test();
+ }
+
+ bool try_lock() {
+ return !flag.test_and_set(std::memory_order_acquire);
+ }
+ };
+
class spinlock {
private:
std::atomic_flag flag = ATOMIC_FLAG_INIT;
diff --git a/kernel/src/generic/pmm.cpp b/kernel/src/generic/pmm.cpp
index 01d38f0..d5c063e 100644
--- a/kernel/src/generic/pmm.cpp
+++ b/kernel/src/generic/pmm.cpp
@@ -75,9 +75,6 @@ void pmm::buddy::merge(buddy_info_t* budy) {
blud->is_splitted = 0;
blud->is_was_splitted = 1;
blud->is_free = 1;
- blud->id = 0;
- bl->id = 0;
- ud->id = 0;
if(blud->parent)
merge(blud);
return;
@@ -177,7 +174,6 @@ int pmm::buddy::nlfree(std::uint64_t phys) {
if(!blud || blud->is_splitted)
return -1;
blud->is_free = 1;
- blud->id = 0;
if(blud->parent)
merge(blud);
return 0;
diff --git a/kernel/src/generic/pmm.hpp b/kernel/src/generic/pmm.hpp
index d3279a9..a404c98 100644
--- a/kernel/src/generic/pmm.hpp
+++ b/kernel/src/generic/pmm.hpp
@@ -18,7 +18,6 @@ typedef struct buddy_info {
};
struct buddy_info* parent;
struct buddy_info* twin;
- std::uint32_t id;
std::uint64_t phys;
} __attribute__((packed)) buddy_info_t;
diff --git a/kernel/src/generic/vfs.cpp b/kernel/src/generic/vfs.cpp
new file mode 100644
index 0000000..d34ae0c
--- /dev/null
+++ b/kernel/src/generic/vfs.cpp
@@ -0,0 +1,7 @@
+#include <cstdint>
+#include <generic/vfs.hpp>
+#include <drivers/disk.hpp>
+
+void vfs::init() {
+
+} \ No newline at end of file
diff --git a/kernel/src/generic/vfs.hpp b/kernel/src/generic/vfs.hpp
new file mode 100644
index 0000000..8736d42
--- /dev/null
+++ b/kernel/src/generic/vfs.hpp
@@ -0,0 +1,74 @@
+#pragma once
+#include <cstdint>
+#include <drivers/disk.hpp>
+#include <generic/lock/mutex.hpp>
+#include <utils/linux.hpp>
+
+enum class file_descriptor_type : std::uint8_t {
+ unallocated = 0,
+ file = 1,
+ pipe = 2,
+ socket = 3,
+ epoll = 4,
+ memfd = 5
+};
+
+struct stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ blksize_t st_blksize;
+ blkcnt_t st_blocks;
+
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+
+#define st_atime st_atim.tv_sec
+#define st_mtime st_mtim.tv_sec
+#define st_ctime st_ctim.tv_sec
+};
+
+struct filesystem {
+ locks::mutex lock;
+
+ std::uint32_t (*open)(void* file_desc, char* path);
+
+ char path[2048];
+};
+
+struct file_descriptor {
+
+ file_descriptor_type type;
+ std::uint32_t flags;
+
+ union fs_specific {
+ std::uint64_t ino;
+ std::uint64_t tmpfs_pointer;
+ };
+
+ struct vnode {
+ disk* target_disk;
+ filesystem* fs;
+
+ signed long (*read)(file_descriptor* file, void* buffer, signed long count);
+ signed long (*write)(file_descriptor* file, void* buffer, signed long count);
+ signed long (*stat)(file_descriptor* file, stat* out);
+ void (*close)(file_descriptor* file);
+ };
+
+};
+
+namespace vfs {
+
+ void init();
+ void open(file_descriptor* fd, char* path, bool follow_symlinks );
+ void create(char* path, std::uint32_t mode); // mode contains type too
+}
+
+// fs should setup this during open
diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp
index 6af515e..7c9ba13 100644
--- a/kernel/src/main.cpp
+++ b/kernel/src/main.cpp
@@ -37,6 +37,7 @@ extern "C" void main() {
acpi::init_tables();
arch::init(ARCH_INIT_EARLY);
acpi::full_init();
+ is_early = 0;
arch::init(ARCH_INIT_COMMON);
mp::init();
mp::sync();
diff --git a/kernel/src/utils/linux.hpp b/kernel/src/utils/linux.hpp
new file mode 100644
index 0000000..0fb2ab6
--- /dev/null
+++ b/kernel/src/utils/linux.hpp
@@ -0,0 +1,21 @@
+#pragma once
+#include <cstdint>
+
+typedef uint64_t dev_t;
+typedef uint64_t ino_t;
+
+typedef uint32_t mode_t;
+typedef uint64_t nlink_t;
+typedef uint32_t uid_t;
+typedef uint32_t gid_t;
+
+typedef int64_t off_t;
+typedef int64_t blksize_t;
+typedef int64_t blkcnt_t;
+
+typedef int64_t time_t;
+
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+}; \ No newline at end of file