Home | History | Annotate | Line # | Download | only in x86
      1 /*	$NetBSD: procfs_machdep.c,v 1.49 2024/10/06 15:36:05 msaitoh Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2001 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Frank van der Linden and Jason R. Thorpe for
      8  * Wasabi Systems, Inc.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *      This product includes software developed for the NetBSD Project by
     21  *      Wasabi Systems, Inc.
     22  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     23  *    or promote products derived from this software without specific prior
     24  *    written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * NOTE: We simply use the primary CPU's cpuid_level and tsc_freq
     41  * here.  Might want to change this later.
     42  */
     43 
     44 #include <sys/cdefs.h>
     45 __KERNEL_RCSID(0, "$NetBSD: procfs_machdep.c,v 1.49 2024/10/06 15:36:05 msaitoh Exp $");
     46 
     47 #include <sys/param.h>
     48 #include <sys/systm.h>
     49 #include <sys/mount.h>
     50 #include <sys/stat.h>
     51 #include <sys/vnode.h>
     52 
     53 #include <miscfs/procfs/procfs.h>
     54 
     55 #include <machine/cpu.h>
     56 #include <machine/reg.h>
     57 #include <machine/specialreg.h>
     58 #include <x86/cputypes.h>
     59 #include <x86/cpuvar.h>
     60 
     61 /*
     62  *  The feature table. The order is the same as Linux's
     63  *  x86/include/asm/cpufeatures.h.
     64  */
     65 static const char * const x86_features[][32] = {
     66 	{ /* (0) Common: 0x0000001 edx */
     67 	"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
     68 	"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
     69 	"pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
     70 	"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe"},
     71 
     72 	{ /* (1) AMD-defined: 0x80000001 edx */
     73 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
     74 	NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
     75 	NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
     76 	NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext","3dnow"},
     77 
     78 	{ /* (2) Transmeta-defined */
     79 	"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
     80 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
     81 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
     82 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
     83 
     84 	{ /* (3) Linux mapping */
     85 	"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL,
     86 	"constant_tsc", "up", "art", "arch_perfmon",
     87 	"pebs", "bts", NULL, NULL,
     88 	"rep_good", NULL, NULL, "acc_power",
     89 	"nopl", NULL, "xtopology", "tsc_reliable",
     90 	"nonstop_tsc", "cpuid", "extd_apicid", "amd_dcm",
     91 	"aperfmperf", "rapl", "nonstop_tsc_s3", "tsc_known_freq"},
     92 
     93 	{ /* (4) Intel-defined: 0x00000001 ecx */
     94 	"pni", "pclmulqdq", "dtes64", "monitor", "ds_cpl", "vmx", "smx", "est",
     95 	"tm2", "ssse3", "cid", "sdbg", "fma", "cx16", "xtpr", "pdcm",
     96 	NULL, "pcid", "dca", "sse4_1", "sse4_2", "x2apic", "movbe", "popcnt",
     97 	"tsc_deadline_timer", "aes", "xsave", NULL,
     98 	"avx", "f16c", "rdrand", "hypervisor"},
     99 
    100 	{ /* (5) VIA/Cyrix/Centaur-defined */
    101 	NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
    102 	"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
    103 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    104 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    105 
    106 	{ /* (6) AMD defined 80000001 ecx */
    107 	"lahf_lm", "cmp_legacy", "svm", "extapic",
    108 	"cr8_legacy", "abm", "sse4a", "misalignsse",
    109 	"3dnowprefetch", "osvw", "ibs", "xop", "skinit", "wdt", NULL, "lwp",
    110 	"fma4", "tce", NULL, "nodeid_msr",
    111 	NULL, "tbm", "topoext", "perfctr_core",
    112 	"perfctr_nb", NULL, "bpext", "ptsc",
    113 	"perfctr_llc", "mwaitx", NULL, NULL},
    114 
    115 	{ /* (7) Linux mapping */
    116 	"ring3mwait", "cpuid_fault", "cpb", "epb",
    117 	"cat_l3", "cat_l2", "cdp_l3", "invpcid_single",
    118 	"hw_pstate", "proc_feedback", NULL, "pti",
    119 	NULL, NULL, "intel_ppin", "cdp_l2",
    120 	NULL, "ssbd", "mba", NULL, "perfmon_v2", NULL, NULL, NULL,
    121 	NULL, "ibrs", "ibpb", "stibp", NULL, NULL, "ibrs_enhanced", NULL},
    122 
    123 	{ /* (8) Linux mapping */
    124 	"tpr_shadow", "flexpriority", "ept", "vpid", NULL, NULL, NULL, NULL,
    125 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, "vmmcall",
    126 	NULL, "ept_ad", NULL, NULL, NULL, NULL, "tdx_guest", NULL,
    127 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    128 
    129 	{ /* (9) Intel-defined: 00000007 ebx */
    130 	"fsgsbase", "tsc_adjust", "sgx", "bmi1", "hle", "avx2", NULL, "smep",
    131 	"bmi2", "erms", "invpcid", "rtm", "cqm", NULL, "mpx", "rdt_a",
    132 	"avx512f", "avx512dq", "rdseed", "adx",
    133 	"smap", "avx512ifma", NULL, "clflushopt",
    134 	"clwb", "intel_pt", "avx512pf", "avx512er",
    135 	"avx512cd", "sha_ni", "avx512bw", "avx512vl"},
    136 
    137 	{ /* (10) 0x0000000d:1 eax */
    138 	"xsaveopt", "xsavec", "xgetbv1", "xsaves", NULL, NULL, NULL, NULL,
    139 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    140 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    141 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    142 
    143 	{ /* (11) Linux mapping */
    144 	"cqm_llc", "cqm_occup_llc", "cqm_mbm_total", "cqm_mbm_local",
    145 	NULL, NULL, "split_lock_detect", NULL,
    146 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    147 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    148 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    149 
    150 	{ /* (12) Intel-defined 0x00000007:1 eax */
    151 	NULL, NULL, NULL, NULL,
    152 	"avx_vnni", "avx512_bf16", NULL, NULL,
    153 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    154 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    155 	NULL, NULL, "lam", NULL, NULL, NULL, NULL, NULL},
    156 
    157 	{ /* (13) AMD 0x80000008 ebx */
    158 	"clzero", "irperf", "xsaveerptr", NULL, "rdpru", NULL, NULL, NULL,
    159 	NULL, "wbnoinvd", NULL, NULL, NULL, NULL, NULL, NULL,
    160 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, "ppin",
    161 	NULL, "virt_ssbd", NULL, "cppc", NULL, NULL, NULL, "brs"},
    162 
    163 	{ /* (14) 0x00000006 eax */
    164 	"dtherm", "ida", "arat", NULL, "pln", NULL, "pts", "hwp",
    165 	"hwp_notify", "hwp_act_window", "hwp_epp","hwp_pkg_req",
    166 	NULL, NULL, NULL, NULL,
    167 	NULL, NULL, NULL, "hfi", NULL, NULL, NULL, NULL,
    168 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    169 
    170 	{ /* (15) AMD 0x8000000a edx */
    171 	"npt", "lbrv", "svm_lock", "nrip_save",
    172 	"tsc_scale", "vmcb_clean", "flushbyasid", "decodeassists",
    173 	NULL, NULL, "pausefilter", NULL, "pfthreshold", "avic", NULL,
    174 	"v_vmsave_vmload",
    175 	"vgif", NULL, "x2avic", NULL, "v_spec_ctrl", NULL, NULL, NULL,
    176 	NULL, "vnmi", NULL, NULL, NULL, NULL, NULL, NULL},
    177 
    178 	{ /* (16) 0x00000007:0 ecx */
    179 	NULL, "avx512vbmi", "umip", "pku",
    180 	"ospke", "waitpkg", "avx512_vbmi2", NULL,
    181 	"gfni", "vaes", "vpclmulqdq", "avx512_vnni",
    182 	"avx512_bitalg", "tme", "avx512_vpopcntdq", NULL,
    183 	"la57", NULL, NULL, NULL, NULL, NULL, "rdpid", NULL,
    184 	NULL, "cldemote", NULL, "movdiri",
    185 	"movdir64b", "enqcmd", "sgx_lc", NULL},
    186 
    187 	{ /* (17) AMD 0x80000007 ebx */
    188 	"overflow_recov", "succor", NULL, "smca", NULL, NULL, NULL, NULL,
    189 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    190 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    191 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    192 
    193 	{ /* (18) Intel 0x00000007 edx */
    194 	NULL, NULL, "avx512_4vnniw", "avx512_4fmaps", "fsrm", NULL, NULL, NULL,
    195 	"vp2intersect", NULL, "md_clear", NULL, NULL, NULL, "serialize", NULL,
    196 	"tsxldtrk", NULL, "pconfig", "arch_lbr",
    197 	"ibt", NULL, "amx_bf16", "avx512_fp16",
    198 	"amx_tile", "amx_int8", NULL, NULL,
    199 	"flush_l1d", "arch_capabilities", NULL, NULL},
    200 
    201 	{ /* (19) AMD 0x8000001f eax */
    202 	"sme", "sev", NULL, "sev_es", NULL, NULL, NULL, NULL,
    203 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    204 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    205 	NULL, NULL, NULL, NULL, "svsm", NULL, NULL, NULL},
    206 };
    207 
    208 static int	procfs_getonecpu(int, struct cpu_info *, char *, size_t *);
    209 
    210 /*
    211  * Linux-style /proc/cpuinfo.
    212  * Only used when procfs is mounted with -o linux.
    213  *
    214  * In the multiprocessor case, this should be a loop over all CPUs.
    215  */
    216 int
    217 procfs_getcpuinfstr(char *bf, size_t *len)
    218 {
    219 	struct cpu_info *ci;
    220 	CPU_INFO_ITERATOR cii;
    221 	size_t i, total, size, used;
    222 
    223 	i = total = 0;
    224 	used = size = *len;
    225 
    226 	for (CPU_INFO_FOREACH(cii, ci)) {
    227 		procfs_getonecpu(i++, ci, bf, &used);
    228 		total += used + 1;
    229 		if (used + 1 <= size) {
    230 			bf += used;
    231 			*bf++ = '\n';
    232 			size -= used + 1;
    233 			used = size;
    234 		} else
    235 			used = 0;
    236 	}
    237 	size = *len;
    238 	*len = total;
    239 	return size < *len ? -1 : 0;
    240 }
    241 
    242 static int
    243 procfs_getonefeatreg(uint32_t reg, const char * const *table, char *p,
    244     size_t *left)
    245 {
    246 	size_t l;
    247 
    248 	for (size_t i = 0; i < 32; i++) {
    249 		if ((reg & (1U << i)) && table[i]) {
    250 			l = snprintf(p, *left, "%s ", table[i]);
    251 			if (l < *left) {
    252 				*left -= l;
    253 				p += l;
    254 			} else
    255 				break;
    256 		}
    257 	}
    258 
    259 	return 0; /* XXX */
    260 }
    261 
    262 /*
    263  * Print feature bits. The code assume that unused entry of x86_features[]
    264  * is zero-cleared.
    265  *
    266  * XXX This function will be rewritten when all of linux entries are
    267  * decoded.
    268  */
    269 static int
    270 procfs_getonecpufeatures(struct cpu_info *ci, char *p, size_t *left)
    271 {
    272 	size_t last = *left;
    273 	size_t diff;
    274 	u_int descs[4];
    275 
    276 	procfs_getonefeatreg(ci->ci_feat_val[0], x86_features[0], p, left);
    277 	diff = last - *left;
    278 
    279 	procfs_getonefeatreg(ci->ci_feat_val[2], x86_features[1], p + diff,
    280 	    left);
    281 	diff = last - *left;
    282 
    283 	/* x86_features[2] is for Transmeta */
    284 	/* x86_features[3] is Linux defined mapping */
    285 
    286 	procfs_getonefeatreg(ci->ci_feat_val[1], x86_features[4], p + diff,
    287 	    left);
    288 	diff = last - *left;
    289 
    290 	procfs_getonefeatreg(ci->ci_feat_val[4], x86_features[5], p + diff,
    291 	    left);
    292 	diff = last - *left;
    293 
    294 	procfs_getonefeatreg(ci->ci_feat_val[3], x86_features[6], p + diff,
    295 	    left);
    296 	diff = last - *left;
    297 
    298 	/* x86_features[7] is Linux defined mapping */
    299 	/* x86_features[8] is Linux defined mapping */
    300 
    301 	procfs_getonefeatreg(ci->ci_feat_val[5], x86_features[9], p + diff,
    302 	    left);
    303 	diff = last - *left;
    304 
    305 	if (ci->ci_max_cpuid >= 0x0d) {
    306 		x86_cpuid2(0x0d, 1, descs);
    307 		procfs_getonefeatreg(descs[0], x86_features[10], p + diff,
    308 		    left);
    309 		diff = last - *left;
    310 	}
    311 
    312 	/* x86_features[11] is Linux defined mapping */
    313 
    314 	if (ci->ci_max_cpuid >= 0x07) {
    315 		x86_cpuid2(0x07, 1, descs);
    316 		procfs_getonefeatreg(descs[0], x86_features[12], p + diff,
    317 		    left);
    318 		diff = last - *left;
    319 	}
    320 
    321 	if ((cpu_vendor == CPUVENDOR_AMD)
    322 	    && (ci->ci_max_ext_cpuid >= 0x80000008)) {
    323 		x86_cpuid(0x80000008, descs);
    324 		procfs_getonefeatreg(descs[1], x86_features[13], p + diff,
    325 		    left);
    326 		diff = last - *left;
    327 	}
    328 
    329 	if (ci->ci_max_cpuid >= 0x06) {
    330 		x86_cpuid(0x06, descs);
    331 		procfs_getonefeatreg(descs[0], x86_features[14], p + diff,
    332 		    left);
    333 		diff = last - *left;
    334 	}
    335 
    336 	if ((cpu_vendor == CPUVENDOR_AMD)
    337 	    && (ci->ci_max_ext_cpuid >= 0x8000000a)) {
    338 		x86_cpuid(0x8000000a, descs);
    339 		procfs_getonefeatreg(descs[3], x86_features[15], p + diff,
    340 		    left);
    341 		diff = last - *left;
    342 	}
    343 
    344 	procfs_getonefeatreg(ci->ci_feat_val[6], x86_features[16], p + diff,
    345 	    left);
    346 	diff = last - *left;
    347 
    348 	if ((cpu_vendor == CPUVENDOR_AMD)
    349 	    && (ci->ci_max_ext_cpuid >= 0x80000007)) {
    350 		x86_cpuid(0x80000007, descs);
    351 		procfs_getonefeatreg(descs[1], x86_features[17], p + diff,
    352 		    left);
    353 		diff = last - *left;
    354 	}
    355 
    356 	if ((cpu_vendor == CPUVENDOR_INTEL)
    357 	    && (ci->ci_max_cpuid >= 0x00000007)) {
    358 		x86_cpuid(0x00000007, descs);
    359 		procfs_getonefeatreg(descs[3], x86_features[18], p + diff,
    360 		    left);
    361 		diff = last - *left;
    362 	}
    363 
    364 	if ((cpu_vendor == CPUVENDOR_AMD)
    365 	    && (ci->ci_max_ext_cpuid >= 0x80000019)) {
    366 		x86_cpuid(0x8000001f, descs);
    367 		procfs_getonefeatreg(descs[0], x86_features[19], p + diff,
    368 		    left);
    369 		diff = last - *left;
    370 	}
    371 
    372 	return 0; /* XXX */
    373 }
    374 
    375 static int
    376 procfs_getonecpu(int xcpu, struct cpu_info *ci, char *bf, size_t *len)
    377 {
    378 	size_t left, l, size;
    379 	char featurebuf[1024], *p;
    380 
    381 	p = featurebuf;
    382 	left = sizeof(featurebuf);
    383 	size = *len;
    384 	procfs_getonecpufeatures(ci, p, &left);
    385 
    386 	p = bf;
    387 	left = *len;
    388 	size = 0;
    389 	l = snprintf(p, left,
    390 	    "processor\t: %d\n"
    391 	    "vendor_id\t: %s\n"
    392 	    "cpu family\t: %d\n"
    393 	    "model\t\t: %d\n"
    394 	    "model name\t: %s\n"
    395 	    "stepping\t: ",
    396 	    xcpu,
    397 	    (char *)ci->ci_vendor,
    398 	    CPUID_TO_FAMILY(ci->ci_signature),
    399 	    CPUID_TO_MODEL(ci->ci_signature),
    400 	    cpu_brand_string
    401 	);
    402 	size += l;
    403 	if (l < left) {
    404 		left -= l;
    405 		p += l;
    406 	} else
    407 		left = 0;
    408 
    409 	if (cpuid_level >= 0)
    410 		l = snprintf(p, left, "%d\n",
    411 		    CPUID_TO_STEPPING(ci->ci_signature));
    412 	else
    413 		l = snprintf(p, left, "unknown\n");
    414 
    415 	size += l;
    416 	if (l < left) {
    417 		left -= l;
    418 		p += l;
    419 	} else
    420 		left = 0;
    421 
    422 	if (ci->ci_data.cpu_cc_freq != 0) {
    423 		uint64_t freq, fraq;
    424 
    425 		freq = (ci->ci_data.cpu_cc_freq + 4999) / 1000000;
    426 		fraq = ((ci->ci_data.cpu_cc_freq + 4999) / 10000) % 100;
    427 		l = snprintf(p, left, "cpu MHz\t\t: %" PRIu64 ".%02" PRIu64
    428 		    "\n", freq, fraq);
    429 	} else
    430 		l = snprintf(p, left, "cpu MHz\t\t: unknown\n");
    431 
    432 	size += l;
    433 	if (l < left) {
    434 		left -= l;
    435 		p += l;
    436 	} else
    437 		left = 0;
    438 
    439 	l = snprintf(p, left,
    440 	    "apicid\t\t: %lu\n"
    441 	    "initial apicid\t: %u\n",
    442 	    ci->ci_cpuid,
    443 	    ci->ci_initapicid
    444 	);
    445 	size += l;
    446 	if (l < left) {
    447 		left -= l;
    448 		p += l;
    449 	} else
    450 		left = 0;
    451 
    452 	l = snprintf(p, left,
    453 #ifdef __i386__
    454 	    "fdiv_bug\t: %s\n"
    455 #endif
    456 	    "fpu\t\t: yes\n"
    457 	    "fpu_exception\t: yes\n"
    458 	    "cpuid level\t: %d\n"
    459 	    "wp\t\t: %s\n"
    460 	    "flags\t\t: %s\n"
    461 	    "clflush size\t: %d\n",
    462 #ifdef __i386__
    463 	    i386_fpu_fdivbug ? "yes" : "no",	/* an old pentium */
    464 #endif
    465 	    ci->ci_max_cpuid,
    466 	    (rcr0() & CR0_WP) ? "yes" : "no",
    467 	    featurebuf,
    468 	    ci->ci_cflush_lsize
    469 	);
    470 	size += l;
    471 
    472 	left = *len;
    473 	*len = size;
    474 	return left < *len ? -1 : 0;
    475 }
    476 
    477 #if defined(__HAVE_PROCFS_MACHDEP) && !defined(__x86_64__)
    478 
    479 void
    480 procfs_machdep_allocvp(struct vnode *vp)
    481 {
    482 	struct pfsnode *pfs = vp->v_data;
    483 
    484 	switch (pfs->pfs_type) {
    485 	case Pmachdep_xmmregs:
    486 		/* /proc/N/xmmregs = -rw------- */
    487 		pfs->pfs_mode = S_IRUSR|S_IWUSR;
    488 		vp->v_type = VREG;
    489 		break;
    490 	default:
    491 		KASSERT(false);
    492 	}
    493 }
    494 
    495 int
    496 procfs_machdep_rw(struct lwp *curl, struct lwp *l, struct pfsnode *pfs,
    497     struct uio *uio)
    498 {
    499 
    500 	switch (pfs->pfs_type) {
    501 	case Pmachdep_xmmregs:
    502 		return (procfs_machdep_doxmmregs(curl, l, pfs, uio));
    503 	default:
    504 		KASSERT(false);
    505 	}
    506 	return EINVAL;
    507 }
    508 
    509 int
    510 procfs_machdep_getattr(struct vnode *vp, struct vattr *vap, struct proc *procp)
    511 {
    512 	struct pfsnode *pfs = VTOPFS(vp);
    513 
    514 	switch (pfs->pfs_type) {
    515 	case Pmachdep_xmmregs:
    516 		vap->va_bytes = vap->va_size = sizeof(struct xmmregs);
    517 		break;
    518 	default:
    519 		KASSERT(false);
    520 	}
    521 	return 0;
    522 }
    523 
    524 int
    525 procfs_machdep_doxmmregs(struct lwp *curl, struct lwp *l,
    526     struct pfsnode *pfs, struct uio *uio)
    527 {
    528 
    529 	return process_machdep_doxmmregs(curl, l, uio);
    530 }
    531 
    532 int
    533 procfs_machdep_validxmmregs(struct lwp *l, struct mount *mp)
    534 {
    535 
    536 	return process_machdep_validxmmregs(l->l_proc);
    537 }
    538 
    539 #endif
    540