ChangeSet 1.1564.1.5, 2005/05/31 14:54:20-06:00, djm@xxxxxxxxxxxxxxx
Two more hyperprivops
Signed-off by: Dan Magenheimer <dan.magenheimer@xxxxxx>
arch/ia64/hyperprivop.S | 162 ++++++++++++++++++++++++++++++++++++++++++++-
arch/ia64/privop.c | 32 ++++++--
arch/ia64/vcpu.c | 18 ++---
include/public/arch-ia64.h | 5 -
4 files changed, 197 insertions(+), 20 deletions(-)
diff -Nru a/xen/arch/ia64/hyperprivop.S b/xen/arch/ia64/hyperprivop.S
--- a/xen/arch/ia64/hyperprivop.S 2005-06-10 14:03:24 -04:00
+++ b/xen/arch/ia64/hyperprivop.S 2005-06-10 14:03:24 -04:00
@@ -32,11 +32,45 @@
// HYPERPRIVOP_RFI?
cmp.eq p7,p6=XEN_HYPER_RFI,r17
(p7) br.sptk.many hyper_rfi;;
- // if not rfi, give up for now and do it the slow way
+
+#if 0
+ // HYPERPRIVOP_SSM_I?
+ cmp.eq p7,p6=XEN_HYPER_SSM_I,r17
+(p7) br.sptk.many hyper_ssm_i;;
+#endif
+
+#if 1
+// hard to test, because only called from rbs_switch
+ // HYPERPRIVOP_COVER?
+ cmp.eq p7,p6=XEN_HYPER_COVER,r17
+(p7) br.sptk.many hyper_cover;;
+#endif
+
+#if 0 // FIXME: This inexplicably causes the number of ssm_dt's to
+ // skyrocket, thus slowing down everything
+ // HYPERPRIVOP_SSM_DT?
+ cmp.eq p7,p6=XEN_HYPER_SSM_DT,r17
+(p7) br.sptk.many hyper_ssm_dt;;
+#endif
+
+#if 1
+ // HYPERPRIVOP_RSM_DT?
+ cmp.eq p7,p6=XEN_HYPER_RSM_DT,r17
+(p7) br.sptk.many hyper_rsm_dt;;
+#endif
+
+ // if not one of the above, give up for now and do it the slow way
br.sptk.many dispatch_break_fault ;;
// ensure that, if giving up, registers at entry to fast_hyperprivop unchanged
ENTRY(hyper_rfi)
+#define FAST_HYPERPRIVOP_CNT
+#ifdef FAST_HYPERPRIVOP_CNT
+ movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);;
+ ld8 r21=[r20];;
+ adds r21=1,r21;;
+ st8 [r20]=r21;;
+#endif
adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
ld8 r21=[r20];; // r21 = vcr.ipsr
extr.u r22=r21,IA64_PSR_BE_BIT,1 ;;
@@ -101,3 +135,129 @@
;;
rfi
;;
+
+ENTRY(hyper_cover)
+#ifdef FAST_HYPERPRIVOP_CNT
+ movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_COVER);;
+ ld8 r21=[r20];;
+ adds r21=1,r21;;
+ st8 [r20]=r21;;
+#endif
+ mov r24=cr.ipsr
+ mov r25=cr.iip;;
+ // skip test for vpsr.ic.. it's a prerequisite for hyperprivops
+ cover ;;
+ adds r20=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;;
+ mov r30=cr.ifs;;
+ adds r22=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18
+ ld4 r21=[r20] ;;
+ cmp.eq p6,p7=r21,r0 ;;
+(p6) st8 [r22]=r30;;
+(p7) st4 [r20]=r0;;
+ mov cr.ifs=r0;;
+ // adjust return address to skip over break instruction
+ extr.u r26=r24,41,2 ;;
+ cmp.eq p6,p7=2,r26 ;;
+(p6) mov r26=0
+(p6) adds r25=16,r25
+(p7) adds r26=1,r26
+ ;;
+ dep r24=r26,r24,41,2
+ ;;
+ mov cr.ipsr=r24
+ mov cr.iip=r25
+ mov pr=r31,-1 ;;
+ rfi
+ ;;
+
+#if 1
+// return from metaphysical mode (meta=1) to virtual mode (meta=0)
+ENTRY(hyper_ssm_dt)
+#ifdef FAST_HYPERPRIVOP_CNT
+ movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SSM_DT);;
+ ld8 r21=[r20];;
+ adds r21=1,r21;;
+ st8 [r20]=r21;;
+#endif
+ mov r24=cr.ipsr
+ mov r25=cr.iip;;
+ adds r20=XSI_METAPHYS_OFS-XSI_PSR_IC_OFS,r18 ;;
+ ld4 r21=[r20];;
+ cmp.eq p7,p0=r21,r0 // meta==0?
+(p7) br.spnt.many 1f ;; // already in virtual mode
+ mov r22=IA64_KR(CURRENT);;
+ adds r22=IA64_VCPU_META_SAVED_RR0_OFFSET,r22;;
+ ld4 r23=[r22];;
+ mov rr[r0]=r23;;
+ srlz.i;;
+ st4 [r20]=r0 ;;
+ // adjust return address to skip over break instruction
+ extr.u r26=r24,41,2 ;;
+ cmp.eq p6,p7=2,r26 ;;
+(p6) mov r26=0
+(p6) adds r25=16,r25
+(p7) adds r26=1,r26
+ ;;
+ dep r24=r26,r24,41,2
+ ;;
+ mov cr.ipsr=r24
+ mov cr.iip=r25
+1: mov pr=r31,-1 ;;
+ rfi
+ ;;
+
+// go to metaphysical mode (meta=1) from virtual mode (meta=0)
+ENTRY(hyper_rsm_dt)
+#ifdef FAST_HYPERPRIVOP_CNT
+ movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RSM_DT);;
+ ld8 r21=[r20];;
+ adds r21=1,r21;;
+ st8 [r20]=r21;;
+#endif
+ mov r24=cr.ipsr
+ mov r25=cr.iip;;
+ adds r20=XSI_METAPHYS_OFS-XSI_PSR_IC_OFS,r18 ;;
+ ld4 r21=[r20];;
+ cmp.ne p7,p0=r21,r0 // meta==0?
+(p7) br.spnt.many 1f ;; // already in metaphysical mode
+ mov r22=IA64_KR(CURRENT);;
+ adds r22=IA64_VCPU_META_RR0_OFFSET,r22;;
+ ld4 r23=[r22];;
+ mov rr[r0]=r23;;
+ srlz.i;;
+ adds r21=1,r0 ;;
+ st4 [r20]=r21 ;;
+ // adjust return address to skip over break instruction
+ extr.u r26=r24,41,2 ;;
+ cmp.eq p6,p7=2,r26 ;;
+(p6) mov r26=0
+(p6) adds r25=16,r25
+(p7) adds r26=1,r26
+ ;;
+ dep r24=r26,r24,41,2
+ ;;
+ mov cr.ipsr=r24
+ mov cr.iip=r25
+1: mov pr=r31,-1 ;;
+ rfi
+ ;;
+
+// enable interrupts (and also interrupt collection)
+ENTRY(hyper_ssm_i)
+#ifdef FAST_HYPERPRIVOP_CNT
+ movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SSM_I);;
+ ld8 r21=[r20];;
+ adds r21=1,r21;;
+ st8 [r20]=r21;;
+#endif
+ mov r24=cr.ipsr
+ mov r25=cr.iip;;
+ movl r20=0x100000001;;
+ st8 [r18]=r20;; // turn on both vpsr.i and vpsr.ic
+// FIXME: NEED TO UPDATE IPSR/IIP TO SKIP BREAK INST
+// FIXME: NEED TO CHECK FOR PENDING INTERRUPTS AND DELIVER THEM!
+1: mov pr=r31,-1 ;;
+ rfi
+ ;;
+#endif
+
diff -Nru a/xen/arch/ia64/privop.c b/xen/arch/ia64/privop.c
--- a/xen/arch/ia64/privop.c 2005-06-10 14:03:24 -04:00
+++ b/xen/arch/ia64/privop.c 2005-06-10 14:03:24 -04:00
@@ -747,14 +747,16 @@
#define HYPERPRIVOP_COVER 0x4
#define HYPERPRIVOP_ITC_D 0x5
#define HYPERPRIVOP_ITC_I 0x6
-#define HYPERPRIVOP_MAX 0x6
+#define HYPERPRIVOP_SSM_I 0x7
+#define HYPERPRIVOP_MAX 0x7
char *hyperpriv_str[HYPERPRIVOP_MAX+1] = {
- 0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i",
+ 0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i", "ssm.i",
0
};
-unsigned long hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 };
+unsigned long slow_hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 };
+unsigned long fast_hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 };
/* hyperprivops are generally executed in assembly (with physical psr.ic off)
* so this code is primarily used for debugging them */
@@ -765,13 +767,12 @@
INST64 inst;
UINT64 val;
-// FIXME: Add instrumentation for these
// FIXME: Handle faults appropriately for these
if (!iim || iim > HYPERPRIVOP_MAX) {
printf("bad hyperprivop; ignored\n");
return 1;
}
- hyperpriv_cnt[iim]++;
+ slow_hyperpriv_cnt[iim]++;
switch(iim) {
case HYPERPRIVOP_RFI:
(void)vcpu_rfi(ed);
@@ -793,6 +794,9 @@
inst.inst = 0;
(void)priv_itc_i(ed,inst);
return 1;
+ case HYPERPRIVOP_SSM_I:
+ (void)vcpu_set_psr_i(ed);
+ return 1;
}
return 0;
}
@@ -981,18 +985,28 @@
{
int i;
char *s = buf;
- s += sprintf(s,"Slow hyperprivops:\n");
+ unsigned long total = 0;
+ for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += slow_hyperpriv_cnt[i];
+ s += sprintf(s,"Slow hyperprivops (total %d:\n",total);
+ for (i = 1; i <= HYPERPRIVOP_MAX; i++)
+ if (slow_hyperpriv_cnt[i])
+ s += sprintf(s,"%10d %s\n",
+ slow_hyperpriv_cnt[i], hyperpriv_str[i]);
+ total = 0;
+ for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += fast_hyperpriv_cnt[i];
+ s += sprintf(s,"Fast hyperprivops (total %d:\n",total);
for (i = 1; i <= HYPERPRIVOP_MAX; i++)
- if (hyperpriv_cnt[i])
+ if (fast_hyperpriv_cnt[i])
s += sprintf(s,"%10d %s\n",
- hyperpriv_cnt[i], hyperpriv_str[i]);
+ fast_hyperpriv_cnt[i], hyperpriv_str[i]);
return s - buf;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|