# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1183387919 21600
# Node ID 89596982890b78ebceffc4c5803662adc3dddc73
# Parent eb21b7274ab8acd950fdb631e0d1d22345fad76b
[IA64] Virtualize ibr/dbr for PV domains.
Signed-off-by: Tristan Gingold <tgingold@xxxxxxx>
---
xen/arch/ia64/xen/domain.c | 24 +++++++++-
xen/arch/ia64/xen/ivt.S | 4 -
xen/arch/ia64/xen/vcpu.c | 56 ++++++++++++++++++-------
xen/include/asm-ia64/domain.h | 5 ++
xen/include/asm-ia64/linux-xen/asm/processor.h | 4 +
5 files changed, 73 insertions(+), 20 deletions(-)
diff -r eb21b7274ab8 -r 89596982890b xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Mon Jul 02 08:38:45 2007 -0600
+++ b/xen/arch/ia64/xen/domain.c Mon Jul 02 08:51:59 2007 -0600
@@ -237,6 +237,14 @@ 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. */
@@ -692,6 +700,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;
@@ -721,7 +737,7 @@ int arch_set_info_guest(struct vcpu *v,
struct domain *d = v->domain;
int was_initialised = v->is_initialised;
unsigned int rbs_size;
- int rc;
+ int rc, i;
/* Finish vcpu initialization. */
if (!was_initialised) {
@@ -826,8 +842,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 eb21b7274ab8 -r 89596982890b xen/arch/ia64/xen/ivt.S
--- a/xen/arch/ia64/xen/ivt.S Mon Jul 02 08:38:45 2007 -0600
+++ b/xen/arch/ia64/xen/ivt.S Mon Jul 02 08:51:59 2007 -0600
@@ -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 eb21b7274ab8 -r 89596982890b xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c Mon Jul 02 08:38:45 2007 -0600
+++ b/xen/arch/ia64/xen/vcpu.c Mon Jul 02 08:51:59 2007 -0600
@@ -1773,33 +1773,61 @@ 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 +2030,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 eb21b7274ab8 -r 89596982890b xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h Mon Jul 02 08:38:45 2007 -0600
+++ b/xen/include/asm-ia64/domain.h Mon Jul 02 08:51:59 2007 -0600
@@ -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 eb21b7274ab8 -r 89596982890b
xen/include/asm-ia64/linux-xen/asm/processor.h
--- a/xen/include/asm-ia64/linux-xen/asm/processor.h Mon Jul 02 08:38:45
2007 -0600
+++ b/xen/include/asm-ia64/linux-xen/asm/processor.h Mon Jul 02 08:51:59
2007 -0600
@@ -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;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|