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