From: kaf24@firebug.cl.cam.ac.uk Date: Wed, 11 Jan 2006 18:44:54 +0000 (+0100) Subject: More code cleanups, mainly to do_iret() implementations. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16541^2~61^2~4 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=ab8eb5a3ef5e7968d0c0f18db4452ac0f0995ed2;p=xen.git More code cleanups, mainly to do_iret() implementations. Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index e1485ed1a0..19c29d084c 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -480,14 +480,6 @@ void new_thread(struct vcpu *d, #ifdef __x86_64__ -void toggle_guest_mode(struct vcpu *v) -{ - v->arch.flags ^= TF_kernel_mode; - __asm__ __volatile__ ( "swapgs" ); - update_pagetables(v); - write_ptbase(v); -} - #define loadsegment(seg,value) ({ \ int __r = 1; \ __asm__ __volatile__ ( \ diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index f15ebb4d9c..a9dba3ef66 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -297,7 +297,6 @@ int map_ldt_shadow_page(unsigned int off) #if defined(__x86_64__) /* If in user mode, switch to kernel mode just to read LDT mapping. */ - extern void toggle_guest_mode(struct vcpu *); int user_mode = !(v->arch.flags & TF_kernel_mode); #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) #elif defined(__i386__) @@ -2971,7 +2970,6 @@ void ptwr_flush(struct domain *d, const int which) #ifdef CONFIG_X86_64 struct vcpu *v = current; - extern void toggle_guest_mode(struct vcpu *); int user_mode = !(v->arch.flags & TF_kernel_mode); #endif diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 4458b70636..9929722fab 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -596,7 +596,6 @@ static inline int guest_io_okay( u16 x; #if defined(__x86_64__) /* If in user mode, switch to kernel mode just to read I/O bitmap. */ - extern void toggle_guest_mode(struct vcpu *); int user_mode = !(v->arch.flags & TF_kernel_mode); #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) #elif defined(__i386__) diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 2c896bce2a..6f7fb83640 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -157,38 +157,37 @@ asmlinkage void do_double_fault(void) __asm__ __volatile__ ( "hlt" ); } +static inline void pop_from_guest_stack( + void *dst, struct cpu_user_regs *regs, unsigned int bytes) +{ + if ( unlikely(copy_from_user(dst, (void __user *)regs->esp, bytes)) ) + domain_crash_synchronous(); + regs->esp += bytes; +} + asmlinkage unsigned long do_iret(void) { struct cpu_user_regs *regs = guest_cpu_user_regs(); - /* Restore EAX (clobbered by hypercall). */ - if ( copy_from_user(®s->eax, (void __user *)regs->esp, 4) ) - domain_crash_synchronous(); - regs->esp += 4; + /* Pop and restore EAX (clobbered by hypercall). */ + pop_from_guest_stack(®s->eax, regs, 4); - /* Restore EFLAGS, CS and EIP. */ - if ( copy_from_user(®s->eip, (void __user *)regs->esp, 12) ) - domain_crash_synchronous(); + /* Pop and restore EFLAGS, CS and EIP. */ + pop_from_guest_stack(®s->eip, regs, 12); if ( VM86_MODE(regs) ) { - /* Return to VM86 mode: restore ESP,SS,ES,DS,FS and GS. */ - if(copy_from_user(®s->esp, (void __user *)(regs->esp+12), 24)) - domain_crash_synchronous(); + /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */ + pop_from_guest_stack(®s->esp, regs, 24); } else if ( RING_0(regs) ) { domain_crash_synchronous(); } - else if ( RING_1(regs) ) { - /* Return to ring 1: pop EFLAGS,CS and EIP. */ - regs->esp += 12; - } - else + else if ( !RING_1(regs) ) { - /* Return to ring 2/3: restore ESP and SS. */ - if ( copy_from_user(®s->esp, (void __user *)(regs->esp+12), 8) ) - domain_crash_synchronous(); + /* Return to ring 2/3: pop and restore ESP and SS. */ + pop_from_guest_stack(®s->esp, regs, 8); } /* Fixup EFLAGS. */ diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index af2f55e29a..9756c54589 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -114,7 +114,13 @@ asmlinkage void do_double_fault(struct cpu_user_regs *regs) __asm__ __volatile__ ( "hlt" ); } -extern void toggle_guest_mode(struct vcpu *); +void toggle_guest_mode(struct vcpu *v) +{ + v->arch.flags ^= TF_kernel_mode; + __asm__ __volatile__ ( "swapgs" ); + update_pagetables(v); + write_ptbase(v); +} long do_iret(void) { @@ -122,13 +128,17 @@ long do_iret(void) struct iret_context iret_saved; struct vcpu *v = current; - if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, sizeof(iret_saved))) || - unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) - return -EFAULT; + if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, + sizeof(iret_saved))) ) + domain_crash_synchronous(); - /* Returning to user mode. */ - if ( (iret_saved.cs & 0x03) == 3 ) + /* Returning to user mode? */ + if ( (iret_saved.cs & 3) == 3 ) + { + if ( unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) + return -EFAULT; toggle_guest_mode(v); + } regs->rip = iret_saved.rip; regs->cs = iret_saved.cs | 3; /* force guest privilege */ diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index a713b89886..6438757d67 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -46,7 +46,10 @@ struct mapcache { struct vcpu_maphash vcpu_maphash[MAX_VIRT_CPUS]; }; -extern void mapcache_init(struct domain *d); +extern void mapcache_init(struct domain *); + +/* x86/64: toggle guest between kernel and user modes. */ +extern void toggle_guest_mode(struct vcpu *); struct arch_domain {