KVM: x86: limit PIT timer frequency
Limit PIT timer frequency similarly to the limit applied by LAPIC timer.
Signed-off-by Marcelo Tosatti <[email protected]>
arch/x86/kvm/i8254.c +18 -0
@@ -37,6 +37,7 @@#include "irq.h" #include "i8254.h" +#include "x86.h" #ifndef CONFIG_X86_64 #define mod_64 (x, y) ((x) - (y) * div64_u64(x, y))
@@ -349,6 +350,23 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)atomic_set (&ps->pending,0 ); ps->irq_ack =1 ; +/* +* Do not allow the guest to program periodic timers with small +* interval, since the hrtimers are not throttled by the host +* scheduler. +*/ +if (ps->is_periodic) { +s64 min_period = min_timer_period_us *1000LL ; + +if (ps->period < min_period) { +pr_info_ratelimited ( +"kvm: requested %lld ns " +"i8254 timer period limited to %lld ns\n" , + ps->period, min_period); + ps->period = min_period; + } + } +hrtimer_start (&ps->timer,ktime_add_ns (ktime_get (), interval),HRTIMER_MODE_ABS ); }
arch/x86/kvm/lapic.c +0 -3
@@ -71,9 +71,6 @@#define VEC_POS (v) ((v) & (32 - 1))#define REG_POS (v) (((v) >> 5) << 4) -static unsigned int min_timer_period_us =500 ; -module_param (min_timer_period_us, uint,S_IRUGO |S_IWUSR ); -static inline void apic_set_reg (struct kvm_lapic *apic,int reg_off,u32 val) { *((u32 *) (apic->regs + reg_off)) = val;
arch/x86/kvm/x86.c +3 -0
@@ -94,6 +94,9 @@ EXPORT_SYMBOL_GPL(kvm_x86_ops);static bool ignore_msrs =0 ;module_param (ignore_msrs, bool,S_IRUGO |S_IWUSR ); +unsigned int min_timer_period_us =500 ; +module_param (min_timer_period_us, uint,S_IRUGO |S_IWUSR ); +bool kvm_has_tsc_control;EXPORT_SYMBOL_GPL (kvm_has_tsc_control);u32 kvm_max_guest_tsc_khz;
arch/x86/kvm/x86.h +2 -0
@@ -125,5 +125,7 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,#define KVM_SUPPORTED_XCR0 (XSTATE_FP | XSTATE_SSE | XSTATE_YMM)extern u64 host_xcr0; +extern unsigned int min_timer_period_us; +extern struct static_key kvm_no_apic_vcpu;#endif
Jan Kiszka
Reviewed-byQuoted 78 lines · Marcelo Tosatti
Limit PIT timer frequency similarly to the limit applied by LAPIC timer.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/i8254.c +18
-0@@ -37,6 +37,7 @@#include "irq.h" #include "i8254.h" +#include "x86.h" #ifndef CONFIG_X86_64 #define mod_64 (x, y) ((x) - (y) * div64_u64(x, y))@@ -349,6 +350,23 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)atomic_set (&ps->pending,0 ); ps->irq_ack =1 ; +/* +* Do not allow the guest to program periodic timers with small +* interval, since the hrtimers are not throttled by the host +* scheduler. +*/ +if (ps->is_periodic) { +s64 min_period = min_timer_period_us *1000LL ; + +if (ps->period < min_period) { +pr_info_ratelimited ( +"kvm: requested %lld ns " +"i8254 timer period limited to %lld ns\n" , + ps->period, min_period); + ps->period = min_period; + } + } +hrtimer_start (&ps->timer,ktime_add_ns (ktime_get (), interval),HRTIMER_MODE_ABS ); }arch/x86/kvm/lapic.c +0
-3@@ -71,9 +71,6 @@#define VEC_POS (v) ((v) & (32 - 1))#define REG_POS (v) (((v) >> 5) << 4) -static unsigned int min_timer_period_us =500 ; -module_param (min_timer_period_us, uint,S_IRUGO |S_IWUSR ); -static inline void apic_set_reg (struct kvm_lapic *apic,int reg_off,u32 val) { *((u32 *) (apic->regs + reg_off)) = val;arch/x86/kvm/x86.c +3
-0@@ -94,6 +94,9 @@ EXPORT_SYMBOL_GPL(kvm_x86_ops);static bool ignore_msrs =0 ;module_param (ignore_msrs, bool,S_IRUGO |S_IWUSR ); +unsigned int min_timer_period_us =500 ; +module_param (min_timer_period_us, uint,S_IRUGO |S_IWUSR ); +bool kvm_has_tsc_control;EXPORT_SYMBOL_GPL (kvm_has_tsc_control);u32 kvm_max_guest_tsc_khz;arch/x86/kvm/x86.h +0
-0
arch/x86/kvm/x86.h int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt, · line 131
Quoted 7 lines
arch/x86/kvm/x86.h +2
-0@@ -125,5 +125,7 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,#define KVM_SUPPORTED_XCR0 (XSTATE_FP | XSTATE_SSE | XSTATE_YMM)extern u64 host_xcr0; +extern unsigned int min_timer_period_us; +extern struct static_key kvm_no_apic_vcpu;#endif
Indeed, required here as well.
Reviewed-by Jan Kiszka <[email protected]>
At this chance, I also grep'ed through timer emulations of other archs. Only MIPS uses a periodic hrtimer, but with a fixed frequency. So we should be safe for now.
Jan
Il 06/01/2014 15:00, Marcelo Tosatti ha scritto:
Quoted 78 lines
Limit PIT timer frequency similarly to the limit applied by LAPIC timer.
Signed-off-by Marcelo Tosatti <[email protected]>arch/x86/kvm/i8254.c +18
-0@@ -37,6 +37,7 @@#include "irq.h" #include "i8254.h" +#include "x86.h" #ifndef CONFIG_X86_64 #define mod_64 (x, y) ((x) - (y) * div64_u64(x, y))@@ -349,6 +350,23 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)atomic_set (&ps->pending,0 ); ps->irq_ack =1 ; +/* +* Do not allow the guest to program periodic timers with small +* interval, since the hrtimers are not throttled by the host +* scheduler. +*/ +if (ps->is_periodic) { +s64 min_period = min_timer_period_us *1000LL ; + +if (ps->period < min_period) { +pr_info_ratelimited ( +"kvm: requested %lld ns " +"i8254 timer period limited to %lld ns\n" , + ps->period, min_period); + ps->period = min_period; + } + } +hrtimer_start (&ps->timer,ktime_add_ns (ktime_get (), interval),HRTIMER_MODE_ABS ); }arch/x86/kvm/lapic.c +0
-3@@ -71,9 +71,6 @@#define VEC_POS (v) ((v) & (32 - 1))#define REG_POS (v) (((v) >> 5) << 4) -static unsigned int min_timer_period_us =500 ; -module_param (min_timer_period_us, uint,S_IRUGO |S_IWUSR ); -static inline void apic_set_reg (struct kvm_lapic *apic,int reg_off,u32 val) { *((u32 *) (apic->regs + reg_off)) = val;arch/x86/kvm/x86.c +3
-0@@ -94,6 +94,9 @@ EXPORT_SYMBOL_GPL(kvm_x86_ops);static bool ignore_msrs =0 ;module_param (ignore_msrs, bool,S_IRUGO |S_IWUSR ); +unsigned int min_timer_period_us =500 ; +module_param (min_timer_period_us, uint,S_IRUGO |S_IWUSR ); +bool kvm_has_tsc_control;EXPORT_SYMBOL_GPL (kvm_has_tsc_control);u32 kvm_max_guest_tsc_khz;arch/x86/kvm/x86.h +0
-0
arch/x86/kvm/x86.h int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt, · line 131
Quoted 7 lines
arch/x86/kvm/x86.h +2
-0@@ -125,5 +125,7 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,#define KVM_SUPPORTED_XCR0 (XSTATE_FP | XSTATE_SSE | XSTATE_YMM)extern u64 host_xcr0; +extern unsigned int min_timer_period_us; +extern struct static_key kvm_no_apic_vcpu;#endif
Applied to kvm/queue, thanks.
Paolo