1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6# Copyright (c) 2017 Konstantin Belousov <kib@FreeBSD.org> 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30# Test scenario for "D12023: Make WRFSBASE and WRGSBASE functional." 31 32[ `uname -m` = "amd64" ] || exit 0 33 34. ../default.cfg 35 36cat > /tmp/rdgsbase.c <<EOF 37/* 38Below is the updated version of the test program. It is probably most 39useful to run it in parallel with the normal stress jobs. Please note 40that the program starts two CPU-intensive threads per core, so the 41whole test load would be run 4x slower. 42 43Also, it is very useful to try to run hwpmc measurements in parallel, at 44least for some time. E.g., 45 pmcstat -S instructions -T 46in a terminal in parallel with other activities is enough. I do not need 47any numbers from hwpmc, just the fact that the driver causes the series of 48NMI to adjust the load for testing. 49*/ 50 51/* $Id: rdgsbase.c,v 1.9 2017/08/13 16:22:01 kostik Exp kostik $ */ 52 53#include <sys/param.h> 54#include <sys/sysctl.h> 55#include <err.h> 56#include <pthread.h> 57#include <signal.h> 58#include <stdio.h> 59#include <stdlib.h> 60#include <unistd.h> 61#include <machine/sysarch.h> 62#include <machine/specialreg.h> 63#include <machine/cpufunc.h> 64 65void 66hand(int i __unused) { /* handler */ 67 _exit(0); 68} 69 70static void * 71rungs(void *arg __unused) 72{ 73 volatile char x[1024]; 74 unsigned i; 75 uint64_t y, oldbase; 76 77 oldbase = rdgsbase(); 78 for (i = 0;;) { 79 wrgsbase((uintptr_t)&x[i]); 80 if (rdgsbase() != (uintptr_t)&x[i]) { 81 wrgsbase(oldbase); 82 printf("bug1 %lx %lx\n", rdgsbase(), (uintptr_t)&x[i]); 83 exit(1); 84 } 85 sysarch(AMD64_GET_GSBASE, &y); 86 if (y != (uintptr_t)&x[i]) { 87 wrgsbase(oldbase); 88 printf("bug2 %lx %lx\n", y, (uintptr_t)&x[i]); 89 exit(1); 90 } 91 i++; 92 if (i >= nitems(x)) 93 i = 0; 94 } 95 return (NULL); 96} 97 98static void * 99runfs(void *arg __unused) 100{ 101 volatile char x[1024]; 102 unsigned i; 103 uint64_t y, oldbase; 104 105 oldbase = rdfsbase(); 106 for (i = 0;;) { 107 wrfsbase((uintptr_t)&x[i]); 108 if (rdfsbase() != (uintptr_t)&x[i]) { 109 wrfsbase(oldbase); 110 printf("bug3 %lx %lx\n", rdfsbase(), (uintptr_t)&x[i]); 111 exit(1); 112 } 113 sysarch(AMD64_GET_FSBASE, &y); 114 if (y != (uintptr_t)&x[i]) { 115 wrfsbase(oldbase); 116 printf("bug4 %lx %lx\n", y, (uintptr_t)&x[i]); 117 exit(1); 118 } 119 i++; 120 if (i > nitems(x)) 121 i = 0; 122 } 123 return (NULL); 124} 125 126static void 127start(int nthreads) 128{ 129 pthread_t thrs[nthreads * 2]; 130 int error, i; 131 132 for (i = 0; i < nthreads; i++) { 133 error = pthread_create(&thrs[i], NULL, rungs, NULL); 134 if (error != 0) 135 errc(1, error, "pthread_create"); 136 } 137 for (; i < 2 * nthreads; i++) { 138 error = pthread_create(&thrs[i], NULL, runfs, NULL); 139 if (error != 0) 140 errc(1, error, "pthread_create"); 141 } 142} 143 144int 145main(void) 146{ 147 static const int mib[2] = {CTL_HW, HW_NCPU}; 148 int error, nthreads; 149 u_int p[4]; 150 size_t len; 151 152 do_cpuid(0, p); 153 if (p[0] < 0x7) { 154 fprintf(stderr, "CPU does not support extended functions\n"); 155 return (1); 156 } 157 cpuid_count(0x7, 0x0, p); 158 if ((p[1] & CPUID_STDEXT_FSGSBASE) == 0) { 159 fprintf(stderr, "CPU does not support RDGSBASE\n"); 160 return (0); 161 } 162 163 len = sizeof(nthreads); 164 error = sysctl(mib, nitems(mib), &nthreads, &len, NULL, 0); 165 if (error == -1) 166 err(1, "sysctl hw.ncpu"); 167 signal(SIGALRM, hand); 168 alarm(10); 169 start(nthreads); 170 for (;;) 171 pause(); 172} 173EOF 174 175mycc -o /tmp/rdgsbase /tmp/rdgsbase.c -lpthread || exit 1 176rm /tmp/rdgsbase.c 177 178(cd /tmp; /tmp/rdgsbase) 179s=$? 180 181rm -f /tmp/rdgsbase /tmp/rdgsbase.core 182exit $s 183