diff options
author | xen-ia64.adm@bkbits.net <xen-ia64.adm@bkbits.net> | 2005-06-29 21:37:40 +0000 |
---|---|---|
committer | xen-ia64.adm@bkbits.net <xen-ia64.adm@bkbits.net> | 2005-06-29 21:37:40 +0000 |
commit | 1daf04f8343750412a3ea47c55d96f760cda8b27 (patch) | |
tree | de80beef4fe2212f728c483927d1922f6bb266a0 | |
parent | 79e1decf57682817f32e869dbff61606e6eac981 (diff) | |
parent | cbd0cf09894d2e34c4db502e61baaa15fc3f71cb (diff) | |
download | xen-1daf04f8343750412a3ea47c55d96f760cda8b27.tar.gz xen-1daf04f8343750412a3ea47c55d96f760cda8b27.tar.bz2 xen-1daf04f8343750412a3ea47c55d96f760cda8b27.zip |
bitkeeper revision 1.1771 (42c314a41N8GOY476cnW9IejbgNDJw)
Merge bk://xen.bkbits.net/xeno-unstable.bk
into bkbits.net:/repos/x/xen-ia64/xeno-unstable-ia64.bk
-rw-r--r-- | xen/arch/ia64/asm-offsets.c | 1 | ||||
-rw-r--r-- | xen/arch/ia64/domain.c | 38 | ||||
-rw-r--r-- | xen/arch/ia64/grant_table.c | 23 | ||||
-rw-r--r-- | xen/arch/ia64/hypercall.c | 3 | ||||
-rw-r--r-- | xen/arch/ia64/hyperprivop.S | 414 | ||||
-rw-r--r-- | xen/arch/ia64/ivt.S | 20 | ||||
-rw-r--r-- | xen/arch/ia64/privop.c | 7 | ||||
-rw-r--r-- | xen/arch/ia64/process.c | 8 | ||||
-rw-r--r-- | xen/include/asm-ia64/xensystem.h | 9 |
9 files changed, 454 insertions, 69 deletions
diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index ca8daa2f87..b374c4809b 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -88,6 +88,7 @@ void foo(void) BLANK(); DEFINE(IA64_CPUINFO_ITM_NEXT_OFFSET, offsetof (struct cpuinfo_ia64, itm_next)); + DEFINE(IA64_CPUINFO_PGD_QUICK_OFFSET, offsetof (struct cpuinfo_ia64, pgd_quick)); //DEFINE(IA64_SIGHAND_SIGLOCK_OFFSET,offsetof (struct sighand_struct, siglock)); diff --git a/xen/arch/ia64/domain.c b/xen/arch/ia64/domain.c index 6903c3532a..c6ead10510 100644 --- a/xen/arch/ia64/domain.c +++ b/xen/arch/ia64/domain.c @@ -50,7 +50,7 @@ unsigned long dom0_size = 512*1024*1024; //FIXME: Should be configurable //FIXME: alignment should be 256MB, lest Linux use a 256MB page size unsigned long dom0_align = 256*1024*1024; #else // CONFIG_VTI -unsigned long dom0_size = 256*1024*1024; //FIXME: Should be configurable +unsigned long dom0_size = 512*1024*1024; //FIXME: Should be configurable //FIXME: alignment should be 256MB, lest Linux use a 256MB page size unsigned long dom0_align = 64*1024*1024; #endif // CONFIG_VTI @@ -465,10 +465,44 @@ if (unlikely(page_to_phys(p) > vhpt_paddr && page_to_phys(p) < vhpt_pend)) { set_pte(pte, pfn_pte(page_to_phys(p) >> PAGE_SHIFT, __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX))); } - else printk("map_new_domain_page: page %p already mapped!\n",p); + else printk("map_new_domain_page: mpaddr %lx already mapped!\n",mpaddr); return p; } +/* map a physical address to the specified metaphysical addr */ +void map_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr) +{ + struct mm_struct *mm = d->arch.mm; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + if (!mm->pgd) { + printk("map_domain_page: domain pgd must exist!\n"); + return; + } + pgd = pgd_offset(mm,mpaddr); + if (pgd_none(*pgd)) + pgd_populate(mm, pgd, pud_alloc_one(mm,mpaddr)); + + pud = pud_offset(pgd, mpaddr); + if (pud_none(*pud)) + pud_populate(mm, pud, pmd_alloc_one(mm,mpaddr)); + + pmd = pmd_offset(pud, mpaddr); + if (pmd_none(*pmd)) + pmd_populate_kernel(mm, pmd, pte_alloc_one_kernel(mm,mpaddr)); +// pmd_populate(mm, pmd, pte_alloc_one(mm,mpaddr)); + + pte = pte_offset_map(pmd, mpaddr); + if (pte_none(*pte)) { + set_pte(pte, pfn_pte(physaddr >> PAGE_SHIFT, + __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX))); + } + else printk("map_domain_page: mpaddr %lx already mapped!\n",mpaddr); +} + void mpafoo(unsigned long mpaddr) { extern unsigned long privop_trace; diff --git a/xen/arch/ia64/grant_table.c b/xen/arch/ia64/grant_table.c index 9f19152749..9436347779 100644 --- a/xen/arch/ia64/grant_table.c +++ b/xen/arch/ia64/grant_table.c @@ -570,13 +570,13 @@ __gnttab_unmap_grant_ref( /* Frame is now unmapped for device access. */ } -#ifdef __ia64__ -// FIXME-ia64: any error checking need to be done here? -#else if ( (virt != 0) && (flags & GNTMAP_host_map) && ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0)) { +#ifdef __ia64__ +// FIXME-ia64: any error checking need to be done here? +#else l1_pgentry_t *pl1e; unsigned long _ol1e; @@ -609,6 +609,7 @@ __gnttab_unmap_grant_ref( rc = -EINVAL; goto unmap_out; } +#endif map->ref_and_flags &= ~GNTMAP_host_map; @@ -627,7 +628,6 @@ __gnttab_unmap_grant_ref( rc = 0; *va = virt; } -#endif if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0) { @@ -696,6 +696,7 @@ gnttab_setup_table( gnttab_setup_table_t op; struct domain *d; int i; + unsigned long addr; if ( count != 1 ) return -EINVAL; @@ -735,10 +736,24 @@ gnttab_setup_table( { ASSERT(d->grant_table != NULL); (void)put_user(GNTST_okay, &uop->status); +#ifdef __ia64__ + if (d == dom0) { + for ( i = 0; i < op.nr_frames; i++ ) + (void)put_user( + (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i, + &uop->frame_list[i]); + } else { + /* IA64 hack - need to map it somewhere */ + addr = (1UL << 40); + map_domain_page(d, addr, virt_to_phys(d->grant_table->shared)); + (void)put_user(addr >> PAGE_SHIFT, &uop->frame_list[0]); + } +#else for ( i = 0; i < op.nr_frames; i++ ) (void)put_user( (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i, &uop->frame_list[i]); +#endif } put_domain(d); diff --git a/xen/arch/ia64/hypercall.c b/xen/arch/ia64/hypercall.c index b6f3167c09..8107e166e2 100644 --- a/xen/arch/ia64/hypercall.c +++ b/xen/arch/ia64/hypercall.c @@ -43,7 +43,8 @@ ia64_hypercall (struct pt_regs *regs) #if 1 #define SPURIOUS_VECTOR 15 if (vcpu_check_pending_interrupts(v)!=SPURIOUS_VECTOR) { -//printf("Domain trying to go idle when interrupt pending!\n"); +// int pi = vcpu_check_pending_interrupts(v); +//printf("idle w/int#%d pending!\n",pi); //this shouldn't happen, but it apparently does quite a bit! so don't //allow it to happen... i.e. if a domain has an interrupt pending and //it tries to halt itself because it thinks it is idle, just return here diff --git a/xen/arch/ia64/hyperprivop.S b/xen/arch/ia64/hyperprivop.S index ab6069c5ba..9fff713278 100644 --- a/xen/arch/ia64/hyperprivop.S +++ b/xen/arch/ia64/hyperprivop.S @@ -17,6 +17,10 @@ #define FAST_HYPERPRIVOP_CNT #define FAST_REFLECT_CNT +// FIXME: This is defined in include/asm-ia64/hw_irq.h but this +// doesn't appear to be include'able from assembly? +#define IA64_TIMER_VECTOR 0xef + // Should be included from common header file (also in process.c) // NO PSR_CLR IS DIFFERENT! (CPL) #define IA64_PSR_CPL1 (__IA64_UL(1) << IA64_PSR_CPL1_BIT) @@ -241,14 +245,23 @@ ENTRY(hyper_ssm_i) adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18; adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;; bsw.1;; - st8 [r2]=r16,16; st8 [r3]=r17,16 ;; - st8 [r2]=r18,16; st8 [r3]=r19,16 ;; - st8 [r2]=r20,16; st8 [r3]=r21,16 ;; - st8 [r2]=r22,16; st8 [r3]=r23,16 ;; - st8 [r2]=r24,16; st8 [r3]=r25,16 ;; - st8 [r2]=r26,16; st8 [r3]=r27,16 ;; - st8 [r2]=r28,16; st8 [r3]=r29,16 ;; - st8 [r2]=r30,16; st8 [r3]=r31,16 ;; + // FIXME: need to handle ar.unat! + .mem.offset 0,0; st8.spill [r2]=r16,16; + .mem.offset 8,0; st8.spill [r3]=r17,16 ;; + .mem.offset 0,0; st8.spill [r2]=r18,16; + .mem.offset 8,0; st8.spill [r3]=r19,16 ;; + .mem.offset 0,0; st8.spill [r2]=r20,16; + .mem.offset 8,0; st8.spill [r3]=r21,16 ;; + .mem.offset 0,0; st8.spill [r2]=r22,16; + .mem.offset 8,0; st8.spill [r3]=r23,16 ;; + .mem.offset 0,0; st8.spill [r2]=r24,16; + .mem.offset 8,0; st8.spill [r3]=r25,16 ;; + .mem.offset 0,0; st8.spill [r2]=r26,16; + .mem.offset 8,0; st8.spill [r3]=r27,16 ;; + .mem.offset 0,0; st8.spill [r2]=r28,16; + .mem.offset 8,0; st8.spill [r3]=r29,16 ;; + .mem.offset 0,0; st8.spill [r2]=r30,16; + .mem.offset 8,0; st8.spill [r3]=r31,16 ;; movl r31=XSI_IPSR;; bsw.0 ;; mov r2=r30; mov r3=r29;; @@ -258,6 +271,174 @@ ENTRY(hyper_ssm_i) rfi ;; +// reflect domain clock interrupt +// r31 == pr +// r30 == cr.ivr +// r29 == rp +GLOBAL_ENTRY(fast_tick_reflect) +#define FAST_TICK +#ifndef FAST_TICK + br.cond.sptk.many rp;; +#endif + mov r28=IA64_TIMER_VECTOR;; + cmp.ne p6,p0=r28,r30 +(p6) br.cond.spnt.few rp;; + movl r20=(PERCPU_ADDR)+IA64_CPUINFO_ITM_NEXT_OFFSET;; + ld8 r21=[r20];; + mov r27=ar.itc;; + cmp.ltu p6,p0=r21,r27 +(p6) br.cond.spnt.few rp;; + mov r17=cr.ipsr;; + // slow path if: ipsr.be==1, ipsr.pp==1 + extr.u r21=r17,IA64_PSR_BE_BIT,1 ;; + cmp.ne p6,p0=r21,r0 +(p6) br.cond.spnt.few rp;; + extr.u r21=r17,IA64_PSR_PP_BIT,1 ;; + cmp.ne p6,p0=r21,r0 +(p6) br.cond.spnt.few rp;; +#ifdef FAST_REFLECT_CNT + movl r20=fast_reflect_count+((0x3000>>8)*8);; + ld8 r21=[r20];; + adds r21=1,r21;; + st8 [r20]=r21;; +#endif + mov cr.eoi=r0;; + mov rp=r29;; + // vcpu_pend_timer(current) + movl r18=XSI_PSR_IC;; + adds r20=XSI_ITV_OFS-XSI_PSR_IC_OFS,r18 ;; + ld8 r20=[r20];; + cmp.eq p6,p0=r20,r0 // if cr.itv==0 done +(p6) br.cond.spnt.few fast_tick_reflect_done;; + tbit.nz p6,p0=r20,16;; // check itv.m (discard) bit +(p6) br.cond.spnt.few fast_tick_reflect_done;; + extr.u r27=r20,0,6 // r27 has low 6 bits of itv.vector + extr.u r26=r20,6,2;; // r26 has irr index of itv.vector + mov r19=IA64_KR(CURRENT);; + adds r22=IA64_VCPU_DOMAIN_ITM_LAST_OFFSET,r19 + adds r23=IA64_VCPU_DOMAIN_ITM_OFFSET,r19;; + ld8 r24=[r22];; + ld8 r23=[r23];; + cmp.eq p6,p0=r23,r24 // skip if this tick already delivered +(p6) br.cond.spnt.few fast_tick_reflect_done;; + // set irr bit + adds r21=IA64_VCPU_IRR0_OFFSET,r19; + shl r26=r26,3;; + add r21=r21,r26;; + mov r25=1;; + shl r22=r25,r27;; + ld8 r23=[r21];; + or r22=r22,r23;; + st8 [r21]=r22;; + // set PSCB(pending_interruption)! + adds r20=XSI_PEND_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r20]=r25;; + + // if interrupted at pl0, we're done + extr.u r16=r17,IA64_PSR_CPL0_BIT,2;; + cmp.eq p6,p0=r16,r0;; +(p6) br.cond.spnt.few fast_tick_reflect_done;; + // if guest vpsr.i is off, we're done + adds r21=XSI_PSR_I_OFS-XSI_PSR_IC_OFS,r18 ;; + ld4 r21=[r21];; + cmp.eq p6,p0=r21,r0 +(p6) br.cond.spnt.few fast_tick_reflect_done;; + + // OK, we have a clock tick to deliver to the active domain! + // so deliver to iva+0x3000 + // r17 == cr.ipsr + // r18 == XSI_PSR_IC + // r19 == IA64_KR(CURRENT) + // r31 == pr + mov r16=cr.isr;; + mov r29=cr.iip;; + adds r21=XSI_IIP_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r29 ;; + // set shared_mem isr + extr.u r16=r16,38,1;; // grab cr.isr.ir bit + dep r16=r16,r0,38,1 ;; // insert into cr.isr (rest of bits zero) + extr.u r20=r17,41,2 ;; // get ipsr.ri + dep r16=r20,r16,41,2 ;; // deposit cr.isr.ei + adds r21=XSI_ISR_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r16 ;; + // set cr.ipsr (make sure cpl==2!) + mov r29=r17 ;; + movl r28=DELIVER_PSR_SET;; + movl r27=~(DELIVER_PSR_CLR|IA64_PSR_CPL0);; + or r29=r29,r28;; + and r29=r29,r27;; + mov cr.ipsr=r29;; + // set shared_mem ipsr (from ipsr in r17 with ipsr.ri already set) + extr.u r29=r17,IA64_PSR_CPL0_BIT,2;; + cmp.eq p6,p7=3,r29;; +(p6) dep r17=-1,r17,IA64_PSR_CPL0_BIT,2 +(p7) dep r17=0,r17,IA64_PSR_CPL0_BIT,2 + ;; + movl r28=(IA64_PSR_DT|IA64_PSR_IT|IA64_PSR_RT);; + movl r27=~(IA64_PSR_BE|IA64_PSR_PP|IA64_PSR_BN|IA64_PSR_I|IA64_PSR_IC);; + dep r21=-1,r21,IA64_PSR_CPL1_BIT,1 ;; + or r17=r17,r28;; + and r17=r17,r27;; + ld4 r16=[r18],4;; + cmp.ne p6,p0=r16,r0;; +(p6) dep r17=-1,r17,IA64_PSR_IC_BIT,1 ;; + ld4 r16=[r18],-4;; + cmp.ne p6,p0=r16,r0;; +(p6) dep r17=-1,r17,IA64_PSR_I_BIT,1 ;; + adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r17 ;; + // set shared_mem interrupt_delivery_enabled to 0 + // set shared_mem interrupt_collection_enabled to 0 + st8 [r18]=r0;; + // cover and set shared_mem precover_ifs to cr.ifs + // set shared_mem ifs and incomplete_regframe to 0 + cover ;; + mov r20=cr.ifs;; + adds r21=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r21]=r0 ;; + adds r21=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r0 ;; + adds r21=XSI_PRECOVER_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r20 ;; + // leave cr.ifs alone for later rfi + // set iip to go to domain IVA break instruction vector + adds r22=IA64_VCPU_IVA_OFFSET,r19;; + ld8 r23=[r22];; + movl r24=0x3000;; + add r24=r24,r23;; + mov cr.iip=r24;; + // OK, now all set to go except for switch to virtual bank0 + mov r30=r2; mov r29=r3;; + adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18; + adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;; + bsw.1;; + // FIXME: need to handle ar.unat! + .mem.offset 0,0; st8.spill [r2]=r16,16; + .mem.offset 8,0; st8.spill [r3]=r17,16 ;; + .mem.offset 0,0; st8.spill [r2]=r18,16; + .mem.offset 8,0; st8.spill [r3]=r19,16 ;; + .mem.offset 0,0; st8.spill [r2]=r20,16; + .mem.offset 8,0; st8.spill [r3]=r21,16 ;; + .mem.offset 0,0; st8.spill [r2]=r22,16; + .mem.offset 8,0; st8.spill [r3]=r23,16 ;; + .mem.offset 0,0; st8.spill [r2]=r24,16; + .mem.offset 8,0; st8.spill [r3]=r25,16 ;; + .mem.offset 0,0; st8.spill [r2]=r26,16; + .mem.offset 8,0; st8.spill [r3]=r27,16 ;; + .mem.offset 0,0; st8.spill [r2]=r28,16; + .mem.offset 8,0; st8.spill [r3]=r29,16 ;; + .mem.offset 0,0; st8.spill [r2]=r30,16; + .mem.offset 8,0; st8.spill [r3]=r31,16 ;; + movl r31=XSI_IPSR;; + bsw.0 ;; + mov r2=r30; mov r3=r29;; + adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r20]=r0 ;; +fast_tick_reflect_done: + mov pr=r31,-1 ;; + rfi +END(fast_tick_reflect) + // reflect domain breaks directly to domain // FIXME: DOES NOT WORK YET // r16 == cr.isr @@ -274,21 +455,21 @@ GLOBAL_ENTRY(fast_break_reflect) mov r29=cr.iip;; extr.u r21=r30,IA64_PSR_BE_BIT,1 ;; cmp.ne p7,p0=r21,r0 ;; -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; extr.u r21=r30,IA64_PSR_PP_BIT,1 ;; cmp.ne p7,p0=r21,r0 ;; -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; #if 1 /* special handling in case running on simulator */ movl r20=first_break;; ld4 r23=[r20];; movl r21=0x80001; movl r22=0x80002;; cmp.ne p7,p0=r23,r0;; -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; cmp.eq p7,p0=r21,r17; -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; cmp.eq p7,p0=r22,r17; -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; #endif #ifdef FAST_REFLECT_CNT movl r20=fast_reflect_count+((0x2c00>>8)*8);; @@ -397,24 +578,26 @@ ENTRY(hyper_rfi) extr.u r22=r21,IA64_PSR_BE_BIT,1 ;; // if turning on psr.be, give up for now and do it the slow way cmp.ne p7,p0=r22,r0 -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; // if (!(vpsr.dt && vpsr.rt && vpsr.it)), do it the slow way movl r20=(IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT);; and r22=r20,r21 ;; cmp.ne p7,p0=r22,r20 -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; // if was in metaphys mode, do it the slow way (FIXME later?) adds r20=XSI_METAPHYS_OFS-XSI_PSR_IC_OFS,r18 ;; ld4 r20=[r20];; cmp.ne p7,p0=r20,r0 -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; // if domain hasn't already done virtual bank switch // do it the slow way (FIXME later?) +#if 0 adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; ld4 r20=[r20];; cmp.eq p7,p0=r20,r0 -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; +#endif // validate vcr.iip, if in Xen range, do it the slow way adds r20=XSI_IIP_OFS-XSI_PSR_IC_OFS,r18 ;; ld8 r22=[r20];; @@ -422,7 +605,11 @@ ENTRY(hyper_rfi) movl r24=XEN_VIRT_SPACE_HIGH ;; cmp.ltu p0,p7=r22,r23 ;; // if !(iip<low) && (p7) cmp.geu p0,p7=r22,r24 ;; // !(iip>=high) -(p7) br.sptk.many dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault ;; +#ifndef RFI_TO_INTERRUPT + cmp.ne p6,p0=r30,r0 +(p6) br.cond.spnt.few dispatch_break_fault ;; +#endif 1: // OK now, let's do an rfi. #ifdef FAST_HYPERPRIVOP_CNT @@ -431,9 +618,12 @@ ENTRY(hyper_rfi) adds r23=1,r23;; st8 [r20]=r23;; #endif +#ifdef RFI_TO_INTERRUPT + // maybe do an immediate interrupt delivery? cmp.ne p6,p0=r30,r0 -(p6) br.cond.sptk.many check_extint; - ;; +(p6) br.cond.spnt.few rfi_check_extint;; +#endif + just_do_rfi: // r18=&vpsr.i|vpsr.ic, r21==vpsr, r22=vcr.iip mov cr.iip=r22;; @@ -461,43 +651,75 @@ just_do_rfi: or r21=r21,r20 ;; mov cr.ipsr=r21 - mov pr=r31,-1 + adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; + ld4 r21=[r20];; + cmp.ne p7,p0=r21,r0 // domain already did "bank 1 switch?" +(p7) br.cond.spnt.few 1f; + // OK, now all set to go except for switch to virtual bank1 + mov r22=1;; st4 [r20]=r22; + mov r30=r2; mov r29=r3;; + adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18; + adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;; + bsw.1;; + // FIXME: need to handle ar.unat! + .mem.offset 0,0; ld8.fill r16=[r2],16 ; + .mem.offset 8,0; ld8.fill r17=[r3],16 ;; + .mem.offset 0,0; ld8.fill r18=[r2],16 ; + .mem.offset 0,0; ld8.fill r19=[r3],16 ;; + .mem.offset 8,0; ld8.fill r20=[r2],16 ; + .mem.offset 8,0; ld8.fill r21=[r3],16 ;; + .mem.offset 8,0; ld8.fill r22=[r2],16 ; + .mem.offset 8,0; ld8.fill r23=[r3],16 ;; + .mem.offset 8,0; ld8.fill r24=[r2],16 ; + .mem.offset 8,0; ld8.fill r25=[r3],16 ;; + .mem.offset 8,0; ld8.fill r26=[r2],16 ; + .mem.offset 8,0; ld8.fill r27=[r3],16 ;; + .mem.offset 8,0; ld8.fill r28=[r2],16 ; + .mem.offset 8,0; ld8.fill r29=[r3],16 ;; + .mem.offset 8,0; ld8.fill r30=[r2],16 ; + .mem.offset 8,0; ld8.fill r31=[r3],16 ;; + bsw.0 ;; + mov r2=r30; mov r3=r29;; +1: mov pr=r31,-1 ;; rfi ;; -check_extint: - br.sptk.many dispatch_break_fault ;; +#ifdef RFI_TO_INTERRUPT +GLOBAL_ENTRY(rfi_check_extint) + //br.sptk.many dispatch_break_fault ;; // r18=&vpsr.i|vpsr.ic, r21==vpsr, r22=vcr.iip + // make sure none of these get trashed in case going to just_do_rfi mov r30=IA64_KR(CURRENT);; adds r24=IA64_VCPU_INSVC3_OFFSET,r30;; mov r25=192 - adds r22=IA64_VCPU_IRR3_OFFSET,r30;; - ld8 r23=[r22];; + adds r16=IA64_VCPU_IRR3_OFFSET,r30;; + ld8 r23=[r16];; cmp.eq p6,p0=r23,r0;; -(p6) adds r22=-8,r22;; +(p6) adds r16=-8,r16;; (p6) adds r24=-8,r24;; (p6) adds r25=-64,r25;; -(p6) ld8 r23=[r22];; +(p6) ld8 r23=[r16];; (p6) cmp.eq p6,p0=r23,r0;; -(p6) adds r22=-8,r22;; +(p6) adds r16=-8,r16;; (p6) adds r24=-8,r24;; (p6) adds r25=-64,r25;; -(p6) ld8 r23=[r22];; +(p6) ld8 r23=[r16];; (p6) cmp.eq p6,p0=r23,r0;; -(p6) adds r22=-8,r22;; +(p6) adds r16=-8,r16;; (p6) adds r24=-8,r24;; (p6) adds r25=-64,r25;; -(p6) ld8 r23=[r22];; +(p6) ld8 r23=[r16];; (p6) cmp.eq p6,p0=r23,r0;; cmp.eq p6,p0=r23,r0 -(p6) br.cond.sptk.many 1f; // this is actually an error - // r22 points to non-zero element of irr, r23 has value +(p6) br.cond.spnt.few just_do_rfi; // this is actually an error + // r16 points to non-zero element of irr, r23 has value // r24 points to corr element of insvc, r25 has elt*64 ld8 r26=[r24];; cmp.geu p6,p0=r26,r23 -(p6) br.cond.spnt.many 1f; +(p6) br.cond.spnt.many just_do_rfi; + // not masked by insvc, get vector number shr.u r26=r23,1;; or r26=r23,r26;; @@ -524,21 +746,109 @@ check_extint: ld8 r20=[r20] ;; extr.u r28=r20,16,1 extr.u r29=r20,4,4 ;; - cmp.ne p6,p0=r28,r0 // if tpr.mmi is set, return SPURIOUS -(p6) br.cond.sptk.many 1f; + cmp.ne p6,p0=r28,r0 // if tpr.mmi is set, just rfi +(p6) br.cond.spnt.few just_do_rfi;; shl r29=r29,4;; adds r29=15,r29;; - cmp.ge p6,p0=r29,r26 -(p6) br.cond.sptk.many 1f; - // OK, have an unmasked vector to process/return - ld8 r25=[r24];; - or r25=r25,r27;; - st8 [r24]=r25;; - ld8 r25=[r22];; - andcm r25=r25,r27;; - st8 [r22]=r25;; - mov r8=r26;; - // not done yet + cmp.ge p6,p0=r29,r26 // if tpr masks interrupt, just rfi +(p6) br.cond.spnt.few just_do_rfi;; + +// this doesn't work yet (dies early after getting to user mode) +// but happens relatively infrequently, so fix it later. +// NOTE that these will be counted incorrectly for now (for privcnt output) +GLOBAL_ENTRY(rfi_with_interrupt) +#if 1 + br.sptk.many dispatch_break_fault ;; +#endif + + // OK, have an unmasked vector, so deliver extint to vcr.iva+0x3000 + // r18 == XSI_PSR_IC + // r21 == vipsr (ipsr in shared_mem) + // r30 == IA64_KR(CURRENT) + // r31 == pr + mov r17=cr.ipsr;; + mov r16=cr.isr;; + // set shared_mem isr + extr.u r16=r16,38,1;; // grab cr.isr.ir bit + dep r16=r16,r0,38,1 ;; // insert into cr.isr (rest of bits zero) + extr.u r20=r21,41,2 ;; // get v(!)psr.ri + dep r16=r20,r16,41,2 ;; // deposit cr.isr.ei + adds r22=XSI_ISR_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r22]=r16 ;; + // set cr.ipsr (make sure cpl==2!) + mov r29=r17 ;; + movl r28=DELIVER_PSR_SET;; + movl r27=~(DELIVER_PSR_CLR|IA64_PSR_CPL0);; + or r29=r29,r28;; + and r29=r29,r27;; + mov cr.ipsr=r29;; + // v.ipsr and v.iip are already set (and v.iip validated) as rfi target + // set shared_mem interrupt_delivery_enabled to 0 + // set shared_mem interrupt_collection_enabled to 0 + st8 [r18]=r0;; + // cover and set shared_mem precover_ifs to cr.ifs + // set shared_mem ifs and incomplete_regframe to 0 +#if 0 + cover ;; + mov r20=cr.ifs;; + adds r22=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r22]=r0 ;; + adds r22=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r22]=r0 ;; + adds r22=XSI_PRECOVER_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r22]=r20 ;; + // leave cr.ifs alone for later rfi +#else + adds r22=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r22]=r0 ;; + adds r22=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; + ld8 r20=[r22];; + st8 [r22]=r0 ;; + adds r22=XSI_PRECOVER_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r22]=r20 ;; +#endif + // set iip to go to domain IVA break instruction vector + adds r22=IA64_VCPU_IVA_OFFSET,r30;; + ld8 r23=[r22];; + movl r24=0x3000;; + add r24=r24,r23;; + mov cr.iip=r24;; +#if 0 + // OK, now all set to go except for switch to virtual bank0 + mov r30=r2; mov r29=r3;; + adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18; + adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;; + bsw.1;; + // FIXME: need to handle ar.unat! + .mem.offset 0,0; st8.spill [r2]=r16,16; + .mem.offset 8,0; st8.spill [r3]=r17,16 ;; + .mem.offset 0,0; st8.spill [r2]=r18,16; + .mem.offset 8,0; st8.spill [r3]=r19,16 ;; + .mem.offset 0,0; st8.spill [r2]=r20,16; + .mem.offset 8,0; st8.spill [r3]=r21,16 ;; + .mem.offset 0,0; st8.spill [r2]=r22,16; + .mem.offset 8,0; st8.spill [r3]=r23,16 ;; + .mem.offset 0,0; st8.spill [r2]=r24,16; + .mem.offset 8,0; st8.spill [r3]=r25,16 ;; + .mem.offset 0,0; st8.spill [r2]=r26,16; + .mem.offset 8,0; st8.spill [r3]=r27,16 ;; + .mem.offset 0,0; st8.spill [r2]=r28,16; + .mem.offset 8,0; st8.spill [r3]=r29,16 ;; + .mem.offset 0,0; st8.spill [r2]=r30,16; + .mem.offset 8,0; st8.spill [r3]=r31,16 ;; + movl r31=XSI_IPSR;; + bsw.0 ;; + mov r2=r30; mov r3=r29;; +#else + bsw.1;; + movl r31=XSI_IPSR;; + bsw.0 ;; +#endif + adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r20]=r0 ;; + mov pr=r31,-1 ;; + rfi +#endif // RFI_TO_INTERRUPT ENTRY(hyper_cover) #ifdef FAST_HYPERPRIVOP_CNT @@ -737,7 +1047,7 @@ ENTRY(hyper_get_ivr) (p6) ld8 r23=[r22];; (p6) cmp.eq p6,p0=r23,r0;; cmp.eq p6,p0=r23,r0 -(p6) br.cond.sptk.many 1f; // this is actually an error +(p6) br.cond.spnt.few 1f; // this is actually an error // r22 points to non-zero element of irr, r23 has value // r24 points to corr element of insvc, r25 has elt*64 ld8 r26=[r24];; @@ -770,11 +1080,11 @@ ENTRY(hyper_get_ivr) extr.u r28=r20,16,1 extr.u r29=r20,4,4 ;; cmp.ne p6,p0=r28,r0 // if tpr.mmi is set, return SPURIOUS -(p6) br.cond.sptk.many 1f; +(p6) br.cond.spnt.few 1f; shl r29=r29,4;; adds r29=15,r29;; cmp.ge p6,p0=r29,r26 -(p6) br.cond.sptk.many 1f; +(p6) br.cond.spnt.few 1f; // OK, have an unmasked vector to process/return ld8 r25=[r24];; or r25=r25,r27;; @@ -834,7 +1144,7 @@ ENTRY(hyper_eoi) (p6) ld8 r23=[r22];; (p6) cmp.eq p6,p0=r23,r0;; cmp.eq p6,p0=r23,r0 -(p6) br.cond.sptk.many 1f; // this is actually an error +(p6) br.cond.spnt.few 1f; // this is actually an error // r22 points to non-zero element of insvc, r23 has value shr.u r24=r23,1;; or r24=r23,r24;; @@ -964,7 +1274,7 @@ ENTRY(hyper_set_rr) adds r24=IA64_VCPU_META_SAVED_RR0_OFFSET,r20;; add r22=r26,r22;; cmp.geu p6,p0=r22,r23 // if r9.rid + starting_rid >= ending_rid -(p6) br.cond.sptk.many 1f; // this is an error, but just ignore/return +(p6) br.cond.spnt.few 1f; // this is an error, but just ignore/return // r21=starting_rid adds r20=XSI_RR0_OFS-XSI_PSR_IC_OFS,r18 ;; shl r25=r25,3;; diff --git a/xen/arch/ia64/ivt.S b/xen/arch/ia64/ivt.S index b1def7004f..37ae794366 100644 --- a/xen/arch/ia64/ivt.S +++ b/xen/arch/ia64/ivt.S @@ -919,6 +919,21 @@ ENTRY(interrupt) DBG_FAULT(12) mov r31=pr // prepare to save predicates ;; +#ifdef XEN + mov r30=cr.ivr // pass cr.ivr as first arg + // FIXME: this is a hack... use cpuinfo.pgd_quick because its + // not used anywhere else and we need a place to stash ivr and + // there's no registers available unused by SAVE_MIN/REST + movl r29=(PERCPU_ADDR)+IA64_CPUINFO_PGD_QUICK_OFFSET;; + st8 [r29]=r30;; + movl r28=slow_interrupt;; + mov r29=rp;; + mov rp=r28;; + br.cond.sptk.many fast_tick_reflect + ;; +slow_interrupt: + mov rp=r29;; +#endif SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 ssm psr.ic | PSR_DEFAULT_BITS ;; @@ -928,7 +943,12 @@ ENTRY(interrupt) SAVE_REST ;; alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group +#ifdef XEN + movl out0=(PERCPU_ADDR)+IA64_CPUINFO_PGD_QUICK_OFFSET;; + ld8 out0=[out0];; +#else mov out0=cr.ivr // pass cr.ivr as first arg +#endif add out1=16,sp // pass pointer to pt_regs as second arg ;; srlz.d // make sure we see the effect of cr.ivr diff --git a/xen/arch/ia64/privop.c b/xen/arch/ia64/privop.c index a45631b226..3ab81421f6 100644 --- a/xen/arch/ia64/privop.c +++ b/xen/arch/ia64/privop.c @@ -693,8 +693,8 @@ priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl) break; } //printf("We who are about do die salute you\n"); - printf("handle_op: can't handle privop at 0x%lx (op=0x%016lx) slot %d (type=%d)\n", - iip, (UINT64)inst.inst, slot, slot_type); + printf("handle_op: can't handle privop at 0x%lx (op=0x%016lx) slot %d (type=%d), ipsr=%p\n", + iip, (UINT64)inst.inst, slot, slot_type, ipsr); //printf("vtop(0x%lx)==0x%lx\n", iip, tr_vtop(iip)); //thread_mozambique("privop fault\n"); return (IA64_ILLOP_FAULT); @@ -734,6 +734,8 @@ priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr) // update iip/ipsr to point to the next instruction (void)vcpu_increment_iip(vcpu); } + if (fault == IA64_ILLOP_FAULT) + printf("priv_emulate: priv_handle_op fails, isr=%p\n",isr); return fault; } @@ -781,6 +783,7 @@ ia64_hyperprivop(unsigned long iim, REGS *regs) // FIXME: Handle faults appropriately for these if (!iim || iim > HYPERPRIVOP_MAX) { printf("bad hyperprivop; ignored\n"); + printf("iim=%d, iip=%p\n",iim,regs->cr_iip); return 1; } slow_hyperpriv_cnt[iim]++; diff --git a/xen/arch/ia64/process.c b/xen/arch/ia64/process.c index a26194d8f3..802a46b4ea 100644 --- a/xen/arch/ia64/process.c +++ b/xen/arch/ia64/process.c @@ -191,8 +191,8 @@ void reflect_interruption(unsigned long ifa, unsigned long isr, unsigned long it if (vector != IA64_DATA_TLB_VECTOR && vector != IA64_ALT_DATA_TLB_VECTOR && vector != IA64_VHPT_TRANS_VECTOR) { -panic_domain(regs,"psr.ic off, delivering fault=%lx,iip=%p,ifa=%p,isr=%p,PSCB.iip=%p\n", - vector,regs->cr_iip,ifa,isr,PSCB(v,iip)); +panic_domain(regs,"psr.ic off, delivering fault=%lx,ipsr=%p,iip=%p,ifa=%p,isr=%p,PSCB.iip=%p\n", + vector,regs->cr_ipsr,regs->cr_iip,ifa,isr,PSCB(v,iip)); } //printf("Delivering NESTED DATA TLB fault\n"); @@ -754,7 +754,8 @@ if (!running_on_sim) { printf("SSC_OPEN, not implemented on hardware. (ignoring vcpu_set_gr(current,8,-1L); break; default: - printf("ia64_handle_break: bad ssc code %lx, iip=%p, b0=%p\n",ssc,regs->cr_iip,regs->b0); + printf("ia64_handle_break: bad ssc code %lx, iip=%p, b0=%p... spinning\n",ssc,regs->cr_iip,regs->b0); + while(1); break; } vcpu_increment_iip(current); @@ -845,6 +846,7 @@ ia64_handle_reflection (unsigned long ifa, struct pt_regs *regs, unsigned long i break; case 26: printf("*** NaT fault... attempting to handle as privop\n"); +printf("isr=%p, ifa=%p,iip=%p,ipsr=%p\n",isr,ifa,regs->cr_iip,psr); vector = priv_emulate(v,regs,isr); if (vector == IA64_NO_FAULT) { printf("*** Handled privop masquerading as NaT fault\n"); diff --git a/xen/include/asm-ia64/xensystem.h b/xen/include/asm-ia64/xensystem.h index c1915646f2..6fadb60ebe 100644 --- a/xen/include/asm-ia64/xensystem.h +++ b/xen/include/asm-ia64/xensystem.h @@ -66,13 +66,12 @@ extern struct task_struct *vmx_ia64_switch_to (void *next_task); register long __gu_r8 asm ("r8"); \ register long __gu_r9 asm ("r9"); \ asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \ - asm volatile ("mov %2=r0;;\n" \ - "[1:]\tcmpxchg"_size".acq %0=[%3],%4,ar.ccv\n" \ - "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n" \ + asm volatile ("mov %1=r0;;\n" \ + "[1:]\tcmpxchg"_size".acq %0=[%2],%3,ar.ccv\n" \ + "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ "[1:]" \ - : "=r"(old), "=r"(__gu_r9), "=r"(__gu_r8) : \ + : "=r"(old), "=r"(__gu_r8) : \ "r"(ptr), "r"(new) : "memory"); \ - (old) = __gu_r9; \ __gu_r8; \ }) |