1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/types.h>
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <unistd.h>
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h>
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h>
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h>
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/header.h"
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline void
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengcpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng      unsigned int *d)
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	__asm__ __volatile__ (".byte 0x53\n\tcpuid\n\t"
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			      "movl %%ebx, %%esi\n\t.byte 0x5b"
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			: "=a" (*a),
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			"=S" (*b),
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			"=c" (*c),
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			"=d" (*d)
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			: "a" (op));
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengget_cpuid(char *buffer, size_t sz)
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned int a, b, c, d, lvl;
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int family = -1, model = -1, step = -1;
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int nb;
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char vendor[16];
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	cpuid(0, &lvl, &b, &c, &d);
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	strncpy(&vendor[0], (char *)(&b), 4);
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	strncpy(&vendor[4], (char *)(&d), 4);
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	strncpy(&vendor[8], (char *)(&c), 4);
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	vendor[12] = '\0';
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (lvl >= 1) {
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		cpuid(1, &a, &b, &c, &d);
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		family = (a >> 8) & 0xf;  /* bits 11 - 8 */
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		model  = (a >> 4) & 0xf;  /* Bits  7 - 4 */
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		step   = a & 0xf;
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* extended family */
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (family == 0xf)
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			family += (a >> 20) & 0xff;
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* extended model */
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (family >= 0x6)
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			model += ((a >> 16) & 0xf) << 4;
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	nb = scnprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* look for end marker to ensure the entire data fit */
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (strchr(buffer, '$')) {
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		buffer[nb-1] = '\0';
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
60