]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
91447636 | 2 | * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. |
1c79356b A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
e5568f75 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
1c79356b | 11 | * |
e5568f75 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
e5568f75 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
1c79356b A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * @OSF_COPYRIGHT@ | |
24 | * | |
25 | */ | |
26 | ||
27 | #ifndef I386_CPU_DATA | |
28 | #define I386_CPU_DATA | |
29 | ||
1c79356b A |
30 | #include <mach_assert.h> |
31 | ||
32 | #if defined(__GNUC__) | |
33 | ||
34 | #include <kern/assert.h> | |
35 | #include <kern/kern_types.h> | |
91447636 | 36 | #include <kern/processor.h> |
55e303ae | 37 | #include <pexpert/pexpert.h> |
1c79356b | 38 | |
91447636 A |
39 | |
40 | /* | |
41 | * Data structures referenced (anonymously) from per-cpu data: | |
42 | */ | |
43 | struct cpu_core; | |
44 | struct cpu_cons_buffer; | |
45 | struct mp_desc_table; | |
46 | ||
47 | ||
48 | /* | |
49 | * Data structures embedded in per-cpu data: | |
50 | */ | |
51 | typedef struct rtclock_timer { | |
52 | uint64_t deadline; | |
53 | boolean_t is_set; | |
54 | boolean_t has_expired; | |
55 | } rtclock_timer_t; | |
56 | ||
57 | typedef struct { | |
58 | uint64_t rnt_tsc; /* timestamp */ | |
59 | uint64_t rnt_nanos; /* nanoseconds */ | |
60 | uint32_t rnt_scale; /* tsc -> nanosec multiplier */ | |
61 | uint32_t rnt_shift; /* tsc -> nanosec shift/div */ | |
62 | uint64_t rnt_step_tsc; /* tsc when scale applied */ | |
63 | uint64_t rnt_step_nanos; /* ns when scale applied */ | |
64 | } rtc_nanotime_t; | |
65 | ||
66 | typedef struct { | |
67 | struct i386_tss *cdi_ktss; | |
68 | #if MACH_KDB | |
69 | struct i386_tss *cdi_dbtss; | |
70 | #endif /* MACH_KDB */ | |
71 | struct fake_descriptor *cdi_gdt; | |
72 | struct fake_descriptor *cdi_idt; | |
73 | struct fake_descriptor *cdi_ldt; | |
74 | } cpu_desc_index_t; | |
75 | ||
76 | ||
77 | /* | |
78 | * Per-cpu data. | |
79 | * | |
80 | * Each processor has a per-cpu data area which is dereferenced through the | |
81 | * current_cpu_datap() macro. For speed, the %gs segment is based here, and | |
82 | * using this, inlines provides single-instruction access to frequently used | |
83 | * members - such as get_cpu_number()/cpu_number(), and get_active_thread()/ | |
84 | * current_thread(). | |
85 | * | |
86 | * Cpu data owned by another processor can be accessed using the | |
87 | * cpu_datap(cpu_number) macro which uses the cpu_data_ptr[] array of per-cpu | |
88 | * pointers. | |
89 | */ | |
90 | typedef struct cpu_data | |
91 | { | |
92 | struct cpu_data *cpu_this; /* pointer to myself */ | |
93 | thread_t cpu_active_thread; | |
94 | thread_t cpu_active_kloaded; | |
95 | vm_offset_t cpu_active_stack; | |
96 | vm_offset_t cpu_kernel_stack; | |
97 | vm_offset_t cpu_int_stack_top; | |
98 | int cpu_preemption_level; | |
99 | int cpu_simple_lock_count; | |
100 | int cpu_interrupt_level; | |
101 | int cpu_number; /* Logical CPU */ | |
102 | int cpu_phys_number; /* Physical CPU */ | |
103 | cpu_id_t cpu_id; /* Platform Expert */ | |
104 | int cpu_signals; /* IPI events */ | |
105 | int cpu_mcount_off; /* mcount recursion */ | |
106 | ast_t cpu_pending_ast; | |
107 | int cpu_type; | |
108 | int cpu_subtype; | |
109 | int cpu_threadtype; | |
110 | int cpu_running; | |
111 | struct cpu_core *cpu_core; /* cpu's parent core */ | |
112 | uint64_t cpu_rtc_tick_deadline; | |
113 | uint64_t cpu_rtc_intr_deadline; | |
114 | rtclock_timer_t cpu_rtc_timer; | |
115 | rtc_nanotime_t cpu_rtc_nanotime; | |
116 | void *cpu_console_buf; | |
117 | struct processor *cpu_processor; | |
118 | struct cpu_pmap *cpu_pmap; | |
119 | struct mp_desc_table *cpu_desc_tablep; | |
120 | cpu_desc_index_t cpu_desc_index; | |
121 | boolean_t cpu_iflag; | |
122 | #ifdef MACH_KDB | |
123 | /* XXX Untested: */ | |
124 | int cpu_db_pass_thru; | |
125 | vm_offset_t cpu_db_stacks; | |
126 | struct i386_saved_state *cpu_kdb_saved_state; | |
127 | spl_t cpu_kdb_saved_ipl; | |
128 | int cpu_kdb_is_slave; | |
129 | int cpu_kdb_active; | |
130 | #endif /* MACH_KDB */ | |
131 | int cpu_reserved1; | |
55e303ae | 132 | } cpu_data_t; |
1c79356b | 133 | |
91447636 A |
134 | extern cpu_data_t *cpu_data_ptr[]; |
135 | extern cpu_data_t cpu_data_master; | |
9bccf70c | 136 | |
55e303ae A |
137 | /* Macro to generate inline bodies to retrieve per-cpu data fields. */ |
138 | #define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | |
91447636 | 139 | #define CPU_DATA_GET(member,type) \ |
55e303ae A |
140 | type ret; \ |
141 | __asm__ volatile ("movl %%gs:%P1,%0" \ | |
142 | : "=r" (ret) \ | |
91447636 | 143 | : "i" (offsetof(cpu_data_t,member))); \ |
55e303ae | 144 | return ret; |
9bccf70c | 145 | |
1c79356b A |
146 | /* |
147 | * Everyone within the osfmk part of the kernel can use the fast | |
148 | * inline versions of these routines. Everyone outside, must call | |
149 | * the real thing, | |
150 | */ | |
91447636 A |
151 | static inline thread_t |
152 | get_active_thread(void) | |
1c79356b | 153 | { |
91447636 | 154 | CPU_DATA_GET(cpu_active_thread,thread_t) |
1c79356b | 155 | } |
91447636 A |
156 | #define current_thread_fast() get_active_thread() |
157 | #define current_thread() current_thread_fast() | |
1c79356b | 158 | |
91447636 A |
159 | static inline int |
160 | get_preemption_level(void) | |
1c79356b | 161 | { |
91447636 | 162 | CPU_DATA_GET(cpu_preemption_level,int) |
55e303ae | 163 | } |
91447636 A |
164 | static inline int |
165 | get_simple_lock_count(void) | |
55e303ae | 166 | { |
91447636 | 167 | CPU_DATA_GET(cpu_simple_lock_count,int) |
55e303ae | 168 | } |
91447636 A |
169 | static inline int |
170 | get_interrupt_level(void) | |
55e303ae | 171 | { |
91447636 | 172 | CPU_DATA_GET(cpu_interrupt_level,int) |
55e303ae | 173 | } |
91447636 A |
174 | static inline int |
175 | get_cpu_number(void) | |
55e303ae A |
176 | { |
177 | CPU_DATA_GET(cpu_number,int) | |
178 | } | |
91447636 A |
179 | static inline int |
180 | get_cpu_phys_number(void) | |
55e303ae A |
181 | { |
182 | CPU_DATA_GET(cpu_phys_number,int) | |
1c79356b | 183 | } |
91447636 A |
184 | static inline struct |
185 | cpu_core * get_cpu_core(void) | |
1c79356b | 186 | { |
91447636 | 187 | CPU_DATA_GET(cpu_core,struct cpu_core *) |
1c79356b A |
188 | } |
189 | ||
91447636 A |
190 | static inline void |
191 | disable_preemption(void) | |
1c79356b | 192 | { |
91447636 A |
193 | __asm__ volatile ("incl %%gs:%P0" |
194 | : | |
195 | : "i" (offsetof(cpu_data_t, cpu_preemption_level))); | |
196 | } | |
1c79356b | 197 | |
91447636 A |
198 | static inline void |
199 | enable_preemption(void) | |
200 | { | |
55e303ae A |
201 | assert(get_preemption_level() > 0); |
202 | ||
91447636 A |
203 | __asm__ volatile ("decl %%gs:%P0 \n\t" |
204 | "jne 1f \n\t" | |
205 | "call _kernel_preempt_check \n\t" | |
206 | "1:" | |
1c79356b | 207 | : /* no outputs */ |
91447636 A |
208 | : "i" (offsetof(cpu_data_t, cpu_preemption_level)) |
209 | : "eax", "ecx", "edx", "cc", "memory"); | |
1c79356b A |
210 | } |
211 | ||
91447636 A |
212 | static inline void |
213 | enable_preemption_no_check(void) | |
1c79356b | 214 | { |
1c79356b | 215 | assert(get_preemption_level() > 0); |
1c79356b | 216 | |
91447636 | 217 | __asm__ volatile ("decl %%gs:%P0" |
1c79356b | 218 | : /* no outputs */ |
91447636 | 219 | : "i" (offsetof(cpu_data_t, cpu_preemption_level)) |
1c79356b | 220 | : "cc", "memory"); |
1c79356b A |
221 | } |
222 | ||
91447636 A |
223 | static inline void |
224 | mp_disable_preemption(void) | |
1c79356b | 225 | { |
1c79356b | 226 | disable_preemption(); |
1c79356b A |
227 | } |
228 | ||
91447636 A |
229 | static inline void |
230 | mp_enable_preemption(void) | |
1c79356b | 231 | { |
1c79356b | 232 | enable_preemption(); |
1c79356b A |
233 | } |
234 | ||
91447636 A |
235 | static inline void |
236 | mp_enable_preemption_no_check(void) | |
1c79356b | 237 | { |
1c79356b | 238 | enable_preemption_no_check(); |
1c79356b A |
239 | } |
240 | ||
91447636 A |
241 | static inline cpu_data_t * |
242 | current_cpu_datap(void) | |
243 | { | |
244 | CPU_DATA_GET(cpu_this, cpu_data_t *); | |
245 | } | |
246 | ||
247 | static inline cpu_data_t * | |
248 | cpu_datap(int cpu) | |
249 | { | |
250 | assert(cpu_data_ptr[cpu]); | |
251 | return cpu_data_ptr[cpu]; | |
252 | } | |
253 | ||
254 | extern cpu_data_t *cpu_data_alloc(boolean_t is_boot_cpu); | |
1c79356b A |
255 | |
256 | #else /* !defined(__GNUC__) */ | |
257 | ||
258 | #endif /* defined(__GNUC__) */ | |
259 | ||
260 | #endif /* I386_CPU_DATA */ |