2 * lscpu - CPU architecture information helper
4 * Copyright (C) 2008 Cai Qian <qcai@redhat.com>
5 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
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; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <sys/utsname.h>
34 #include <sys/types.h>
37 #if (defined(__x86_64__) || defined(__i386__))
38 # if !defined( __SANITIZE_ADDRESS__)
39 # define INCLUDE_VMWARE_BDOOR
41 # warning VMWARE detection disabled by __SANITIZE_ADDRESS__
45 #ifdef INCLUDE_VMWARE_BDOOR
55 #if defined(HAVE_LIBRTAS)
59 #include <libsmartcols.h>
68 #include "closestream.h"
75 #define _PATH_SYS_SYSTEM "/sys/devices/system"
76 #define _PATH_SYS_CPU _PATH_SYS_SYSTEM "/cpu"
77 #define _PATH_SYS_NODE _PATH_SYS_SYSTEM "/node"
78 #define _PATH_PROC_XEN "/proc/xen"
79 #define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities"
80 #define _PATH_PROC_CPUINFO "/proc/cpuinfo"
81 #define _PATH_PROC_PCIDEVS "/proc/bus/pci/devices"
82 #define _PATH_PROC_SYSINFO "/proc/sysinfo"
83 #define _PATH_PROC_STATUS "/proc/self/status"
84 #define _PATH_PROC_VZ "/proc/vz"
85 #define _PATH_PROC_BC "/proc/bc"
86 #define _PATH_PROC_DEVICETREE "/proc/device-tree"
87 #define _PATH_DEV_MEM "/dev/mem"
89 /* virtualization types */
96 const char *virt_types
[] = {
97 [VIRT_NONE
] = N_("none"),
98 [VIRT_PARA
] = N_("para"),
99 [VIRT_FULL
] = N_("full"),
100 [VIRT_CONT
] = N_("container"),
103 const char *hv_vendors
[] = {
107 [HYPER_MSHV
] = "Microsoft",
108 [HYPER_VMWARE
] = "VMware",
110 [HYPER_VSERVER
] = "Linux-VServer",
111 [HYPER_UML
] = "User-mode Linux",
112 [HYPER_INNOTEK
] = "Innotek GmbH",
113 [HYPER_HITACHI
] = "Hitachi",
114 [HYPER_PARALLELS
] = "Parallels",
115 [HYPER_VBOX
] = "Oracle",
116 [HYPER_OS400
] = "OS/400",
117 [HYPER_PHYP
] = "pHyp",
118 [HYPER_SPAR
] = "Unisys s-Par"
121 const int hv_vendor_pci
[] = {
122 [HYPER_NONE
] = 0x0000,
123 [HYPER_XEN
] = 0x5853,
124 [HYPER_KVM
] = 0x0000,
125 [HYPER_MSHV
] = 0x1414,
126 [HYPER_VMWARE
] = 0x15ad,
127 [HYPER_VBOX
] = 0x80ee,
130 const int hv_graphics_pci
[] = {
131 [HYPER_NONE
] = 0x0000,
132 [HYPER_XEN
] = 0x0001,
133 [HYPER_KVM
] = 0x0000,
134 [HYPER_MSHV
] = 0x5353,
135 [HYPER_VMWARE
] = 0x0710,
136 [HYPER_VBOX
] = 0xbeef,
141 MODE_32BIT
= (1 << 1),
142 MODE_64BIT
= (1 << 2)
145 /* cache(s) description */
151 cpu_set_t
**sharedmaps
;
154 /* dispatching modes */
160 const char *disp_modes
[] = {
161 [DISP_HORIZONTAL
] = N_("horizontal"),
162 [DISP_VERTICAL
] = N_("vertical")
165 /* cpu polarization */
174 struct polarization_modes
{
179 struct polarization_modes polar_modes
[] = {
180 [POLAR_UNKNOWN
] = {"U", "-"},
181 [POLAR_VLOW
] = {"VL", "vert-low"},
182 [POLAR_VMEDIUM
] = {"VM", "vert-medium"},
183 [POLAR_VHIGH
] = {"VH", "vert-high"},
184 [POLAR_HORIZONTAL
] = {"H", "horizontal"},
187 /* global description */
194 char *revision
; /* alternative for model (ppc) */
195 char *cpu
; /* alternative for modelname (ppc, sparc) */
196 char *virtflag
; /* virtualization flag (vmx, svm) */
197 char *hypervisor
; /* hypervisor software */
198 int hyper
; /* hypervisor vendor ID */
199 int virtype
; /* VIRT_PARA|FULL|NONE ? */
201 char **maxmhz
; /* maximum mega hertz */
202 char **minmhz
; /* minimum mega hertz */
206 int dispatching
; /* none, horizontal or vertical */
207 int mode
; /* rm, lm or/and tm */
209 int ncpuspos
; /* maximal possible CPUs */
210 int ncpus
; /* number of present CPUs */
211 cpu_set_t
*present
; /* mask with present CPUs */
212 cpu_set_t
*online
; /* mask with online CPUs */
214 int nthreads
; /* number of online threads */
217 struct cpu_cache
*caches
;
220 * All maps are sequentially indexed (0..ncpuspos), the array index
221 * does not have match with cpuX number as presented by kernel. You
222 * have to use real_cpu_num() to get the real cpuX number.
224 * For example, the possible system CPUs are: 1,3,5, it means that
225 * ncpuspos=3, so all arrays are in range 0..3.
227 int *idx2cpunum
; /* mapping index to CPU num */
229 int nnodes
; /* number of NUMA modes */
230 int *idx2nodenum
; /* Support for discontinuous nodes */
231 cpu_set_t
**nodemaps
; /* array with NUMA nodes */
233 /* books -- based on book_siblings (internal kernel map of cpuX's
234 * hardware threads within the same book */
235 int nbooks
; /* number of all online books */
236 cpu_set_t
**bookmaps
; /* unique book_siblings */
238 /* sockets -- based on core_siblings (internal kernel map of cpuX's
239 * hardware threads within the same physical_package_id (socket)) */
240 int nsockets
; /* number of all online sockets */
241 cpu_set_t
**socketmaps
; /* unique core_siblings */
243 /* cores -- based on thread_siblings (internel kernel map of cpuX's
244 * hardware threads within the same core as cpuX) */
245 int ncores
; /* number of all online cores */
246 cpu_set_t
**coremaps
; /* unique thread_siblings */
248 int *polarization
; /* cpu polarization */
249 int *addresses
; /* physical cpu addresses */
250 int *configured
; /* cpu configured */
251 int physsockets
; /* Physical sockets (modules) */
252 int physchips
; /* Physical chips */
253 int physcoresperchip
; /* Physical cores per chip */
257 OUTPUT_SUMMARY
= 0, /* default */
258 OUTPUT_PARSABLE
, /* -p */
259 OUTPUT_READABLE
, /* -e */
263 SYSTEM_LIVE
= 0, /* analyzing a live system */
264 SYSTEM_SNAPSHOT
, /* analyzing a snapshot of a different system */
267 struct lscpu_modifier
{
268 int mode
; /* OUTPUT_* */
269 int system
; /* SYSTEM_* */
270 unsigned int hex
:1, /* print CPU masks rather than CPU lists */
271 compat
:1, /* use backwardly compatible format */
272 online
:1, /* print online CPUs */
273 offline
:1; /* print offline CPUs */
276 static int maxcpus
; /* size in bits of kernel cpu mask */
278 #define is_cpu_online(_d, _cpu) \
279 ((_d) && (_d)->online ? \
280 CPU_ISSET_S((_cpu), CPU_ALLOC_SIZE(maxcpus), (_d)->online) : 0)
281 #define is_cpu_present(_d, _cpu) \
282 ((_d) && (_d)->present ? \
283 CPU_ISSET_S((_cpu), CPU_ALLOC_SIZE(maxcpus), (_d)->present) : 0)
285 #define real_cpu_num(_d, _i) ((_d)->idx2cpunum[(_i)])
305 /* column description
307 struct lscpu_coldesc
{
311 unsigned int is_abbr
:1; /* name is abbreviation */
314 static struct lscpu_coldesc coldescs
[] =
316 [COL_CPU
] = { "CPU", N_("logical CPU number"), 1 },
317 [COL_CORE
] = { "CORE", N_("logical core number") },
318 [COL_SOCKET
] = { "SOCKET", N_("logical socket number") },
319 [COL_NODE
] = { "NODE", N_("logical NUMA node number") },
320 [COL_BOOK
] = { "BOOK", N_("logical book number") },
321 [COL_CACHE
] = { "CACHE", N_("shows how caches are shared between CPUs") },
322 [COL_POLARIZATION
] = { "POLARIZATION", N_("CPU dispatching mode on virtual hardware") },
323 [COL_ADDRESS
] = { "ADDRESS", N_("physical address of a CPU") },
324 [COL_CONFIGURED
] = { "CONFIGURED", N_("shows if the hypervisor has allocated the CPU") },
325 [COL_ONLINE
] = { "ONLINE", N_("shows if Linux currently makes use of the CPU") },
326 [COL_MAXMHZ
] = { "MAXMHZ", N_("shows the maximum MHz of the CPU") },
327 [COL_MINMHZ
] = { "MINMHZ", N_("shows the minimum MHz of the CPU") }
331 column_name_to_id(const char *name
, size_t namesz
)
335 for (i
= 0; i
< ARRAY_SIZE(coldescs
); i
++) {
336 const char *cn
= coldescs
[i
].name
;
338 if (!strncasecmp(name
, cn
, namesz
) && !*(cn
+ namesz
))
341 warnx(_("unknown column: %s"), name
);
345 /* Lookup a pattern and get the value from cpuinfo.
348 * "<pattern> : <key>"
351 lookup(char *line
, char *pattern
, char **value
)
354 int len
= strlen(pattern
);
356 /* don't re-fill already found tags, first one wins */
357 if (!*line
|| *value
)
361 if (strncmp(line
, pattern
, len
))
365 for (p
= line
+ len
; isspace(*p
); p
++);
372 for (++p
; isspace(*p
); p
++);
380 len
= strlen(line
) - 1;
381 for (p
= line
+ len
; isspace(*(p
-1)); p
--);
388 /* Don't init the mode for platforms where we are not able to
389 * detect that CPU supports 64-bit mode.
392 init_mode(struct lscpu_modifier
*mod
)
396 if (mod
->system
== SYSTEM_SNAPSHOT
)
397 /* reading info from any /{sys,proc} dump, don't mix it with
398 * information about our real CPU */
401 #if defined(__alpha__) || defined(__ia64__)
402 m
|= MODE_64BIT
; /* 64bit platforms only */
404 /* platforms with 64bit flag in /proc/cpuinfo, define
405 * 32bit default here */
406 #if defined(__i386__) || defined(__x86_64__) || \
407 defined(__s390x__) || defined(__s390__) || defined(__sparc_v9__)
413 #if defined(HAVE_LIBRTAS)
414 #define PROCESSOR_MODULE_INFO 43
415 static int strbe16toh(const char *buf
, int offset
)
417 return (buf
[offset
] << 8) + buf
[offset
+1];
420 static void read_physical_info_powerpc(struct lscpu_desc
*desc
)
425 desc
->physsockets
= desc
->physchips
= desc
->physcoresperchip
= 0;
427 rc
= rtas_get_sysparm(PROCESSOR_MODULE_INFO
, sizeof(buf
), buf
);
431 len
= strbe16toh(buf
, 0);
435 ntypes
= strbe16toh(buf
, 2);
441 desc
->physsockets
= strbe16toh(buf
, 4);
442 desc
->physchips
= strbe16toh(buf
, 6);
443 desc
->physcoresperchip
= strbe16toh(buf
, 8);
446 static void read_physical_info_powerpc(
447 struct lscpu_desc
*desc
__attribute__((__unused__
)))
453 read_basicinfo(struct lscpu_desc
*desc
, struct lscpu_modifier
*mod
)
455 FILE *fp
= path_fopen("r", 1, _PATH_PROC_CPUINFO
);
457 struct utsname utsbuf
;
461 if (uname(&utsbuf
) == -1)
462 err(EXIT_FAILURE
, _("error: uname failed"));
463 desc
->arch
= xstrdup(utsbuf
.machine
);
466 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
467 if (lookup(buf
, "vendor", &desc
->vendor
)) ;
468 else if (lookup(buf
, "vendor_id", &desc
->vendor
)) ;
469 else if (lookup(buf
, "family", &desc
->family
)) ;
470 else if (lookup(buf
, "cpu family", &desc
->family
)) ;
471 else if (lookup(buf
, "model", &desc
->model
)) ;
472 else if (lookup(buf
, "model name", &desc
->modelname
)) ;
473 else if (lookup(buf
, "stepping", &desc
->stepping
)) ;
474 else if (lookup(buf
, "cpu MHz", &desc
->mhz
)) ;
475 else if (lookup(buf
, "flags", &desc
->flags
)) ; /* x86 */
476 else if (lookup(buf
, "features", &desc
->flags
)) ; /* s390 */
477 else if (lookup(buf
, "type", &desc
->flags
)) ; /* sparc64 */
478 else if (lookup(buf
, "bogomips", &desc
->bogomips
)) ;
479 else if (lookup(buf
, "bogomips per cpu", &desc
->bogomips
)) ; /* s390 */
480 else if (lookup(buf
, "cpu", &desc
->cpu
)) ;
481 else if (lookup(buf
, "revision", &desc
->revision
)) ;
486 desc
->mode
= init_mode(mod
);
489 snprintf(buf
, sizeof(buf
), " %s ", desc
->flags
);
490 if (strstr(buf
, " svm "))
491 desc
->virtflag
= xstrdup("svm");
492 else if (strstr(buf
, " vmx "))
493 desc
->virtflag
= xstrdup("vmx");
494 if (strstr(buf
, " lm "))
495 desc
->mode
|= MODE_32BIT
| MODE_64BIT
; /* x86_64 */
496 if (strstr(buf
, " zarch "))
497 desc
->mode
|= MODE_32BIT
| MODE_64BIT
; /* s390x */
498 if (strstr(buf
, " sun4v ") || strstr(buf
, " sun4u "))
499 desc
->mode
|= MODE_32BIT
| MODE_64BIT
; /* sparc64 */
502 if (desc
->arch
&& mod
->system
!= SYSTEM_SNAPSHOT
) {
503 if (strcmp(desc
->arch
, "ppc64") == 0)
504 desc
->mode
|= MODE_32BIT
| MODE_64BIT
;
505 else if (strcmp(desc
->arch
, "ppc") == 0)
506 desc
->mode
|= MODE_32BIT
;
511 if (path_exist(_PATH_SYS_CPU
"/kernel_max"))
512 /* note that kernel_max is maximum index [NR_CPUS-1] */
513 maxcpus
= path_read_s32(_PATH_SYS_CPU
"/kernel_max") + 1;
515 else if (mod
->system
== SYSTEM_LIVE
)
516 /* the root is '/' so we are working with data from the current kernel */
517 maxcpus
= get_max_number_of_cpus();
520 /* error or we are reading some /sys snapshot instead of the
521 * real /sys, let's use any crazy number... */
524 setsize
= CPU_ALLOC_SIZE(maxcpus
);
526 if (path_exist(_PATH_SYS_CPU
"/possible")) {
527 cpu_set_t
*tmp
= path_read_cpulist(maxcpus
, _PATH_SYS_CPU
"/possible");
530 desc
->ncpuspos
= CPU_COUNT_S(setsize
, tmp
);
531 desc
->idx2cpunum
= xcalloc(desc
->ncpuspos
, sizeof(int));
533 for (num
= 0, idx
= 0; num
< maxcpus
; num
++) {
534 if (CPU_ISSET(num
, tmp
))
535 desc
->idx2cpunum
[idx
++] = num
;
539 err(EXIT_FAILURE
, _("failed to determine number of CPUs: %s"),
540 _PATH_SYS_CPU
"/possible");
543 /* get mask for present CPUs */
544 if (path_exist(_PATH_SYS_CPU
"/present")) {
545 desc
->present
= path_read_cpulist(maxcpus
, _PATH_SYS_CPU
"/present");
546 desc
->ncpus
= CPU_COUNT_S(setsize
, desc
->present
);
549 /* get mask for online CPUs */
550 if (path_exist(_PATH_SYS_CPU
"/online")) {
551 desc
->online
= path_read_cpulist(maxcpus
, _PATH_SYS_CPU
"/online");
552 desc
->nthreads
= CPU_COUNT_S(setsize
, desc
->online
);
555 /* get dispatching mode */
556 if (path_exist(_PATH_SYS_CPU
"/dispatching"))
557 desc
->dispatching
= path_read_s32(_PATH_SYS_CPU
"/dispatching");
559 desc
->dispatching
= -1;
561 if (mod
->system
== SYSTEM_LIVE
)
562 read_physical_info_powerpc(desc
);
566 has_pci_device(unsigned int vendor
, unsigned int device
)
569 unsigned int num
, fn
, ven
, dev
;
572 f
= path_fopen("r", 0, _PATH_PROC_PCIDEVS
);
576 /* for more details about bus/pci/devices format see
577 * drivers/pci/proc.c in linux kernel
579 while(fscanf(f
, "%02x%02x\t%04x%04x\t%*[^\n]",
580 &num
, &fn
, &ven
, &dev
) == 4) {
582 if (ven
== vendor
&& dev
== device
)
592 #if defined(__x86_64__) || defined(__i386__)
595 * This CPUID leaf returns the information about the hypervisor.
596 * EAX : maximum input value for CPUID supported by the hypervisor.
597 * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
599 #define HYPERVISOR_INFO_LEAF 0x40000000
602 cpuid(unsigned int op
, unsigned int *eax
, unsigned int *ebx
,
603 unsigned int *ecx
, unsigned int *edx
)
606 #if defined(__PIC__) && defined(__i386__)
607 /* x86 PIC cannot clobber ebx -- gcc bitches */
623 read_hypervisor_cpuid(struct lscpu_desc
*desc
)
625 unsigned int eax
= 0, ebx
= 0, ecx
= 0, edx
= 0;
626 char hyper_vendor_id
[13];
628 memset(hyper_vendor_id
, 0, sizeof(hyper_vendor_id
));
630 cpuid(HYPERVISOR_INFO_LEAF
, &eax
, &ebx
, &ecx
, &edx
);
631 memcpy(hyper_vendor_id
+ 0, &ebx
, 4);
632 memcpy(hyper_vendor_id
+ 4, &ecx
, 4);
633 memcpy(hyper_vendor_id
+ 8, &edx
, 4);
634 hyper_vendor_id
[12] = '\0';
636 if (!hyper_vendor_id
[0])
639 if (!strncmp("XenVMMXenVMM", hyper_vendor_id
, 12))
640 desc
->hyper
= HYPER_XEN
;
641 else if (!strncmp("KVMKVMKVM", hyper_vendor_id
, 9))
642 desc
->hyper
= HYPER_KVM
;
643 else if (!strncmp("Microsoft Hv", hyper_vendor_id
, 12))
644 desc
->hyper
= HYPER_MSHV
;
645 else if (!strncmp("VMwareVMware", hyper_vendor_id
, 12))
646 desc
->hyper
= HYPER_VMWARE
;
647 else if (!strncmp("UnisysSpar64", hyper_vendor_id
, 12))
648 desc
->hyper
= HYPER_SPAR
;
651 #else /* ! (__x86_64__ || __i386__) */
653 read_hypervisor_cpuid(struct lscpu_desc
*desc
__attribute__((__unused__
)))
658 static int is_compatible(const char *path
, const char *str
)
660 FILE *fd
= path_fopen("r", 0, "%s", path
);
666 memset(buf
, 0, sizeof(buf
));
667 len
= fread(buf
, 1, sizeof(buf
) - 1, fd
);
670 for (i
= 0; i
< len
;) {
671 if (!strcmp(&buf
[i
], str
))
673 i
+= strlen(&buf
[i
]);
682 read_hypervisor_powerpc(struct lscpu_desc
*desc
)
684 assert(!desc
->hyper
);
686 /* IBM iSeries: legacy, para-virtualized on top of OS/400 */
687 if (path_exist("/proc/iSeries")) {
688 desc
->hyper
= HYPER_OS400
;
689 desc
->virtype
= VIRT_PARA
;
691 /* PowerNV (POWER Non-Virtualized, bare-metal) */
692 } else if (is_compatible(_PATH_PROC_DEVICETREE
"/compatible", "ibm,powernv")) {
693 desc
->hyper
= HYPER_NONE
;
694 desc
->virtype
= VIRT_NONE
;
696 /* PowerVM (IBM's proprietary hypervisor, aka pHyp) */
697 } else if (path_exist(_PATH_PROC_DEVICETREE
"/ibm,partition-name")
698 && path_exist(_PATH_PROC_DEVICETREE
"/hmc-managed?")
699 && !path_exist(_PATH_PROC_DEVICETREE
"/chosen/qemu,graphic-width")) {
701 desc
->hyper
= HYPER_PHYP
;
702 desc
->virtype
= VIRT_PARA
;
703 fd
= path_fopen("r", 0, _PATH_PROC_DEVICETREE
"/ibm,partition-name");
706 if (fscanf(fd
, "%255s", buf
) == 1 && !strcmp(buf
, "full"))
707 desc
->virtype
= VIRT_NONE
;
712 } else if (is_compatible(_PATH_PROC_DEVICETREE
"/compatible", "qemu,pseries")) {
713 desc
->hyper
= HYPER_KVM
;
714 desc
->virtype
= VIRT_PARA
;
719 #ifdef INCLUDE_VMWARE_BDOOR
721 #define VMWARE_BDOOR_MAGIC 0x564D5868
722 #define VMWARE_BDOOR_PORT 0x5658
723 #define VMWARE_BDOOR_CMD_GETVERSION 10
725 static UL_ASAN_BLACKLIST
726 void vmware_bdoor(uint32_t *eax
, uint32_t *ebx
, uint32_t *ecx
, uint32_t *edx
)
729 #if defined(__PIC__) && defined(__i386__)
730 /* x86 PIC cannot clobber ebx -- gcc bitches */
742 : "0" (VMWARE_BDOOR_MAGIC
),
743 "1" (VMWARE_BDOOR_CMD_GETVERSION
),
744 "2" (VMWARE_BDOOR_PORT
),
749 static jmp_buf segv_handler_env
;
752 segv_handler(__attribute__((__unused__
)) int sig
,
753 __attribute__((__unused__
)) siginfo_t
*info
,
754 __attribute__((__unused__
)) void *ignored
)
756 siglongjmp(segv_handler_env
, 1);
760 is_vmware_platform(void)
762 uint32_t eax
, ebx
, ecx
, edx
;
763 struct sigaction act
, oact
;
766 * The assembly routine for vmware detection works
767 * fine under vmware, even if ran as regular user. But
768 * on real HW or under other hypervisors, it segfaults (which is
769 * expected). So we temporarily install SIGSEGV handler to catch
770 * the signal. All this magic is needed because lscpu
771 * isn't supposed to require root privileges.
773 if (sigsetjmp(segv_handler_env
, 1))
776 memset(&act
, 0, sizeof(act
));
777 act
.sa_sigaction
= segv_handler
;
778 act
.sa_flags
= SA_SIGINFO
;
780 if (sigaction(SIGSEGV
, &act
, &oact
))
781 err(EXIT_FAILURE
, _("error: can not set signal handler"));
783 vmware_bdoor(&eax
, &ebx
, &ecx
, &edx
);
785 if (sigaction(SIGSEGV
, &oact
, NULL
))
786 err(EXIT_FAILURE
, _("error: can not restore signal handler"));
788 return eax
!= (uint32_t)-1 && ebx
== VMWARE_BDOOR_MAGIC
;
791 #else /* ! INCLUDE_VMWARE_BDOOR */
794 is_vmware_platform(void)
799 #endif /* INCLUDE_VMWARE_BDOOR */
802 read_hypervisor(struct lscpu_desc
*desc
, struct lscpu_modifier
*mod
)
806 if (mod
->system
!= SYSTEM_SNAPSHOT
) {
807 read_hypervisor_cpuid(desc
);
809 desc
->hyper
= read_hypervisor_dmi();
810 if (!desc
->hyper
&& is_vmware_platform())
811 desc
->hyper
= HYPER_VMWARE
;
815 desc
->virtype
= VIRT_FULL
;
817 else if (read_hypervisor_powerpc(desc
) > 0) {}
819 /* Xen para-virt or dom0 */
820 else if (path_exist(_PATH_PROC_XEN
)) {
822 fd
= path_fopen("r", 0, _PATH_PROC_XENCAP
);
827 if (fscanf(fd
, "%255s", buf
) == 1 &&
828 !strcmp(buf
, "control_d"))
832 desc
->virtype
= dom0
? VIRT_NONE
: VIRT_PARA
;
833 desc
->hyper
= HYPER_XEN
;
835 /* Xen full-virt on non-x86_64 */
836 } else if (has_pci_device( hv_vendor_pci
[HYPER_XEN
], hv_graphics_pci
[HYPER_XEN
])) {
837 desc
->hyper
= HYPER_XEN
;
838 desc
->virtype
= VIRT_FULL
;
839 } else if (has_pci_device( hv_vendor_pci
[HYPER_VMWARE
], hv_graphics_pci
[HYPER_VMWARE
])) {
840 desc
->hyper
= HYPER_VMWARE
;
841 desc
->virtype
= VIRT_FULL
;
842 } else if (has_pci_device( hv_vendor_pci
[HYPER_VBOX
], hv_graphics_pci
[HYPER_VBOX
])) {
843 desc
->hyper
= HYPER_VBOX
;
844 desc
->virtype
= VIRT_FULL
;
847 } else if (path_exist(_PATH_PROC_SYSINFO
)) {
848 FILE *sysinfo_fd
= path_fopen("r", 0, _PATH_PROC_SYSINFO
);
853 desc
->hyper
= HYPER_IBM
;
854 desc
->hypervisor
= "PR/SM";
855 desc
->virtype
= VIRT_FULL
;
856 while (fgets(buf
, sizeof(buf
), sysinfo_fd
) != NULL
) {
859 if (!strstr(buf
, "Control Program:"))
861 if (!strstr(buf
, "KVM"))
862 desc
->hyper
= HYPER_IBM
;
864 desc
->hyper
= HYPER_KVM
;
865 str
= strchr(buf
, ':');
868 xasprintf(&str
, "%s", str
+ 1);
870 /* remove leading, trailing and repeating whitespace */
873 desc
->hypervisor
= str
;
874 str
+= strlen(str
) - 1;
875 while ((*str
== '\n') || (*str
== ' '))
877 while ((str
= strstr(desc
->hypervisor
, " ")))
878 memmove(str
, str
+ 1, strlen(str
));
883 /* OpenVZ/Virtuozzo - /proc/vz dir should exist
884 * /proc/bc should not */
885 else if (path_exist(_PATH_PROC_VZ
) && !path_exist(_PATH_PROC_BC
)) {
886 desc
->hyper
= HYPER_PARALLELS
;
887 desc
->virtype
= VIRT_CONT
;
890 } else if (desc
->vendor
&&
891 (strcmp(desc
->vendor
, "PowerVM Lx86") == 0 ||
892 strcmp(desc
->vendor
, "IBM/S390") == 0)) {
893 desc
->hyper
= HYPER_IBM
;
894 desc
->virtype
= VIRT_FULL
;
896 /* User-mode-linux */
897 } else if (desc
->modelname
&& strstr(desc
->modelname
, "UML")) {
898 desc
->hyper
= HYPER_UML
;
899 desc
->virtype
= VIRT_PARA
;
902 } else if (path_exist(_PATH_PROC_STATUS
)) {
906 fd
= path_fopen("r", 1, _PATH_PROC_STATUS
);
907 while (fgets(buf
, sizeof(buf
), fd
) != NULL
) {
908 if (lookup(buf
, "VxID", &val
))
914 while (isdigit(*val
))
917 desc
->hyper
= HYPER_VSERVER
;
918 desc
->virtype
= VIRT_CONT
;
924 /* add @set to the @ary, unnecessary set is deallocated. */
925 static int add_cpuset_to_array(cpu_set_t
**ary
, int *items
, cpu_set_t
*set
)
928 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
933 for (i
= 0; i
< *items
; i
++) {
934 if (CPU_EQUAL_S(setsize
, set
, ary
[i
]))
947 read_topology(struct lscpu_desc
*desc
, int idx
)
949 cpu_set_t
*thread_siblings
, *core_siblings
, *book_siblings
;
950 int num
= real_cpu_num(desc
, idx
);
952 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/topology/thread_siblings", num
))
955 thread_siblings
= path_read_cpuset(maxcpus
, _PATH_SYS_CPU
956 "/cpu%d/topology/thread_siblings", num
);
957 core_siblings
= path_read_cpuset(maxcpus
, _PATH_SYS_CPU
958 "/cpu%d/topology/core_siblings", num
);
959 book_siblings
= NULL
;
960 if (path_exist(_PATH_SYS_CPU
"/cpu%d/topology/book_siblings", num
))
961 book_siblings
= path_read_cpuset(maxcpus
, _PATH_SYS_CPU
962 "/cpu%d/topology/book_siblings", num
);
964 if (!desc
->coremaps
) {
965 int nbooks
, nsockets
, ncores
, nthreads
;
966 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
968 /* threads within one core */
969 nthreads
= CPU_COUNT_S(setsize
, thread_siblings
);
973 /* cores within one socket */
974 ncores
= CPU_COUNT_S(setsize
, core_siblings
) / nthreads
;
978 /* number of sockets within one book. Because of odd /
979 * non-present cpu maps and to keep calculation easy we make
980 * sure that nsockets and nbooks is at least 1.
982 nsockets
= desc
->ncpus
/ nthreads
/ ncores
;
986 /* number of books */
987 nbooks
= desc
->ncpus
/ nthreads
/ ncores
/ nsockets
;
991 /* all threads, see also read_basicinfo()
992 * -- fallback for kernels without
993 * /sys/devices/system/cpu/online.
996 desc
->nthreads
= nbooks
* nsockets
* ncores
* nthreads
;
998 /* For each map we make sure that it can have up to ncpuspos
999 * entries. This is because we cannot reliably calculate the
1000 * number of cores, sockets and books on all architectures.
1001 * E.g. completely virtualized architectures like s390 may
1002 * have multiple sockets of different sizes.
1004 desc
->coremaps
= xcalloc(desc
->ncpuspos
, sizeof(cpu_set_t
*));
1005 desc
->socketmaps
= xcalloc(desc
->ncpuspos
, sizeof(cpu_set_t
*));
1007 desc
->bookmaps
= xcalloc(desc
->ncpuspos
, sizeof(cpu_set_t
*));
1010 add_cpuset_to_array(desc
->socketmaps
, &desc
->nsockets
, core_siblings
);
1011 add_cpuset_to_array(desc
->coremaps
, &desc
->ncores
, thread_siblings
);
1013 add_cpuset_to_array(desc
->bookmaps
, &desc
->nbooks
, book_siblings
);
1017 read_polarization(struct lscpu_desc
*desc
, int idx
)
1020 int num
= real_cpu_num(desc
, idx
);
1022 if (desc
->dispatching
< 0)
1024 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/polarization", num
))
1026 if (!desc
->polarization
)
1027 desc
->polarization
= xcalloc(desc
->ncpuspos
, sizeof(int));
1028 path_read_str(mode
, sizeof(mode
), _PATH_SYS_CPU
"/cpu%d/polarization", num
);
1029 if (strncmp(mode
, "vertical:low", sizeof(mode
)) == 0)
1030 desc
->polarization
[idx
] = POLAR_VLOW
;
1031 else if (strncmp(mode
, "vertical:medium", sizeof(mode
)) == 0)
1032 desc
->polarization
[idx
] = POLAR_VMEDIUM
;
1033 else if (strncmp(mode
, "vertical:high", sizeof(mode
)) == 0)
1034 desc
->polarization
[idx
] = POLAR_VHIGH
;
1035 else if (strncmp(mode
, "horizontal", sizeof(mode
)) == 0)
1036 desc
->polarization
[idx
] = POLAR_HORIZONTAL
;
1038 desc
->polarization
[idx
] = POLAR_UNKNOWN
;
1042 read_address(struct lscpu_desc
*desc
, int idx
)
1044 int num
= real_cpu_num(desc
, idx
);
1046 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/address", num
))
1048 if (!desc
->addresses
)
1049 desc
->addresses
= xcalloc(desc
->ncpuspos
, sizeof(int));
1050 desc
->addresses
[idx
] = path_read_s32(_PATH_SYS_CPU
"/cpu%d/address", num
);
1054 read_configured(struct lscpu_desc
*desc
, int idx
)
1056 int num
= real_cpu_num(desc
, idx
);
1058 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/configure", num
))
1060 if (!desc
->configured
)
1061 desc
->configured
= xcalloc(desc
->ncpuspos
, sizeof(int));
1062 desc
->configured
[idx
] = path_read_s32(_PATH_SYS_CPU
"/cpu%d/configure", num
);
1066 read_max_mhz(struct lscpu_desc
*desc
, int idx
)
1068 int num
= real_cpu_num(desc
, idx
);
1070 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/cpufreq/cpuinfo_max_freq", num
))
1073 desc
->maxmhz
= xcalloc(desc
->ncpuspos
, sizeof(char *));
1074 xasprintf(&(desc
->maxmhz
[idx
]), "%.4f",
1075 (float)path_read_s32(_PATH_SYS_CPU
1076 "/cpu%d/cpufreq/cpuinfo_max_freq", num
) / 1000);
1080 read_min_mhz(struct lscpu_desc
*desc
, int idx
)
1082 int num
= real_cpu_num(desc
, idx
);
1084 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/cpufreq/cpuinfo_min_freq", num
))
1087 desc
->minmhz
= xcalloc(desc
->ncpuspos
, sizeof(char *));
1088 xasprintf(&(desc
->minmhz
[idx
]), "%.4f",
1089 (float)path_read_s32(_PATH_SYS_CPU
1090 "/cpu%d/cpufreq/cpuinfo_min_freq", num
) / 1000);
1094 cachecmp(const void *a
, const void *b
)
1096 struct cpu_cache
*c1
= (struct cpu_cache
*) a
;
1097 struct cpu_cache
*c2
= (struct cpu_cache
*) b
;
1099 return strcmp(c2
->name
, c1
->name
);
1103 read_cache(struct lscpu_desc
*desc
, int idx
)
1107 int num
= real_cpu_num(desc
, idx
);
1109 if (!desc
->ncaches
) {
1110 while(path_exist(_PATH_SYS_CPU
"/cpu%d/cache/index%d",
1111 num
, desc
->ncaches
))
1117 desc
->caches
= xcalloc(desc
->ncaches
, sizeof(*desc
->caches
));
1119 for (i
= 0; i
< desc
->ncaches
; i
++) {
1120 struct cpu_cache
*ca
= &desc
->caches
[i
];
1123 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/cache/index%d",
1130 path_read_str(buf
, sizeof(buf
),
1131 _PATH_SYS_CPU
"/cpu%d/cache/index%d/type",
1133 if (!strcmp(buf
, "Data"))
1135 else if (!strcmp(buf
, "Instruction"))
1141 level
= path_read_s32(_PATH_SYS_CPU
"/cpu%d/cache/index%d/level",
1144 snprintf(buf
, sizeof(buf
), "L%d%c", level
, type
);
1146 snprintf(buf
, sizeof(buf
), "L%d", level
);
1148 ca
->name
= xstrdup(buf
);
1151 if (path_exist(_PATH_SYS_CPU
"/cpu%d/cache/index%d/size",num
, i
)) {
1152 path_read_str(buf
, sizeof(buf
),
1153 _PATH_SYS_CPU
"/cpu%d/cache/index%d/size", num
, i
);
1154 ca
->size
= xstrdup(buf
);
1156 ca
->size
= xstrdup("unknown size");
1160 /* information about how CPUs share different caches */
1161 map
= path_read_cpuset(maxcpus
,
1162 _PATH_SYS_CPU
"/cpu%d/cache/index%d/shared_cpu_map",
1165 if (!ca
->sharedmaps
)
1166 ca
->sharedmaps
= xcalloc(desc
->ncpuspos
, sizeof(cpu_set_t
*));
1167 add_cpuset_to_array(ca
->sharedmaps
, &ca
->nsharedmaps
, map
);
1171 static inline int is_node_dirent(struct dirent
*d
)
1175 #ifdef _DIRENT_HAVE_D_TYPE
1176 (d
->d_type
== DT_DIR
|| d
->d_type
== DT_UNKNOWN
) &&
1178 strncmp(d
->d_name
, "node", 4) == 0 &&
1179 isdigit_string(d
->d_name
+ 4);
1183 nodecmp(const void *ap
, const void *bp
)
1185 int *a
= (int *) ap
, *b
= (int *) bp
;
1190 read_nodes(struct lscpu_desc
*desc
)
1197 /* number of NUMA node */
1198 path
= path_strdup(_PATH_SYS_NODE
);
1199 dir
= opendir(path
);
1202 while (dir
&& (d
= readdir(dir
))) {
1203 if (is_node_dirent(d
))
1207 if (!desc
->nnodes
) {
1213 desc
->nodemaps
= xcalloc(desc
->nnodes
, sizeof(cpu_set_t
*));
1214 desc
->idx2nodenum
= xmalloc(desc
->nnodes
* sizeof(int));
1218 while ((d
= readdir(dir
)) && i
< desc
->nnodes
) {
1219 if (is_node_dirent(d
))
1220 desc
->idx2nodenum
[i
++] = strtol_or_err(((d
->d_name
) + 4),
1221 _("Failed to extract the node number"));
1224 qsort(desc
->idx2nodenum
, desc
->nnodes
, sizeof(int), nodecmp
);
1227 /* information about how nodes share different CPUs */
1228 for (i
= 0; i
< desc
->nnodes
; i
++)
1229 desc
->nodemaps
[i
] = path_read_cpuset(maxcpus
,
1230 _PATH_SYS_NODE
"/node%d/cpumap",
1231 desc
->idx2nodenum
[i
]);
1235 get_cell_data(struct lscpu_desc
*desc
, int idx
, int col
,
1236 struct lscpu_modifier
*mod
,
1237 char *buf
, size_t bufsz
)
1239 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
1241 int cpu
= real_cpu_num(desc
, idx
);
1247 snprintf(buf
, bufsz
, "%d", cpu
);
1250 if (cpuset_ary_isset(cpu
, desc
->coremaps
,
1251 desc
->ncores
, setsize
, &i
) == 0)
1252 snprintf(buf
, bufsz
, "%zu", i
);
1255 if (cpuset_ary_isset(cpu
, desc
->socketmaps
,
1256 desc
->nsockets
, setsize
, &i
) == 0)
1257 snprintf(buf
, bufsz
, "%zu", i
);
1260 if (cpuset_ary_isset(cpu
, desc
->nodemaps
,
1261 desc
->nnodes
, setsize
, &i
) == 0)
1262 snprintf(buf
, bufsz
, "%d", desc
->idx2nodenum
[i
]);
1265 if (cpuset_ary_isset(cpu
, desc
->bookmaps
,
1266 desc
->nbooks
, setsize
, &i
) == 0)
1267 snprintf(buf
, bufsz
, "%zu", i
);
1275 for (j
= desc
->ncaches
- 1; j
>= 0; j
--) {
1276 struct cpu_cache
*ca
= &desc
->caches
[j
];
1278 if (cpuset_ary_isset(cpu
, ca
->sharedmaps
,
1279 ca
->nsharedmaps
, setsize
, &i
) == 0) {
1280 int x
= snprintf(p
, sz
, "%zu", i
);
1281 if (x
< 0 || (size_t) x
>= sz
)
1289 *p
++ = mod
->compat
? ',' : ':';
1296 case COL_POLARIZATION
:
1297 if (desc
->polarization
) {
1298 int x
= desc
->polarization
[idx
];
1300 snprintf(buf
, bufsz
, "%s",
1301 mod
->mode
== OUTPUT_PARSABLE
?
1302 polar_modes
[x
].parsable
:
1303 polar_modes
[x
].readable
);
1307 if (desc
->addresses
)
1308 snprintf(buf
, bufsz
, "%d", desc
->addresses
[idx
]);
1310 case COL_CONFIGURED
:
1311 if (!desc
->configured
)
1313 if (mod
->mode
== OUTPUT_PARSABLE
)
1314 snprintf(buf
, bufsz
, "%s",
1315 desc
->configured
[idx
] ? _("Y") : _("N"));
1317 snprintf(buf
, bufsz
, "%s",
1318 desc
->configured
[idx
] ? _("yes") : _("no"));
1323 if (mod
->mode
== OUTPUT_PARSABLE
)
1324 snprintf(buf
, bufsz
, "%s",
1325 is_cpu_online(desc
, cpu
) ? _("Y") : _("N"));
1327 snprintf(buf
, bufsz
, "%s",
1328 is_cpu_online(desc
, cpu
) ? _("yes") : _("no"));
1332 xstrncpy(buf
, desc
->maxmhz
[idx
], bufsz
);
1336 xstrncpy(buf
, desc
->minmhz
[idx
], bufsz
);
1343 get_cell_header(struct lscpu_desc
*desc
, int col
,
1344 struct lscpu_modifier
*mod
,
1345 char *buf
, size_t bufsz
)
1349 if (col
== COL_CACHE
) {
1354 for (i
= desc
->ncaches
- 1; i
>= 0; i
--) {
1355 int x
= snprintf(p
, sz
, "%s", desc
->caches
[i
].name
);
1356 if (x
< 0 || (size_t) x
>= sz
)
1363 *p
++ = mod
->compat
? ',' : ':';
1371 snprintf(buf
, bufsz
, "%s", coldescs
[col
].name
);
1376 * [-p] backend, we support two parsable formats:
1378 * 1) "compatible" -- this format is compatible with the original lscpu(1)
1379 * output and it contains fixed set of the columns. The CACHE columns are at
1380 * the end of the line and the CACHE is not printed if the number of the caches
1381 * is zero. The CACHE columns are separated by two commas, for example:
1384 * # CPU,Core,Socket,Node,,L1d,L1i,L2
1388 * 2) "user defined output" -- this format prints always all columns without
1389 * special prefix for CACHE column. If there are not CACHEs then the column is
1390 * empty and the header "Cache" is printed rather than a real name of the cache.
1391 * The CACHE columns are separated by ':'.
1393 * $ lscpu --parse=CPU,CORE,SOCKET,NODE,CACHE
1394 * # CPU,Core,Socket,Node,L1d:L1i:L2
1399 print_parsable(struct lscpu_desc
*desc
, int cols
[], int ncols
,
1400 struct lscpu_modifier
*mod
)
1402 char buf
[BUFSIZ
], *data
;
1409 "# The following is the parsable format, which can be fed to other\n"
1410 "# programs. Each different item in every column has an unique ID\n"
1411 "# starting from zero.\n"));
1413 fputs("# ", stdout
);
1414 for (i
= 0; i
< ncols
; i
++) {
1417 if (col
== COL_CACHE
) {
1418 if (mod
->compat
&& !desc
->ncaches
)
1420 if (mod
->compat
&& i
!= 0)
1426 data
= get_cell_header(desc
, col
, mod
, buf
, sizeof(buf
));
1428 if (data
&& * data
&& col
!= COL_CACHE
&&
1429 !coldescs
[col
].is_abbr
) {
1431 * For normal column names use mixed case (e.g. "Socket")
1435 while (p
&& *p
!= '\0') {
1436 *p
= tolower((unsigned int) *p
);
1440 fputs(data
&& *data
? data
: "", stdout
);
1447 for (i
= 0; i
< desc
->ncpuspos
; i
++) {
1449 int cpu
= real_cpu_num(desc
, i
);
1451 if (!mod
->offline
&& desc
->online
&& !is_cpu_online(desc
, cpu
))
1453 if (!mod
->online
&& desc
->online
&& is_cpu_online(desc
, cpu
))
1455 if (desc
->present
&& !is_cpu_present(desc
, cpu
))
1457 for (c
= 0; c
< ncols
; c
++) {
1458 if (mod
->compat
&& cols
[c
] == COL_CACHE
) {
1467 data
= get_cell_data(desc
, i
, cols
[c
], mod
,
1469 fputs(data
&& *data
? data
: "", stdout
);
1479 print_readable(struct lscpu_desc
*desc
, int cols
[], int ncols
,
1480 struct lscpu_modifier
*mod
)
1485 struct libscols_table
*table
;
1487 scols_init_debug(0);
1489 table
= scols_new_table();
1491 err(EXIT_FAILURE
, _("failed to initialize output table"));
1493 for (i
= 0; i
< ncols
; i
++) {
1494 data
= get_cell_header(desc
, cols
[i
], mod
, buf
, sizeof(buf
));
1495 if (!scols_table_new_column(table
, xstrdup(data
), 0, 0))
1496 err(EXIT_FAILURE
, _("failed to initialize output column"));
1499 for (i
= 0; i
< desc
->ncpuspos
; i
++) {
1501 struct libscols_line
*line
;
1502 int cpu
= real_cpu_num(desc
, i
);
1504 if (!mod
->offline
&& desc
->online
&& !is_cpu_online(desc
, cpu
))
1506 if (!mod
->online
&& desc
->online
&& is_cpu_online(desc
, cpu
))
1508 if (desc
->present
&& !is_cpu_present(desc
, cpu
))
1511 line
= scols_table_new_line(table
, NULL
);
1513 err(EXIT_FAILURE
, _("failed to initialize output line"));
1515 for (c
= 0; c
< ncols
; c
++) {
1516 data
= get_cell_data(desc
, i
, cols
[c
], mod
,
1518 if (!data
|| !*data
)
1520 scols_line_set_data(line
, c
, data
);
1524 scols_print_table(table
);
1525 scols_unref_table(table
);
1528 /* output formats "<key> <value>"*/
1529 #define print_s(_key, _val) printf("%-23s%s\n", _key, _val)
1530 #define print_n(_key, _val) printf("%-23s%d\n", _key, _val)
1533 print_cpuset(const char *key
, cpu_set_t
*set
, int hex
)
1535 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
1536 size_t setbuflen
= 7 * maxcpus
;
1537 char setbuf
[setbuflen
], *p
;
1540 p
= cpumask_create(setbuf
, setbuflen
, set
, setsize
);
1541 printf("%-23s0x%s\n", key
, p
);
1543 p
= cpulist_create(setbuf
, setbuflen
, set
, setsize
);
1553 print_summary(struct lscpu_desc
*desc
, struct lscpu_modifier
*mod
)
1557 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
1559 print_s(_("Architecture:"), desc
->arch
);
1562 char mbuf
[64], *p
= mbuf
;
1564 if (desc
->mode
& MODE_32BIT
) {
1565 strcpy(p
, "32-bit, ");
1568 if (desc
->mode
& MODE_64BIT
) {
1569 strcpy(p
, "64-bit, ");
1573 print_s(_("CPU op-mode(s):"), mbuf
);
1575 #if !defined(WORDS_BIGENDIAN)
1576 print_s(_("Byte Order:"), "Little Endian");
1578 print_s(_("Byte Order:"), "Big Endian");
1580 print_n(_("CPU(s):"), desc
->ncpus
);
1583 print_cpuset(mod
->hex
? _("On-line CPU(s) mask:") :
1584 _("On-line CPU(s) list:"),
1585 desc
->online
, mod
->hex
);
1587 if (desc
->online
&& CPU_COUNT_S(setsize
, desc
->online
) != desc
->ncpus
) {
1590 /* Linux kernel provides cpuset of off-line CPUs that contains
1591 * all configured CPUs (see /sys/devices/system/cpu/offline),
1592 * but want to print real (present in system) off-line CPUs only.
1594 set
= cpuset_alloc(maxcpus
, NULL
, NULL
);
1596 err(EXIT_FAILURE
, _("failed to callocate cpu set"));
1597 CPU_ZERO_S(setsize
, set
);
1598 for (i
= 0; i
< desc
->ncpuspos
; i
++) {
1599 int cpu
= real_cpu_num(desc
, i
);
1600 if (!is_cpu_online(desc
, cpu
) && is_cpu_present(desc
, cpu
))
1601 CPU_SET_S(cpu
, setsize
, set
);
1603 print_cpuset(mod
->hex
? _("Off-line CPU(s) mask:") :
1604 _("Off-line CPU(s) list:"),
1609 if (desc
->nsockets
) {
1610 int cores_per_socket
, sockets_per_book
, books
;
1612 cores_per_socket
= sockets_per_book
= books
= 0;
1613 /* s390 detects its cpu topology via /proc/sysinfo, if present.
1614 * Using simply the cpu topology masks in sysfs will not give
1615 * usable results since everything is virtualized. E.g.
1616 * virtual core 0 may have only 1 cpu, but virtual core 2 may
1618 * If the cpu topology is not exported (e.g. 2nd level guest)
1619 * fall back to old calculation scheme.
1621 if (path_exist(_PATH_PROC_SYSINFO
)) {
1622 FILE *fd
= path_fopen("r", 0, _PATH_PROC_SYSINFO
);
1626 while (fd
&& fgets(pbuf
, sizeof(pbuf
), fd
) != NULL
) {
1627 if (sscanf(pbuf
, "CPU Topology SW:%d%d%d%d%d%d",
1628 &t0
, &t1
, &t2
, &books
, &sockets_per_book
,
1629 &cores_per_socket
) == 6)
1635 print_n(_("Thread(s) per core:"), desc
->nthreads
/ desc
->ncores
);
1636 print_n(_("Core(s) per socket:"),
1637 cores_per_socket
?: desc
->ncores
/ desc
->nsockets
);
1639 print_n(_("Socket(s) per book:"),
1640 sockets_per_book
?: desc
->nsockets
/ desc
->nbooks
);
1641 print_n(_("Book(s):"), books
?: desc
->nbooks
);
1643 print_n(_("Socket(s):"), sockets_per_book
?: desc
->nsockets
);
1647 print_n(_("NUMA node(s):"), desc
->nnodes
);
1649 print_s(_("Vendor ID:"), desc
->vendor
);
1651 print_s(_("CPU family:"), desc
->family
);
1652 if (desc
->model
|| desc
->revision
)
1653 print_s(_("Model:"), desc
->revision
? desc
->revision
: desc
->model
);
1654 if (desc
->modelname
|| desc
->cpu
)
1655 print_s(_("Model name:"), desc
->cpu
? desc
->cpu
: desc
->modelname
);
1657 print_s(_("Stepping:"), desc
->stepping
);
1659 print_s(_("CPU MHz:"), desc
->mhz
);
1661 print_s(_("CPU max MHz:"), desc
->maxmhz
[0]);
1663 print_s(_("CPU min MHz:"), desc
->minmhz
[0]);
1665 print_s(_("BogoMIPS:"), desc
->bogomips
);
1666 if (desc
->virtflag
) {
1667 if (!strcmp(desc
->virtflag
, "svm"))
1668 print_s(_("Virtualization:"), "AMD-V");
1669 else if (!strcmp(desc
->virtflag
, "vmx"))
1670 print_s(_("Virtualization:"), "VT-x");
1672 if (desc
->hypervisor
)
1673 print_s(_("Hypervisor:"), desc
->hypervisor
);
1675 print_s(_("Hypervisor vendor:"), hv_vendors
[desc
->hyper
]);
1676 print_s(_("Virtualization type:"), _(virt_types
[desc
->virtype
]));
1678 if (desc
->dispatching
>= 0)
1679 print_s(_("Dispatching mode:"), _(disp_modes
[desc
->dispatching
]));
1680 if (desc
->ncaches
) {
1683 for (i
= desc
->ncaches
- 1; i
>= 0; i
--) {
1684 snprintf(cbuf
, sizeof(cbuf
),
1685 _("%s cache:"), desc
->caches
[i
].name
);
1686 print_s(cbuf
, desc
->caches
[i
].size
);
1690 for (i
= 0; i
< desc
->nnodes
; i
++) {
1691 snprintf(buf
, sizeof(buf
), _("NUMA node%d CPU(s):"), desc
->idx2nodenum
[i
]);
1692 print_cpuset(buf
, desc
->nodemaps
[i
], mod
->hex
);
1696 print_s(_("Flags:"), desc
->flags
);
1698 if (desc
->physsockets
) {
1699 print_n(_("Physical sockets:"), desc
->physsockets
);
1700 print_n(_("Physical chips:"), desc
->physchips
);
1701 print_n(_("Physical cores/chip:"), desc
->physcoresperchip
);
1705 static void __attribute__((__noreturn__
)) usage(FILE *out
)
1709 fputs(USAGE_HEADER
, out
);
1710 fprintf(out
, _(" %s [options]\n"), program_invocation_short_name
);
1712 fputs(USAGE_SEPARATOR
, out
);
1713 fputs(_("Display information about the CPU architecture.\n"), out
);
1715 fputs(USAGE_OPTIONS
, out
);
1716 fputs(_(" -a, --all print both online and offline CPUs (default for -e)\n"), out
);
1717 fputs(_(" -b, --online print online CPUs only (default for -p)\n"), out
);
1718 fputs(_(" -c, --offline print offline CPUs only\n"), out
);
1719 fputs(_(" -e, --extended[=<list>] print out an extended readable format\n"), out
);
1720 fputs(_(" -p, --parse[=<list>] print out a parsable format\n"), out
);
1721 fputs(_(" -s, --sysroot <dir> use specified directory as system root\n"), out
);
1722 fputs(_(" -x, --hex print hexadecimal masks rather than lists of CPUs\n"), out
);
1723 fputs(USAGE_SEPARATOR
, out
);
1724 fputs(USAGE_HELP
, out
);
1725 fputs(USAGE_VERSION
, out
);
1727 fprintf(out
, _("\nAvailable columns:\n"));
1729 for (i
= 0; i
< ARRAY_SIZE(coldescs
); i
++)
1730 fprintf(out
, " %13s %s\n", coldescs
[i
].name
, _(coldescs
[i
].help
));
1732 fprintf(out
, USAGE_MAN_TAIL("lscpu(1)"));
1734 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
1737 int main(int argc
, char *argv
[])
1739 struct lscpu_modifier _mod
= { .mode
= OUTPUT_SUMMARY
}, *mod
= &_mod
;
1740 struct lscpu_desc _desc
= { .flags
= 0 }, *desc
= &_desc
;
1742 int columns
[ARRAY_SIZE(coldescs
)], ncolumns
= 0;
1743 int cpu_modifier_specified
= 0;
1745 static const struct option longopts
[] = {
1746 { "all", no_argument
, 0, 'a' },
1747 { "online", no_argument
, 0, 'b' },
1748 { "offline", no_argument
, 0, 'c' },
1749 { "help", no_argument
, 0, 'h' },
1750 { "extended", optional_argument
, 0, 'e' },
1751 { "parse", optional_argument
, 0, 'p' },
1752 { "sysroot", required_argument
, 0, 's' },
1753 { "hex", no_argument
, 0, 'x' },
1754 { "version", no_argument
, 0, 'V' },
1758 static const ul_excl_t excl
[] = { /* rows and cols in ASCII order */
1763 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
1765 setlocale(LC_ALL
, "");
1766 bindtextdomain(PACKAGE
, LOCALEDIR
);
1767 textdomain(PACKAGE
);
1768 atexit(close_stdout
);
1770 while ((c
= getopt_long(argc
, argv
, "abce::hp::s:xV", longopts
, NULL
)) != -1) {
1772 err_exclusive_options(c
, longopts
, excl
, excl_st
);
1776 mod
->online
= mod
->offline
= 1;
1777 cpu_modifier_specified
= 1;
1781 cpu_modifier_specified
= 1;
1785 cpu_modifier_specified
= 1;
1794 ncolumns
= string_to_idarray(optarg
,
1795 columns
, ARRAY_SIZE(columns
),
1798 return EXIT_FAILURE
;
1800 mod
->mode
= c
== 'p' ? OUTPUT_PARSABLE
: OUTPUT_READABLE
;
1803 path_set_prefix(optarg
);
1804 mod
->system
= SYSTEM_SNAPSHOT
;
1810 printf(UTIL_LINUX_VERSION
);
1811 return EXIT_SUCCESS
;
1817 if (cpu_modifier_specified
&& mod
->mode
== OUTPUT_SUMMARY
) {
1819 _("%s: options --all, --online and --offline may only "
1820 "be used with options --extended or --parse.\n"),
1821 program_invocation_short_name
);
1822 return EXIT_FAILURE
;
1828 /* set default cpu display mode if none was specified */
1829 if (!mod
->online
&& !mod
->offline
) {
1831 mod
->offline
= mod
->mode
== OUTPUT_READABLE
? 1 : 0;
1834 read_basicinfo(desc
, mod
);
1836 for (i
= 0; i
< desc
->ncpuspos
; i
++) {
1837 read_topology(desc
, i
);
1838 read_cache(desc
, i
);
1839 read_polarization(desc
, i
);
1840 read_address(desc
, i
);
1841 read_configured(desc
, i
);
1842 read_max_mhz(desc
, i
);
1843 read_min_mhz(desc
, i
);
1847 qsort(desc
->caches
, desc
->ncaches
,
1848 sizeof(struct cpu_cache
), cachecmp
);
1851 read_hypervisor(desc
, mod
);
1854 case OUTPUT_SUMMARY
:
1855 print_summary(desc
, mod
);
1857 case OUTPUT_PARSABLE
:
1859 columns
[ncolumns
++] = COL_CPU
;
1860 columns
[ncolumns
++] = COL_CORE
;
1861 columns
[ncolumns
++] = COL_SOCKET
;
1862 columns
[ncolumns
++] = COL_NODE
;
1863 columns
[ncolumns
++] = COL_CACHE
;
1866 print_parsable(desc
, columns
, ncolumns
, mod
);
1868 case OUTPUT_READABLE
:
1870 /* No list was given. Just print whatever is there. */
1871 columns
[ncolumns
++] = COL_CPU
;
1873 columns
[ncolumns
++] = COL_NODE
;
1875 columns
[ncolumns
++] = COL_BOOK
;
1876 if (desc
->socketmaps
)
1877 columns
[ncolumns
++] = COL_SOCKET
;
1879 columns
[ncolumns
++] = COL_CORE
;
1881 columns
[ncolumns
++] = COL_CACHE
;
1883 columns
[ncolumns
++] = COL_ONLINE
;
1884 if (desc
->configured
)
1885 columns
[ncolumns
++] = COL_CONFIGURED
;
1886 if (desc
->polarization
)
1887 columns
[ncolumns
++] = COL_POLARIZATION
;
1888 if (desc
->addresses
)
1889 columns
[ncolumns
++] = COL_ADDRESS
;
1891 columns
[ncolumns
++] = COL_MAXMHZ
;
1893 columns
[ncolumns
++] = COL_MINMHZ
;
1895 print_readable(desc
, columns
, ncolumns
, mod
);
1899 return EXIT_SUCCESS
;