Hi Simon, This series seems to work ok for me, at least as far as existing functionality, I haven't tested kexec. This patch has some commented out code (a couple lines in the asm, then a chunk later). Can this be cleaned out, or should it at least be better commented about why it remains? There's also a rather obvious FIXME in this patch, has this been resolved to your satisfaction, or can someone else on list familiar with unwind statements comment? Thanks,
Alex On Thu, 2008-04-24 at 09:04 +1000, Simon Horman wrote: > A cut down version of set_one_rr (and ia64_new_rr7) for > use when switching to the EFI RID for SAL, PAL and EFI calls. > > There seems to be no need to repin: palcode, mapped_regs or vhpt in this > case. If it turns they do need to be repinned then special care needs to > betaken to track the correct value to repin. That is generally the values > that were most recently pinned by ia64_new_rr7. > > ia64_new_rr7_efi can probably be merged with ia64_new_rr7, > as they are quite similar, but for testing purposes it seems > easier to keep them separate. > > Cc: Isaku Yamahata <[EMAIL PROTECTED]> > Cc: Alex Williamson <[EMAIL PROTECTED]> > Cc: Aron Griffis <[EMAIL PROTECTED]> > Signed-off-by: Simon Horman <[EMAIL PROTECTED]> > > --- > > Wed, 23 Apr 2008 10:09:03 +1000 > * Repin VPD (privregs) if they have been pinned > - A separate patch handles unpinning on kexec > > Thu, 24 Apr 2008 08:35:03 +1000 > * Move percpu_set declaration from xen/include/xen/cpumask.h > (symlink, generic code) to xen/include/asm-ia64/regionreg.h > (file, architecture-specific code) > > Index: xen-unstable.hg/xen/arch/ia64/xen/regionreg.c > =================================================================== > --- xen-unstable.hg.orig/xen/arch/ia64/xen/regionreg.c 2008-04-24 > 08:31:32.000000000 +1000 > +++ xen-unstable.hg/xen/arch/ia64/xen/regionreg.c 2008-04-24 > 08:33:36.000000000 +1000 > @@ -11,6 +11,7 @@ > #include <linux/config.h> > #include <linux/types.h> > #include <linux/sched.h> > +#include <linux/percpu.h> > #include <asm/page.h> > #include <asm/regionreg.h> > #include <asm/vhpt.h> > @@ -20,6 +21,8 @@ > > /* Defined in xemasm.S */ > extern void ia64_new_rr7(unsigned long rid, void *shared_info, void > *shared_arch_info, unsigned long shared_info_va, unsigned long va_vhpt); > +extern void ia64_new_rr7_efi(unsigned long rid, unsigned long percpu_pte, > + unsigned long privregs); > > /* RID virtualization mechanism is really simple: domains have less rid bits > than the host and the host rid space is shared among the domains. (Values > @@ -233,6 +236,7 @@ set_rr(unsigned long rr, unsigned long r > DEFINE_PER_CPU(unsigned long, inserted_vhpt); > #endif > DEFINE_PER_CPU(unsigned long, inserted_shared_info); > +DEFINE_PER_CPU(unsigned long, inserted_privregs); > > // validates and changes a single region register > // in the currently executing domain > @@ -281,6 +285,29 @@ int set_one_rr(unsigned long rr, unsigne > return 1; > } > > +int set_one_rr_efi(unsigned long rr, unsigned long val) > +{ > + unsigned long rreg = REGION_NUMBER(rr); > + struct vcpu *v = current; > + int percpu_set_f; > + unsigned long privregs = 0UL; > + > + BUG_ON(rreg != 6 && rreg != 7); > + > + if (rreg == 6) { > + ia64_set_rr(rr, val); > + ia64_srlz_d(); > + } > + else { > + percpu_set_f = cpu_isset(smp_processor_id(), percpu_set); > + if (percpu_set_f) > + privregs = __get_cpu_var(inserted_privregs); > + ia64_new_rr7_efi(val, percpu_set_f, privregs); > + } > + > + return 1; > +} > + > void set_virtual_rr0(void) > { > struct vcpu *v = current; > Index: xen-unstable.hg/xen/arch/ia64/xen/xenasm.S > =================================================================== > --- xen-unstable.hg.orig/xen/arch/ia64/xen/xenasm.S 2008-04-23 > 12:30:32.000000000 +1000 > +++ xen-unstable.hg/xen/arch/ia64/xen/xenasm.S 2008-04-24 > 08:33:36.000000000 +1000 > @@ -195,6 +195,193 @@ GLOBAL_ENTRY(ia64_new_rr7) > br.ret.sptk.many rp > END(ia64_new_rr7) > > + > + /* ia64_new_rr7_efi: > + * in0 = rid > + * in1 = repin_percpu > + * in2 = vpd vaddr > + * > + * There seems to be no need to repin: palcode, mapped_regs > + * or vhpt. If they do need to be repinned then special care > + * needs to betaken to track the correct value to repin. > + * That is generally the values that were most recently pinned by > + * ia64_new_rr7. > + * > + * This code function could probably be merged with ia64_new_rr7 > + * as it is just a trimmed down version of that function. > + * However, current can change without repinning occuring, > + * so simply getting the values from current does not work correctly. > + */ > + > +GLOBAL_ENTRY(ia64_new_rr7_efi) > + // FIXME? not sure this unwind statement is correct... > + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1) > + alloc loc1 = ar.pfs, 3, 9, 0, 0 > + movl loc2=PERCPU_ADDR > +1: { > + mov loc3 = psr // save psr > + mov loc0 = rp // save rp > + mov r8 = ip // save ip to compute branch > + };; > + .body > + tpa loc2=loc2 // grab this BEFORE changing rr7 > + adds r8 = 1f-1b,r8 // calculate return address for call > + ;; > + movl r17=PSR_BITS_TO_SET > + mov loc4=ar.rsc // save RSE configuration > + movl r16=PSR_BITS_TO_CLEAR > + ;; > + tpa r8=r8 // convert rp to physical > + mov ar.rsc=0 // put RSE in enforced lazy, LE mode > + or loc3=loc3,r17 // add in psr the bits to set > + ;; > + movl loc5=pal_vaddr // get pal_vaddr > + ;; > + ld8 loc5=[loc5] // read pal_vaddr > + ;; > + dep loc7 = 0,in2,60,4 // get physical address of privregs > + ;; > + dep loc7 = 0,loc7,0,IA64_GRANULE_SHIFT > + // mask granule shift > + ;; > + andcm r16=loc3,r16 // removes bits to clear from psr > + dep loc6=0,r8,0,KERNEL_TR_PAGE_SHIFT // Xen code paddr > + br.call.sptk.many rp=ia64_switch_mode_phys > +//1: > + movl r26=PAGE_KERNEL > + // now in physical mode with psr.i/ic off so do rr7 switch > + dep r16=-1,r0,61,3 > + ;; > + mov loc8=rr[r16] > + ;; > + mov rr[r16]=in0 > + //mov rr[r16]=loc8 > + ;; > + srlz.d > + > + // re-pin mappings for kernel text and data > + mov r24=KERNEL_TR_PAGE_SHIFT<<2 > + movl r17=KERNEL_START > + ;; > + ptr.i r17,r24 > + ;; > + ptr.d r17,r24 > + ;; > + srlz.i > + ;; > + srlz.d > + ;; > + mov r16=IA64_TR_KERNEL > + mov cr.itir=r24 > + mov cr.ifa=r17 > + or r18=loc6,r26 > + ;; > + itr.i itr[r16]=r18 > + ;; > + itr.d dtr[r16]=r18 > + ;; > + srlz.i > + ;; > + srlz.d > + ;; > + > + // re-pin mappings for stack (current) > + > + // unless overlaps with KERNEL_TR > + dep r18=0,r13,0,KERNEL_TR_PAGE_SHIFT > + ;; > + cmp.eq p7,p0=r17,r18 > +(p7) br.cond.sptk ia64_new_rr7_efi_stack_overlaps > + mov r25=IA64_GRANULE_SHIFT<<2 > + dep r21=0,r13,60,4 // physical address of "current" > + ;; > + ptr.d r13,r25 > + ;; > + srlz.d > + ;; > + or r23=r21,r26 // construct PA | page properties > + mov cr.itir=r25 > + mov cr.ifa=r13 // VA of next task... > + mov r21=IA64_TR_CURRENT_STACK > + ;; > + itr.d dtr[r21]=r23 // wire in new mapping... > + ;; > + srlz.d > + ;; > +ia64_new_rr7_efi_stack_overlaps: > + > + // Per-cpu > + cmp.eq p7,p0=r0,in1 > +(p7) br.cond.sptk ia64_new_rr7_efi_percpu_not_mapped > + mov r24=PERCPU_PAGE_SHIFT<<2 > + movl r22=PERCPU_ADDR > + ;; > + ptr.d r22,r24 > + ;; > + srlz.d > + ;; > + or r23=loc2,r26 > + mov cr.itir=r24 > + mov cr.ifa=r22 > + mov r25=IA64_TR_PERCPU_DATA > + ;; > + itr.d dtr[r25]=r23 // wire in new mapping... > + ;; > + srlz.d > + ;; > +ia64_new_rr7_efi_percpu_not_mapped: > + > +#if 0 > + // Purge/insert PAL TR > + mov r24=IA64_TR_PALCODE > + mov r23=IA64_GRANULE_SHIFT<<2 > + dep r25=0,loc5,60,4 // convert pal vaddr to paddr > + ;; > + dep r25 = 0,r25,0,IA64_GRANULE_SHIFT > + // mask granule shift > + ;; > + ptr.i loc5,r23 > + or r25=r25,r26 // construct PA | page properties > + mov cr.itir=r23 > + mov cr.ifa=loc5 > + ;; > + itr.i itr[r24]=r25 > +#endif > + > + // privregs / mapped_regs > + cmp.eq p7,p0=r0,in2 > +(p7) br.cond.sptk ia64_new_rr7_efi_privregs_not_mapped > + or loc7 = r26,loc7 // construct PA | page properties > + mov r22=IA64_TR_VPD > + mov r24=IA64_TR_MAPPED_REGS > + mov r23=IA64_GRANULE_SHIFT<<2 > + ;; > + ptr.i in2,r23 > + ;; > + srlz.i > + ;; > + mov cr.itir=r23 > + mov cr.ifa=in2 > + ;; > + itr.i itr[r22]=loc7 > + ;; > + srlz.i > +ia64_new_rr7_efi_privregs_not_mapped: > + > + // done, switch back to virtual and return > + mov r16=loc3 // r16= original psr > + br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode > + mov psr.l = loc3 // restore init PSR > + ;; > + > + mov ar.pfs = loc1 > + mov rp = loc0 > + ;; > + mov ar.rsc=loc4 // restore RSE configuration > + srlz.d // seralize restoration of psr.l > + br.ret.sptk.many rp > +END(ia64_new_rr7_efi) > + > #if 0 /* Not used */ > #include "minstate.h" > > Index: xen-unstable.hg/xen/include/asm-ia64/regionreg.h > =================================================================== > --- xen-unstable.hg.orig/xen/include/asm-ia64/regionreg.h 2008-04-24 > 08:31:25.000000000 +1000 > +++ xen-unstable.hg/xen/include/asm-ia64/regionreg.h 2008-04-24 > 08:38:08.000000000 +1000 > @@ -37,8 +37,12 @@ typedef union ia64_rr { > #define RR_RID_MASK 0x00000000ffffff00L > > DECLARE_PER_CPU(unsigned long, inserted_vhpt); > +DECLARE_PER_CPU(unsigned long, inserted_privregs); > + > +extern cpumask_t percpu_set; > > int set_one_rr(unsigned long rr, unsigned long val); > +int set_one_rr_efi(unsigned long rr, unsigned long val); > > // This function is purely for performance... apparently scrambling > // bits in the region id makes for better hashing, which means better > Index: xen-unstable.hg/xen/arch/ia64/xen/mm_init.c > =================================================================== > --- xen-unstable.hg.orig/xen/arch/ia64/xen/mm_init.c 2008-04-23 > 12:30:32.000000000 +1000 > +++ xen-unstable.hg/xen/arch/ia64/xen/mm_init.c 2008-04-24 > 08:33:36.000000000 +1000 > @@ -18,12 +18,16 @@ struct ia64_mca_tlb_info ia64_mca_tlb_li > > extern void ia64_tlb_init (void); > > +#ifdef XEN > +cpumask_t percpu_set; > +#endif > + > void __devinit > ia64_mmu_init (void *my_cpu_data) > { > unsigned long psr, impl_va_bits; > extern void __devinit tlb_init (void); > - int cpu; > + int cpu = smp_processor_id(); > > /* Pin mapping for percpu area into TLB */ > psr = ia64_clear_ic(); > @@ -33,6 +37,9 @@ ia64_mmu_init (void *my_cpu_data) > > ia64_set_psr(psr); > ia64_srlz_i(); > +#ifdef XEN > + cpu_set(cpu, percpu_set); > +#endif > > /* > * Check if the virtually mapped linear page table (VMLPT) overlaps > with a mapped > @@ -72,8 +79,6 @@ ia64_mmu_init (void *my_cpu_data) > ia64_srlz_d(); > #endif > > - cpu = smp_processor_id(); > - > /* mca handler uses cr.lid as key to pick the right entry */ > ia64_mca_tlb_list[cpu].cr_lid = ia64_getreg(_IA64_REG_CR_LID); > > Index: xen-unstable.hg/xen/arch/ia64/vmx/vmx_phy_mode.c > =================================================================== > --- xen-unstable.hg.orig/xen/arch/ia64/vmx/vmx_phy_mode.c 2008-04-24 > 08:31:25.000000000 +1000 > +++ xen-unstable.hg/xen/arch/ia64/vmx/vmx_phy_mode.c 2008-04-24 > 08:33:36.000000000 +1000 > @@ -174,6 +174,7 @@ vmx_load_all_rr(VCPU *vcpu) > #if VHPT_ENABLED > __get_cpu_var(inserted_vhpt) = __va_ul(vcpu_vhpt_maddr(v)); > #endif > + __get_cpu_var(inserted_privregs) = vcpu->arch.privregs; > vmx_switch_rr7(vrrtomrr(vcpu,VMX(vcpu, vrr[VRN7])), > (void *)vcpu->arch.vhpt.hash, > pal_vaddr, vcpu->arch.privregs); > Index: xen-unstable.hg/xen/arch/ia64/vmx/vmx_vcpu.c > =================================================================== > --- xen-unstable.hg.orig/xen/arch/ia64/vmx/vmx_vcpu.c 2008-04-24 > 08:31:25.000000000 +1000 > +++ xen-unstable.hg/xen/arch/ia64/vmx/vmx_vcpu.c 2008-04-24 > 08:33:36.000000000 +1000 > @@ -184,6 +184,7 @@ IA64FAULT vmx_vcpu_set_rr(VCPU *vcpu, u6 > #if VHPT_ENABLED > __get_cpu_var(inserted_vhpt) = __va_ul(vcpu_vhpt_maddr(v)); > #endif > + __get_cpu_var(inserted_privregs) = vcpu->arch.privregs; > vmx_switch_rr7(vrrtomrr(vcpu,val), (void *)vcpu->arch.vhpt.hash, > pal_vaddr, vcpu->arch.privregs); > } > -- Alex Williamson HP Open Source & Linux Org. _______________________________________________ Xen-ia64-devel mailing list Xen-ia64-devel@lists.xensource.com http://lists.xensource.com/xen-ia64-devel