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 20 extern "C" void SVec(); 21 22 extern uint32 gPlatform; 23 24 25 status_t 26 arch_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 33 status_t 34 arch_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 48 status_t 49 arch_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 73 status_t 74 arch_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 85 status_t 86 arch_cpu_init_post_modules(kernel_args *args) 87 { 88 return B_OK; 89 } 90 91 92 void 93 arch_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 104 void 105 arch_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 131 void 132 arch_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 144 void 145 arch_cpu_global_TLB_invalidate(void) 146 { 147 FlushTlbAll(); 148 } 149 150 151 void 152 arch_cpu_user_TLB_invalidate(void) 153 { 154 FlushTlbAllAsid(0); 155 } 156 157 158 status_t 159 arch_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