# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1217474750 -32400
# Node ID e9706492e960ba7d8c79476c80183f5a86ae1dbc
# Parent c587457f6916456f6cf210255cd156e6f426fc91
[IA64] Fix mca handler so as not to destroy ar
This patchf ixes the mca handler so as not to destroy ar
and some bugs.
On mca the firmware saves non-banked and banked general registers
and the most of ar registers must be unchanged.
However before ia64_os_mca_proc_state_dump saves such registers,
the cited hunks unconditionally overwrite ar.k[36] so that
they are destroyed.
Signed-off-by: Kazuhiro Suzuki <kaz@xxxxxxxxxxxxxx>
---
xen/arch/ia64/linux-xen/mca_asm.S | 220 +++++++++++++++------------
xen/arch/ia64/xen/regionreg.c | 3
xen/include/asm-ia64/linux-xen/asm/mca_asm.h | 29 +++
xen/include/asm-ia64/regionreg.h | 1
4 files changed, 160 insertions(+), 93 deletions(-)
diff -r c587457f6916 -r e9706492e960 xen/arch/ia64/linux-xen/mca_asm.S
--- a/xen/arch/ia64/linux-xen/mca_asm.S Mon Jul 28 17:29:09 2008 +0900
+++ b/xen/arch/ia64/linux-xen/mca_asm.S Thu Jul 31 12:25:50 2008 +0900
@@ -154,71 +154,6 @@
.text
.align 16
-#ifdef XEN
-/*
- * void set_per_cpu_data(void)
- * {
- * int i;
- * for (i = 0; i < 64; i++) {
- * if (ia64_mca_tlb_list[i].cr_lid == ia64_getreg(_IA64_REG_CR_LID)) {
- * ia64_set_kr(IA64_KR_PER_CPU_DATA, ia64_mca_tlb_list[i].percpu_paddr);
- * return;
- * }
- * }
- * while(1); // Endless loop on error
- * }
- */
-#define SET_PER_CPU_DATA() \
- LOAD_PHYSICAL(p0,r2,ia64_mca_tlb_list);; \
- mov r7 = r0; \
- mov r6 = r0;; \
- adds r3 = IA64_MCA_PERCPU_OFFSET, r2; \
-1: add r4 = r6, r2; \
- mov r5=cr.lid;; \
- adds r7 = 1, r7; \
- ld8 r4 = [r4];; \
- cmp.ne p6, p7 = r5, r4; \
- cmp4.lt p8, p9 = NR_CPUS-1, r7; \
-(p7) br.cond.dpnt 3f; \
- adds r6 = 16, r6; \
-(p9) br.cond.sptk 1b; \
-2: br 2b;; /* Endless loop on error */ \
-3: add r4 = r6, r3;; \
- ld8 r4 = [r4];; \
- mov ar.k3=r4
-
-/*
- * GET_VA_VCPU_VHPT_MADDR() emulates 'reg = __va_ul(vcpu_vhpt_maddr(v))'.
- */
-#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
-#define HAS_PERVCPU_VHPT_MASK 0x2
-#define GET_VA_VCPU_VHPT_MADDR(reg,tmp) \
- GET_THIS_PADDR(reg,cpu_kr);; \
- add reg=IA64_KR_CURRENT_OFFSET,reg;; \
- ld8 reg=[reg];; \
- dep tmp=0,reg,60,4;; /* V to P */ \
- add tmp=IA64_VCPU_VHPT_PAGE_OFFSET,tmp;; \
- ld8 tmp=[tmp];; \
- cmp.eq p6,p0=tmp,r0; /* v->arch.vhpt_page == NULL */ \
-(p6) br.cond.sptk 1f; \
- add reg=IA64_VCPU_VHPT_MADDR_OFFSET,reg;; \
- dep reg=0,reg,60,4;; /* V to P */ \
- ld8 reg=[reg];; \
- dep reg=-1,reg,60,4; /* P to V */ \
- br.sptk 2f; \
-1: \
- GET_THIS_PADDR(reg, vhpt_paddr);; \
- ld8 reg=[reg];; \
- dep reg=-1,reg,60,4; /* P to V */ \
-2:
-#else /* CONFIG_XEN_IA64_PERVCPU_VHPT */
-#define GET_VA_VCPU_VHPT_MADDR(reg,tmp) \
- GET_THIS_PADDR(reg, vhpt_paddr);; \
- ld8 reg=[reg];; \
- dep reg=-1,reg,60,4 /* P to V */
-#endif /* CONFIG_XEN_IA64_PERVCPU_VHPT */
-#endif /* XEN */
-
/*
* Just the TLB purge part is moved to a separate function
* so we can re-use the code for cpu hotplug code as well
@@ -227,10 +162,6 @@ 2:
*/
ia64_do_tlb_purge:
-#ifdef XEN
- // This needs to be called in order for GET_THIS_PADDR to work
- SET_PER_CPU_DATA();;
-#endif
#define O(member) IA64_CPUINFO_##member##_OFFSET
GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2
@@ -346,15 +277,19 @@ 4:
// a VMX domain hasn't been started since boot
GET_THIS_PADDR(r2, inserted_vpd);;
ld8 r16=[r2]
- mov r18=XMAPPEDREGS_SHIFT<<2
- ;;
- cmp.eq p7,p0=r2,r0
+ mov r18=IA64_GRANULE_SHIFT<<2
+ ;;
+ cmp.eq p7,p0=r16,r0
;;
(p7) br.cond.sptk .vpd_not_mapped
;;
ptr.i r16,r18
;;
+ ptr.d r16,r18
+ ;;
srlz.i
+ ;;
+ srlz.d
;;
.vpd_not_mapped:
@@ -362,6 +297,7 @@ 4:
// GET_VA_VCPU_VHPT_MADDR() may not give the
// value of the VHPT currently pinned into the TLB
GET_THIS_PADDR(r2, inserted_vhpt);;
+ ld8 r2=[r2]
;;
cmp.eq p7,p0=r2,r0
;;
@@ -389,9 +325,6 @@ ia64_os_mca_spin:
cmp.ne p6,p0=r4,r0
(p6) br ia64_os_mca_spin
-#ifdef XEN
- SET_PER_CPU_DATA();;
-#endif
// Save the SAL to OS MCA handoff state as defined
// by SAL SPEC 3.0
// NOTE : The order in which the state gets saved
@@ -524,24 +457,129 @@ ia64_reload_tr:
srlz.d
;;
#ifdef XEN
-.reload_vhpt:
- // 5. VHPT
- GET_THIS_PADDR(r1, inserted_vhpt);;
- cmp.eq p7,p0=r2,r0
-(p7) br.cond.sptk .overlap_vhpt // vhpt isn't mapped.
+ // if !VMX_DOMAIN(current)
+ // pin down shared_info and mapped_regs
+ // else
+ // pin down VPD
+ GET_THIS_PADDR(r2,cpu_kr);;
+ add r2=IA64_KR_CURRENT_OFFSET,r2
+ ;;
+ ld8 r2=[r2]
+ ;;
+ dep r2=0,r2,60,4
+ ;;
+ add r2=IA64_VCPU_FLAGS_OFFSET,r2
+ ;;
+ ld8 r2=[r2]
+ ;;
+ cmp.eq p6,p7 = r2,r0
+(p7) br.cond.sptk .vmx_domain
+
+ // 5. shared_info
+ GET_THIS_PADDR(r2, inserted_shared_info);;
+ ld8 r16=[r2]
+ mov r18=XSI_SHIFT<<2
+ movl r20=__pgprot(__DIRTY_BITS | _PAGE_PL_PRIV | _PAGE_AR_RW)
+ ;;
+ GET_THIS_PADDR(r2, domain_shared_info);;
+ ld8 r17=[r2]
+ ;;
+ dep r17=0,r17,60,4
+ ;;
+ or r17=r17,r20 // construct PA | page properties
+ mov cr.itir=r18
+ mov cr.ifa=r16
+ ;;
+ mov r16=IA64_TR_SHARED_INFO
+ ;;
+ itr.d dtr[r16]=r17 // wire in new mapping...
+ ;;
+ srlz.d
+ ;;
+
+ // 6. mapped_regs
+ GET_THIS_PADDR(r2, inserted_mapped_regs);;
+ ld8 r16=[r2]
+ mov r18=XMAPPEDREGS_SHIFT<<2
+ ;;
+ GET_THIS_PADDR(r2,cpu_kr);;
+ add r2=IA64_KR_CURRENT_OFFSET,r2
+ ;;
+ ld8 r2=[r2]
+ ;;
+ dep r2=0,r2,60,4
+ ;;
+ add r2=IA64_VPD_BASE_OFFSET,r2
+ ;;
+ ld8 r17=[r2]
+ ;;
+ dep r17=0,r17,60,4
+ ;;
+ or r17=r17,r20 // construct PA | page properties
+ mov cr.itir=r18
+ mov cr.ifa=r16
+ ;;
+ mov r16=IA64_TR_MAPPED_REGS
+ ;;
+ itr.d dtr[r16]=r17 // wire in new mapping...
+ ;;
+ srlz.d
+ ;;
+ br.sptk.many .reload_vpd_not_mapped;;
+.vmx_domain:
+
+ // 7. VPD
+ GET_THIS_PADDR(r2, inserted_vpd);;
+ ld8 r16=[r2]
+ mov r18=IA64_GRANULE_SHIFT<<2
+ ;;
+ cmp.eq p7,p0=r16,r0
+ ;;
+(p7) br.cond.sptk .reload_vpd_not_mapped
+ dep r17=0,r16,60,4
+ ;;
+ dep r17=0,r17,0,IA64_GRANULE_SHIFT
+ ;;
+ movl r20=PAGE_KERNEL
+ ;;
+ or r17=r20,r17 // construct PA | page properties
+ ;;
+ mov cr.itir=r18
+ mov cr.ifa=r16
+ ;;
+ mov r16=IA64_TR_VPD
+ mov r18=IA64_TR_MAPPED_REGS
+ ;;
+ itr.i itr[r16]=r17
+ ;;
+ itr.d dtr[r18]=r17
+ ;;
+ srlz.i
+ ;;
+ srlz.d
+ ;;
+.reload_vpd_not_mapped:
+
+ // 8. VHPT
+ GET_THIS_PADDR(r2, inserted_vhpt);;
+ ld8 r2=[r2]
+ ;;
+ cmp.eq p7,p0=r2,r0
+ ;;
+(p7) br.cond.sptk .overlap_vhpt // vhpt isn't mapped.
// avoid overlapping with stack TR
- shr.u r17=r2,IA64_GRANULE_SHIFT
- GET_THIS_PADDR(r3, cpu_kr);;
- add r3=IA64_KR_CURRENT_STACK_OFFSET,r3
- ;;
- ld8 r3=[r3]
- ;;
- cmp.eq p7,p0=r3,r17
+ dep r16=0,r2,0,IA64_GRANULE_SHIFT
+ ;;
+ GET_THIS_PADDR(r2,cpu_kr);;
+ add r2=IA64_KR_CURRENT_OFFSET,r2
+ ;;
+ ld8 r2=[r2]
+ ;;
+ dep r17=0,r2,0,IA64_GRANULE_SHIFT
+ ;;
+ cmp.eq p7,p0=r16,r17
(p7) br.cond.sptk .overlap_vhpt
- ;;
-
- dep r16=0,r2,0,IA64_GRANULE_SHIFT
movl r20=PAGE_KERNEL
;;
mov r18=IA64_TR_VHPT
@@ -1123,8 +1161,6 @@ GLOBAL_ENTRY(ia64_monarch_init_handler)
GLOBAL_ENTRY(ia64_monarch_init_handler)
.prologue
#ifdef XEN /* Need in ia64_monarch_init_handler? */
- SET_PER_CPU_DATA();;
-
// Set current to ar.k6
GET_THIS_PADDR(r2,cpu_kr);;
add r2=IA64_KR_CURRENT_OFFSET,r2;;
diff -r c587457f6916 -r e9706492e960 xen/arch/ia64/xen/regionreg.c
--- a/xen/arch/ia64/xen/regionreg.c Mon Jul 28 17:29:09 2008 +0900
+++ b/xen/arch/ia64/xen/regionreg.c Thu Jul 31 12:25:50 2008 +0900
@@ -52,6 +52,7 @@ static unsigned int domain_rid_bits_defa
static unsigned int domain_rid_bits_default = IA64_MIN_IMPL_RID_BITS;
integer_param("dom_rid_bits", domain_rid_bits_default);
+DEFINE_PER_CPU(unsigned long, domain_shared_info);
DEFINE_PER_CPU(unsigned long, inserted_vhpt);
DEFINE_PER_CPU(unsigned long, inserted_shared_info);
DEFINE_PER_CPU(unsigned long, inserted_mapped_regs);
@@ -270,6 +271,8 @@ int set_one_rr(unsigned long rr, unsigne
if (!PSCB(v,metaphysical_mode))
set_rr(rr,newrrv.rrval);
} else if (rreg == 7) {
+ __get_cpu_var(domain_shared_info) =
+ (unsigned long)v->domain->shared_info;
#if VHPT_ENABLED
__get_cpu_var(inserted_vhpt) = __va_ul(vcpu_vhpt_maddr(v));
#endif
diff -r c587457f6916 -r e9706492e960
xen/include/asm-ia64/linux-xen/asm/mca_asm.h
--- a/xen/include/asm-ia64/linux-xen/asm/mca_asm.h Mon Jul 28 17:29:09
2008 +0900
+++ b/xen/include/asm-ia64/linux-xen/asm/mca_asm.h Thu Jul 31 12:25:50
2008 +0900
@@ -58,8 +58,35 @@
#endif
#ifdef XEN
+/*
+ * void set_per_cpu_data(*ret)
+ * {
+ * int i;
+ * for (i = 0; i < 64; i++) {
+ * if (ia64_mca_tlb_list[i].cr_lid == ia64_getreg(_IA64_REG_CR_LID)) {
+ * *ret = ia64_mca_tlb_list[i].percpu_paddr;
+ * return;
+ * }
+ * }
+ * while(1); // Endless loop on error
+ * }
+ */
+#define SET_PER_CPU_DATA(reg,_tmp1,_tmp2,_tmp3) \
+ LOAD_PHYSICAL(p0,reg,ia64_mca_tlb_list);;\
+ mov _tmp1 = ar.lc;; \
+ mov ar.lc = NR_CPUS-1; \
+ mov _tmp2 = cr.lid;; \
+10: ld8 _tmp3 = [reg],16;; \
+ cmp.ne p6, p7 = _tmp3, _tmp2;; \
+(p7) br.cond.dpnt 30f;; \
+ br.cloop.sptk.few 10b;; \
+20: br 20b;;/* Endless loop on error */ \
+30: mov ar.lc = _tmp1; \
+ adds reg = IA64_MCA_PERCPU_OFFSET-IA64_MCA_TLB_INFO_SIZE, reg;; \
+ ld8 reg = [reg]
+
#define GET_THIS_PADDR(reg, var) \
- mov reg = IA64_KR(PER_CPU_DATA);; \
+ SET_PER_CPU_DATA(reg,r5,r6,r7);; \
addl reg = THIS_CPU(var) - PERCPU_ADDR, reg
#else
#define GET_THIS_PADDR(reg, var) \
diff -r c587457f6916 -r e9706492e960 xen/include/asm-ia64/regionreg.h
--- a/xen/include/asm-ia64/regionreg.h Mon Jul 28 17:29:09 2008 +0900
+++ b/xen/include/asm-ia64/regionreg.h Thu Jul 31 12:25:50 2008 +0900
@@ -36,6 +36,7 @@ typedef union ia64_rr {
#define RR_RID(arg) (((arg) & 0x0000000000ffffff) << 8)
#define RR_RID_MASK 0x00000000ffffff00L
+DECLARE_PER_CPU(unsigned long, domain_shared_info);
DECLARE_PER_CPU(unsigned long, inserted_vhpt);
DECLARE_PER_CPU(unsigned long, inserted_shared_info);
DECLARE_PER_CPU(unsigned long, inserted_mapped_regs);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|