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 <yamahata@xxxxxxxxxxxxx>
> Cc: Alex Williamson <alex.williamson@xxxxxx>
> Cc: Aron Griffis <aron@xxxxxx>
> Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
>
> ---
>
> 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@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|