]>
Commit | Line | Data |
---|---|---|
1f2f436a A |
1 | /* |
2 | * Copyright (c) 2003-2010 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 | #if defined(__i386__) || defined(__x86_64__) | |
30 | ||
31 | #ifndef _I386_PLATFUNC_H | |
32 | #define _I386_PLATFUNC_H | |
33 | ||
34 | #ifndef __ASSEMBLER__ | |
35 | #include <stdint.h> | |
36 | #endif /* __ASSEMBLER__ */ | |
37 | ||
38 | // This is a shared macro which calls PLATFUNC_VARIANT_NAME which has different | |
39 | // implementations in __ASSEMBLER__ and !__ASSEMBLER__ | |
40 | #define PLATFUNC_DESCRIPTOR_NAME(name, variant) \ | |
41 | PLATFUNC_VARIANT_NAME(platfunc_ ## name, variant) | |
42 | ||
43 | #ifdef __ASSEMBLER__ | |
44 | ||
45 | /* When trying to acquire a spinlock or mutex, we will spin in | |
46 | * user mode for awhile, before entering the kernel to relinquish. | |
47 | * MP_SPIN_TRIES is the initial value of _COMM_PAGE_SPIN_COUNT. | |
48 | * The idea is that _COMM_PAGE_SPIN_COUNT will be adjusted up or | |
49 | * down as the machine is plugged in/out, etc. | |
50 | * At present spinlocks do not use _COMM_PAGE_SPIN_COUNT. | |
51 | * They use MP_SPIN_TRIES directly. | |
52 | */ | |
53 | #define MP_SPIN_TRIES 1000 | |
54 | ||
55 | #define PLATFUNC_VARIANT_NAME(name, variant) _ ## name ## $VARIANT$ ## variant | |
56 | ||
57 | #if defined (__i386__) | |
58 | #define PLATFUNC_DESCRIPTOR_FIELD_POINTER .long | |
59 | #define PLATFUNC_DESCRIPTOR_REFERENCE(name, variant) \ | |
60 | .long PLATFUNC_DESCRIPTOR_NAME(name, variant) | |
61 | #elif defined (__x86_64__) | |
62 | #define PLATFUNC_DESCRIPTOR_FIELD_POINTER .quad | |
63 | #define PLATFUNC_DESCRIPTOR_REFERENCE(name, variant) \ | |
64 | .quad PLATFUNC_DESCRIPTOR_NAME(name, variant) | |
65 | #else | |
66 | #error unsupported architecture | |
67 | #endif | |
68 | ||
69 | #ifdef VARIANT_DYLD | |
70 | ||
71 | #define PLATFUNC_FUNCTION_START_GENERIC(name, variant, codetype, alignment) \ | |
72 | PLATFUNC_FUNCTION_START(name, variant, codetype, alignment) \ | |
73 | .globl _ ## name ;\ | |
74 | _ ## name ## : | |
75 | ||
76 | #define PLATFUNC_DESCRIPTOR(name, variant, must, cant) | |
77 | ||
78 | #else /* VARIANT_DYLD */ | |
79 | ||
80 | #define PLATFUNC_FUNCTION_START_GENERIC PLATFUNC_FUNCTION_START | |
81 | ||
82 | #define PLATFUNC_DESCRIPTOR(name, variant, must, cant) \ | |
83 | .const_data ;\ | |
84 | .private_extern PLATFUNC_DESCRIPTOR_NAME(name, variant) ;\ | |
85 | PLATFUNC_DESCRIPTOR_NAME(name, variant) ## : ;\ | |
86 | PLATFUNC_DESCRIPTOR_FIELD_POINTER PLATFUNC_VARIANT_NAME(name, variant) ;\ | |
87 | .long must ;\ | |
88 | .long cant ;\ | |
89 | .text | |
90 | ||
91 | #endif /* VARIANT_DYLD */ | |
92 | ||
93 | #define PLATFUNC_FUNCTION_START(name, variant, codetype, alignment) \ | |
94 | .text ;\ | |
95 | .align alignment, 0x90 ;\ | |
96 | .private_extern PLATFUNC_VARIANT_NAME(name, variant) ;\ | |
97 | PLATFUNC_VARIANT_NAME(name, variant) ## : | |
98 | ||
99 | #else /* __ASSEMBLER__ */ | |
100 | ||
101 | #define PLATFUNC_VARIANT_NAME(name, variant) name ## $VARIANT$ ## variant | |
102 | #define PLATFUNC_DESCRIPTOR_PROTOTYPE(name, variant) extern const platfunc_descriptor PLATFUNC_DESCRIPTOR_NAME(name, variant); | |
103 | #define PLATFUNC_DESCRIPTOR_REFERENCE(name, variant) &PLATFUNC_DESCRIPTOR_NAME(name, variant) | |
104 | ||
105 | #define PLATFUNC_DESCRIPTOR(name, variant, must, cant) \ | |
106 | extern void PLATFUNC_VARIANT_NAME(name, variant) (void); \ | |
107 | const platfunc_descriptor PLATFUNC_DESCRIPTOR_NAME(name, variant) = { \ | |
108 | .address = PLATFUNC_VARIANT_NAME(name, variant), \ | |
109 | .musthave = must, \ | |
110 | .canthave = cant \ | |
111 | } | |
112 | ||
113 | /* | |
114 | * Each potential platfunc routine is described by one of these. | |
115 | * Note that the PLATFUNC_DESCRIPTOR macro (above), used in | |
116 | * assembly language, must agree with this. | |
117 | */ | |
118 | ||
119 | typedef struct platfunc_descriptor { | |
120 | void *address; // address of code | |
121 | uint32_t musthave; // _cpu_capability bits we must have | |
122 | uint32_t canthave; // _cpu_capability bits we can't have | |
123 | } platfunc_descriptor; | |
124 | ||
125 | void *find_platform_function(const platfunc_descriptor *descriptors[]); | |
126 | ||
127 | #endif /* __ASSEMBLER__ */ | |
128 | ||
129 | #endif /* _I386_PLATFUNC_H */ | |
130 | ||
131 | #endif /* __i386__ || __x86_64__ */ |