diff options
author | xen-ia64.adm@bkbits.net <xen-ia64.adm@bkbits.net> | 2005-03-07 17:31:43 +0000 |
---|---|---|
committer | xen-ia64.adm@bkbits.net <xen-ia64.adm@bkbits.net> | 2005-03-07 17:31:43 +0000 |
commit | 1cc05252d378a0fff39f6e13bec30615b4669f5e (patch) | |
tree | 3a3f43909e80c149c8ee1ee3281877c86d94823d | |
parent | aa4b616c673527e14e7729c571b37de35daee7bf (diff) | |
parent | 45dd7ca4d6a4879e08a810ebda6724ebcce9bf10 (diff) | |
download | xen-1cc05252d378a0fff39f6e13bec30615b4669f5e.tar.gz xen-1cc05252d378a0fff39f6e13bec30615b4669f5e.tar.bz2 xen-1cc05252d378a0fff39f6e13bec30615b4669f5e.zip |
bitkeeper revision 1.1236.11.1 (422c8fffPd62_3ejA06WBfNou1MZyg)
Merge bk://xen.bkbits.net/xeno-unstable.bk
into bkbits.net:/repos/x/xen-ia64/xeno-unstable-ia64.bk
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | xen/arch/ia64/Makefile | 1 | ||||
-rw-r--r-- | xen/arch/ia64/privop.c | 90 | ||||
-rw-r--r-- | xen/arch/ia64/process.c | 39 | ||||
-rw-r--r-- | xen/arch/ia64/tools/mkbuildtree | 5 | ||||
-rw-r--r-- | xen/arch/ia64/xenasm.S | 19 | ||||
-rw-r--r-- | xen/arch/ia64/xenmisc.c | 12 | ||||
-rw-r--r-- | xen/arch/ia64/xensetup.c | 2 | ||||
-rw-r--r-- | xen/include/asm-ia64/config.h | 17 |
9 files changed, 151 insertions, 35 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a20c296edf..b8ea3df1eb 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -76,4 +76,5 @@ tlh20@elite.cl.cam.ac.uk tlh20@labyrinth.cl.cam.ac.uk tw275@labyrinth.cl.cam.ac.uk tw275@striker.cl.cam.ac.uk +xen-ia64.adm@bkbits.net xenbk@gandalf.hpl.hp.com diff --git a/xen/arch/ia64/Makefile b/xen/arch/ia64/Makefile index e6f2c26af2..fb0511ffe2 100644 --- a/xen/arch/ia64/Makefile +++ b/xen/arch/ia64/Makefile @@ -7,6 +7,7 @@ OBJS = xensetup.o setup.o time.o irq.o ia64_ksyms.o process.o smp.o \ machvec.o dom0_ops.o domain.o \ idle0_task.o pal.o hpsim.o efi.o efi_stub.o ivt.o mm_contig.o \ mm_bootmem.o sal.o cmdline.o mm_init.o tlb.o page_alloc.o slab.o \ + extable.o linuxextable.o \ regionreg.o entry.o unaligned.o privop.o vcpu.o \ irq_ia64.o irq_lsapic.o hpsim_irq.o vhpt.o xenasm.o dom_fw.o # perfmon.o diff --git a/xen/arch/ia64/privop.c b/xen/arch/ia64/privop.c index d3540462d3..85c839103d 100644 --- a/xen/arch/ia64/privop.c +++ b/xen/arch/ia64/privop.c @@ -538,7 +538,8 @@ unsigned long privop_trace = 0; IA64FAULT priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl) { - IA64_BUNDLE bundle, __get_domain_bundle(UINT64); + IA64_BUNDLE bundle; + IA64_BUNDLE __get_domain_bundle(UINT64); int slot; IA64_SLOT_TYPE slot_type; INST64 inst; @@ -550,19 +551,14 @@ priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl) // make a local copy of the bundle containing the privop #if 1 bundle = __get_domain_bundle(iip); - if (!bundle.i64[0] && !bundle.i64[1]) return IA64_RETRY; -#else -#ifdef AVOIDING_POSSIBLE_DOMAIN_TLB_MISS - //TODO: this needs to check for faults and behave accordingly - if (!vcpu_get_iip_bundle(&bundle)) return IA64_DTLB_FAULT; + if (!bundle.i64[0] && !bundle.i64[1]) #else -if (iip < 0x10000) { - printf("priv_handle_op: unlikely iip=%p,b0=%p\n",iip,regs->b0); - dummy(); -} - bundle = *(IA64_BUNDLE *)iip; -#endif + if (__copy_from_user(&bundle,iip,sizeof(bundle))) #endif + { +//printf("*** priv_handle_op: privop bundle @%p not mapped, retrying\n",iip); + return IA64_RETRY; + } #if 0 if (iip==0xa000000100001820) { static int firstpagefault = 1; @@ -783,10 +779,12 @@ char *cr_str[128] = { RS,RS,RS,RS,RS,RS,RS,RS }; -void dump_privop_counts(void) +// FIXME: should use snprintf to ensure no buffer overflow +int dump_privop_counts(char *buf) { int i, j; UINT64 sum = 0; + char *s = buf; // this is ugly and should probably produce sorted output // but it will have to do for now @@ -795,63 +793,64 @@ void dump_privop_counts(void) sum += privcnt.rfi; sum += privcnt.bsw0; sum += privcnt.bsw1; sum += privcnt.cover; for (i=0; i < 64; i++) sum += privcnt.Mpriv_cnt[i]; - printf("Privop statistics: (Total privops: %ld)\r\n",sum); + s += sprintf(s,"Privop statistics: (Total privops: %ld)\r\n",sum); if (privcnt.mov_to_ar_imm) - printf("%10d %s [%d%%]\r\n", privcnt.mov_to_ar_imm, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.mov_to_ar_imm, "mov_to_ar_imm", (privcnt.mov_to_ar_imm*100L)/sum); if (privcnt.mov_to_ar_reg) - printf("%10d %s [%d%%]\r\n", privcnt.mov_to_ar_reg, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.mov_to_ar_reg, "mov_to_ar_reg", (privcnt.mov_to_ar_reg*100L)/sum); if (privcnt.ssm) - printf("%10d %s [%d%%]\r\n", privcnt.ssm, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.ssm, "ssm", (privcnt.ssm*100L)/sum); if (privcnt.rsm) - printf("%10d %s [%d%%]\r\n", privcnt.rsm, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.rsm, "rsm", (privcnt.rsm*100L)/sum); if (privcnt.rfi) - printf("%10d %s [%d%%]\r\n", privcnt.rfi, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.rfi, "rfi", (privcnt.rfi*100L)/sum); if (privcnt.bsw0) - printf("%10d %s [%d%%]\r\n", privcnt.bsw0, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.bsw0, "bsw0", (privcnt.bsw0*100L)/sum); if (privcnt.bsw1) - printf("%10d %s [%d%%]\r\n", privcnt.bsw1, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.bsw1, "bsw1", (privcnt.bsw1*100L)/sum); if (privcnt.cover) - printf("%10d %s [%d%%]\r\n", privcnt.cover, + s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.cover, "cover", (privcnt.cover*100L)/sum); for (i=0; i < 64; i++) if (privcnt.Mpriv_cnt[i]) { - if (!Mpriv_str[i]) printf("PRIVSTRING NULL!!\r\n"); - else printf("%10d %s [%d%%]\r\n", privcnt.Mpriv_cnt[i], + if (!Mpriv_str[i]) s += sprintf(s,"PRIVSTRING NULL!!\r\n"); + else s += sprintf(s,"%10d %s [%d%%]\r\n", privcnt.Mpriv_cnt[i], Mpriv_str[i], (privcnt.Mpriv_cnt[i]*100L)/sum); if (i == 0x24) { // mov from CR - printf(" ["); + s += sprintf(s," ["); for (j=0; j < 128; j++) if (from_cr_cnt[j]) { if (!cr_str[j]) - printf("PRIVSTRING NULL!!\r\n"); - printf("%s(%d),",cr_str[j],from_cr_cnt[j]); + s += sprintf(s,"PRIVSTRING NULL!!\r\n"); + s += sprintf(s,"%s(%d),",cr_str[j],from_cr_cnt[j]); } - printf("]\r\n"); + s += sprintf(s,"]\r\n"); } else if (i == 0x2c) { // mov to CR - printf(" ["); + s += sprintf(s," ["); for (j=0; j < 128; j++) if (to_cr_cnt[j]) { if (!cr_str[j]) - printf("PRIVSTRING NULL!!\r\n"); - printf("%s(%d),",cr_str[j],to_cr_cnt[j]); + s += sprintf(s,"PRIVSTRING NULL!!\r\n"); + s += sprintf(s,"%s(%d),",cr_str[j],to_cr_cnt[j]); } - printf("]\r\n"); + s += sprintf(s,"]\r\n"); } } + return s - buf; } -void zero_privop_counts(void) +int zero_privop_counts(char *buf) { int i, j; + char *s = buf; // this is ugly and should probably produce sorted output // but it will have to do for now - printf("Zeroing privop statistics\r\n"); privcnt.mov_to_ar_imm = 0; privcnt.mov_to_ar_reg = 0; privcnt.ssm = 0; privcnt.rsm = 0; privcnt.rfi = 0; privcnt.bsw0 = 0; @@ -859,4 +858,27 @@ void zero_privop_counts(void) for (i=0; i < 64; i++) privcnt.Mpriv_cnt[i] = 0; for (j=0; j < 128; j++) from_cr_cnt[j] = 0; for (j=0; j < 128; j++) to_cr_cnt[j] = 0; + s += sprintf(s,"All privop statistics zeroed\r\n"); + return s - buf; +} + +#define TMPBUFLEN 8*1024 +int dump_privop_counts_to_user(char __user *ubuf, int len) +{ + char buf[TMPBUFLEN]; + int n = dump_privop_counts(buf); + + if (len < TMPBUFLEN) return -1; + if (__copy_to_user(ubuf,buf,n)) return -1; + return n; +} + +int zero_privop_counts_to_user(char __user *ubuf, int len) +{ + char buf[TMPBUFLEN]; + int n = zero_privop_counts(buf); + + if (len < TMPBUFLEN) return -1; + if (__copy_to_user(ubuf,buf,n)) return -1; + return n; } diff --git a/xen/arch/ia64/process.c b/xen/arch/ia64/process.c index 029ec803c7..8baacbc816 100644 --- a/xen/arch/ia64/process.c +++ b/xen/arch/ia64/process.c @@ -242,7 +242,9 @@ void xen_handle_domain_access(unsigned long address, unsigned long isr, struct p unsigned long pteval, mpaddr; unsigned long lookup_domain_mpa(struct domain *,unsigned long); IA64FAULT fault; +#ifndef USER_ACCESS extern void __get_domain_bundle(void); +#endif // NEED TO HANDLE THREE CASES: // 1) domain is in metaphysical mode @@ -265,20 +267,41 @@ void xen_handle_domain_access(unsigned long address, unsigned long isr, struct p vcpu_itc_no_srlz(ed,2,address,pteval,PAGE_SHIFT); return; } -if (address < 0x4000) printf("WARNING: page_fault @%p, iip=%p\n",address,iip); +#ifndef USER_ACCESS if (*(unsigned long *)__get_domain_bundle != iip) { printf("Bad user space access @%p ",address); printf("iip=%p, ipsr=%p, b0=%p\n",iip,psr,regs->b0); while(1); } +#endif +if (address < 0x4000) printf("WARNING: page_fault @%p, iip=%p\n",address,iip); fault = vcpu_tpa(ed,address,&mpaddr); if (fault != IA64_NO_FAULT) { +#ifndef USER_ACCESS // this is hardcoded to handle __get_domain_bundle only regs->r8 = 0; regs->r9 = 0; regs->cr_iip += 0x20; //regs->cr_iip |= (2UL << IA64_PSR_RI_BIT); return; +#else /* USER_ACCESS */ + static int uacnt = 0; + // can't translate it, just fail (poor man's exception) + // which results in retrying execution +//printk("*** xen_handle_domain_access: poor man's exception cnt=%i iip=%p, addr=%p...\n",uacnt++,iip,address); + if (ia64_done_with_exception(regs)) { +//if (!(uacnt++ & 0x3ff)) printk("*** xen_handle_domain_access: successfully handled cnt=%d iip=%p, addr=%p...\n",uacnt,iip,address); + return; + } + else { + // should never happen. If it does, region 0 addr may + // indicate a bad xen pointer + printk("*** xen_handle_domain_access: exception table" + " lookup failed, iip=%p, addr=%p, spinning...\n", + iip,address); + while(1); + } +#endif /* USER_ACCESS */ } if (d == dom0) { if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) { @@ -286,6 +309,7 @@ if (address < 0x4000) printf("WARNING: page_fault @%p, iip=%p\n",address,iip); tdpfoo(); } } +//printk("*** xen_handle_domain_access: tpa resolved miss @%p...\n",address); pteval = lookup_domain_mpa(d,mpaddr); // would be nice to have a counter here //printf("Handling privop data TLB miss\n"); @@ -755,6 +779,16 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u // FIXME: need fixes in efi.h from 2.6.9 regs->r8 = EFI_UNSUPPORTED; break; + case 0xffff: // test dummy hypercall + regs->r8 = dump_privop_counts_to_user( + vcpu_get_gr(ed,32), + vcpu_get_gr(ed,33)); + break; + case 0xfffe: // test dummy hypercall + regs->r8 = zero_privop_counts_to_user( + vcpu_get_gr(ed,32), + vcpu_get_gr(ed,33)); + break; } vcpu_increment_iip(current); } @@ -809,6 +843,9 @@ ia64_handle_reflection (unsigned long ifa, struct pt_regs *regs, unsigned long i case 10: check_lazy_cover = 1; vector = IA64_DATA_ACCESS_BIT_VECTOR; break; + case 20: + check_lazy_cover = 1; + vector = IA64_PAGE_NOT_PRESENT_VECTOR; break; case 22: vector = IA64_INST_ACCESS_RIGHTS_VECTOR; break; case 23: diff --git a/xen/arch/ia64/tools/mkbuildtree b/xen/arch/ia64/tools/mkbuildtree index 883dd91b8a..35c3e926a9 100644 --- a/xen/arch/ia64/tools/mkbuildtree +++ b/xen/arch/ia64/tools/mkbuildtree @@ -98,6 +98,9 @@ cp_patch mm/bootmem.c arch/ia64/mm_bootmem.c mm_bootmem.c cp_patch mm/page_alloc.c arch/ia64/page_alloc.c page_alloc.c cp_patch mm/slab.c arch/ia64/slab.c slab.c +# following renamed to avoid conflict +softlink kernel/extable.c arch/ia64/linuxextable.c + cp_patch arch/ia64/mm/contig.c arch/ia64/mm_contig.c mm_contig.c cp_patch arch/ia64/mm/tlb.c arch/ia64/tlb.c tlb.c @@ -108,6 +111,7 @@ softlink arch/ia64/kernel/entry.h arch/ia64/entry.h softlink arch/ia64/kernel/ia64_ksyms.c arch/ia64/ia64_ksyms.c softlink arch/ia64/kernel/irq_lsapic.c arch/ia64/irq_lsapic.c softlink arch/ia64/kernel/machvec.c arch/ia64/machvec.c +softlink arch/ia64/mm/extable.c arch/ia64/extable.c softlink arch/ia64/kernel/pal.S arch/ia64/pal.S softlink arch/ia64/kernel/patch.c arch/ia64/patch.c softlink arch/ia64/kernel/sal.c arch/ia64/sal.c @@ -182,6 +186,7 @@ null include/asm-ia64/domain_page.h null include/asm-ia64/flushtlb.h null include/asm-ia64/io_apic.h null include/asm-ia64/pdb.h +null include/asm-ia64/module.h softlink include/asm-ia64/acpi.h include/asm-ia64/acpi.h softlink include/asm-ia64/asmmacro.h include/asm-ia64/asmmacro.h diff --git a/xen/arch/ia64/xenasm.S b/xen/arch/ia64/xenasm.S index 3be0b9b2a8..998a3d87d1 100644 --- a/xen/arch/ia64/xenasm.S +++ b/xen/arch/ia64/xenasm.S @@ -261,6 +261,8 @@ GLOBAL_ENTRY(ia64_prepare_handle_reflection) br.cond.sptk.many rp // goes to ia64_leave_kernel END(ia64_prepare_handle_reflection) +#ifndef USER_ACCESS +// REMOVE: replaced with get_user // NOTE: instruction spacing must be explicit for recovery on miss GLOBAL_ENTRY(__get_domain_bundle) ld8 r8=[r32],8 @@ -276,6 +278,23 @@ GLOBAL_ENTRY(__get_domain_bundle) nop 0 ;; END(__get_domain_bundle) +#else +GLOBAL_ENTRY(__get_domain_bundle) + EX(.failure_in_get_bundle,ld8 r8=[r32],8) + ;; + EX(.failure_in_get_bundle,ld8 r9=[r32]) + ;; + br.ret.sptk.many rp + ;; +.failure_in_get_bundle: + mov r8=0 + ;; + mov r9=0 + ;; + br.ret.sptk.many rp + ;; +END(__get_domain_bundle) +#endif GLOBAL_ENTRY(dorfirfi) #define SI_CR_IIP_OFFSET 0x10 diff --git a/xen/arch/ia64/xenmisc.c b/xen/arch/ia64/xenmisc.c index 663319de3c..425aed9894 100644 --- a/xen/arch/ia64/xenmisc.c +++ b/xen/arch/ia64/xenmisc.c @@ -216,3 +216,15 @@ physdev_pci_access_modify(domid_t id, int bus, int dev, int func, int enable) { return -EINVAL; } + +// accomodate linux extable.c +//const struct exception_table_entry * +void *search_module_extables(unsigned long addr) +{ + return NULL; +} + +void *module_text_address(unsigned long addr) +{ + return NULL; +} diff --git a/xen/arch/ia64/xensetup.c b/xen/arch/ia64/xensetup.c index 713dd5761a..59ba8a4c49 100644 --- a/xen/arch/ia64/xensetup.c +++ b/xen/arch/ia64/xensetup.c @@ -288,6 +288,8 @@ printk("About to call ac_timer_init()\n"); // init_xen_time(); ??? // schedulers_start(); ??? // do_initcalls(); ??? +printk("About to call sort_main_extable()\n"); + sort_main_extable(); #else start_of_day(); diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 80a80c0eb0..3d1c4fc500 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -1,4 +1,7 @@ +// control flags for turning on/off features under test #undef CLONE_DOMAIN0 +#define USER_ACCESS + // manufactured from component pieces // defined in linux/arch/ia64/defconfig @@ -160,6 +163,20 @@ struct pci_bus_region { unsigned long end; }; +// from linux/include/linux/module.h + +// warning: unless search_extable is declared, the return value gets +// truncated to 32-bits, causing a very strange error in privop handling +struct exception_table_entry; + +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value); +void sort_extable(struct exception_table_entry *start, + struct exception_table_entry *finish); +void sort_main_extable(void); + // defined (why?) in include/asm-i386/processor.h // used in common/physdev.c #define IO_BITMAP_SIZE 32 |