1/* 2 * Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <KernelExport.h> 8 9#include <arch/cpu.h> 10#include <boot/kernel_args.h> 11#include <vm/VMAddressSpace.h> 12#include <commpage.h> 13#include <elf.h> 14#include <Htif.h> 15#include <platform/sbi/sbi_syscalls.h> 16 17#include <algorithm> 18 19 20extern "C" void SVec(); 21 22extern uint32 gPlatform; 23 24 25status_t 26arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu) 27{ 28 // dprintf("arch_cpu_preboot_init_percpu(%" B_PRId32 ")\n", curr_cpu); 29 return B_OK; 30} 31 32 33status_t 34arch_cpu_init_percpu(kernel_args *args, int curr_cpu) 35{ 36 SetStvec((uint64)SVec); 37 SstatusReg sstatus{.val = Sstatus()}; 38 sstatus.ie = 0; 39 sstatus.fs = extStatusInitial; // enable FPU 40 sstatus.xs = extStatusOff; 41 SetSstatus(sstatus.val); 42 SetBitsSie((1 << sTimerInt) | (1 << sSoftInt) | (1 << sExternInt)); 43 44 return B_OK; 45} 46 47 48status_t 49arch_cpu_init(kernel_args *args) 50{ 51 for (uint32 curCpu = 0; curCpu < args->num_cpus; curCpu++) { 52 cpu_ent* cpu = &gCPU[curCpu]; 53 54 cpu->arch.hartId = args->arch_args.hartIds[curCpu]; 55 56 cpu->topology_id[CPU_TOPOLOGY_PACKAGE] = 0; 57 cpu->topology_id[CPU_TOPOLOGY_CORE] = curCpu; 58 cpu->topology_id[CPU_TOPOLOGY_SMT] = 0; 59 60 for (unsigned int i = 0; i < CPU_MAX_CACHE_LEVEL; i++) 61 cpu->cache_id[i] = -1; 62 } 63 64 uint64 conversionFactor 65 = (1LL << 32) * 1000000LL / args->arch_args.timerFrequency; 66 67 __riscv64_setup_system_time(conversionFactor); 68 69 return B_OK; 70} 71 72 73status_t 74arch_cpu_init_post_vm(kernel_args *args) 75{ 76 // Set address space ownership to currently running threads 77 for (uint32 i = 0; i < args->num_cpus; i++) { 78 VMAddressSpace::Kernel()->Get(); 79 } 80 81 return B_OK; 82} 83 84 85status_t 86arch_cpu_init_post_modules(kernel_args *args) 87{ 88 return B_OK; 89} 90 91 92void 93arch_cpu_sync_icache(void *address, size_t len) 94{ 95 FenceI(); 96 97 if (smp_get_num_cpus() > 1) { 98 memory_full_barrier(); 99 sbi_remote_fence_i(0, -1); 100 } 101} 102 103 104void 105arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) 106{ 107 addr_t kernelStart = std::max<addr_t>(start, KERNEL_BASE); 108 addr_t kernelEnd = std::min<addr_t>(end, KERNEL_TOP); 109 110 addr_t userStart = std::max<addr_t>(start, USER_BASE); 111 addr_t userEnd = std::min<addr_t>(end, USER_TOP); 112 113 if (kernelStart <= kernelEnd) { 114 int64 numPages = kernelStart / B_PAGE_SIZE - kernelEnd / B_PAGE_SIZE; 115 while (numPages-- >= 0) { 116 FlushTlbPage(start); 117 start += B_PAGE_SIZE; 118 } 119 } 120 121 if (userStart <= userEnd) { 122 int64 numPages = userStart / B_PAGE_SIZE - userEnd / B_PAGE_SIZE; 123 while (numPages-- >= 0) { 124 FlushTlbPageAsid(start, 0); 125 start += B_PAGE_SIZE; 126 } 127 } 128} 129 130 131void 132arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) 133{ 134 for (int i = 0; i < num_pages; i++) { 135 addr_t page = pages[i]; 136 if (IS_KERNEL_ADDRESS(page)) 137 FlushTlbPage(page); 138 else 139 FlushTlbPageAsid(page, 0); 140 } 141} 142 143 144void 145arch_cpu_global_TLB_invalidate(void) 146{ 147 FlushTlbAll(); 148} 149 150 151void 152arch_cpu_user_TLB_invalidate(void) 153{ 154 FlushTlbAllAsid(0); 155} 156 157 158status_t 159arch_cpu_shutdown(bool reboot) 160{ 161 if (gPlatform == kPlatformSbi) { 162 sbi_system_reset( 163 reboot ? SBI_RESET_TYPE_COLD_REBOOT : SBI_RESET_TYPE_SHUTDOWN, 164 SBI_RESET_REASON_NONE); 165 } 166 167 HtifShutdown(); 168 return B_ERROR; 169} 170