diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/kvm_para.h | 4 | ||||
-rw-r--r-- | arch/x86/kvm/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 74 |
4 files changed, 86 insertions, 2 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index da6bbee878ca..59086a77ff13 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -389,6 +389,15 @@ struct kvm_vcpu_arch { | |||
389 | unsigned int hw_tsc_khz; | 389 | unsigned int hw_tsc_khz; |
390 | unsigned int time_offset; | 390 | unsigned int time_offset; |
391 | struct page *time_page; | 391 | struct page *time_page; |
392 | |||
393 | struct { | ||
394 | u64 msr_val; | ||
395 | u64 last_steal; | ||
396 | u64 accum_steal; | ||
397 | struct gfn_to_hva_cache stime; | ||
398 | struct kvm_steal_time steal; | ||
399 | } st; | ||
400 | |||
392 | u64 last_guest_tsc; | 401 | u64 last_guest_tsc; |
393 | u64 last_kernel_ns; | 402 | u64 last_kernel_ns; |
394 | u64 last_tsc_nsec; | 403 | u64 last_tsc_nsec; |
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index 65f8bb9279e0..c484ba8e05ea 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h | |||
@@ -45,6 +45,10 @@ struct kvm_steal_time { | |||
45 | __u32 pad[12]; | 45 | __u32 pad[12]; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | #define KVM_STEAL_ALIGNMENT_BITS 5 | ||
49 | #define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1))) | ||
50 | #define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1) | ||
51 | |||
48 | #define KVM_MAX_MMU_OP_BATCH 32 | 52 | #define KVM_MAX_MMU_OP_BATCH 32 |
49 | 53 | ||
50 | #define KVM_ASYNC_PF_ENABLED (1 << 0) | 54 | #define KVM_ASYNC_PF_ENABLED (1 << 0) |
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 50f63648ce1b..99c3f0589faa 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig | |||
@@ -31,6 +31,7 @@ config KVM | |||
31 | select KVM_ASYNC_PF | 31 | select KVM_ASYNC_PF |
32 | select USER_RETURN_NOTIFIER | 32 | select USER_RETURN_NOTIFIER |
33 | select KVM_MMIO | 33 | select KVM_MMIO |
34 | select TASK_DELAY_ACCT | ||
34 | ---help--- | 35 | ---help--- |
35 | Support hosting fully virtualized guest machines using hardware | 36 | Support hosting fully virtualized guest machines using hardware |
36 | virtualization extensions. You will need a fairly recent | 37 | virtualization extensions. You will need a fairly recent |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0b803f04bde7..c96cdc092484 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -808,12 +808,12 @@ EXPORT_SYMBOL_GPL(kvm_get_dr); | |||
808 | * kvm-specific. Those are put in the beginning of the list. | 808 | * kvm-specific. Those are put in the beginning of the list. |
809 | */ | 809 | */ |
810 | 810 | ||
811 | #define KVM_SAVE_MSRS_BEGIN 8 | 811 | #define KVM_SAVE_MSRS_BEGIN 9 |
812 | static u32 msrs_to_save[] = { | 812 | static u32 msrs_to_save[] = { |
813 | MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, | 813 | MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, |
814 | MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, | 814 | MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, |
815 | HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, | 815 | HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, |
816 | HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, | 816 | HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME, |
817 | MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, | 817 | MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, |
818 | MSR_STAR, | 818 | MSR_STAR, |
819 | #ifdef CONFIG_X86_64 | 819 | #ifdef CONFIG_X86_64 |
@@ -1488,6 +1488,35 @@ static void kvmclock_reset(struct kvm_vcpu *vcpu) | |||
1488 | } | 1488 | } |
1489 | } | 1489 | } |
1490 | 1490 | ||
1491 | static void accumulate_steal_time(struct kvm_vcpu *vcpu) | ||
1492 | { | ||
1493 | u64 delta; | ||
1494 | |||
1495 | if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) | ||
1496 | return; | ||
1497 | |||
1498 | delta = current->sched_info.run_delay - vcpu->arch.st.last_steal; | ||
1499 | vcpu->arch.st.last_steal = current->sched_info.run_delay; | ||
1500 | vcpu->arch.st.accum_steal = delta; | ||
1501 | } | ||
1502 | |||
1503 | static void record_steal_time(struct kvm_vcpu *vcpu) | ||
1504 | { | ||
1505 | if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) | ||
1506 | return; | ||
1507 | |||
1508 | if (unlikely(kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.st.stime, | ||
1509 | &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)))) | ||
1510 | return; | ||
1511 | |||
1512 | vcpu->arch.st.steal.steal += vcpu->arch.st.accum_steal; | ||
1513 | vcpu->arch.st.steal.version += 2; | ||
1514 | vcpu->arch.st.accum_steal = 0; | ||
1515 | |||
1516 | kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime, | ||
1517 | &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); | ||
1518 | } | ||
1519 | |||
1491 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | 1520 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) |
1492 | { | 1521 | { |
1493 | switch (msr) { | 1522 | switch (msr) { |
@@ -1570,6 +1599,33 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
1570 | if (kvm_pv_enable_async_pf(vcpu, data)) | 1599 | if (kvm_pv_enable_async_pf(vcpu, data)) |
1571 | return 1; | 1600 | return 1; |
1572 | break; | 1601 | break; |
1602 | case MSR_KVM_STEAL_TIME: | ||
1603 | |||
1604 | if (unlikely(!sched_info_on())) | ||
1605 | return 1; | ||
1606 | |||
1607 | if (data & KVM_STEAL_RESERVED_MASK) | ||
1608 | return 1; | ||
1609 | |||
1610 | if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime, | ||
1611 | data & KVM_STEAL_VALID_BITS)) | ||
1612 | return 1; | ||
1613 | |||
1614 | vcpu->arch.st.msr_val = data; | ||
1615 | |||
1616 | if (!(data & KVM_MSR_ENABLED)) | ||
1617 | break; | ||
1618 | |||
1619 | vcpu->arch.st.last_steal = current->sched_info.run_delay; | ||
1620 | |||
1621 | preempt_disable(); | ||
1622 | accumulate_steal_time(vcpu); | ||
1623 | preempt_enable(); | ||
1624 | |||
1625 | kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); | ||
1626 | |||
1627 | break; | ||
1628 | |||
1573 | case MSR_IA32_MCG_CTL: | 1629 | case MSR_IA32_MCG_CTL: |
1574 | case MSR_IA32_MCG_STATUS: | 1630 | case MSR_IA32_MCG_STATUS: |
1575 | case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1: | 1631 | case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1: |
@@ -1855,6 +1911,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
1855 | case MSR_KVM_ASYNC_PF_EN: | 1911 | case MSR_KVM_ASYNC_PF_EN: |
1856 | data = vcpu->arch.apf.msr_val; | 1912 | data = vcpu->arch.apf.msr_val; |
1857 | break; | 1913 | break; |
1914 | case MSR_KVM_STEAL_TIME: | ||
1915 | data = vcpu->arch.st.msr_val; | ||
1916 | break; | ||
1858 | case MSR_IA32_P5_MC_ADDR: | 1917 | case MSR_IA32_P5_MC_ADDR: |
1859 | case MSR_IA32_P5_MC_TYPE: | 1918 | case MSR_IA32_P5_MC_TYPE: |
1860 | case MSR_IA32_MCG_CAP: | 1919 | case MSR_IA32_MCG_CAP: |
@@ -2166,6 +2225,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
2166 | kvm_migrate_timers(vcpu); | 2225 | kvm_migrate_timers(vcpu); |
2167 | vcpu->cpu = cpu; | 2226 | vcpu->cpu = cpu; |
2168 | } | 2227 | } |
2228 | |||
2229 | accumulate_steal_time(vcpu); | ||
2230 | kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); | ||
2169 | } | 2231 | } |
2170 | 2232 | ||
2171 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | 2233 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) |
@@ -2487,6 +2549,10 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
2487 | (1 << KVM_FEATURE_CLOCKSOURCE2) | | 2549 | (1 << KVM_FEATURE_CLOCKSOURCE2) | |
2488 | (1 << KVM_FEATURE_ASYNC_PF) | | 2550 | (1 << KVM_FEATURE_ASYNC_PF) | |
2489 | (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); | 2551 | (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); |
2552 | |||
2553 | if (sched_info_on()) | ||
2554 | entry->eax |= (1 << KVM_FEATURE_STEAL_TIME); | ||
2555 | |||
2490 | entry->ebx = 0; | 2556 | entry->ebx = 0; |
2491 | entry->ecx = 0; | 2557 | entry->ecx = 0; |
2492 | entry->edx = 0; | 2558 | entry->edx = 0; |
@@ -5470,6 +5536,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) | |||
5470 | r = 1; | 5536 | r = 1; |
5471 | goto out; | 5537 | goto out; |
5472 | } | 5538 | } |
5539 | if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu)) | ||
5540 | record_steal_time(vcpu); | ||
5541 | |||
5473 | } | 5542 | } |
5474 | 5543 | ||
5475 | r = kvm_mmu_reload(vcpu); | 5544 | r = kvm_mmu_reload(vcpu); |
@@ -6206,6 +6275,7 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu) | |||
6206 | 6275 | ||
6207 | kvm_make_request(KVM_REQ_EVENT, vcpu); | 6276 | kvm_make_request(KVM_REQ_EVENT, vcpu); |
6208 | vcpu->arch.apf.msr_val = 0; | 6277 | vcpu->arch.apf.msr_val = 0; |
6278 | vcpu->arch.st.msr_val = 0; | ||
6209 | 6279 | ||
6210 | kvmclock_reset(vcpu); | 6280 | kvmclock_reset(vcpu); |
6211 | 6281 | ||