xref: /haiku/src/system/kernel/cpu.cpp (revision 1294543de9ac0eff000eaea1b18368c36435d08e)
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