Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: kvm guest: pvclock vsyscall support

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>

+61 -12
+6
arch/x86/include/asm/kvm_guest.h
··· 1 + #ifndef _ASM_X86_KVM_GUEST_H 2 + #define _ASM_X86_KVM_GUEST_H 3 + 4 + int kvm_setup_vsyscall_timeinfo(void); 5 + 6 + #endif /* _ASM_X86_KVM_GUEST_H */
+13
arch/x86/kernel/kvm.c
··· 42 42 #include <asm/apic.h> 43 43 #include <asm/apicdef.h> 44 44 #include <asm/hypervisor.h> 45 + #include <asm/kvm_guest.h> 45 46 46 47 static int kvmapf = 1; 47 48 ··· 62 61 } 63 62 64 63 early_param("no-steal-acc", parse_no_stealacc); 64 + 65 + static int kvmclock_vsyscall = 1; 66 + static int parse_no_kvmclock_vsyscall(char *arg) 67 + { 68 + kvmclock_vsyscall = 0; 69 + return 0; 70 + } 71 + 72 + early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall); 65 73 66 74 static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64); 67 75 static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64); ··· 480 470 481 471 if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) 482 472 apic_set_eoi_write(kvm_guest_apic_eoi_write); 473 + 474 + if (kvmclock_vsyscall) 475 + kvm_setup_vsyscall_timeinfo(); 483 476 484 477 #ifdef CONFIG_SMP 485 478 smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
+42 -12
arch/x86/kernel/kvmclock.c
··· 40 40 early_param("no-kvmclock", parse_no_kvmclock); 41 41 42 42 /* The hypervisor will put information about time periodically here */ 43 - struct pvclock_aligned_vcpu_time_info { 44 - struct pvclock_vcpu_time_info clock; 45 - } __attribute__((__aligned__(SMP_CACHE_BYTES))); 46 - 47 - static struct pvclock_aligned_vcpu_time_info *hv_clock; 43 + static struct pvclock_vsyscall_time_info *hv_clock; 48 44 static struct pvclock_wall_clock wall_clock; 49 45 50 46 /* ··· 63 67 preempt_disable(); 64 68 cpu = smp_processor_id(); 65 69 66 - vcpu_time = &hv_clock[cpu].clock; 70 + vcpu_time = &hv_clock[cpu].pvti; 67 71 pvclock_read_wallclock(&wall_clock, vcpu_time, &ts); 68 72 69 73 preempt_enable(); ··· 84 88 85 89 preempt_disable_notrace(); 86 90 cpu = smp_processor_id(); 87 - src = &hv_clock[cpu].clock; 91 + src = &hv_clock[cpu].pvti; 88 92 ret = pvclock_clocksource_read(src); 89 93 preempt_enable_notrace(); 90 94 return ret; ··· 112 116 113 117 preempt_disable(); 114 118 cpu = smp_processor_id(); 115 - src = &hv_clock[cpu].clock; 119 + src = &hv_clock[cpu].pvti; 116 120 tsc_khz = pvclock_tsc_khz(src); 117 121 preempt_enable(); 118 122 return tsc_khz; ··· 139 143 if (!hv_clock) 140 144 return ret; 141 145 142 - src = &hv_clock[cpu].clock; 146 + src = &hv_clock[cpu].pvti; 143 147 if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) { 144 148 src->flags &= ~PVCLOCK_GUEST_STOPPED; 145 149 ret = true; ··· 160 164 { 161 165 int cpu = smp_processor_id(); 162 166 int low, high, ret; 163 - struct pvclock_vcpu_time_info *src = &hv_clock[cpu].clock; 167 + struct pvclock_vcpu_time_info *src = &hv_clock[cpu].pvti; 164 168 165 169 low = (int)__pa(src) | 1; 166 170 high = ((u64)__pa(src) >> 32); ··· 231 235 printk(KERN_INFO "kvm-clock: Using msrs %x and %x", 232 236 msr_kvm_system_time, msr_kvm_wall_clock); 233 237 234 - mem = memblock_alloc(sizeof(struct pvclock_aligned_vcpu_time_info) * NR_CPUS, 238 + mem = memblock_alloc(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS, 235 239 PAGE_SIZE); 236 240 if (!mem) 237 241 return; ··· 240 244 if (kvm_register_clock("boot clock")) { 241 245 hv_clock = NULL; 242 246 memblock_free(mem, 243 - sizeof(struct pvclock_aligned_vcpu_time_info)*NR_CPUS); 247 + sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS); 244 248 return; 245 249 } 246 250 pv_time_ops.sched_clock = kvm_clock_read; ··· 264 268 265 269 if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)) 266 270 pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); 271 + } 272 + 273 + int __init kvm_setup_vsyscall_timeinfo(void) 274 + { 275 + #ifdef CONFIG_X86_64 276 + int cpu; 277 + int ret; 278 + u8 flags; 279 + struct pvclock_vcpu_time_info *vcpu_time; 280 + unsigned int size; 281 + 282 + size = sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS; 283 + 284 + preempt_disable(); 285 + cpu = smp_processor_id(); 286 + 287 + vcpu_time = &hv_clock[cpu].pvti; 288 + flags = pvclock_read_flags(vcpu_time); 289 + 290 + if (!(flags & PVCLOCK_TSC_STABLE_BIT)) { 291 + preempt_enable(); 292 + return 1; 293 + } 294 + 295 + if ((ret = pvclock_init_vsyscall(hv_clock, size))) { 296 + preempt_enable(); 297 + return ret; 298 + } 299 + 300 + preempt_enable(); 301 + 302 + kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK; 303 + #endif 304 + return 0; 267 305 }