1/* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12/* 13 * Copyright 2023 Oxide Computer Company 14 */ 15 16#include <sys/asm_linkage.h> 17 18/* 19 * TSC math functions that require multiplication of 64-bit numbers with 20 * intermediate steps requiring 128-bit precision. 21 * 22 * See block comment in vmm.c for more details. 23 */ 24 25 26/* 27 * calc_freq_multiplier: calculates the ratio of guest_hz / host_hz, with 28 * `frac_size` fractional bits. 29 * 30 * (guest_hz * (1 << FRAC_SIZE)) / host_hz 31 * 32 * Note: this will generate a #DE if: 33 * - the integer portion of the ratio does not fit into (64 - FRAC_SIZE) bits 34 * - host_hz is 0 35 * Callers should validate input appropriately. 36 * 37 * 38 * uint64_t calc_freq_multiplier(uint64_t guest_hz, uint64_t host_hz, 39 * uint32_t frac_size) 40 * %rdi: uint64_t guest_hz 41 * %rsi: uint64_t host_hz 42 * %edx: uint32_t frac_size 43 */ 44ENTRY_NP(calc_freq_multiplier) 45 /* 46 * Create scaling factor: 1 << frac_size 47 * Store result in %rax 48 */ 49 movl $1, %eax 50 movl %edx, %ecx 51 shlq %cl, %rax 52 53 /* 54 * Multiply: guest_hz (%rdi) * scaling_factor (%rax) 55 * Result is in %rdx:%rax 56 */ 57 mulq %rdi 58 59 /* Divide: result by host_hz (%rsi) */ 60 divq %rsi 61 ret 62SET_SIZE(calc_freq_multiplier) 63 64 65/* 66 * scale_tsc: Scales a TSC value based on a frequency multiplier with 67 * FRAC_SIZE fractional bits. 68 * 69 * (tsc * multiplier) >> FRAC_SIZE 70 * 71 * 72 * uint64_t scale_tsc(uint64_t tsc, uint64_t multiplier, uint32_t frac_size) 73 * %rdi: uint64_t tsc 74 * %rsi: uint64_t multiplier 75 * %edx: uint32_t frac_size 76 */ 77ENTRY_NP(scale_tsc) 78 /* Save `frac_size` */ 79 mov %edx, %ecx 80 81 /* 82 * Multiply tsc (%rdi) * multiplier (%rsi) 83 * mulq result is in %rdx:%rax 84 */ 85 movq %rdi, %rax 86 mulq %rsi 87 88 /* 89 * Shift the 128-bit product right `frac_size` bits: 90 * - shift lower 64 bits right, `frac_size` bits 91 * - shift upper 64 bits left, (64 - `frac_size`) bits 92 * - bitwise OR upper bits and lower bits 93 */ 94 95 /* Shift lower 64 bits right `frac_size` */ 96 shrq %cl, %rax 97 98 /* Compute 64 - FRAC_SIZE and store result in %cl */ 99 movl %ecx, %r9d 100 movl $64, %ecx 101 subl %r9d, %ecx 102 103 /* Shift upper 64 bits left, (64 - `frac_size`) bits */ 104 shlq %cl, %rdx 105 106 /* Bitwise OR upper and lower bits */ 107 orq %rdx, %rax 108 109 ret 110SET_SIZE(scale_tsc) 111