[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] Implement eager save, lazy restore FP algorithm



# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1169574727 25200
# Node ID d12ea0bfecce0aa5b62a9441185330b601487838
# Parent  8bfc6e85eeba6b79ffc8d1f1f8d7049afeed1e88
[IA64] Implement eager save, lazy restore FP algorithm

Signed-off-by: Anthony Xu <anthony.xu@xxxxxxxxx>
---
 xen/arch/ia64/asm-offsets.c                 |    1 
 xen/arch/ia64/asm-xsi-offsets.c             |    2 
 xen/arch/ia64/vmx/optvfault.S               |   15 +++
 xen/arch/ia64/vmx/vmx_process.c             |   66 +++++++++-----
 xen/arch/ia64/vmx/vmx_vcpu.c                |    3 
 xen/arch/ia64/xen/domain.c                  |  131 +++++++++++++++++-----------
 xen/arch/ia64/xen/faults.c                  |   20 ++++
 xen/arch/ia64/xen/hyperprivop.S             |   39 ++++++++
 xen/arch/ia64/xen/vcpu.c                    |   33 ++++++-
 xen/include/asm-ia64/domain.h               |    1 
 xen/include/asm-ia64/linux-xen/asm/percpu.h |    5 +
 xen/include/asm-ia64/vcpu.h                 |    1 
 xen/include/public/arch-ia64.h              |    4 
 13 files changed, 245 insertions(+), 76 deletions(-)

diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/asm-offsets.c
--- a/xen/arch/ia64/asm-offsets.c       Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/asm-offsets.c       Tue Jan 23 10:52:07 2007 -0700
@@ -57,6 +57,7 @@ void foo(void)
 
        DEFINE(IA64_VCPU_DOMAIN_OFFSET, offsetof (struct vcpu, domain));
        DEFINE(IA64_VCPU_HYPERCALL_CONTINUATION_OFS, offsetof (struct vcpu, 
arch.hypercall_continuation));
+       DEFINE(IA64_VCPU_FP_PSR_OFFSET, offsetof (struct vcpu, arch.fp_psr));
        DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct vcpu, 
arch.metaphysical_rr0));
        DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, 
arch.metaphysical_saved_rr0));
        DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, 
arch.breakimm));
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/asm-xsi-offsets.c
--- a/xen/arch/ia64/asm-xsi-offsets.c   Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/asm-xsi-offsets.c   Tue Jan 23 10:52:07 2007 -0700
@@ -61,6 +61,8 @@ void foo(void)
        DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir);
        DEFINE_MAPPED_REG_OFS(XSI_ITV_OFS, itv);
        DEFINE_MAPPED_REG_OFS(XSI_PTA_OFS, pta);
+       DEFINE_MAPPED_REG_OFS(XSI_VPSR_DFH_OFS, vpsr_dfh);
+       DEFINE_MAPPED_REG_OFS(XSI_HPSR_DFH_OFS, hpsr_dfh);
        DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled);
        DEFINE_MAPPED_REG_OFS(XSI_VPSR_PP_OFS, vpsr_pp);
        DEFINE_MAPPED_REG_OFS(XSI_METAPHYS_OFS, metaphysical_mode);
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/vmx/optvfault.S
--- a/xen/arch/ia64/vmx/optvfault.S     Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/vmx/optvfault.S     Tue Jan 23 10:52:07 2007 -0700
@@ -192,6 +192,13 @@ GLOBAL_ENTRY(vmx_asm_rsm)
     ;;   
     st8 [r17]=r19
     and r20=r20,r28
