]>
Commit | Line | Data |
---|---|---|
43866e37 | 1 | /* |
b0d623f7 | 2 | * Copyright (c) 2003-2009 Apple Inc. All rights reserved. |
43866e37 | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
43866e37 | 5 | * |
2d21ac55 A |
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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
43866e37 A |
27 | */ |
28 | ||
29 | #ifndef _I386_COMMPAGE_H | |
30 | #define _I386_COMMPAGE_H | |
31 | ||
55e303ae A |
32 | #ifndef __ASSEMBLER__ |
33 | #include <stdint.h> | |
b0d623f7 A |
34 | #include <mach/boolean.h> |
35 | #include <mach/vm_types.h> | |
36 | #include <machine/cpu_capabilities.h> | |
55e303ae A |
37 | #endif /* __ASSEMBLER__ */ |
38 | ||
b0d623f7 A |
39 | /* When trying to acquire a spinlock or mutex, we will spin in |
40 | * user mode for awhile, before entering the kernel to relinquish. | |
41 | * MP_SPIN_TRIES is the initial value of _COMM_PAGE_SPIN_COUNT. | |
42 | * The idea is that _COMM_PAGE_SPIN_COUNT will be adjusted up or | |
43 | * down as the machine is plugged in/out, etc. | |
44 | * At present spinlocks do not use _COMM_PAGE_SPIN_COUNT. | |
45 | * They use MP_SPIN_TRIES directly. | |
46 | */ | |
47 | #define MP_SPIN_TRIES 1000 | |
48 | ||
49 | ||
0c530ab8 A |
50 | /* The following macro is used to generate the 64-bit commpage address for a given |
51 | * routine, based on its 32-bit address. This is used in the kernel to compile | |
b0d623f7 | 52 | * the 64-bit commpage. Since the kernel can be a 32-bit object, cpu_capabilities.h |
0c530ab8 A |
53 | * only defines the 32-bit address. |
54 | */ | |
55 | #define _COMM_PAGE_32_TO_64( ADDRESS ) ( ADDRESS + _COMM_PAGE64_START_ADDRESS - _COMM_PAGE32_START_ADDRESS ) | |
56 | ||
57 | ||
55e303ae | 58 | #ifdef __ASSEMBLER__ |
55e303ae | 59 | |
b0d623f7 A |
60 | #define COMMPAGE_DESCRIPTOR_NAME(label) _commpage_ ## label |
61 | ||
62 | #if defined (__i386__) | |
63 | ||
64 | #define COMMPAGE_DESCRIPTOR_FIELD_POINTER .long | |
65 | #define COMMPAGE_DESCRIPTOR_REFERENCE(label) \ | |
66 | .long COMMPAGE_DESCRIPTOR_NAME(label) | |
67 | ||
68 | #elif defined (__x86_64__) | |
69 | ||
70 | #define COMMPAGE_DESCRIPTOR_FIELD_POINTER .quad | |
71 | #define COMMPAGE_DESCRIPTOR_REFERENCE(label) \ | |
72 | .quad COMMPAGE_DESCRIPTOR_NAME(label) | |
73 | ||
74 | #else | |
75 | #error unsupported architecture | |
76 | #endif | |
77 | ||
78 | #define COMMPAGE_FUNCTION_START(label,codetype,alignment) \ | |
79 | .text ;\ | |
80 | .code ## codetype ;\ | |
81 | .align alignment, 0x90 ;\ | |
82 | L ## label ## : | |
83 | ||
55e303ae | 84 | #define COMMPAGE_DESCRIPTOR(label,address,must,cant) \ |
b0d623f7 A |
85 | L ## label ## _end: ;\ |
86 | .set L ## label ## _size, L ## label ## _end - L ## label ;\ | |
87 | .const_data ;\ | |
88 | .private_extern COMMPAGE_DESCRIPTOR_NAME(label) ;\ | |
89 | COMMPAGE_DESCRIPTOR_NAME(label) ## : ;\ | |
90 | COMMPAGE_DESCRIPTOR_FIELD_POINTER L ## label ;\ | |
91 | .long L ## label ## _size ;\ | |
92 | .long address ;\ | |
93 | .long must ;\ | |
94 | .long cant ;\ | |
55e303ae A |
95 | .text |
96 | ||
b0d623f7 A |
97 | |
98 | /* COMMPAGE_CALL(target,from,start) | |
99 | * | |
100 | * This macro compiles a relative near call to one | |
101 | * commpage routine from another. | |
102 | * The assembler cannot handle this directly because the code | |
103 | * is not being assembled at the address at which it will execute. | |
104 | * The alternative to this macro would be to use an | |
105 | * indirect call, which is slower because the target of an | |
106 | * indirect branch is poorly predicted. | |
107 | * The macro arguments are: | |
108 | * target = the commpage routine we are calling | |
109 | * from = the commpage routine we are in now | |
110 | * start = the label at the start of the code for this func | |
111 | * This is admitedly ugly and fragile. Is there a better way? | |
112 | */ | |
113 | #define COMMPAGE_CALL(target,from,start) \ | |
114 | COMMPAGE_CALL_INTERNAL(target,from,start,__LINE__) | |
115 | ||
116 | #define COMMPAGE_CALL_INTERNAL(target,from,start,unique) \ | |
117 | .byte 0xe8 ;\ | |
118 | .set UNIQUEID(unique), L ## start - . + target - from - 4 ;\ | |
119 | .long UNIQUEID(unique) | |
120 | ||
121 | #define UNIQUEID(name) L ## name | |
122 | ||
55e303ae A |
123 | #else /* __ASSEMBLER__ */ |
124 | ||
125 | /* Each potential commpage routine is described by one of these. | |
126 | * Note that the COMMPAGE_DESCRIPTOR macro (above), used in | |
127 | * assembly language, must agree with this. | |
128 | */ | |
129 | ||
130 | typedef struct commpage_descriptor { | |
b0d623f7 A |
131 | void *code_address; // address of code |
132 | uint32_t code_length; // length in bytes | |
133 | uint32_t commpage_address; // put at this address (_COMM_PAGE_BCOPY etc) | |
134 | uint32_t musthave; // _cpu_capability bits we must have | |
135 | uint32_t canthave; // _cpu_capability bits we can't have | |
55e303ae A |
136 | } commpage_descriptor; |
137 | ||
138 | ||
2d21ac55 A |
139 | /* Warning: following structure must match the layout of the commpage. */ |
140 | /* This is the data starting at _COMM_PAGE_TIME_DATA_START, ie for nanotime() and gettimeofday() */ | |
141 | ||
142 | typedef volatile struct commpage_time_data { | |
143 | uint64_t nt_tsc_base; // _COMM_PAGE_NT_TSC_BASE | |
144 | uint32_t nt_scale; // _COMM_PAGE_NT_SCALE | |
145 | uint32_t nt_shift; // _COMM_PAGE_NT_SHIFT | |
146 | uint64_t nt_ns_base; // _COMM_PAGE_NT_NS_BASE | |
147 | uint32_t nt_generation; // _COMM_PAGE_NT_GENERATION | |
148 | uint32_t gtod_generation; // _COMM_PAGE_GTOD_GENERATION | |
149 | uint64_t gtod_ns_base; // _COMM_PAGE_GTOD_NS_BASE | |
150 | uint64_t gtod_sec_base; // _COMM_PAGE_GTOD_SEC_BASE | |
151 | } commpage_time_data; | |
152 | ||
153 | ||
0c530ab8 A |
154 | extern char *commPagePtr32; // virt address of 32-bit commpage in kernel map |
155 | extern char *commPagePtr64; // ...and of 64-bit commpage | |
156 | ||
2d21ac55 | 157 | extern void commpage_set_timestamp(uint64_t abstime, uint64_t secs); |
2d21ac55 | 158 | extern void commpage_disable_timestamp( void ); |
0c530ab8 | 159 | extern void commpage_set_nanotime(uint64_t tsc_base, uint64_t ns_base, uint32_t scale, uint32_t shift); |
b0d623f7 A |
160 | extern void commpage_set_memory_pressure(unsigned int pressure); |
161 | extern void commpage_set_spin_count(unsigned int count); | |
2d21ac55 | 162 | extern void commpage_sched_gen_inc(void); |
6d2010ae | 163 | extern void commpage_update_active_cpus(void); |
91447636 | 164 | |
b0d623f7 A |
165 | extern uint32_t commpage_is_in_pfz32(uint32_t); |
166 | extern uint32_t commpage_is_in_pfz64(addr64_t); | |
167 | ||
55e303ae | 168 | #endif /* __ASSEMBLER__ */ |
43866e37 A |
169 | |
170 | #endif /* _I386_COMMPAGE_H */ |