WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] svm: Rationalise register synchronisation

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] svm: Rationalise register synchronisation to be similar to our vmx
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 15 May 2007 08:20:49 -0700
Delivery-date: Tue, 15 May 2007 08:25:01 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1178837344 -3600
# Node ID 60240a72e2b2676a6af652a869746dd6552eed2a
# Parent  e19ddfa781c5f9c8c4e30b63baf12d3cdefc4e0e
svm: Rationalise register synchronisation to be similar to our vmx
handling.
 1. Do not copy all VMCB register state in cpu_user_regs on every
 vmexit.
 2. Save/restore RAX inside asm stub (in particular, before STGI on
 vmexit).
 3. Simplify store/load_cpu_guest_regs() hook functions to synchronise
 precisely the same state as VMX.

By my measurements this reduces the round-trip latency for a null
hypercall by around 150 cycles. This is about 3% of the ~5000-cycle
total on my AMD X2 system. Not a great win, but a nice extra on top of
the code rationalisation.
---
 xen/arch/x86/hvm/svm/svm.c          |   29 --------
 xen/arch/x86/hvm/svm/x86_32/exits.S |   98 ++++++++--------------------
 xen/arch/x86/hvm/svm/x86_64/exits.S |  123 ++++++++++++------------------------
 3 files changed, 73 insertions(+), 177 deletions(-)

diff -r e19ddfa781c5 -r 60240a72e2b2 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Thu May 10 22:54:43 2007 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Thu May 10 23:49:04 2007 +0100
@@ -110,15 +110,11 @@ static void svm_store_cpu_guest_regs(
 
     if ( regs != NULL )
     {
-        regs->eip    = vmcb->rip;
+        regs->ss     = vmcb->ss.sel;
         regs->esp    = vmcb->rsp;
         regs->eflags = vmcb->rflags;
         regs->cs     = vmcb->cs.sel;
-        regs->ds     = vmcb->ds.sel;
-        regs->es     = vmcb->es.sel;
-        regs->ss     = vmcb->ss.sel;
-        regs->gs     = vmcb->gs.sel;
-        regs->fs     = vmcb->fs.sel;
+        regs->eip    = vmcb->rip;
     }
 
     if ( crs != NULL )
@@ -752,28 +748,10 @@ static void svm_init_hypercall_page(stru
     *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
 }
 
-static void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    ctxt->eax = vmcb->rax;
-    ctxt->ss = vmcb->ss.sel;
-    ctxt->esp = vmcb->rsp;
-    ctxt->eflags = vmcb->rflags;
-    ctxt->cs = vmcb->cs.sel;
-    ctxt->eip = vmcb->rip;
-    
-    ctxt->gs = vmcb->gs.sel;
-    ctxt->fs = vmcb->fs.sel;
-    ctxt->es = vmcb->es.sel;
-    ctxt->ds = vmcb->ds.sel;
-}
-
 static void svm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    
-    vmcb->rax      = regs->eax;
+
     vmcb->ss.sel   = regs->ss;
     vmcb->rsp      = regs->esp;   
     vmcb->rflags   = regs->eflags | 2UL;
