# HG changeset patch # User Tristan Gingold # Date 1182910939 -7200 # Node ID a4e2b5305503db01efc92663808be0aef859b727 # Parent dddbacf2e2f5532a4cf73a03066d13e0b52d36c5 Virtualize ibr/dbr for PV domains. Signed-off-by: Tristan Gingold diff -r dddbacf2e2f5 -r a4e2b5305503 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Sun Jun 24 05:21:41 2007 +0200 +++ b/xen/arch/ia64/xen/domain.c Wed Jun 27 04:22:19 2007 +0200 @@ -237,6 +237,12 @@ void context_switch(struct vcpu *prev, s ia64_disable_vhpt_walker(); lazy_fp_switch(prev, current); + if (prev->arch.dbg_used || next->arch.dbg_used) { + /* Load debug registers either because they are valid or to clear + the previous one. */ + ia64_load_debug_regs (next->arch.dbr); + } + prev = ia64_switch_to(next); /* Note: ia64_switch_to does not return here at vcpu initialization. */ @@ -693,6 +699,14 @@ void arch_get_info_guest(struct vcpu *v, c.nat->privregs_pfn = get_gpfn_from_mfn (virt_to_maddr(v->arch.privregs) >> PAGE_SHIFT); + for (i = 0; i < IA64_NUM_DBG_REGS; i++) { + vcpu_get_dbr (v, i, &c.nat->regs.dbr[i]); + vcpu_get_ibr (v, i, &c.nat->regs.ibr[i]); + } + + for (i = 0; i < 7; i++) + vcpu_get_rr (v, (unsigned long)i << 61, &c.nat->regs.rr[i]); + /* Fill extra regs. */ for (i = 0; i < 8; i++) { tr->itrs[i].pte = v->arch.itrs[i].pte.val; @@ -723,6 +737,7 @@ int arch_set_info_guest(struct vcpu *v, int was_initialised = v->is_initialised; unsigned int rbs_size; int rc; + int i; /* Finish vcpu initialization. */ if (!was_initialised) { @@ -828,8 +843,12 @@ int arch_set_info_guest(struct vcpu *v, uregs->ar_rsc |= (2 << 2); /* force PL2/3 */ } + for (i = 0; i < IA64_NUM_DBG_REGS; i++) { + vcpu_set_dbr (v, i, c.nat->regs.dbr[i]); + vcpu_set_ibr (v, i, c.nat->regs.ibr[i]); + } + if (c.nat->flags & VGCF_EXTRA_REGS) { - int i; struct vcpu_tr_regs *tr = &c.nat->regs.tr; for (i = 0; i < 8; i++) { diff -r dddbacf2e2f5 -r a4e2b5305503 xen/arch/ia64/xen/ivt.S --- a/xen/arch/ia64/xen/ivt.S Sun Jun 24 05:21:41 2007 +0200 +++ b/xen/arch/ia64/xen/ivt.S Wed Jun 27 04:22:19 2007 +0200 @@ -1183,11 +1183,7 @@ END(speculation_vector) // 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56) ENTRY(debug_vector) DBG_FAULT(29) -#ifdef XEN FAULT_OR_REFLECT(29) -#else - FAULT(29) -#endif END(debug_vector) .org ia64_ivt+0x5a00 diff -r dddbacf2e2f5 -r a4e2b5305503 xen/arch/ia64/xen/vcpu.c --- a/xen/arch/ia64/xen/vcpu.c Sun Jun 24 05:21:41 2007 +0200 +++ b/xen/arch/ia64/xen/vcpu.c Wed Jun 27 04:22:19 2007 +0200 @@ -1773,33 +1773,63 @@ IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val) { - // TODO: unimplemented DBRs return a reserved register fault - // TODO: Should set Logical CPU state, not just physical - ia64_set_dbr(reg, val); + if (reg >= IA64_NUM_DBG_REGS) + return IA64_RSVDREG_FAULT; + if ((reg & 1) == 0) { + /* Validate address. */ + if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END) + return IA64_ILLOP_FAULT; + } + else { + /* Mask PL0. */ + val &= ~(1UL << 56); + } + if (val != 0) + vcpu->arch.dbg_used |= (1 << reg); + else + vcpu->arch.dbg_used &= ~(1 << reg); + vcpu->arch.dbr[reg] = val; + if (vcpu == current) + ia64_set_dbr(reg, val); return IA64_NO_FAULT; } IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val) { - // TODO: unimplemented IBRs return a reserved register fault - // TODO: Should set Logical CPU state, not just physical - ia64_set_ibr(reg, val); + if (reg >= IA64_NUM_DBG_REGS) + return IA64_RSVDREG_FAULT; + if ((reg & 1) == 0) { + /* Validate address. */ + if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END) + return IA64_ILLOP_FAULT; + } + else { + /* Mask PL0. */ + val &= ~(1UL << 56); + } + if (val != 0) + vcpu->arch.dbg_used |= (1 << (reg + IA64_NUM_DBG_REGS)); + else + vcpu->arch.dbg_used &= ~(1 << (reg + IA64_NUM_DBG_REGS)); + vcpu->arch.ibr[reg] = val; + if (vcpu == current) + ia64_set_ibr(reg, val); return IA64_NO_FAULT; } IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval) { - // TODO: unimplemented DBRs return a reserved register fault - u64 val = ia64_get_dbr(reg); - *pval = val; + if (reg >= IA64_NUM_DBG_REGS) + return IA64_RSVDREG_FAULT; + *pval = vcpu->arch.dbr[reg]; return IA64_NO_FAULT; } IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval) { - // TODO: unimplemented IBRs return a reserved register fault - u64 val = ia64_get_ibr(reg); - *pval = val; + if (reg >= IA64_NUM_DBG_REGS) + return IA64_RSVDREG_FAULT; + *pval = vcpu->arch.ibr[reg]; return IA64_NO_FAULT; } @@ -2002,8 +2032,8 @@ IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 r IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val) { PSCB(vcpu, rrs)[reg >> 61] = val; - // warning: set_one_rr() does it "live" - set_one_rr(reg, val); + if (vcpu == current) + set_one_rr(reg, val); return IA64_NO_FAULT; } diff -r dddbacf2e2f5 -r a4e2b5305503 xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Sun Jun 24 05:21:41 2007 +0200 +++ b/xen/include/asm-ia64/domain.h Wed Jun 27 04:22:19 2007 +0200 @@ -180,6 +180,11 @@ struct arch_vcpu { int starting_rid; /* first RID assigned to domain */ int ending_rid; /* one beyond highest RID assigned to domain */ + /* Bitset for debug register use. */ + unsigned int dbg_used; + u64 dbr[IA64_NUM_DBG_REGS]; + u64 ibr[IA64_NUM_DBG_REGS]; + struct thread_struct _thread; // this must be last thash_cb_t vtlb; diff -r dddbacf2e2f5 -r a4e2b5305503 xen/include/asm-ia64/linux-xen/asm/processor.h --- a/xen/include/asm-ia64/linux-xen/asm/processor.h Sun Jun 24 05:21:41 2007 +0200 +++ b/xen/include/asm-ia64/linux-xen/asm/processor.h Wed Jun 27 04:22:19 2007 +0200 @@ -292,11 +292,14 @@ struct thread_struct { #else # define INIT_THREAD_PM #endif +#ifndef XEN __u64 dbr[IA64_NUM_DBG_REGS]; __u64 ibr[IA64_NUM_DBG_REGS]; +#endif struct ia64_fpreg fph[96]; /* saved/loaded on demand */ }; +#ifndef XEN #define INIT_THREAD { \ .flags = 0, \ .on_ustack = 0, \ @@ -333,6 +336,7 @@ struct thread_struct { regs->r1 = 0; regs->r9 = 0; regs->r11 = 0; regs->r13 = 0; regs->r15 = 0; \ } \ } while (0) +#endif /* Forward declarations, a strange C thing... */ struct mm_struct;