# 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(¤t->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) = ¤t->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(¤t->arch.arch_vmx.vtm.vtm_timer,
- current->processor);
+ if (VMX_DOMAIN(current)) {
+ vmx_load_all_rr(current);
+ migrate_timer(¤t->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
|