mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
bitkeeper revision 1.1159.170.1 (418fbcfftbJRf270n_KReJDuXIouGg)
Rejig the layout of saved activations on Xen's stack. Touches a bunch of stuff but things are generally a bit cleaner now. Should be easier to integrate vm86 support, and I'm now ready to do bigger changes to the Xen->guest exit code.
This commit is contained in:
1 parent
31a94a2dd7
commit
6b75d294b5
10 files changed
+305
-315
No files matched your search
@@ -731,6 +731,7 @@
|
||||
3ddb79c3ezddh34MdelJpa5tNR00Dw xen/include/asm-x86/system.h
|
||||
3ddb79c4HugMq7IYGxcQKFBpKwKhzA xen/include/asm-x86/types.h
|
||||
40cf1596saFaHD5DC5zvrSn7CDCWGQ xen/include/asm-x86/uaccess.h
|
||||
418fbcfe_WliJPToeVM-9VStvym-hw xen/include/asm-x86/x86_32/asm_defns.h
|
||||
3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/include/asm-x86/x86_32/current.h
|
||||
3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/regs.h
|
||||
3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h
|
||||
|
||||
+15
-8
@@ -166,14 +166,25 @@ void show_stack(unsigned long *esp)
|
||||
void show_registers(struct xen_regs *regs)
|
||||
{
|
||||
unsigned long esp;
|
||||
unsigned short ss;
|
||||
unsigned short ss, ds, es, fs, gs;
|
||||
|
||||
esp = (unsigned long)(®s->esp);
|
||||
ss = __HYPERVISOR_DS;
|
||||
if ( regs->xcs & 3 )
|
||||
{
|
||||
esp = regs->esp;
|
||||
ss = regs->xss & 0xffff;
|
||||
ds = regs->xds & 0xffff;
|
||||
es = regs->xes & 0xffff;
|
||||
fs = regs->xfs & 0xffff;
|
||||
gs = regs->xgs & 0xffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
esp = (unsigned long)(®s->esp);
|
||||
ss = __HYPERVISOR_DS;
|
||||
ds = __HYPERVISOR_DS;
|
||||
es = __HYPERVISOR_DS;
|
||||
fs = __HYPERVISOR_DS;
|
||||
gs = __HYPERVISOR_DS;
|
||||
}
|
||||
|
||||
printk("CPU: %d\nEIP: %04x:[<%08lx>] \nEFLAGS: %08lx\n",
|
||||
@@ -183,8 +194,7 @@ void show_registers(struct xen_regs *regs)
|
||||
printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
|
||||
regs->esi, regs->edi, regs->ebp, esp);
|
||||
printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
|
||||
regs->xds & 0xffff, regs->xes & 0xffff,
|
||||
regs->xfs & 0xffff, regs->xgs & 0xffff, ss);
|
||||
ds, es, fs, gs, ss);
|
||||
|
||||
show_stack(®s->esp);
|
||||
}
|
||||
@@ -230,7 +240,6 @@ static inline void do_trap(int trapnr, char *str,
|
||||
{
|
||||
DPRINTK("Trap %d: %08lx -> %08lx\n", trapnr, regs->eip, fixup);
|
||||
regs->eip = fixup;
|
||||
regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -394,7 +403,6 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
|
||||
if ( !d->mm.shadow_mode )
|
||||
DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup);
|
||||
regs->eip = fixup;
|
||||
regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -509,7 +517,6 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code)
|
||||
{
|
||||
DPRINTK("GPF (%04lx): %08lx -> %08lx\n", error_code, regs->eip, fixup);
|
||||
regs->eip = fixup;
|
||||
regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+109
-223
@@ -59,76 +59,9 @@
|
||||
#include <xen/config.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <asm/x86_32/asm_defns.h>
|
||||
#include <public/xen.h>
|
||||
|
||||
EBX = 0x00
|
||||
ECX = 0x04
|
||||
EDX = 0x08
|
||||
ESI = 0x0C
|
||||
EDI = 0x10
|
||||
EBP = 0x14
|
||||
EAX = 0x18
|
||||
DS = 0x1C
|
||||
ES = 0x20
|
||||
FS = 0x24
|
||||
GS = 0x28
|
||||
ORIG_EAX = 0x2C
|
||||
EIP = 0x30
|
||||
CS = 0x34
|
||||
EFLAGS = 0x38
|
||||
OLDESP = 0x3C
|
||||
OLDSS = 0x40
|
||||
|
||||
/* Offsets in domain structure */
|
||||
PROCESSOR = 0
|
||||
SHARED_INFO = 4
|
||||
EVENT_SEL = 8
|
||||
EVENT_ADDR = 12
|
||||
FAILSAFE_BUFFER = 16
|
||||
FAILSAFE_SEL = 32
|
||||
FAILSAFE_ADDR = 36
|
||||
|
||||
/* Offsets in shared_info_t */
|
||||
#define UPCALL_PENDING /* 0 */
|
||||
#define UPCALL_MASK 1
|
||||
|
||||
/* Offsets in guest_trap_bounce */
|
||||
GTB_ERROR_CODE = 0
|
||||
GTB_CR2 = 4
|
||||
GTB_FLAGS = 8
|
||||
GTB_CS = 10
|
||||
GTB_EIP = 12
|
||||
GTBF_TRAP = 1
|
||||
GTBF_TRAP_NOCODE = 2
|
||||
GTBF_TRAP_CR2 = 4
|
||||
|
||||
CF_MASK = 0x00000001
|
||||
IF_MASK = 0x00000200
|
||||
NT_MASK = 0x00004000
|
||||
|
||||
#define SAVE_ALL_NOSEGREGS \
|
||||
cld; \
|
||||
pushl %gs; \
|
||||
pushl %fs; \
|
||||
pushl %es; \
|
||||
pushl %ds; \
|
||||
pushl %eax; \
|
||||
pushl %ebp; \
|
||||
pushl %edi; \
|
||||
pushl %esi; \
|
||||
pushl %edx; \
|
||||
pushl %ecx; \
|
||||
pushl %ebx; \
|
||||
|
||||
#define SAVE_ALL \
|
||||
SAVE_ALL_NOSEGREGS \
|
||||
movl $(__HYPERVISOR_DS),%edx; \
|
||||
movl %edx,%ds; \
|
||||
movl %edx,%es; \
|
||||
movl %edx,%fs; \
|
||||
movl %edx,%gs; \
|
||||
sti;
|
||||
|
||||
#define GET_CURRENT(reg) \
|
||||
movl $4096-4, reg; \
|
||||
orl %esp, reg; \
|
||||
@@ -226,17 +159,10 @@ multicall_fixup1:
|
||||
|
||||
ALIGN
|
||||
restore_all_guest:
|
||||
# First, may need to restore %ds if clobbered by create_bounce_frame
|
||||
pushl %ss
|
||||
popl %ds
|
||||
# Second, create a failsafe copy of DS,ES,FS,GS in case any are bad
|
||||
leal DS(%esp),%esi
|
||||
leal FAILSAFE_BUFFER(%ebx),%edi
|
||||
movsl
|
||||
movsl
|
||||
movsl
|
||||
movsl
|
||||
# Finally, restore guest registers -- faults will cause failsafe
|
||||
1: movl XREGS_ds(%esp),%ds
|
||||
2: movl XREGS_es(%esp),%es
|
||||
3: movl XREGS_fs(%esp),%fs
|
||||
4: movl XREGS_gs(%esp),%gs
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
@@ -244,62 +170,50 @@ restore_all_guest:
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popl %eax
|
||||
1: popl %ds
|
||||
2: popl %es
|
||||
3: popl %fs
|
||||
4: popl %gs
|
||||
addl $4,%esp
|
||||
5: iret
|
||||
.section .fixup,"ax"
|
||||
10: subl $4,%esp
|
||||
pushl %gs
|
||||
9: pushl %fs
|
||||
8: pushl %es
|
||||
7: pushl %ds
|
||||
6: pushl %eax
|
||||
6: subl $4,%esp
|
||||
pushl %eax
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl %ss
|
||||
popl %ds
|
||||
pushl %ss
|
||||
popl %es
|
||||
jmp failsafe_callback
|
||||
7: SET_XEN_SEGMENTS
|
||||
jmp failsafe_callback
|
||||
.previous
|
||||
.section __ex_table,"a"
|
||||
.align 4
|
||||
.long 1b,6b
|
||||
.long 1b,7b
|
||||
.long 2b,7b
|
||||
.long 3b,8b
|
||||
.long 4b,9b
|
||||
.long 5b,10b
|
||||
.long 3b,7b
|
||||
.long 4b,7b
|
||||
.long 5b,6b
|
||||
.previous
|
||||
|
||||
/* No special register assumptions */
|
||||
failsafe_callback:
|
||||
GET_CURRENT(%ebx)
|
||||
movl PROCESSOR(%ebx),%eax
|
||||
movl DOMAIN_processor(%ebx),%eax
|
||||
shl $4,%eax
|
||||
lea guest_trap_bounce(%eax),%edx
|
||||
movl FAILSAFE_ADDR(%ebx),%eax
|
||||
movl %eax,GTB_EIP(%edx)
|
||||
movl FAILSAFE_SEL(%ebx),%eax
|
||||
movw %ax,GTB_CS(%edx)
|
||||
movl DOMAIN_failsafe_addr(%ebx),%eax
|
||||
movl %eax,GTB_eip(%edx)
|
||||
movl DOMAIN_failsafe_sel(%ebx),%eax
|
||||
movw %ax,GTB_cs(%edx)
|
||||
call create_bounce_frame
|
||||
subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame
|
||||
leal FAILSAFE_BUFFER(%ebx),%ebp
|
||||
movl 0(%ebp),%eax # DS
|
||||
FAULT1: movl %eax,(%esi)
|
||||
movl 4(%ebp),%eax # ES
|
||||
FAULT2: movl %eax,4(%esi)
|
||||
movl 8(%ebp),%eax # FS
|
||||
FAULT3: movl %eax,8(%esi)
|
||||
movl 12(%ebp),%eax # GS
|
||||
FAULT4: movl %eax,12(%esi)
|
||||
movl %esi,OLDESP(%esp)
|
||||
movl XREGS_ds(%esp),%eax
|
||||
FAULT1: movl %eax,%gs:(%esi)
|
||||
movl XREGS_es(%esp),%eax
|
||||
FAULT2: movl %eax,%gs:4(%esi)
|
||||
movl XREGS_fs(%esp),%eax
|
||||
FAULT3: movl %eax,%gs:8(%esi)
|
||||
movl XREGS_gs(%esp),%eax
|
||||
FAULT4: movl %eax,%gs:12(%esi)
|
||||
movl %esi,XREGS_esp(%esp)
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
@@ -307,15 +221,10 @@ FAULT4: movl %eax,12(%esi)
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popl %eax
|
||||
addl $20,%esp # skip DS/ES/FS/GS/ORIG_EAX
|
||||
addl $4,%esp
|
||||
FAULT5: iret
|
||||
|
||||
|
||||
ALIGN
|
||||
# Simple restore -- we should never fault as we we will only interrupt ring 0
|
||||
# when sane values have been placed in all registers. The only exception is
|
||||
# NMI, which may interrupt before good values have been placed in DS-GS.
|
||||
# The NMI return code deals with this problem itself.
|
||||
restore_all_xen:
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
@@ -324,10 +233,6 @@ restore_all_xen:
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popl %eax
|
||||
popl %ds
|
||||
popl %es
|
||||
popl %fs
|
||||
popl %gs
|
||||
addl $4,%esp
|
||||
iret
|
||||
|
||||
@@ -335,37 +240,38 @@ restore_all_xen:
|
||||
ENTRY(hypercall)
|
||||
pushl %eax # save orig_eax
|
||||
SAVE_ALL
|
||||
GET_CURRENT(%ebx)
|
||||
sti
|
||||
GET_CURRENT(%ebx)
|
||||
andl $(NR_hypercalls-1),%eax
|
||||
call *SYMBOL_NAME(hypercall_table)(,%eax,4)
|
||||
|
||||
ret_from_hypercall:
|
||||
movl %eax,EAX(%esp) # save the return value
|
||||
movl %eax,XREGS_eax(%esp) # save the return value
|
||||
|
||||
test_all_events:
|
||||
xorl %ecx,%ecx
|
||||
notl %ecx
|
||||
cli # tests must not race interrupts
|
||||
/*test_softirqs:*/
|
||||
movl PROCESSOR(%ebx),%eax
|
||||
movl DOMAIN_processor(%ebx),%eax
|
||||
shl $6,%eax # sizeof(irq_cpustat) == 64
|
||||
test %ecx,SYMBOL_NAME(irq_stat)(%eax,1)
|
||||
jnz process_softirqs
|
||||
/*test_guest_events:*/
|
||||
movl SHARED_INFO(%ebx),%eax
|
||||
testb $0xFF,UPCALL_MASK(%eax)
|
||||
movl DOMAIN_shared_info(%ebx),%eax
|
||||
testb $0xFF,SHINFO_upcall_mask(%eax)
|
||||
jnz restore_all_guest
|
||||
testb $0xFF,UPCALL_PENDING(%eax)
|
||||
testb $0xFF,SHINFO_upcall_pending(%eax)
|
||||
jz restore_all_guest
|
||||
movb $1,UPCALL_MASK(%eax) # Upcalls are masked during delivery
|
||||
movb $1,SHINFO_upcall_mask(%eax) # Upcalls are masked during delivery
|
||||
/*process_guest_events:*/
|
||||
movl PROCESSOR(%ebx),%edx
|
||||
shl $4,%edx # sizeof(guest_trap_bounce) == 16
|
||||
movl DOMAIN_processor(%ebx),%edx
|
||||
shl $4,%edx # sizeof(guest_trap_bounce) == 16
|
||||
lea guest_trap_bounce(%edx),%edx
|
||||
movl EVENT_ADDR(%ebx),%eax
|
||||
movl %eax,GTB_EIP(%edx)
|
||||
movl EVENT_SEL(%ebx),%eax
|
||||
movw %ax,GTB_CS(%edx)
|
||||
movl DOMAIN_event_addr(%ebx),%eax
|
||||
movl %eax,GTB_eip(%edx)
|
||||
movl DOMAIN_event_sel(%ebx),%eax
|
||||
movw %ax,GTB_cs(%edx)
|
||||
call create_bounce_frame
|
||||
jmp restore_all_guest
|
||||
|
||||
@@ -375,16 +281,16 @@ process_softirqs:
|
||||
call SYMBOL_NAME(do_softirq)
|
||||
jmp test_all_events
|
||||
|
||||
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
|
||||
/* {EIP, CS, EFLAGS, [ESP, SS]} */
|
||||
/* %edx == guest_trap_bounce, %ebx == task_struct */
|
||||
/* %eax,%ecx are clobbered. %ds:%esi contain new OLDSS/OLDESP. */
|
||||
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
|
||||
/* {EIP, CS, EFLAGS, [ESP, SS]} */
|
||||
/* %edx == guest_trap_bounce, %ebx == task_struct */
|
||||
/* %eax,%ecx are clobbered. %gs:%esi contain new XREGS_ss/XREGS_esp. */
|
||||
create_bounce_frame:
|
||||
mov CS+4(%esp),%cl
|
||||
mov XREGS_cs+4(%esp),%cl
|
||||
test $2,%cl
|
||||
jz 1f /* jump if returning to an existing ring-1 activation */
|
||||
/* obtain ss/esp from TSS -- no current ring-1 activations */
|
||||
movl PROCESSOR(%ebx),%eax
|
||||
movl DOMAIN_processor(%ebx),%eax
|
||||
/* next 4 lines multiply %eax by 8320, which is sizeof(tss_struct) */
|
||||
movl %eax, %ecx
|
||||
shll $7, %ecx
|
||||
@@ -392,38 +298,37 @@ create_bounce_frame:
|
||||
addl %ecx,%eax
|
||||
addl $init_tss + 12,%eax
|
||||
movl (%eax),%esi /* tss->esp1 */
|
||||
FAULT6: movl 4(%eax),%ds /* tss->ss1 */
|
||||
FAULT6: movl 4(%eax),%gs /* tss->ss1 */
|
||||
/* base of stack frame must contain ss/esp (inter-priv iret) */
|
||||
subl $8,%esi
|
||||
movl OLDESP+4(%esp),%eax
|
||||
FAULT7: movl %eax,(%esi)
|
||||
movl OLDSS+4(%esp),%eax
|
||||
FAULT8: movl %eax,4(%esi)
|
||||
movl XREGS_esp+4(%esp),%eax
|
||||
FAULT7: movl %eax,%gs:(%esi)
|
||||
movl XREGS_ss+4(%esp),%eax
|
||||
FAULT8: movl %eax,%gs:4(%esi)
|
||||
jmp 2f
|
||||
1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */
|
||||
movl OLDESP+4(%esp),%esi
|
||||
FAULT9: movl OLDSS+4(%esp),%ds
|
||||
movl XREGS_esp+4(%esp),%esi
|
||||
FAULT9: movl XREGS_ss+4(%esp),%gs
|
||||
2: /* Construct a stack frame: EFLAGS, CS/EIP */
|
||||
subl $12,%esi
|
||||
movl EIP+4(%esp),%eax
|
||||
FAULT10:movl %eax,(%esi)
|
||||
movl CS+4(%esp),%eax
|
||||
FAULT11:movl %eax,4(%esi)
|
||||
movl EFLAGS+4(%esp),%eax
|
||||
FAULT12:movl %eax,8(%esi)
|
||||
movl XREGS_eip+4(%esp),%eax
|
||||
FAULT10:movl %eax,%gs:(%esi)
|
||||
movl XREGS_cs+4(%esp),%eax
|
||||
FAULT11:movl %eax,%gs:4(%esi)
|
||||
movl XREGS_eflags+4(%esp),%eax
|
||||
FAULT12:movl %eax,%gs:8(%esi)
|
||||
/* Rewrite our stack frame and return to ring 1. */
|
||||
/* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
|
||||
andl $0xfffcbeff,%eax
|
||||
movl %eax,EFLAGS+4(%esp)
|
||||
movl %ds,OLDSS+4(%esp)
|
||||
movl %esi,OLDESP+4(%esp)
|
||||
movzwl %es:GTB_CS(%edx),%eax
|
||||
movl %eax,CS+4(%esp)
|
||||
movl %es:GTB_EIP(%edx),%eax
|
||||
movl %eax,EIP+4(%esp)
|
||||
movl %eax,XREGS_eflags+4(%esp)
|
||||
movl %gs,XREGS_ss+4(%esp)
|
||||
movl %esi,XREGS_esp+4(%esp)
|
||||
movzwl GTB_cs(%edx),%eax
|
||||
movl %eax,XREGS_cs+4(%esp)
|
||||
movl GTB_eip(%edx),%eax
|
||||
movl %eax,XREGS_eip+4(%esp)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
.section __ex_table,"a"
|
||||
.align 4
|
||||
.long FAULT1, crash_domain_fixup3 # Fault writing to ring-1 stack
|
||||
@@ -447,44 +352,41 @@ FAULT12:movl %eax,8(%esi)
|
||||
crash_domain_fixup1:
|
||||
subl $4,%esp
|
||||
SAVE_ALL
|
||||
sti
|
||||
jmp domain_crash
|
||||
crash_domain_fixup2:
|
||||
addl $4,%esp
|
||||
crash_domain_fixup3:
|
||||
pushl %ss
|
||||
popl %ds
|
||||
jmp domain_crash
|
||||
.previous
|
||||
|
||||
ALIGN
|
||||
process_guest_exception_and_events:
|
||||
movl PROCESSOR(%ebx),%eax
|
||||
movl DOMAIN_processor(%ebx),%eax
|
||||
shl $4,%eax
|
||||
lea guest_trap_bounce(%eax),%edx
|
||||
testb $~0,GTB_FLAGS(%edx)
|
||||
testb $~0,GTB_flags(%edx)
|
||||
jz test_all_events
|
||||
call create_bounce_frame # just the basic frame
|
||||
mov %es:GTB_FLAGS(%edx),%cl
|
||||
mov GTB_flags(%edx),%cl
|
||||
test $GTBF_TRAP_NOCODE,%cl
|
||||
jnz 2f
|
||||
subl $4,%esi # push error_code onto guest frame
|
||||
movl %es:GTB_ERROR_CODE(%edx),%eax
|
||||
FAULT13:movl %eax,(%esi)
|
||||
movl GTB_error_code(%edx),%eax
|
||||
FAULT13:movl %eax,%gs:(%esi)
|
||||
test $GTBF_TRAP_CR2,%cl
|
||||
jz 1f
|
||||
subl $4,%esi # push %cr2 onto guest frame
|
||||
movl %es:GTB_CR2(%edx),%eax
|
||||
FAULT14:movl %eax,(%esi)
|
||||
1: movl %esi,OLDESP(%esp)
|
||||
2: push %es # unclobber %ds
|
||||
pop %ds
|
||||
movb $0,GTB_FLAGS(%edx)
|
||||
movl GTB_cr2(%edx),%eax
|
||||
FAULT14:movl %eax,%gs:(%esi)
|
||||
1: movl %esi,XREGS_esp(%esp)
|
||||
2: movb $0,GTB_flags(%edx)
|
||||
jmp test_all_events
|
||||
|
||||
ALIGN
|
||||
ENTRY(ret_from_intr)
|
||||
GET_CURRENT(%ebx)
|
||||
movb CS(%esp),%al
|
||||
movb XREGS_cs(%esp),%al
|
||||
testb $3,%al # return to non-supervisor?
|
||||
jne test_all_events
|
||||
jmp restore_all_xen
|
||||
@@ -494,36 +396,31 @@ ENTRY(divide_error)
|
||||
pushl $ SYMBOL_NAME(do_divide_error)
|
||||
ALIGN
|
||||
error_code:
|
||||
pushl %fs
|
||||
pushl %es
|
||||
pushl %ds
|
||||
pushl %eax
|
||||
xorl %eax,%eax
|
||||
pushl %ebp
|
||||
cld
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
decl %eax # eax = -1
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
cld
|
||||
movl %gs,%ecx
|
||||
movl ORIG_EAX(%esp), %esi # get the error code
|
||||
movl GS(%esp), %edi # get the function address
|
||||
movl %eax, ORIG_EAX(%esp)
|
||||
movl %ecx, GS(%esp)
|
||||
movl $(__HYPERVISOR_DS),%edx
|
||||
movl %edx,%ds
|
||||
movl %edx,%es
|
||||
movl %edx,%fs
|
||||
movl %edx,%gs
|
||||
movb XREGS_cs(%esp),%bl
|
||||
testb $3,%bl
|
||||
je 1f
|
||||
movl %ds,XREGS_ds(%esp)
|
||||
movl %es,XREGS_es(%esp)
|
||||
movl %fs,XREGS_fs(%esp)
|
||||
movl %gs,XREGS_gs(%esp)
|
||||
1: SET_XEN_SEGMENTS
|
||||
movl XREGS_orig_eax(%esp),%esi # get the error code
|
||||
movl XREGS_eax(%esp),%edi # get the function address
|
||||
movl %eax,XREGS_eax(%esp)
|
||||
movl %esp,%edx
|
||||
pushl %esi # push the error code
|
||||
pushl %edx # push the xen_regs pointer
|
||||
GET_CURRENT(%ebx)
|
||||
call *%edi
|
||||
call *%edi
|
||||
addl $8,%esp
|
||||
movb CS(%esp),%al
|
||||
movb XREGS_cs(%esp),%al
|
||||
testb $3,%al
|
||||
je restore_all_xen
|
||||
jmp process_guest_exception_and_events
|
||||
@@ -628,21 +525,21 @@ ENTRY(nmi)
|
||||
# In all other cases we bail without touching DS-GS, as we have
|
||||
# interrupted an enclosing Xen activation in tricky prologue or
|
||||
# epilogue code.
|
||||
movb CS(%esp),%al
|
||||
movb XREGS_cs(%esp),%al
|
||||
testb $3,%al
|
||||
jne do_watchdog_tick
|
||||
movl DS(%esp),%eax
|
||||
movl XREGS_ds(%esp),%eax
|
||||
cmpw $(__HYPERVISOR_DS),%ax
|
||||
jne nmi_badseg
|
||||
movl ES(%esp),%eax
|
||||
jne restore_all_xen
|
||||
movl XREGS_es(%esp),%eax
|
||||
cmpw $(__HYPERVISOR_DS),%ax
|
||||
jne nmi_badseg
|
||||
movl FS(%esp),%eax
|
||||
jne restore_all_xen
|
||||
movl XREGS_fs(%esp),%eax
|
||||
cmpw $(__HYPERVISOR_DS),%ax
|
||||
jne nmi_badseg
|
||||
movl GS(%esp),%eax
|
||||
jne restore_all_xen
|
||||
movl XREGS_gs(%esp),%eax
|
||||
cmpw $(__HYPERVISOR_DS),%ax
|
||||
jne nmi_badseg
|
||||
jne restore_all_xen
|
||||
|
||||
do_watchdog_tick:
|
||||
movl $(__HYPERVISOR_DS),%edx
|
||||
@@ -653,34 +550,23 @@ do_watchdog_tick:
|
||||
pushl %edx # regs
|
||||
call SYMBOL_NAME(do_nmi)
|
||||
addl $8,%esp
|
||||
movb CS(%esp),%al
|
||||
movb XREGS_cs(%esp),%al
|
||||
testb $3,%al
|
||||
je restore_all_xen
|
||||
GET_CURRENT(%ebx)
|
||||
jmp restore_all_guest
|
||||
|
||||
nmi_badseg:
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popl %eax
|
||||
addl $20,%esp
|
||||
iret
|
||||
|
||||
nmi_parity_err:
|
||||
# Clear and disable the parity-error line
|
||||
andb $0xf,%al
|
||||
orb $0x4,%al
|
||||
outb %al,$0x61
|
||||
cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
|
||||
je nmi_badseg
|
||||
je restore_all_xen
|
||||
bts $0,%ss:SYMBOL_NAME(nmi_softirq_reason)
|
||||
bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
|
||||
cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
|
||||
je nmi_badseg
|
||||
je restore_all_xen
|
||||
movl $(__HYPERVISOR_DS),%edx # nmi=fatal
|
||||
movl %edx,%ds
|
||||
movl %edx,%es
|
||||
@@ -696,11 +582,11 @@ nmi_io_err:
|
||||
orb $0x8,%al
|
||||
outb %al,$0x61
|
||||
cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
|
||||
je nmi_badseg
|
||||
je restore_all_xen
|
||||
bts $1,%ss:SYMBOL_NAME(nmi_softirq_reason)
|
||||
bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
|
||||
cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
|
||||
je nmi_badseg
|
||||
je restore_all_xen
|
||||
movl $(__HYPERVISOR_DS),%edx # nmi=fatal
|
||||
movl %edx,%ds
|
||||
movl %edx,%es
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/x86_32/asm_defns.h>
|
||||
|
||||
extern void disable_irq(unsigned int);
|
||||
extern void disable_irq_nosync(unsigned int);
|
||||
@@ -83,36 +84,6 @@ extern char _stext, _etext;
|
||||
|
||||
#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
|
||||
|
||||
#define __STR(x) #x
|
||||
#define STR(x) __STR(x)
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
#define SAVE_ALL \
|
||||
"cld\n\t" \
|
||||
"pushl %gs\n\t" \
|
||||
"pushl %fs\n\t" \
|
||||
"pushl %es\n\t" \
|
||||
"pushl %ds\n\t" \
|
||||
"pushl %eax\n\t" \
|
||||
"pushl %ebp\n\t" \
|
||||
"pushl %edi\n\t" \
|
||||
"pushl %esi\n\t" \
|
||||
"pushl %edx\n\t" \
|
||||
"pushl %ecx\n\t" \
|
||||
"pushl %ebx\n\t" \
|
||||
"movl $" STR(__HYPERVISOR_DS) ",%edx\n\t" \
|
||||
"movl %edx,%ds\n\t" \
|
||||
"movl %edx,%es\n\t" \
|
||||
"movl %edx,%fs\n\t" \
|
||||
"movl %edx,%gs\n\t"
|
||||
|
||||
#else
|
||||
|
||||
#define SAVE_ALL
|
||||
|
||||
#endif
|
||||
|
||||
#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
|
||||
#define XBUILD_SMP_INTERRUPT(x,v)\
|
||||
asmlinkage void x(void); \
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#ifndef __ASM_DEFNS_H__
|
||||
#define __ASM_DEFNS_H__
|
||||
|
||||
/* Offsets in 'struct xen_regs' --- AUTO-GENERATE ME! */
|
||||
#define XREGS_ebx 0x00
|
||||
#define XREGS_ecx 0x04
|
||||
#define XREGS_edx 0x08
|
||||
#define XREGS_esi 0x0C
|
||||
#define XREGS_edi 0x10
|
||||
#define XREGS_ebp 0x14
|
||||
#define XREGS_eax 0x18
|
||||
#define XREGS_orig_eax 0x1C
|
||||
#define XREGS_eip 0x20
|
||||
#define XREGS_cs 0x24
|
||||
#define XREGS_eflags 0x28
|
||||
#define XREGS_esp 0x2C
|
||||
#define XREGS_ss 0x30
|
||||
#define XREGS_es 0x34
|
||||
#define XREGS_ds 0x38
|
||||
#define XREGS_fs 0x3C
|
||||
#define XREGS_gs 0x40
|
||||
|
||||
/* Offsets in 'struct domain' --- AUTO-GENERATE ME! */
|
||||
#define DOMAIN_processor 0
|
||||
#define DOMAIN_shared_info 4
|
||||
#define DOMAIN_event_sel 8
|
||||
#define DOMAIN_event_addr 12
|
||||
#define DOMAIN_failsafe_sel 16
|
||||
#define DOMAIN_failsafe_addr 20
|
||||
|
||||
/* Offsets in shared_info_t --- AUTO-GENERATE ME! */
|
||||
#define SHINFO_upcall_pending /* 0 */
|
||||
#define SHINFO_upcall_mask 1
|
||||
|
||||
/* Offsets in 'struct guest_trap_bounce' --- AUTO-GENERATE ME! */
|
||||
#define GTB_error_code 0
|
||||
#define GTB_cr2 4
|
||||
#define GTB_flags 8
|
||||
#define GTB_cs 10
|
||||
#define GTB_eip 12
|
||||
#define GTBF_TRAP 1
|
||||
#define GTBF_TRAP_NOCODE 2
|
||||
#define GTBF_TRAP_CR2 4
|
||||
|
||||
/* EFLAGS masks. */
|
||||
#define CF_MASK 0x00000001
|
||||
#define IF_MASK 0x00000200
|
||||
#define NT_MASK 0x00004000
|
||||
|
||||
#define __STR(x) #x
|
||||
#define STR(x) __STR(x)
|
||||
|
||||
/* AUTO-GENERATE the following two cases (quoted vs. unquoted). */
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define __SAVE_ALL_PRE \
|
||||
"cld;" \
|
||||
"pushl %eax;" \
|
||||
"pushl %ebp;" \
|
||||
"pushl %edi;" \
|
||||
"pushl %esi;" \
|
||||
"pushl %edx;" \
|
||||
"pushl %ecx;" \
|
||||
"pushl %ebx;" \
|
||||
"movb "STR(XREGS_cs)"(%esp),%al;" \
|
||||
"testb $3,%al;" \
|
||||
"je 1f;" \
|
||||
"movl %ds,"STR(XREGS_ds)"(%esp);" \
|
||||
"movl %es,"STR(XREGS_es)"(%esp);" \
|
||||
"movl %fs,"STR(XREGS_fs)"(%esp);" \
|
||||
"movl %gs,"STR(XREGS_gs)"(%esp);"
|
||||
|
||||
#define SAVE_ALL_NOSEGREGS \
|
||||
__SAVE_ALL_PRE \
|
||||
"1:"
|
||||
|
||||
#define SET_XEN_SEGMENTS \
|
||||
"movl $("STR(__HYPERVISOR_DS)"),%edx;" \
|
||||
"movl %edx,%ds;" \
|
||||
"movl %edx,%es;"
|
||||
|
||||
#define SAVE_ALL \
|
||||
__SAVE_ALL_PRE \
|
||||
SET_XEN_SEGMENTS \
|
||||
"1:"
|
||||
|
||||
#else
|
||||
|
||||
#define __SAVE_ALL_PRE \
|
||||
cld; \
|
||||
pushl %eax; \
|
||||
pushl %ebp; \
|
||||
pushl %edi; \
|
||||
pushl %esi; \
|
||||
pushl %edx; \
|
||||
pushl %ecx; \
|
||||
pushl %ebx; \
|
||||
movb XREGS_cs(%esp),%dl; \
|
||||
testb $3,%dl; \
|
||||
je 1f; \
|
||||
movl %ds,XREGS_ds(%esp); \
|
||||
movl %es,XREGS_es(%esp); \
|
||||
movl %fs,XREGS_fs(%esp); \
|
||||
movl %gs,XREGS_gs(%esp);
|
||||
|
||||
#define SAVE_ALL_NOSEGREGS \
|
||||
__SAVE_ALL_PRE \
|
||||
1:
|
||||
|
||||
#define SET_XEN_SEGMENTS \
|
||||
movl $(__HYPERVISOR_DS),%edx; \
|
||||
movl %edx,%ds; \
|
||||
movl %edx,%es;
|
||||
|
||||
#define SAVE_ALL \
|
||||
__SAVE_ALL_PRE \
|
||||
SET_XEN_SEGMENTS \
|
||||
1:
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_DEFNS_H__ */
|
||||
@@ -31,11 +31,17 @@ static inline execution_context_t *get_execution_context(void)
|
||||
return execution_context;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the top-of-stack, as stored in the per-CPU TSS. This is actually
|
||||
* 20 bytes below the real top of the stack to allow space for:
|
||||
* domain pointer, DS, ES, FS, GS.
|
||||
*/
|
||||
static inline unsigned long get_stack_top(void)
|
||||
{
|
||||
unsigned long p;
|
||||
__asm__ ( "orl %%esp,%0; andl $~3,%0"
|
||||
: "=r" (p) : "0" (STACK_SIZE-4) );
|
||||
__asm__ ( "andl %%esp,%0; addl %2,%0"
|
||||
: "=r" (p)
|
||||
: "0" (~(STACK_SIZE-1)), "i" (STACK_SIZE-20) );
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +1,51 @@
|
||||
#ifndef _I386_REGS_H
|
||||
#define _I386_REGS_H
|
||||
|
||||
struct xen_regs {
|
||||
long ebx;
|
||||
long ecx;
|
||||
long edx;
|
||||
long esi;
|
||||
long edi;
|
||||
long ebp;
|
||||
long eax;
|
||||
int xds;
|
||||
int xes;
|
||||
int xfs;
|
||||
int xgs;
|
||||
long orig_eax;
|
||||
long eip;
|
||||
int xcs;
|
||||
long eflags;
|
||||
long esp;
|
||||
int xss;
|
||||
struct xen_regs
|
||||
{
|
||||
/* All saved activations contain the following fields. */
|
||||
long ebx;
|
||||
long ecx;
|
||||
long edx;
|
||||
long esi;
|
||||
long edi;
|
||||
long ebp;
|
||||
long eax;
|
||||
long orig_eax;
|
||||
long eip;
|
||||
int xcs;
|
||||
long eflags;
|
||||
|
||||
/* Only saved guest activations contain the following fields. */
|
||||
long esp;
|
||||
int xss;
|
||||
int xes;
|
||||
int xds;
|
||||
int xfs;
|
||||
int xgs;
|
||||
};
|
||||
|
||||
enum EFLAGS {
|
||||
EF_CF = 0x00000001,
|
||||
EF_PF = 0x00000004,
|
||||
EF_AF = 0x00000010,
|
||||
EF_ZF = 0x00000040,
|
||||
EF_SF = 0x00000080,
|
||||
EF_TF = 0x00000100,
|
||||
EF_IE = 0x00000200,
|
||||
EF_DF = 0x00000400,
|
||||
EF_OF = 0x00000800,
|
||||
EF_IOPL = 0x00003000,
|
||||
EF_IOPL_RING0 = 0x00000000,
|
||||
EF_IOPL_RING1 = 0x00001000,
|
||||
EF_IOPL_RING2 = 0x00002000,
|
||||
EF_NT = 0x00004000, /* nested task */
|
||||
EF_RF = 0x00010000, /* resume */
|
||||
EF_VM = 0x00020000, /* virtual mode */
|
||||
EF_AC = 0x00040000, /* alignment */
|
||||
EF_VIF = 0x00080000, /* virtual interrupt */
|
||||
EF_VIP = 0x00100000, /* virtual interrupt pending */
|
||||
EF_ID = 0x00200000, /* id */
|
||||
EF_CF = 0x00000001,
|
||||
EF_PF = 0x00000004,
|
||||
EF_AF = 0x00000010,
|
||||
EF_ZF = 0x00000040,
|
||||
EF_SF = 0x00000080,
|
||||
EF_TF = 0x00000100,
|
||||
EF_IE = 0x00000200,
|
||||
EF_DF = 0x00000400,
|
||||
EF_OF = 0x00000800,
|
||||
EF_IOPL = 0x00003000,
|
||||
EF_IOPL_RING0 = 0x00000000,
|
||||
EF_IOPL_RING1 = 0x00001000,
|
||||
EF_IOPL_RING2 = 0x00002000,
|
||||
EF_NT = 0x00004000, /* nested task */
|
||||
EF_RF = 0x00010000, /* resume */
|
||||
EF_VM = 0x00020000, /* virtual mode */
|
||||
EF_AC = 0x00040000, /* alignment */
|
||||
EF_VIF = 0x00080000, /* virtual interrupt */
|
||||
EF_VIP = 0x00100000, /* virtual interrupt pending */
|
||||
EF_ID = 0x00200000, /* id */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -92,16 +92,16 @@ typedef struct
|
||||
unsigned long edi;
|
||||
unsigned long ebp;
|
||||
unsigned long eax;
|
||||
unsigned long ds;
|
||||
unsigned long es;
|
||||
unsigned long fs;
|
||||
unsigned long gs;
|
||||
unsigned long _unused;
|
||||
unsigned long eip;
|
||||
unsigned long cs;
|
||||
unsigned long eflags;
|
||||
unsigned long esp;
|
||||
unsigned long ss;
|
||||
unsigned long es;
|
||||
unsigned long ds;
|
||||
unsigned long fs;
|
||||
unsigned long gs;
|
||||
} PACKED execution_context_t;
|
||||
|
||||
typedef u64 tsc_timestamp_t; /* RDTSC timestamp */
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* This makes sure that old versions of dom0 tools will stop working in a
|
||||
* well-defined way (rather than crashing the machine, for instance).
|
||||
*/
|
||||
#define DOM0_INTERFACE_VERSION 0xAAAA0019
|
||||
#define DOM0_INTERFACE_VERSION 0xAAAA001A
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
@@ -75,15 +75,8 @@ struct domain
|
||||
unsigned long event_selector; /* 08: entry CS */
|
||||
unsigned long event_address; /* 12: entry EIP */
|
||||
|
||||
/* Saved DS,ES,FS,GS immediately before return to guest OS. */
|
||||
unsigned long failsafe_selectors[4]; /* 16-32 */
|
||||
|
||||
/*
|
||||
* END OF FIRST CACHELINE. Stuff above is touched a lot!
|
||||
*/
|
||||
|
||||
unsigned long failsafe_selector; /* 32: entry CS */
|
||||
unsigned long failsafe_address; /* 36: entry EIP */
|
||||
unsigned long failsafe_selector; /* 16: entry CS */
|
||||
unsigned long failsafe_address; /* 20: entry EIP */
|
||||
|
||||
/*
|
||||
* From here on things can be added and shuffled without special attention
|
||||
|
||||