From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christian Ehrhardt Date: Thu, 02 Oct 2008 12:02:00 +0000 Subject: Re: exit timing analysis v1 - comments&discussions welcome Message-Id: <48E4B838.1010906@linux.vnet.ibm.com> MIME-Version: 1 Content-Type: multipart/mixed; boundary="------------010901090800080007020006" List-Id: References: <48DA0747.3020004@linux.vnet.ibm.com> In-Reply-To: <48DA0747.3020004@linux.vnet.ibm.com> To: kvm-ppc@vger.kernel.org This is a multi-part message in MIME format. --------------010901090800080007020006 Content-Type: text/plain; charset="iso-8859-1"; format="flowed" Content-Transfer-Encoding: quoted-printable Today I refactored my code in a way that it might eventually get upstream. That means I removed some debug blocks, made it configurable and print=20 output only on request per sysrq. Feel free to review that code now, otherwise wait for my separate rfc=20 post that will follow ~next week. Additionally I realized in a discussion that my host system was still=20 configured in demo mode (X11+xfce, dhcpd, avahi, ... running in host). I took some updated numbers without all those background activities -=20 testacase again boot, login, ls, kill. I intend to the irq path in detail as suggested and first of all I'll=20 try to get some timing of the "segments" of such a call. This should show us where we loose our "constant base time" and give me=20 some hints when looking at it in detail. FYI - new numbers without high background load (monospace recommended): NOPV: MMIO count 10105 min 46 max 1534=20 sum 2952467 avg 292.1788 stddev 295.933 % 2.04 DCR count 5428 min 40 max 209=20 sum 246168 avg 45.3515 stddev 6.758 % 0.17 SIGNAL count 695 min 65 max 3755=20 sum 89767 avg 129.1612 stddev 314.421 % 0.06 ITLBREAL count 80045 min 13 max 108=20 sum 1063127 avg 13.2816 stddev 2.338 % 0.73 ITLBVIRT count 1000585 min 21 max 264827=20 sum 24300596 avg 24.2864 stddev 264.753 % 16.78 DTLBREAL count 91206 min 13 max 69=20 sum 1285214 avg 14.0913 stddev 2.225 % 0.89 DTLBVIRT count 977434 min 21 max 1446=20 sum 24007008 avg 24.5613 stddev 4.426 % 16.58 SYSCALL count 10460 min 11 max 55=20 sum 116447 avg 11.1326 stddev 1.929 % 0.08 ISI count 11724 min 11 max 61=20 sum 130007 avg 11.0890 stddev 1.929 % 0.09 DSI count 20737 min 11 max 57=20 sum 230009 avg 11.0917 stddev 1.914 % 0.16 EMULINST count 5683356 min 11 max 3778=20 sum 79339467 avg 13.9600 stddev 50.275 % 54.78 DEC count 13079 min 50 max 826=20 sum 732712 avg 56.0220 stddev 22.382 % 0.51 EXTINT count 55 min 30 max 1478=20 sum 10996 avg 199.9273 stddev 238.150 % 0.01 FP_UNAVAIL count 280 min 11 max 53=20 sum 3163 avg 11.2964 stddev 3.495 % 0.00 TIMEINGUEST count 7905189 min 0 max 3688=20 sum 10330742 avg 1.3068 stddev 8.970 % 7.13 csum 15810378 =20 sumsum 144837890 =3D> ~2:24 runtime =20 sumavg 7241894 PV: MMIO count 12505 min 46 max 3087=20 sum 3693782 avg 295.3844 stddev 260.788 % 4.01 DCR count 5595 min 40 max 706=20 sum 273578 avg 48.8969 stddev 31.305 % 0.30 SIGNAL count 654 min 65 max 4132=20 sum 300027 avg 458.7569 stddev 571.130 % 0.33 ITLBREAL count 71711 min 13 max 104=20 sum 943053 avg 13.1507 stddev 2.360 % 1.02 ITLBVIRT count 750649 min 21 max 1503=20 sum 18178245 avg 24.2167 stddev 7.335 % 19.71 DTLBREAL count 83356 min 13 max 102=20 sum 1146242 avg 13.7512 stddev 2.406 % 1.24 DTLBPV count 30086 min 20 max 237=20 sum 653556 avg 21.7229 stddev 4.639 % 0.71 DTLBVIRT count 772811 min 21 max 713=20 sum 19079477 avg 24.6884 stddev 6.593 % 20.69 SYSCALL count 7647 min 11 max 57=20 sum 84821 avg 11.0921 stddev 1.897 % 0.09 HCALL count 1 min 19 max 19=20 sum 19 avg 19.0000 stddev 0.000 % 0.00 ISI count 9895 min 11 max 73=20 sum 109667 avg 11.0831 stddev 1.904 % 0.12 DSI count 17974 min 10 max 57=20 sum 199504 avg 11.0996 stddev 2.046 % 0.22 EMULINST count 2567245 min 11 max 4212=20 sum 40501314 avg 15.7762 stddev 65.673 % 43.92 DEC count 7488 min 51 max 641=20 sum 426813 avg 56.9996 stddev 23.893 % 0.46 EXTINT count 2215 min 31 max 1677=20 sum 297495 avg 134.3093 stddev 116.219 % 0.32 FP_UNAVAIL count 258 min 11 max 11=20 sum 2838 avg 11.0000 stddev 0.000 % 0.00 TIMEINGUEST count 4340090 min 0 max 3850=20 sum 6316079 avg 1.4553 stddev 12.599 % 6.85 csum 8680180 =20 sumsum 92206510 =3D> ~1:32 runtime =20 sumavg 4610325 Hollis Blanchard wrote: > On Thu, 2008-09-25 at 17:32 +0800, Liu Yu-B13201 wrote: >>> On Wed, 2008-09-24 at 11:24 +0200, Christian Ehrhardt wrote: >>>> count min max =20 >>>> sum avg stddev time% >>>> EMULINST 6,423,699 12 247,582 =20 >>> 91,732,705 =20 >>>> 14.2804 241.200 45.36 >>>> ITLBVIRT 1,777,242 21 264,257 =20 >>> 47,116,557 =20 >>>> 26.5111 286.040 23.30 >>>> DTLBVIRT 1,544,241 22 263,947 =20 >>> 41,765,447 =20 >>>> 27.0459 218.997 20.65 >>> (The max here is of course when the guest was de-scheduled in favor of >>> another host process.) >>> >>> I think it's interesting that the min instruction emulation time is 12 >>> usecs. In fact, our "null" exits where we do almost no=20 >>> processing (ISI, >>> DSI, syscall) are 11 usecs, which suggests we have a problem with >>> interrupt handler overhead (for all exit types). >>> >> Will you consider about moving tlb manipulation out of entering path? >> Examining the modify array may cost some time. > > Yes, definitely. > > That's about the only thing I can see in the 440 interrupt path that > might take significant time. Unfortunately we can't profile that code > because we have no performance counters, so finding the problem will > require some experimentation. --=20 Gr=FCsse / regards,=20 Christian Ehrhardt IBM Linux Technology Center, Open Virtualization --------------010901090800080007020006 Content-Type: text/x-diff; name="kvmppc-exit-timing.diff" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="kvmppc-exit-timing.diff" diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -348,5 +348,12 @@ DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); #endif +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING + DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu, arch.timing_exit.tv32.tbu)); + DEFINE(VCPU_TIMING_EXIT_TBL, offsetof(struct kvm_vcpu, arch.timing_exit.tv32.tbl)); + DEFINE(VCPU_TIMING_LAST_ENTER_TBU, offsetof(struct kvm_vcpu, arch.timing_last_enter.tv32.tbu)); + DEFINE(VCPU_TIMING_LAST_ENTER_TBL, offsetof(struct kvm_vcpu, arch.timing_last_enter.tv32.tbl)); +#endif + return 0; } diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -37,6 +37,14 @@ Provides host support for KVM on Book E PowerPC processors. Currently this works on 440 processors only. +config KVM_BOOKE_EXIT_TIMING + bool "Trace detailed exit Timing" + depends on KVM_BOOKE_HOST + ---help--- + Inserts code to trace timestamps for every exit/enter cycle. A report + can be triggered using debugfs entry TODO. + This adds overhead, it's not recommended for production environments. + config KVM_TRACE bool "KVM trace support" depends on KVM && MARKERS && SYSFS diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c --- a/arch/powerpc/kvm/booke_guest.c +++ b/arch/powerpc/kvm/booke_guest.c @@ -56,6 +56,21 @@ { "halt_wakeup", VCPU_STAT(halt_wakeup) }, { NULL } }; + +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING +u32 last_exit_type; +u32 timing_count_type[__NUMBER_OF_KVM_EXIT_TYPES]; +u64 timing_sum_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +u64 timing_sum_quad_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +u64 timing_min_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +u64 timing_max_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +u64 timing_last_exit; +struct sysrq_key_op trigger_print_exit_timing_op = { + .handler = print_exit_timing_handler, + .help_msg = "Print KVm PowerPC exit timings", + .action_msg = "Printing KVM PowerPC exit timings", +}; +#endif static const u32 interrupt_msr_mask[16] = { [BOOKE_INTERRUPT_CRITICAL] = MSR_ME, @@ -261,6 +276,9 @@ enum emulation_result er; int r = RESUME_HOST; + /* update before a new last_exit_type is written */ + update_exit_timing(&(vcpu->arch)); + local_irq_enable(); run->exit_reason = KVM_EXIT_UNKNOWN; @@ -285,10 +303,13 @@ * misses before ceding control. */ if (need_resched()) cond_resched(); - if (exit_nr == BOOKE_INTERRUPT_DECREMENTER) + if (exit_nr == BOOKE_INTERRUPT_DECREMENTER) { vcpu->stat.dec_exits++; - else + set_last_exit_type(DEC_EXITS); + } else { vcpu->stat.ext_intr_exits++; + set_last_exit_type(EXT_INTR_EXITS); + } r = RESUME_GUEST; break; @@ -299,6 +320,7 @@ vcpu->arch.esr = vcpu->arch.fault_esr; kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); r = RESUME_GUEST; + set_last_exit_type(USR_PR_INST); break; } @@ -308,10 +330,12 @@ /* Future optimization: only reload non-volatiles if * they were actually modified by emulation. */ vcpu->stat.emulated_inst_exits++; + set_last_exit_type(EMULATED_INST_EXITS); r = RESUME_GUEST_NV; break; case EMULATE_DO_DCR: run->exit_reason = KVM_EXIT_DCR; + set_last_exit_type(DCR_EXITS); r = RESUME_HOST; break; case EMULATE_FAIL: @@ -331,6 +355,7 @@ case BOOKE_INTERRUPT_FP_UNAVAIL: kvmppc_queue_exception(vcpu, exit_nr); + set_last_exit_type(FP_UNAVAIL); r = RESUME_GUEST; break; @@ -339,6 +364,7 @@ vcpu->arch.esr = vcpu->arch.fault_esr; kvmppc_queue_exception(vcpu, exit_nr); vcpu->stat.dsi_exits++; + set_last_exit_type(DSI_EXITS); r = RESUME_GUEST; break; @@ -346,6 +372,7 @@ vcpu->arch.esr = vcpu->arch.fault_esr; kvmppc_queue_exception(vcpu, exit_nr); vcpu->stat.isi_exits++; + set_last_exit_type(ISI_EXITS); r = RESUME_GUEST; break; @@ -353,9 +380,11 @@ if (vcpu->arch.last_inst == KVM_HYPERCALL_BIN) { kvmppc_do_hypercall(vcpu); vcpu->stat.hcall_exits++; + set_last_exit_type(HCALL_EXITS); } else { kvmppc_queue_exception(vcpu, exit_nr); vcpu->stat.syscall_exits++; + set_last_exit_type(SYSCALL_EXITS); } r = RESUME_GUEST; break; @@ -370,6 +399,7 @@ vcpu->arch.pvmem_gpaddr >> KVM_PPCPV_MAGIC_PAGE_SHIFT, 0, KVM_PPCPV_MAGIC_PAGE_FLAGS); vcpu->stat.dtlb_pvmem_miss_exits++; + set_last_exit_type(DTLB_PVMEM_MISS_EXITS); r = RESUME_GUEST; break; } @@ -382,6 +412,7 @@ vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr; vcpu->stat.dtlb_real_miss_exits++; + set_last_exit_type(DTLB_REAL_MISS_EXITS); r = RESUME_GUEST; break; } @@ -399,11 +430,13 @@ kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid, gtlbe->word2); vcpu->stat.dtlb_virt_miss_exits++; + set_last_exit_type(DTLB_VIRT_MISS_EXITS); r = RESUME_GUEST; } else { /* Guest has mapped and accessed a page which is not * actually RAM. */ r = kvmppc_emulate_mmio(run, vcpu); + set_last_exit_type(MMIO_EXITS); } break; @@ -422,10 +455,12 @@ /* The guest didn't have a mapping for it. */ kvmppc_queue_exception(vcpu, exit_nr); vcpu->stat.itlb_real_miss_exits++; + set_last_exit_type(ITLB_REAL_MISS_EXITS); break; } vcpu->stat.itlb_virt_miss_exits++; + set_last_exit_type(ITLB_VIRT_MISS_EXITS); gfn = tlb_xlate(gtlbe, eaddr) >> PAGE_SHIFT; @@ -458,6 +493,7 @@ mtspr(SPRN_DBSR, dbsr); run->exit_reason = KVM_EXIT_DEBUG; + set_last_exit_type(DEBUG_EXITS); r = RESUME_HOST; break; } @@ -482,6 +518,7 @@ r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV); vcpu->stat.signal_exits++; + set_last_exit_type(SIGNAL_EXITS); } else { vcpu->stat.light_exits++; } @@ -495,6 +532,7 @@ break; case KVM_EXIT_INTR: vcpu->stat.signal_exits++; + set_last_exit_type(SIGNAL_EXITS); break; } } @@ -535,6 +573,8 @@ * real timebase frequency. Accordingly, it must see the state of * CCR1[TCS]. */ vcpu->arch.ccr1 = mfspr(SPRN_CCR1); + + init_exit_timing(&(vcpu->arch)); return 0; } diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -109,6 +109,18 @@ li r6, 1 slw r6, r6, r5 + +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING + /* save exit time */ +..exit_tbu_overflow_loop: + mfspr r7, SPRN_TBRU + mfspr r8, SPRN_TBRL + mfspr r9, SPRN_TBRU + cmpw r9, r7 + bne ..exit_tbu_overflow_loop + stw r8, VCPU_TIMING_EXIT_TBL(r4) + stw r9, VCPU_TIMING_EXIT_TBU(r4) +#endif /* Save the faulting instruction and all GPRs for emulation. */ andi. r7, r6, NEED_INST_MASK @@ -415,6 +427,18 @@ lwz r3, VCPU_SPRG7(r4) mtspr SPRN_SPRG7, r3 +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING + /* save enter time */ +..enter_tbu_overflow_loop: + mfspr r6, SPRN_TBRU + mfspr r7, SPRN_TBRL + mfspr r8, SPRN_TBRU + cmpw r8, r6 + bne ..enter_tbu_overflow_loop + stw r7, VCPU_TIMING_LAST_ENTER_TBL(r4) + stw r8, VCPU_TIMING_LAST_ENTER_TBU(r4) +#endif + /* Finish loading guest volatiles and jump to guest. */ lwz r3, VCPU_CTR(r4) mtctr r3 diff --git a/include/asm-powerpc/kvm_host.h b/include/asm-powerpc/kvm_host.h --- a/include/asm-powerpc/kvm_host.h +++ b/include/asm-powerpc/kvm_host.h @@ -25,6 +25,12 @@ #include #include #include + +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING +#include +#include +#include +#endif #define KVM_MAX_VCPUS 1 #define KVM_MEMORY_SLOTS 32 @@ -66,6 +72,55 @@ u32 halt_wakeup; }; +enum kvm_exit_types { + MMIO_EXITS, + DCR_EXITS, + SIGNAL_EXITS, + ITLB_REAL_MISS_EXITS, + ITLB_VIRT_MISS_EXITS, + DTLB_REAL_MISS_EXITS, + DTLB_PVMEM_MISS_EXITS, + DTLB_VIRT_MISS_EXITS, + SYSCALL_EXITS, + HCALL_EXITS, + ISI_EXITS, + DSI_EXITS, + EMULATED_INST_EXITS, + DEC_EXITS, + EXT_INTR_EXITS, + HALT_WAKEUP, + USR_PR_INST, + FP_UNAVAIL, + DEBUG_EXITS, + TIMEINGUEST, + __NUMBER_OF_KVM_EXIT_TYPES +}; + +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING +static const char* kvm_exit_names[__NUMBER_OF_KVM_EXIT_TYPES] = { + "MMIO", + "DCR", + "SIGNAL", + "ITLBREAL", + "ITLBVIRT", + "DTLBREAL", + "DTLBPV", + "DTLBVIRT", + "SYSCALL", + "HCALL", + "ISI", + "DSI", + "EMULINST", + "DEC", + "EXTINT", + "HALT", + "USR_PR_INST", + "FP_UNAVAIL", + "DEBUG", + "TIMEINGUEST" +}; +#endif + struct tlbe { u32 tid; /* Only the low 8 bits are used. */ u32 word0; @@ -75,6 +130,16 @@ struct kvm_arch { }; + +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING +/* allow access to big endian 32bit upper/lower parts and 64bit var */ +typedef union { + u64 tv64; + struct { + u32 tbu, tbl; + } tv32; +} exit_timing_t; +#endif struct kvm_vcpu_arch { /* Unmodified copy of the guest's TLB. */ @@ -139,6 +204,11 @@ u32 dbcr0; u32 dbcr1; +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING + exit_timing_t timing_exit; + exit_timing_t timing_last_enter; +#endif + u32 last_inst; u32 fault_dear; u32 fault_esr; @@ -165,4 +235,131 @@ int singlestep; }; +#ifdef CONFIG_KVM_BOOKE_EXIT_TIMING +/* helpers for instruction timing, allocated in arch/powerpc/kvm/powerpc.c */ +extern u32 last_exit_type; +extern u32 timing_count_type[__NUMBER_OF_KVM_EXIT_TYPES]; +extern u64 timing_sum_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +extern u64 timing_sum_quad_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +extern u64 timing_min_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +extern u64 timing_max_duration[__NUMBER_OF_KVM_EXIT_TYPES]; +extern u64 timing_last_exit; +extern struct sysrq_key_op trigger_print_exit_timing_op; + +static void print_exit_timing_handler(int key, struct tty_struct *tty) +{ + int i; + u64 min, max; + + printk(KERN_ERR"### start exit timing statistics ###\n"); + for (i=0; i<__NUMBER_OF_KVM_EXIT_TYPES; i++) { + if (timing_min_duration[i]==0xFFFFFFFF) + min = 0; + else + min = timing_min_duration[i]; + if (timing_max_duration[i]==0) + max = 0; + else + max = timing_max_duration[i]; + + printk(KERN_ERR"exit type %2d (%12s) count %10d min %10lld max %10lld sum %20lld sum_quad %20lld\n", + i, kvm_exit_names[i], timing_count_type[i], timing_min_duration[i], timing_max_duration[i], + timing_sum_duration[i], timing_sum_quad_duration[i]); + } + printk(KERN_ERR"please post calc: avg = sum/count; stddev = sqrt((sum_quad/count)-(sum_dur/count)������)\n"); + printk(KERN_ERR"### end exit timing statistics ###\n"); +} + +static inline void print_exit_timing(void) { + print_exit_timing_handler(0,NULL); +} + +static inline void init_exit_timing(struct kvm_vcpu_arch* vcpu_arch) +{ + int i; + + last_exit_type=0xDEAD; + for (i=0; i<__NUMBER_OF_KVM_EXIT_TYPES; i++) { + timing_count_type[i]=0; + timing_max_duration[i]=0; + timing_min_duration[i]=0xFFFFFFFF; + timing_sum_duration[i]=0; + timing_sum_quad_duration[i]=0; + } + vcpu_arch->timing_exit.tv64 = 0; + timing_last_exit = 0; + vcpu_arch->timing_last_enter.tv64 = 0; + + if (register_sysrq_key('y', &trigger_print_exit_timing_op)) + printk(KERN_ERR"%s - failed to register sysrq key\n", __func__); + +/* TODO unregister_sysrq_key(int key, struct sysrq_key_op *op_p) */ +} + +static inline void set_last_exit_type(int type) +{ + last_exit_type=type; +} + +static inline void add_exit_timing(u64 duration, int type) +{ + u64 old; + + do_div(duration, tb_ticks_per_usec); + if (unlikely(duration > 0xFFFFFFFF)) { + printk(KERN_ERR"%s - duration too big, **2 would overflow duration %lld max 4294967295 type %d exit # of type %d (tb_ticks_per_usec=%ld)\n", + __func__, duration, type, timing_count_type[type], tb_ticks_per_usec); + print_exit_timing(); + } + + + timing_count_type[type]++; + + /* sum */ + old = timing_sum_duration[type]; + timing_sum_duration[type] += duration; + if (unlikely(old > timing_sum_duration[type])) { + printk(KERN_ERR"%s - wraparound adding sum of durations old %lld new %lld type %d exit # of type %d\n", + __func__, old, timing_sum_duration[type], type, timing_count_type[type]); + print_exit_timing(); + } + + /* square sum */ + old = timing_sum_quad_duration[type]; + timing_sum_quad_duration[type] += (duration*duration); + if (unlikely(old > timing_sum_quad_duration[type])) { + printk(KERN_ERR"%s - wraparound adding sum of squared durations old %lld new %lld type %d exit # of type %d\n", + __func__, old, timing_sum_quad_duration[type], type, timing_count_type[type]); + print_exit_timing(); + } + + /* set min/max */ + if (unlikely(duration < timing_min_duration[type])) + timing_min_duration[type] = duration; + if (unlikely(duration > timing_max_duration[type])) + timing_max_duration[type] = duration; +} + +static inline void update_exit_timing(struct kvm_vcpu_arch* vcpu_arch) +{ + u64 exit = timing_last_exit; + u64 enter = vcpu_arch->timing_last_enter.tv64; + + /* save exit time to use it next exit when the related enter time is known */ + timing_last_exit = vcpu_arch->timing_exit.tv64; + + if (unlikely(last_exit_type==0xDEAD)) + return; /* skip first incomplete enter/exit cycle */ + + /* update statistics for average and standard deviation */ + add_exit_timing((enter - exit), last_exit_type); + /* enter -> timing_last_exit is time spent in guest - log this too */ + add_exit_timing((timing_last_exit - enter), TIMEINGUEST); +} +#else +static inline void init_exit_timing(struct kvm_vcpu_arch* vcpu_arch) {} +static inline void set_last_exit_type(int type) {} +static inline void update_exit_timing(struct kvm_vcpu_arch* vcpu_arch) {} +#endif /* CONFIG_KVM_BOOKE_EXIT_TIMING */ + #endif /* __POWERPC_KVM_HOST_H__ */ --------------010901090800080007020006--