1 | #ifndef _ASM_IA64_XEN_PRIVOP_H |
---|
2 | #define _ASM_IA64_XEN_PRIVOP_H |
---|
3 | |
---|
4 | /* |
---|
5 | * Copyright (C) 2005 Hewlett-Packard Co |
---|
6 | * Dan Magenheimer <dan.magenheimer@hp.com> |
---|
7 | * |
---|
8 | * Paravirtualizations of privileged operations for Xen/ia64 |
---|
9 | * |
---|
10 | */ |
---|
11 | |
---|
12 | |
---|
13 | #include <xen/interface/arch-ia64.h> |
---|
14 | |
---|
15 | #define IA64_PARAVIRTUALIZED |
---|
16 | |
---|
17 | /* At 1 MB, before per-cpu space but still addressable using addl instead |
---|
18 | of movl. */ |
---|
19 | #define XSI_BASE 0xfffffffffff00000 |
---|
20 | |
---|
21 | /* Address of mapped regs. */ |
---|
22 | #define XMAPPEDREGS_BASE (XSI_BASE + XSI_SIZE) |
---|
23 | |
---|
24 | #ifdef __ASSEMBLY__ |
---|
25 | #define XEN_HYPER_RFI break HYPERPRIVOP_RFI |
---|
26 | #define XEN_HYPER_RSM_PSR_DT break HYPERPRIVOP_RSM_DT |
---|
27 | #define XEN_HYPER_SSM_PSR_DT break HYPERPRIVOP_SSM_DT |
---|
28 | #define XEN_HYPER_COVER break HYPERPRIVOP_COVER |
---|
29 | #define XEN_HYPER_ITC_D break HYPERPRIVOP_ITC_D |
---|
30 | #define XEN_HYPER_ITC_I break HYPERPRIVOP_ITC_I |
---|
31 | #define XEN_HYPER_SSM_I break HYPERPRIVOP_SSM_I |
---|
32 | #define XEN_HYPER_GET_IVR break HYPERPRIVOP_GET_IVR |
---|
33 | #define XEN_HYPER_GET_TPR break HYPERPRIVOP_GET_TPR |
---|
34 | #define XEN_HYPER_SET_TPR break HYPERPRIVOP_SET_TPR |
---|
35 | #define XEN_HYPER_EOI break HYPERPRIVOP_EOI |
---|
36 | #define XEN_HYPER_SET_ITM break HYPERPRIVOP_SET_ITM |
---|
37 | #define XEN_HYPER_THASH break HYPERPRIVOP_THASH |
---|
38 | #define XEN_HYPER_PTC_GA break HYPERPRIVOP_PTC_GA |
---|
39 | #define XEN_HYPER_ITR_D break HYPERPRIVOP_ITR_D |
---|
40 | #define XEN_HYPER_GET_RR break HYPERPRIVOP_GET_RR |
---|
41 | #define XEN_HYPER_SET_RR break HYPERPRIVOP_SET_RR |
---|
42 | #define XEN_HYPER_SET_KR break HYPERPRIVOP_SET_KR |
---|
43 | #define XEN_HYPER_FC break HYPERPRIVOP_FC |
---|
44 | #define XEN_HYPER_GET_CPUID break HYPERPRIVOP_GET_CPUID |
---|
45 | #define XEN_HYPER_GET_PMD break HYPERPRIVOP_GET_PMD |
---|
46 | #define XEN_HYPER_GET_EFLAG break HYPERPRIVOP_GET_EFLAG |
---|
47 | #define XEN_HYPER_SET_EFLAG break HYPERPRIVOP_SET_EFLAG |
---|
48 | #define XEN_HYPER_GET_PSR break HYPERPRIVOP_GET_PSR |
---|
49 | |
---|
50 | #define XSI_IFS (XSI_BASE + XSI_IFS_OFS) |
---|
51 | #define XSI_PRECOVER_IFS (XSI_BASE + XSI_PRECOVER_IFS_OFS) |
---|
52 | #define XSI_IFA (XSI_BASE + XSI_IFA_OFS) |
---|
53 | #define XSI_ISR (XSI_BASE + XSI_ISR_OFS) |
---|
54 | #define XSI_IIM (XSI_BASE + XSI_IIM_OFS) |
---|
55 | #define XSI_ITIR (XSI_BASE + XSI_ITIR_OFS) |
---|
56 | #define XSI_PSR_I_ADDR (XSI_BASE + XSI_PSR_I_ADDR_OFS) |
---|
57 | #define XSI_PSR_IC (XSI_BASE + XSI_PSR_IC_OFS) |
---|
58 | #define XSI_IPSR (XSI_BASE + XSI_IPSR_OFS) |
---|
59 | #define XSI_IIP (XSI_BASE + XSI_IIP_OFS) |
---|
60 | #define XSI_B1NAT (XSI_BASE + XSI_B1NATS_OFS) |
---|
61 | #define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS) |
---|
62 | #define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS) |
---|
63 | #define XSI_IHA (XSI_BASE + XSI_IHA_OFS) |
---|
64 | #endif |
---|
65 | |
---|
66 | #ifndef __ASSEMBLY__ |
---|
67 | #define XEN_HYPER_SSM_I asm("break %0" : : "i" (HYPERPRIVOP_SSM_I)) |
---|
68 | #define XEN_HYPER_GET_IVR asm("break %0" : : "i" (HYPERPRIVOP_GET_IVR)) |
---|
69 | |
---|
70 | /************************************************/ |
---|
71 | /* Instructions paravirtualized for correctness */ |
---|
72 | /************************************************/ |
---|
73 | |
---|
74 | /* "fc" and "thash" are privilege-sensitive instructions, meaning they |
---|
75 | * may have different semantics depending on whether they are executed |
---|
76 | * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't |
---|
77 | * be allowed to execute directly, lest incorrect semantics result. */ |
---|
78 | extern unsigned long xen_fc(unsigned long addr); |
---|
79 | #define ia64_fc(addr) xen_fc((unsigned long)(addr)) |
---|
80 | extern unsigned long xen_thash(unsigned long addr); |
---|
81 | #define ia64_thash(addr) xen_thash((unsigned long)(addr)) |
---|
82 | /* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" |
---|
83 | * is not currently used (though it may be in a long-format VHPT system!) |
---|
84 | * and the semantics of cover only change if psr.ic is off which is very |
---|
85 | * rare (and currently non-existent outside of assembly code */ |
---|
86 | |
---|
87 | /* There are also privilege-sensitive registers. These registers are |
---|
88 | * readable at any privilege level but only writable at PL0. */ |
---|
89 | extern unsigned long xen_get_cpuid(int index); |
---|
90 | #define ia64_get_cpuid(i) xen_get_cpuid(i) |
---|
91 | extern unsigned long xen_get_pmd(int index); |
---|
92 | #define ia64_get_pmd(i) xen_get_pmd(i) |
---|
93 | extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */ |
---|
94 | extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */ |
---|
95 | |
---|
96 | /************************************************/ |
---|
97 | /* Instructions paravirtualized for performance */ |
---|
98 | /************************************************/ |
---|
99 | |
---|
100 | /* Xen uses memory-mapped virtual privileged registers for access to many |
---|
101 | * performance-sensitive privileged registers. Some, like the processor |
---|
102 | * status register (psr), are broken up into multiple memory locations. |
---|
103 | * Others, like "pend", are abstractions based on privileged registers. |
---|
104 | * "Pend" is guaranteed to be set if reading cr.ivr would return a |
---|
105 | * (non-spurious) interrupt. */ |
---|
106 | #define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE) |
---|
107 | #define XSI_PSR_I \ |
---|
108 | (*XEN_MAPPEDREGS->interrupt_mask_addr) |
---|
109 | #define xen_get_virtual_psr_i() \ |
---|
110 | (!XSI_PSR_I) |
---|
111 | #define xen_set_virtual_psr_i(_val) \ |
---|
112 | ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; }) |
---|
113 | #define xen_set_virtual_psr_ic(_val) \ |
---|
114 | ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; }) |
---|
115 | #define xen_get_virtual_pend() \ |
---|
116 | (*(((uint8_t *)XEN_MAPPEDREGS->interrupt_mask_addr) - 1)) |
---|
117 | |
---|
118 | /* Hyperprivops are "break" instructions with a well-defined API. |
---|
119 | * In particular, the virtual psr.ic bit must be off; in this way |
---|
120 | * it is guaranteed to never conflict with a linux break instruction. |
---|
121 | * Normally, this is done in a xen stub but this one is frequent enough |
---|
122 | * that we inline it */ |
---|
123 | #define xen_hyper_ssm_i() \ |
---|
124 | ({ \ |
---|
125 | XEN_HYPER_SSM_I; \ |
---|
126 | }) |
---|
127 | |
---|
128 | /* turning off interrupts can be paravirtualized simply by writing |
---|
129 | * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */ |
---|
130 | #define xen_rsm_i() xen_set_virtual_psr_i(0) |
---|
131 | |
---|
132 | /* turning on interrupts is a bit more complicated.. write to the |
---|
133 | * memory-mapped virtual psr.i bit first (to avoid race condition), |
---|
134 | * then if any interrupts were pending, we have to execute a hyperprivop |
---|
135 | * to ensure the pending interrupt gets delivered; else we're done! */ |
---|
136 | #define xen_ssm_i() \ |
---|
137 | ({ \ |
---|
138 | int old = xen_get_virtual_psr_i(); \ |
---|
139 | if (!old) { \ |
---|
140 | if (xen_get_virtual_pend()) \ |
---|
141 | xen_hyper_ssm_i(); \ |
---|
142 | else \ |
---|
143 | xen_set_virtual_psr_i(1); \ |
---|
144 | } \ |
---|
145 | }) |
---|
146 | |
---|
147 | #define xen_ia64_intrin_local_irq_restore(x) \ |
---|
148 | { \ |
---|
149 | if (is_running_on_xen()) { \ |
---|
150 | if ((x) & IA64_PSR_I) { xen_ssm_i(); } \ |
---|
151 | else { xen_rsm_i(); } \ |
---|
152 | } \ |
---|
153 | else __ia64_intrin_local_irq_restore((x)); \ |
---|
154 | } |
---|
155 | |
---|
156 | #define xen_get_psr_i() \ |
---|
157 | ( \ |
---|
158 | (is_running_on_xen()) ? \ |
---|
159 | (xen_get_virtual_psr_i() ? IA64_PSR_I : 0) \ |
---|
160 | : __ia64_get_psr_i() \ |
---|
161 | ) |
---|
162 | |
---|
163 | #define xen_ia64_ssm(mask) \ |
---|
164 | { \ |
---|
165 | if ((mask)==IA64_PSR_I) { \ |
---|
166 | if (is_running_on_xen()) { xen_ssm_i(); } \ |
---|
167 | else { __ia64_ssm(mask); } \ |
---|
168 | } \ |
---|
169 | else { __ia64_ssm(mask); } \ |
---|
170 | } |
---|
171 | |
---|
172 | #define xen_ia64_rsm(mask) \ |
---|
173 | { \ |
---|
174 | if ((mask)==IA64_PSR_I) { \ |
---|
175 | if (is_running_on_xen()) { xen_rsm_i(); } \ |
---|
176 | else { __ia64_rsm(mask); } \ |
---|
177 | } \ |
---|
178 | else { __ia64_rsm(mask); } \ |
---|
179 | } |
---|
180 | |
---|
181 | |
---|
182 | /* Although all privileged operations can be left to trap and will |
---|
183 | * be properly handled by Xen, some are frequent enough that we use |
---|
184 | * hyperprivops for performance. */ |
---|
185 | |
---|
186 | extern unsigned long xen_get_psr(void); |
---|
187 | extern unsigned long xen_get_ivr(void); |
---|
188 | extern unsigned long xen_get_tpr(void); |
---|
189 | extern void xen_set_itm(unsigned long); |
---|
190 | extern void xen_set_tpr(unsigned long); |
---|
191 | extern void xen_eoi(void); |
---|
192 | extern void xen_set_rr(unsigned long index, unsigned long val); |
---|
193 | extern unsigned long xen_get_rr(unsigned long index); |
---|
194 | extern void xen_set_kr(unsigned long index, unsigned long val); |
---|
195 | extern void xen_ptcga(unsigned long addr, unsigned long size); |
---|
196 | |
---|
197 | /* Note: It may look wrong to test for is_running_on_xen() in each case. |
---|
198 | * However regnum is always a constant so, as written, the compiler |
---|
199 | * eliminates the switch statement, whereas is_running_on_xen() must be |
---|
200 | * tested dynamically. */ |
---|
201 | #define xen_ia64_getreg(regnum) \ |
---|
202 | ({ \ |
---|
203 | __u64 ia64_intri_res; \ |
---|
204 | \ |
---|
205 | switch(regnum) { \ |
---|
206 | case _IA64_REG_PSR: \ |
---|
207 | ia64_intri_res = (is_running_on_xen()) ? \ |
---|
208 | xen_get_psr() : \ |
---|
209 | __ia64_getreg(regnum); \ |
---|
210 | break; \ |
---|
211 | case _IA64_REG_CR_IVR: \ |
---|
212 | ia64_intri_res = (is_running_on_xen()) ? \ |
---|
213 | xen_get_ivr() : \ |
---|
214 | __ia64_getreg(regnum); \ |
---|
215 | break; \ |
---|
216 | case _IA64_REG_CR_TPR: \ |
---|
217 | ia64_intri_res = (is_running_on_xen()) ? \ |
---|
218 | xen_get_tpr() : \ |
---|
219 | __ia64_getreg(regnum); \ |
---|
220 | break; \ |
---|
221 | case _IA64_REG_AR_EFLAG: \ |
---|
222 | ia64_intri_res = (is_running_on_xen()) ? \ |
---|
223 | xen_get_eflag() : \ |
---|
224 | __ia64_getreg(regnum); \ |
---|
225 | break; \ |
---|
226 | default: \ |
---|
227 | ia64_intri_res = __ia64_getreg(regnum); \ |
---|
228 | break; \ |
---|
229 | } \ |
---|
230 | ia64_intri_res; \ |
---|
231 | }) |
---|
232 | |
---|
233 | #define xen_ia64_setreg(regnum,val) \ |
---|
234 | ({ \ |
---|
235 | switch(regnum) { \ |
---|
236 | case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: \ |
---|
237 | (is_running_on_xen()) ? \ |
---|
238 | xen_set_kr((regnum-_IA64_REG_AR_KR0), val) : \ |
---|
239 | __ia64_setreg(regnum,val); \ |
---|
240 | break; \ |
---|
241 | case _IA64_REG_CR_ITM: \ |
---|
242 | (is_running_on_xen()) ? \ |
---|
243 | xen_set_itm(val) : \ |
---|
244 | __ia64_setreg(regnum,val); \ |
---|
245 | break; \ |
---|
246 | case _IA64_REG_CR_TPR: \ |
---|
247 | (is_running_on_xen()) ? \ |
---|
248 | xen_set_tpr(val) : \ |
---|
249 | __ia64_setreg(regnum,val); \ |
---|
250 | break; \ |
---|
251 | case _IA64_REG_CR_EOI: \ |
---|
252 | (is_running_on_xen()) ? \ |
---|
253 | xen_eoi() : \ |
---|
254 | __ia64_setreg(regnum,val); \ |
---|
255 | break; \ |
---|
256 | case _IA64_REG_AR_EFLAG: \ |
---|
257 | (is_running_on_xen()) ? \ |
---|
258 | xen_set_eflag(val) : \ |
---|
259 | __ia64_setreg(regnum,val); \ |
---|
260 | break; \ |
---|
261 | default: \ |
---|
262 | __ia64_setreg(regnum,val); \ |
---|
263 | break; \ |
---|
264 | } \ |
---|
265 | }) |
---|
266 | |
---|
267 | #define ia64_ssm xen_ia64_ssm |
---|
268 | #define ia64_rsm xen_ia64_rsm |
---|
269 | #define ia64_intrin_local_irq_restore xen_ia64_intrin_local_irq_restore |
---|
270 | #define ia64_ptcga xen_ptcga |
---|
271 | #define ia64_set_rr(index,val) xen_set_rr(index,val) |
---|
272 | #define ia64_get_rr(index) xen_get_rr(index) |
---|
273 | #define ia64_getreg xen_ia64_getreg |
---|
274 | #define ia64_setreg xen_ia64_setreg |
---|
275 | #define ia64_get_psr_i xen_get_psr_i |
---|
276 | |
---|
277 | /* the remainder of these are not performance-sensitive so its |
---|
278 | * OK to not paravirtualize and just take a privop trap and emulate */ |
---|
279 | #define ia64_hint __ia64_hint |
---|
280 | #define ia64_set_pmd __ia64_set_pmd |
---|
281 | #define ia64_itci __ia64_itci |
---|
282 | #define ia64_itcd __ia64_itcd |
---|
283 | #define ia64_itri __ia64_itri |
---|
284 | #define ia64_itrd __ia64_itrd |
---|
285 | #define ia64_tpa __ia64_tpa |
---|
286 | #define ia64_set_ibr __ia64_set_ibr |
---|
287 | #define ia64_set_pkr __ia64_set_pkr |
---|
288 | #define ia64_set_pmc __ia64_set_pmc |
---|
289 | #define ia64_get_ibr __ia64_get_ibr |
---|
290 | #define ia64_get_pkr __ia64_get_pkr |
---|
291 | #define ia64_get_pmc __ia64_get_pmc |
---|
292 | #define ia64_ptce __ia64_ptce |
---|
293 | #define ia64_ptcl __ia64_ptcl |
---|
294 | #define ia64_ptri __ia64_ptri |
---|
295 | #define ia64_ptrd __ia64_ptrd |
---|
296 | |
---|
297 | #endif /* !__ASSEMBLY__ */ |
---|
298 | |
---|
299 | /* these routines utilize privilege-sensitive or performance-sensitive |
---|
300 | * privileged instructions so the code must be replaced with |
---|
301 | * paravirtualized versions */ |
---|
302 | #define ia64_pal_halt_light xen_pal_halt_light |
---|
303 | #define ia64_leave_kernel xen_leave_kernel |
---|
304 | #define ia64_leave_syscall xen_leave_syscall |
---|
305 | #define ia64_trace_syscall xen_trace_syscall |
---|
306 | #define ia64_ret_from_clone xen_ret_from_clone |
---|
307 | #define ia64_switch_to xen_switch_to |
---|
308 | #define ia64_pal_call_static xen_pal_call_static |
---|
309 | |
---|
310 | #endif /* _ASM_IA64_XEN_PRIVOP_H */ |
---|