+    adds r27=IA64_VCPU_FP_PSR_OFFSET,r21
+    ;;
+    ld8 r27=[r27]
+    ;;
+    tbit.nz p8,p0= r27,IA64_PSR_DFH_BIT
+    ;;
+    (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1
     ;;
     mov cr.ipsr=r20
     tbit.nz p6,p0=r23,0
@@ -359,6 +366,14 @@ vmx_asm_mov_to_psr_1:
     ;;
     add r20=r19,r20
     mov b0=r24
+    ;;
+    adds r27=IA64_VCPU_FP_PSR_OFFSET,r21
+    ;;
+    ld8 r27=[r27]
+    ;;
+    tbit.nz p8,p0=r27,IA64_PSR_DFH_BIT
+    ;;
+    (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1
     ;;
     mov cr.ipsr=r20
     cmp.ne p6,p0=r0,r0
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c   Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/vmx/vmx_process.c   Tue Jan 23 10:52:07 2007 -0700
@@ -79,36 +79,56 @@ static u64 vec2off[68] = {0x0,0x400,0x80
 
 
 void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim,
-                              u64 vector, REGS *regs)
-{
-    u64 status;
+                              u64 vec, REGS *regs)
+{
+    u64 status, vector;
     VCPU *vcpu = current;
     u64 vpsr = VCPU(vcpu, vpsr);
-    vector=vec2off[vector];
+    
+    vector = vec2off[vec];
     if(!(vpsr&IA64_PSR_IC)&&(vector!=IA64_DATA_NESTED_TLB_VECTOR)){
         panic_domain(regs, "Guest nested fault vector=%lx!\n", vector);
     }
-    else{ // handle fpswa emulation
+
+    switch (vec) {
+
+    case 25:   // IA64_DISABLED_FPREG_VECTOR
+
+        if (FP_PSR(vcpu) & IA64_PSR_DFH) {
+            FP_PSR(vcpu) = IA64_PSR_MFH;
+            if (__ia64_per_cpu_var(fp_owner) != vcpu)
+                __ia64_load_fpu(vcpu->arch._thread.fph);
+        }
+        if (!(VCPU(vcpu, vpsr) & IA64_PSR_DFH)) {
+            regs->cr_ipsr &= ~IA64_PSR_DFH;
+            return;
+        }
+
+        break;       
+        
+    case 32:   // IA64_FP_FAULT_VECTOR
+        // handle fpswa emulation
         // fp fault
-        if (vector == IA64_FP_FAULT_VECTOR) {
-            status = handle_fpu_swa(1, regs, isr);
-            if (!status) {
-                vcpu_increment_iip(vcpu);
-                return;
-            } else if (IA64_RETRY == status)
-                return;
-        }
+        status = handle_fpu_swa(1, regs, isr);
+        if (!status) {
+            vcpu_increment_iip(vcpu);
+            return;
+        } else if (IA64_RETRY == status)
+            return;
+        break;
+
+    case 33:   // IA64_FP_TRAP_VECTOR
         //fp trap
-        else if (vector == IA64_FP_TRAP_VECTOR) {
-            status = handle_fpu_swa(0, regs, isr);
-            if (!status)
-                return;
-            else if (IA64_RETRY == status) {
-                vcpu_decrement_iip(vcpu);
-                return;
-            }
-        }
-    }
+        status = handle_fpu_swa(0, regs, isr);
+        if (!status)
+            return;
+        else if (IA64_RETRY == status) {
+            vcpu_decrement_iip(vcpu);
+            return;
+        }
+        break;
+    
+    } 
     VCPU(vcpu,isr)=isr;
     VCPU(vcpu,iipa) = regs->cr_iip;
     if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/vmx/vmx_vcpu.c
--- a/xen/arch/ia64/vmx/vmx_vcpu.c      Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/vmx/vmx_vcpu.c      Tue Jan 23 10:52:07 2007 -0700
@@ -140,6 +140,9 @@ vmx_vcpu_set_psr(VCPU *vcpu, unsigned lo
         IA64_PSR_VM;
 
     regs->cr_ipsr = (regs->cr_ipsr & mask ) | ( value & (~mask) );
+
+    if (FP_PSR(vcpu) & IA64_PSR_DFH)
+        regs->cr_ipsr |= IA64_PSR_DFH;
 
     check_mm_mode_switch(vcpu, old_psr, new_psr);
     return ;
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/xen/domain.c        Tue Jan 23 10:52:07 2007 -0700
@@ -68,6 +68,8 @@ DEFINE_PER_CPU(uint8_t *, current_psr_i_
 DEFINE_PER_CPU(uint8_t *, current_psr_i_addr);
 DEFINE_PER_CPU(int *, current_psr_ic_addr);
 
+DEFINE_PER_CPU(struct vcpu *, fp_owner);
+
 #include <xen/sched-if.h>
 
 static void
@@ -135,12 +137,44 @@ static void flush_vtlb_for_context_switc
        }
 }
 
+static void lazy_fp_switch(struct vcpu *prev, struct vcpu *next)
+{
+       /*
+        * Implement eager save, lazy restore
+        */
+       if (!is_idle_vcpu(prev)) {
+               if (VMX_DOMAIN(prev)) {
+                       if (FP_PSR(prev) & IA64_PSR_MFH) {
+                               __ia64_save_fpu(prev->arch._thread.fph);
+                               __ia64_per_cpu_var(fp_owner) = prev;
+                       }
+               } else {
+                       if (PSCB(prev, hpsr_mfh)) {
+                               __ia64_save_fpu(prev->arch._thread.fph);
+                               __ia64_per_cpu_var(fp_owner) = prev;
+                       }
+               }
+       }
+
+       if (!is_idle_vcpu(next)) {
+               if (VMX_DOMAIN(next)) {
+                       FP_PSR(next) = IA64_PSR_DFH;
+                       vcpu_regs(next)->cr_ipsr |= IA64_PSR_DFH;
+               } else {
+                       PSCB(next, hpsr_dfh) = 1;
+                       PSCB(next, hpsr_mfh) = 0;
+                       vcpu_regs(next)->cr_ipsr |= IA64_PSR_DFH;
+               }
+       }
+}
+
 void schedule_tail(struct vcpu *prev)
 {
        extern char ia64_ivt;
+
        context_saved(prev);
-
        ia64_disable_vhpt_walker();
+
        if (VMX_DOMAIN(current)) {
                vmx_do_launch(current);
                migrate_timer(&current->arch.arch_vmx.vtm.vtm_timer,
@@ -148,7 +182,7 @@ void schedule_tail(struct vcpu *prev)
        } else {
                ia64_set_iva(&ia64_ivt);
                load_region_regs(current);
-               ia64_set_pta(vcpu_pta(current));
+               ia64_set_pta(vcpu_pta(current));
                vcpu_load_kernel_regs(current);
                __ia64_per_cpu_var(current_psr_i_addr) = &current->domain->
                  shared_info->vcpu_info[current->vcpu_id].evtchn_upcall_mask;
@@ -165,64 +199,67 @@ void context_switch(struct vcpu *prev, s
 
     local_irq_save(spsr);
 
-    if (!is_idle_domain(prev->domain)) 
-        __ia64_save_fpu(prev->arch._thread.fph);
-    if (!is_idle_domain(next->domain)) 
-        __ia64_load_fpu(next->arch._thread.fph);
-
     if (VMX_DOMAIN(prev)) {
-       vmx_save_state(prev);
-       if (!VMX_DOMAIN(next)) {
-           /* VMX domains can change the physical cr.dcr.
-            * Restore default to prevent leakage. */
-           ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK
-                          | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP
-                          | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC));
-       }
+        vmx_save_state(prev);
+        if (!VMX_DOMAIN(next)) {
+            /* VMX domains can change the physical cr.dcr.
+             * Restore default to prevent leakage. */
+            ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK
+                           | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP
+                           | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC));
+        }
     }
     if (VMX_DOMAIN(next))
-       vmx_load_state(next);
+        vmx_load_state(next);
 
     ia64_disable_vhpt_walker();
-    /*ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next);*/
+    lazy_fp_switch(prev, current);
+
     prev = ia64_switch_to(next);
 
     /* Note: ia64_switch_to does not return here at vcpu initialization.  */
 
-    //cpu_set(smp_processor_id(), current->domain->domain_dirty_cpumask);
- 
-    if (VMX_DOMAIN(current)){
-       vmx_load_all_rr(current);
-       migrate_timer(&current->arch.arch_vmx.vtm.vtm_timer,
-                     current->processor);
+    if (VMX_DOMAIN(current)) {
+        vmx_load_all_rr(current);
+        migrate_timer(&current->arch.arch_vmx.vtm.vtm_timer,
+                      current->processor);
     } else {
-       struct domain *nd;
-       extern char ia64_ivt;
-
-       ia64_set_iva(&ia64_ivt);
-
-       nd = current->domain;
-       if (!is_idle_domain(nd)) {
-               load_region_regs(current);
-               ia64_set_pta(vcpu_pta(current));
-               vcpu_load_kernel_regs(current);
-               vcpu_set_next_timer(current);
-               if (vcpu_timer_expired(current))
-                       vcpu_pend_timer(current);
-               __ia64_per_cpu_var(current_psr_i_addr) = &nd->shared_info->
-                 vcpu_info[current->vcpu_id].evtchn_upcall_mask;
-               __ia64_per_cpu_var(current_psr_ic_addr) =
-                 (int *)(nd->arch.shared_info_va + XSI_PSR_IC_OFS);
-       } else {
-               /* When switching to idle domain, only need to disable vhpt
-                * walker. Then all accesses happen within idle context will
-                * be handled by TR mapping and identity mapping.
-                */
-               __ia64_per_cpu_var(current_psr_i_addr) = NULL;
-               __ia64_per_cpu_var(current_psr_ic_addr) = NULL;
+        struct domain *nd;
+        extern char ia64_ivt;
+
+        ia64_set_iva(&ia64_ivt);
+
+        nd = current->domain;
+        if (!is_idle_domain(nd)) {
+            load_region_regs(current);
+            ia64_set_pta(vcpu_pta(current));
+            vcpu_load_kernel_regs(current);
+            vcpu_set_next_timer(current);
+            if (vcpu_timer_expired(current))
+                vcpu_pend_timer(current);
+            __ia64_per_cpu_var(current_psr_i_addr) = &nd->shared_info->
+                vcpu_info[current->vcpu_id].evtchn_upcall_mask;
+            __ia64_per_cpu_var(current_psr_ic_addr) =
+                (int *)(nd->arch.shared_info_va + XSI_PSR_IC_OFS);
+        } else {
+            /* When switching to idle domain, only need to disable vhpt
+             * walker. Then all accesses happen within idle context will
+             * be handled by TR mapping and identity mapping.
+             */
+            __ia64_per_cpu_var(current_psr_i_addr) = NULL;
+            __ia64_per_cpu_var(current_psr_ic_addr) = NULL;
         }
     }
     local_irq_restore(spsr);
+
+    /* lazy fp */
+    if (current->processor != current->arch.last_processor) {
+        unsigned long *addr;
+        addr = (unsigned long *)per_cpu_addr(fp_owner,
+                                             current->arch.last_processor);
+        ia64_cmpxchg(acq, addr, current, 0, 8);
+    }
+   
     flush_vtlb_for_context_switch(prev, current);
     context_saved(prev);
 }
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/xen/faults.c
--- a/xen/arch/ia64/xen/faults.c        Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/xen/faults.c        Tue Jan 23 10:52:07 2007 -0700
@@ -92,6 +92,9 @@ void reflect_interruption(unsigned long 
        regs->cr_iip = ((unsigned long)PSCBX(v, iva) + vector) & ~0xffUL;
        regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
 
+       if (PSCB(v, hpsr_dfh))
+               regs->cr_ipsr |= IA64_PSR_DFH;  
+       PSCB(v, vpsr_dfh) = 0;
        v->vcpu_info->evtchn_upcall_mask = 1;
        PSCB(v, interrupt_collection_enabled) = 0;
 
@@ -152,6 +155,9 @@ void reflect_event(void)
        regs->cr_iip = v->arch.event_callback_ip;
        regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
 
+       if (PSCB(v, hpsr_dfh))
+               regs->cr_ipsr |= IA64_PSR_DFH;
+       PSCB(v, vpsr_dfh) = 0;
        v->vcpu_info->evtchn_upcall_mask = 1;
        PSCB(v, interrupt_collection_enabled) = 0;
 }
@@ -261,6 +267,10 @@ void ia64_do_page_fault(unsigned long ad
                    ((unsigned long)PSCBX(current, iva) + fault) & ~0xffUL;
                regs->cr_ipsr =
                    (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
+
+               if (PSCB(current, hpsr_dfh))
+                       regs->cr_ipsr |= IA64_PSR_DFH;  
+               PSCB(current, vpsr_dfh) = 0;
                perfc_incra(slow_reflect, fault >> 8);
                return;
        }
@@ -608,6 +618,16 @@ ia64_handle_reflection(unsigned long ifa
                vector = IA64_GENEX_VECTOR;
                break;
        case 25:
+               if (PSCB(v, hpsr_dfh)) {
+                       PSCB(v, hpsr_dfh) = 0;
+                       PSCB(v, hpsr_mfh) = 1;
+                       if (__ia64_per_cpu_var(fp_owner) != v)
+                               __ia64_load_fpu(v->arch._thread.fph);
+               }
+               if (!PSCB(v, vpsr_dfh)) {
+                       regs->cr_ipsr &= ~IA64_PSR_DFH;
+                       return;
+               }
                vector = IA64_DISABLED_FPREG_VECTOR;
                break;
        case 26:
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/xen/hyperprivop.S
--- a/xen/arch/ia64/xen/hyperprivop.S   Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/xen/hyperprivop.S   Tue Jan 23 10:52:07 2007 -0700
@@ -252,6 +252,10 @@ ENTRY(hyper_ssm_i)
        movl r27=~DELIVER_PSR_CLR;;
        or r29=r29,r28;;
        and r29=r29,r27;;
+       // set hpsr_dfh to ipsr
+       adds r28=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;;
+       ld1 r28=[r28];;
+       dep r29=r28,r29,IA64_PSR_DFH_BIT,1;;
        mov cr.ipsr=r29;;
        // set shared_mem ipsr (from ipsr in r30 with ipsr.ri already set)
        extr.u r29=r30,IA64_PSR_CPL0_BIT,2;;
@@ -269,6 +273,12 @@ ENTRY(hyper_ssm_i)
        movl r22=THIS_CPU(current_psr_i_addr)
        adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
        ld8 r22=[r22]
+       ;;
+       adds r27=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;;
+       ld1 r28=[r27];;
+       st1 [r27]=r0
+       dep r30=r28,r30,IA64_PSR_DFH_BIT,1
+       ;;
        st8 [r21]=r30;;
        // set shared_mem interrupt_delivery_enabled to 0
        // set shared_mem interrupt_collection_enabled to 0
@@ -607,6 +617,10 @@ ENTRY(fast_reflect)
        movl r27=~(DELIVER_PSR_CLR|IA64_PSR_CPL0);;
        or r29=r29,r28;;
        and r29=r29,r27;;
+       // set hpsr_dfh to ipsr
+       adds r28=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;;
+       ld1 r28=[r28];;
+       dep r29=r28,r29,IA64_PSR_DFH_BIT,1;;
        mov cr.ipsr=r29;;
        // set shared_mem ipsr (from ipsr in r30 with ipsr.ri already set)
        extr.u r29=r30,IA64_PSR_CPL0_BIT,2;;
@@ -629,7 +643,13 @@ ENTRY(fast_reflect)
 (p6)   dep r30=0,r30,IA64_PSR_I_BIT,1
 (p7)   dep r30=-1,r30,IA64_PSR_I_BIT,1 ;;
        mov r22=1
-       adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
+       adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 
+       ;;
+       adds r27=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;;
+       ld1 r28=[r27];;
+       st1 [r27]=r0
+       dep r30=r28,r30,IA64_PSR_DFH_BIT,1
+       ;;
        st8 [r21]=r30 ;;
        // set shared_mem interrupt_delivery_enabled to 0
        // set shared_mem interrupt_collection_enabled to 0
@@ -1103,6 +1123,18 @@ just_do_rfi:
                  IA64_PSR_IT|IA64_PSR_BN)
        ;;
        or r21=r21,r20
+       ;;
+       adds r20=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;;
+       tbit.z p8,p9 = r21, IA64_PSR_DFH_BIT
+       ;;
+       (p9) mov r27=1;;
+       (p9) st1 [r20]=r27
+       ;;
+       (p8) st1 [r20]=r0
+       (p8) adds r20=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;;
+       (p8) ld1 r27=[r20]
+       ;;
+       (p8) dep r21=r27,r21, IA64_PSR_DFH_BIT, 1
        ;;
        mov cr.ipsr=r21
        adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;;
@@ -1488,6 +1520,11 @@ ENTRY(hyper_get_psr)
        ld8 r20=[r20];;
        ld1 r21=[r20];;
        dep r8=r21,r8,IA64_PSR_I_BIT,1
+       ;;
+       // set vpsr.dfh
+       adds r20=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;;
+       ld1 r21=[r20];;
+       dep r8=r21,r8,IA64_PSR_DFH_BIT,1
        ;;
        mov r25=cr.iip
        extr.u r26=r24,41,2 ;;
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c  Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/arch/ia64/xen/vcpu.c  Tue Jan 23 10:52:07 2007 -0700
@@ -141,6 +141,9 @@ void vcpu_init_regs(struct vcpu *v)
                /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
                /* Need to be expanded as macro */
                regs->cr_ipsr = 0x501008826008;
+               /* lazy fp */
+               FP_PSR(v) = IA64_PSR_DFH;
+               regs->cr_ipsr |= IA64_PSR_DFH;
        } else {
                regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
                    | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
@@ -148,6 +151,10 @@ void vcpu_init_regs(struct vcpu *v)
                                   | IA64_PSR_RI | IA64_PSR_IS);
                // domain runs at PL2
                regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
+               // lazy fp 
+               PSCB(v, hpsr_dfh) = 1;
+               PSCB(v, hpsr_mfh) = 0;
+               regs->cr_ipsr |= IA64_PSR_DFH;
        }
        regs->cr_ifs = 1UL << 63;       /* or clear? */
        regs->ar_fpsr = FPSR_DEFAULT;
@@ -265,8 +272,10 @@ IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu,
                      IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
                      IA64_PSR_DFL | IA64_PSR_DFH))
                return IA64_ILLOP_FAULT;
-       if (imm.dfh)
-               ipsr->dfh = 0;
+       if (imm.dfh) {
+               ipsr->dfh = PSCB(vcpu, hpsr_dfh);
+               PSCB(vcpu, vpsr_dfh) = 0;
+       }
        if (imm.dfl)
                ipsr->dfl = 0;
        if (imm.pp) {
@@ -320,8 +329,10 @@ IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u
            IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH;
        if (imm24 & ~mask)
                return IA64_ILLOP_FAULT;
-       if (imm.dfh)
+       if (imm.dfh) {
+               PSCB(vcpu, vpsr_dfh) = 1;
                ipsr->dfh = 1;
+       } 
        if (imm.dfl)
                ipsr->dfl = 1;
        if (imm.pp) {
@@ -386,8 +397,13 @@ IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u6
        //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP))
        //      return IA64_ILLOP_FAULT;
        // however trying to set other bits can't be an error as it is in ssm
-       if (newpsr.dfh)
+       if (newpsr.dfh) {
                ipsr->dfh = 1;
+               PSCB(vcpu, vpsr_dfh) = 1;
+       } else {
+               ipsr->dfh = PSCB(vcpu, hpsr_dfh);
+               PSCB(vcpu, vpsr_dfh) = 0;
+       }       
        if (newpsr.dfl)
                ipsr->dfl = 1;
        if (newpsr.pp) {
@@ -466,6 +482,8 @@ IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 
                newpsr.pp = 1;
        else
                newpsr.pp = 0;
+       newpsr.dfh = PSCB(vcpu, vpsr_dfh);
+
        *pval = *(unsigned long *)&newpsr;
        *pval &= (MASK(0, 32) | MASK(35, 2));
        return IA64_NO_FAULT;
@@ -497,6 +515,7 @@ u64 vcpu_get_ipsr_int_state(VCPU * vcpu,
        psr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
        psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
        psr.ia64_psr.bn = PSCB(vcpu, banknum);
+       psr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh);
        psr.ia64_psr.dt = 1;
        psr.ia64_psr.it = 1;
        psr.ia64_psr.rt = 1;
@@ -1343,6 +1362,12 @@ IA64FAULT vcpu_rfi(VCPU * vcpu)
        if (psr.ia64_psr.cpl < 3)
                psr.ia64_psr.cpl = 2;
        int_enable = psr.ia64_psr.i;
+       if (psr.ia64_psr.dfh) {
+               PSCB(vcpu, vpsr_dfh) = 1;
+       } else {
+               psr.ia64_psr.dfh = PSCB(vcpu, hpsr_dfh);
+               PSCB(vcpu, vpsr_dfh) = 0;
+       }
        if (psr.ia64_psr.ic)
                PSCB(vcpu, interrupt_collection_enabled) = 1;
        if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it)
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h     Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/include/asm-ia64/domain.h     Tue Jan 23 10:52:07 2007 -0700
@@ -175,6 +175,7 @@ struct arch_vcpu {
     unsigned long metaphysical_rr4;            // from arch_domain (so is 
pinned)
     unsigned long metaphysical_saved_rr0;      // from arch_domain (so is 
pinned)
     unsigned long metaphysical_saved_rr4;      // from arch_domain (so is 
pinned)
+    unsigned long fp_psr;       // used for lazy float register
     int breakimm;                      // from arch_domain (so is pinned)
     int starting_rid;          /* first RID assigned to domain */
     int ending_rid;            /* one beyond highest RID assigned to domain */
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/include/asm-ia64/linux-xen/asm/percpu.h
--- a/xen/include/asm-ia64/linux-xen/asm/percpu.h       Tue Jan 23 09:45:26 
2007 -0700
+++ b/xen/include/asm-ia64/linux-xen/asm/percpu.h       Tue Jan 23 10:52:07 
2007 -0700
@@ -43,6 +43,9 @@ DECLARE_PER_CPU(unsigned long, local_per
 
 #define per_cpu(var, cpu)  (*RELOC_HIDE(&per_cpu__##var, 
__per_cpu_offset[cpu]))
 #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, 
