@@ -31,6 +31,7 @@
static int kvmclock = 1;
static int msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
static int msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
+static int kvm_memory_area_available = 0;
static int parse_no_kvmclock(char *arg)
{
@@ -43,6 +44,27 @@ early_param("no-kvmclock", parse_no_kvmclock);
static DEFINE_PER_CPU_SHARED_ALIGNED(struct pvclock_vcpu_time_info, hv_clock);
static struct pvclock_wall_clock wall_clock;
+static int kvm_register_mem_area(u64 base, int type, int size)
+{
+ int low, high;
+
+ struct kvm_memory_area mem;
+
+ if (!kvm_memory_area_available)
+ return 1;
+
+ mem.base = base;
+ mem.size = size;
+ mem.type = type;
+
+ low = (int)__pa_symbol(&mem);
+ high = ((u64)__pa_symbol(&mem) >> 32);
+
+ native_write_msr(MSR_KVM_REGISTER_MEM_AREA, low, high);
+ return mem.result;
+}
+
+
/*
* The wallclock is the time of day when we booted. Since then, some time may
* have elapsed since the hypervisor wrote the data. So we try to account for
@@ -53,11 +75,17 @@ static unsigned long kvm_get_wallclock(void)
struct pvclock_vcpu_time_info *vcpu_time;
struct timespec ts;
int low, high;
-
- low = (int)__pa_symbol(&wall_clock);
- high = ((u64)__pa_symbol(&wall_clock) >> 32);
-
- native_write_msr(msr_kvm_wall_clock, low, high);
+ u64 addr = __pa_symbol(&wall_clock);
+ int ret;
+
+ ret = kvm_register_mem_area(addr, KVM_AREA_WALLCLOCK,
+ sizeof(wall_clock));
+ if (ret != 0) {
+ low = (int)addr;
+ high = ((u64)addr >> 32);
+
+ native_write_msr(msr_kvm_wall_clock, low, high);
+ }
vcpu_time = &get_cpu_var(hv_clock);
pvclock_read_wallclock(&wall_clock, vcpu_time, &ts);
@@ -179,6 +207,9 @@ void __init kvmclock_init(void)
if (!kvm_para_available())
return;
+ if (kvm_para_has_feature(KVM_FEATURE_MEMORY_AREA))
+ kvm_memory_area_available = 1;
+
if (kvmclock && kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE2)) {
msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;