@@ -2242,7 +2220,6 @@ asmlinkage void svm_vmexit_handler(struc
     int inst_len, rc;
 
     exit_reason = vmcb->exitcode;
-    save_svm_cpu_user_regs(v, regs);
 
     HVMTRACE_2D(VMEXIT, v, vmcb->rip, exit_reason);
 
diff -r e19ddfa781c5 -r 60240a72e2b2 xen/arch/x86/hvm/svm/x86_32/exits.S
--- a/xen/arch/x86/hvm/svm/x86_32/exits.S       Thu May 10 22:54:43 2007 +0100
+++ b/xen/arch/x86/hvm/svm/x86_32/exits.S       Thu May 10 23:49:04 2007 +0100
@@ -16,6 +16,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  */
+
 #include <xen/config.h>
 #include <xen/errno.h>
 #include <xen/softirq.h>
@@ -25,60 +26,23 @@
 #include <public/xen.h>
 
 #define GET_CURRENT(reg)         \
-        movl $STACK_SIZE-4, reg; \
-        orl  %esp, reg;          \
+        movl $STACK_SIZE-4,reg;  \
+        orl  %esp,reg;           \
         andl $~3,reg;            \
         movl (reg),reg;
 
-/*
- * At VMExit time the processor saves the guest selectors, esp, eip, 
- * and eflags. Therefore we don't save them, but simply decrement 
- * the kernel stack pointer to make it consistent with the stack frame 
- * at usual interruption time. The eflags of the host is not saved by AMD-V, 
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used 
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- *   (10) u32 gs;                 
- *   (9)  u32 fs;
- *   (8)  u32 ds;
- *   (7)  u32 es;
- *               <- get_stack_bottom() (= HOST_ESP)
- *   (6)  u32 ss;
- *   (5)  u32 esp;
- *   (4)  u32 eflags;
- *   (3)  u32 cs;
- *   (2)  u32 eip;
- * (2/1)  u16 entry_vector;
- * (1/1)  u16 error_code;
- * However, get_stack_bottom() actually returns 20 bytes before the real
- * bottom of the stack to allow space for:
- * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers.
- */
-
 #define HVM_MONITOR_EFLAGS 0x202 /* IF on */
-#define NR_SKIPPED_REGS    6     /* See the above explanation */
-#define HVM_SAVE_ALL_NOSEGREGS \
-        pushl $HVM_MONITOR_EFLAGS; \
-        popf; \
-        subl $(NR_SKIPPED_REGS*4), %esp; \
-        pushl %eax; \
-        pushl %ebp; \
-        pushl %edi; \
-        pushl %esi; \
-        pushl %edx; \
-        pushl %ecx; \
+#define NR_SKIPPED_REGS    7     /* Skip SS thru EAX */
+#define HVM_SAVE_ALL_NOSEGREGS                  \
+        pushl $HVM_MONITOR_EFLAGS;              \
+        popf;                                   \
+        subl $(NR_SKIPPED_REGS*4),%esp;         \
+        pushl %ebp;                             \
+        pushl %edi;                             \
+        pushl %esi;                             \
+        pushl %edx;                             \
+        pushl %ecx;                             \
         pushl %ebx;
-
-#define HVM_RESTORE_ALL_NOSEGREGS   \
-        popl %ebx;  \
-        popl %ecx;  \
-        popl %edx;  \
-        popl %esi;  \
-        popl %edi;  \
-        popl %ebp;  \
-        popl %eax;  \
-        addl $(NR_SKIPPED_REGS*4), %esp
 
 #define VMRUN  .byte 0x0F,0x01,0xD8
 #define VMLOAD .byte 0x0F,0x01,0xDA
@@ -88,12 +52,10 @@
 
 ENTRY(svm_asm_do_resume)
         GET_CURRENT(%ebx)
-        xorl %ecx,%ecx
-        notl %ecx
         cli                             # tests must not race interrupts
         movl VCPU_processor(%ebx),%eax
         shl  $IRQSTAT_shift,%eax
-        test %ecx,irq_stat(%eax,1)
+        testl $~0,irq_stat(%eax,1)
         jnz  svm_process_softirqs
         call svm_intr_assist
         call svm_load_cr2
@@ -101,39 +63,35 @@ ENTRY(svm_asm_do_resume)
         CLGI                
         sti
         GET_CURRENT(%ebx)
-        movl VCPU_svm_vmcb(%ebx), %ecx
-        movl 24(%esp), %eax
-        movl %eax, VMCB_rax(%ecx)
-        movl VCPU_processor(%ebx), %eax
-        movl root_vmcb_pa(,%eax,8), %eax
+        movl VCPU_svm_vmcb(%ebx),%ecx
+        movl UREGS_eax(%esp),%eax
+        movl %eax,VMCB_rax(%ecx)
+        movl VCPU_processor(%ebx),%eax
+        movl root_vmcb_pa(,%eax,8),%eax
         VMSAVE
 
-        movl VCPU_svm_vmcb_pa(%ebx), %eax
+        movl VCPU_svm_vmcb_pa(%ebx),%eax
         popl %ebx
         popl %ecx
         popl %edx
         popl %esi
         popl %edi
         popl %ebp
-
-        /* 
-         * Skip %eax, we need to have vmcb address in there.
-         * Don't worry, EAX is restored through the VMRUN instruction.
-         */
-        addl $4, %esp       
-        addl $(NR_SKIPPED_REGS*4), %esp
+        addl $(NR_SKIPPED_REGS*4),%esp
         VMLOAD
         VMRUN
         VMSAVE
-        /* eax is the only register we're allowed to touch here... */
 
-        GET_CURRENT(%eax)
+        HVM_SAVE_ALL_NOSEGREGS
 
-        movl VCPU_processor(%eax), %eax
-        movl root_vmcb_pa(,%eax,8), %eax
+        GET_CURRENT(%ebx)
+        movl VCPU_svm_vmcb(%ebx),%ecx
+        movl VMCB_rax(%ecx),%eax
+        movl %eax,UREGS_eax(%esp)
+        movl VCPU_processor(%ebx),%eax
+        movl root_vmcb_pa(,%eax,8),%eax
         VMLOAD
 
-        HVM_SAVE_ALL_NOSEGREGS
         STGI
 .globl svm_stgi_label;
 svm_stgi_label:
diff -r e19ddfa781c5 -r 60240a72e2b2 xen/arch/x86/hvm/svm/x86_64/exits.S
--- a/xen/arch/x86/hvm/svm/x86_64/exits.S       Thu May 10 22:54:43 2007 +0100
+++ b/xen/arch/x86/hvm/svm/x86_64/exits.S       Thu May 10 23:49:04 2007 +0100
@@ -16,6 +16,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  */
+
 #include <xen/config.h>
 #include <xen/errno.h>
 #include <xen/softirq.h>
@@ -25,72 +26,32 @@
 #include <public/xen.h>
 
 #define GET_CURRENT(reg)         \
-        movq $STACK_SIZE-8, reg; \
-        orq  %rsp, reg;          \
+        movq $STACK_SIZE-8,reg;  \
+        orq  %rsp,reg;           \
         andq $~7,reg;            \
         movq (reg),reg;
 
-/*
- * At VMExit time the processor saves the guest selectors, rsp, rip, 
- * and rflags. Therefore we don't save them, but simply decrement 
- * the kernel stack pointer to make it consistent with the stack frame 
- * at usual interruption time. The rflags of the host is not saved by AMD-V, 
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used 
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- *   (10) u64 gs;                 
- *   (9)  u64 fs;
- *   (8)  u64 ds;
- *   (7)  u64 es;
- *               <- get_stack_bottom() (= HOST_ESP)
- *   (6)  u64 ss;
- *   (5)  u64 rsp;
- *   (4)  u64 rflags;
- *   (3)  u64 cs;
- *   (2)  u64 rip;
- * (2/1)  u32 entry_vector;
- * (1/1)  u32 error_code;
- */
 #define HVM_MONITOR_RFLAGS 0x202 /* IF on */
-#define NR_SKIPPED_REGS    6     /* See the above explanation */
-#define HVM_SAVE_ALL_NOSEGREGS \
-        pushq $HVM_MONITOR_RFLAGS; \
-        popfq; \
-        subq $(NR_SKIPPED_REGS*8), %rsp; \
-        pushq %rdi; \
-        pushq %rsi; \
-        pushq %rdx; \
-        pushq %rcx; \
-        pushq %rax; \
-        pushq %r8;  \
-        pushq %r9;  \
-        pushq %r10; \
-        pushq %r11; \
-        pushq %rbx; \
-        pushq %rbp; \
-        pushq %r12; \
-        pushq %r13; \
-        pushq %r14; \
-        pushq %r15; \
-
-#define HVM_RESTORE_ALL_NOSEGREGS \
-        popq %r15; \
-        popq %r14; \
-        popq %r13; \
-        popq %r12; \
-        popq %rbp; \
-        popq %rbx; \
-        popq %r11; \
-        popq %r10; \
-        popq %r9;  \
-        popq %r8;  \
-        popq %rax; \
-        popq %rcx; \
-        popq %rdx; \
-        popq %rsi; \
-        popq %rdi; \
-        addq $(NR_SKIPPED_REGS*8), %rsp; \
+#define NR_SKIPPED_REGS    6     /* Skip SS thru error_code */
+#define HVM_SAVE_ALL_NOSEGREGS                  \
+        pushq $HVM_MONITOR_RFLAGS;              \
+        popfq;                                  \
+        subq $(NR_SKIPPED_REGS*8),%rsp;         \
+        pushq %rdi;                             \
+        pushq %rsi;                             \
+        pushq %rdx;                             \
+        pushq %rcx;                             \
+        pushq %rax;                             \
+        pushq %r8;                              \
+        pushq %r9;                              \
+        pushq %r10;                             \
+        pushq %r11;                             \
+        pushq %rbx;                             \
+        pushq %rbp;                             \
+        pushq %r12;                             \
+        pushq %r13;                             \
+        pushq %r14;                             \
+        pushq %r15;
 
 #define VMRUN  .byte 0x0F,0x01,0xD8
 #define VMLOAD .byte 0x0F,0x01,0xDA
@@ -102,9 +63,9 @@ ENTRY(svm_asm_do_resume)
         GET_CURRENT(%rbx)
         cli                             # tests must not race interrupts
         movl VCPU_processor(%rbx),%eax
-        shl  $IRQSTAT_shift, %rax
-        leaq irq_stat(%rip), %rdx
-        testl $~0, (%rdx, %rax, 1)
+        shl  $IRQSTAT_shift,%rax
+        leaq irq_stat(%rip),%rdx
+        testl $~0,(%rdx,%rax,1)
         jnz  svm_process_softirqs
         call svm_intr_assist
         call svm_load_cr2
@@ -112,15 +73,15 @@ ENTRY(svm_asm_do_resume)
         CLGI                
         sti
         GET_CURRENT(%rbx)
-        movq VCPU_svm_vmcb(%rbx), %rcx
-        movq UREGS_rax(%rsp), %rax
-        movq %rax, VMCB_rax(%rcx)
-        leaq root_vmcb_pa(%rip), %rax
-        movl VCPU_processor(%rbx), %ecx
-        movq (%rax,%rcx,8), %rax
+        movq VCPU_svm_vmcb(%rbx),%rcx
+        movq UREGS_rax(%rsp),%rax
+        movq %rax,VMCB_rax(%rcx)
+        leaq root_vmcb_pa(%rip),%rax
+        movl VCPU_processor(%rbx),%ecx
+        movq (%rax,%rcx,8),%rax
         VMSAVE
 
-        movq VCPU_svm_vmcb_pa(%rbx), %rax
+        movq VCPU_svm_vmcb_pa(%rbx),%rax
         popq %r15
         popq %r14
         popq %r13
@@ -131,26 +92,26 @@ ENTRY(svm_asm_do_resume)
         popq %r10
         popq %r9
         popq %r8
-        /*
-         * Skip %rax, we need to have vmcb address in there.
-         * Don't worry, RAX is restored through the VMRUN instruction.
-         */
-        addq $8, %rsp
+        addq $8,%rsp /* Skip %rax: restored by VMRUN. */
         popq %rcx
         popq %rdx
         popq %rsi
         popq %rdi
-        addq $(NR_SKIPPED_REGS*8), %rsp
+        addq $(NR_SKIPPED_REGS*8),%rsp
 
         VMLOAD
         VMRUN
         VMSAVE
+
         HVM_SAVE_ALL_NOSEGREGS
 
         GET_CURRENT(%rbx)
-        leaq root_vmcb_pa(%rip), %rax
-        movl VCPU_processor(%rbx), %ecx
-        movq (%rax,%rcx,8), %rax
+        movq VCPU_svm_vmcb(%rbx),%rcx
+        movq VMCB_rax(%rcx),%rax
+        movq %rax,UREGS_rax(%rsp)
+        leaq root_vmcb_pa(%rip),%rax
+        movl VCPU_processor(%rbx),%ecx
+        movq (%rax,%rcx,8),%rax
         VMLOAD
 
         STGI

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] svm: Rationalise register synchronisation to be similar to our vmx, Xen patchbot-unstable <=