14 #include <sys/utsname.h>
22 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
25 * Note: on other architectures, entries differ (cf. Alpha)!!!
27 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30 static void read_cpuinfo(hd_data_t
*hd_data
);
31 static void dump_cpu_data(hd_data_t
*hd_data
);
33 #if defined(__i386__) || defined(__x86_64__)
34 static inline unsigned units_per_cpu();
37 static int ia64DetectSMP(hd_data_t
*hd_data
);
40 void hd_scan_cpu(hd_data_t
*hd_data
)
46 if(!hd_probe_feature(hd_data
, pr_cpu
)) return;
48 hd_data
->module
= mod_cpu
;
51 remove_hd_entries(hd_data
);
52 hd_data
->cpu
= free_str_list(hd_data
->cpu
);
54 PROGRESS(1, 0, "cpuinfo");
56 read_cpuinfo(hd_data
);
58 for(hd0
= hd_data
->hd
; hd0
; hd0
= hd0
->next
) {
59 if(hd0
->base_class
.id
== bc_internal
&& hd0
->sub_class
.id
== sc_int_cpu
) break;
62 if(!hd0
|| hd0
->next
) return; /* 0 or > 1 entries */
64 /* only one entry, maybe UP kernel on SMP system */
69 cpus
= ia64DetectSMP(hd_data
);
72 for(i
= 1; i
< cpus
; i
++) {
73 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
82 void read_cpuinfo(hd_data_t
*hd_data
)
89 #if defined(__i386__) || defined (__x86_64__)
90 char model_id
[80], vendor_id
[80], features
[0x100];
91 unsigned bogo
, mhz
, cache
, family
, model
, stepping
;
96 char model_id
[80], vendor_id
[80], features
[0x100];
97 unsigned mhz
, stepping
;
102 char model_id
[80], system_id
[80], serial_number
[80], platform
[80];
103 unsigned cpu_variation
, cpu_revision
, u
, hz
;
108 char model_id
[80], vendor_id
[80], motherboard
[80];
109 unsigned bogo
, mhz
, cache
, family
, model
, stepping
;
114 char cpu_id
[80], fpu_id
[80], promlib
[80], prom
[80], type
[80], mmu
[80];
115 unsigned u
, bogo
, cpus_active
;
118 #if defined(__s390__) || defined(__s390x__)
121 unsigned u0
, u1
, u2
, u3
;
124 hd_data
->cpu
= read_file(PROC_CPUINFO
, 0, 0);
125 if((hd_data
->debug
& HD_DEB_CPU
)) dump_cpu_data(hd_data
);
126 if(!hd_data
->cpu
) return;
129 *model_id
= *system_id
= *serial_number
= *platform
= 0;
130 cpu_variation
= cpu_revision
= hz
= 0;
132 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
133 if(sscanf(sl
->str
, "cpu model : %79[^\n]", model_id
) == 1) continue;
134 if(sscanf(sl
->str
, "system type : %79[^\n]", system_id
) == 1) continue;
135 if(sscanf(sl
->str
, "cpu variation : %u", &cpu_variation
) == 1) continue;
136 if(sscanf(sl
->str
, "cpu revision : %u", &cpu_revision
) == 1) continue;
137 if(sscanf(sl
->str
, "system serial number : %79[^\n]", serial_number
) == 1) continue;
138 if(sscanf(sl
->str
, "cpus detected : %u", &cpus
) == 1) continue;
139 if(sscanf(sl
->str
, "cycle frequency [Hz] : %u", &hz
) == 1) continue;
140 if(sscanf(sl
->str
, "system variation : %79[^\n]", platform
) == 1) continue;
143 if(*model_id
|| *system_id
) { /* at least one of those */
144 ct
= new_mem(sizeof *ct
);
145 ct
->architecture
= arch_alpha
;
146 if(model_id
) ct
->model_name
= new_str(model_id
);
147 if(system_id
) ct
->vend_name
= new_str(system_id
);
148 if(strncmp(serial_number
, "MILO", 4) == 0)
149 hd_data
->boot
= boot_milo
;
151 hd_data
->boot
= boot_aboot
;
153 ct
->family
= cpu_variation
;
154 ct
->model
= cpu_revision
;
157 ct
->clock
= (hz
+ 500000) / 1000000;
159 if(platform
&& strcmp(platform
, "0")) {
160 ct
->platform
= new_str(platform
);
163 if(!cpus
) cpus
= 1; /* at least 1 machine had a "cpus: 0" entry... */
164 for(u
= 0; u
< cpus
; u
++) {
165 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
166 hd
->base_class
.id
= bc_internal
;
167 hd
->sub_class
.id
= sc_int_cpu
;
169 hd
->detail
= new_mem(sizeof *hd
->detail
);
170 hd
->detail
->type
= hd_detail_cpu
;
172 hd
->detail
->cpu
.data
= ct1
= new_mem(sizeof *ct
);
174 ct1
->model_name
= new_str(ct1
->model_name
);
175 ct1
->vend_name
= new_str(ct1
->vend_name
);
176 ct1
->platform
= new_str(ct1
->platform
);
179 hd
->detail
->cpu
.data
= ct
;
184 #endif /* __alpha__ */
188 *cpu_id
= *fpu_id
= *promlib
= *prom
= *type
= *mmu
= 0;
189 cpus
= cpus_active
= bogo
= 0;
191 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
192 if(sscanf(sl
->str
, "cpu : %79[^\n]", cpu_id
) == 1);
193 if(sscanf(sl
->str
, "fpu : %79[^\n]", fpu_id
) == 1);
194 if(sscanf(sl
->str
, "promlib : %79[^\n]", promlib
) == 1);
195 if(sscanf(sl
->str
, "prom : %79[^\n]", prom
) == 1);
196 if(sscanf(sl
->str
, "type : %79[^\n]", type
) == 1);
197 if(sscanf(sl
->str
, "ncpus probed : %u", &cpus
) == 1);
198 if(sscanf(sl
->str
, "ncpus active : %u", &cpus_active
) == 1);
199 if(sscanf(sl
->str
, "BogoMips : %u", &bogo
) == 1);
200 if(sscanf(sl
->str
, "MMU Type : %79[^\n]", mmu
) == 1);
204 for(u
= 0; u
< cpus
; u
++) {
205 ct
= new_mem(sizeof *ct
);
206 ct
->platform
= new_str (type
);
207 if(strcmp (type
, "sun4u") == 0)
208 ct
->architecture
= arch_sparc64
;
210 ct
->architecture
= arch_sparc
;
212 ct
->model_name
= new_str(cpu_id
);
213 hd_data
->boot
= boot_silo
;
215 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
216 hd
->base_class
.id
= bc_internal
;
217 hd
->sub_class
.id
= sc_int_cpu
;
219 hd
->detail
= new_mem(sizeof *hd
->detail
);
220 hd
->detail
->type
= hd_detail_cpu
;
221 hd
->detail
->cpu
.data
= ct
;
227 #if defined(__i386__) || defined (__x86_64__)
228 *model_id
= *vendor_id
= *features
= 0;
229 bogo
= mhz
= cache
= family
= model
= stepping
= 0;
231 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
232 if(sscanf(sl
->str
, "model name : %79[^\n]", model_id
) == 1);
233 if(sscanf(sl
->str
, "vendor_id : %79[^\n]", vendor_id
) == 1);
234 if(sscanf(sl
->str
, "flags : %255[^\n]", features
) == 1);
235 if(sscanf(sl
->str
, "bogomips : %u", &bogo
) == 1);
236 if(sscanf(sl
->str
, "cpu MHz : %u", &mhz
) == 1);
237 if(sscanf(sl
->str
, "cache size : %u KB", &cache
) == 1);
239 if(sscanf(sl
->str
, "cpu family : %u", &family
) == 1);
240 if(sscanf(sl
->str
, "model : %u", &model
) == 1);
241 if(sscanf(sl
->str
, "stepping : %u", &stepping
) == 1);
243 if(strstr(sl
->str
, "processor") == sl
->str
|| !sl
->next
) { /* EOF */
244 if(*model_id
|| *vendor_id
) { /* at least one of those */
245 ct
= new_mem(sizeof *ct
);
247 ct
->architecture
= arch_intel
;
250 ct
->architecture
= arch_x86_64
;
252 if(model_id
) ct
->model_name
= new_str(model_id
);
253 if(vendor_id
) ct
->vend_name
= new_str(vendor_id
);
256 ct
->stepping
= stepping
;
258 hd_data
->boot
= boot_grub
;
260 /* round clock to typical values */
261 if(mhz
>= 38 && mhz
<= 42)
263 else if(mhz
>= 88 && mhz
<= 92)
272 else if(u
>= 25 && u
<= 29)
274 else if(u
>= 33 && u
<= 37)
276 else if(u
>= 50 && u
<= 54)
278 else if(u
>= 66 && u
<= 70)
280 else if(u
>= 75 && u
<= 79)
282 else if(u
>= 80 && u
<= 84) /* there are 180MHz PPros */
290 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
291 hd
->base_class
.id
= bc_internal
;
292 hd
->sub_class
.id
= sc_int_cpu
;
294 hd
->detail
= new_mem(sizeof *hd
->detail
);
295 hd
->detail
->type
= hd_detail_cpu
;
296 hd
->detail
->cpu
.data
= ct
;
299 for(t0
= features
; (t
= strsep(&t0
, " ")); ) {
300 add_str_list(&ct
->features
, t
);
301 if(!strcmp(t
, "ht")) ct
->units
= units_per_cpu();
305 *model_id
= *vendor_id
= 0;
306 bogo
= mhz
= cache
= family
= model
= 0;
311 #endif /* __i386__ || __x86_64__ */
315 *model_id
= *vendor_id
= *motherboard
= 0;
316 bogo
= mhz
= cache
= family
= model
= stepping
= 0;
318 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
319 if(sscanf(sl
->str
, "machine : %79[^\n]", vendor_id
) == 1);
322 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
323 if(sscanf(sl
->str
, "cpu : %79[^\n]", model_id
) == 1);
324 if(sscanf(sl
->str
, "motherboard : %79[^\n]", motherboard
) == 1);
325 if(sscanf(sl
->str
, "bogomips : %u", &bogo
) == 1);
326 if(sscanf(sl
->str
, "clock : %u", &mhz
) == 1);
327 if(sscanf(sl
->str
, "L2 cache : %u KB", &cache
) == 1);
329 if(strstr(sl
->str
, "processor") == sl
->str
|| !sl
->next
) { /* EOF */
330 if(*model_id
) { /* at least one of those */
331 ct
= new_mem(sizeof *ct
);
332 ct
->architecture
= arch_ppc
;
334 ct
->model_name
= new_str(model_id
);
338 if(strstr(un
.machine
,"ppc64"))
339 ct
->architecture
= arch_ppc64
;
341 if(vendor_id
) ct
->vend_name
= new_str(vendor_id
);
342 if(motherboard
) ct
->platform
= new_str(motherboard
);
345 ct
->stepping
= stepping
;
347 hd_data
->boot
= boot_ppc
;
350 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
351 hd
->base_class
.id
= bc_internal
;
352 hd
->sub_class
.id
= sc_int_cpu
;
354 hd
->detail
= new_mem(sizeof *hd
->detail
);
355 hd
->detail
->type
= hd_detail_cpu
;
356 hd
->detail
->cpu
.data
= ct
;
358 if(ct
->vend_name
&& !strcmp(ct
->vend_name
, "PowerBook") && !hd_data
->color_code
) {
359 hd_data
->color_code
= 7; // black
363 bogo
= mhz
= cache
= family
= model
= 0;
372 *model_id
= *vendor_id
= *features
= 0;
375 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
376 if(sscanf(sl
->str
, "family : %79[^\n]", model_id
) == 1);
377 if(sscanf(sl
->str
, "vendor : %79[^\n]", vendor_id
) == 1);
378 if(sscanf(sl
->str
, "features : %255[^\n]", features
) == 1);
379 if(sscanf(sl
->str
, "cpu MHz : %u", &mhz
) == 1);
380 if(sscanf(sl
->str
, "revision : %u", &stepping
) == 1);
382 if(strstr(sl
->str
, "processor") == sl
->str
|| !sl
->next
) { /* EOF */
383 if(*model_id
|| *vendor_id
) { /* at least one of those */
384 ct
= new_mem(sizeof *ct
);
385 ct
->architecture
= arch_ia64
;
386 if(model_id
) ct
->model_name
= new_str(model_id
);
387 if(vendor_id
) ct
->vend_name
= new_str(vendor_id
);
388 ct
->stepping
= stepping
;
389 hd_data
->boot
= boot_elilo
;
391 /* round clock to typical values */
392 if(mhz
>= 38 && mhz
<= 42)
394 else if(mhz
>= 88 && mhz
<= 92)
403 else if(u
>= 25 && u
<= 29)
405 else if(u
>= 33 && u
<= 37)
407 else if(u
>= 50 && u
<= 54)
409 else if(u
>= 66 && u
<= 70)
411 else if(u
>= 75 && u
<= 79)
413 else if(u
>= 80 && u
<= 84) /* there are 180MHz PPros */
421 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
422 hd
->base_class
.id
= bc_internal
;
423 hd
->sub_class
.id
= sc_int_cpu
;
425 hd
->detail
= new_mem(sizeof *hd
->detail
);
426 hd
->detail
->type
= hd_detail_cpu
;
427 hd
->detail
->cpu
.data
= ct
;
430 for(t0
= features
; (t
= strsep(&t0
, " ")); ) {
431 add_str_list(&ct
->features
, t
);
435 *model_id
= *vendor_id
= 0;
442 #endif /* __ia64__ */
445 #if defined(__s390__) || defined(__s390x__)
449 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
450 if(sscanf(sl
->str
, "vendor_id : %79[^\n]", vendor_id
) == 1);
451 if(sscanf(sl
->str
, "bogomips per cpu : %u", &bogo
) == 1);
454 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
456 sscanf(sl
->str
, "processor %u : version = %x , identification = %x , machine = %x", &u0
, &u1
, &u2
, &u3
) == 4
458 ct
= new_mem(sizeof *ct
);
460 ct
->architecture
= arch_s390x
;
462 ct
->architecture
= arch_s390
;
464 if(vendor_id
) ct
->vend_name
= new_str(vendor_id
);
466 hd_data
->boot
= boot_s390
;
468 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
469 hd
->base_class
.id
= bc_internal
;
470 hd
->sub_class
.id
= sc_int_cpu
;
472 hd
->detail
= new_mem(sizeof *hd
->detail
);
473 hd
->detail
->type
= hd_detail_cpu
;
474 hd
->detail
->cpu
.data
= ct
;
480 #endif /* defined(__s390__) || defined(__s390x__) */
484 * Add some cpu data to the global log.
486 void dump_cpu_data(hd_data_t
*hd_data
)
490 ADD2LOG("----- /proc/cpuinfo -----\n");
491 for(sl
= hd_data
->cpu
; sl
; sl
= sl
->next
) {
492 ADD2LOG(" %s", sl
->str
);
494 ADD2LOG("----- /proc/cpuinfo end -----\n");
498 #if defined(__i386__) || defined(__x86_64__)
499 inline unsigned units_per_cpu()
512 "movzx %%bh,%%eax\n\t"
530 * IA64 SMP detection code
533 #define PAGE_OFFSET(addr) ((uintptr_t) (addr) & (getpagesize () - 1))
539 } __attribute__ ((packed
)) acpi_table_entry_header
;
541 struct acpi20_table_rsdp
547 uint32_t rsdt_address
;
549 unsigned long xsdt_address
;
550 uint8_t ext_checksum
;
552 } __attribute__ ((packed
));
554 struct acpi_table_header
561 char oem_table_id
[8];
562 uint32_t oem_revision
;
563 char asl_compiler_id
[4];
564 uint32_t asl_compiler_revision
;
567 #define ACPI_XSDT_SIG "XSDT"
568 struct acpi_table_xsdt
570 struct acpi_table_header header
;
571 unsigned long entry
[0];
572 } __attribute__ ((packed
));
574 #define ACPI_MADT_SIG "ACPI"
575 struct acpi_table_madt
577 struct acpi_table_header header
;
578 uint32_t lapic_address
;
581 uint32_t pcat_compat
:1;
582 uint32_t reserved
:31;
584 } __attribute__ ((packed
));
586 #define ACPI_MADT_LSAPIC 7
588 struct acpi_table_lsapic
590 acpi_table_entry_header header
;
598 uint32_t reserved
:31;
600 } __attribute__ ((packed
));
603 * Map an ACPI table into virtual memory
605 static struct acpi_table_header
*
606 acpi_map_table (int mem
, unsigned long addr
, char *signature
)
608 /* mmap header to determine table size */
609 struct acpi_table_header
*table
= NULL
;
610 unsigned long offset
= PAGE_OFFSET (addr
);
611 uint8_t *mapped
= mmap (NULL
,
612 sizeof (struct acpi_table_header
) + offset
,
616 (unsigned long) addr
- offset
);
617 table
= (struct acpi_table_header
*) (mapped
!= MAP_FAILED
622 if (memcmp (table
->signature
, signature
, sizeof (table
->signature
)))
624 munmap ((char *) table
- offset
,
625 sizeof (struct acpi_table_header
) + offset
);
629 /* re-mmap entire table */
630 unsigned long size
= table
->length
;
631 munmap ((uint8_t *) table
- offset
,
632 sizeof (struct acpi_table_header
) + offset
);
633 mapped
= mmap (NULL
, size
+ offset
, PROT_READ
, MAP_PRIVATE
, mem
,
634 (unsigned long) addr
- offset
);
635 table
= (struct acpi_table_header
*) (mapped
!= MAP_FAILED
644 * Unmap an ACPI table from virtual memory
647 acpi_unmap_table (struct acpi_table_header
* table
)
651 unsigned long offset
= PAGE_OFFSET (table
);
652 munmap ((uint8_t *) table
- offset
, table
->length
+ offset
);
657 acpi_parse_lsapic (acpi_table_entry_header
*p
)
659 struct acpi_table_lsapic
*lsapic
= (struct acpi_table_lsapic
*) p
;
661 return lsapic
->flags
.enabled
;
665 acpi_parse_madt (struct acpi_table_madt
*madt
)
667 acpi_table_entry_header
*p
, *end
;
670 p
= (acpi_table_entry_header
*) (madt
+ 1);
671 end
= (acpi_table_entry_header
*) ((char *) madt
+ madt
->header
.length
);
675 if (p
->type
== ACPI_MADT_LSAPIC
)
676 n_cpu
+= acpi_parse_lsapic (p
);
678 p
= (acpi_table_entry_header
*) ((char *) p
+ p
->length
);
685 acpi_parse_rsdp (int mem_fd
, struct acpi20_table_rsdp
*rsdp
)
689 struct acpi_table_xsdt
*xsdt
= 0;
692 if (rsdp
->xsdt_address
)
693 xsdt
= (struct acpi_table_xsdt
*) acpi_map_table (mem_fd
, rsdp
->xsdt_address
,
697 tables
= (xsdt
->header
.length
- sizeof (struct acpi_table_header
)) / 8;
698 for (i
= 0; i
< tables
; i
++)
700 struct acpi_table_header
*dt
701 = acpi_map_table (mem_fd
, xsdt
->entry
[i
], ACPI_MADT_SIG
);
703 n_cpu
+= acpi_parse_madt ((struct acpi_table_madt
*) dt
);
704 acpi_unmap_table (dt
);
706 acpi_unmap_table ((struct acpi_table_header
*) xsdt
);
711 int ia64DetectSMP(hd_data_t
*hd_data
)
713 int n_cpu
= 0, mem_fd
, systab_fd
;
714 struct acpi20_table_rsdp rsdp
;
716 unsigned long addr
= 0, offset
;
719 const char *rsd_klog
= "ACPI 2.0=";
720 const char *rsd_systab
= "ACPI20=";
723 mem_fd
= open("/dev/mem", O_RDONLY
);
724 if(mem_fd
== -1) return -1;
726 systab_fd
= open("/proc/efi/systab", O_RDONLY
);
730 int n_read
= read(systab_fd
, buffer
, sizeof(buffer
) - 1);
735 if ((s
= strstr(buffer
, rsd_systab
)) != NULL
&&
736 sscanf(s
+ strlen(rsd_systab
), "%lx", &addr
) == 1)
741 if(!hd_data
->klog
) read_klog(hd_data
);
743 for(sl
= hd_data
->klog
; sl
; sl
= sl
->next
) {
744 if((s
= strstr(sl
->str
, rsd_klog
))) {
745 if(sscanf(s
+ strlen(rsd_klog
), "%lx", &addr
) == 1) {
747 offset
= PAGE_OFFSET (addr
);
748 mapped
= mmap(NULL
, sizeof rsdp
+ offset
, PROT_READ
, MAP_PRIVATE
,
749 mem_fd
, (unsigned long) addr
- offset
);
750 if(mapped
!= MAP_FAILED
) {
751 ADD2LOG("seek to 0x%lx\n", addr
);
752 memcpy(&rsdp
, mapped
+ offset
, sizeof rsdp
);
753 munmap(mapped
, sizeof rsdp
+ offset
);
762 n_cpu
= acpi_parse_rsdp(mem_fd
, &rsdp
);
764 ADD2LOG("RSDP found at 0x%lx\n", addr
);
770 ADD2LOG("n_cpu = %d\n", n_cpu
);
776 #endif /* __ia64__ */