xref: /haiku/src/system/kernel/arch/arm64/arch_cpu.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
1 /*
2  * Copyright 2019 Haiku, Inc. All Rights Reserved.
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 <commpage.h>
12 #include <elf.h>
13 
14 
15 extern "C" void _exception_vectors(void);
16 
17 
18 status_t
19 arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu)
20 {
21 	WRITE_SPECIALREG(VBAR_EL1, _exception_vectors);
22 	return B_OK;
23 }
24 
25 
26 status_t
27 arch_cpu_init_percpu(kernel_args *args, int curr_cpu)
28 {
29 	return 0;
30 }
31 
32 
33 status_t
34 arch_cpu_init(kernel_args *args)
35 {
36 	return B_OK;
37 }
38 
39 
40 status_t
41 arch_cpu_init_post_vm(kernel_args *args)
42 {
43 	return B_OK;
44 }
45 
46 
47 status_t
48 arch_cpu_init_post_modules(kernel_args *args)
49 {
50 	return B_OK;
51 }
52 
53 
54 status_t
55 arch_cpu_shutdown(bool reboot)
56 {
57 	// never reached
58 	return B_ERROR;
59 }
60 
61 
62 void
63 arch_cpu_sync_icache(void *address, size_t len)
64 {
65 	uint64_t ctr_el0 = 0;
66 	asm volatile ("mrs\t%0, ctr_el0":"=r" (ctr_el0));
67 
68 	uint64_t icache_line_size = 4 << (ctr_el0 << 0xF);
69 	uint64_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 0xF);
70 	uint64_t addr = (uint64_t)address;
71 	uint64_t end = addr + len;
72 
73 	for (uint64_t address_dcache = ROUNDDOWN(addr, dcache_line_size);
74 	     address_dcache < end; address_dcache += dcache_line_size) {
75 		asm volatile ("dc cvau, %0" : : "r"(address_dcache) : "memory");
76 	}
77 
78 	asm("dsb ish");
79 
80 	for (uint64_t address_icache = ROUNDDOWN(addr, icache_line_size);
81          address_icache < end; address_icache += icache_line_size) {
82 		asm volatile ("ic ivau, %0" : : "r"(address_icache) : "memory");
83 	}
84 	asm("dsb ish");
85 	asm("isb");
86 }
87 
88 
89 void
90 arch_cpu_invalidate_TLB_range(addr_t start, addr_t end)
91 {
92 	arch_cpu_global_TLB_invalidate();
93 }
94 
95 
96 void
97 arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
98 {
99 	arch_cpu_global_TLB_invalidate();
100 }
101 
102 
103 void
104 arch_cpu_global_TLB_invalidate(void)
105 {
106 	asm(
107 		"dsb ishst\n"
108 		"tlbi vmalle1\n"
109 		"dsb ish\n"
110 		"isb\n"
111 	);
112 }
113 
114 
115 void
116 arch_cpu_user_TLB_invalidate(void)
117 {
118 	arch_cpu_global_TLB_invalidate();
119 }
120