• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Dump CPUID information
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <com32.h>
9 #include <sys/cpu.h>
10 #include "sysdump.h"
11 
12 struct cpuid_data {
13     uint32_t eax, ebx, ecx, edx;
14 };
15 
16 struct cpuid_info {
17     uint32_t eax, ecx;
18     struct cpuid_data data;
19 };
20 
get_cpuid(uint32_t eax,uint32_t ecx,struct cpuid_data * data)21 static void get_cpuid(uint32_t eax, uint32_t ecx, struct cpuid_data *data)
22 {
23 #if __SIZEOF_POINTER__ == 4
24     asm("pushl %%ebx ; cpuid ; movl %%ebx,%1 ; popl %%ebx"
25 	: "=a" (data->eax), "=r" (data->ebx),
26 	  "=c" (data->ecx), "=d" (data->edx)
27 	: "a" (eax), "c" (ecx));
28 #elif __SIZEOF_POINTER__ == 8
29         asm volatile("push %%rbx; cpuid; movl %%ebx, %1; pop %%rbx"
30             : "=a" (data->eax),
31               "=b" (data->ebx),
32               "=c" (data->ecx),
33               "=d" (data->edx)
34             : "a" (eax), "c" (ecx));
35 #else
36 #error "unsupported architecture"
37 #endif
38 }
39 
40 #define CPUID_CHUNK 128
41 
dump_cpuid(struct upload_backend * be)42 void dump_cpuid(struct upload_backend *be)
43 {
44     struct cpuid_info *buf = NULL;
45     int nentry, nalloc;
46     uint32_t region;
47     struct cpuid_data base_leaf;
48     uint32_t base, leaf, count;
49     struct cpuid_data invalid_leaf;
50     struct cpuid_data data;
51 
52     if (!cpu_has_eflag(EFLAGS_ID))
53 	return;
54 
55     printf("Dumping CPUID... ");
56 
57     nentry = nalloc = 0;
58 
59     /* Find out what the CPU returns for invalid leaves */
60     get_cpuid(0, 0, &base_leaf);
61     get_cpuid(base_leaf.eax+1, 0, &invalid_leaf);
62 
63     for (region = 0 ; region <= 0xffff ; region++) {
64 	base = region << 16;
65 
66 	get_cpuid(base, 0, &base_leaf);
67 	if (region && !memcmp(&base_leaf, &invalid_leaf, sizeof base_leaf))
68 	    continue;
69 
70 	if ((base_leaf.eax ^ base) & 0xffff0000)
71 	    continue;
72 
73 	for (leaf = base ; leaf <= base_leaf.eax ; leaf++) {
74 	    get_cpuid(leaf, 0, &data);
75 	    count = 0;
76 
77 	    do {
78 		if (nentry >= nalloc) {
79 		    nalloc += CPUID_CHUNK;
80 		    buf = realloc(buf, nalloc*sizeof *buf);
81 		    if (!buf)
82 			return;		/* FAILED */
83 		}
84 		buf[nentry].eax = leaf;
85 		buf[nentry].ecx = count;
86 		buf[nentry].data = data;
87 		nentry++;
88 		count++;
89 
90 		get_cpuid(leaf, count, &data);
91 	    } while (memcmp(&data, &buf[nentry-1].data, sizeof data) &&
92 		     (data.eax | data.ebx | data.ecx | data.edx));
93 	}
94     }
95 
96     if (nentry)
97 	cpio_writefile(be, "cpuid", buf, nentry*sizeof *buf);
98     free(buf);
99 
100     printf("done.\n");
101 }
102