aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxen-ia64.adm@bkbits.net <xen-ia64.adm@bkbits.net>2005-06-29 21:37:40 +0000
committerxen-ia64.adm@bkbits.net <xen-ia64.adm@bkbits.net>2005-06-29 21:37:40 +0000
commit1daf04f8343750412a3ea47c55d96f760cda8b27 (patch)
treede80beef4fe2212f728c483927d1922f6bb266a0
parent79e1decf57682817f32e869dbff61606e6eac981 (diff)
parentcbd0cf09894d2e34c4db502e61baaa15fc3f71cb (diff)
downloadxen-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.c1
-rw-r--r--xen/arch/ia64/domain.c38
-rw-r--r--xen/arch/ia64/grant_table.c23
-rw-r--r--xen/arch/ia64/hypercall.c3
-rw-r--r--xen/arch/ia64/hyperprivop.S414
-rw-r--r--xen/arch/ia64/ivt.S20
-rw-r--r--xen/arch/ia64/privop.c7
-rw-r--r--xen/arch/ia64/process.c8
-rw-r--r--xen/include/asm-ia64/xensystem.h9
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; \
})