xref: /haiku/src/system/kernel/arch/riscv64/arch_cpu.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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