12428aad8SPatrick Mooney/* 22428aad8SPatrick Mooney * This file and its contents are supplied under the terms of the 32428aad8SPatrick Mooney * Common Development and Distribution License ("CDDL"), version 1.0. 42428aad8SPatrick Mooney * You may only use this file in accordance with the terms of version 52428aad8SPatrick Mooney * 1.0 of the CDDL. 62428aad8SPatrick Mooney * 72428aad8SPatrick Mooney * A full copy of the text of the CDDL should have accompanied this 82428aad8SPatrick Mooney * source. A copy of the CDDL is also available via the Internet at 92428aad8SPatrick Mooney * http://www.illumos.org/license/CDDL. 102428aad8SPatrick Mooney */ 112428aad8SPatrick Mooney 122428aad8SPatrick Mooney/* 13e121b61fSPatrick Mooney * Copyright 2019 Joyent, Inc. 14beed421eSPatrick Mooney * Copyright 2020 Oxide Computer Company 152428aad8SPatrick Mooney */ 162428aad8SPatrick Mooney 172428aad8SPatrick Mooney#include <sys/asm_linkage.h> 182428aad8SPatrick Mooney#include <sys/segments.h> 192428aad8SPatrick Mooney#include <sys/time_impl.h> 202428aad8SPatrick Mooney#include <sys/tsc.h> 212428aad8SPatrick Mooney#include <cp_offsets.h> 222428aad8SPatrick Mooney 232428aad8SPatrick Mooney#define GETCPU_GDT_OFFSET SEL_GDT(GDT_CPUID, SEL_UPL) 242428aad8SPatrick Mooney 25e121b61fSPatrick Mooney/* 26e121b61fSPatrick Mooney * For __cp_tsc_read calls which incur looping retries due to CPU migration, 27e121b61fSPatrick Mooney * this represents the maximum number of tries before bailing out. 28e121b61fSPatrick Mooney */ 29e121b61fSPatrick Mooney#define TSC_READ_MAXLOOP 0x4 30e121b61fSPatrick Mooney 312428aad8SPatrick Mooney .file "cp_subr.s" 322428aad8SPatrick Mooney 332428aad8SPatrick Mooney/* 342428aad8SPatrick Mooney * hrtime_t 35e121b61fSPatrick Mooney * __cp_tsc_read(comm_page_t *cp) 362428aad8SPatrick Mooney * 372428aad8SPatrick Mooney * Stack usage: 0x18 bytes 38e121b61fSPatrick Mooney * 39e121b61fSPatrick Mooney * %ebp-0x00 - frame pointer 40e121b61fSPatrick Mooney * %ebp-0x04 - saved %edi 41e121b61fSPatrick Mooney * %ebp-0x08 - saved %esi 42e121b61fSPatrick Mooney * %ebp-0x0c - CPU ID 43e121b61fSPatrick Mooney * %ebp-0x10 - loop count 44e121b61fSPatrick Mooney * %ebp-0x14 - saved %ebx (during cpuid) 452428aad8SPatrick Mooney */ 462428aad8SPatrick Mooney ENTRY_NP(__cp_tsc_read) 472428aad8SPatrick Mooney pushl %ebp 482428aad8SPatrick Mooney movl %esp, %ebp 492428aad8SPatrick Mooney pushl %edi 502428aad8SPatrick Mooney pushl %esi 51e121b61fSPatrick Mooney subl $0x8, %esp 522428aad8SPatrick Mooney 532428aad8SPatrick Mooney movl 0x8(%ebp), %edi 542428aad8SPatrick Mooney movl CP_TSC_TYPE(%edi), %eax 552428aad8SPatrick Mooney movl CP_TSC_NCPU(%edi), %esi 562428aad8SPatrick Mooney cmpl $TSC_TSCP, %eax 572428aad8SPatrick Mooney jne 3f 582428aad8SPatrick Mooney rdtscp 592428aad8SPatrick Mooney cmpl $0, %esi 602428aad8SPatrick Mooney jne 2f 612428aad8SPatrick Mooney1: 62e121b61fSPatrick Mooney addl $0x8, %esp 632428aad8SPatrick Mooney popl %esi 642428aad8SPatrick Mooney popl %edi 652428aad8SPatrick Mooney leave 662428aad8SPatrick Mooney ret 672428aad8SPatrick Mooney2: 682428aad8SPatrick Mooney /* 692428aad8SPatrick Mooney * When cp_tsc_ncpu is non-zero, it indicates the length of the 702428aad8SPatrick Mooney * cp_tsc_sync_tick_delta array, which contains per-CPU offsets for the 712428aad8SPatrick Mooney * TSC. The CPU ID furnished by the IA32_TSC_AUX register via rdtscp 722428aad8SPatrick Mooney * is used to look up an offset value in that array and apply it to the 732428aad8SPatrick Mooney * TSC reading. 742428aad8SPatrick Mooney */ 752428aad8SPatrick Mooney leal CP_TSC_SYNC_TICK_DELTA(%edi), %esi 762428aad8SPatrick Mooney leal (%esi, %ecx, 8), %ecx 772428aad8SPatrick Mooney addl (%ecx), %eax 782428aad8SPatrick Mooney adcl 0x4(%ecx), %edx 792428aad8SPatrick Mooney jmp 1b 802428aad8SPatrick Mooney 812428aad8SPatrick Mooney3: 82e121b61fSPatrick Mooney testl %esi, %esi 83e121b61fSPatrick Mooney jz 4f 84e121b61fSPatrick Mooney 85e121b61fSPatrick Mooney movl $0, (%esp) 862428aad8SPatrick Mooney mov $GETCPU_GDT_OFFSET, %eax 873cc24548SToomas Soome lsl %eax, %eax 88e121b61fSPatrick Mooney movl %eax, 0x4(%esp) 892428aad8SPatrick Mooney movl CP_TSC_TYPE(%edi), %eax 902428aad8SPatrick Mooney 912428aad8SPatrick Mooney4: 92beed421eSPatrick Mooney /* 93beed421eSPatrick Mooney * TSC_RDTSC_MFENCE was used in the past for AMD chips, but has been 94beed421eSPatrick Mooney * supplanted by TSC_RDTSC_LFENCE, which works on Intel and AMD (when 95beed421eSPatrick Mooney * lfence can be confirmed as serializing). 96beed421eSPatrick Mooney */ 972428aad8SPatrick Mooney 982428aad8SPatrick Mooney5: 992428aad8SPatrick Mooney cmpl $TSC_RDTSC_LFENCE, %eax 1002428aad8SPatrick Mooney jne 6f 1012428aad8SPatrick Mooney lfence 1022428aad8SPatrick Mooney rdtsc 1032428aad8SPatrick Mooney jmp 8f 1042428aad8SPatrick Mooney 1052428aad8SPatrick Mooney6: 1062428aad8SPatrick Mooney cmpl $TSC_RDTSC_CPUID, %eax 1072428aad8SPatrick Mooney jne 7f 1082428aad8SPatrick Mooney pushl %ebx 1092428aad8SPatrick Mooney xorl %eax, %eax 1102428aad8SPatrick Mooney cpuid 1112428aad8SPatrick Mooney rdtsc 1122428aad8SPatrick Mooney popl %ebx 1132428aad8SPatrick Mooney jmp 8f 1142428aad8SPatrick Mooney 1152428aad8SPatrick Mooney7: 1162428aad8SPatrick Mooney /* 1172428aad8SPatrick Mooney * Other protections should have prevented this function from being 118e121b61fSPatrick Mooney * called in the first place. Since callers must handle a failure from 119e121b61fSPatrick Mooney * CPU migration looping, yield the same result as a bail-out: 0 1202428aad8SPatrick Mooney */ 121e121b61fSPatrick Mooney xorl %eax, %eax 122e121b61fSPatrick Mooney xorl %edx, %edx 123e121b61fSPatrick Mooney jmp 1b 1242428aad8SPatrick Mooney 1252428aad8SPatrick Mooney8: 1262428aad8SPatrick Mooney 1272428aad8SPatrick Mooney cmpl $0, %esi 1282428aad8SPatrick Mooney je 1b 1292428aad8SPatrick Mooney /* 1302428aad8SPatrick Mooney * With a TSC reading in-hand, confirm that the thread has not migrated 1312428aad8SPatrick Mooney * since the cpu_id was first checked. 1322428aad8SPatrick Mooney */ 1332428aad8SPatrick Mooney movl $GETCPU_GDT_OFFSET, %ecx 1343cc24548SToomas Soome lsl %ecx, %ecx 135e121b61fSPatrick Mooney movl 0x4(%esp), %esi 1362428aad8SPatrick Mooney cmpl %ecx, %esi 137e121b61fSPatrick Mooney jne 9f 138e121b61fSPatrick Mooney 139e121b61fSPatrick Mooney /* Grab the per-cpu offset and add it to the TSC result */ 140e121b61fSPatrick Mooney leal CP_TSC_SYNC_TICK_DELTA(%edi), %esi 141e121b61fSPatrick Mooney leal (%esi, %ecx, 8), %ecx 142e121b61fSPatrick Mooney addl (%ecx), %eax 143e121b61fSPatrick Mooney adcl 0x4(%ecx), %edx 144e121b61fSPatrick Mooney jmp 1b 145e121b61fSPatrick Mooney 146e121b61fSPatrick Mooney9: 1472428aad8SPatrick Mooney /* 148e121b61fSPatrick Mooney * It appears that a migration has occurred between the first CPU ID 149e121b61fSPatrick Mooney * query and now. Check if the loop limit has been broken and retry if 150e121b61fSPatrick Mooney * that's not the case. 1512428aad8SPatrick Mooney */ 152e121b61fSPatrick Mooney movl (%esp), %eax 153e121b61fSPatrick Mooney cmpl $TSC_READ_MAXLOOP, %eax 154e121b61fSPatrick Mooney jge 10f 155e121b61fSPatrick Mooney 156e121b61fSPatrick Mooney incl %eax 1572428aad8SPatrick Mooney movl %eax, (%esp) 158e121b61fSPatrick Mooney movl %ecx, 0x4(%esp) 1592428aad8SPatrick Mooney movl CP_TSC_NCPU(%edi), %esi 1602428aad8SPatrick Mooney movl CP_TSC_TYPE(%edi), %eax 1612428aad8SPatrick Mooney jmp 4b 1622428aad8SPatrick Mooney 163e121b61fSPatrick Mooney10: 164e121b61fSPatrick Mooney /* Loop limit was reached. Return bail-out value of 0. */ 165e121b61fSPatrick Mooney xorl %eax, %eax 166e121b61fSPatrick Mooney xorl %edx, %edx 1672428aad8SPatrick Mooney jmp 1b 168e121b61fSPatrick Mooney 1692428aad8SPatrick Mooney SET_SIZE(__cp_tsc_read) 1702428aad8SPatrick Mooney 171e121b61fSPatrick Mooney/* 172e121b61fSPatrick Mooney * hrtime_t 173e121b61fSPatrick Mooney * __cp_gethrtime_fasttrap() 174e121b61fSPatrick Mooney */ 175e121b61fSPatrick Mooney ENTRY_NP(__cp_gethrtime_fasttrap) 176e121b61fSPatrick Mooney movl $T_GETHRTIME, %eax 177e121b61fSPatrick Mooney int $T_FASTTRAP 178e121b61fSPatrick Mooney ret 179e121b61fSPatrick Mooney SET_SIZE(__cp_gethrtime_fasttrap) 180e121b61fSPatrick Mooney 1812428aad8SPatrick Mooney/* 1822428aad8SPatrick Mooney * uint_t 1832428aad8SPatrick Mooney * __cp_getcpu(uint_t cp_tsc_type) 1842428aad8SPatrick Mooney */ 1852428aad8SPatrick Mooney ENTRY_NP(__cp_getcpu) 1862428aad8SPatrick Mooney /* 1872428aad8SPatrick Mooney * If RDTSCP is available, it is a quick way to grab the cpu_id which 1882428aad8SPatrick Mooney * is stored in the TSC_AUX MSR by the kernel. 1892428aad8SPatrick Mooney */ 1902428aad8SPatrick Mooney movl 4(%esp), %eax 1912428aad8SPatrick Mooney movl CP_TSC_TYPE(%eax), %eax 1922428aad8SPatrick Mooney cmpl $TSC_TSCP, %eax 1932428aad8SPatrick Mooney jne 1f 1942428aad8SPatrick Mooney rdtscp 1952428aad8SPatrick Mooney movl %ecx, %eax 1962428aad8SPatrick Mooney ret 1972428aad8SPatrick Mooney1: 1982428aad8SPatrick Mooney mov $GETCPU_GDT_OFFSET, %eax 1993cc24548SToomas Soome lsl %eax, %eax 2002428aad8SPatrick Mooney ret 2012428aad8SPatrick Mooney SET_SIZE(__cp_getcpu) 202