bitkeeper revision 1.1221.1.1 (42265de0hZSi5pHFW0EmtG7Pkn2Ojw)
authordjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Thu, 3 Mar 2005 00:44:16 +0000 (00:44 +0000)
committerdjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Thu, 3 Mar 2005 00:44:16 +0000 (00:44 +0000)
Add user access code and mechanism and switch privop access
code over to use it.

xen/arch/ia64/Makefile
xen/arch/ia64/privop.c
xen/arch/ia64/process.c
xen/arch/ia64/tools/mkbuildtree
xen/arch/ia64/xenasm.S
xen/arch/ia64/xenmisc.c
xen/arch/ia64/xensetup.c
xen/include/asm-ia64/config.h

index e6f2c26af248a6e10b6843bfb82cf838e1e1692f..fb0511ffe22d672515cb67b3d60835bb25ce7612 100644 (file)
@@ -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
index d3540462d3500788ebfb2557c0d176e23450e874..85c839103d064e3de4a9f6b80c4120140cfe4933 100644 (file)
@@ -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;
 }
index 029ec803c766ecea483a19af5055aee4bb4ba1d1..f1d40d7b8a0a235ab79f77987e8ab73064762f12 100644 (file)
@@ -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);
        }
index 883dd91b8a0aed7356ffd0406eeec2bebe16fb01..35c3e926a9a0c3dd5e68c5348d4676352fdf609a 100644 (file)
@@ -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
index 3be0b9b2a8c154950f45541ad6a8ce5dcee8fcba..998a3d87d15d31bf2191cb1c92bc4d17b54cdd90 100644 (file)
@@ -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
index 663319de3c335bf09f808174b137aa3026afc123..425aed9894d31ac6d9a55a0b6d3d86473c693833 100644 (file)
@@ -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;
+}
index e8d779ecc1f4f7ca89ac413dc8c8b45cb6aa01ff..888e7488df6d55e657dc616526bd7af6c9285dcf 100644 (file)
@@ -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();
 
index 80a80c0eb06c978c27ee7a2cca0822d06ea4355c..3d1c4fc5002c8dd66128bac3911f58efba52e7d3 100644 (file)
@@ -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