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