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 */
23cpu_ent gCPU[MAX_BOOT_CPUS];
24
25static spinlock sSetCpuLock;
26
27
28status_t
29cpu_init(kernel_args *args)
30{
31	return arch_cpu_init(args);
32}
33
34
35status_t
36cpu_init_percpu(kernel_args *args, int curr_cpu)
37{
38	return arch_cpu_init_percpu(args, curr_cpu);
39}
40
41
42status_t
43cpu_init_post_vm(kernel_args *args)
44{
45	return arch_cpu_init_post_vm(args);
46}
47
48
49status_t
50cpu_init_post_modules(kernel_args *args)
51{
52	return arch_cpu_init_post_modules(args);
53}
54
55
56status_t
57cpu_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
68bigtime_t
69cpu_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
83void
84clear_caches(void *address, size_t length, uint32 flags)
85{
86	// ToDo: implement me!
87}
88
89
90//	#pragma mark -
91
92
93void
94_user_clear_caches(void *address, size_t length, uint32 flags)
95{
96	clear_caches(address, length, flags);
97}
98
99
100bool
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
110status_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