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;
// 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;
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
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;
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;
}
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
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) {
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");
// 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);
}