1845a180fSFrançois Revol /* 2845a180fSFrançois Revol * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. 3845a180fSFrançois Revol * Distributed under the terms of the MIT License. 4845a180fSFrançois Revol * 5845a180fSFrançois Revol * Copyright 2001, Travis Geiselbrecht. All rights reserved. 6845a180fSFrançois Revol * Distributed under the terms of the NewOS License. 7845a180fSFrançois Revol */ 8845a180fSFrançois Revol 9845a180fSFrançois Revol 10845a180fSFrançois Revol #include <KernelExport.h> 11845a180fSFrançois Revol 12845a180fSFrançois Revol #include <arch_platform.h> 13845a180fSFrançois Revol #include <arch_thread.h> 14845a180fSFrançois Revol #include <arch/cpu.h> 15845a180fSFrançois Revol #include <boot/kernel_args.h> 16845a180fSFrançois Revol 17845a180fSFrançois Revol 18845a180fSFrançois Revol status_t 19845a180fSFrançois Revol arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu) 20845a180fSFrançois Revol { 21845a180fSFrançois Revol // enable FPU 22*829748d8SFrançois Revol //ppc:set_msr(get_msr() | MSR_FP_AVAILABLE); 23845a180fSFrançois Revol 24845a180fSFrançois Revol // The current thread must be NULL for all CPUs till we have threads. 25845a180fSFrançois Revol // Some boot code relies on this. 26845a180fSFrançois Revol arch_thread_set_current_thread(NULL); 27845a180fSFrançois Revol 28845a180fSFrançois Revol return B_OK; 29845a180fSFrançois Revol } 30845a180fSFrançois Revol 31845a180fSFrançois Revol 32845a180fSFrançois Revol status_t 33845a180fSFrançois Revol arch_cpu_init(kernel_args *args) 34845a180fSFrançois Revol { 35845a180fSFrançois Revol return B_OK; 36845a180fSFrançois Revol } 37845a180fSFrançois Revol 38845a180fSFrançois Revol 39845a180fSFrançois Revol status_t 40845a180fSFrançois Revol arch_cpu_init_post_vm(kernel_args *args) 41845a180fSFrançois Revol { 42845a180fSFrançois Revol return B_OK; 43845a180fSFrançois Revol } 44845a180fSFrançois Revol 45845a180fSFrançois Revol status_t 46845a180fSFrançois Revol arch_cpu_init_post_modules(kernel_args *args) 47845a180fSFrançois Revol { 48845a180fSFrançois Revol return B_OK; 49845a180fSFrançois Revol } 50845a180fSFrançois Revol 51845a180fSFrançois Revol #define CACHELINE 32 52845a180fSFrançois Revol 53845a180fSFrançois Revol void 54845a180fSFrançois Revol arch_cpu_sync_icache(void *address, size_t len) 55845a180fSFrançois Revol { 56845a180fSFrançois Revol int l, off; 57845a180fSFrançois Revol char *p; 58*829748d8SFrançois Revol uint32 cacr; 59845a180fSFrançois Revol 60845a180fSFrançois Revol off = (unsigned int)address & (CACHELINE - 1); 61845a180fSFrançois Revol len += off; 62845a180fSFrançois Revol 63845a180fSFrançois Revol l = len; 64845a180fSFrançois Revol p = (char *)address - off; 65*829748d8SFrançois Revol asm volatile ("movec %%cacr,%0" : "=r"(cacr):); 66*829748d8SFrançois Revol cacr |= 0x00000004; /* ClearInstructionCacheEntry */ 67845a180fSFrançois Revol do { 68*829748d8SFrançois Revol asm volatile ("movec %0,%%caar" :: "r"(p)); 69*829748d8SFrançois Revol asm volatile ("movec %0,%%cacr" :: "r"(cacr)); 70845a180fSFrançois Revol p += CACHELINE; 71845a180fSFrançois Revol } while ((l -= CACHELINE) > 0); 72*829748d8SFrançois Revol m68k_nop(); 73845a180fSFrançois Revol } 74845a180fSFrançois Revol 75845a180fSFrançois Revol 76845a180fSFrançois Revol void 77845a180fSFrançois Revol arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) 78845a180fSFrançois Revol { 79ee75f852SFrançois Revol m68k_nop(); 80845a180fSFrançois Revol while (start < end) { 81ee75f852SFrançois Revol pflush(start); 82ee75f852SFrançois Revol m68k_nop(); 83845a180fSFrançois Revol start += B_PAGE_SIZE; 84845a180fSFrançois Revol } 85ee75f852SFrançois Revol m68k_nop(); 86845a180fSFrançois Revol } 87845a180fSFrançois Revol 88845a180fSFrançois Revol 89845a180fSFrançois Revol void 90845a180fSFrançois Revol arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) 91845a180fSFrançois Revol { 92845a180fSFrançois Revol int i; 93845a180fSFrançois Revol 94ee75f852SFrançois Revol m68k_nop(); 95845a180fSFrançois Revol for (i = 0; i < num_pages; i++) { 96ee75f852SFrançois Revol pflush(pages[i]); 97ee75f852SFrançois Revol m68k_nop(); 98845a180fSFrançois Revol } 99ee75f852SFrançois Revol m68k_nop(); 100845a180fSFrançois Revol } 101845a180fSFrançois Revol 102845a180fSFrançois Revol 103845a180fSFrançois Revol void 104845a180fSFrançois Revol arch_cpu_global_TLB_invalidate(void) 105845a180fSFrançois Revol { 106ee75f852SFrançois Revol m68k_nop(); 107*829748d8SFrançois Revol pflusha(); 108ee75f852SFrançois Revol m68k_nop(); 109845a180fSFrançois Revol } 110845a180fSFrançois Revol 111845a180fSFrançois Revol 112845a180fSFrançois Revol void 113845a180fSFrançois Revol arch_cpu_user_TLB_invalidate(void) 114845a180fSFrançois Revol { 115*829748d8SFrançois Revol // pflushfd ? 116845a180fSFrançois Revol arch_cpu_global_TLB_invalidate(); 117845a180fSFrançois Revol } 118845a180fSFrançois Revol 119845a180fSFrançois Revol 120845a180fSFrançois Revol status_t 121845a180fSFrançois Revol arch_cpu_user_memcpy(void *to, const void *from, size_t size, 122845a180fSFrançois Revol addr_t *faultHandler) 123845a180fSFrançois Revol { 124845a180fSFrançois Revol char *tmp = (char *)to; 125845a180fSFrançois Revol char *s = (char *)from; 126845a180fSFrançois Revol addr_t oldFaultHandler = *faultHandler; 127845a180fSFrançois Revol 128845a180fSFrançois Revol if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 129845a180fSFrançois Revol goto error; 130845a180fSFrançois Revol 131845a180fSFrançois Revol while (size--) 132845a180fSFrançois Revol *tmp++ = *s++; 133845a180fSFrançois Revol 134845a180fSFrançois Revol *faultHandler = oldFaultHandler; 135845a180fSFrançois Revol return 0; 136845a180fSFrançois Revol 137845a180fSFrançois Revol error: 138845a180fSFrançois Revol *faultHandler = oldFaultHandler; 139845a180fSFrançois Revol return B_BAD_ADDRESS; 140845a180fSFrançois Revol } 141845a180fSFrançois Revol 142845a180fSFrançois Revol 143845a180fSFrançois Revol /** \brief Copies at most (\a size - 1) characters from the string in \a from to 144845a180fSFrançois Revol * the string in \a to, NULL-terminating the result. 145845a180fSFrançois Revol * 146845a180fSFrançois Revol * \param to Pointer to the destination C-string. 147845a180fSFrançois Revol * \param from Pointer to the source C-string. 148845a180fSFrançois Revol * \param size Size in bytes of the string buffer pointed to by \a to. 149845a180fSFrançois Revol * 150845a180fSFrançois Revol * \return strlen(\a from). 151845a180fSFrançois Revol */ 152845a180fSFrançois Revol 153845a180fSFrançois Revol ssize_t 154845a180fSFrançois Revol arch_cpu_user_strlcpy(char *to, const char *from, size_t size, addr_t *faultHandler) 155845a180fSFrançois Revol { 156845a180fSFrançois Revol int from_length = 0; 157845a180fSFrançois Revol addr_t oldFaultHandler = *faultHandler; 158845a180fSFrançois Revol 159845a180fSFrançois Revol if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 160845a180fSFrançois Revol goto error; 161845a180fSFrançois Revol 162845a180fSFrançois Revol if (size > 0) { 163845a180fSFrançois Revol to[--size] = '\0'; 164845a180fSFrançois Revol // copy 165845a180fSFrançois Revol for ( ; size; size--, from_length++, to++, from++) { 166845a180fSFrançois Revol if ((*to = *from) == '\0') 167845a180fSFrançois Revol break; 168845a180fSFrançois Revol } 169845a180fSFrançois Revol } 170845a180fSFrançois Revol // count any leftover from chars 171845a180fSFrançois Revol while (*from++ != '\0') 172845a180fSFrançois Revol from_length++; 173845a180fSFrançois Revol 174845a180fSFrançois Revol *faultHandler = oldFaultHandler; 175845a180fSFrançois Revol return from_length; 176845a180fSFrançois Revol 177845a180fSFrançois Revol error: 178845a180fSFrançois Revol *faultHandler = oldFaultHandler; 179845a180fSFrançois Revol return B_BAD_ADDRESS; 180845a180fSFrançois Revol } 181845a180fSFrançois Revol 182845a180fSFrançois Revol 183845a180fSFrançois Revol status_t 184845a180fSFrançois Revol arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler) 185845a180fSFrançois Revol { 186845a180fSFrançois Revol char *xs = (char *)s; 187845a180fSFrançois Revol addr_t oldFaultHandler = *faultHandler; 188845a180fSFrançois Revol 189845a180fSFrançois Revol if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 190845a180fSFrançois Revol goto error; 191845a180fSFrançois Revol 192845a180fSFrançois Revol while (count--) 193845a180fSFrançois Revol *xs++ = c; 194845a180fSFrançois Revol 195845a180fSFrançois Revol *faultHandler = oldFaultHandler; 196845a180fSFrançois Revol return 0; 197845a180fSFrançois Revol 198845a180fSFrançois Revol error: 199845a180fSFrançois Revol *faultHandler = oldFaultHandler; 200845a180fSFrançois Revol return B_BAD_ADDRESS; 201845a180fSFrançois Revol } 202845a180fSFrançois Revol 203845a180fSFrançois Revol 204845a180fSFrançois Revol status_t 205845a180fSFrançois Revol arch_cpu_shutdown(bool reboot) 206845a180fSFrançois Revol { 207845a180fSFrançois Revol M68KPlatform::Default()->ShutDown(reboot); 208845a180fSFrançois Revol return B_ERROR; 209845a180fSFrançois Revol } 210845a180fSFrançois Revol 211845a180fSFrançois Revol 212845a180fSFrançois Revol void 213845a180fSFrançois Revol arch_cpu_idle(void) 214845a180fSFrançois Revol { 215845a180fSFrançois Revol } 216845a180fSFrançois Revol 217845a180fSFrançois Revol 218845a180fSFrançois Revol // The purpose of this function is to trick the compiler. When setting the 219845a180fSFrançois Revol // page_handler to a label that is obviously (to the compiler) never used, 220845a180fSFrançois Revol // it may reorganize the control flow, so that the labeled part is optimized 221845a180fSFrançois Revol // away. 222845a180fSFrançois Revol // By invoking the function like this 223845a180fSFrançois Revol // 224845a180fSFrançois Revol // if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 225845a180fSFrançois Revol // goto error; 226845a180fSFrançois Revol // 227845a180fSFrançois Revol // the compiler has to keep the labeled code, since it can't guess the return 228845a180fSFrançois Revol // value of this (non-inlinable) function. At least in my tests it worked that 229845a180fSFrançois Revol // way, and I hope it will continue to work like this in the future. 230845a180fSFrançois Revol // 231845a180fSFrançois Revol bool 232845a180fSFrançois Revol m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler) 233845a180fSFrançois Revol { 234845a180fSFrançois Revol *handlerLocation = handler; 235845a180fSFrançois Revol return false; 236845a180fSFrançois Revol } 237