Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2870

kernel-2.6.18-128.1.10.el5.src.rpm

From: Tetsu Yamamoto <tyamamot@redhat.com>
Date: Mon, 14 Jan 2008 12:12:21 -0500
Subject: [xen] virtualize ibr/dbr for PV domains
Message-id: 20080114171221.17245.50369.sendpatchset@dhcp78-13.lab.boston.redhat.com
O-Subject: [RHEL5.2 PATCH 1/2][Xen][Take2] domU HVM application cannot debug via gdb
Bugzilla: 426362

# HG changeset patch
# User Kouya Shimura <kouya@jp.fujitsu.com>
# Date 1200028121 -32400
# Node ID 0aaefec6775aeedcbbb5193d3bf8ccc00c6a6bf7
# Parent  227b6138b15f9f7bd2ad2d6ea3f81d2c6a5c3c16
ia64 cset 15414
[IA64] Virtualize ibr/dbr for PV domains.

Signed-off-by: Tristan Gingold <tgingold@free.fr>

Acked-by: "Stephen C. Tweedie" <sct@redhat.com>
Acked-by: Bill Burns <bburns@redhat.com>
Acked-by: Jarod Wilson <jwilson@redhat.com>

diff --git a/arch/ia64/xen/domain.c b/arch/ia64/xen/domain.c
index 02968c9..57f528a 100644
--- a/arch/ia64/xen/domain.c
+++ b/arch/ia64/xen/domain.c
@@ -238,6 +238,14 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
     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.  */
diff --git a/arch/ia64/xen/ivt.S b/arch/ia64/xen/ivt.S
index ac55769..5bee6d6 100644
--- a/arch/ia64/xen/ivt.S
+++ b/arch/ia64/xen/ivt.S
@@ -2103,11 +2103,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 --git a/arch/ia64/xen/vcpu.c b/arch/ia64/xen/vcpu.c
index fae2520..3f0263d 100644
--- a/arch/ia64/xen/vcpu.c
+++ b/arch/ia64/xen/vcpu.c
@@ -1749,33 +1749,61 @@ IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
 
 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;
 }
 
@@ -1978,8 +2006,8 @@ unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
 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 --git a/include/asm-ia64/domain.h b/include/asm-ia64/domain.h
index 80af70c..ba414d8 100644
--- a/include/asm-ia64/domain.h
+++ b/include/asm-ia64/domain.h
@@ -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 --git a/include/asm-ia64/linux-xen/asm/processor.h b/include/asm-ia64/linux-xen/asm/processor.h
index fb753e0..4a1e070 100644
--- a/include/asm-ia64/linux-xen/asm/processor.h
+++ b/include/asm-ia64/linux-xen/asm/processor.h
@@ -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;