1 /* 2 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2002, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 9 /* This file contains the cpu functions (init, etc). */ 10 11 12 #include <cpu.h> 13 #include <thread_types.h> 14 #include <arch/cpu.h> 15 #include <boot/kernel_args.h> 16 17 #include <string.h> 18 19 20 /* global per-cpu structure */ 21 cpu_ent gCPU[MAX_BOOT_CPUS]; 22 23 static spinlock sSetCpuLock; 24 25 26 status_t 27 cpu_init(kernel_args *args) 28 { 29 return arch_cpu_init(args); 30 } 31 32 33 status_t 34 cpu_init_percpu(kernel_args *args, int curr_cpu) 35 { 36 return arch_cpu_init_percpu(args, curr_cpu); 37 } 38 39 40 status_t 41 cpu_init_post_vm(kernel_args *args) 42 { 43 return arch_cpu_init_post_vm(args); 44 } 45 46 47 status_t 48 cpu_init_post_modules(kernel_args *args) 49 { 50 return arch_cpu_init_post_modules(args); 51 } 52 53 54 status_t 55 cpu_preboot_init_percpu(kernel_args *args, int curr_cpu) 56 { 57 // set the cpu number in the local cpu structure so that 58 // we can use it for get_current_cpu 59 memset(&gCPU[curr_cpu], 0, sizeof(gCPU[curr_cpu])); 60 gCPU[curr_cpu].cpu_num = curr_cpu; 61 62 return arch_cpu_preboot_init_percpu(args, curr_cpu); 63 } 64 65 66 bigtime_t 67 cpu_get_active_time(int32 cpu) 68 { 69 bigtime_t activeTime; 70 cpu_status state; 71 72 if (cpu < 0 || cpu > smp_get_num_cpus()) 73 return 0; 74 75 // We need to grab the thread lock here, because the thread activity 76 // time is not maintained atomically (because there is no need to) 77 78 state = disable_interrupts(); 79 GRAB_THREAD_LOCK(); 80 81 activeTime = gCPU[cpu].active_time; 82 83 RELEASE_THREAD_LOCK(); 84 restore_interrupts(state); 85 86 return activeTime; 87 } 88 89 90 void 91 clear_caches(void *address, size_t length, uint32 flags) 92 { 93 // ToDo: implement me! 94 } 95 96 97 // #pragma mark - 98 99 100 void 101 _user_clear_caches(void *address, size_t length, uint32 flags) 102 { 103 clear_caches(address, length, flags); 104 } 105 106 107 bool 108 _user_cpu_enabled(int32 cpu) 109 { 110 if (cpu < 0 || cpu >= smp_get_num_cpus()) 111 return false; 112 113 return !gCPU[cpu].disabled; 114 } 115 116 117 status_t 118 _user_set_cpu_enabled(int32 cpu, bool enabled) 119 { 120 status_t status = B_OK; 121 cpu_status state; 122 int32 i, count; 123 124 if (cpu < 0 || cpu >= smp_get_num_cpus()) 125 return B_BAD_VALUE; 126 127 // We need to lock here to make sure that no one can disable 128 // the last CPU 129 130 state = disable_interrupts(); 131 acquire_spinlock(&sSetCpuLock); 132 133 if (!enabled) { 134 // check if this is the last CPU to be disabled 135 for (i = 0, count = 0; i < smp_get_num_cpus(); i++) { 136 if (!gCPU[i].disabled) 137 count++; 138 } 139 140 if (count == 1) 141 status = B_NOT_ALLOWED; 142 } 143 144 if (status == B_OK) 145 gCPU[cpu].disabled = !enabled; 146 147 release_spinlock(&sSetCpuLock); 148 restore_interrupts(state); 149 return status; 150 } 151 152