aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-06-25 00:19:28 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-08 07:15:52 -0400
commit2be29982a08009c731307f4a39053b70ac4700da (patch)
treef01fcf847f36b9da5cd87cefa7ee6c13d193077d /include
parentc7245da6ae7e5208504ff027c4e0eec69b788651 (diff)
x86/paravirt: add sysret/sysexit pvops for returning to 32-bit compatibility userspace
In a 64-bit system, we need separate sysret/sysexit operations to return to a 32-bit userspace. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citirx.com> Cc: xen-devel <xen-devel@lists.xensource.com> Cc: Stephen Tweedie <sct@redhat.com> Cc: Eduardo Habkost <ehabkost@redhat.com> Cc: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r--include/asm-x86/irqflags.h14
-rw-r--r--include/asm-x86/paravirt.h56
2 files changed, 56 insertions, 14 deletions
diff --git a/include/asm-x86/irqflags.h b/include/asm-x86/irqflags.h
index 544836c96b61..ea9bd2635d59 100644
--- a/include/asm-x86/irqflags.h
+++ b/include/asm-x86/irqflags.h
@@ -112,9 +112,17 @@ static inline unsigned long __raw_local_irq_save(void)
112 112
113#ifdef CONFIG_X86_64 113#ifdef CONFIG_X86_64
114#define INTERRUPT_RETURN iretq 114#define INTERRUPT_RETURN iretq
115#define USERGS_SYSRET \ 115#define USERGS_SYSRET64 \
116 swapgs; \ 116 swapgs; \
117 sysretq; 117 sysretq;
118#define USERGS_SYSRET32 \
119 swapgs; \
120 sysretl
121#define ENABLE_INTERRUPTS_SYSEXIT32 \
122 swapgs; \
123 sti; \
124 sysexit
125
118#else 126#else
119#define INTERRUPT_RETURN iret 127#define INTERRUPT_RETURN iret
120#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit 128#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index dad5b4186f51..33f72f8fe757 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -141,9 +141,32 @@ struct pv_cpu_ops {
141 u64 (*read_pmc)(int counter); 141 u64 (*read_pmc)(int counter);
142 unsigned long long (*read_tscp)(unsigned int *aux); 142 unsigned long long (*read_tscp)(unsigned int *aux);
143 143
144 /* These three are jmp to, not actually called. */ 144 /*
145 * Atomically enable interrupts and return to userspace. This
146 * is only ever used to return to 32-bit processes; in a
147 * 64-bit kernel, it's used for 32-on-64 compat processes, but
148 * never native 64-bit processes. (Jump, not call.)
149 */
145 void (*irq_enable_sysexit)(void); 150 void (*irq_enable_sysexit)(void);
146 void (*usergs_sysret)(void); 151
152 /*
153 * Switch to usermode gs and return to 64-bit usermode using
154 * sysret. Only used in 64-bit kernels to return to 64-bit
155 * processes. Usermode register state, including %rsp, must
156 * already be restored.
157 */
158 void (*usergs_sysret64)(void);
159
160 /*
161 * Switch to usermode gs and return to 32-bit usermode using
162 * sysret. Used to return to 32-on-64 compat processes.
163 * Other usermode register state, including %esp, must already
164 * be restored.
165 */
166 void (*usergs_sysret32)(void);
167
168 /* Normal iret. Jump to this with the standard iret stack
169 frame set up. */
147 void (*iret)(void); 170 void (*iret)(void);
148 171
149 void (*swapgs)(void); 172 void (*swapgs)(void);
@@ -1481,18 +1504,24 @@ static inline unsigned long __raw_local_irq_save(void)
1481 call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ 1504 call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \
1482 PV_RESTORE_REGS;) 1505 PV_RESTORE_REGS;)
1483 1506
1484#define ENABLE_INTERRUPTS_SYSEXIT \ 1507#define USERGS_SYSRET32 \
1485 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \ 1508 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \
1486 CLBR_NONE, \ 1509 CLBR_NONE, \
1487 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit)) 1510 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret32))
1488
1489 1511
1490#ifdef CONFIG_X86_32 1512#ifdef CONFIG_X86_32
1491#define GET_CR0_INTO_EAX \ 1513#define GET_CR0_INTO_EAX \
1492 push %ecx; push %edx; \ 1514 push %ecx; push %edx; \
1493 call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \ 1515 call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \
1494 pop %edx; pop %ecx 1516 pop %edx; pop %ecx
1495#else 1517
1518#define ENABLE_INTERRUPTS_SYSEXIT \
1519 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
1520 CLBR_NONE, \
1521 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
1522
1523
1524#else /* !CONFIG_X86_32 */
1496#define SWAPGS \ 1525#define SWAPGS \
1497 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ 1526 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \
1498 PV_SAVE_REGS; \ 1527 PV_SAVE_REGS; \
@@ -1505,11 +1534,16 @@ static inline unsigned long __raw_local_irq_save(void)
1505 movq %rax, %rcx; \ 1534 movq %rax, %rcx; \
1506 xorq %rax, %rax; 1535 xorq %rax, %rax;
1507 1536
1508#define USERGS_SYSRET \ 1537#define USERGS_SYSRET64 \
1509 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret), \ 1538 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \
1510 CLBR_NONE, \ 1539 CLBR_NONE, \
1511 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret)) 1540 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64))
1512#endif 1541
1542#define ENABLE_INTERRUPTS_SYSEXIT32 \
1543 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
1544 CLBR_NONE, \
1545 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
1546#endif /* CONFIG_X86_32 */
1513 1547
1514#endif /* __ASSEMBLY__ */ 1548#endif /* __ASSEMBLY__ */
1515#endif /* CONFIG_PARAVIRT */ 1549#endif /* CONFIG_PARAVIRT */