blob: 943ebce048118ebb44470f6050cef22d9028110a [file] [log] [blame]
Stefan Reinauer03646be2008-05-13 22:14:21 +00001/*
2 * inteltool - dump all registers on an Intel CPU + chipset based system.
3 *
4 * Copyright (C) 2008 by coresystems GmbH
5 * written by Stefan Reinauer <stepan@coresystems.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <errno.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <stdint.h>
28#include <getopt.h>
29#include <sys/mman.h>
30#include <sys/io.h>
31#include <pci/pci.h>
32
33#define INTELTOOL_VERSION "1.0"
34
35/* Tested Chipsets: */
36#define PCI_VENDOR_ID_INTEL 0x8086
Stefan Reinauerb69e46b2008-05-14 11:38:22 +000037#define PCI_DEVICE_ID_INTEL_ICH 0x2410
38#define PCI_DEVICE_ID_INTEL_ICH0 0x2420
39#define PCI_DEVICE_ID_INTEL_ICH4 0x24c0
40#define PCI_DEVICE_ID_INTEL_ICH4M 0x24cc
Stefan Reinauer03646be2008-05-13 22:14:21 +000041#define PCI_DEVICE_ID_INTEL_ICH7 0x27b8
42#define PCI_DEVICE_ID_INTEL_82945GM 0x27a0
43
44#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
45
46int fd_mem;
47int fd_msr;
48
49typedef struct { uint32_t hi, lo; } msr_t;
50typedef struct { uint16_t addr; int size; char *name; } io_register_t;
51
Stefan Reinauerb69e46b2008-05-14 11:38:22 +000052
53static const io_register_t ich0_gpio_registers[] = {
54 { 0x00, 4, "GPIO_USE_SEL" },
55 { 0x04, 4, "GP_IO_SEL" },
56 { 0x08, 4, "RESERVED" },
57 { 0x0c, 4, "GP_LVL" },
58 { 0x10, 4, "RESERVED" },
59 { 0x14, 4, "GPO_TTL" },
60 { 0x18, 4, "GPO_BLINK" },
61 { 0x1c, 4, "RESERVED" },
62 { 0x20, 4, "RESERVED" },
63 { 0x24, 4, "RESERVED" },
64 { 0x28, 4, "RESERVED" },
65 { 0x2c, 4, "GPI_INV" },
66 { 0x30, 4, "RESERVED" },
67 { 0x34, 4, "RESERVED" },
68 { 0x38, 4, "RESERVED" },
69 { 0x3C, 4, "RESERVED" }
70};
71
72static const io_register_t ich4_gpio_registers[] = {
73 { 0x00, 4, "GPIO_USE_SEL" },
74 { 0x04, 4, "GP_IO_SEL" },
75 { 0x08, 4, "RESERVED" },
76 { 0x0c, 4, "GP_LVL" },
77 { 0x10, 4, "RESERVED" },
78 { 0x14, 4, "GPO_TTL" },
79 { 0x18, 4, "GPO_BLINK" },
80 { 0x1c, 4, "RESERVED" },
81 { 0x20, 4, "RESERVED" },
82 { 0x24, 4, "RESERVED" },
83 { 0x28, 4, "RESERVED" },
84 { 0x2c, 4, "GPI_INV" },
85 { 0x30, 4, "GPIO_USE_SEL2" },
86 { 0x34, 4, "GP_IO_SEL2" },
87 { 0x38, 4, "GP_LVL2" },
88 { 0x3C, 4, "RESERVED" }
89};
90
91static const io_register_t ich7_gpio_registers[] = {
92 { 0x00, 4, "GPIO_USE_SEL" },
93 { 0x04, 4, "GP_IO_SEL" },
94 { 0x08, 4, "RESERVED" },
95 { 0x0c, 4, "GP_LVL" },
96 { 0x10, 4, "RESERVED" },
97 { 0x14, 4, "RESERVED" },
98 { 0x18, 4, "GPO_BLINK" },
99 { 0x1c, 4, "RESERVED" },
100 { 0x20, 4, "RESERVED" },
101 { 0x24, 4, "RESERVED" },
102 { 0x28, 4, "RESERVED" },
103 { 0x2c, 4, "GPI_INV" },
104 { 0x30, 4, "GPIO_USE_SEL2" },
105 { 0x34, 4, "GP_IO_SEL2" },
106 { 0x38, 4, "GP_LVL2" },
107 { 0x3C, 4, "RESERVED" }
108};
109
Stefan Reinauer03646be2008-05-13 22:14:21 +0000110int print_gpios(struct pci_dev *sb)
111{
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000112 int i, size;
Stefan Reinauer03646be2008-05-13 22:14:21 +0000113 uint16_t gpiobase;
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000114 const io_register_t *gpio_registers;
Stefan Reinauer03646be2008-05-13 22:14:21 +0000115
116 printf("\n============= GPIOS =============\n\n");
117
118 switch (sb->device_id) {
119 case PCI_DEVICE_ID_INTEL_ICH7:
120 gpiobase = pci_read_word(sb, 0x48) & 0xfffc;
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000121 gpio_registers = ich7_gpio_registers;
122 size = ARRAY_SIZE(ich7_gpio_registers);
123 break;
124 case PCI_DEVICE_ID_INTEL_ICH4:
125 case PCI_DEVICE_ID_INTEL_ICH4M:
126 gpiobase = pci_read_word(sb, 0x58) & 0xfffc;
127 gpio_registers = ich4_gpio_registers;
128 size = ARRAY_SIZE(ich4_gpio_registers);
129 break;
130 case PCI_DEVICE_ID_INTEL_ICH:
131 case PCI_DEVICE_ID_INTEL_ICH0:
132 gpiobase = pci_read_word(sb, 0x58) & 0xfffc;
133 gpio_registers = ich0_gpio_registers;
134 size = ARRAY_SIZE(ich0_gpio_registers);
Stefan Reinauer03646be2008-05-13 22:14:21 +0000135 break;
136 case 0x1234: // Dummy for non-existent functionality
137 printf("Error: This southbridge does not have GPIOBASE.\n");
138 return 1;
139 default:
140 printf("Error: Dumping GPIOs on this southbridge is not (yet) supported.\n");
141 return 1;
142 }
143
144 printf("GPIOBASE = 0x%04x (IO)\n\n", gpiobase);
145
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000146 for (i=0; i<size; i++) {
147 switch (gpio_registers[i].size) {
Stefan Reinauer03646be2008-05-13 22:14:21 +0000148 case 4:
149 printf("gpiobase+0x%04x: 0x%08x (%s)\n",
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000150 gpio_registers[i].addr,
151 inl(gpiobase+gpio_registers[i].addr),
152 gpio_registers[i].name);
Stefan Reinauer03646be2008-05-13 22:14:21 +0000153 break;
154 case 2:
155 printf("gpiobase+0x%04x: 0x%04x (%s)\n",
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000156 gpio_registers[i].addr,
157 inw(gpiobase+gpio_registers[i].addr),
158 gpio_registers[i].name);
Stefan Reinauer03646be2008-05-13 22:14:21 +0000159 break;
160 case 1:
161 printf("gpiobase+0x%04x: 0x%02x (%s)\n",
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000162 gpio_registers[i].addr,
163 inb(gpiobase+gpio_registers[i].addr),
164 gpio_registers[i].name);
Stefan Reinauer03646be2008-05-13 22:14:21 +0000165 break;
166 }
167 }
168
169 return 0;
170}
171
172int print_rcba(struct pci_dev *sb)
173{
174 int i, size=0x4000;
175 volatile uint8_t *rcba;
176 uint32_t rcba_phys;
177
178 printf("\n============= RCBA ==============\n\n");
179
180 switch (sb->device_id) {
181 case PCI_DEVICE_ID_INTEL_ICH7:
182 rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe;
183 break;
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000184 case PCI_DEVICE_ID_INTEL_ICH:
185 case PCI_DEVICE_ID_INTEL_ICH0:
186 case PCI_DEVICE_ID_INTEL_ICH4:
187 case PCI_DEVICE_ID_INTEL_ICH4M:
Stefan Reinauer03646be2008-05-13 22:14:21 +0000188 printf("Error: This southbridge does not have RCBA.\n");
189 return 1;
190 default:
191 printf("Error: Dumping RCBA on this southbridge is not (yet) supported.\n");
192 return 1;
193 }
194
195 rcba = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
196 fd_mem, (off_t) rcba_phys);
197
198 if (rcba == MAP_FAILED) {
199 perror("Error mapping RCBA");
200 exit(1);
201 }
202
203 printf("RCBA = 0x%08x (MEM)\n\n", rcba_phys);
204
205 for (i=0; i<size; i+=4) {
206 if(*(uint32_t *)(rcba+i))
207 printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(rcba+i));
208 }
209
210 munmap((void *) rcba, size);
211 return 0;
212}
213
214int print_pmbase(struct pci_dev *sb)
215{
216 int i, size=0x80;
217 uint16_t pmbase;
218
219 printf("\n============= PMBASE ============\n\n");
220
221 switch (sb->device_id) {
222 case PCI_DEVICE_ID_INTEL_ICH7:
223 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
224 break;
225 case 0x1234: // Dummy for non-existent functionality
226 printf("Error: This southbridge does not have PMBASE.\n");
227 return 1;
228 default:
229 printf("Error: Dumping PMBASE on this southbridge is not (yet) supported.\n");
230 return 1;
231 }
232
233 printf("PMBASE = 0x%04x (IO)\n\n", pmbase);
234
235 for (i=0; i<size; i+=4) {
236 printf("pmbase+0x%04x: 0x%08x\n", i, inl(pmbase+i));
237 }
238
239 return 0;
240}
241
242/*
243 * (G)MCH MMIO Config Space
244 */
245
246int print_mchbar(struct pci_dev *nb)
247{
248 int i, size=(16*1024);
249 volatile uint8_t *mchbar;
250 uint32_t mchbar_phys;
251
252 printf("\n============= MCHBAR ============\n\n");
253
254 switch (nb->device_id) {
255 case PCI_DEVICE_ID_INTEL_82945GM:
256 mchbar_phys = pci_read_long(nb, 0x44) & 0xfffffffe;
257 break;
258 case 0x1234: // Dummy for non-existent functionality
259 printf("Error: This northbrigde does not have MCHBAR.\n");
260 return 1;
261 default:
262 printf("Error: Dumping MCHBAR on this northbridge is not (yet) supported.\n");
263 return 1;
264 }
265
266 mchbar = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
267 fd_mem, (off_t) mchbar_phys );
268
269 if (mchbar == MAP_FAILED) {
270 perror("Error mapping MCHBAR");
271 exit(1);
272 }
273
274 printf("MCHBAR = 0x%08x (MEM)\n\n", mchbar_phys);
275
276 for (i=0; i<size; i+=4) {
277 if(*(uint32_t *)(mchbar+i))
278 printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(mchbar+i));
279 }
280
281 munmap((void *) mchbar, size);
282 return 0;
283}
284
285/*
286 * Egress Port Root Complex MMIO configuration space
287 */
288int print_epbar(struct pci_dev *nb)
289{
290 int i, size=4096;
291 volatile uint8_t *epbar;
292 uint32_t epbar_phys;
293
294 printf("\n============= EPBAR =============\n\n");
295
296 switch (nb->device_id) {
297 case PCI_DEVICE_ID_INTEL_82945GM:
298 epbar_phys = pci_read_long(nb, 0x40) & 0xfffffffe;
299 break;
300 case 0x1234: // Dummy for non-existent functionality
301 printf("Error: This northbrigde does not have EPBAR.\n");
302 return 1;
303 default:
304 printf("Error: Dumping EPBAR on this northbridge is not (yet) supported.\n");
305 return 1;
306 }
307
308 epbar = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
309 fd_mem, (off_t) epbar_phys );
310
311 if (epbar == MAP_FAILED) {
312 perror("Error mapping EPBAR");
313 exit(1);
314 }
315
316 printf("EPBAR = 0x%08x (MEM)\n\n", epbar_phys);
317 for (i=0; i<size; i+=4) {
318 if(*(uint32_t *)(epbar+i))
319 printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(epbar+i));
320 }
321
322 munmap((void *) epbar, size);
323 return 0;
324}
325
326
327/*
328 * MCH-ICH Serial Interconnect Ingress Root Complex MMIO configuration space
329 */
330int print_dmibar(struct pci_dev *nb)
331{
332 int i, size=4096;
333 volatile uint8_t *dmibar;
334 uint32_t dmibar_phys;
335
336 printf("\n============= DMIBAR ============\n\n");
337
338 switch (nb->device_id) {
339 case PCI_DEVICE_ID_INTEL_82945GM:
340 dmibar_phys = pci_read_long(nb, 0x4c) & 0xfffffffe;
341 break;
342 case 0x1234: // Dummy for non-existent functionality
343 printf("Error: This northbrigde does not have DMIBAR.\n");
344 return 1;
345 default:
346 printf("Error: Dumping DMIBAR on this northbridge is not (yet) supported.\n");
347 return 1;
348 }
349
350 dmibar = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
351 fd_mem, (off_t) dmibar_phys );
352
353 if (dmibar == MAP_FAILED) {
354 perror("Error mapping DMIBAR");
355 exit(1);
356 }
357
358 printf("DMIBAR = 0x%08x (MEM)\n\n", dmibar_phys);
359 for (i=0; i<size; i+=4) {
360 if(*(uint32_t *)(dmibar+i))
361 printf("0x%04x: 0x%08x\n", i, *(uint32_t *)(dmibar+i));
362 }
363
364 munmap((void *) dmibar, size);
365 return 0;
366}
367
368/*
369 * PCIe MMIO configuration space
370 */
371int print_pciexbar(struct pci_dev *nb)
372{
373 uint32_t pciexbar_reg;
374 uint32_t pciexbar_phys;
375 volatile uint8_t *pciexbar;
376 int max_busses, devbase, i;
377 int bus, dev, fn;
378
379 printf("========= PCIEXBAR ========\n\n");
380
381 switch (nb->device_id) {
382 case PCI_DEVICE_ID_INTEL_82945GM:
383 pciexbar_reg = pci_read_long(nb, 0x48);
384 break;
385 case 0x1234: // Dummy for non-existent functionality
386 printf("Error: This northbrigde does not have PCIEXBAR.\n");
387 return 1;
388 default:
389 printf("Error: Dumping PCIEXBAR on this northbridge is not (yet) supported.\n");
390 return 1;
391 }
392
393 if( !(pciexbar_reg & (1 << 0))) {
394 printf("PCIEXBAR register is disabled.\n");
395 return 0;
396 }
397
398 switch ((pciexbar_reg >> 1) & 3) {
399 case 0: // 256MB
400 pciexbar_phys = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
401 max_busses = 256;
402 break;
403 case 1: // 128M
404 pciexbar_phys = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
405 max_busses = 128;
406 break;
407 case 2: // 64M
408 pciexbar_phys = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
409 max_busses = 64;
410 break;
411 default: // RSVD
412 printf("Undefined Address base. Bailing out\n");
413 return 1;
414 }
415
416 printf("PCIEXBAR: 0x%08x\n", pciexbar_phys);
417
418 pciexbar = mmap(0, (max_busses * 1024 * 1024), PROT_WRITE | PROT_READ, MAP_SHARED,
419 fd_mem, (off_t) pciexbar_phys );
420
421 if (pciexbar == MAP_FAILED) {
422 perror("Error mapping PCIEXBAR");
423 exit(1);
424 }
425
426 for (bus = 0; bus < max_busses; bus++) {
427 for (dev = 0; dev < 32; dev++) {
428 for (fn = 0; fn < 8; fn++) {
429 devbase = (bus * 1024 * 1024) + (dev * 32 * 1024) + (fn * 4 * 1024);
430
431 if (*(uint16_t *)(pciexbar + devbase) == 0xffff)
432 continue;
433
434 /* This is a heuristics. Anyone got a better check? */
435 if( (*(uint32_t *)(pciexbar + devbase + 256) == 0xffffffff) &&
436 (*(uint32_t *)(pciexbar + devbase + 512) == 0xffffffff) ) {
437#if DEBUG
438 printf("Skipped non-PCIe device %02x:%02x.%01x\n", bus, dev, fn);
439#endif
440 continue;
441 }
442
443 printf("\nPCIe %02x:%02x.%01x extended config space:", bus, dev, fn);
444 for (i=0; i<4096; i++) {
445 if((i % 0x10) == 0)
446 printf("\n%04x:", i);
447 printf(" %02x", *(pciexbar+devbase+i));
448 }
449 printf("\n");
450 }
451 }
452 }
453
454 munmap((void *) pciexbar, (max_busses * 1024 * 1024));
455
456 return 0;
457}
458
459int msr_readerror = 0;
460
461msr_t rdmsr(int addr)
462{
463 unsigned char buf[8];
464 msr_t msr = { 0xffffffff, 0xffffffff };
465
466 if (lseek(fd_msr, (off_t) addr, SEEK_SET) == -1) {
467 perror("Could not lseek() to MSR");
468 close(fd_msr);
469 exit(1);
470 }
471
472 if (read(fd_msr, buf, 8) == 8) {
473 msr.lo = *(uint32_t *)buf;
474 msr.hi = *(uint32_t *)(buf+4);
475
476 return msr;
477 }
478
479 if (errno == 5) {
480 printf(" (*)"); // Not all bits of the MSR could be read
481 msr_readerror = 1;
482 } else {
483 // A severe error.
484 perror("Could not read() MSR");
485 close(fd_msr);
486 exit(1);
487 }
488
489 return msr;
490}
491
492int print_intel_core_msrs(void)
493{
494 unsigned int i, core;
495 msr_t msr;
496
497
498#define IA32_PLATFORM_ID 0x0017
499#define EBL_CR_POWERON 0x002a
500#define FSB_CLK_STS 0x00cd
501#define IA32_TIME_STAMP_COUNTER 0x0010
502#define IA32_APIC_BASE 0x001b
503
504 typedef struct {
505 int number;
506 char *name;
507 } msr_entry_t;
508
509 msr_entry_t global_msrs[] = {
510 { 0x0017, "IA32_PLATFORM_ID" },
511 { 0x002a, "EBL_CR_POWERON" },
512 { 0x00cd, "FSB_CLOCK_STS" },
513 { 0x00ce, "FSB_CLOCK_VCC" },
514 { 0x00e2, "CLOCK_CST_CONFIG_CONTROL" },
515 { 0x00e3, "PMG_IO_BASE_ADDR" },
516 { 0x00e4, "PMG_IO_CAPTURE_ADDR" },
517 { 0x00ee, "EXT_CONFIG" },
518 { 0x011e, "BBL_CR_CTL3" },
519 { 0x0194, "CLOCK_FLEX_MAX" },
520 { 0x0198, "IA32_PERF_STATUS" },
521 { 0x01a0, "IA32_MISC_ENABLES" },
522 { 0x01aa, "PIC_SENS_CFG" },
523 { 0x0400, "IA32_MC0_CTL" },
524 { 0x0401, "IA32_MC0_STATUS" },
525 { 0x0402, "IA32_MC0_ADDR" },
526 //{ 0x0403, "IA32_MC0_MISC" }, // Seems to be RO
527 { 0x040c, "IA32_MC4_CTL" },
528 { 0x040d, "IA32_MC4_STATUS" },
529 { 0x040e, "IA32_MC4_ADDR" },
530 //{ 0x040f, "IA32_MC4_MISC" } // Seems to be RO
531 };
532
533 msr_entry_t per_core_msrs[] = {
534 { 0x0010, "IA32_TIME_STAMP_COUNTER" },
535 { 0x001b, "IA32_APIC_BASE" },
536 { 0x003a, "IA32_FEATURE_CONTROL" },
537 { 0x003f, "IA32_TEMPERATURE_OFFSET" },
538 //{ 0x0079, "IA32_BIOS_UPDT_TRIG" }, // Seems to be RO
539 { 0x008b, "IA32_BIOS_SIGN_ID" },
540 { 0x00e7, "IA32_MPERF" },
541 { 0x00e8, "IA32_APERF" },
542 { 0x00fe, "IA32_MTRRCAP" },
543 { 0x015f, "DTS_CAL_CTRL" },
544 { 0x0179, "IA32_MCG_CAP" },
545 { 0x017a, "IA32_MCG_STATUS" },
546 { 0x0199, "IA32_PERF_CONTROL" },
547 { 0x019a, "IA32_CLOCK_MODULATION" },
548 { 0x019b, "IA32_THERM_INTERRUPT" },
549 { 0x019c, "IA32_THERM_STATUS" },
550 { 0x019d, "GV_THERM" },
551 { 0x01d9, "IA32_DEBUGCTL" },
552 { 0x0200, "IA32_MTRR_PHYSBASE0" },
553 { 0x0201, "IA32_MTRR_PHYSMASK0" },
554 { 0x0202, "IA32_MTRR_PHYSBASE1" },
555 { 0x0203, "IA32_MTRR_PHYSMASK1" },
556 { 0x0204, "IA32_MTRR_PHYSBASE2" },
557 { 0x0205, "IA32_MTRR_PHYSMASK2" },
558 { 0x0206, "IA32_MTRR_PHYSBASE3" },
559 { 0x0207, "IA32_MTRR_PHYSMASK3" },
560 { 0x0208, "IA32_MTRR_PHYSBASE4" },
561 { 0x0209, "IA32_MTRR_PHYSMASK4" },
562 { 0x020a, "IA32_MTRR_PHYSBASE5" },
563 { 0x020b, "IA32_MTRR_PHYSMASK5" },
564 { 0x020c, "IA32_MTRR_PHYSBASE6" },
565 { 0x020d, "IA32_MTRR_PHYSMASK6" },
566 { 0x020e, "IA32_MTRR_PHYSBASE7" },
567 { 0x020f, "IA32_MTRR_PHYSMASK7" },
568 { 0x0250, "IA32_MTRR_FIX64K_00000" },
569 { 0x0258, "IA32_MTRR_FIX16K_80000" },
570 { 0x0259, "IA32_MTRR_FIX16K_A0000" },
571 { 0x0268, "IA32_MTRR_FIX4K_C0000" },
572 { 0x0269, "IA32_MTRR_FIX4K_C8000" },
573 { 0x026a, "IA32_MTRR_FIX4K_D0000" },
574 { 0x026b, "IA32_MTRR_FIX4K_D8000" },
575 { 0x026c, "IA32_MTRR_FIX4K_E0000" },
576 { 0x026d, "IA32_MTRR_FIX4K_E8000" },
577 { 0x026e, "IA32_MTRR_FIX4K_F0000" },
578 { 0x026f, "IA32_MTRR_FIX4K_F8000" },
579 { 0x02ff, "IA32_MTRR_DEF_TYPE" },
580 //{ 0x00c000080, "IA32_CR_EFER" }, // Seems to be RO
581 };
582
583 fd_msr = open("/dev/cpu/0/msr", O_RDWR);
584 if (fd_msr<0) {
585 perror("Error while opening /dev/cpu/0/msr");
586 printf("Did you run 'modprobe msr'?\n");
587 return -1;
588 }
589
590 printf("\n===================== SHARED MSRs (All Cores) =====================\n");
591
592 for (i = 0; i < ARRAY_SIZE(global_msrs); i++) {
593 msr = rdmsr(global_msrs[i].number);
594 printf(" MSR 0x%08X = 0x%08X:0x%08X (%s)\n",
595 global_msrs[i].number, msr.hi, msr.lo, global_msrs[i].name);
596 }
597
598
599 close(fd_msr);
600
601 for (core=0; core < 8; core++) {
602 char msrfilename[64];
603 memset(msrfilename, 0, 64);
604 sprintf(msrfilename, "/dev/cpu/%d/msr", core);
605
606 fd_msr = open(msrfilename, O_RDWR);
607 if (fd_msr<0) {
608 /* If the file is not there, we're probably through.
609 * No error, since we successfully opened /dev/cpu/0/msr before
610 */
611 break;
612 }
613
614 printf("\n====================== UNIQUE MSRs (core %d) ======================\n", core);
615
616 for (i = 0; i < ARRAY_SIZE(per_core_msrs); i++) {
617 msr = rdmsr(per_core_msrs[i].number);
618 printf(" MSR 0x%08X = 0x%08X:0x%08X (%s)\n",
619 per_core_msrs[i].number, msr.hi, msr.lo, per_core_msrs[i].name);
620 }
621
622 close(fd_msr);
623 }
624
625 if (msr_readerror)
626 printf("\n(*) Some MSRs could not be read. The marked values are unreliable.\n");
627
628 return 0;
629}
630
631void print_version(void)
632{
633 printf("inteltool v%s -- ", INTELTOOL_VERSION);
634 printf("Copyright (C) 2008 coresystems GmbH\n\n");
635 printf(
636 "This program is free software: you can redistribute it and/or modify\n"
637 "it under the terms of the GNU General Public License as published by\n"
638 "the Free Software Foundation, version 2 of the License.\n\n"
639 "This program is distributed in the hope that it will be useful,\n"
640 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
641 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
642 "GNU General Public License for more details.\n\n"
643 "You should have received a copy of the GNU General Public License\n"
644 "along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n");
645}
646
647void print_usage(const char *name)
648{
649 printf("usage: %s [-vh?grpmedPM]\n", name);
650 printf("\n"
651 " -v | --version: print the version\n"
652 " -h | --help: print this help\n\n"
653 " -g | --gpio: dump soutbridge GPIO registers\n"
654 " -r | --rcba: dump soutbridge RCBA registers\n"
655 " -p | --pmbase: dump soutbridge Power Management registers\n\n"
656 " -m | --mchbar: dump northbridge Memory Controller registers\n"
657 " -e | --epbar: dump northbridge EPBAR registers\n"
658 " -d | --dmibar: dump northbridge DMIBAR registers\n"
659 " -P | --pciexpress: dump northbridge PCIEXBAR registers\n\n"
660 " -M | --msrs: dump CPU MSRs\n"
661 "\n");
662 exit(1);
663}
664
665int main(int argc, char *argv[])
666{
667 struct pci_access *pacc;
668 struct pci_dev *sb, *nb;
669 int opt;
670 int option_index = 0;
671 int i;
672
673 char *sbname="unknown", *nbname="unknown";
674
675 int dump_gpios=0, dump_mchbar=0, dump_rcba=0;
676 int dump_pmbase=0, dump_epbar=0, dump_dmibar=0;
677 int dump_pciexbar=0, dump_coremsrs=0;
678
679 static struct option long_options[] = {
680 {"version", 0, 0, 'v'},
681 {"help", 0, 0, 'h'},
682 {"gpios", 0, 0, 'g'},
683 {"mchbar", 0, 0, 'm'},
684 {"rcba", 0, 0, 'r'},
685 {"pmbase", 0, 0, 'p'},
686 {"epbar", 0, 0, 'e'},
687 {"dmibar", 0, 0, 'd'},
688 {"pciexpress", 0, 0, 'P'},
689 {"msrs", 0, 0, 'M'},
690 {"all", 0, 0, 'a'},
691 {0, 0, 0, 0}
692 };
693
694 struct {
695 uint16_t vendor_id, device_id;
696 char * name;
697 } supported_chips_list[] = {
698 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945GM, "i945" },
Stefan Reinauerb69e46b2008-05-14 11:38:22 +0000699 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7, "ICH7" },
700 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH4M, "ICH4-M" },
701 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH4, "ICH4" },
702 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH0, "ICH0" },
703 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH, "ICH" }
Stefan Reinauer03646be2008-05-13 22:14:21 +0000704 };
705
706 while ((opt = getopt_long(argc, argv, "vh?gmrpedPca",
707 long_options, &option_index)) != EOF) {
708 switch (opt) {
709 case 'v':
710 print_version();
711 exit(0);
712 break;
713 case 'g':
714 dump_gpios = 1;
715 break;
716 case 'm':
717 dump_mchbar = 1;
718 break;
719 case 'r':
720 dump_rcba = 1;
721 break;
722 case 'p':
723 dump_pmbase = 1;
724 break;
725 case 'e':
726 dump_epbar = 1;
727 break;
728 case 'd':
729 dump_dmibar = 1;
730 break;
731 case 'P':
732 dump_pciexbar = 1;
733 break;
734 case 'M':
735 dump_coremsrs = 1;
736 break;
737 case 'a':
738 dump_gpios = 1;
739 dump_mchbar = 1;
740 dump_rcba = 1;
741 dump_pmbase = 1;
742 dump_epbar = 1;
743 dump_dmibar = 1;
744 dump_pciexbar = 1;
745 dump_coremsrs = 1;
746 break;
747 case 'h':
748 case '?':
749 default:
750 print_usage(argv[0]);
751 exit(0);
752 break;
753 }
754 }
755
756 if (iopl(3)) { printf("You need to be root.\n"); exit(1); }
757
758 if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) {
759 perror("Can not open /dev/mem");
760 exit(1);
761 }
762
763 pacc = pci_alloc();
764 pci_init(pacc);
765 pci_scan_bus(pacc);
766
767
768 /* Find the required devices */
769
770 sb = pci_get_dev(pacc, 0, 0, 0x1f, 0);
771 if (!sb) {
772 printf("No southbridge found.\n");
773 exit(1);
774 }
775
776 pci_fill_info(sb, PCI_FILL_IDENT|PCI_FILL_BASES|PCI_FILL_SIZES|PCI_FILL_CLASS);
777
778 if (sb->vendor_id != PCI_VENDOR_ID_INTEL) {
779 printf("Not an Intel(R) southbridge.\n");
780 exit(1);
781 }
782
783 nb = pci_get_dev(pacc, 0, 0, 0x00, 0);
784 if (!nb) {
785 printf("No northbridge found.\n");
786 exit(1);
787 }
788
789 pci_fill_info(nb, PCI_FILL_IDENT|PCI_FILL_BASES|PCI_FILL_SIZES|PCI_FILL_CLASS);
790
791 if (nb->vendor_id != PCI_VENDOR_ID_INTEL) {
792 printf("Not an Intel(R) northbridge.\n");
793 exit(1);
794 }
795
796 /* TODO check cpuid, too */
797
798 /* Determine names */
799 for (i=0; i<ARRAY_SIZE(supported_chips_list); i++)
800 if (nb->device_id == supported_chips_list[i].device_id)
801 nbname = supported_chips_list[i].name;
802 for (i=0; i<ARRAY_SIZE(supported_chips_list); i++)
803 if (sb->device_id == supported_chips_list[i].device_id)
804 sbname = supported_chips_list[i].name;
805
806 printf("Intel Northbridge: %04x:%04x (%s)\n",
807 nb->vendor_id, nb->device_id, nbname);
808
809 printf("Intel Southbridge: %04x:%04x (%s)\n",
810 sb->vendor_id, sb->device_id, sbname);
811
812 /* Now do the deed */
813
814 if (dump_gpios) {
815 print_gpios(sb);
816 printf("\n\n");
817 }
818
819 if (dump_rcba) {
820 print_rcba(sb);
821 printf("\n\n");
822 }
823
824 if (dump_pmbase) {
825 print_pmbase(sb);
826 printf("\n\n");
827 }
828
829 if (dump_mchbar) {
830 print_mchbar(nb);
831 printf("\n\n");
832 }
833
834 if (dump_epbar) {
835 print_epbar(nb);
836 printf("\n\n");
837 }
838
839 if (dump_dmibar) {
840 print_dmibar(nb);
841 printf("\n\n");
842 }
843
844 if (dump_pciexbar) {
845 print_pciexbar(nb);
846 printf("\n\n");
847 }
848
849 if (dump_coremsrs) {
850 print_intel_core_msrs();
851 printf("\n\n");
852 }
853
854
855 /* Clean up */
856
857 pci_free_dev(nb);
858 pci_free_dev(sb);
859 pci_cleanup(pacc);
860
861 return 0;
862}