diff --git a/bin/cat/cat.c b/bin/cat/cat.c index 37b92269..841263a1 100644 --- a/bin/cat/cat.c +++ b/bin/cat/cat.c @@ -2,14 +2,14 @@ int main(int argc, const char* argv[]){ file fd2 = { .id = 2 }; - if (argc != 2){ - string err_msg = string_from_literal("Usage cat "); + if (argc < 1 || argc > 2){ + string err_msg = string_from_literal("Usage cat [size]"); fwrite(&fd2, err_msg.data, err_msg.length); free(err_msg.data, err_msg.mem_length); return 2; } const char* path = argv[0]; - size_t size = parse_int_u64(argv[1], UINT32_MAX); + size_t size = argc < 2 ? 0 : parse_int_u64(argv[1], UINT32_MAX); file fd = {}; fopen(path, &fd); if (fd.size == 0){ diff --git a/kernel/audio/virtio_audio_pci.cpp b/kernel/audio/virtio_audio_pci.cpp index 0650cc5e..26c05460 100644 --- a/kernel/audio/virtio_audio_pci.cpp +++ b/kernel/audio/virtio_audio_pci.cpp @@ -206,7 +206,7 @@ bool VirtioAudioDriver::config_streams(uint32_t streams){ void VirtioAudioDriver::send_buffer(sizedptr buf){ virtio_add_buffer(&audio_dev, cmd_index % audio_dev.common_cfg->queue_size, buf.ptr, buf.size, true); - struct virtq_used* u = (struct virtq_used*)(uintptr_t)audio_dev.common_cfg->queue_device; + volatile virtq_used* u = (virtq_used*)audio_dev.common_cfg->queue_device; while (u->idx < cmd_index-2) yield(); cmd_index++; diff --git a/kernel/bin/bin_mod.c b/kernel/bin/bin_mod.c index 644eee49..2e7ff0a6 100644 --- a/kernel/bin/bin_mod.c +++ b/kernel/bin/bin_mod.c @@ -51,17 +51,30 @@ process_t* execute(const char* prog_name, int argc, const char* argv[]){ } process_t *proc = load_elf_file(prog_name, 0, program, fd.size); string_free(path); - free(full_name,name_len); + free(full_name, name_len); if (!proc){ kprintf("Failed to create process for %s",prog_name); } proc->PROC_X0 = argc; - size_t total = 0; - for (int i = 0; i < argc; i++) - total += strlen(argv[i], 0); - char **nargv = (char **)kalloc((void*)proc->heap, total, ALIGN_16B, MEM_PRIV_USER); - memcpy(nargv, argv, total); - proc->PROC_X1 = (uintptr_t)nargv; + if (argc > 0){ + uintptr_t start = (uintptr_t)argv[0]; + uintptr_t end = (uintptr_t)argv; + size_t total = end-start; + size_t argvs = argc * sizeof(uintptr_t); + char *nargvals = (char*)(proc->stack_phys-total-argvs); + char *vnargvals = (char*)(proc->stack-total-argvs); + char** nargv = (char**)(proc->stack_phys-argvs); + uintptr_t strptr = 0; + for (int i = 0; i < argc; i++){ + size_t strsize = strlen(argv[i],0); + memcpy(nargvals + strptr, argv[i], strsize); + *(char*)(nargvals + strptr + strsize) = 0; + nargv[i] = vnargvals + strptr; + strptr += strsize; + } + proc->PROC_X1 = (uintptr_t)proc->stack-argvs; + proc->sp -= total+argvs; + } proc->state = READY; return proc; } diff --git a/kernel/console/serial/uart.c b/kernel/console/serial/uart.c index a375b869..5d29c9cc 100644 --- a/kernel/console/serial/uart.c +++ b/kernel/console/serial/uart.c @@ -3,6 +3,7 @@ #include "gpio.h" #include "hw/hw.h" #include "mailbox/mailbox.h" +#include "memory/mmu.h" #define UART0_DR (UART0_BASE + 0x00) #define UART0_FR (UART0_BASE + 0x18) @@ -29,6 +30,8 @@ volatile uint32_t uart_mbox[9] __attribute__((aligned(16))) = { }; void enable_uart() { + register_device_memory(UART0_CR, UART0_CR); + write32(UART0_CR, 0x0); uint32_t ibrd = 1; diff --git a/kernel/exceptions/irq.c b/kernel/exceptions/irq.c index 6b9ad6f9..6518706a 100644 --- a/kernel/exceptions/irq.c +++ b/kernel/exceptions/irq.c @@ -11,6 +11,7 @@ #include "audio/audio.h" #include "networking/interface_manager.h" #include "process/syscall.h" +#include "memory/mmu.h" #define IRQ_TIMER 30 #define SLEEP_TIMER 27 @@ -40,6 +41,9 @@ static void gic_enable_irq(uint32_t irq, uint8_t priority, uint8_t cpu_target) { } void irq_init() { + register_device_memory(GICD_BASE, GICD_BASE); + register_device_memory(GICC_BASE, GICC_BASE); + if (RPI_BOARD != 3){ write32(GICD_BASE, 0); // Disable Distributor write32(GICC_BASE, 0); // Disable CPU Interface diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 79048ba4..3de3e4a9 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -228,7 +228,7 @@ sizedptr FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, ch if (entry->flags.volume_id) return {0,0}; bool is_last = *seek_to(seek, '/') == '\0'; - if (!is_last && strstart(seek, filename, true) == 0) return {0, 0}; + if (!is_last && strstart(seek, filename, true) < (int)(strlen(filename, 0)-1)) return {0, 0}; if (is_last && strcmp(seek, filename, true) != 0) return {0, 0}; uint32_t filecluster = (entry->hi_first_cluster << 16) | entry->lo_first_cluster; @@ -265,7 +265,7 @@ size_t FAT32FS::read_file(file *descriptor, void* buf, size_t size){ sizedptr FAT32FS::list_entries_handler(FAT32FS *instance, f32file_entry *entry, char *filename, const char *seek) { if (entry->flags.volume_id) return { 0, 0 }; - if (strstart(seek, filename, true) == 0) return { 0, 0 }; + if (strstart(seek, filename, true) != (int)(strlen(filename, 0)-1)) return { 0, 0 }; bool is_last = *seek_to(seek, '/') == '\0'; diff --git a/kernel/filesystem/virtio_blk_pci.c b/kernel/filesystem/virtio_blk_pci.c index 01a725bc..c0a2b7de 100644 --- a/kernel/filesystem/virtio_blk_pci.c +++ b/kernel/filesystem/virtio_blk_pci.c @@ -1,3 +1,4 @@ +#include "virtio_blk_pci.h" #include "disk.h" #include "std/string.h" #include "std/memory_access.h" @@ -6,28 +7,16 @@ #include "pci.h" #include "virtio/virtio_pci.h" #include "std/memory.h" -#include "virtio_blk_pci.h" +#include "sysregs.h" #define VIRTIO_BLK_T_IN 0 #define VIRTIO_BLK_T_OUT 1 -struct virtio_blk_req { +typedef struct { uint32_t type; uint32_t reserved; uint64_t sector; -} __attribute__((packed)); - -struct virtio_blk_config { - uint64_t capacity;//In number of sectors - uint32_t size_max; - uint32_t seg_max; - struct { - uint16_t cylinders; - uint8_t heads; - uint8_t sectors; - } geometry; - uint32_t blk_size; -} __attribute__((packed)); +} __attribute__((packed)) virtio_blk_req; #define VIRTIO_BLK_SUPPORTED_FEATURES \ ((1 << 0) | (1 << 1) | (1 << 4)) @@ -72,28 +61,28 @@ bool vblk_find_disk(){ void* disk_cmd; void vblk_write(const void *buffer, uint32_t sector, uint32_t count) { - if (!disk_cmd) disk_cmd = kalloc(blk_dev.memory_page, sizeof(struct virtio_blk_req), ALIGN_64B, MEM_PRIV_KERNEL); + if (!disk_cmd) disk_cmd = kalloc(blk_dev.memory_page, sizeof(virtio_blk_req), ALIGN_64B, MEM_PRIV_KERNEL); void* data = kalloc(blk_dev.memory_page, count * 512, ALIGN_64B, MEM_PRIV_KERNEL); memcpy(data, buffer, count * 512); - struct virtio_blk_req *req = (struct virtio_blk_req *)(uintptr_t)disk_cmd; + virtio_blk_req *req = (virtio_blk_req *)disk_cmd; req->type = VIRTIO_BLK_T_OUT; req->reserved = 0; req->sector = sector; - virtio_send_3d(&blk_dev, (uintptr_t)disk_cmd, sizeof(struct virtio_blk_req), (uintptr_t)data, count * 512, 0); + virtio_send_3d(&blk_dev, (uintptr_t)disk_cmd, sizeof(virtio_blk_req), (uintptr_t)data, count * 512, 0); kfree((void *)data,count * 512); } void vblk_read(void *buffer, uint32_t sector, uint32_t count) { - if (!disk_cmd) disk_cmd = kalloc(blk_dev.memory_page, sizeof(struct virtio_blk_req), ALIGN_64B, MEM_PRIV_KERNEL); + if (!disk_cmd) disk_cmd = kalloc(blk_dev.memory_page, sizeof(virtio_blk_req), ALIGN_64B, MEM_PRIV_KERNEL); - struct virtio_blk_req *req = (struct virtio_blk_req *)disk_cmd; + virtio_blk_req *req = (virtio_blk_req *)disk_cmd; req->type = VIRTIO_BLK_T_IN; req->reserved = 0; req->sector = sector; - virtio_send_3d(&blk_dev, (uintptr_t)disk_cmd, sizeof(struct virtio_blk_req), (uintptr_t)buffer, count * 512, VIRTQ_DESC_F_WRITE); + virtio_send_3d(&blk_dev, VIRT_TO_PHYS((uintptr_t)disk_cmd), sizeof(virtio_blk_req), VIRT_TO_PHYS((uintptr_t)buffer), count * 512, VIRTQ_DESC_F_WRITE); } \ No newline at end of file diff --git a/kernel/fw/fw_cfg.c b/kernel/fw/fw_cfg.c index 2055545f..a32deaea 100644 --- a/kernel/fw/fw_cfg.c +++ b/kernel/fw/fw_cfg.c @@ -2,6 +2,8 @@ #include "console/kio.h" #include "std/memory_access.h" #include "memory/mmu.h" +#include "async.h" +#include "sysregs.h" #define FW_CFG_DATA 0x09020000 #define FW_CFG_CTL (FW_CFG_DATA + 0x8) @@ -25,25 +27,26 @@ struct fw_cfg_dma_access { bool fw_cfg_check(){ if (checked) return true; + register_device_memory(FW_CFG_DATA, FW_CFG_DATA); checked = read64(FW_CFG_DATA) == 0x554D4551; - if (checked){ - register_device_memory(FW_CFG_DATA, FW_CFG_DATA); - } + if (!checked) mmu_unmap(FW_CFG_DATA, FW_CFG_DATA); return checked; } void fw_cfg_dma_operation(void* dest, uint32_t size, uint32_t ctrl) { struct fw_cfg_dma_access access = { - .address = __builtin_bswap64((uint64_t)dest), + .address = __builtin_bswap64(VIRT_TO_PHYS((uint64_t)dest)), .length = __builtin_bswap32(size), .control = __builtin_bswap32(ctrl), }; - write64(FW_CFG_DMA, __builtin_bswap64((uint64_t)&access)); + write64(FW_CFG_DMA, __builtin_bswap64(VIRT_TO_PHYS((uint64_t)&access))); - __asm__("ISB"); + __asm__("isb"); - while (__builtin_bswap32(access.control) & ~0x1) {} + if (!wait(&access.control, __builtin_bswap32(~0x1), false, 2000)){ + kprintf("[FW_CFG error] failed to communicate with fw_cfg"); + } } @@ -67,7 +70,7 @@ bool fw_find_file(const char* search, struct fw_cfg_file *file) { return false; uint32_t count; - fw_cfg_dma_read(&count, sizeof(count), FW_LIST_DIRECTORY); + fw_cfg_dma_read(VIRT_TO_PHYS_P(&count), sizeof(count), FW_LIST_DIRECTORY); count = __builtin_bswap32(count); diff --git a/kernel/graph/drivers/framebuffer_gpus/ramfb_driver/ramfb.cpp b/kernel/graph/drivers/framebuffer_gpus/ramfb_driver/ramfb.cpp index c2e93df3..c59bb86e 100644 --- a/kernel/graph/drivers/framebuffer_gpus/ramfb_driver/ramfb.cpp +++ b/kernel/graph/drivers/framebuffer_gpus/ramfb_driver/ramfb.cpp @@ -6,6 +6,7 @@ #include "std/memory.h" #include "theme/theme.h" #include "memory/page_allocator.h" +#include "sysregs.h" typedef struct { uint64_t addr; @@ -71,7 +72,7 @@ bool RamFBGPUDriver::init(gpu_size preferred_screen_size){ void RamFBGPUDriver::update_gpu_fb(){ ramfb_structure fb = { - .addr = __builtin_bswap64((uintptr_t)framebuffer), + .addr = __builtin_bswap64(VIRT_TO_PHYS((uintptr_t)framebuffer)), .fourcc = __builtin_bswap32(RGB_FORMAT_ARGB8888), .flags = __builtin_bswap32(0), .width = __builtin_bswap32(screen_size.width), diff --git a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp index 7c3ce2b3..efefafc6 100644 --- a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp +++ b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp @@ -5,6 +5,7 @@ #include "std/std.h" #include "theme/theme.h" #include "memory/page_allocator.h" +#include "sysregs.h" #define VIRTIO_GPU_CMD_GET_DISPLAY_INFO 0x0100 #define VIRTIO_GPU_CMD_RESOURCE_CREATE_2D 0x0101 @@ -72,7 +73,7 @@ bool VirtioGPUDriver::init(gpu_size preferred_screen_size){ resource_id_counter = 0; framebuffer_size = screen_size.width * screen_size.height * BPP; - framebuffer = (uintptr_t)kalloc(gpu_dev.memory_page, framebuffer_size, ALIGN_4KB, MEM_PRIV_KERNEL); + framebuffer = VIRT_TO_PHYS((uintptr_t)kalloc(gpu_dev.memory_page, framebuffer_size, ALIGN_4KB, MEM_PRIV_KERNEL)); ctx = { .dirty_rects = {}, @@ -454,7 +455,7 @@ uint32_t VirtioGPUDriver::new_cursor(uint32_t color){ uint32_t *cursor = (uint32_t*)kalloc(gpu_dev.memory_page, cursor_size, ALIGN_4KB, MEM_PRIV_KERNEL); draw_ctx ctx = {{},cursor, 64 * BPP, 64, 64, 0,0}; fb_draw_cursor(&ctx, color); - attach_backing(id, (sizedptr){(uintptr_t)cursor, cursor_size}); + attach_backing(id, (sizedptr){VIRT_TO_PHYS((uintptr_t)cursor), cursor_size}); transfer_to_host(id, {{0,0},{64,64}}); return id; } diff --git a/kernel/graph/tres.cpp b/kernel/graph/tres.cpp index a88f22c0..7aed5c89 100644 --- a/kernel/graph/tres.cpp +++ b/kernel/graph/tres.cpp @@ -6,6 +6,7 @@ #include "syscalls/syscalls.h" #include "kernel_processes/windows/launcher.h" #include "console/kio.h" +#include "sysregs.h" clinkedlist_t *window_list; window_frame *focused_window; @@ -36,7 +37,7 @@ extern "C" void create_window(uint32_t x, uint32_t y, uint32_t width, uint32_t h frame->height = height; frame->x = x; frame->y = y; - clinkedlist_push_front(window_list, frame); + clinkedlist_push_front(window_list, PHYS_TO_VIRT_P(frame)); main_gpu_driver->create_window(x,y, width, height, &frame->win_ctx); process_t *p = launch_launcher(); p->win_id = frame->win_id; @@ -45,6 +46,7 @@ extern "C" void create_window(uint32_t x, uint32_t y, uint32_t width, uint32_t h } int find_window(void *node, void *key){ + if (!node || !key) return -1; window_frame* frame = (window_frame*)node; uint16_t wid = *(uint16_t*)key; if (frame->win_id == wid) return 0; @@ -53,7 +55,7 @@ int find_window(void *node, void *key){ void resize_window(uint32_t width, uint32_t height){ process_t *p = get_current_proc(); - clinkedlist_node_t *node = clinkedlist_find(window_list, &p->win_id, find_window); + clinkedlist_node_t *node = clinkedlist_find(window_list, PHYS_TO_VIRT_P(&p->win_id), (typeof(find_window)*)PHYS_TO_VIRT_P(find_window)); if (node && node->data){ window_frame* frame = (window_frame*)node->data; main_gpu_driver->resize_window(width, height, &frame->win_ctx); @@ -65,7 +67,7 @@ void resize_window(uint32_t width, uint32_t height){ void get_window_ctx(draw_ctx* out_ctx){ process_t *p = get_current_proc(); - clinkedlist_node_t *node = clinkedlist_find(window_list, &p->win_id, find_window); + clinkedlist_node_t *node = clinkedlist_find(window_list, PHYS_TO_VIRT_P(&p->win_id), (typeof(find_window)*)PHYS_TO_VIRT_P(find_window)); if (node && node->data){ window_frame* frame = (window_frame*)node->data; *out_ctx = frame->win_ctx; @@ -76,7 +78,7 @@ void get_window_ctx(draw_ctx* out_ctx){ void commit_frame(draw_ctx* frame_ctx, window_frame* frame){ if (!frame){ process_t *p = get_current_proc(); - clinkedlist_node_t *node = clinkedlist_find(window_list, &p->win_id, find_window); + clinkedlist_node_t *node = clinkedlist_find(window_list, PHYS_TO_VIRT_P(&p->win_id), (typeof(find_window)*)PHYS_TO_VIRT_P(find_window)); if (!node || !node->data) return; frame = (window_frame*)node->data; } @@ -120,7 +122,7 @@ void commit_frame(draw_ctx* frame_ctx, window_frame* frame){ } void set_window_focus(uint16_t win_id){ - clinkedlist_node_t *node = clinkedlist_find(window_list, &win_id, find_window); + clinkedlist_node_t *node = clinkedlist_find(window_list, PHYS_TO_VIRT_P(&win_id), (typeof(find_window)*)PHYS_TO_VIRT_P(find_window)); if (!node || !node->data) return; focused_window = (window_frame*)node->data; dirty_windows = true; diff --git a/kernel/hw/hw.c b/kernel/hw/hw.c index 234ba645..e48c8d6b 100644 --- a/kernel/hw/hw.c +++ b/kernel/hw/hw.c @@ -1,6 +1,7 @@ #include "hw.h" #include "console/kio.h" #include "gpio.h" +#include "sysregs.h" uint8_t BOARD_TYPE; uint8_t RPI_BOARD; @@ -88,6 +89,18 @@ void detect_hardware(){ } } +void hw_high_va(){ + if (UART0_BASE) UART0_BASE |= HIGH_VA; + if (MMIO_BASE) MMIO_BASE |= HIGH_VA; + if (BOARD_TYPE != 1 && PCI_BASE)//virt is probably doing some weird PCI address stuff already + PCI_BASE |= HIGH_VA; + if (GICD_BASE) GICD_BASE |= HIGH_VA; + if (GICC_BASE) GICC_BASE |= HIGH_VA; + if (MAILBOX_BASE) MAILBOX_BASE |= HIGH_VA; + if (SDHCI_BASE) SDHCI_BASE |= HIGH_VA; + if (XHCI_BASE) XHCI_BASE |= HIGH_VA; +} + void print_hardware(){ kprintf("Board type %i",BOARD_TYPE); } \ No newline at end of file diff --git a/kernel/hw/hw.h b/kernel/hw/hw.h index 33249462..3b03557a 100644 --- a/kernel/hw/hw.h +++ b/kernel/hw/hw.h @@ -38,4 +38,5 @@ extern uint32_t MSI_OFFSET; extern uintptr_t LOWEST_ADDR; void detect_hardware(); -void print_hardware(); \ No newline at end of file +void print_hardware(); +void hw_high_va(); \ No newline at end of file diff --git a/kernel/input/dwc2.cpp b/kernel/input/dwc2.cpp index 85881ad4..57af1d2f 100644 --- a/kernel/input/dwc2.cpp +++ b/kernel/input/dwc2.cpp @@ -36,6 +36,8 @@ bool DWC2Driver::init() { use_interrupts = false; + register_device_memory(DWC2_BASE, DWC2_BASE); + dwc2 = (dwc2_regs*)DWC2_BASE; host = (dwc2_host*)(DWC2_BASE + 0x400); diff --git a/kernel/input/usb.cpp b/kernel/input/usb.cpp index 3fa34b17..8562c6b5 100644 --- a/kernel/input/usb.cpp +++ b/kernel/input/usb.cpp @@ -4,6 +4,7 @@ #include "std/string.h" #include "memory/page_allocator.h" #include "usb_types.h" +#include "sysregs.h" uint16_t USBDriver::packet_size(uint16_t speed){ switch (speed) { @@ -25,7 +26,7 @@ bool USBDriver::setup_device(uint8_t address, uint16_t port){ } usb_device_descriptor* descriptor = (usb_device_descriptor*)kalloc(mem_page, sizeof(usb_device_descriptor), ALIGN_64B, MEM_PRIV_KERNEL); - if (!request_descriptor(address, 0, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, descriptor)){ + if (!request_descriptor(address, 0, 0x80, 6, USB_DEVICE_DESCRIPTOR, 0, 0, VIRT_TO_PHYS_P(descriptor))){ kprintf("[USB error] failed to get device descriptor"); return false; } @@ -34,7 +35,7 @@ bool USBDriver::setup_device(uint8_t address, uint16_t port){ bool use_lang_desc = true; - if (!request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, 0, 0, lang_desc)){ + if (!request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, 0, 0, VIRT_TO_PHYS_P(lang_desc))){ kprintf("[USB warning] failed to get language descriptor"); use_lang_desc = false; } @@ -48,21 +49,21 @@ bool USBDriver::setup_device(uint8_t address, uint16_t port){ //TODO: we want to maintain the strings so we can have USB device information uint16_t langid = lang_desc->lang_ids[0]; usb_string_descriptor* prod_name = (usb_string_descriptor*)kalloc(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, MEM_PRIV_KERNEL); - if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, prod_name)){ + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iProduct, langid, VIRT_TO_PHYS_P(prod_name))){ char name[128]; if (utf16tochar(prod_name->unicode_string, name, sizeof(name))) { kprintf("[USB device] Product name: %s", (uint64_t)name); } } usb_string_descriptor* man_name = (usb_string_descriptor*)kalloc(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, MEM_PRIV_KERNEL); - if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, man_name)){ + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iManufacturer, langid, VIRT_TO_PHYS_P(man_name))){ char name[128]; if (utf16tochar(man_name->unicode_string, name, sizeof(name))) { kprintf("[USB device] Manufacturer name: %s", (uint64_t)name); } } usb_string_descriptor* ser_name = (usb_string_descriptor*)kalloc(mem_page, sizeof(usb_string_descriptor), ALIGN_64B, MEM_PRIV_KERNEL); - if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, ser_name)){ + if (request_descriptor(address, 0, 0x80, 6, USB_STRING_DESCRIPTOR, descriptor->iSerialNumber, langid, VIRT_TO_PHYS_P(ser_name))){ char name[128]; if (utf16tochar(ser_name->unicode_string, name, sizeof(name))) { kprintf("[USB device] Serial: %s", (uint64_t)name); @@ -77,7 +78,7 @@ bool USBDriver::get_configuration(uint8_t address){ usb_manager->register_device(address); - usb_configuration_descriptor* config = (usb_configuration_descriptor*)kalloc(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, MEM_PRIV_KERNEL); + usb_configuration_descriptor* config = (usb_configuration_descriptor*)VIRT_TO_PHYS_P(kalloc(mem_page, sizeof(usb_configuration_descriptor), ALIGN_64B, MEM_PRIV_KERNEL)); if (!request_sized_descriptor(address, 0, 0x80, 6, USB_CONFIGURATION_DESCRIPTOR, 0, 0, 8, config)){ kprintf("[USB error] could not get config descriptor header"); return false; diff --git a/kernel/input/xhci.cpp b/kernel/input/xhci.cpp index 41085ee4..aee8fa53 100644 --- a/kernel/input/xhci.cpp +++ b/kernel/input/xhci.cpp @@ -9,6 +9,8 @@ #include "std/memory.h" #include "async.h" #include "memory/page_allocator.h" +#include "memory/mmu.h" +#include "sysregs.h" uint64_t awaited_addr; uint32_t awaited_type; @@ -33,13 +35,13 @@ uint32_t awaited_type; bool XHCIDriver::check_fatal_error() { uint32_t sts = op->usbsts; if (sts & (XHCI_USBSTS_HSE | XHCI_USBSTS_CE)) { - kprintf("[xHCI ERROR] Fatal condition: USBSTS = %x", sts); + kprintf("[xHCI ERROR] Fatal condition: USBSTS = %llx", sts); return true; } return false; } -#define CHECK_XHCI_FIELD(field) (op->field != 0 ? (kprintf("[xHCI Error] wrong " #field " %x", op->field), false) : (kprintfv("[xHCI] Correct " #field " value"), true)) +#define CHECK_XHCI_FIELD(field) (op->field != 0 ? (kprintf("[xHCI Error] wrong " #field " %llx", op->field), false) : (kprintfv("[xHCI] Correct " #field " value"), true)) #define XHCI_EP_TYPE_INT_IN 7 #define XHCI_EP_TYPE_INT_OUT 3 @@ -55,7 +57,8 @@ bool XHCIDriver::init(){ use_interrupts = true; if (XHCI_BASE){ addr = XHCI_BASE; - mmio = addr; + mmio = VIRT_TO_PHYS(addr); + register_device_memory(mmio, VIRT_TO_PHYS(mmio)); if (BOARD_TYPE == 2 && RPI_BOARD >= 5) quirk_simulate_interrupts = !pci_setup_msi_rp1(36, true); } else if (PCI_BASE) { @@ -67,7 +70,7 @@ bool XHCIDriver::init(){ return false; } - kprintfv("[xHCI] init %x",addr); + kprintfv("[xHCI] init %llx",addr); if (use_pci){ if (!(*(uint16_t*)(addr + 0x06) & (1 << 4))){ kprintf("[xHCI] Wrong capabilities list"); @@ -82,6 +85,8 @@ bool XHCIDriver::init(){ } pci_register(mmio, mmio_size); + + mmio = VIRT_TO_PHYS(mmio); uint8_t interrupts_ok = pci_setup_interrupts(addr, INPUT_IRQ, 1); switch(interrupts_ok){ @@ -97,18 +102,20 @@ bool XHCIDriver::init(){ break; } - kprintfv("[xHCI] BARs set up @ %x (%x)",mmio,mmio_size); + kprintfv("[xHCI] BARs set up @ %llx (%llx)",mmio,mmio_size); } + mmio = VIRT_TO_PHYS(mmio); + cap = (xhci_cap_regs*)mmio; - kprintfv("[xHCI] caplength %x",cap->caplength); + kprintfv("[xHCI] caplength %llx",cap->caplength); uintptr_t op_base = mmio + cap->caplength; op = (xhci_op_regs*)op_base; ports = (xhci_port_regs*)(op_base + 0x400); db_base = mmio + (cap->dboff & ~0x1F); rt_base = mmio + (cap->rtsoff & ~0x1F); - kprintfv("[xHCI] Resetting controller"); + kprintfv("[xHCI] Resetting controller %llx",&op->usbcmd); op->usbcmd &= ~1; wait(&op->usbcmd, 1, false, 16); kprintfv("[xHCI] Clear complete"); @@ -144,7 +151,7 @@ bool XHCIDriver::init(){ mem_page = palloc(0x1000, MEM_PRIV_KERNEL, MEM_RW | MEM_DEV, false); - uintptr_t dcbaap_addr = (uintptr_t)kalloc(mem_page, (max_device_slots + 1) * sizeof(uintptr_t), ALIGN_64B, MEM_PRIV_KERNEL); + uintptr_t dcbaap_addr = VIRT_TO_PHYS((uintptr_t)kalloc(mem_page, (max_device_slots + 1) * sizeof(uintptr_t), ALIGN_64B, MEM_PRIV_KERNEL)); op->dcbaap = dcbaap_addr; @@ -152,22 +159,22 @@ bool XHCIDriver::init(){ uint32_t scratchpad_count = ((cap->hcsparams2 >> 27) & 0x1F); - dcbaap = (uintptr_t*)dcbaap_addr; + dcbaap = (uintptr_t*)PHYS_TO_VIRT(dcbaap_addr); uint64_t* scratchpad_array = (uint64_t*)kalloc(mem_page, (scratchpad_count == 0 ? 1 : scratchpad_count) * sizeof(uintptr_t), ALIGN_64B, MEM_PRIV_KERNEL); for (uint32_t i = 0; i < scratchpad_count; i++) scratchpad_array[i] = (uint64_t)kalloc(mem_page, 0x1000, ALIGN_64B, MEM_PRIV_KERNEL); dcbaap[0] = (uint64_t)scratchpad_array; - kprintfv("[xHCI] dcbaap assigned at %x with %i scratchpads",dcbaap_addr,scratchpad_count); + kprintfv("[xHCI] dcbaap assigned at %llx with %i scratchpads",dcbaap_addr,scratchpad_count); - command_ring.ring = (trb*)kalloc(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, MEM_PRIV_KERNEL); + command_ring.ring = (trb*)VIRT_TO_PHYS_P(kalloc(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, MEM_PRIV_KERNEL)); op->crcr = (uintptr_t)command_ring.ring | command_ring.cycle_bit; make_ring_link(command_ring.ring, command_ring.cycle_bit); - kprintfv("[xHCI] command ring allocated at %x. crcr now %x",(uintptr_t)command_ring.ring, op->crcr); + kprintfv("[xHCI] command ring allocated at %llx. crcr now %llx",(uintptr_t)command_ring.ring, op->crcr); if (!enable_events()){ kprintf("[xHCI error] failed to enable events"); @@ -183,7 +190,7 @@ bool XHCIDriver::init(){ endpoint_map = IndexMap(255 * 5); context_map = IndexMap(255 * 5); - kprintfv("[xHCI] Init complete with usbcmd %x, usbsts %x",op->usbcmd, op->usbsts); + kprintfv("[xHCI] Init complete with usbcmd %llx, usbsts %llx",op->usbcmd, op->usbsts); if (check_fatal_error()) return false; @@ -205,7 +212,7 @@ bool XHCIDriver::port_reset(uint16_t port){ kprintf("[xHCI] port %i",port); - xhci_port_regs* port_info = &ports[port]; + xhci_port_regs* port_info = (xhci_port_regs*)VIRT_TO_PHYS_P(&ports[port]); if (port_info->portsc.pp == 0){ port_info->portsc.pp = 1; @@ -247,28 +254,28 @@ bool XHCIDriver::enable_events(){ kprintfv("[xHCI] Allocating ERST"); interrupter = (xhci_interrupter*)(rt_base + 0x20); - uint64_t ev_ring = (uintptr_t)kalloc(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, MEM_PRIV_KERNEL); - uint64_t erst_addr = (uintptr_t)kalloc(mem_page, MAX_ERST_AMOUNT * sizeof(erst_entry), ALIGN_64B, MEM_PRIV_KERNEL); + uint64_t ev_ring = VIRT_TO_PHYS((uintptr_t)kalloc(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, MEM_PRIV_KERNEL)); + uint64_t erst_addr = VIRT_TO_PHYS((uintptr_t)kalloc(mem_page, MAX_ERST_AMOUNT * sizeof(erst_entry), ALIGN_64B, MEM_PRIV_KERNEL)); erst_entry* erst = (erst_entry*)erst_addr; erst->ring_base = ev_ring; erst->ring_size = MAX_TRB_AMOUNT; - kprintfv("[xHCI] ERST ring_base: %x", ev_ring); - kprintfv("[xHCI] ERST ring_size: %x", erst[0].ring_size); + kprintfv("[xHCI] ERST ring_base: %llx", ev_ring); + kprintfv("[xHCI] ERST ring_size: %llx", erst[0].ring_size); event_ring.ring = (trb*)ev_ring; event_ring.cycle_bit = 1; - kprintfv("[xHCI] Interrupter register @ %x", rt_base + 0x20); + kprintfv("[xHCI] Interrupter register @ %llx", rt_base + 0x20); interrupter->erstsz = 1; - kprintfv("[xHCI] ERSTSZ set to: %x", interrupter->erstsz); + kprintfv("[xHCI] ERSTSZ set to: %llx", (uintptr_t)interrupter->erstsz); interrupter->erdp = ev_ring; interrupter->erstba = erst_addr; - kprintfv("[xHCI] ERSTBA set to: %x", interrupter->erstba); + kprintfv("[xHCI] ERSTBA set to: %llx", (uintptr_t)interrupter->erstba); - kprintfv("[xHCI] ERDP set to: %x", interrupter->erdp); + kprintfv("[xHCI] ERDP set to: %llx", (uintptr_t)interrupter->erdp); interrupter->iman |= 1 << 1;//Enable interrupt @@ -286,33 +293,34 @@ void XHCIDriver::make_ring_link_control(trb* ring, bool cycle){ } void XHCIDriver::make_ring_link(trb* ring, bool cycle){ - ring[MAX_TRB_AMOUNT-1].parameter = (uintptr_t)ring; + ring[MAX_TRB_AMOUNT-1].parameter = VIRT_TO_PHYS((uintptr_t)ring); ring[MAX_TRB_AMOUNT-1].status = 0; make_ring_link_control(ring, cycle); } void XHCIDriver::ring_doorbell(uint32_t slot, uint32_t endpoint) { volatile uint32_t* db = (uint32_t*)(uintptr_t)(db_base + (slot << 2)); - kprintfv("[xHCI] Ringing doorbell at %x with value %x", db_base + (slot << 2),endpoint); + kprintfv("[xHCI] Ringing doorbell at %llx with value %llx", db_base + (slot << 2),endpoint); *db = endpoint; } bool XHCIDriver::await_response(uint64_t command, uint32_t type){ while (1){ if (check_fatal_error()){ - kprintf("[xHCI error] USBSTS value %x",op->usbsts); + kprintf("[xHCI error] USBSTS value %llx",op->usbsts); awaited_type = 0; return false; } for (; event_ring.index < MAX_TRB_AMOUNT; event_ring.index++){ last_event = &event_ring.ring[event_ring.index]; + // kprintf("LAST EVENT %llx",last_event); if (!wait(&last_event->control, event_ring.cycle_bit, true, 2000)){ - kprintf("[xHCI error] Timeout awaiting response to %x command of type %x", command, type); + kprintf("[xHCI error] Timeout awaiting response to %llx command of type %llx", command, type); awaited_type = 0; return false; } - // kprintf("[xHCI] A response at %i of type %x as a response to %x",event_ring.index, (last_event->control & TRB_TYPE_MASK) >> 10, last_event->parameter); - // kprintf("[xHCI] %x vs %x = %i and %x vs %x = %i", (ev->control & TRB_TYPE_MASK) >> 10, type, (ev->control & TRB_TYPE_MASK) >> 10 == type, ev->parameter, command, command == 0 || ev->parameter == command); + // kprintf("[xHCI] A response at %i of type %llx as a response to %llx",event_ring.index, (last_event->control & TRB_TYPE_MASK) >> 10, last_event->parameter); + // kprintf("[xHCI] %llx vs %llx = %i and %llx vs %llx = %i", (ev->control & TRB_TYPE_MASK) >> 10, type, (ev->control & TRB_TYPE_MASK) >> 10 == type, ev->parameter, command, command == 0 || ev->parameter == command); if (event_ring.index == MAX_TRB_AMOUNT - 1){ event_ring.index = 0; event_ring.cycle_bit = !event_ring.cycle_bit; @@ -320,7 +328,7 @@ bool XHCIDriver::await_response(uint64_t command, uint32_t type){ if ((((last_event->control & TRB_TYPE_MASK) >> 10) == type) && (command == 0 || last_event->parameter == command)){ uint8_t completion_code = (last_event->status >> 24) & 0xFF; if (completion_code != 1) - kprintf("[xHCI error] wrong status %i on command type %x", completion_code, ((last_event->control & TRB_TYPE_MASK) >> 10) ); + kprintf("[xHCI error] wrong status %i on command type %llx", completion_code, ((last_event->control & TRB_TYPE_MASK) >> 10) ); interrupter->erdp = (uintptr_t)&event_ring.ring[event_ring.index+1] | (1 << 3);//Inform of latest processed event interrupter->iman |= 1;//Clear interrupts op->usbsts |= 1 << 3;//Clear interrupts @@ -341,7 +349,7 @@ bool XHCIDriver::issue_command(uint64_t param, uint32_t status, uint32_t control cmd->control = control | command_ring.cycle_bit; uint64_t cmd_addr = (uintptr_t)cmd; - kprintfv("[xHCI] issuing command with control: %x from %x", cmd->control, cmd_addr); + kprintfv("[xHCI] issuing command with control: %llx from %llx", cmd->control, cmd_addr); if (command_ring.index == MAX_TRB_AMOUNT - 1){ make_ring_link_control(command_ring.ring, command_ring.cycle_bit); command_ring.cycle_bit = !command_ring.cycle_bit; @@ -358,7 +366,7 @@ bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ } address = (last_event->control >> 24) & 0xFF; - kprintfv("[xHCI] Slot id %x", address); + kprintfv("[xHCI] Slot id %llx", address); if (address == 0){ kprintf("[xHCI error]: Wrong slot id 0"); @@ -369,11 +377,11 @@ bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ transfer_ring->cycle_bit = 1; - xhci_input_context *ctx = (xhci_input_context*)kalloc(mem_page, sizeof(xhci_input_context), ALIGN_64B, MEM_PRIV_KERNEL); - kprintfv("[xHCI] Allocating input context at %x", (uintptr_t)ctx); - context_map[address << 8] = ctx; - void* output_ctx = (void*)kalloc(mem_page, 0x1000, ALIGN_64B, MEM_PRIV_KERNEL); - kprintfv("[xHCI] Allocating output for context at %x", (uintptr_t)output_ctx); + xhci_input_context *ctx = (xhci_input_context*)VIRT_TO_PHYS_P(kalloc(mem_page, sizeof(xhci_input_context), ALIGN_64B, MEM_PRIV_KERNEL)); + kprintfv("[xHCI] Allocating input context at %llx", (uintptr_t)ctx); + context_map[address << 8] = (xhci_input_context *)ctx; + void* output_ctx = VIRT_TO_PHYS_P((void*)kalloc(mem_page, 0x1000, ALIGN_64B, MEM_PRIV_KERNEL)); + kprintfv("[xHCI] Allocating output for context at %llx", (uintptr_t)output_ctx); ctx->control_context.add_flags = 0b11; @@ -388,14 +396,14 @@ bool XHCIDriver::setup_device(uint8_t address, uint16_t port){ ctx->device_context.endpoints[0].endpoint_f1.max_packet_size = packet_size(ctx->device_context.slot_f0.speed); transfer_ring->ring = (trb*)kalloc(mem_page, MAX_TRB_AMOUNT * sizeof(trb), ALIGN_64B, MEM_PRIV_KERNEL); - kprintfv("Transfer ring at %x %i",(uintptr_t)transfer_ring->ring, address << 8); + kprintfv("Transfer ring at %llx %i",(uintptr_t)transfer_ring->ring, address << 8); make_ring_link(transfer_ring->ring, transfer_ring->cycle_bit); ctx->device_context.endpoints[0].endpoint_f23.dcs = transfer_ring->cycle_bit; - ctx->device_context.endpoints[0].endpoint_f23.ring_ptr = ((uintptr_t)transfer_ring->ring) >> 4; + ctx->device_context.endpoints[0].endpoint_f23.ring_ptr = VIRT_TO_PHYS((uintptr_t)transfer_ring->ring) >> 4; ctx->device_context.endpoints[0].endpoint_f4.average_trb_length = sizeof(trb); - dcbaap[address] = (uintptr_t)output_ctx; + dcbaap[address] = VIRT_TO_PHYS((uintptr_t)output_ctx); return USBDriver::setup_device(address, port); } @@ -409,7 +417,7 @@ bool XHCIDriver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uin .wLength = descriptor_size }; - // kprintf("RT: %x R: %x V: %x I: %x L: %x",packet.bmRequestType,packet.bRequest,packet.wValue,packet.wIndex,packet.wLength); + // kprintf("RT: %llx R: %llx V: %llx I: %llx L: %llx",packet.bmRequestType,packet.bRequest,packet.wValue,packet.wIndex,packet.wLength); xhci_ring *transfer_ring = &endpoint_map[address << 8 | endpoint]; @@ -444,14 +452,14 @@ bool XHCIDriver::request_sized_descriptor(uint8_t address, uint8_t endpoint, uin uint8_t XHCIDriver::address_device(uint8_t address){ xhci_input_context* ctx = context_map[address << 8]; - kprintfv("Addressing device %i with context %x", address, (uintptr_t)ctx); + kprintfv("Addressing device %i with context %llx", address, (uintptr_t)ctx); if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_ADDRESS_DEV << 10))){ - kprintf("[xHCI error] failed addressing device at slot %x",address); + kprintf("[xHCI error] failed addressing device at slot %llx",address); return 0; } xhci_device_context* context = (xhci_device_context*)dcbaap[address]; - kprintfv("[xHCI] ADDRESS_DEVICE %i command issued. dcbaap %x Received packet size %i",address, (uintptr_t)dcbaap, context->endpoints[0].endpoint_f1.max_packet_size); + kprintfv("[xHCI] ADDRESS_DEVICE %i command issued. dcbaap %llx Received packet size %i",address, (uintptr_t)dcbaap, context->endpoints[0].endpoint_f1.max_packet_size); return address; } @@ -460,7 +468,7 @@ uint8_t XHCIDriver::get_ep_type(usb_endpoint_descriptor* descriptor) { } bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *endpoint, uint8_t configuration_value, usb_device_types type){ - kprintfv("[xHCI] endpoint address %x",endpoint->bEndpointAddress); + kprintfv("[xHCI] endpoint address %llx",endpoint->bEndpointAddress); uint8_t ep_address = endpoint->bEndpointAddress; uint8_t ep_dir = (ep_address & 0x80) ? 1 : 0; // 1 IN, 0 OUT uint8_t ep_num = ((ep_address & 0x0F) * 2) + ep_dir; @@ -493,7 +501,7 @@ bool XHCIDriver::configure_endpoint(uint8_t address, usb_endpoint_descriptor *en ep_ring->cycle_bit = 1; make_ring_link(ep_ring->ring, ep_ring->cycle_bit); ctx->device_context.endpoints[ep_num-1].endpoint_f23.dcs = ep_ring->cycle_bit; - ctx->device_context.endpoints[ep_num-1].endpoint_f23.ring_ptr = ((uintptr_t)ep_ring->ring) >> 4; + ctx->device_context.endpoints[ep_num-1].endpoint_f23.ring_ptr = VIRT_TO_PHYS((uintptr_t)ep_ring->ring) >> 4; ctx->device_context.endpoints[ep_num-1].endpoint_f4.average_trb_length = sizeof(trb); if (!issue_command((uintptr_t)ctx, 0, (address << 24) | (TRB_TYPE_CONFIG_EP << 10))){ @@ -537,7 +545,7 @@ void XHCIDriver::handle_interrupt(){ uint64_t addr = ev->parameter; if (type == awaited_type && (awaited_addr == 0 || (awaited_addr & 0xFFFFFFFFFFFFFFFF) == addr)) return; - kprintfv("[xHCI] >>> Unhandled interrupt %i %x",event_ring.index,type); + kprintfv("[xHCI] >>> Unhandled interrupt %i %llx",event_ring.index,type); uint8_t completion_code = (ev->status >> 24) & 0xFF; if (completion_code == 1 || completion_code == 4){ switch (type){ @@ -558,14 +566,14 @@ void XHCIDriver::handle_interrupt(){ } } } else { - kprintf("[xHCI error] wrong status %i on command type %x", completion_code, ((ev->control & TRB_TYPE_MASK) >> 10)); + kprintf("[xHCI error] wrong status %i on command type %llx", completion_code, ((ev->control & TRB_TYPE_MASK) >> 10)); } if (event_ring.index == MAX_TRB_AMOUNT - 1){ event_ring.index = 0; event_ring.cycle_bit = !event_ring.cycle_bit; } else event_ring.index++; - interrupter->erdp = (uintptr_t)&event_ring.ring[event_ring.index] | (1 << 3);//Inform of latest processed event + interrupter->erdp = VIRT_TO_PHYS((uintptr_t)&event_ring.ring[event_ring.index]) | (1 << 3);//Inform of latest processed event interrupter->iman |= 1;//Clear interrupts op->usbsts |= 1 << 3;//Clear interrupts } diff --git a/kernel/kernel.c b/kernel/kernel.c index bff53a95..f39959cb 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -27,7 +27,7 @@ void kernel_main() { detect_hardware(); - mmu_alloc(); + mmu_init_kernel(); if (BOARD_TYPE == 2) mailbox_init(); @@ -40,6 +40,7 @@ void kernel_main() { // if (BOARD_TYPE == 1) disable_visual(); load_module(&console_module); + mmu_init(); print_hardware(); @@ -52,8 +53,8 @@ void kernel_main() { load_module(&graphics_module); - // if (BOARD_TYPE == 2 && RPI_BOARD >= 5) - // pci_setup_rp1(); + if (BOARD_TYPE == 2 && RPI_BOARD >= 5) + pci_setup_rp1(); load_module(&disk_module); @@ -64,15 +65,13 @@ void kernel_main() { network_available = load_module(&net_module); load_module(&audio_module); - - init_audio_mixer(); } - - mmu_init(); kprint("Kernel initialization finished"); kprint("Starting processes"); + + if (BOARD_TYPE == 1) init_audio_mixer(); init_filesystem(); diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index 6fca8e7c..74268b56 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -3,6 +3,7 @@ #include "process/scheduler.h" #include "memory/page_allocator.h" #include "exceptions/irq.h" +#include "sysregs.h" process_t *create_kernel_process(const char *name, int (*func)(int argc, char* argv[]), int argc, const char* argv[]){ @@ -15,11 +16,11 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a uint64_t stack_size = 0x1000; uintptr_t stack = (uintptr_t)palloc(stack_size, MEM_PRIV_KERNEL, MEM_RW, false); - kprintf("Stack size %x. Start %x", stack_size,stack); + kprintf("Stack size %llx. Start %llx", stack_size,stack); if (!stack) return 0; uintptr_t heap = (uintptr_t)palloc(stack_size, MEM_PRIV_KERNEL, MEM_RW, false); - kprintf("Heap %x", heap); + kprintf("Heap %llx", heap); if (!heap) return 0; proc->stack = (stack + stack_size); @@ -29,14 +30,14 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a proc->sp = proc->stack; - proc->pc = (uintptr_t)func; - kprintf("Kernel process %s (%i) allocated with address at %x, stack at %x, heap at %x. %i argument(s)", (uintptr_t)name, proc->id, proc->pc, proc->sp, proc->heap, argc); + proc->pc = PHYS_TO_VIRT(((uintptr_t)func)); + kprintf("Kernel process %s (%i) allocated with address at %llx, stack at %llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->pc, proc->sp, proc->heap, argc); proc->spsr = 0x205; proc->state = READY; proc->PROC_X0 = argc; proc->PROC_X1 = (uintptr_t)argv; - proc->output = (uintptr_t)palloc(0x1000, MEM_PRIV_KERNEL, MEM_RW, true); + proc->output = PHYS_TO_VIRT((uintptr_t)palloc(0x1000, MEM_PRIV_KERNEL, MEM_RW, true)); enable_interrupt(); diff --git a/kernel/kernel_processes/windows/launcher.cpp b/kernel/kernel_processes/windows/launcher.cpp index 8d4861ae..20fd6802 100644 --- a/kernel/kernel_processes/windows/launcher.cpp +++ b/kernel/kernel_processes/windows/launcher.cpp @@ -57,7 +57,7 @@ void Launcher::load_entries(){ entries.empty(); size_t listsize = 0x1000; void *listptr = malloc(listsize); - if (!list_directory_contents("/boot/redos/user/", listptr, listsize, 0)){ + if (!list_directory_contents("/shared/redos/user/", listptr, listsize, 0)){ kprintf("Failed to read contents of directory"); return; } @@ -67,7 +67,7 @@ void Launcher::load_entries(){ for (uint32_t i = 0; i < list->count; i++){ char *file = reader; if (*file){ - string fullpath = string_format("/boot/redos/user/%s",(uintptr_t)file); + string fullpath = string_format("/shared/redos/user/%s",(uintptr_t)file); string name = string_from_literal_length(file,find_extension(file)); string ext = string_from_literal(file + find_extension(file)); if (strcmp(ext.data,".red", true) == 0){ @@ -188,11 +188,11 @@ void Launcher::activate_current(){ } active_proc->win_id = get_current_proc()->win_id; active_proc->priority = PROC_PRIORITY_FULL; - kprintf("[LAUNCHER] process launched"); - enable_interrupt(); process_active = true; sys_set_focus(active_proc->id); active_proc->state = process_t::process_state::READY; + kprintf("[LAUNCHER] process launched"); + enable_interrupt(); } } diff --git a/kernel/linker.ld b/kernel/linker.ld index 27bfb552..8242c8c9 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -32,9 +32,6 @@ SECTIONS { .heap_fill : { FILL(0); . = . + 0xFF000; } heap_limit = .; - . = ALIGN(0x200000); - kcode_end = .; - .shared : ALIGN(0x1000) { shared_start = .; *libshared.a:*(.text*) @@ -51,5 +48,5 @@ SECTIONS { } . = ALIGN(0x200000); - kfull_end = .; + kcode_end = .; } \ No newline at end of file diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index 0d411acd..dcf1a238 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -8,11 +8,8 @@ #include "pci.h" #include "filesystem/disk.h" #include "memory/page_allocator.h" - -#define MAIR_DEVICE_nGnRnE 0b00000000 -#define MAIR_NORMAL_NOCACHE 0b01000100 -#define MAIR_IDX_DEVICE 0 -#define MAIR_IDX_NORMAL 1 +#include "sysregs.h" +#include "std/memory.h" #define PD_TABLE 0b11 #define PD_BLOCK 0b01 @@ -26,7 +23,7 @@ #define PAGE_TABLE_ENTRIES 512 -uint64_t *page_table_l0; +uint64_t *kernel_mmu_page; static bool mmu_verbose; @@ -41,19 +38,19 @@ void mmu_enable_verbose(){ }\ }) -void mmu_map_2mb(uint64_t va, uint64_t pa, uint64_t attr_index) { +void mmu_map_2mb(uint64_t *table, uint64_t va, uint64_t pa, uint64_t attr_index) { uint64_t l0_index = (va >> 39) & 0x1FF; uint64_t l1_index = (va >> 30) & 0x1FF; uint64_t l2_index = (va >> 21) & 0x1FF; kprintfv("[MMU] Mapping 2mb memory %x at [%i][%i][%i] for EL1", va, l0_index,l1_index,l2_index); - if (!(page_table_l0[l0_index] & 1)) { + if (!(table[l0_index] & 1)) { uint64_t* l1 = (uint64_t*)talloc(PAGE_SIZE); - page_table_l0[l0_index] = ((uint64_t)l1 & 0xFFFFFFFFF000ULL) | PD_TABLE; + table[l0_index] = ((uint64_t)l1 & 0xFFFFFFFFF000ULL) | PD_TABLE; } - uint64_t* l1 = (uint64_t*)(page_table_l0[l0_index] & 0xFFFFFFFFF000ULL); + uint64_t* l1 = (uint64_t*)(table[l0_index] & 0xFFFFFFFFF000ULL); if (!(l1[l1_index] & 1)) { uint64_t* l2 = (uint64_t*)talloc(PAGE_SIZE); @@ -68,18 +65,18 @@ void mmu_map_2mb(uint64_t va, uint64_t pa, uint64_t attr_index) { } //Level 0 = EL0, Level 1 = EL1, Level 2 = Shared -void mmu_map_4kb(uint64_t va, uint64_t pa, uint64_t attr_index, uint8_t mem_attributes, uint8_t level) { +void mmu_map_4kb(uint64_t *table, uint64_t va, uint64_t pa, uint64_t attr_index, uint8_t mem_attributes, uint8_t level) { uint64_t l0_index = (va >> 39) & 0x1FF; uint64_t l1_index = (va >> 30) & 0x1FF; uint64_t l2_index = (va >> 21) & 0x1FF; uint64_t l3_index = (va >> 12) & 0x1FF; - if (!(page_table_l0[l0_index] & 1)) { + if (!(table[l0_index] & 1)) { uint64_t* l1 = (uint64_t*)talloc(PAGE_SIZE); - page_table_l0[l0_index] = ((uint64_t)l1 & 0xFFFFFFFFF000ULL) | PD_TABLE; + table[l0_index] = ((uint64_t)l1 & 0xFFFFFFFFF000ULL) | PD_TABLE; } - uint64_t* l1 = (uint64_t*)(page_table_l0[l0_index] & 0xFFFFFFFFF000ULL); + uint64_t* l1 = (uint64_t*)(table[l0_index] & 0xFFFFFFFFF000ULL); if (!(l1[l1_index] & 1)) { uint64_t* l2 = (uint64_t*)talloc(PAGE_SIZE); l1[l1_index] = ((uint64_t)l2 & 0xFFFFFFFFF000ULL) | PD_TABLE; @@ -142,6 +139,8 @@ static inline void mmu_flush_icache() { } void mmu_unmap(uint64_t va, uint64_t pa){ + + uint64_t *table = kernel_mmu_page; uint64_t l0_index = (va >> 39) & 0x1FF; uint64_t l1_index = (va >> 30) & 0x1FF; @@ -149,9 +148,9 @@ void mmu_unmap(uint64_t va, uint64_t pa){ uint64_t l3_index = (va >> 12) & 0x1FF; kprintfv("[MMU] Unmapping 4kb memory %x at [%i][%i][%i][%i] for EL1", va, l0_index,l1_index,l2_index, l3_index); - if (!(page_table_l0[l0_index] & 1)) return; + if (!(table[l0_index] & 1)) return; - uint64_t* l1 = (uint64_t*)(page_table_l0[l0_index] & 0xFFFFFFFFF000ULL); + uint64_t* l1 = (uint64_t*)(table[l0_index] & 0xFFFFFFFFF000ULL); if (!(l1[l1_index] & 1)) return; uint64_t* l2 = (uint64_t*)(l1[l1_index] & 0xFFFFFFFFF000ULL); @@ -170,8 +169,12 @@ void mmu_unmap(uint64_t va, uint64_t pa){ mmu_flush_icache(); } -void mmu_alloc(){ - page_table_l0 = (uint64_t*)talloc(PAGE_SIZE); +void mmu_init_kernel(){ + kernel_mmu_page = mmu_alloc(); +} + +uint64_t *mmu_alloc(){ + return (uint64_t*)talloc(PAGE_SIZE); } extern uint64_t shared_start; @@ -179,95 +182,133 @@ extern uint64_t shared_code_end; extern uint64_t shared_ro_end; extern uint64_t shared_end; +extern uintptr_t cpec; +extern uintptr_t ksp; + +extern void mmu_start(uint64_t *mmu); + void mmu_init() { - //TODO: Move these hardcoded mappings to their own file uint64_t kstart = mem_get_kmem_start(); uint64_t kend = mem_get_kmem_end(); for (uint64_t addr = kstart; addr < kend; addr += GRANULE_2MB) - mmu_map_2mb(addr, addr, MAIR_IDX_NORMAL); - - for (uint64_t addr = get_uart_base(); addr <= get_uart_base(); addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_DEVICE, MEM_RW, MEM_PRIV_KERNEL); - - for (uint64_t addr = GICD_BASE; addr <= GICC_BASE + 0x1000; addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_DEVICE, MEM_RW, MEM_PRIV_KERNEL); - - for (uint64_t addr = (uintptr_t)&shared_start; addr < (uintptr_t)&shared_code_end; addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, MEM_EXEC | MEM_RO, MEM_PRIV_SHARED); - - for (uint64_t addr = (uintptr_t)&shared_code_end; addr < (uintptr_t)&shared_ro_end; addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, MEM_RO, MEM_PRIV_SHARED); - - for (uint64_t addr = (uintptr_t)&shared_ro_end; addr < (uintptr_t)&shared_end; addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, MEM_RW, MEM_PRIV_SHARED); - - if (XHCI_BASE) - for (uint64_t addr = XHCI_BASE; addr <= XHCI_BASE + 0x1000; addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_DEVICE, MEM_RW, MEM_PRIV_KERNEL); + mmu_map_2mb(kernel_mmu_page, addr, addr, MAIR_IDX_NORMAL); uint64_t dstart; uint64_t dsize; - if (dtb_addresses(&dstart,&dsize)){ + if (dtb_addresses(&dstart,&dsize)) for (uint64_t addr = dstart; addr <= dstart + dsize; addr += GRANULE_4KB) - mmu_map_4kb(addr, addr, MAIR_IDX_NORMAL, MEM_RO, MEM_PRIV_KERNEL); - } + mmu_map_4kb(kernel_mmu_page, addr, addr, MAIR_IDX_NORMAL, MEM_RO, MEM_PRIV_KERNEL); - uint64_t mair = (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL * 8)); - asm volatile ("msr mair_el1, %0" :: "r"(mair)); + hw_high_va(); - //30 = Translation granule EL1. 10 = 4kb | 14 = TG EL0 00 = 4kb - uint64_t tcr = ((64 - 48) << 0) | ((64 - 48) << 16) | (0b00 << 14) | (0b10 << 30); - asm volatile ("msr tcr_el1, %0" :: "r"(tcr)); + mmu_start(kernel_mmu_page); - asm volatile ("dsb ish"); - asm volatile ("isb"); + kprintf("Finished MMU init"); +} - asm volatile ("msr ttbr0_el1, %0" :: "r"(page_table_l0)); - - asm volatile ( - "mrs x0, sctlr_el1\n" - "orr x0, x0, #0x1\n" - "bic x0, x0, #(1 << 19)\n" - "msr sctlr_el1, x0\n" - "isb\n" - ::: "x0", "memory" - ); +void mmu_copy(uintptr_t *new_ttrb, uintptr_t *old_ttrb, int level){ + for (int i = 0; i < PAGE_TABLE_ENTRIES; i++){ + if (old_ttrb[i] & 1){ + if (level == 3 || (old_ttrb[i] & 0b11) == PD_BLOCK){ + new_ttrb[i] = old_ttrb[i]; + } else { + uintptr_t *old_entry = (uintptr_t*)(old_ttrb[i] & 0xFFFFFFFFF000ULL); + uintptr_t *new_entry = mmu_alloc(); + if (!old_entry || !new_entry) continue; + uint64_t entry = old_ttrb[i] & ~(0xFFFFFFFFF000ULL); + new_ttrb[i] = entry | ((uintptr_t)new_entry & 0xFFFFFFFFF000ULL); + if (level < 3) mmu_copy(new_entry, old_entry, level+1); + } + } + } +} - kprintf("Finished MMU init"); +uintptr_t* mmu_new_ttrb(){ + uintptr_t *ttrb = mmu_alloc(); + mmu_copy(ttrb, kernel_mmu_page,0); + return ttrb; } void register_device_memory(uint64_t va, uint64_t pa){ - mmu_map_4kb(va, pa, MAIR_IDX_DEVICE, MEM_RW, 1); + if (pttrb && pttrb != kernel_mmu_page)//TODO: This won't be necessary once kernel is exclusively in ttbr1 + mmu_map_4kb(pttrb, va, pa, MAIR_IDX_DEVICE, MEM_RW, MEM_PRIV_KERNEL); + mmu_map_4kb(kernel_mmu_page, va, pa, MAIR_IDX_DEVICE, MEM_RW, MEM_PRIV_KERNEL); mmu_flush_all(); mmu_flush_icache(); } void register_device_memory_2mb(uint64_t va, uint64_t pa){ - mmu_map_2mb(va, pa, MAIR_IDX_DEVICE); + if (pttrb && pttrb != kernel_mmu_page)//TODO: This won't be necessary once kernel is exclusively in ttbr1 + mmu_map_2mb(pttrb, va, pa, MAIR_IDX_DEVICE); + mmu_map_2mb(kernel_mmu_page, va, pa, MAIR_IDX_DEVICE); mmu_flush_all(); mmu_flush_icache(); } void register_proc_memory(uint64_t va, uint64_t pa, uint8_t attributes, uint8_t level){ - mmu_map_4kb(va, pa, MAIR_IDX_NORMAL, attributes, level); + if (pttrb && pttrb != kernel_mmu_page) + mmu_map_4kb(pttrb, va, pa, MAIR_IDX_NORMAL, attributes, level); + mmu_map_4kb(kernel_mmu_page, va, pa, MAIR_IDX_NORMAL, attributes, level); mmu_flush_all(); mmu_flush_icache(); } +uintptr_t mmu_translate(uintptr_t va){ + uint64_t *table = pttrb && (va >> 48) == 0 ? pttrb : kernel_mmu_page; + + uint64_t l0_index = (va >> 39) & 0x1FF; + uint64_t l1_index = (va >> 30) & 0x1FF; + uint64_t l2_index = (va >> 21) & 0x1FF; + uint64_t l3_index = (va >> 12) & 0x1FF; + + if (!(table[l0_index] & 1)) { + kprintf("L1 Table missing"); + return 0; + } + uint64_t* l1 = (uint64_t*)(table[l0_index] & 0xFFFFFFFFF000ULL); + if (!(l1[l1_index] & 1)) { + kprintf("L2 Table missing"); + return 0; + } + uint64_t* l2 = (uint64_t*)(l1[l1_index] & 0xFFFFFFFFF000ULL); + uint64_t l3_val = l2[l2_index]; + if (!(l3_val & 1)) { + kprintf("L3 Table missing"); + return 0; + } + + if (!((l3_val >> 1) & 1)){ + kprintf("Mapped as 2MB memory in L3"); + kprintf("Entry: %b", l3_val); + return 0; + } + + uint64_t* l3 = (uint64_t*)(l2[l2_index] & 0xFFFFFFFFF000ULL); + uint64_t l4_val = l3[l3_index]; + if (!(l4_val & 1)){ + kprintf("L4 Table entry missing"); + return 0; + } + return l4_val & 0xFFFFFFFFF000ULL; +} + void debug_mmu_address(uint64_t va){ - uint64_t l0_index = (va >> 37) & 0x1FF; + + uint64_t *table = pttrb ? pttrb : kernel_mmu_page; + + uint64_t l0_index = (va >> 39) & 0x1FF; uint64_t l1_index = (va >> 30) & 0x1FF; uint64_t l2_index = (va >> 21) & 0x1FF; uint64_t l3_index = (va >> 12) & 0x1FF; kprintf("Address %x is meant to be mapped to [%i][%i][%i][%i]",va, l0_index,l1_index,l2_index,l3_index); - if (!(page_table_l0[l0_index] & 1)) { + if (!(table[l0_index] & 1)) { kprintf("L1 Table missing"); return; } - uint64_t* l1 = (uint64_t*)(page_table_l0[l0_index] & 0xFFFFFFFFF000ULL); + uint64_t* l1 = (uint64_t*)(table[l0_index] & 0xFFFFFFFFF000ULL); if (!(l1[l1_index] & 1)) { kprintf("L2 Table missing"); return; @@ -294,3 +335,11 @@ void debug_mmu_address(uint64_t va){ kprintf("Entry: %b", l4_val); return; } + +extern void mmu_swap(uintptr_t* ttbr); + +uintptr_t *pttrb; + +void mmu_swap_ttbr(uintptr_t* ttbr){ + pttrb = ttbr ? ttbr : kernel_mmu_page; +} diff --git a/kernel/memory/mmu.h b/kernel/memory/mmu.h index 4995aedd..ce69294e 100644 --- a/kernel/memory/mmu.h +++ b/kernel/memory/mmu.h @@ -5,18 +5,27 @@ #define GRANULE_4KB 0x1000 #define GRANULE_2MB 0x200000 -void mmu_alloc(); +uint64_t* mmu_alloc(); void mmu_init(); #ifdef __cplusplus extern "C" { #endif +void mmu_map_kernel(uintptr_t *ttrb); +uintptr_t* mmu_new_ttrb(); void register_device_memory(uint64_t va, uint64_t pa); void register_device_memory_2mb(uint64_t va, uint64_t pa); void register_proc_memory(uint64_t va, uint64_t pa, uint8_t attributes, uint8_t level); +void mmu_map_4kb(uint64_t *table, uint64_t va, uint64_t pa, uint64_t attr_index, uint8_t mem_attributes, uint8_t level); void debug_mmu_address(uint64_t va); void mmu_enable_verbose(); +void mmu_swap_ttbr(uintptr_t* ttbr); +void mmu_default_ttbr(); +uintptr_t mmu_translate(uintptr_t va); #ifdef __cplusplus } #endif -void mmu_unmap(uint64_t va, uint64_t pa); \ No newline at end of file +extern uintptr_t *pttrb; + +void mmu_unmap(uint64_t va, uint64_t pa); +void mmu_init_kernel(); \ No newline at end of file diff --git a/kernel/memory/mmu_start.S b/kernel/memory/mmu_start.S new file mode 100644 index 00000000..a5899d95 --- /dev/null +++ b/kernel/memory/mmu_start.S @@ -0,0 +1,54 @@ +#include "sysregs.h" + +.global mmu_start +mmu_start://(uint64_t *page x0) +.type mmu_start, %function + ldr x3, =MAIR_VALUE + msr mair_el1, x3 + ldr x3, =TCR_VALUE + msr tcr_el1, x3 + dsb ish + isb + + msr ttbr0_el1, x0 + msr ttbr1_el1, x0 + + mrs x0, sctlr_el1 + orr x0, x0, #0x1 + bic x0, x0, #(1 << 19) + msr sctlr_el1, x0 + isb + + ldr x1, =HIGH_VA + + ldr x0, =ksp + orr x0, x0, x1 + adrp x3, ksp + str x0, [x3] + + ldr x0, =cpec + orr x0, x0, x1 + adrp x3, cpec + str x0, [x3] + + mov x0, sp + orr x0, x0, x1 + mov sp, x0 + + mov x0, x29 + orr x0, x0, x1 + mov x29, x0 + + mov x0, x30 + orr x0, x0, x1 + mov x30, x0 + + ldr x0, [sp, #8] + orr x0, x0, x1 + str x0, [sp, #8] + + mrs x0, vbar_el1 + orr x0, x0, x1 + msr vbar_el1, x0 + + ret \ No newline at end of file diff --git a/kernel/memory/page_allocator.c b/kernel/memory/page_allocator.c index c95254d3..64d3f61f 100644 --- a/kernel/memory/page_allocator.c +++ b/kernel/memory/page_allocator.c @@ -7,6 +7,7 @@ #include "math/math.h" #include "console/kio.h" #include "process/scheduler.h" +#include "sysregs.h" #define PD_TABLE 0b11 #define PD_BLOCK 0b01 @@ -207,7 +208,7 @@ void mark_used(uintptr_t address, size_t pages) #define PAGE_INDEX_LIMIT (PAGE_SIZE-sizeof(page_index_hdr))/sizeof(page_index_entry) //TODO: maybe alloc to different base pages based on alignment? Then it's easier to keep track of full pages, freeing and sizes -void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level){ +void* kalloc_inner(void *page, uint64_t size, uint16_t alignment, uint8_t level, uintptr_t page_va, uintptr_t *next_va, uintptr_t *ttrb){ //TODO: we're changing the size but not reporting it back, which means the free function does not fully free the allocd memory size = (size + alignment - 1) & ~(alignment - 1); @@ -219,19 +220,27 @@ void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level){ if (size >= PAGE_SIZE){ void* ptr = palloc(size, level, info->attributes, true); page_index *index = info->page_alloc; - if (!info->page_alloc){ - info->page_alloc = palloc(PAGE_SIZE, level, info->attributes, true); + if (!index){ + info->page_alloc = palloc(PAGE_SIZE, level, info->attributes, true);//TODO: HIGH_VA index = info->page_alloc; } while (index->header.next) { index = index->header.next; } if (index->header.size >= PAGE_INDEX_LIMIT){ - index->header.next = palloc(PAGE_SIZE, level, info->attributes, true); + index->header.next = palloc(PAGE_SIZE, level, info->attributes, true);//TODO: HIGH_VA index = index->header.next; } index->ptrs[index->header.size].ptr = ptr; index->ptrs[index->header.size++].size = size; + if (page_va && next_va && ttrb){ + uintptr_t va = *next_va; + for (uintptr_t i = (uintptr_t)ptr; i < (uintptr_t)ptr + size; i+= GRANULE_4KB){ + mmu_map_4kb(ttrb, *next_va, (uintptr_t)i, (info->attributes & MEM_DEV) ? MAIR_IDX_DEVICE : MAIR_IDX_NORMAL, info->attributes, level); + *next_va += PAGE_SIZE; + } + return (void*)va; + } return ptr; } @@ -244,6 +253,9 @@ void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level){ *curr = (*curr)->next; memset((void*)result, 0, size); info->size += size; + if (page_va){ + return (void*)(page_va | (result & 0xFFF)); + } return (void*)result; } kprintfv("-> %x",(uintptr_t)&(*curr)->next); @@ -257,10 +269,16 @@ void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level){ kprintfv("[in_page_alloc] Aligned next pointer %x",info->next_free_mem_ptr); if (info->next_free_mem_ptr + size > (((uintptr_t)page) + PAGE_SIZE)) { - if (!info->next) + if (!info->next){ info->next = palloc(PAGE_SIZE, level, info->attributes, false); + if (page_va && next_va && ttrb){ + mmu_map_4kb(ttrb, *next_va, (uintptr_t)info->next, (info->attributes & MEM_DEV) ? MAIR_IDX_DEVICE : MAIR_IDX_NORMAL, info->attributes, level); + *next_va += PAGE_SIZE; + } + kprintfv("[in_page_alloc] Page %llx points to new page %llx",page,info->next); + } kprintfv("[in_page_alloc] Page full. Moving to %x",(uintptr_t)info->next); - return kalloc(info->next, size, alignment, level); + return kalloc_inner(info->next, size, alignment, level, page_va ? page_va + PAGE_SIZE : 0, next_va, ttrb); } uint64_t result = info->next_free_mem_ptr; @@ -270,9 +288,19 @@ void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level){ memset((void*)result, 0, size); info->size += size; + if (page_va){ + return (void*)(page_va | (result & 0xFFF)); + } return (void*)result; } +//TODO: rather than kalloc, it should be palloc that does translations +void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level){ + void* ptr = kalloc_inner(page, size, alignment, level, 0, 0, 0); + if (level == MEM_PRIV_KERNEL) ptr = PHYS_TO_VIRT_P(ptr); + return ptr; +} + void kfree(void* ptr, uint64_t size) { kprintfv("[page_alloc_free] Freeing block at %x size %x",(uintptr_t)ptr, size); @@ -280,7 +308,9 @@ void kfree(void* ptr, uint64_t size) { mem_page *page = (mem_page *)(((uintptr_t)ptr) & ~0xFFF); - FreeBlock* block = (FreeBlock*)ptr; + uintptr_t phys_page = mmu_translate((uintptr_t)page); + + FreeBlock* block = (FreeBlock*)((uintptr_t)phys_page | ((uintptr_t)ptr & 0xFFF)); block->size = size; block->next = page->free_list; page->free_list = block; diff --git a/kernel/memory/page_allocator.h b/kernel/memory/page_allocator.h index 3fd97c49..9c95442b 100644 --- a/kernel/memory/page_allocator.h +++ b/kernel/memory/page_allocator.h @@ -31,6 +31,7 @@ void mark_used(uintptr_t address, size_t pages); bool page_used(uintptr_t ptr); +void* kalloc_inner(void *page, uint64_t size, uint16_t alignment, uint8_t level, uintptr_t page_va, uintptr_t *next_va, uintptr_t *ttrb); void* kalloc(void *page, uint64_t size, uint16_t alignment, uint8_t level); void kfree(void* ptr, uint64_t size); diff --git a/kernel/memory/talloc.c b/kernel/memory/talloc.c index a63da829..27c80731 100644 --- a/kernel/memory/talloc.c +++ b/kernel/memory/talloc.c @@ -42,7 +42,6 @@ extern uint64_t kernel_start; extern uint64_t heap_bottom; extern uint64_t heap_limit; extern uint64_t kcode_end; -extern uint64_t kfull_end; static bool talloc_verbose = false; uint64_t next_free_temp_memory = (uint64_t)&heap_bottom; @@ -148,7 +147,7 @@ int get_memory_region(uint64_t *out_base, uint64_t *out_size) { void calc_ram(){ if (get_memory_region(&total_ram_start, &total_ram_size)) { calculated_ram_end = total_ram_start + total_ram_size; - calculated_ram_start = ((uint64_t)&kfull_end) + 0x1; + calculated_ram_start = ((uint64_t)&kcode_end) + 0x1; calculated_ram_start = ((calculated_ram_start) & ~((1ULL << 21) - 1)); calculated_ram_end = ((calculated_ram_end) & ~((1ULL << 21) - 1)); } else { diff --git a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp index 371cb58c..d5b5e478 100644 --- a/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp +++ b/kernel/networking/drivers/virtio_net_pci/virtio_net_pci.cpp @@ -158,9 +158,9 @@ sizedptr VirtioNetDriver::allocate_packet(size_t size){ sizedptr VirtioNetDriver::handle_receive_packet(){ select_queue(&vnp_net_dev, RECEIVE_QUEUE); - struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; - struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; - struct virtq_avail* avail = (struct virtq_avail*)(uintptr_t)vnp_net_dev.common_cfg->queue_driver; + volatile virtq_used* used = (virtq_used*)vnp_net_dev.common_cfg->queue_device; + volatile virtq_desc* desc = (virtq_desc*)vnp_net_dev.common_cfg->queue_desc; + volatile virtq_avail* avail = (virtq_avail*)vnp_net_dev.common_cfg->queue_driver; uint16_t qsz = vnp_net_dev.common_cfg->queue_size; uint16_t new_idx = used->idx; @@ -169,7 +169,7 @@ sizedptr VirtioNetDriver::handle_receive_packet(){ } uint16_t used_ring_index = (uint16_t)(last_used_receive_idx % qsz); - struct virtq_used_elem* e = &used->ring[used_ring_index]; + volatile virtq_used_elem* e = &used->ring[used_ring_index]; last_used_receive_idx++; uint32_t desc_index = e->id; @@ -178,7 +178,7 @@ sizedptr VirtioNetDriver::handle_receive_packet(){ { avail->ring[avail->idx % qsz] = (uint16_t)desc_index; avail->idx++; - *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; + *(volatile uint16_t*)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; return (sizedptr){0,0}; } @@ -189,14 +189,14 @@ sizedptr VirtioNetDriver::handle_receive_packet(){ if (!out_buf){ avail->ring[avail->idx % qsz] = (uint16_t)desc_index; avail->idx++; - *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; + *(volatile uint16_t*)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; return (sizedptr){0,0}; } memcpy(out_buf, (void*)(packet_addr + header_size), payload_len); avail->ring[avail->idx % qsz] = (uint16_t)desc_index; avail->idx++; - *(volatile uint16_t*)(uintptr_t)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; + *(volatile uint16_t*)(vnp_net_dev.notify_cfg + vnp_net_dev.notify_off_multiplier * RECEIVE_QUEUE) = 0; return (sizedptr){ (uintptr_t)out_buf, payload_len }; } @@ -204,15 +204,15 @@ sizedptr VirtioNetDriver::handle_receive_packet(){ void VirtioNetDriver::handle_sent_packet(){ select_queue(&vnp_net_dev, TRANSMIT_QUEUE); - struct virtq_used* used = (struct virtq_used*)(uintptr_t)vnp_net_dev.common_cfg->queue_device; - struct virtq_desc* desc = (struct virtq_desc*)(uintptr_t)vnp_net_dev.common_cfg->queue_desc; + volatile virtq_used* used = (virtq_used*)vnp_net_dev.common_cfg->queue_device; + volatile virtq_desc* desc = (virtq_desc*)vnp_net_dev.common_cfg->queue_desc; uint16_t qsz = vnp_net_dev.common_cfg->queue_size; int cleaned = 0; while (last_used_sent_idx != used->idx && cleaned < 64) { uint16_t used_ring_index = (uint16_t)(last_used_sent_idx % qsz); last_used_sent_idx = (uint16_t)(last_used_sent_idx + 1); - struct virtq_used_elem* e = &used->ring[used_ring_index]; + volatile virtq_used_elem* e = &used->ring[used_ring_index]; uint32_t desc_index = e->id; if (desc_index < qsz) { diff --git a/kernel/pci.c b/kernel/pci.c index b74d243c..417a6a2c 100644 --- a/kernel/pci.c +++ b/kernel/pci.c @@ -5,6 +5,7 @@ #include "memory/mmu.h" #include "std/memory_access.h" #include "hw/hw.h" +#include "sysregs.h" #define PCI_BUS_MAX 256 #define PCI_SLOT_MAX 32 @@ -210,6 +211,8 @@ uint64_t pci_setup_bar(uint64_t pci_addr, uint32_t bar_index, uint64_t *mmio_sta *mmio_start = config_base; *mmio_size = size; + config_base = VIRT_TO_PHYS(config_base); + write32(bar_addr, config_base & 0xFFFFFFFF); write32(bar_addr_hi, config_base >> 32); @@ -231,6 +234,8 @@ uint64_t pci_setup_bar(uint64_t pci_addr, uint32_t bar_index, uint64_t *mmio_sta *mmio_start = config_base; *mmio_size = size32; + config_base = VIRT_TO_PHYS(config_base); + write32(bar_addr, config_base & 0xFFFFFFFF); } @@ -284,7 +289,7 @@ void pci_register(uint64_t mmio_addr, uint64_t mmio_size){ uint64_t start = mmio_addr & ~(GRANULE_4KB - 1); uint64_t end = (mmio_addr + mmio_size + GRANULE_4KB - 1) & ~(GRANULE_4KB - 1); for (uint64_t addr = start; addr < end; addr += GRANULE_4KB) - register_device_memory(addr,addr); + register_device_memory(PHYS_TO_VIRT(addr), VIRT_TO_PHYS(addr)); } #pragma region Interrupts @@ -442,8 +447,12 @@ bool pci_setup_msix(uint64_t pci_addr, msix_irq_line* irq_lines, uint8_t line_si if(!table_addr){ uint64_t bar_size = 0; pci_setup_bar(pci_addr, bir, &table_addr, &bar_size); + pci_register(table_addr, bar_size); kprintf("Setting up new bar for MSI-X %x + %x",table_addr, table_addr_offset); - } else kprintf("Bar %i setup at %x + %x",bir, table_addr, table_addr_offset); + } else { + kprintf("Bar %i setup at %x + %x",bir, table_addr, table_addr_offset); + pci_register(table_addr, GRANULE_4KB); + } volatile msix_table_entry *msix_start = (volatile msix_table_entry *)(uintptr_t)(table_addr + table_addr_offset); diff --git a/kernel/process/context_switch.S b/kernel/process/context_switch.S index b5ee4469..a0d031c3 100644 --- a/kernel/process/context_switch.S +++ b/kernel/process/context_switch.S @@ -1,3 +1,5 @@ +#include "sysregs.h" + .global save_pc_interrupt save_pc_interrupt: mrs x1, elr_el1 @@ -51,6 +53,23 @@ restore_context: msr elr_el1, x17 mov x17, #0 + + ldr x18, =pttrb + + cmp x18, #0 + b.eq 4f + + ldr x18, [x18] + + cmp x18, #0 + b.eq 4f + + msr ttbr0_el1, x18 + + tlbi vmalle1is +4: dsb ish + isb + mov x18, #0 eret \ No newline at end of file diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index 8962cd5e..9907790b 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -6,6 +6,8 @@ #include "exceptions/exception_handler.h" #include "std/memory.h" #include "memory/mmu.h" +#include "memory/talloc.h" +#include "sysregs.h" typedef struct { uint64_t code_base_start; @@ -291,8 +293,6 @@ process_t* create_process(const char *name, const char *bundle, sizedptr text, u if (bss_va + bss.size > max_addr) max_addr = bss_va + bss.size; } - // max_addr = (max_addr + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - size_t code_size = max_addr-min_addr; // kprintf("Code takes %x from %x to %x",code_size, min_addr, max_addr); @@ -302,21 +302,13 @@ process_t* create_process(const char *name, const char *bundle, sizedptr text, u // kprintf("Allocated space for process between %x and %x",dest,dest+((code_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))); - if (!allow_va || text_va + code_size >= LOWEST_ADDR){ - if (!allow_va) - kprintf("[PROCESS_LOADING IMPLEMENTATION WARNING] virtual addressing currently not supported for this process. System is limited to one VA process at a time :("); - else - kprintf("[PROCESS_LOADING IMPLEMENTATION WARNING] virtual addressing currently not supported for this process. Would overwrite %x",LOWEST_ADDR); - entry += dest - min_addr; - proc->use_va = false; - } else { - //TODO: multiple TTBRs - for (uint32_t i = min_addr; i < max_addr; i += GRANULE_4KB){ - register_proc_memory( i, (uintptr_t)dest + (i - min_addr), MEM_EXEC | MEM_RO | MEM_NORM, MEM_PRIV_USER); - } - proc->use_va = true; - allow_va = false; + uintptr_t *ttbr = mmu_new_ttrb(); + + for (uintptr_t i = min_addr; i < max_addr; i += GRANULE_4KB){ + mmu_map_4kb(ttbr, i, (uintptr_t)dest + (i - min_addr), MAIR_IDX_NORMAL, MEM_EXEC | MEM_RO | MEM_NORM, MEM_PRIV_USER); } + proc->use_va = true; + allow_va = false; map_section(proc, dest, min_addr, text_va, text); map_section(proc, dest, min_addr, data_va, data); @@ -326,27 +318,49 @@ process_t* create_process(const char *name, const char *bundle, sizedptr text, u proc->va = min_addr; proc->code = (void*)dest; proc->code_size = (code_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + max_addr = (max_addr + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + proc->last_va_mapping = max_addr; uint64_t stack_size = 0x1000; uintptr_t stack = (uintptr_t)palloc(stack_size, MEM_PRIV_USER, MEM_RW, true); if (!stack) return 0; + + proc->last_va_mapping += PAGE_SIZE;//Unmapped page to catch stack overflows + proc->stack = (proc->last_va_mapping + stack_size); + proc->stack_phys = (stack + stack_size); + + for (uintptr_t i = stack; i < stack + stack_size; i += GRANULE_4KB){ + mmu_map_4kb(ttbr, proc->last_va_mapping, i, MAIR_IDX_NORMAL, MEM_RW | MEM_NORM, MEM_PRIV_USER); + mmu_map_4kb(ttbr, i, i, MAIR_IDX_NORMAL, MEM_RW | MEM_NORM, MEM_PRIV_USER); + kprintf("Stack %llx -> %llx",proc->last_va_mapping, i); + proc->last_va_mapping += PAGE_SIZE; + } + + proc->last_va_mapping += PAGE_SIZE;//Unmapped page to catch stack overflows uintptr_t heap = (uintptr_t)palloc(PAGE_SIZE, MEM_PRIV_USER, MEM_RW, false); if (!heap) return 0; - proc->stack = (stack + stack_size); + proc->heap = proc->last_va_mapping; + proc->heap_phys = heap; + mmu_map_4kb(ttbr, proc->last_va_mapping, heap, MAIR_IDX_NORMAL, MEM_RW | MEM_NORM, MEM_PRIV_USER); + mmu_map_4kb(ttbr, heap, heap, MAIR_IDX_NORMAL, MEM_RW | MEM_NORM, MEM_PRIV_USER); + + proc->last_va_mapping += PAGE_SIZE; + proc->stack_size = stack_size; - proc->heap = heap; + + proc->ttbr = ttbr; proc->sp = proc->stack; + proc->output = PHYS_TO_VIRT((uintptr_t)palloc(0x1000, MEM_PRIV_USER, MEM_RW, true)); proc->pc = (uintptr_t)(entry); - kprintf("User process %s allocated with address at %x, stack at %x, heap at %x",(uintptr_t)name,proc->pc, proc->sp, proc->heap); + kprintf("User process %s allocated with address at %llx, stack at %llx (%llx), heap at %llx (%llx)",(uintptr_t)name,proc->pc, proc->sp, proc->stack_phys, proc->heap, proc->heap_phys); proc->spsr = 0; proc->state = BLOCKED; - - proc->output = (uintptr_t)palloc(0x1000, MEM_PRIV_USER, MEM_RW, true); return proc; } \ No newline at end of file diff --git a/kernel/process/process.h b/kernel/process/process.h index e499f7c9..62b56c7e 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -42,15 +42,20 @@ typedef struct { //Not used in process saving uint16_t id; uintptr_t stack; + uintptr_t stack_phys; uint64_t stack_size; uintptr_t heap; + uintptr_t heap_phys; uintptr_t output; + size_t output_size; + uintptr_t last_va_mapping; file out_fd; uint64_t exit_code; bool focused; void *code; size_t code_size; bool use_va; + uintptr_t *ttbr; uintptr_t va; enum process_state { STOPPED, READY, RUNNING, BLOCKED } state; __attribute__((aligned(16))) input_buffer_t input_buffer; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 9a0a828d..7b3332db 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -14,6 +14,7 @@ #include "math/math.h" #include "memory/mmu.h" #include "process/syscall.h" +#include "sysregs.h" extern void save_pc_interrupt(uintptr_t ptr); extern void restore_context(uintptr_t ptr); @@ -64,6 +65,7 @@ void switch_proc(ProcSwitchReason reason) { current_proc = next_proc; cpec = (uintptr_t)&processes[current_proc]; timer_reset(processes[current_proc].priority); + mmu_swap_ttbr(processes[current_proc].ttbr); process_restore(); } @@ -112,8 +114,8 @@ void reset_process(process_t *proc){ bool just_finished = processes[current_proc].id == proc->id; proc->sp = 0; if (!just_finished || !(processes[current_proc].PROC_PRIV))//Privileged processes use their own stack even in an exception. We'll free it when we reuse it - if (proc->stack) pfree((void*)proc->stack-proc->stack_size,proc->stack_size); - if (proc->heap) free_managed_page((void*)proc->heap);//Sadly, full pages of alloc'd memory are not kept track and will not be freed + if (proc->stack_phys) pfree((void*)proc->stack_phys-proc->stack_size,proc->stack_size); + if (proc->heap_phys) free_managed_page((void*)proc->heap_phys); proc->pc = 0; proc->spsr = 0; proc->exit_code = 0; @@ -311,11 +313,11 @@ FS_RESULT open_proc(const char *path, file *descriptor){ file->pid = proc->id; if (strcmp(path, "out", true) == 0){ - descriptor->size = 0;//TODO: sizeof buffer, could already have data + descriptor->size = proc->output_size; file->buffer = proc->output; } else if (strcmp(path, "state", true) == 0){ descriptor->size = sizeof(int); - file->buffer = (uintptr_t)&proc->state; + file->buffer = PHYS_TO_VIRT((uintptr_t)&proc->state); file->ignore_cursor = true; file->read_only = true; } else return FS_RESULT_NOTFOUND; @@ -363,6 +365,8 @@ size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ if (fd->id == FD_OUT){ process_t *proc = get_current_proc(); pbuf = proc->output; + if (size > PROC_OUT_BUF) + size = PROC_OUT_BUF; } else { node = clinkedlist_find(proc_opened_files, (void*)&fd->id, find_open_proc_file); if (!node->data) return 0; @@ -371,23 +375,25 @@ size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ pbuf = file->buffer; } - if (size >= PROC_OUT_BUF){ - kprint("Output too large"); - return 0; - } if (fd->cursor + size >= PROC_OUT_BUF){ fd->cursor = 0; memset((void*)pbuf, 0, PROC_OUT_BUF); } memcpy((void*)(pbuf + fd->cursor), buf, size); fd->cursor += size; - //TODO: Need a better way to handle opening a file multiple times - for (clinkedlist_node_t *start = proc_opened_files->head; start != proc_opened_files->tail; start = start->next){ - if (start != node){ - proc_open_file *n_file = (proc_open_file*)start->data; - if (n_file && n_file->buffer == pbuf){ - n_file->file_size += size; - } + if (fd->id == FD_OUT){ + process_t *proc = get_current_proc(); + proc->output_size += size; + } + if (proc_opened_files && proc_opened_files->head){ + //TODO: Need a better way to handle opening a file multiple times + for (clinkedlist_node_t *start = proc_opened_files->head; start != 0; start = start->next){ + if (fd->id == FD_OUT || start != node){ + proc_open_file *n_file = (proc_open_file*)start->data; + if (n_file && n_file->buffer == pbuf){ + n_file->file_size += size; + } + } } } return size; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 9d59884d..9ac33ef1 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -22,6 +22,7 @@ #include "bin/bin_mod.h" #include "net/transport_layer/csocket.h" #include "loading/dwarf.h" +#include "sysregs.h" int syscall_depth = 0; @@ -31,11 +32,12 @@ uintptr_t cpec; typedef uint64_t (*syscall_entry)(process_t *ctx); uint64_t syscall_malloc(process_t *ctx){ - void* page_ptr = syscall_depth > 1 ? (void*)get_proc_by_pid(1)->heap : (void*)get_current_heap(); + void* page_ptr = (void*)mmu_translate(syscall_depth > 1 ? get_proc_by_pid(1)->heap : ctx->heap); if ((uintptr_t)page_ptr == 0x0){ handle_exception("Wrong process heap state", 0); } - return (uintptr_t)kalloc(page_ptr, ctx->PROC_X0, ALIGN_16B, get_current_privilege()); + size_t size = ctx->PROC_X0; + return (uintptr_t)kalloc_inner(page_ptr, size, ALIGN_16B, get_current_privilege(), ctx->heap, &ctx->last_va_mapping, ctx->ttbr); } uint64_t syscall_free(process_t *ctx){ @@ -284,7 +286,7 @@ void backtrace(uintptr_t fp, uintptr_t elr, sizedptr debug_line, sizedptr debug_ kprintf("%i: caller address: %x", depth, return_address, return_address); fp = *(uintptr_t*)fp; } else return; - + } } @@ -376,14 +378,16 @@ void sync_el0_handler_c(){ } } } - //We could handle more exceptions now, such as x25 (unmasked x96) = data abort. 0x21 at end of 0x25 = alignment fault if (currentEL == 1){ - kprintf("System has crashed. ESR: %x. ELR: %x. FAR: %x", esr, elr, far); - coredump(esr, elr, far, proc->sp); - handle_exception("UNEXPECTED EXCEPTION",ec); + if (syscall_depth < 3){ + if (syscall_depth == 1) kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); + if (syscall_depth < 2) coredump(esr, elr, far, proc->sp); + handle_exception("UNEXPECTED EXCEPTION",ec); + } + while (true); } else { - kprintf("Process has crashed. ESR: %x. ELR: %x. FAR: %x", esr, elr, far); - coredump(esr, elr, far, proc->sp); + kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); + if (syscall_depth < 2) coredump(esr, elr, far, proc->sp); syscall_depth--; stop_current_process(ec); } diff --git a/kernel/sysregs.h b/kernel/sysregs.h index 72a98da7..6855cf20 100644 --- a/kernel/sysregs.h +++ b/kernel/sysregs.h @@ -46,4 +46,25 @@ #define TRAP_PHYS_TIMER_DISABLED (1 << 0) #define TRAV_VIRT_TIMER_DISABLED (1 << 1) //Disable trapping of timer calls on hypervisor level -#define CNTHCTL_VALUE (TRAP_PHYS_TIMER_DISABLED | TRAV_VIRT_TIMER_DISABLED) \ No newline at end of file +#define CNTHCTL_VALUE (TRAP_PHYS_TIMER_DISABLED | TRAV_VIRT_TIMER_DISABLED) + +// *************************************** +// MMU +// *************************************** + +//30 = Translation granule EL1. 10 = 4kb | 14 = TG EL0 00 = 4kb. 0xFFFFFFFF to translate to 64 +#define TCR_VALUE ((0xFFFFFFFF << 32) | ((64 - 48) << 0) | ((64 - 48) << 16) | (0b00 << 14) | (0b10 << 30)) + +#define MAIR_DEVICE_nGnRnE 0b00000000 +#define MAIR_NORMAL_NOCACHE 0b01000100 +#define MAIR_IDX_DEVICE 0 +#define MAIR_IDX_NORMAL 1 + +#define MAIR_VALUE ((MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL * 8))) + +#define HIGH_VA 0xFFFF000000000000ULL +#define VIRT_TO_PHYS(x) (x & ~HIGH_VA) +#define PHYS_TO_VIRT(x) (x | HIGH_VA) + +#define VIRT_TO_PHYS_P(x) ((void*)(((uintptr_t)x) & ~HIGH_VA)) +#define PHYS_TO_VIRT_P(x) ((void*)(((uintptr_t)x) | HIGH_VA)) \ No newline at end of file diff --git a/kernel/virtio/virtio_pci.c b/kernel/virtio/virtio_pci.c index a0974578..fa470f13 100644 --- a/kernel/virtio/virtio_pci.c +++ b/kernel/virtio/virtio_pci.c @@ -4,6 +4,7 @@ #include "memory/page_allocator.h" #include "virtio_pci.h" #include "async.h" +#include "sysregs.h" #define VIRTIO_STATUS_RESET 0x0 #define VIRTIO_STATUS_ACKNOWLEDGE 0x1 @@ -73,21 +74,22 @@ void virtio_get_capabilities(virtio_device *dev, uint64_t pci_addr, uint64_t *mm if (cap->cfg_type < VIRTIO_PCI_CAP_PCI_CFG && bar_base == 0){ kprintfv("[VIRTIO] Setting up bar"); bar_base = pci_setup_bar(pci_addr, cap->bar, mmio_start, mmio_size); - kprintfv("[VIRTIO] Bar @ %llx", (unsigned long long)bar_base); + bar_base = VIRT_TO_PHYS(bar_base); + kprintfv("[VIRTIO] Bar @ %llx", bar_base); } if (cap->cfg_type == VIRTIO_PCI_CAP_COMMON_CFG){ - kprintfv("[VIRTIO] Common CFG @ %llx",(unsigned long long)(bar_base + cap->offset)); + kprintfv("[VIRTIO] Common CFG @ %llx",(unsigned long long)(bar_base + cap->offset) >> 32); dev->common_cfg = (struct virtio_pci_common_cfg*)(uintptr_t)(bar_base + cap->offset); } else if (cap->cfg_type == VIRTIO_PCI_CAP_NOTIFY_CFG) { - kprintfv("[VIRTIO] Notify CFG @ %llx",(unsigned long long)(bar_base + cap->offset)); + kprintfv("[VIRTIO] Notify CFG @ %llx",(unsigned long long)(bar_base + cap->offset) >> 32); dev->notify_cfg = (uint8_t*)(uintptr_t)(bar_base + cap->offset); dev->notify_off_multiplier = *(uint32_t*)(uintptr_t)(cap_addr + sizeof(struct virtio_pci_cap)); } else if (cap->cfg_type == VIRTIO_PCI_CAP_DEVICE_CFG){ - kprintfv("[VIRTIO] Device CFG @ %llx",(unsigned long long)(bar_base + cap->offset)); + kprintfv("[VIRTIO] Device CFG @ %llx",(unsigned long long)(bar_base + cap->offset) >> 32); dev->device_cfg = (uint8_t*)(uintptr_t)(bar_base + cap->offset); } else if (cap->cfg_type == VIRTIO_PCI_CAP_ISR_CFG){ - kprintfv("[VIRTIO] ISR CFG @ %llx",(unsigned long long)(bar_base + cap->offset)); + kprintfv("[VIRTIO] ISR CFG @ %llx",(unsigned long long)(bar_base + cap->offset) >> 32); dev->isr_cfg = (uint8_t*)(uintptr_t)(bar_base + cap->offset); } } @@ -146,15 +148,15 @@ bool virtio_init_device(virtio_device *dev) { uint64_t avail = (uintptr_t)kalloc(dev->memory_page, avail_sz, ALIGN_4KB, MEM_PRIV_KERNEL); uint64_t used = (uintptr_t)kalloc(dev->memory_page, used_sz, ALIGN_4KB, MEM_PRIV_KERNEL); - dev->common_cfg->queue_desc = base; - dev->common_cfg->queue_driver = avail; - dev->common_cfg->queue_device = used; + dev->common_cfg->queue_desc = VIRT_TO_PHYS(base); + dev->common_cfg->queue_driver = VIRT_TO_PHYS(avail); + dev->common_cfg->queue_device = VIRT_TO_PHYS(used); - volatile struct virtq_avail* A = (volatile struct virtq_avail*)(uintptr_t)avail; + volatile virtq_avail* A = (volatile virtq_avail*)(uintptr_t)avail; A->flags = 0; A->idx = 0; - volatile struct virtq_used* U = (volatile struct virtq_used*)(uintptr_t)used; + volatile virtq_used* U = (volatile virtq_used*)(uintptr_t)used; U->flags = 0; U->idx = 0; @@ -177,22 +179,22 @@ uint32_t select_queue(virtio_device *dev, uint32_t index){ } bool virtio_send_3d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags) { - struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)dev->common_cfg->queue_desc; - struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)dev->common_cfg->queue_driver; - struct virtq_used* u = (struct virtq_used*)(uintptr_t)dev->common_cfg->queue_device; + volatile virtq_desc* d = (virtq_desc*)dev->common_cfg->queue_desc; + volatile virtq_avail* a = (virtq_avail*)dev->common_cfg->queue_driver; + volatile virtq_used* u = (virtq_used*)dev->common_cfg->queue_device; - d[0].addr = cmd; + d[0].addr = VIRT_TO_PHYS(cmd); d[0].len = cmd_len; d[0].flags = VIRTQ_DESC_F_NEXT; d[0].next = 1; - d[1].addr = resp; + d[1].addr = VIRT_TO_PHYS(resp); d[1].len = resp_len; d[1].flags = VIRTQ_DESC_F_NEXT | flags; d[1].next = 2; *dev->status_dma = 0; - d[2].addr = (uint64_t)dev->status_dma; + d[2].addr = VIRT_TO_PHYS((uint64_t)dev->status_dma); d[2].len = 1; d[2].flags = VIRTQ_DESC_F_WRITE; d[2].next = 0; @@ -201,7 +203,7 @@ bool virtio_send_3d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len, uint64_t a->ring[a->idx % dev->common_cfg->queue_size] = 0; a->idx++; - *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; + *(volatile uint16_t*)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; while (last_used_idx == u->idx);//TODO: OPT @@ -214,17 +216,17 @@ bool virtio_send_3d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len, uint64_t bool virtio_send_2d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len, uint64_t resp, uint32_t resp_len, uint8_t flags) { - struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)dev->common_cfg->queue_desc; - struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)dev->common_cfg->queue_driver; - struct virtq_used* u = (struct virtq_used*)(uintptr_t)dev->common_cfg->queue_device; + volatile virtq_desc* d = (virtq_desc*)dev->common_cfg->queue_desc; + volatile virtq_avail* a = (virtq_avail*)dev->common_cfg->queue_driver; + volatile virtq_used* u = (virtq_used*)dev->common_cfg->queue_device; uint16_t last_used_idx = u->idx; - d[0].addr = cmd; + d[0].addr = VIRT_TO_PHYS(cmd); d[0].len = cmd_len; d[0].flags = flags; d[0].next = 1; - d[1].addr = resp; + d[1].addr = VIRT_TO_PHYS(resp); d[1].len = resp_len; d[1].flags = VIRTQ_DESC_F_WRITE; d[1].next = 0; @@ -232,7 +234,7 @@ bool virtio_send_2d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len, uint64_t a->ring[a->idx % dev->common_cfg->queue_size] = 0; a->idx++; - *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; + *(volatile uint16_t*)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; while (last_used_idx == u->idx);//TODO: OPT @@ -241,12 +243,12 @@ bool virtio_send_2d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len, uint64_t bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { - struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)dev->common_cfg->queue_desc; - struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)dev->common_cfg->queue_driver; - struct virtq_used* u = (struct virtq_used*)(uintptr_t)dev->common_cfg->queue_device; + volatile virtq_desc* d = (virtq_desc*)dev->common_cfg->queue_desc; + volatile virtq_avail* a = (virtq_avail*)dev->common_cfg->queue_driver; + volatile virtq_used* u = (virtq_used*)dev->common_cfg->queue_device; uint16_t last_used_idx = u->idx; - d[0].addr = cmd; + d[0].addr = VIRT_TO_PHYS(cmd); d[0].len = cmd_len; d[0].flags = 0; d[0].next = 0; @@ -255,7 +257,7 @@ bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { a->idx++; - *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; + *(volatile uint16_t*)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; while (last_used_idx == u->idx);//TODO: OPT @@ -264,10 +266,10 @@ bool virtio_send_1d(virtio_device *dev, uint64_t cmd, uint32_t cmd_len) { void virtio_add_buffer(virtio_device *dev, uint16_t index, uint64_t buf, uint32_t buf_len, bool host_to_dev) { - struct virtq_desc* d = (struct virtq_desc*)(uintptr_t)dev->common_cfg->queue_desc; - struct virtq_avail* a = (struct virtq_avail*)(uintptr_t)dev->common_cfg->queue_driver; + volatile virtq_desc* d = (virtq_desc*)dev->common_cfg->queue_desc; + volatile virtq_avail* a = (virtq_avail*)dev->common_cfg->queue_driver; - d[index].addr = buf; + d[index].addr = VIRT_TO_PHYS(buf); d[index].len = buf_len; d[index].flags = host_to_dev ? 0 : VIRTQ_DESC_F_WRITE; d[index].next = 0; @@ -275,5 +277,5 @@ void virtio_add_buffer(virtio_device *dev, uint16_t index, uint64_t buf, uint32_ a->ring[a->idx % dev->common_cfg->queue_size] = index; a->idx++; - *(volatile uint16_t*)(uintptr_t)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; + *(volatile uint16_t*)(dev->notify_cfg + dev->notify_off_multiplier * dev->common_cfg->queue_select) = 0; } \ No newline at end of file diff --git a/kernel/virtio/virtio_pci.h b/kernel/virtio/virtio_pci.h index 03e61d0a..9196fc69 100644 --- a/kernel/virtio/virtio_pci.h +++ b/kernel/virtio/virtio_pci.h @@ -32,29 +32,29 @@ typedef struct virtio_pci_common_cfg { uint16_t queue_reset; }__attribute__((packed)) virtio_pci_common_cfg; -struct virtq_desc { +typedef struct { uint64_t addr; uint32_t len; uint16_t flags; uint16_t next; -} __attribute__((packed)); +}__attribute__((packed)) virtq_desc; -struct virtq_avail { +typedef struct { uint16_t flags; uint16_t idx; uint16_t ring[]; -} __attribute__((packed)); +}__attribute__((packed)) virtq_avail; -struct virtq_used_elem { +typedef struct { uint32_t id; uint32_t len; -} __attribute__((packed)); +}__attribute__((packed)) virtq_used_elem; -struct virtq_used { +typedef struct { uint16_t flags; uint16_t idx; - struct virtq_used_elem ring[128]; -} __attribute__((packed)); + virtq_used_elem ring[128]; +}__attribute__((packed)) virtq_used; typedef struct virtio_device { struct virtio_pci_common_cfg* common_cfg; diff --git a/run_virt b/run_virt index 4de9948f..0dceda02 100755 --- a/run_virt +++ b/run_virt @@ -88,7 +88,7 @@ $PRIVILEGE qemu-system-aarch64 \ -device usb-kbd,bus=usb.0 \ -device usb-mouse,bus=usb.0 \ -device virtio-sound-pci,audiodev=audio \ - -trace file=./trace \ + -trace events=./traceevents -trace file=./trace \ -audiodev ${AUDIO_BACKEND},id=audio \ -d guest_errors \ $ARGS diff --git a/rundebug b/rundebug index 4c1edd63..c007fc81 100755 --- a/rundebug +++ b/rundebug @@ -1,6 +1,6 @@ -#!/bin/bash +#!/bin/sh -MODE="raspi" +MODE="virt" ARGS=() for arg in "$@"; do @@ -10,11 +10,15 @@ for arg in "$@"; do esac done -# osascript <