1 /* 2 * Copyright 2007, François Revol, revol@free.fr. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. 6 * Distributed under the terms of the MIT License. 7 * 8 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 9 * Distributed under the terms of the NewOS License. 10 */ 11 12 13 #include <KernelExport.h> 14 15 #include <arch/cpu.h> 16 #include <boot/kernel_args.h> 17 #include <commpage.h> 18 #include <elf.h> 19 20 21 int arch_cpu_type; 22 int arch_fpu_type; 23 int arch_mmu_type; 24 int arch_platform; 25 26 status_t 27 arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu) 28 { 29 // enable FPU 30 //ppc:set_msr(get_msr() | MSR_FP_AVAILABLE); 31 32 // The current thread must be NULL for all CPUs till we have threads. 33 // Some boot code relies on this. 34 arch_thread_set_current_thread(NULL); 35 36 return B_OK; 37 } 38 39 40 status_t 41 arch_cpu_init_percpu(kernel_args *args, int curr_cpu) 42 { 43 if (curr_cpu != 0) 44 panic("No SMP support on ARM yet!\n"); 45 46 return 0; 47 } 48 49 50 status_t 51 arch_cpu_init(kernel_args *args) 52 { 53 arch_cpu_type = args->arch_args.cpu_type; 54 arch_fpu_type = args->arch_args.fpu_type; 55 arch_mmu_type = args->arch_args.mmu_type; 56 arch_platform = args->arch_args.platform; 57 arch_platform = args->arch_args.machine; 58 59 return B_OK; 60 } 61 62 63 status_t 64 arch_cpu_init_post_vm(kernel_args *args) 65 { 66 return B_OK; 67 } 68 69 70 status_t 71 arch_cpu_init_post_modules(kernel_args *args) 72 { 73 // add the functions to the commpage image 74 image_id image = get_commpage_image(); 75 76 return B_OK; 77 } 78 79 80 void 81 arch_cpu_idle(void) 82 { 83 uint32 Rd = 0; 84 asm volatile("mcr p15, 0, %[c7format], c7, c0, 4" : : [c7format] "r" (Rd) ); 85 } 86 87 88 status_t 89 arch_cpu_shutdown(bool reboot) 90 { 91 while(1) 92 arch_cpu_idle(); 93 94 // never reached 95 return B_ERROR; 96 } 97 98 99 void 100 arch_cpu_sync_icache(void *address, size_t len) 101 { 102 uint32 Rd = 0; 103 asm volatile ("mcr p15, 0, %[c7format], c7, c5, 0" 104 : : [c7format] "r" (Rd) ); 105 } 106 107 108 void 109 arch_cpu_memory_read_barrier(void) 110 { 111 asm volatile ("" : : : "memory"); 112 } 113 114 115 void 116 arch_cpu_memory_write_barrier(void) 117 { 118 asm volatile ("" : : : "memory"); 119 } 120 121 122 void 123 arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) 124 { 125 int32 num_pages = end / B_PAGE_SIZE - start / B_PAGE_SIZE; 126 while (num_pages-- >= 0) { 127 asm volatile ("mcr p15, 0, %[c8format], c8, c6, 1" 128 : : [c8format] "r" (start) ); 129 start += B_PAGE_SIZE; 130 } 131 } 132 133 134 void 135 arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) 136 { 137 for (int i = 0; i < num_pages; i++) { 138 asm volatile ("mcr p15, 0, %[c8format], c8, c6, 1": 139 : [c8format] "r" (pages[i]) ); 140 } 141 } 142 143 144 void 145 arch_cpu_global_TLB_invalidate(void) 146 { 147 uint32 Rd = 0; 148 asm volatile ("mcr p15, 0, %[c8format], c8, c7, 0" 149 : : [c8format] "r" (Rd) ); 150 } 151 152 153 void 154 arch_cpu_user_TLB_invalidate(void) 155 {/* 156 cpu_ops.flush_insn_pipeline(); 157 cpu_ops.flush_atc_user(); 158 cpu_ops.flush_insn_pipeline(); 159 */ 160 #warning WRITEME 161 } 162 163 164 // TODO: all functions that use fault handlers need to be implemented 165 // in assembly due to problems passing in label addresses in gcc4. 166 status_t 167 arch_cpu_user_memcpy(void *to, const void *from, size_t size, 168 addr_t *faultHandler) 169 { 170 #warning WRITEME 171 /* 172 char *tmp = (char *)to; 173 char *s = (char *)from; 174 addr_t oldFaultHandler = *faultHandler; 175 176 if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 177 goto error; 178 179 while (size--) 180 *tmp++ = *s++; 181 182 *faultHandler = oldFaultHandler; 183 return 0; 184 185 error: 186 *faultHandler = oldFaultHandler;*/ 187 return B_BAD_ADDRESS; 188 } 189 190 191 /** \brief Copies at most (\a size - 1) characters from the string in \a from to 192 * the string in \a to, NULL-terminating the result. 193 * 194 * \param to Pointer to the destination C-string. 195 * \param from Pointer to the source C-string. 196 * \param size Size in bytes of the string buffer pointed to by \a to. 197 * 198 * \return strlen(\a from). 199 */ 200 201 ssize_t 202 arch_cpu_user_strlcpy(char *to, const char *from, 203 size_t size, addr_t *faultHandler) 204 { 205 #warning WRITEME 206 /* 207 int from_length = 0; 208 addr_t oldFaultHandler = *faultHandler; 209 210 if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 211 goto error; 212 213 if (size > 0) { 214 to[--size] = '\0'; 215 // copy 216 for ( ; size; size--, from_length++, to++, from++) { 217 if ((*to = *from) == '\0') 218 break; 219 } 220 } 221 // count any leftover from chars 222 while (*from++ != '\0') 223 from_length++; 224 225 *faultHandler = oldFaultHandler; 226 return from_length; 227 228 error: 229 *faultHandler = oldFaultHandler;*/ 230 return B_BAD_ADDRESS; 231 } 232 233 234 status_t 235 arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler) 236 { 237 #warning WRITEME 238 239 /* 240 char *xs = (char *)s; 241 addr_t oldFaultHandler = *faultHandler; 242 243 if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 244 goto error; 245 246 while (count--) 247 *xs++ = c; 248 249 *faultHandler = oldFaultHandler; 250 return 0; 251 252 error: 253 *faultHandler = oldFaultHandler;*/ 254 255 return B_BAD_ADDRESS; 256 } 257 258 259 // The purpose of this function is to trick the compiler. When setting the 260 // page_handler to a label that is obviously (to the compiler) never used, 261 // it may reorganize the control flow, so that the labeled part is optimized 262 // away. 263 // By invoking the function like this 264 // 265 // if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 266 // goto error; 267 // 268 // the compiler has to keep the labeled code, since it can't guess the return 269 // value of this (non-inlinable) function. At least in my tests it worked that 270 // way, and I hope it will continue to work like this in the future. 271 // 272 /*bool 273 m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler) 274 { 275 *handlerLocation = handler; 276 return false; 277 }*/ 278