* Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, * yielding a 64-bit result. */
| 78 | * yielding a 64-bit result. |
| 79 | */ |
| 80 | static inline uint64_t |
| 81 | pvclock_scale_delta(uint64_t delta, uint32_t mul_frac, int shift) |
| 82 | { |
| 83 | uint64_t product; |
| 84 | |
| 85 | if (shift < 0) |
| 86 | delta >>= -shift; |
| 87 | else |
| 88 | delta <<= shift; |
| 89 | |
| 90 | #if defined(__i386__) |
| 91 | { |
| 92 | uint32_t tmp1, tmp2; |
| 93 | |
| 94 | /** |
| 95 | * For i386, the formula looks like: |
| 96 | * |
| 97 | * lower = (mul_frac * (delta & UINT_MAX)) >> 32 |
| 98 | * upper = mul_frac * (delta >> 32) |
| 99 | * product = lower + upper |
| 100 | */ |
| 101 | __asm__ ( |
| 102 | "mul %5 ; " |
| 103 | "mov %4,%%eax ; " |
| 104 | "mov %%edx,%4 ; " |
| 105 | "mul %5 ; " |
| 106 | "xor %5,%5 ; " |
| 107 | "add %4,%%eax ; " |
| 108 | "adc %5,%%edx ; " |
| 109 | : "=A" (product), "=r" (tmp1), "=r" (tmp2) |
| 110 | : "a" ((uint32_t)delta), "1" ((uint32_t)(delta >> 32)), |
| 111 | "2" (mul_frac) ); |
| 112 | } |
| 113 | #elif defined(__amd64__) |
| 114 | { |
| 115 | unsigned long tmp; |
| 116 | |
| 117 | __asm__ ( |
| 118 | "mulq %[mul_frac] ; shrd $32, %[hi], %[lo]" |
| 119 | : [lo]"=a" (product), [hi]"=d" (tmp) |
| 120 | : "0" (delta), [mul_frac]"rm"((uint64_t)mul_frac)); |
| 121 | } |
| 122 | #else |
| 123 | #error "pvclock: unsupported x86 architecture?" |
| 124 | #endif |
| 125 | |
| 126 | return (product); |
| 127 | } |
| 128 | |
| 129 | static uint64_t |
| 130 | pvclock_get_nsec_offset(struct pvclock_vcpu_time_info *ti) |
no outgoing calls
no test coverage detected