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_platform.h> 16#include <arch_thread.h> 17#include <arch/cpu.h> 18#include <boot/kernel_args.h> 19#include <commpage.h> 20#include <elf.h> 21 22extern struct m68k_cpu_ops cpu_ops_030; 23extern struct m68k_cpu_ops cpu_ops_040; 24extern struct m68k_cpu_ops cpu_ops_060; 25 26struct m68k_cpu_ops cpu_ops; 27 28int arch_cpu_type; 29int arch_fpu_type; 30int arch_mmu_type; 31int arch_platform; 32 33status_t 34arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu) 35{ 36 // enable FPU 37 //ppc:set_msr(get_msr() | MSR_FP_AVAILABLE); 38 39 // The current thread must be NULL for all CPUs till we have threads. 40 // Some boot code relies on this. 41 arch_thread_set_current_thread(NULL); 42 43 return B_OK; 44} 45 46 47status_t 48arch_cpu_init_percpu(kernel_args *args, int curr_cpu) 49{ 50 //detect_cpu(curr_cpu); 51 52 // we only support one anyway... 53 return 0; 54} 55 56 57status_t 58arch_cpu_init(kernel_args *args) 59{ 60 arch_cpu_type = args->arch_args.cpu_type; 61 arch_fpu_type = args->arch_args.fpu_type; 62 arch_mmu_type = args->arch_args.mmu_type; 63 arch_platform = args->arch_args.platform; 64 arch_platform = args->arch_args.machine; 65 66 switch (arch_cpu_type) { 67 case 68020: 68 case 68030: 69 memcpy(&cpu_ops, &cpu_ops_030, sizeof(cpu_ops)); 70 break; 71 72 case 68040: 73 memcpy(&cpu_ops, &cpu_ops_040, sizeof(cpu_ops)); 74 break; 75 76#ifdef SUPPORTS_060 77 case 68060: 78 memcpy(&cpu_ops, &cpu_ops_060, sizeof(cpu_ops)); 79 break; 80#endif 81 default: 82 panic("unknown cpu_type %d\n", arch_cpu_type); 83 } 84 85 return B_OK; 86} 87 88 89status_t 90arch_cpu_init_post_vm(kernel_args *args) 91{ 92 return B_OK; 93} 94 95status_t 96arch_cpu_init_post_modules(kernel_args *args) 97{ 98 // add the functions to the commpage image 99 image_id image = get_commpage_image(); 100 101 return B_OK; 102} 103 104 105void 106arch_cpu_sync_icache(void *address, size_t len) 107{ 108 cpu_ops.flush_icache((addr_t)address, len); 109} 110 111 112void 113arch_cpu_memory_read_barrier(void) 114{ 115 asm volatile ("nop;" : : : "memory"); 116#warning M68k: check arch_cpu_memory_read_barrier (FNOP ?) 117} 118 119 120void 121arch_cpu_memory_write_barrier(void) 122{ 123 asm volatile ("nop;" : : : "memory"); 124#warning M68k: check arch_cpu_memory_write_barrier (FNOP ?) 125} 126 127 128void 129arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) 130{ 131 int32 num_pages = end / B_PAGE_SIZE - start / B_PAGE_SIZE; 132 cpu_ops.flush_insn_pipeline(); 133 while (num_pages-- >= 0) { 134 cpu_ops.flush_atc_addr(start); 135 cpu_ops.flush_insn_pipeline(); 136 start += B_PAGE_SIZE; 137 } 138 cpu_ops.flush_insn_pipeline(); 139} 140 141 142void 143arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) 144{ 145 int i; 146 147 cpu_ops.flush_insn_pipeline(); 148 for (i = 0; i < num_pages; i++) { 149 cpu_ops.flush_atc_addr(pages[i]); 150 cpu_ops.flush_insn_pipeline(); 151 } 152 cpu_ops.flush_insn_pipeline(); 153} 154 155 156void 157arch_cpu_global_TLB_invalidate(void) 158{ 159 cpu_ops.flush_insn_pipeline(); 160 cpu_ops.flush_atc_all(); 161 cpu_ops.flush_insn_pipeline(); 162} 163 164 165void 166arch_cpu_user_TLB_invalidate(void) 167{ 168 cpu_ops.flush_insn_pipeline(); 169 cpu_ops.flush_atc_user(); 170 cpu_ops.flush_insn_pipeline(); 171} 172 173 174status_t 175arch_cpu_shutdown(bool reboot) 176{ 177 M68KPlatform::Default()->ShutDown(reboot); 178 return B_ERROR; 179} 180 181 182// The purpose of this function is to trick the compiler. When setting the 183// page_handler to a label that is obviously (to the compiler) never used, 184// it may reorganize the control flow, so that the labeled part is optimized 185// away. 186// By invoking the function like this 187// 188// if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) 189// goto error; 190// 191// the compiler has to keep the labeled code, since it can't guess the return 192// value of this (non-inlinable) function. At least in my tests it worked that 193// way, and I hope it will continue to work like this in the future. 194// 195bool 196m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler) 197{ 198// TODO: This doesn't work correctly with gcc 4 anymore! 199 *handlerLocation = handler; 200 return false; 201} 202