xref: /haiku/src/system/kernel/arch/riscv64/arch_cpu.cpp (revision 1d9ad3fad7b143964ee6f258319bc7662ef975ee)
1c085f386SAlexander von Gluck IV /*
2c085f386SAlexander von Gluck IV  * Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk.
3c085f386SAlexander von Gluck IV  * Distributed under the terms of the MIT License.
4c085f386SAlexander von Gluck IV  */
5c085f386SAlexander von Gluck IV 
6c085f386SAlexander von Gluck IV 
7c085f386SAlexander von Gluck IV #include <KernelExport.h>
8c085f386SAlexander von Gluck IV 
9c085f386SAlexander von Gluck IV #include <arch/cpu.h>
10c085f386SAlexander von Gluck IV #include <boot/kernel_args.h>
11d031c09cSX512 #include <vm/VMAddressSpace.h>
12c085f386SAlexander von Gluck IV #include <commpage.h>
13c085f386SAlexander von Gluck IV #include <elf.h>
14d031c09cSX512 #include <Htif.h>
15d031c09cSX512 #include <platform/sbi/sbi_syscalls.h>
16d031c09cSX512 
17*1d9ad3faSX512 #include <algorithm>
18*1d9ad3faSX512 
19d031c09cSX512 
208ca0f03dSX512 extern "C" void SVec();
218ca0f03dSX512 
22fa41d6faSX512 extern uint32 gPlatform;
23c085f386SAlexander von Gluck IV 
24c085f386SAlexander von Gluck IV 
25c085f386SAlexander von Gluck IV status_t
arch_cpu_preboot_init_percpu(kernel_args * args,int curr_cpu)26c085f386SAlexander von Gluck IV arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu)
27c085f386SAlexander von Gluck IV {
288ca0f03dSX512 	// dprintf("arch_cpu_preboot_init_percpu(%" B_PRId32 ")\n", curr_cpu);
29c085f386SAlexander von Gluck IV 	return B_OK;
30c085f386SAlexander von Gluck IV }
31c085f386SAlexander von Gluck IV 
32c085f386SAlexander von Gluck IV 
33c085f386SAlexander von Gluck IV status_t
arch_cpu_init_percpu(kernel_args * args,int curr_cpu)34c085f386SAlexander von Gluck IV arch_cpu_init_percpu(kernel_args *args, int curr_cpu)
35c085f386SAlexander von Gluck IV {
368ca0f03dSX512 	SetStvec((uint64)SVec);
37fa557843SX512 	SstatusReg sstatus{.val = Sstatus()};
388ca0f03dSX512 	sstatus.ie = 0;
398ca0f03dSX512 	sstatus.fs = extStatusInitial; // enable FPU
408ca0f03dSX512 	sstatus.xs = extStatusOff;
418ca0f03dSX512 	SetSstatus(sstatus.val);
42fa557843SX512 	SetBitsSie((1 << sTimerInt) | (1 << sSoftInt) | (1 << sExternInt));
43c085f386SAlexander von Gluck IV 
448ca0f03dSX512 	return B_OK;
45c085f386SAlexander von Gluck IV }
46c085f386SAlexander von Gluck IV 
47c085f386SAlexander von Gluck IV 
48c085f386SAlexander von Gluck IV status_t
arch_cpu_init(kernel_args * args)49c085f386SAlexander von Gluck IV arch_cpu_init(kernel_args *args)
50c085f386SAlexander von Gluck IV {
518ca0f03dSX512 	for (uint32 curCpu = 0; curCpu < args->num_cpus; curCpu++) {
528ca0f03dSX512 		cpu_ent* cpu = &gCPU[curCpu];
538ca0f03dSX512 
548ca0f03dSX512 		cpu->arch.hartId = args->arch_args.hartIds[curCpu];
558ca0f03dSX512 
568ca0f03dSX512 		cpu->topology_id[CPU_TOPOLOGY_PACKAGE] = 0;
578ca0f03dSX512 		cpu->topology_id[CPU_TOPOLOGY_CORE] = curCpu;
588ca0f03dSX512 		cpu->topology_id[CPU_TOPOLOGY_SMT] = 0;
598ca0f03dSX512 
608ca0f03dSX512 		for (unsigned int i = 0; i < CPU_MAX_CACHE_LEVEL; i++)
618ca0f03dSX512 			cpu->cache_id[i] = -1;
628ca0f03dSX512 	}
638ca0f03dSX512 
64d031c09cSX512 	uint64 conversionFactor
655855a8e3SPrzemysław Buczkowski 		= (1LL << 32) * 1000000LL / args->arch_args.timerFrequency;
66d031c09cSX512 
67d031c09cSX512 	__riscv64_setup_system_time(conversionFactor);
68f8ef2441SAlexander von Gluck IV 
69c085f386SAlexander von Gluck IV 	return B_OK;
70c085f386SAlexander von Gluck IV }
71c085f386SAlexander von Gluck IV 
72c085f386SAlexander von Gluck IV 
73c085f386SAlexander von Gluck IV status_t
arch_cpu_init_post_vm(kernel_args * args)74c085f386SAlexander von Gluck IV arch_cpu_init_post_vm(kernel_args *args)
75c085f386SAlexander von Gluck IV {
76d031c09cSX512 	// Set address space ownership to currently running threads
77d031c09cSX512 	for (uint32 i = 0; i < args->num_cpus; i++) {
78d031c09cSX512 		VMAddressSpace::Kernel()->Get();
79d031c09cSX512 	}
80d031c09cSX512 
81c085f386SAlexander von Gluck IV 	return B_OK;
82c085f386SAlexander von Gluck IV }
83c085f386SAlexander von Gluck IV 
84c085f386SAlexander von Gluck IV 
85c085f386SAlexander von Gluck IV status_t
arch_cpu_init_post_modules(kernel_args * args)86c085f386SAlexander von Gluck IV arch_cpu_init_post_modules(kernel_args *args)
87c085f386SAlexander von Gluck IV {
88c085f386SAlexander von Gluck IV 	return B_OK;
89c085f386SAlexander von Gluck IV }
90c085f386SAlexander von Gluck IV 
91c085f386SAlexander von Gluck IV 
92c085f386SAlexander von Gluck IV void
arch_cpu_sync_icache(void * address,size_t len)93c085f386SAlexander von Gluck IV arch_cpu_sync_icache(void *address, size_t len)
94c085f386SAlexander von Gluck IV {
95408a7e27SX512 	FenceI();
96408a7e27SX512 
97408a7e27SX512 	if (smp_get_num_cpus() > 1) {
98408a7e27SX512 		memory_full_barrier();
99408a7e27SX512 		sbi_remote_fence_i(0, -1);
100408a7e27SX512 	}
101c085f386SAlexander von Gluck IV }
102c085f386SAlexander von Gluck IV 
103c085f386SAlexander von Gluck IV 
104c085f386SAlexander von Gluck IV void
arch_cpu_invalidate_TLB_range(addr_t start,addr_t end)105c085f386SAlexander von Gluck IV arch_cpu_invalidate_TLB_range(addr_t start, addr_t end)
106c085f386SAlexander von Gluck IV {
107*1d9ad3faSX512 	addr_t kernelStart = std::max<addr_t>(start, KERNEL_BASE);
108*1d9ad3faSX512 	addr_t kernelEnd   = std::min<addr_t>(end,   KERNEL_TOP);
109*1d9ad3faSX512 
110*1d9ad3faSX512 	addr_t userStart = std::max<addr_t>(start, USER_BASE);
111*1d9ad3faSX512 	addr_t userEnd   = std::min<addr_t>(end,   USER_TOP);
112*1d9ad3faSX512 
113*1d9ad3faSX512 	if (kernelStart <= kernelEnd) {
114*1d9ad3faSX512 		int64 numPages = kernelStart / B_PAGE_SIZE - kernelEnd / B_PAGE_SIZE;
1158ca0f03dSX512 		while (numPages-- >= 0) {
1168ca0f03dSX512 			FlushTlbPage(start);
1178ca0f03dSX512 			start += B_PAGE_SIZE;
1188ca0f03dSX512 		}
119c085f386SAlexander von Gluck IV 	}
120c085f386SAlexander von Gluck IV 
121*1d9ad3faSX512 	if (userStart <= userEnd) {
122*1d9ad3faSX512 		int64 numPages = userStart / B_PAGE_SIZE - userEnd / B_PAGE_SIZE;
123*1d9ad3faSX512 		while (numPages-- >= 0) {
124*1d9ad3faSX512 			FlushTlbPageAsid(start, 0);
125*1d9ad3faSX512 			start += B_PAGE_SIZE;
126*1d9ad3faSX512 		}
127*1d9ad3faSX512 	}
128*1d9ad3faSX512 }
129*1d9ad3faSX512 
130c085f386SAlexander von Gluck IV 
131c085f386SAlexander von Gluck IV void
arch_cpu_invalidate_TLB_list(addr_t pages[],int num_pages)132c085f386SAlexander von Gluck IV arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
133c085f386SAlexander von Gluck IV {
134*1d9ad3faSX512 	for (int i = 0; i < num_pages; i++) {
135*1d9ad3faSX512 		addr_t page = pages[i];
136*1d9ad3faSX512 		if (IS_KERNEL_ADDRESS(page))
137*1d9ad3faSX512 			FlushTlbPage(page);
138*1d9ad3faSX512 		else
139*1d9ad3faSX512 			FlushTlbPageAsid(page, 0);
140*1d9ad3faSX512 	}
141c085f386SAlexander von Gluck IV }
142c085f386SAlexander von Gluck IV 
143c085f386SAlexander von Gluck IV 
144c085f386SAlexander von Gluck IV void
arch_cpu_global_TLB_invalidate(void)145c085f386SAlexander von Gluck IV arch_cpu_global_TLB_invalidate(void)
146c085f386SAlexander von Gluck IV {
1478ca0f03dSX512 	FlushTlbAll();
148c085f386SAlexander von Gluck IV }
149c085f386SAlexander von Gluck IV 
150c085f386SAlexander von Gluck IV 
151c085f386SAlexander von Gluck IV void
arch_cpu_user_TLB_invalidate(void)152c085f386SAlexander von Gluck IV arch_cpu_user_TLB_invalidate(void)
153c085f386SAlexander von Gluck IV {
154*1d9ad3faSX512 	FlushTlbAllAsid(0);
155c085f386SAlexander von Gluck IV }
156c085f386SAlexander von Gluck IV 
157c085f386SAlexander von Gluck IV 
158c085f386SAlexander von Gluck IV status_t
arch_cpu_shutdown(bool reboot)159c085f386SAlexander von Gluck IV arch_cpu_shutdown(bool reboot)
160c085f386SAlexander von Gluck IV {
161fa41d6faSX512 	if (gPlatform == kPlatformSbi) {
162d031c09cSX512 		sbi_system_reset(
163d031c09cSX512 			reboot ? SBI_RESET_TYPE_COLD_REBOOT : SBI_RESET_TYPE_SHUTDOWN,
164d031c09cSX512 			SBI_RESET_REASON_NONE);
165d031c09cSX512 	}
166d031c09cSX512 
167d031c09cSX512 	HtifShutdown();
168c085f386SAlexander von Gluck IV 	return B_ERROR;
169c085f386SAlexander von Gluck IV }
170