source: trunk/packages/xen-3.1/xen-3.1/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 10.9 KB
Line 
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. */
78extern unsigned long xen_fc(unsigned long addr);
79#define ia64_fc(addr)                   xen_fc((unsigned long)(addr))
80extern 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. */
89extern unsigned long xen_get_cpuid(int index);
90#define ia64_get_cpuid(i)               xen_get_cpuid(i)
91extern unsigned long xen_get_pmd(int index);
92#define ia64_get_pmd(i)                 xen_get_pmd(i)
93extern unsigned long xen_get_eflag(void);       /* see xen_ia64_getreg */
94extern 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
186extern unsigned long xen_get_psr(void);
187extern unsigned long xen_get_ivr(void);
188extern unsigned long xen_get_tpr(void);
189extern void xen_set_itm(unsigned long);
190extern void xen_set_tpr(unsigned long);
191extern void xen_eoi(void);
192extern void xen_set_rr(unsigned long index, unsigned long val);
193extern unsigned long xen_get_rr(unsigned long index);
194extern void xen_set_kr(unsigned long index, unsigned long val);
195extern 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 */
Note: See TracBrowser for help on using the repository browser.