Skip to content

Commit

Permalink
x86: kvm guest: pvclock vsyscall support
Browse files Browse the repository at this point in the history
Hook into generic pvclock vsyscall code, with the aim to
allow userspace to have visibility into pvclock data.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
  • Loading branch information
Marcelo Tosatti committed Nov 28, 2012
1 parent 71056ae commit 3dc4f7c
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 12 deletions.
6 changes: 6 additions & 0 deletions arch/x86/include/asm/kvm_guest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef _ASM_X86_KVM_GUEST_H
#define _ASM_X86_KVM_GUEST_H

int kvm_setup_vsyscall_timeinfo(void);

#endif /* _ASM_X86_KVM_GUEST_H */
13 changes: 13 additions & 0 deletions arch/x86/kernel/kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <asm/apic.h>
#include <asm/apicdef.h>
#include <asm/hypervisor.h>
#include <asm/kvm_guest.h>

static int kvmapf = 1;

Expand All @@ -62,6 +63,15 @@ static int parse_no_stealacc(char *arg)

early_param("no-steal-acc", parse_no_stealacc);

static int kvmclock_vsyscall = 1;
static int parse_no_kvmclock_vsyscall(char *arg)
{
kvmclock_vsyscall = 0;
return 0;
}

early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);

static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
static int has_steal_clock = 0;
Expand Down Expand Up @@ -471,6 +481,9 @@ void __init kvm_guest_init(void)
if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
apic_set_eoi_write(kvm_guest_apic_eoi_write);

if (kvmclock_vsyscall)
kvm_setup_vsyscall_timeinfo();

#ifdef CONFIG_SMP
smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
register_cpu_notifier(&kvm_cpu_notifier);
Expand Down
54 changes: 42 additions & 12 deletions arch/x86/kernel/kvmclock.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,7 @@ static int parse_no_kvmclock(char *arg)
early_param("no-kvmclock", parse_no_kvmclock);

/* The hypervisor will put information about time periodically here */
struct pvclock_aligned_vcpu_time_info {
struct pvclock_vcpu_time_info clock;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));

static struct pvclock_aligned_vcpu_time_info *hv_clock;
static struct pvclock_vsyscall_time_info *hv_clock;
static struct pvclock_wall_clock wall_clock;

/*
Expand All @@ -67,7 +63,7 @@ static unsigned long kvm_get_wallclock(void)
preempt_disable();
cpu = smp_processor_id();

vcpu_time = &hv_clock[cpu].clock;
vcpu_time = &hv_clock[cpu].pvti;
pvclock_read_wallclock(&wall_clock, vcpu_time, &ts);

preempt_enable();
Expand All @@ -88,7 +84,7 @@ static cycle_t kvm_clock_read(void)

preempt_disable_notrace();
cpu = smp_processor_id();
src = &hv_clock[cpu].clock;
src = &hv_clock[cpu].pvti;
ret = pvclock_clocksource_read(src);
preempt_enable_notrace();
return ret;
Expand Down Expand Up @@ -116,7 +112,7 @@ static unsigned long kvm_get_tsc_khz(void)

preempt_disable();
cpu = smp_processor_id();
src = &hv_clock[cpu].clock;
src = &hv_clock[cpu].pvti;
tsc_khz = pvclock_tsc_khz(src);
preempt_enable();
return tsc_khz;
Expand All @@ -143,7 +139,7 @@ bool kvm_check_and_clear_guest_paused(void)
if (!hv_clock)
return ret;

src = &hv_clock[cpu].clock;
src = &hv_clock[cpu].pvti;
if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) {
src->flags &= ~PVCLOCK_GUEST_STOPPED;
ret = true;
Expand All @@ -164,7 +160,7 @@ int kvm_register_clock(char *txt)
{
int cpu = smp_processor_id();
int low, high, ret;
struct pvclock_vcpu_time_info *src = &hv_clock[cpu].clock;
struct pvclock_vcpu_time_info *src = &hv_clock[cpu].pvti;

low = (int)__pa(src) | 1;
high = ((u64)__pa(src) >> 32);
Expand Down Expand Up @@ -235,7 +231,7 @@ void __init kvmclock_init(void)
printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
msr_kvm_system_time, msr_kvm_wall_clock);

mem = memblock_alloc(sizeof(struct pvclock_aligned_vcpu_time_info) * NR_CPUS,
mem = memblock_alloc(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS,
PAGE_SIZE);
if (!mem)
return;
Expand All @@ -244,7 +240,7 @@ void __init kvmclock_init(void)
if (kvm_register_clock("boot clock")) {
hv_clock = NULL;
memblock_free(mem,
sizeof(struct pvclock_aligned_vcpu_time_info)*NR_CPUS);
sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
return;
}
pv_time_ops.sched_clock = kvm_clock_read;
Expand All @@ -269,3 +265,37 @@ void __init kvmclock_init(void)
if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT))
pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
}

int __init kvm_setup_vsyscall_timeinfo(void)
{
#ifdef CONFIG_X86_64
int cpu;
int ret;
u8 flags;
struct pvclock_vcpu_time_info *vcpu_time;
unsigned int size;

size = sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS;

preempt_disable();
cpu = smp_processor_id();

vcpu_time = &hv_clock[cpu].pvti;
flags = pvclock_read_flags(vcpu_time);

if (!(flags & PVCLOCK_TSC_STABLE_BIT)) {
preempt_enable();
return 1;
}

if ((ret = pvclock_init_vsyscall(hv_clock, size))) {
preempt_enable();
return ret;
}

preempt_enable();

kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK;
#endif
return 0;
}

0 comments on commit 3dc4f7c

Please sign in to comment.