| 
									
										
										
										
											2008-10-22 22:26:29 -07:00
										 |  |  | #ifndef _ASM_X86_PVCLOCK_H
 | 
					
						
							|  |  |  | #define _ASM_X86_PVCLOCK_H
 | 
					
						
							| 
									
										
										
										
											2008-06-03 16:17:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <linux/clocksource.h>
 | 
					
						
							|  |  |  | #include <asm/pvclock-abi.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* some helper functions for xen and kvm pv clock sources */ | 
					
						
							|  |  |  | cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src); | 
					
						
							| 
									
										
										
										
											2012-11-27 23:28:52 -02:00
										 |  |  | u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src); | 
					
						
							| 
									
										
										
										
											2010-05-11 12:17:39 -04:00
										 |  |  | void pvclock_set_flags(u8 flags); | 
					
						
							| 
									
										
										
										
											2008-07-28 11:47:52 -03:00
										 |  |  | unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); | 
					
						
							| 
									
										
										
										
											2008-06-03 16:17:29 +02:00
										 |  |  | void pvclock_read_wallclock(struct pvclock_wall_clock *wall, | 
					
						
							|  |  |  | 			    struct pvclock_vcpu_time_info *vcpu, | 
					
						
							|  |  |  | 			    struct timespec *ts); | 
					
						
							| 
									
										
										
										
											2010-10-25 16:53:46 -07:00
										 |  |  | void pvclock_resume(void); | 
					
						
							| 
									
										
										
										
											2008-06-03 16:17:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-11 21:39:25 -03:00
										 |  |  | void pvclock_touch_watchdogs(void); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-19 22:07:29 -10:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, | 
					
						
							|  |  |  |  * yielding a 64-bit result. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u64 product; | 
					
						
							|  |  |  | #ifdef __i386__
 | 
					
						
							|  |  |  | 	u32 tmp1, tmp2; | 
					
						
							| 
									
										
										
										
											2011-06-15 20:50:04 -07:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	ulong tmp; | 
					
						
							| 
									
										
										
										
											2010-08-19 22:07:29 -10:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (shift < 0) | 
					
						
							|  |  |  | 		delta >>= -shift; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		delta <<= shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __i386__
 | 
					
						
							|  |  |  | 	__asm__ ( | 
					
						
							|  |  |  | 		"mul  %5       ; " | 
					
						
							|  |  |  | 		"mov  %4,%%eax ; " | 
					
						
							|  |  |  | 		"mov  %%edx,%4 ; " | 
					
						
							|  |  |  | 		"mul  %5       ; " | 
					
						
							|  |  |  | 		"xor  %5,%5    ; " | 
					
						
							|  |  |  | 		"add  %4,%%eax ; " | 
					
						
							|  |  |  | 		"adc  %5,%%edx ; " | 
					
						
							|  |  |  | 		: "=A" (product), "=r" (tmp1), "=r" (tmp2) | 
					
						
							|  |  |  | 		: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); | 
					
						
							|  |  |  | #elif defined(__x86_64__)
 | 
					
						
							|  |  |  | 	__asm__ ( | 
					
						
							| 
									
										
										
										
											2011-08-30 10:58:22 +02:00
										 |  |  | 		"mulq %[mul_frac] ; shrd $32, %[hi], %[lo]" | 
					
						
							| 
									
										
										
										
											2011-06-15 20:50:04 -07:00
										 |  |  | 		: [lo]"=a"(product), | 
					
						
							|  |  |  | 		  [hi]"=d"(tmp) | 
					
						
							|  |  |  | 		: "0"(delta), | 
					
						
							|  |  |  | 		  [mul_frac]"rm"((u64)mul_frac)); | 
					
						
							| 
									
										
										
										
											2010-08-19 22:07:29 -10:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #error implement me!
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return product; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-27 23:28:51 -02:00
										 |  |  | static __always_inline | 
					
						
							|  |  |  | u64 pvclock_get_nsec_offset(const struct pvclock_vcpu_time_info *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u64 delta = __native_read_tsc() - src->tsc_timestamp; | 
					
						
							|  |  |  | 	return pvclock_scale_delta(delta, src->tsc_to_system_mul, | 
					
						
							|  |  |  | 				   src->tsc_shift); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static __always_inline | 
					
						
							|  |  |  | unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, | 
					
						
							|  |  |  | 			       cycle_t *cycles, u8 *flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned version; | 
					
						
							|  |  |  | 	cycle_t ret, offset; | 
					
						
							|  |  |  | 	u8 ret_flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	version = src->version; | 
					
						
							| 
									
										
										
										
											2012-11-27 23:28:53 -02:00
										 |  |  | 	/* Note: emulated platforms which do not advertise SSE2 support
 | 
					
						
							|  |  |  | 	 * result in kvmclock not using the necessary RDTSC barriers. | 
					
						
							|  |  |  | 	 * Without barriers, it is possible that RDTSC instruction reads from | 
					
						
							|  |  |  | 	 * the time stamp counter outside rdtsc_barrier protected section | 
					
						
							|  |  |  | 	 * below, resulting in violation of monotonicity. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-11-27 23:28:51 -02:00
										 |  |  | 	rdtsc_barrier(); | 
					
						
							|  |  |  | 	offset = pvclock_get_nsec_offset(src); | 
					
						
							|  |  |  | 	ret = src->system_time + offset; | 
					
						
							|  |  |  | 	ret_flags = src->flags; | 
					
						
							|  |  |  | 	rdtsc_barrier(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*cycles = ret; | 
					
						
							|  |  |  | 	*flags = ret_flags; | 
					
						
							|  |  |  | 	return version; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-27 23:28:55 -02:00
										 |  |  | struct pvclock_vsyscall_time_info { | 
					
						
							|  |  |  | 	struct pvclock_vcpu_time_info pvti; | 
					
						
							|  |  |  | } __attribute__((__aligned__(SMP_CACHE_BYTES))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
 | 
					
						
							|  |  |  | #define PVCLOCK_VSYSCALL_NR_PAGES (((NR_CPUS-1)/(PAGE_SIZE/PVTI_SIZE))+1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i, | 
					
						
							|  |  |  | 				 int size); | 
					
						
							|  |  |  | struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 22:26:29 -07:00
										 |  |  | #endif /* _ASM_X86_PVCLOCK_H */
 |