1 /* 2 * Copyright 2012, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar R. Adema <ithamar@upgrade-android.com> 7 */ 8 9 #include "cpu.h" 10 11 #include <OS.h> 12 #include <boot/platform.h> 13 #include <boot/stdio.h> 14 #include <boot/kernel_args.h> 15 #include <boot/stage2.h> 16 #include <arch/cpu.h> 17 #include <arch_kernel.h> 18 #include <arch_system_info.h> 19 #include <arch_cpu.h> 20 #include <string.h> 21 22 #define TRACE_CPU 23 #ifdef TRACE_CPU 24 # define TRACE(x) dprintf x 25 #else 26 # define TRACE(x) ; 27 #endif 28 29 /*! Detect ARM core version and features. 30 Please note the fact that ARM7 and ARMv7 are two different things ;) 31 ARMx is a specific ARM CPU core instance, while ARMvX refers to the 32 ARM architecture specification version.... 33 34 Most of the architecture versions we're detecting here we will probably 35 never run on, just included for completeness sake... ARMv5 and up are 36 the likely ones for us to support (as they all have some kind of MMU). 37 */ 38 static status_t 39 check_cpu_features() 40 { 41 uint32 result = 0; 42 int arch = 0; 43 int variant = 0; 44 int part = 0; 45 int revision = 0; 46 int implementor = 0; 47 48 asm volatile("MRC p15, 0, %[c1out], c0, c0, 0":[c1out] "=r" (result)); 49 50 implementor = (result >> 24) & 0xff; 51 52 switch ((result >> 12) & 0xf) { 53 case 0: /* early ARMv3 or even older */ 54 arch = ARCH_ARM_PRE_ARM7; 55 break; 56 57 case 7: /* ARM7 processor */ 58 arch = (result & (1 << 23)) ? ARCH_ARM_v4T : ARCH_ARM_v3; 59 variant = (result >> 16) & 0x7f; 60 part = (result >> 4) & 0xfff; 61 revision = result & 0xf; 62 break; 63 64 default: 65 revision = result & 0xf; 66 part = (result >> 4) & 0xfff; 67 switch((result >> 16) & 0xf) { 68 case 1: arch = ARCH_ARM_v4; break; 69 case 2: arch = ARCH_ARM_v4T; break; 70 case 3: arch = ARCH_ARM_v5; break; 71 case 4: arch = ARCH_ARM_v5T; break; 72 case 5: arch = ARCH_ARM_v5TE; break; 73 case 6: arch = ARCH_ARM_v5TEJ; break; 74 case 7: arch = ARCH_ARM_v6; break; 75 case 0xf: 76 arch = ARCH_ARM_v7; 77 // TODO ... or later. We apparently need to scan the 78 // CPUID registers to decide. 79 break; 80 } 81 variant = (result >> 20) & 0xf; 82 break; 83 } 84 85 // TODO actually check for VFP support, and maybe there is a better place 86 // to do this. 87 if (arch >= ARCH_ARM_v7) 88 { 89 // Enable VFP/NEON. We HAVE to do this before the trace call below, 90 // which is the first time we call vprintf. Otherwise, it will crash 91 // when trying to push floating point registers on the stack. 92 asm volatile( 93 " MRC p15, #0, r1, c1, c0, #2\n" // r1 = Access Control Register 94 " ORR r1, r1, #(0xf << 20)\n" // enable full access for p10,11 95 " MCR p15, #0, r1, c1, c0, #2\n" // Access Control Register = r1 96 " MOV r1, #0\n" 97 " MCR p15, #0, r1, c7, c5, #4\n" // flush prefetch buffer because of 98 // FMXR below and CP 10 & 11 were only just enabled 99 " MOV r0,#0x40000000 \n" // Enable VFP itself 100 " FMXR FPEXC, r0" //FPEXC = r0 101 :::"r0", "r1"); 102 } 103 104 105 TRACE(("%s: implementor=0x%x('%c'), arch=%d, variant=0x%x, part=0x%x, revision=0x%x\n", 106 __func__, implementor, implementor, arch, variant, part, revision)); 107 108 return (arch < ARCH_ARM_v5) ? B_ERROR : B_OK; 109 } 110 111 112 extern "C" void 113 arch_cpu_memory_read_barrier(void) 114 { 115 asm volatile ("" : : : "memory"); 116 } 117 118 119 extern "C" void 120 arch_cpu_memory_write_barrier(void) 121 { 122 asm volatile ("" : : : "memory"); 123 } 124 125 126 extern "C" status_t 127 boot_arch_cpu_init(void) 128 { 129 status_t err = check_cpu_features(); 130 if (err != B_OK) { 131 panic("Retire your old Acorn and get something modern to boot!\n"); 132 return err; 133 } 134 135 gKernelArgs.num_cpus = 1; 136 // this will eventually be corrected later on 137 138 return B_OK; 139 } 140 141 142 extern "C" bigtime_t 143 system_time() 144 { 145 #warning Implement system_time in ARM bootloader! 146 return 0; 147 } 148 149 150 extern "C" void 151 spin(bigtime_t microseconds) 152 { 153 #warning Implment spin in ARM bootloader! 154 //bigtime_t time = system_time(); 155 //while ((system_time() - time) < microseconds) 156 // asm volatile ("nop;"); 157 } 158