__ia64_per_cpu_var(local_per_cpu_offset)))
+#ifdef XEN
+#define per_cpu_addr(var, cpu)  (RELOC_HIDE(&per_cpu__##var, 
__per_cpu_offset[cpu]))
+#endif
 
 extern void percpu_modcopy(void *pcpudst, const void *src, unsigned long size);
 extern void setup_per_cpu_areas (void);
@@ -67,6 +70,8 @@ extern void *per_cpu_init(void);
  */
 #define __ia64_per_cpu_var(var)        (per_cpu__##var)
 
+DECLARE_PER_CPU(struct vcpu *, fp_owner);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_IA64_PERCPU_H */
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/include/asm-ia64/vcpu.h
--- a/xen/include/asm-ia64/vcpu.h       Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/include/asm-ia64/vcpu.h       Tue Jan 23 10:52:07 2007 -0700
@@ -20,6 +20,7 @@ extern u64 cycle_to_ns(u64 cycle);
 #define VCPU(_v,_x)    (_v->arch.privregs->_x)
 #define PSCB(_v,_x)    VCPU(_v,_x)
 #define PSCBX(_v,_x)   (_v->arch._x)
+#define FP_PSR(_v)     PSCBX(_v, fp_psr)
 
 #define SPURIOUS_VECTOR 0xf
 
diff -r 8bfc6e85eeba -r d12ea0bfecce xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h    Tue Jan 23 09:45:26 2007 -0700
+++ b/xen/include/public/arch-ia64.h    Tue Jan 23 10:52:07 2007 -0700
@@ -288,7 +288,9 @@ struct mapped_regs {
             unsigned char *interrupt_mask_addr;
             int pending_interruption;
             unsigned char vpsr_pp;
-            unsigned char reserved5_2[3];
+            unsigned char vpsr_dfh;
+            unsigned char hpsr_dfh;
+            unsigned char hpsr_mfh;
             unsigned long reserved5_1[4];
             int metaphysical_mode; // 1 = use metaphys mapping, 0 = use virtual
             int banknum; // 0 or 1, which virtual register bank is active

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.