KVM: x86: introduce do_shl32_div32

This is similar to the existing div_frac function, but it returns the
remainder too.  Unlike div_frac, it can be used to implement long
division, e.g. (a << 64) / b for 32-bit a and b.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2016-01-22 11:39:22 +01:00
parent 765bdb406d
commit b51012deb3
2 changed files with 17 additions and 8 deletions

View File

@ -1196,14 +1196,8 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
static uint32_t div_frac(uint32_t dividend, uint32_t divisor)
{
uint32_t quotient, remainder;
/* Don't try to replace with do_div(), this one calculates
* "(dividend << 32) / divisor" */
__asm__ ( "divl %4"
: "=a" (quotient), "=d" (remainder)
: "0" (0), "1" (dividend), "r" (divisor) );
return quotient;
do_shl32_div32(dividend, divisor);
return dividend;
}
static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz,

View File

@ -192,4 +192,19 @@ extern unsigned int min_timer_period_us;
extern unsigned int lapic_timer_advance_ns;
extern struct static_key kvm_no_apic_vcpu;
/* Same "calling convention" as do_div:
* - divide (n << 32) by base
* - put result in n
* - return remainder
*/
#define do_shl32_div32(n, base) \
({ \
u32 __quot, __rem; \
asm("divl %2" : "=a" (__quot), "=d" (__rem) \
: "rm" (base), "0" (0), "1" ((u32) n)); \
n = __quot; \
__rem; \
})
#endif