diff options
| author | cpplover0 <osdev555@yandex.com> | 2026-03-15 08:59:16 +0300 |
|---|---|---|
| committer | cpplover0 <osdev555@yandex.com> | 2026-03-15 08:59:16 +0300 |
| commit | 9361d205de9931d0dbeb63aa621ce66b995eca1a (patch) | |
| tree | fe57cf12888cae4473aeb50a9199d0894266ae0b | |
| parent | 76778e2715414a64c6f8abc6682e3727e3c9329a (diff) | |
pvclock trying to get working ext2
28 files changed, 650 insertions, 40 deletions
@@ -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 Binary files differindex 4709edd..9aa3900 100644 --- a/kernel/src/bg.bmp +++ b/kernel/src/bg.bmp 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 |
