]> git.saurik.com Git - apple/xnu.git/blob - osfmk/chud/i386/chud_cpu_i386.c
xnu-1228.tar.gz
[apple/xnu.git] / osfmk / chud / i386 / chud_cpu_i386.c
1 /*
2 * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <mach/mach_types.h>
30 #include <mach/mach_host.h>
31
32 #include <kern/host.h>
33 #include <kern/processor.h>
34
35 #include <i386/cpu_data.h>
36 #include <i386/machine_routines.h>
37 #include <i386/perfmon.h>
38 #include <i386/mp.h>
39 #include <i386/trap.h>
40 #include <mach/i386/syscall_sw.h>
41
42 #include <chud/chud_xnu.h>
43
44 #pragma mark **** cpu enable/disable ****
45
46 extern kern_return_t processor_start(processor_t processor); // osfmk/kern/processor.c
47 extern kern_return_t processor_exit(processor_t processor); // osfmk/kern/processor.c
48
49 __private_extern__
50 kern_return_t chudxnu_enable_cpu(int cpu, boolean_t enable)
51 {
52 chudxnu_unbind_thread(current_thread(), 0);
53
54 if(cpu < 0 || (unsigned int)cpu >= real_ncpus) // sanity check
55 return KERN_FAILURE;
56
57 if((cpu_data_ptr[cpu] != NULL) && cpu != master_cpu) {
58 processor_t processor = cpu_to_processor(cpu);
59
60 if(processor == master_processor) // don't mess with the boot processor
61 return KERN_FAILURE;
62
63 if(enable) {
64 return processor_start(processor);
65 } else {
66 return processor_exit(processor);
67 }
68 }
69 return KERN_FAILURE;
70 }
71
72 #pragma mark **** perfmon facility ****
73
74 __private_extern__ kern_return_t
75 chudxnu_perfmon_acquire_facility(task_t task)
76 {
77 return pmc_acquire(task);
78 }
79
80 __private_extern__ kern_return_t
81 chudxnu_perfmon_release_facility(task_t task)
82 {
83 return pmc_release(task);
84 }
85
86 #pragma mark **** interrupt counters ****
87
88 __private_extern__ kern_return_t
89 chudxnu_get_cpu_interrupt_counters(int cpu, rupt_counters_t *rupts)
90 {
91 if(cpu < 0 || (unsigned int)cpu >= real_ncpus) { // sanity check
92 return KERN_FAILURE;
93 }
94
95 if(rupts) {
96 boolean_t oldlevel = ml_set_interrupts_enabled(FALSE);
97 cpu_data_t *per_proc;
98
99 per_proc = cpu_data_ptr[cpu];
100 // For now, we'll call an NMI a 'reset' interrupt
101 rupts->hwResets = per_proc->cpu_hwIntCnt[T_NMI];
102 rupts->hwMachineChecks = per_proc->cpu_hwIntCnt[T_MACHINE_CHECK];
103 rupts->hwDSIs = 0;
104 rupts->hwISIs = 0;
105 // we could accumulate 0x20-0x7f, but that'd likely overflow...
106 rupts->hwExternals = 0;
107 // This appears to be wrong.
108 rupts->hwAlignments = 0; //per_proc->cpu_hwIntCnt[0x11];
109 rupts->hwPrograms = 0;
110 rupts->hwFloatPointUnavailable = per_proc->cpu_hwIntCnt[T_NO_FPU];
111 // osfmk/i386/mp.h
112 rupts->hwDecrementers = per_proc->cpu_hwIntCnt[LAPIC_VECTOR(TIMER)];
113 // LAPIC_ERROR == IO ERROR??
114 rupts->hwIOErrors = per_proc->cpu_hwIntCnt[LAPIC_VECTOR(ERROR)];
115
116 // accumulate all system call types
117 // osfmk/mach/i386/syscall_sw.h
118 rupts->hwSystemCalls = per_proc->cpu_hwIntCnt[UNIX_INT] +
119 per_proc->cpu_hwIntCnt[MACH_INT] +
120 per_proc->cpu_hwIntCnt[MACHDEP_INT] +
121 per_proc->cpu_hwIntCnt[DIAG_INT];
122
123 rupts->hwTraces = per_proc->cpu_hwIntCnt[T_DEBUG]; // single steps == traces??
124 rupts->hwFloatingPointAssists = 0;
125 // osfmk/i386/mp.h
126 rupts->hwPerformanceMonitors =
127 per_proc->cpu_hwIntCnt[LAPIC_VECTOR(PERFCNT)];
128 rupts->hwAltivecs = 0;
129 rupts->hwInstBreakpoints = per_proc->cpu_hwIntCnt[T_INT3];
130 rupts->hwSystemManagements = 0;
131 rupts->hwAltivecAssists = 0;
132 rupts->hwThermal = per_proc->cpu_hwIntCnt[LAPIC_VECTOR(THERMAL)];
133 rupts->hwSoftPatches = 0;
134 rupts->hwMaintenances = 0;
135 // Watchpoint == instrumentation
136 rupts->hwInstrumentations = per_proc->cpu_hwIntCnt[T_WATCHPOINT];
137
138 ml_set_interrupts_enabled(oldlevel);
139 return KERN_SUCCESS;
140 } else {
141 return KERN_FAILURE;
142 }
143 }
144
145 __private_extern__ kern_return_t
146 chudxnu_clear_cpu_interrupt_counters(int cpu)
147 {
148 if(cpu < 0 || (unsigned int)cpu >= real_ncpus) { // sanity check
149 return KERN_FAILURE;
150 }
151 cpu_data_t *per_proc;
152
153 per_proc = cpu_data_ptr[cpu];
154
155 bzero((char *)per_proc->cpu_hwIntCnt, sizeof(uint32_t)*256);
156
157 return KERN_SUCCESS;
158 }
159
160 #pragma mark *** deprecated ***
161
162 //DEPRECATED
163 __private_extern__ kern_return_t
164 chudxnu_get_cpu_rupt_counters(int cpu, rupt_counters_t *rupts)
165 {
166 return chudxnu_get_cpu_interrupt_counters(cpu, rupts);
167 }
168
169 //DEPRECATED
170 __private_extern__ kern_return_t
171 chudxnu_clear_cpu_rupt_counters(int cpu)
172 {
173 return chudxnu_clear_cpu_interrupt_counters(cpu);
174 }