PowerPC KVM patches for 2.6.29
Subsystems (3)
PATCH 1/1 kvm: ppc: directly insert shadow mappings into the hardware TLB
In reply to Hollis BlanchardFormerly, we used to maintain a per-vcpu shadow TLB and on every entry to the guest would load this array into the hardware TLB. This consumed 1280 bytes of memory (64 entries of 16 bytes plus a struct page pointer each), and also required some assembly to loop over the array on every entry.
Instead of saving a copy in memory, we can just store shadow mappings directly into the hardware TLB, accepting that the host kernel will clobber these as part of the normal 440 TLB round robin. When we do that we need less than half the memory, and we have decreased the exit handling time for all guest exits, at the cost of increased number of TLB misses because the host overwrites some guest entries.
These savings will be increased on processors with larger TLBs or which implement intelligent flush instructions like tlbivax (which will avoid the need to walk arrays in software).
In addition to that and to the code simplification, we have a greater chance of leaving other host userspace mappings in the TLB, instead of forcing all subsequent tasks to re-fault all their mappings.
arch/powerpc/include/asm/kvm_44x.h +14 -8
@@ -22,19 +22,25 @@#include <linux/kvm_host.h> -/* XXX Can't include mmu-44x.h because it redefines struct mm_context. */ #define PPC44x_TLB_SIZE 64 + +/* If the guest is expecting it, this can be as large as we like; we'd just +* need to find some way of advertising it. */ +#define KVM44x_GUEST_TLB_SIZE 64 + +struct kvmppc_44x_shadow_ref { +struct page *page; +u16 gtlb_index; +u8 writeable; +u8 tid; +};struct kvmppc_vcpu_44x {/* Unmodified copy of the guest's TLB. */ -struct kvmppc_44x_tlbe guest_tlb[PPC44x_TLB_SIZE]; -/* TLB that's actually used when the guest is running. */ -struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE]; -/* Pages which are referenced in the shadow TLB. */ -struct page *shadow_pages[PPC44x_TLB_SIZE]; +struct kvmppc_44x_tlbe guest_tlb[KVM44x_GUEST_TLB_SIZE]; -/* Track which TLB entries we've modified in the current exit. */ -u8 shadow_tlb_mod[PPC44x_TLB_SIZE]; +/* References to guest pages in the hardware TLB. */ +struct kvmppc_44x_shadow_ref shadow_refs[PPC44x_TLB_SIZE];struct kvm_vcpu vcpu; };
arch/powerpc/include/asm/kvm_ppc.h +2 -1
@@ -53,7 +53,8 @@ extern void kvmppc_emulate_dec(struct kvextern void kvmppc_emulate_dec (struct kvm_vcpu *vcpu);extern void kvmppc_mmu_map (struct kvm_vcpu *vcpu,u64 gvaddr,gpa_t gpaddr, -u64 asid,u32 flags,u32 max_bytes); +u64 asid,u32 flags,u32 max_bytes, +unsigned int gtlb_idx);extern void kvmppc_mmu_priv_switch (struct kvm_vcpu *vcpu,int usermode);extern void kvmppc_mmu_switch_pid (struct kvm_vcpu *vcpu,u32 pid);
arch/powerpc/kernel/asm-offsets.c +0 -6
@@ -357,12 +357,6 @@ int main(void)#ifdef CONFIG_KVM DEFINE (TLBE_BYTES ,sizeof (struct kvmppc_44x_tlbe )); -DEFINE (VCPU_TO_44X , offsetof(struct kvmppc_vcpu_44x , vcpu)); -DEFINE (VCPU44x_SHADOW_TLB, - offsetof(struct kvmppc_vcpu_44x , shadow_tlb)); -DEFINE (VCPU44x_SHADOW_MOD, - offsetof(struct kvmppc_vcpu_44x , shadow_tlb_mod)); - DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
arch/powerpc/kvm/44x.c +8 -11
@@ -96,21 +96,14 @@ void kvmppc_core_load_guest_debugstate(svoid kvmppc_core_vcpu_load (struct kvm_vcpu *vcpu,int cpu) { -int i; - -/* Mark every guest entry in the shadow TLB entry modified, so that they -* will all be reloaded on the next vcpu run (instead of being -* demand-faulted). */ -for (i =0 ; i <= tlb_44x_hwater; i++) -kvmppc_tlbe_set_modified (vcpu, i); }void kvmppc_core_vcpu_put (struct kvm_vcpu *vcpu) { -/* Don't leave guest TLB entries resident when being de-scheduled. */ -/* XXX It would be nice to differentiate between heavyweight exit and -* sched_out here, since we could avoid the TLB flush for heavyweight -* exits. */ +/* XXX Since every guest uses TS=1 TID=0/1 mappings, we can't leave any TLB +* entries around when we're descheduled, so we must completely flush the +* TLB of all guest mappings. On the other hand, if there is only one +* guest, this flush is completely unnecessary. */ _tlbia (); }
@@ -130,6 +123,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vc {struct kvmppc_vcpu_44x *vcpu_44x =to_44x (vcpu);struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0 ]; +int i; tlbe->tid =0 ; tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
@@ -147,6 +141,9 @@ int kvmppc_core_vcpu_setup(struct kvm_vc* real timebase frequency. Accordingly, it must see the state of * CCR1[TCS]. */ vcpu->arch.ccr1 =mfspr (SPRN_CCR1 ); + +for (i =0 ; i <ARRAY_SIZE (vcpu_44x->shadow_refs); i++) + vcpu_44x->shadow_refs[i].gtlb_index =-1 ;return 0 ; }
arch/powerpc/kvm/44x_tlb.c +123 -129
410 lines not on this page · raw message
arch/powerpc/kvm/44x_tlb.h +2 -5
@@ -25,11 +25,8 @@extern int kvmppc_44x_tlb_index (struct kvm_vcpu *vcpu,gva_t eaddr,unsigned int pid,unsigned int as); -extern struct kvmppc_44x_tlbe *kvmppc_44x_dtlb_search (struct kvm_vcpu *vcpu, -gva_t eaddr); -extern struct kvmppc_44x_tlbe *kvmppc_44x_itlb_search (struct kvm_vcpu *vcpu, -gva_t eaddr); -extern void kvmppc_tlbe_set_modified (struct kvm_vcpu *vcpu,unsigned int i); +extern int kvmppc_44x_dtlb_index (struct kvm_vcpu *vcpu,gva_t eaddr); +extern int kvmppc_44x_itlb_index (struct kvm_vcpu *vcpu,gva_t eaddr);extern int kvmppc_44x_emul_tlbsx (struct kvm_vcpu *vcpu,u8 rt,u8 ra,u8 rb,u8 rc);
arch/powerpc/kvm/booke.c +18 -12
@@ -24,10 +24,12 @@#include <linux/module.h> #include <linux/vmalloc.h> #include <linux/fs.h> +#include <asm/cputable.h> #include <asm/uaccess.h> #include <asm/kvm_ppc.h> #include <asm/cacheflush.h> +#include <asm/kvm_44x.h> #include "booke.h" #include "44x_tlb.h"
@@ -207,10 +209,6 @@ int kvmppc_handle_exit(struct kvm_run *r* handled this interrupt the moment we enabled interrupts. * Now we just offer it a chance to reschedule the guest. */ -/* XXX At this point the TLB still holds our shadow TLB, so if -* we do reschedule the host will fault over it. Perhaps we -* should politely restore the host's entries to minimize -* misses before ceding control. */ vcpu->stat.dec_exits++;if (need_resched ())cond_resched ();
@@ -281,14 +279,17 @@ int kvmppc_handle_exit(struct kvm_run *r r =RESUME_GUEST ;break ; +/* XXX move to a 440-specific file. */ case BOOKE_INTERRUPT_DTLB_MISS : { -struct kvmppc_44x_tlbe *gtlbe; -unsigned long eaddr = vcpu->arch.fault_dear; +struct kvmppc_vcpu_44x *vcpu_44x =to_44x (vcpu); +struct kvmppc_44x_tlbe *gtlbe; +unsigned long eaddr = vcpu->arch.fault_dear; +int gtlb_index;gfn_t gfn;/* Check the guest TLB. */ - gtlbe =kvmppc_44x_dtlb_search (vcpu, eaddr); -if (!gtlbe) { + gtlb_index =kvmppc_44x_dtlb_index (vcpu, eaddr); +if (gtlb_index <0 ) {/* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_DTLB_MISS ); vcpu->arch.dear = vcpu->arch.fault_dear;
@@ -298,6 +299,7 @@ int kvmppc_handle_exit(struct kvm_run *rbreak ; } + gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; vcpu->arch.paddr_accessed =tlb_xlate (gtlbe, eaddr); gfn = vcpu->arch.paddr_accessed >>PAGE_SHIFT ;
@@ -309,7 +311,7 @@ int kvmppc_handle_exit(struct kvm_run *r* Either way, we need to satisfy the fault without * invoking the guest. */ kvmppc_mmu_map (vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, - gtlbe->word2,get_tlb_bytes (gtlbe)); + gtlbe->word2,get_tlb_bytes (gtlbe), gtlb_index); vcpu->stat.dtlb_virt_miss_exits++; r =RESUME_GUEST ; }else {
@@ -322,17 +324,20 @@ int kvmppc_handle_exit(struct kvm_run *rbreak ; } +/* XXX move to a 440-specific file. */ case BOOKE_INTERRUPT_ITLB_MISS : { +struct kvmppc_vcpu_44x *vcpu_44x =to_44x (vcpu);struct kvmppc_44x_tlbe *gtlbe;unsigned long eaddr = vcpu->arch.pc;gpa_t gpaddr;gfn_t gfn; +int gtlb_index; r =RESUME_GUEST ;/* Check the guest TLB. */ - gtlbe =kvmppc_44x_itlb_search (vcpu, eaddr); -if (!gtlbe) { + gtlb_index =kvmppc_44x_itlb_index (vcpu, eaddr); +if (gtlb_index <0 ) {/* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_ITLB_MISS ); vcpu->stat.itlb_real_miss_exits++;
@@ -341,6 +346,7 @@ int kvmppc_handle_exit(struct kvm_run *r vcpu->stat.itlb_virt_miss_exits++; + gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; gpaddr =tlb_xlate (gtlbe, eaddr); gfn = gpaddr >>PAGE_SHIFT ;
@@ -352,7 +358,7 @@ int kvmppc_handle_exit(struct kvm_run *r* Either way, we need to satisfy the fault without * invoking the guest. */ kvmppc_mmu_map (vcpu, eaddr, gpaddr, gtlbe->tid, - gtlbe->word2,get_tlb_bytes (gtlbe)); + gtlbe->word2,get_tlb_bytes (gtlbe), gtlb_index); }else {/* Guest mapped and leaped at non-RAM! */ kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_MACHINE_CHECK );
arch/powerpc/kvm/booke_interrupts.S +0 -48
54 lines not on this page · raw message
PATCH 1/1 powerpc/44x: declare tlb_44x_index for use in C code
In reply to Hollis BlanchardKVM currently ignores the host's round robin TLB eviction selection, instead maintaining its own TLB state and its own round robin index. However, by participating in the normal 44x TLB selection, we can drop the alternate TLB processing in KVM. This results in a significant performance improvement, since that processing currently must be done on *every* guest exit.
Accordingly, KVM needs to be able to access and increment tlb_44x_index. (KVM on 440 cannot be a module, so there is no need to export this symbol.)
arch/powerpc/include/asm/mmu-44x.h +1 -0
@@ -56,6 +56,7 @@ #ifndef __ASSEMBLY__ extern unsigned int tlb_44x_hwater; +extern unsigned int tlb_44x_index; typedef struct { unsigned long id;
PATCH 1/1 kvm: ppc: save and restore guest mappings on context switch
In reply to Hollis BlanchardStore shadow TLB entries in memory, but only use it on host context switch (instead of every guest entry). This improves performance for most workloads on 440 by reducing the guest TLB miss rate.
arch/powerpc/include/asm/kvm_44x.h +6 -0
@@ -42,6 +42,10 @@ struct kvmppc_vcpu_44x {/* References to guest pages in the hardware TLB. */ struct kvmppc_44x_shadow_ref shadow_refs[PPC44x_TLB_SIZE]; +/* State of the shadow TLB at guest context switch time. */ +struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE]; +u8 shadow_tlb_mod[PPC44x_TLB_SIZE]; +struct kvm_vcpu vcpu; };
@@ -51,5 +55,7 @@ static inline struct kvmppc_vcpu_44x *to }void kvmppc_set_pid (struct kvm_vcpu *vcpu,u32 new_pid); +void kvmppc_44x_tlb_put (struct kvm_vcpu *vcpu); +void kvmppc_44x_tlb_load (struct kvm_vcpu *vcpu);#endif /* __ASM_44X_H__ */
arch/powerpc/kvm/44x.c +2 -5
@@ -96,15 +96,12 @@ void kvmppc_core_load_guest_debugstate(svoid kvmppc_core_vcpu_load (struct kvm_vcpu *vcpu,int cpu) { +kvmppc_44x_tlb_load (vcpu); }void kvmppc_core_vcpu_put (struct kvm_vcpu *vcpu) { -/* XXX Since every guest uses TS=1 TID=0/1 mappings, we can't leave any TLB -* entries around when we're descheduled, so we must completely flush the -* TLB of all guest mappings. On the other hand, if there is only one -* guest, this flush is completely unnecessary. */ -_tlbia (); +kvmppc_44x_tlb_put (vcpu); }int kvmppc_core_check_processor_compat (void )
arch/powerpc/kvm/44x_tlb.c +58 -0
76 lines not on this page · raw message
PATCH 1/1 kvm: ppc: support large host pages
In reply to Hollis BlanchardKVM on 440 has always been able to handle large guest mappings with 4K host pages -- we must, since the guest kernel uses 256MB mappings.
This patch makes KVM work when the host has large pages too (tested with 64K).
arch/powerpc/include/asm/kvm_ppc.h +2 -2
@@ -52,8 +52,8 @@ extern int kvmppc_emulate_mmio(struct kvextern int kvmppc_emulate_mmio (struct kvm_run *run,struct kvm_vcpu *vcpu);extern void kvmppc_emulate_dec (struct kvm_vcpu *vcpu); -extern void kvmppc_mmu_map (struct kvm_vcpu *vcpu,u64 gvaddr,gfn_t gfn, -u64 asid,u32 flags); +extern void kvmppc_mmu_map (struct kvm_vcpu *vcpu,u64 gvaddr,gpa_t gpaddr, +u64 asid,u32 flags,u32 max_bytes);extern void kvmppc_mmu_priv_switch (struct kvm_vcpu *vcpu,int usermode);extern void kvmppc_mmu_switch_pid (struct kvm_vcpu *vcpu,u32 pid);
arch/powerpc/kvm/44x_tlb.c +55 -16
117 lines not on this page · raw message
arch/powerpc/kvm/booke.c +7 -5
@@ -308,8 +308,8 @@ int kvmppc_handle_exit(struct kvm_run *r* b) the guest used a large mapping which we're faking * Either way, we need to satisfy the fault without * invoking the guest. */ -kvmppc_mmu_map (vcpu, eaddr, gfn, gtlbe->tid, - gtlbe->word2); +kvmppc_mmu_map (vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, + gtlbe->word2,get_tlb_bytes (gtlbe)); vcpu->stat.dtlb_virt_miss_exits++; r =RESUME_GUEST ; }else {
@@ -325,6 +325,7 @@ int kvmppc_handle_exit(struct kvm_run *rcase BOOKE_INTERRUPT_ITLB_MISS : {struct kvmppc_44x_tlbe *gtlbe;unsigned long eaddr = vcpu->arch.pc; +gpa_t gpaddr;gfn_t gfn; r =RESUME_GUEST ;
@@ -340,7 +341,8 @@ int kvmppc_handle_exit(struct kvm_run *r vcpu->stat.itlb_virt_miss_exits++; - gfn =tlb_xlate (gtlbe, eaddr) >>PAGE_SHIFT ; + gpaddr =tlb_xlate (gtlbe, eaddr); + gfn = gpaddr >>PAGE_SHIFT ;if (kvm_is_visible_gfn (vcpu->kvm, gfn)) {/* The guest TLB had a mapping, but the shadow TLB
@@ -349,8 +351,8 @@ int kvmppc_handle_exit(struct kvm_run *r* b) the guest used a large mapping which we're faking * Either way, we need to satisfy the fault without * invoking the guest. */ -kvmppc_mmu_map (vcpu, eaddr, gfn, gtlbe->tid, - gtlbe->word2); +kvmppc_mmu_map (vcpu, eaddr, gpaddr, gtlbe->tid, + gtlbe->word2,get_tlb_bytes (gtlbe)); }else {/* Guest mapped and leaped at non-RAM! */ kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_MACHINE_CHECK );
PATCH 1/1 kvm: ppc: mostly cosmetic updates to the exit timing accounting code
In reply to Hollis BlanchardThe only significant changes were to kvmppc_exit_timing_write() and kvmppc_exit_timing_show(), both of which were dramatically simplified.
arch/powerpc/include/asm/kvm_host.h +3 -5
@@ -102,9 +102,8 @@ enum kvm_exit_types {__NUMBER_OF_KVM_EXIT_TYPES }; -#ifdef CONFIG_KVM_EXIT_TIMING/* allow access to big endian 32bit upper/lower parts and 64bit var */ -struct exit_timing { +struct kvmppc_exit_timing { union { u64 tv64; struct {
@@ -112,7 +111,6 @@ struct exit_timing { } tv32; }; }; -#endif struct kvm_arch { };
@@ -174,8 +172,8 @@ struct kvm_vcpu_arch {u32 dbcr1;#ifdef CONFIG_KVM_EXIT_TIMING -struct exit_timing timing_exit; -struct exit_timing timing_last_enter; +struct kvmppc_exit_timing timing_exit; +struct kvmppc_exit_timing timing_last_enter;u32 last_exit_type;u32 timing_count_type[__NUMBER_OF_KVM_EXIT_TYPES];u64 timing_sum_duration[__NUMBER_OF_KVM_EXIT_TYPES];
arch/powerpc/kvm/44x_emulate.c +2 -2
@@ -132,7 +132,7 @@ int kvmppc_core_emulate_op(struct kvm_ru run->dcr.is_write =0 ; vcpu->arch.io_gpr = rt; vcpu->arch.dcr_needed =1 ; -account_exit (vcpu,DCR_EXITS ); +kvmppc_account_exit (vcpu,DCR_EXITS ); emulated =EMULATE_DO_DCR ; }
@@ -152,7 +152,7 @@ int kvmppc_core_emulate_op(struct kvm_ru run->dcr.data = vcpu->arch.gpr[rs]; run->dcr.is_write =1 ; vcpu->arch.dcr_needed =1 ; -account_exit (vcpu,DCR_EXITS ); +kvmppc_account_exit (vcpu,DCR_EXITS ); emulated =EMULATE_DO_DCR ; }
arch/powerpc/kvm/booke.c +15 -15
@@ -202,7 +202,7 @@ int kvmppc_handle_exit(struct kvm_run *rbreak ;case BOOKE_INTERRUPT_EXTERNAL : -account_exit (vcpu,EXT_INTR_EXITS ); +kvmppc_account_exit (vcpu,EXT_INTR_EXITS );if (need_resched ())cond_resched (); r =RESUME_GUEST ;
@@ -212,7 +212,7 @@ int kvmppc_handle_exit(struct kvm_run *r/* Since we switched IVPR back to the host's value, the host * handled this interrupt the moment we enabled interrupts. * Now we just offer it a chance to reschedule the guest. */ -account_exit (vcpu,DEC_EXITS ); +kvmppc_account_exit (vcpu,DEC_EXITS );if (need_resched ())cond_resched (); r =RESUME_GUEST ;
@@ -225,7 +225,7 @@ int kvmppc_handle_exit(struct kvm_run *r vcpu->arch.esr = vcpu->arch.fault_esr;kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_PROGRAM ); r =RESUME_GUEST ; -account_exit (vcpu,USR_PR_INST ); +kvmppc_account_exit (vcpu,USR_PR_INST );break ; }
@@ -233,7 +233,7 @@ int kvmppc_handle_exit(struct kvm_run *rswitch (er) {case EMULATE_DONE :/* don't overwrite subtypes, just account kvm_stats */ -account_exit_stat (vcpu,EMULATED_INST_EXITS ); +kvmppc_account_exit_stat (vcpu,EMULATED_INST_EXITS );/* Future optimization: only reload non-volatiles if * they were actually modified by emulation. */ r =RESUME_GUEST_NV ;
@@ -259,7 +259,7 @@ int kvmppc_handle_exit(struct kvm_run *rcase BOOKE_INTERRUPT_FP_UNAVAIL :kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_FP_UNAVAIL ); -account_exit (vcpu,FP_UNAVAIL ); +kvmppc_account_exit (vcpu,FP_UNAVAIL ); r =RESUME_GUEST ;break ;
@@ -267,20 +267,20 @@ int kvmppc_handle_exit(struct kvm_run *r vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr;kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_DATA_STORAGE ); -account_exit (vcpu,DSI_EXITS ); +kvmppc_account_exit (vcpu,DSI_EXITS ); r =RESUME_GUEST ;break ;case BOOKE_INTERRUPT_INST_STORAGE : vcpu->arch.esr = vcpu->arch.fault_esr;kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_INST_STORAGE ); -account_exit (vcpu,ISI_EXITS ); +kvmppc_account_exit (vcpu,ISI_EXITS ); r =RESUME_GUEST ;break ;case BOOKE_INTERRUPT_SYSCALL :kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_SYSCALL ); -account_exit (vcpu,SYSCALL_EXITS ); +kvmppc_account_exit (vcpu,SYSCALL_EXITS ); r =RESUME_GUEST ;break ;
@@ -299,7 +299,7 @@ int kvmppc_handle_exit(struct kvm_run *rkvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_DTLB_MISS ); vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr; -account_exit (vcpu,DTLB_REAL_MISS_EXITS ); +kvmppc_account_exit (vcpu,DTLB_REAL_MISS_EXITS ); r =RESUME_GUEST ;break ; }
@@ -317,13 +317,13 @@ int kvmppc_handle_exit(struct kvm_run *r* invoking the guest. */ kvmppc_mmu_map (vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, gtlbe->word2,get_tlb_bytes (gtlbe), gtlb_index); -account_exit (vcpu,DTLB_VIRT_MISS_EXITS ); +kvmppc_account_exit (vcpu,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); -account_exit (vcpu,MMIO_EXITS ); +kvmppc_account_exit (vcpu,MMIO_EXITS ); }break ;
@@ -345,11 +345,11 @@ int kvmppc_handle_exit(struct kvm_run *rif (gtlb_index <0 ) {/* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_ITLB_MISS ); -account_exit (vcpu,ITLB_REAL_MISS_EXITS ); +kvmppc_account_exit (vcpu,ITLB_REAL_MISS_EXITS );break ; } -account_exit (vcpu,ITLB_VIRT_MISS_EXITS ); +kvmppc_account_exit (vcpu,ITLB_VIRT_MISS_EXITS ); gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; gpaddr =tlb_xlate (gtlbe, eaddr);
@@ -383,7 +383,7 @@ int kvmppc_handle_exit(struct kvm_run *rmtspr (SPRN_DBSR , dbsr); run->exit_reason =KVM_EXIT_DEBUG ; -account_exit (vcpu,DEBUG_EXITS ); +kvmppc_account_exit (vcpu,DEBUG_EXITS ); r =RESUME_HOST ;break ; }
@@ -404,7 +404,7 @@ int kvmppc_handle_exit(struct kvm_run *rif (signal_pending (current)) { run->exit_reason =KVM_EXIT_INTR ; r = (-EINTR <<2 ) |RESUME_HOST | (r &RESUME_FLAG_NV ); -account_exit (vcpu,SIGNAL_EXITS ); +kvmppc_account_exit (vcpu,SIGNAL_EXITS ); } }
arch/powerpc/kvm/timing.c +43 -66
175 lines not on this page · raw message
arch/powerpc/kvm/timing.h +3 -3
@@ -45,7 +45,7 @@ static inline void kvmppc_set_exit_type(#endif /* CONFIG_KVM_EXIT_TIMING */ /* account the exit in kvm_stats */ -static inline void account_exit_stat (struct kvm_vcpu *vcpu,int type) +static inline void kvmppc_account_exit_stat (struct kvm_vcpu *vcpu,int type) {/* type has to be known at build time for optimization */ BUILD_BUG_ON (__builtin_constant_p (type));
@@ -93,10 +93,10 @@ static inline void account_exit_stat(str }/* wrapper to set exit time and account for it in kvm_stats */ -static inline void account_exit (struct kvm_vcpu *vcpu,int type) +static inline void kvmppc_account_exit (struct kvm_vcpu *vcpu,int type) {kvmppc_set_exit_type (vcpu, type); -account_exit_stat (vcpu, type); +kvmppc_account_exit_stat (vcpu, type); }#endif /* __POWERPC_KVM_EXITTIMING_H__ */
PATCH 1/1 PowerPC KVM patches for 2.6.29
Hi Avi, here's the latest batch of PowerPC kernel patches.
The first set dramatically improve performance. Most importantly, we add support for large host pages with KVM (i.e. PAGE_SHIFT > 12). (Large *guest* pages have already been supported since day 1, since the guest kernel uses them for the linear map.) Followup patches further improve performance by changing how we manage the shadow TLB.
The last two add some accounting code to easily discover performance bottlenecks. This is especially important since the 440 core lacks performance monitoring hardware.
These patches, in conjunction with 64KB pages on guest and host, get us to 96% of native performance for compute-bound workloads, which I'm pretty happy with. See http://kvm.qumranet.com/kvmwiki/PowerPC_Exittimings for more details (those statistics were gathered using the accounting patches).
These have been tested pretty thoroughly for several weeks. Please apply for 2.6.29. Thanks!
-Hollis
PATCH 1/1 kvm: ppc: Implement in-kernel exit timing statistics
Existing KVM statistics are either just counters (kvm_stat) reported for KVM generally or trace based aproaches like kvm_trace.
For KVM on powerpc we had the need to track the timings of the different exit types. While this could be achieved parsing data created with a kvm_trace extension this adds too much overhead (at least on embedded PowerPC) slowing down the workloads we wanted to measure.
Therefore this patch adds a in-kernel exit timing statistic to the powerpc kvm code. These statistic is available per vm&vcpu under the kvm debugfs directory. As this statistic is low, but still some overhead it can be enabled via a .config entry and should be off by default.
Since this patch touched all powerpc kvm_stat code anyway this code is now merged and simplified together with the exit timing statistic code (still working with exit timing disabled in .config).
arch/powerpc/include/asm/kvm_host.h +56 -0
@@ -71,6 +71,49 @@ struct kvmppc_44x_tlbe {u32 word2; }; +enum kvm_exit_types { +MMIO_EXITS , +DCR_EXITS , +SIGNAL_EXITS , +ITLB_REAL_MISS_EXITS , +ITLB_VIRT_MISS_EXITS , +DTLB_REAL_MISS_EXITS , +DTLB_VIRT_MISS_EXITS , +SYSCALL_EXITS , +ISI_EXITS , +DSI_EXITS , +EMULATED_INST_EXITS , +EMULATED_MTMSRWE_EXITS , +EMULATED_WRTEE_EXITS , +EMULATED_MTSPR_EXITS , +EMULATED_MFSPR_EXITS , +EMULATED_MTMSR_EXITS , +EMULATED_MFMSR_EXITS , +EMULATED_TLBSX_EXITS , +EMULATED_TLBWE_EXITS , +EMULATED_RFI_EXITS , +DEC_EXITS , +EXT_INTR_EXITS , +HALT_WAKEUP , +USR_PR_INST , +FP_UNAVAIL , +DEBUG_EXITS , +TIMEINGUEST , + __NUMBER_OF_KVM_EXIT_TYPES +}; + +#ifdef CONFIG_KVM_EXIT_TIMING +/* allow access to big endian 32bit upper/lower parts and 64bit var */ +struct exit_timing { +union { +u64 tv64; +struct { +u32 tbu, tbl; + } tv32; + }; +}; +#endif +struct kvm_arch { };
@@ -130,6 +173,19 @@ struct kvm_vcpu_arch {u32 dbcr0;u32 dbcr1; +#ifdef CONFIG_KVM_EXIT_TIMING +struct exit_timing timing_exit; +struct exit_timing timing_last_enter; +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 dentry *debugfs_exit_timing; +#endif +u32 last_inst;ulong fault_dear;ulong fault_esr;
arch/powerpc/kernel/asm-offsets.c +11 -0
@@ -381,5 +381,16 @@ int main(void)DEFINE (PTE_SHIFT ,PTE_SHIFT );#endif +#ifdef CONFIG_KVM_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 ; }
arch/powerpc/kvm/44x_emulate.c +10 -1
@@ -22,6 +22,7 @@#include <asm/dcr-regs.h> #include <asm/disassemble.h> #include <asm/kvm_44x.h> +#include "timing.h" #include "booke.h" #include "44x_tlb.h"
@@ -58,11 +59,11 @@ int kvmppc_core_emulate_op(struct kvm_ruint ws;switch (get_op (inst)) { -case OP_RFI :switch (get_xop (inst)) {case XOP_RFI :kvmppc_emul_rfi (vcpu); +kvmppc_set_exit_type (vcpu,EMULATED_RFI_EXITS ); *advance =0 ;break ;
@@ -78,10 +79,12 @@ int kvmppc_core_emulate_op(struct kvm_rucase XOP_MFMSR : rt =get_rt (inst); vcpu->arch.gpr[rt] = vcpu->arch.msr; +kvmppc_set_exit_type (vcpu,EMULATED_MFMSR_EXITS );break ;case XOP_MTMSR : rs =get_rs (inst); +kvmppc_set_exit_type (vcpu,EMULATED_MTMSR_EXITS );kvmppc_set_msr (vcpu, vcpu->arch.gpr[rs]);break ;
@@ -89,11 +92,13 @@ int kvmppc_core_emulate_op(struct kvm_ru rs =get_rs (inst); vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE ) | (vcpu->arch.gpr[rs] &MSR_EE ); +kvmppc_set_exit_type (vcpu,EMULATED_WRTEE_EXITS );break ;case XOP_WRTEEI : vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE ) | (inst &MSR_EE ); +kvmppc_set_exit_type (vcpu,EMULATED_WRTEE_EXITS );break ;case XOP_MFDCR :
@@ -127,6 +132,7 @@ int kvmppc_core_emulate_op(struct kvm_ru run->dcr.is_write =0 ; vcpu->arch.io_gpr = rt; vcpu->arch.dcr_needed =1 ; +account_exit (vcpu,DCR_EXITS ); emulated =EMULATE_DO_DCR ; }
@@ -146,6 +152,7 @@ int kvmppc_core_emulate_op(struct kvm_ru run->dcr.data = vcpu->arch.gpr[rs]; run->dcr.is_write =1 ; vcpu->arch.dcr_needed =1 ; +account_exit (vcpu,DCR_EXITS ); emulated =EMULATE_DO_DCR ; }
@@ -276,6 +283,7 @@ int kvmppc_core_emulate_mtspr(struct kvmreturn EMULATE_FAIL ; } +kvmppc_set_exit_type (vcpu,EMULATED_MTSPR_EXITS );return EMULATE_DONE ; }
@@ -357,6 +365,7 @@ int kvmppc_core_emulate_mfspr(struct kvmreturn EMULATE_FAIL ; } +kvmppc_set_exit_type (vcpu,EMULATED_MFSPR_EXITS );return EMULATE_DONE ; }
arch/powerpc/kvm/44x_tlb.c +3 -0
@@ -27,6 +27,7 @@#include <asm/mmu-44x.h> #include <asm/kvm_ppc.h> #include <asm/kvm_44x.h> +#include "timing.h" #include "44x_tlb.h"
@@ -470,6 +471,7 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpKVMTRACE_5D (GTLB_WRITE , vcpu, gtlb_index, tlbe->tid, tlbe->word0, tlbe->word1, tlbe->word2, handler); +kvmppc_set_exit_type (vcpu,EMULATED_TLBWE_EXITS );return EMULATE_DONE ; }
@@ -493,5 +495,6 @@ int kvmppc_44x_emul_tlbsx(struct kvm_vcp } vcpu->arch.gpr[rt] = gtlb_index; +kvmppc_set_exit_type (vcpu,EMULATED_TLBSX_EXITS );return EMULATE_DONE ; }
arch/powerpc/kvm/Kconfig +11 -0
@@ -32,6 +32,17 @@ config KVM_440 If unsure, say N. +config KVM_EXIT_TIMING + bool "Detailed exit timing" + depends on KVM + ---help--- + Calculate elapsed time for every exit/enter cycle. A per-vcpu + report is available in debugfs kvm/vm#_vcpu#_timing. + The overhead is relatively small, however it is not recommended for + production environments. + + If unsure, say N. + config KVM_TRACE bool "KVM trace support" depends on KVM && MARKERS && SYSFS
arch/powerpc/kvm/Makefile +1 -0
@@ -9,6 +9,7 @@ common-objs-$(CONFIG_KVM_TRACE) += $(ad common-objs-$(CONFIG_KVM_TRACE) += $(addprefix ../../../virt/kvm/, kvm_trace.o) kvm-objs := $(common-objs-y) powerpc.o emulate.o +obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o obj-$(CONFIG_KVM) += kvm.o AFLAGS_booke_interrupts.o := -I$(obj)
arch/powerpc/kvm/booke.c +22 -14
@@ -28,6 +28,7 @@#include <asm/cputable.h> #include <asm/uaccess.h> #include <asm/kvm_ppc.h> +#include "timing.h" #include <asm/cacheflush.h> #include <asm/kvm_44x.h>
@@ -185,6 +186,9 @@ int kvmppc_handle_exit(struct kvm_run *renum emulation_result er;int r =RESUME_HOST ; +/* update before a new last_exit_type is rewritten */ +kvmppc_update_timing_stats (vcpu); +local_irq_enable (); run->exit_reason =KVM_EXIT_UNKNOWN ;
@@ -198,7 +202,7 @@ int kvmppc_handle_exit(struct kvm_run *rbreak ;case BOOKE_INTERRUPT_EXTERNAL : - vcpu->stat.ext_intr_exits++; +account_exit (vcpu,EXT_INTR_EXITS );if (need_resched ())cond_resched (); r =RESUME_GUEST ;
@@ -208,8 +212,7 @@ int kvmppc_handle_exit(struct kvm_run *r/* Since we switched IVPR back to the host's value, the host * handled this interrupt the moment we enabled interrupts. * Now we just offer it a chance to reschedule the guest. */ - - vcpu->stat.dec_exits++; +account_exit (vcpu,DEC_EXITS );if (need_resched ())cond_resched (); r =RESUME_GUEST ;
@@ -222,20 +225,21 @@ int kvmppc_handle_exit(struct kvm_run *r vcpu->arch.esr = vcpu->arch.fault_esr;kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_PROGRAM ); r =RESUME_GUEST ; +account_exit (vcpu,USR_PR_INST );break ; } er =kvmppc_emulate_instruction (run, vcpu);switch (er) {case EMULATE_DONE : +/* don't overwrite subtypes, just account kvm_stats */ +account_exit_stat (vcpu,EMULATED_INST_EXITS );/* Future optimization: only reload non-volatiles if * they were actually modified by emulation. */ - vcpu->stat.emulated_inst_exits++; r =RESUME_GUEST_NV ;break ;case EMULATE_DO_DCR : run->exit_reason =KVM_EXIT_DCR ; - vcpu->stat.dcr_exits++; r =RESUME_HOST ;break ;case EMULATE_FAIL :
@@ -255,6 +259,7 @@ int kvmppc_handle_exit(struct kvm_run *rcase BOOKE_INTERRUPT_FP_UNAVAIL :kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_FP_UNAVAIL ); +account_exit (vcpu,FP_UNAVAIL ); r =RESUME_GUEST ;break ;
@@ -262,20 +267,20 @@ int kvmppc_handle_exit(struct kvm_run *r vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr;kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_DATA_STORAGE ); - vcpu->stat.dsi_exits++; +account_exit (vcpu,DSI_EXITS ); r =RESUME_GUEST ;break ;case BOOKE_INTERRUPT_INST_STORAGE : vcpu->arch.esr = vcpu->arch.fault_esr;kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_INST_STORAGE ); - vcpu->stat.isi_exits++; +account_exit (vcpu,ISI_EXITS ); r =RESUME_GUEST ;break ;case BOOKE_INTERRUPT_SYSCALL :kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_SYSCALL ); - vcpu->stat.syscall_exits++; +account_exit (vcpu,SYSCALL_EXITS ); r =RESUME_GUEST ;break ;
@@ -294,7 +299,7 @@ int kvmppc_handle_exit(struct kvm_run *rkvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_DTLB_MISS ); vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr; - vcpu->stat.dtlb_real_miss_exits++; +account_exit (vcpu,DTLB_REAL_MISS_EXITS ); r =RESUME_GUEST ;break ; }
@@ -312,13 +317,13 @@ int kvmppc_handle_exit(struct kvm_run *r* invoking the guest. */ kvmppc_mmu_map (vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, gtlbe->word2,get_tlb_bytes (gtlbe), gtlb_index); - vcpu->stat.dtlb_virt_miss_exits++; +account_exit (vcpu,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); - vcpu->stat.mmio_exits++; +account_exit (vcpu,MMIO_EXITS ); }break ;
@@ -340,11 +345,11 @@ int kvmppc_handle_exit(struct kvm_run *rif (gtlb_index <0 ) {/* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio (vcpu,BOOKE_IRQPRIO_ITLB_MISS ); - vcpu->stat.itlb_real_miss_exits++; +account_exit (vcpu,ITLB_REAL_MISS_EXITS );break ; } - vcpu->stat.itlb_virt_miss_exits++; +account_exit (vcpu,ITLB_VIRT_MISS_EXITS ); gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; gpaddr =tlb_xlate (gtlbe, eaddr);
@@ -378,6 +383,7 @@ int kvmppc_handle_exit(struct kvm_run *rmtspr (SPRN_DBSR , dbsr); run->exit_reason =KVM_EXIT_DEBUG ; +account_exit (vcpu,DEBUG_EXITS ); r =RESUME_HOST ;break ; }
@@ -398,7 +404,7 @@ int kvmppc_handle_exit(struct kvm_run *rif (signal_pending (current)) { run->exit_reason =KVM_EXIT_INTR ; r = (-EINTR <<2 ) |RESUME_HOST | (r &RESUME_FLAG_NV ); - vcpu->stat.signal_exits++; +account_exit (vcpu,SIGNAL_EXITS ); } }
@@ -417,6 +423,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu/* Eye-catching number so we know if the guest takes an interrupt * before it's programmed its own IVPR. */ vcpu->arch.ivpr =0x55550000 ; + +kvmppc_init_timing_stats (vcpu);return kvmppc_core_vcpu_setup (vcpu); }
arch/powerpc/kvm/booke.h +4 -1
@@ -22,6 +22,7 @@#include <linux/types.h> #include <linux/kvm_host.h> +#include "timing.h" /* interrupt priortity ordering */ #define BOOKE_IRQPRIO_DATA_STORAGE 0
@@ -50,8 +51,10 @@ static inline void kvmppc_set_msr(struct vcpu->arch.msr = new_msr; -if (vcpu->arch.msr &MSR_WE ) +if (vcpu->arch.msr &MSR_WE ) {kvm_vcpu_block (vcpu); +kvmppc_set_exit_type (vcpu,EMULATED_MTMSRWE_EXITS ); + }; }#endif /* __KVM_BOOKE_H__ */
arch/powerpc/kvm/booke_interrupts.S +24 -0
@@ -106,6 +106,18 @@ _GLOBAL(kvmppc_resume_host) li r6, 1 slw r6, r6, r5 + +#ifdef CONFIG_KVM_EXIT_TIMING + /* save exit time */ +1: + mfspr r7, SPRN_TBRU + mfspr r8, SPRN_TBRL + mfspr r9, SPRN_TBRU + cmpw r9, r7 + bne 1b + 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
@@ -375,6 +387,18 @@ lightweight_exit: lwz r3, VCPU_SPRG7(r4) mtspr SPRN_SPRG7, r3 +#ifdef CONFIG_KVM_EXIT_TIMING + /* save enter time */ +1: + mfspr r6, SPRN_TBRU + mfspr r7, SPRN_TBRL + mfspr r8, SPRN_TBRU + cmpw r8, r6 + bne 1b + 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
arch/powerpc/kvm/emulate.c +4 -0
@@ -28,6 +28,7 @@#include <asm/byteorder.h> #include <asm/kvm_ppc.h> #include <asm/disassemble.h> +#include "timing.h" void kvmppc_emulate_dec (struct kvm_vcpu *vcpu) {
@@ -72,6 +73,9 @@ int kvmppc_emulate_instruction(struct kvint sprn;enum emulation_result emulated =EMULATE_DONE ;int advance =1 ; + +/* this default type might be overwritten by subcategories */ +kvmppc_set_exit_type (vcpu,EMULATED_INST_EXITS );switch (get_op (inst)) {case 3 :/* trap */
arch/powerpc/kvm/powerpc.c +6 -2
@@ -28,7 +28,7 @@#include <asm/uaccess.h> #include <asm/kvm_ppc.h> #include <asm/tlbflush.h> - +#include "timing.h" gfn_t unalias_gfn (struct kvm *kvm,gfn_t gfn) {
@@ -170,11 +170,15 @@ void kvm_arch_flush_shadow(struct kvm *kstruct kvm_vcpu *kvm_arch_vcpu_create (struct kvm *kvm,unsigned int id) { -return kvmppc_core_vcpu_create (kvm, id); +struct kvm_vcpu *vcpu; + vcpu =kvmppc_core_vcpu_create (kvm, id); +kvmppc_create_vcpu_debugfs (vcpu, id); +return vcpu; }void kvm_arch_vcpu_free (struct kvm_vcpu *vcpu) { +kvmppc_remove_vcpu_debugfs (vcpu);kvmppc_core_vcpu_free (vcpu); }
arch/powerpc/kvm/timing.c new file +262 -0
262 lines not on this page · raw message
arch/powerpc/kvm/timing.h new file +102 -0
102 lines not on this page · raw message
Avi Kivity
AppliedQuoted 12 lines · Hollis Blanchard
Hi Avi, here's the latest batch of PowerPC kernel patches.
The first set dramatically improve performance. Most importantly, we add support for large host pages with KVM (i.e.
PAGE_SHIFT> 12). (Large *guest* pages have already been supported since day 1, since the guest kernel uses them for the linear map.) Followup patches further improve performance by changing how we manage the shadow TLB.The last two add some accounting code to easily discover performance bottlenecks. This is especially important since the 440 core lacks performance monitoring hardware.
Quoted 8 lines
These patches, in conjunction with 64KB pages on guest and host, get us to 96% of native performance for compute-bound workloads, which I'm pretty happy with. See http://kvm.qumranet.com/kvmwiki/PowerPC_Exittimings for more details (those statistics were gathered using the accounting patches).
These have been tested pretty thoroughly for several weeks. Please apply for 2.6.29. Thanks!
Applied all, thanks.
I'm not thrilled about the private exit timing statistics gathering, hopefully it can be morphed into the more general framework.
Signature · 1 line
error compiling committee.c: too many arguments to function
Quoted 18 lines · Avi Kivity
Quoted 17 lines · Hollis Blanchard
Hi Avi, here's the latest batch of PowerPC kernel patches.
The first set dramatically improve performance. Most importantly, we add support for large host pages with KVM (i.e.
PAGE_SHIFT> 12). (Large *guest* pages have already been supported since day 1, since the guest kernel uses them for the linear map.) Followup patches further improve performance by changing how we manage the shadow TLB.The last two add some accounting code to easily discover performance bottlenecks. This is especially important since the 440 core lacks performance monitoring hardware.
These patches, in conjunction with 64KB pages on guest and host, get us to 96% of native performance for compute-bound workloads, which I'm pretty happy with. See http://kvm.qumranet.com/kvmwiki/PowerPC_Exittimings for more details (those statistics were gathered using the accounting patches).
Quoted 5 lines
Quoted 3 lines
These have been tested pretty thoroughly for several weeks. Please apply for 2.6.29. Thanks!
Applied all, thanks.
Thanks.
Quoted 2 lines
I'm not thrilled about the private exit timing statistics gathering, hopefully it can be morphed into the more general framework.
Is there anything in particular you have in mind? I think it could be generally useful, but since x86 has hardware support for performance monitoring, oprofile will already give you more accurate information. Of course, I don't think you could extract standard deviation from an oprofile report, and that has been very useful for us because it can tell us e.g. 99% of instruction emulation is handled in the minimum amount of time, but 1% takes hundreds of ms.
I'll let Christian comment when he gets back from vacation on Monday.
Signature · 7 lines
Hollis Blanchard IBM Linux Technology Center -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 4 lines · Hollis Blanchard
Quoted 3 lines
I'm not thrilled about the private exit timing statistics gathering, hopefully it can be morphed into the more general framework.
Quoted 8 lines
Is there anything in particular you have in mind? I think it could be generally useful, but since x86 has hardware support for performance monitoring, oprofile will already give you more accurate information. Of course, I don't think you could extract standard deviation from an oprofile report, and that has been very useful for us because it can tell us e.g. 99% of instruction emulation is handled in the minimum amount of time, but 1% takes hundreds of ms.
kvmtrace is basically a bunch of trace_marker()s sprinkled around the code. the marker infrastructure allow you to attach a callback to the markers, where you can do the accounting. The nice thing it can be switched off at runtime, being replaced by a nop so compiled-in-but-disabled overhead is very low.
Signature · 6 lines
error compiling committee.c: too many arguments to function -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 15 lines · Avi Kivity
Quoted 5 lines · Hollis Blanchard
Quoted 4 lines
I'm not thrilled about the private exit timing statistics gathering, hopefully it can be morphed into the more general framework.
Quoted 8 lines
Is there anything in particular you have in mind? I think it could be generally useful, but since x86 has hardware support for performance monitoring, oprofile will already give you more accurate information. Of course, I don't think you could extract standard deviation from an oprofile report, and that has been very useful for us because it can tell us e.g. 99% of instruction emulation is handled in the minimum amount of time, but 1% takes hundreds of ms.
Quoted 5 lines
kvmtrace is basically a bunch of trace_marker()s sprinkled around the code. the marker infrastructure allow you to attach a callback to the markers, where you can do the accounting. The nice thing it can be switched off at runtime, being replaced by a nop so compiled-in-but-disabled overhead is very low.
However, we grab timestamps extremely early and late in the exit handlers, in contexts from which it is not safe to call C code. This is really important because we need to be able to measure the time spent in the interrupt handler assembly. For x86 that may be confined to a simple inline asm statement, but the code in arch/powerpc/kvm/booke_interrupts.S is non-trivial and worth measuring.
Signature · 2 lines
Hollis Blanchard IBM Linux Technology Center
Quoted 22 lines · Hollis Blanchard
Quoted 15 lines · Avi Kivity
Quoted 5 lines · Hollis Blanchard
Quoted 4 lines
I'm not thrilled about the private exit timing statistics gathering, hopefully it can be morphed into the more general framework.
Quoted 8 lines
Is there anything in particular you have in mind? I think it could be generally useful, but since x86 has hardware support for performance monitoring, oprofile will already give you more accurate information. Of course, I don't think you could extract standard deviation from an oprofile report, and that has been very useful for us because it can tell us e.g. 99% of instruction emulation is handled in the minimum amount of time, but 1% takes hundreds of ms.
Quoted 5 lines
kvmtrace is basically a bunch of trace_marker()s sprinkled around the code. the marker infrastructure allow you to attach a callback to the markers, where you can do the accounting. The nice thing it can be switched off at runtime, being replaced by a nop so compiled-in-but-disabled overhead is very low.
Quoted 6 lines
However, we grab timestamps extremely early and late in the exit handlers, in contexts from which it is not safe to call C code. This is really important because we need to be able to measure the time spent in the interrupt handler assembly. For x86 that may be confined to a simple inline asm statement, but the code in
arch/powerpc/kvm/booke_interrupts.Sis non-trivial and worth measuring.
Well, I suppose we could save the timestamp to the vcpu, and call kvmtrace code later using that data. I'll stop now and let Christian comment when he's back. :)
Signature · 2 lines
Hollis Blanchard IBM Linux Technology Center