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
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <sys/utsname.h>
33 #include <sys/types.h>
47 #define _PATH_SYS_SYSTEM "/sys/devices/system"
48 #define _PATH_SYS_CPU _PATH_SYS_SYSTEM "/cpu"
49 #define _PATH_PROC_XEN "/proc/xen"
50 #define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities"
51 #define _PATH_PROC_CPUINFO "/proc/cpuinfo"
52 #define _PATH_PROC_PCIDEVS "/proc/bus/pci/devices"
53 #define _PATH_PROC_SYSINFO "/proc/sysinfo"
55 /* virtualization types */
61 const char *virt_types
[] = {
62 [VIRT_NONE
] = N_("none"),
63 [VIRT_PARA
] = N_("para"),
64 [VIRT_FULL
] = N_("full")
67 /* hypervisor vendors */
76 const char *hv_vendors
[] = {
80 [HYPER_MSHV
] = "Microsoft",
81 [HYPER_VMWARE
] = "VMware",
87 MODE_32BIT
= (1 << 1),
91 /* cache(s) description */
97 cpu_set_t
**sharedmaps
;
100 /* dispatching modes */
106 const char *disp_modes
[] = {
107 [DISP_HORIZONTAL
] = N_("horizontal"),
108 [DISP_VERTICAL
] = N_("vertical")
111 /* cpu polarization */
120 const char *polar_modes
[] = {
121 [POLAR_UNKNOWN
] = "U",
123 [POLAR_VMEDIUM
] = "VM",
124 [POLAR_VHIGH
] = "VH",
125 [POLAR_HORIZONTAL
] = "H"
128 /* global description */
134 char *virtflag
; /* virtualization flag (vmx, svm) */
135 int hyper
; /* hypervisor vendor ID */
136 int virtype
; /* VIRT_PARA|FULL|NONE ? */
141 int dispatching
; /* none, horizontal or vertical */
142 int mode
; /* rm, lm or/and tm */
144 int ncpus
; /* number of CPUs */
145 cpu_set_t
*online
; /* mask with online CPUs */
147 int nnodes
; /* number of NUMA modes */
148 cpu_set_t
**nodemaps
; /* array with NUMA nodes */
150 /* books -- based on book_siblings (internal kernel map of cpuX's
151 * hardware threads within the same book */
152 int nbooks
; /* number of all online books */
153 cpu_set_t
**bookmaps
; /* unique book_siblings */
155 /* sockets -- based on core_siblings (internal kernel map of cpuX's
156 * hardware threads within the same physical_package_id (socket)) */
157 int nsockets
; /* number of all online sockets */
158 cpu_set_t
**socketmaps
; /* unique core_siblings */
160 /* cores -- based on thread_siblings (internel kernel map of cpuX's
161 * hardware threads within the same core as cpuX) */
162 int ncores
; /* number of all online cores */
163 cpu_set_t
**coremaps
; /* unique thread_siblings */
165 int nthreads
; /* number of online threads */
168 struct cpu_cache
*caches
;
170 int *polarization
; /* cpu polarization */
171 int *addresses
; /* physical cpu addresses */
174 static size_t sysrootlen
;
175 static char pathbuf
[PATH_MAX
];
176 static int maxcpus
; /* size in bits of kernel cpu mask */
178 #define is_cpu_online(_d, _cpu) \
179 ((_d) && (_d)->online ? \
180 CPU_ISSET_S((_cpu), CPU_ALLOC_SIZE(maxcpus), (_d)->online) : 0)
182 static FILE *path_fopen(const char *mode
, int exit_on_err
, const char *path
, ...)
183 __attribute__ ((__format__ (__printf__
, 3, 4)));
184 static void path_getstr(char *result
, size_t len
, const char *path
, ...)
185 __attribute__ ((__format__ (__printf__
, 3, 4)));
186 static int path_getnum(const char *path
, ...)
187 __attribute__ ((__format__ (__printf__
, 1, 2)));
188 static int path_exist(const char *path
, ...)
189 __attribute__ ((__format__ (__printf__
, 1, 2)));
190 static cpu_set_t
*path_cpuset(const char *path
, ...)
191 __attribute__ ((__format__ (__printf__
, 1, 2)));
207 static const char *colnames
[] =
211 [COL_SOCKET
] = "Socket",
214 [COL_CACHE
] = "Cache",
215 [COL_POLARIZATION
] = "Polarization",
216 [COL_ADDRESS
] = "Address"
220 static int column_name_to_id(const char *name
, size_t namesz
)
224 for (i
= 0; i
< ARRAY_SIZE(colnames
); i
++) {
225 const char *cn
= colnames
[i
];
227 if (!strncasecmp(name
, cn
, namesz
) && !*(cn
+ namesz
))
230 warnx(_("unknown column: %s"), name
);
235 path_vcreate(const char *path
, va_list ap
)
238 vsnprintf(pathbuf
+ sysrootlen
,
239 sizeof(pathbuf
) - sysrootlen
, path
, ap
);
241 vsnprintf(pathbuf
, sizeof(pathbuf
), path
, ap
);
246 path_vfopen(const char *mode
, int exit_on_error
, const char *path
, va_list ap
)
249 const char *p
= path_vcreate(path
, ap
);
252 if (!f
&& exit_on_error
)
253 err(EXIT_FAILURE
, _("error: cannot open %s"), p
);
258 path_fopen(const char *mode
, int exit_on_error
, const char *path
, ...)
264 fd
= path_vfopen(mode
, exit_on_error
, path
, ap
);
271 path_getstr(char *result
, size_t len
, const char *path
, ...)
277 fd
= path_vfopen("r", 1, path
, ap
);
280 if (!fgets(result
, len
, fd
))
281 err(EXIT_FAILURE
, _("failed to read: %s"), pathbuf
);
284 len
= strlen(result
);
285 if (result
[len
- 1] == '\n')
286 result
[len
- 1] = '\0';
290 path_getnum(const char *path
, ...)
297 fd
= path_vfopen("r", 1, path
, ap
);
300 if (fscanf(fd
, "%d", &result
) != 1) {
302 err(EXIT_FAILURE
, _("failed to read: %s"), pathbuf
);
304 errx(EXIT_FAILURE
, _("parse error: %s"), pathbuf
);
311 path_exist(const char *path
, ...)
317 p
= path_vcreate(path
, ap
);
320 return access(p
, F_OK
) == 0;
324 path_cpuparse(int islist
, const char *path
, va_list ap
)
328 size_t setsize
, len
= maxcpus
* 7;
331 fd
= path_vfopen("r", 1, path
, ap
);
333 if (!fgets(buf
, len
, fd
))
334 err(EXIT_FAILURE
, _("failed to read: %s"), pathbuf
);
338 if (buf
[len
- 1] == '\n')
341 set
= cpuset_alloc(maxcpus
, &setsize
, NULL
);
343 err(EXIT_FAILURE
, _("failed to callocate cpu set"));
346 if (cpulist_parse(buf
, set
, setsize
, 0))
347 errx(EXIT_FAILURE
, _("failed to parse CPU list %s"), buf
);
349 if (cpumask_parse(buf
, set
, setsize
))
350 errx(EXIT_FAILURE
, _("failed to parse CPU mask %s"), buf
);
356 path_cpuset(const char *path
, ...)
362 set
= path_cpuparse(0, path
, ap
);
369 path_cpulist(const char *path
, ...)
375 set
= path_cpuparse(1, path
, ap
);
381 /* Lookup a pattern and get the value from cpuinfo.
384 * "<pattern> : <key>"
386 int lookup(char *line
, char *pattern
, char **value
)
389 int len
= strlen(pattern
);
395 if (strncmp(line
, pattern
, len
))
399 for (p
= line
+ len
; isspace(*p
); p
++);
406 for (++p
; isspace(*p
); p
++);
414 len
= strlen(line
) - 1;
415 for (p
= line
+ len
; isspace(*(p
-1)); p
--);
422 /* Don't init the mode for platforms where we are not able to
423 * detect that CPU supports 64-bit mode.
431 /* reading info from any /{sys,proc} dump, don't mix it with
432 * information about our real CPU */
435 #if defined(__alpha__) || defined(__ia64__)
436 m
|= MODE_64BIT
; /* 64bit platforms only */
438 /* platforms with 64bit flag in /proc/cpuinfo, define
439 * 32bit default here */
440 #if defined(__i386__) || defined(__x86_64__) || \
441 defined(__s390x__) || defined(__s390__) || defined(__sparc_v9__)
448 read_basicinfo(struct lscpu_desc
*desc
)
450 FILE *fp
= path_fopen("r", 1, _PATH_PROC_CPUINFO
);
452 struct utsname utsbuf
;
455 if (uname(&utsbuf
) == -1)
456 err(EXIT_FAILURE
, _("error: uname failed"));
457 desc
->arch
= xstrdup(utsbuf
.machine
);
460 while(path_exist(_PATH_SYS_SYSTEM
"/cpu/cpu%d", desc
->ncpus
))
464 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
465 if (lookup(buf
, "vendor", &desc
->vendor
)) ;
466 else if (lookup(buf
, "vendor_id", &desc
->vendor
)) ;
467 else if (lookup(buf
, "family", &desc
->family
)) ;
468 else if (lookup(buf
, "cpu family", &desc
->family
)) ;
469 else if (lookup(buf
, "model", &desc
->model
)) ;
470 else if (lookup(buf
, "stepping", &desc
->stepping
)) ;
471 else if (lookup(buf
, "cpu MHz", &desc
->mhz
)) ;
472 else if (lookup(buf
, "flags", &desc
->flags
)) ; /* x86 */
473 else if (lookup(buf
, "features", &desc
->flags
)) ; /* s390 */
474 else if (lookup(buf
, "type", &desc
->flags
)) ; /* sparc64 */
475 else if (lookup(buf
, "bogomips", &desc
->bogomips
)) ;
476 else if (lookup(buf
, "bogomips per cpu", &desc
->bogomips
)) ; /* s390 */
481 desc
->mode
= init_mode();
484 snprintf(buf
, sizeof(buf
), " %s ", desc
->flags
);
485 if (strstr(buf
, " svm "))
486 desc
->virtflag
= strdup("svm");
487 else if (strstr(buf
, " vmx "))
488 desc
->virtflag
= strdup("vmx");
489 if (strstr(buf
, " lm "))
490 desc
->mode
|= MODE_32BIT
| MODE_64BIT
; /* x86_64 */
491 if (strstr(buf
, " zarch "))
492 desc
->mode
|= MODE_32BIT
| MODE_64BIT
; /* s390x */
493 if (strstr(buf
, " sun4v ") || strstr(buf
, " sun4u "))
494 desc
->mode
|= MODE_32BIT
| MODE_64BIT
; /* sparc64 */
499 if (path_exist(_PATH_SYS_SYSTEM
"/cpu/kernel_max"))
500 /* note that kernel_max is maximum index [NR_CPUS-1] */
501 maxcpus
= path_getnum(_PATH_SYS_SYSTEM
"/cpu/kernel_max") + 1;
503 else if (!sysrootlen
)
504 /* the root is '/' so we are working with data from the current kernel */
505 maxcpus
= get_max_number_of_cpus();
507 /* we are reading some /sys snapshot instead of the real /sys,
508 * let's use any crazy number... */
509 maxcpus
= desc
->ncpus
> 2048 ? desc
->ncpus
: 2048;
511 /* get mask for online CPUs */
512 if (path_exist(_PATH_SYS_SYSTEM
"/cpu/online")) {
513 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
514 desc
->online
= path_cpulist(_PATH_SYS_SYSTEM
"/cpu/online");
515 desc
->nthreads
= CPU_COUNT_S(setsize
, desc
->online
);
518 /* get dispatching mode */
519 if (path_exist(_PATH_SYS_SYSTEM
"/cpu/dispatching"))
520 desc
->dispatching
= path_getnum(_PATH_SYS_SYSTEM
"/cpu/dispatching");
522 desc
->dispatching
= -1;
526 has_pci_device(int vendor
, int device
)
529 int num
, fn
, ven
, dev
;
532 f
= path_fopen("r", 0, _PATH_PROC_PCIDEVS
);
536 /* for more details about bus/pci/devices format see
537 * drivers/pci/proc.c in linux kernel
539 while(fscanf(f
, "%02x%02x\t%04x%04x\t%*[^\n]",
540 &num
, &fn
, &ven
, &dev
) == 4) {
542 if (ven
== vendor
&& dev
== device
)
552 #if defined(__x86_64__) || defined(__i386__)
555 * This CPUID leaf returns the information about the hypervisor.
556 * EAX : maximum input value for CPUID supported by the hypervisor.
557 * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
559 #define HYPERVISOR_INFO_LEAF 0x40000000
562 cpuid(unsigned int op
, unsigned int *eax
, unsigned int *ebx
,
563 unsigned int *ecx
, unsigned int *edx
)
566 #if defined(__PIC__) && defined(__i386__)
567 /* x86 PIC cannot clobber ebx -- gcc bitches */
584 read_hypervisor_cpuid(struct lscpu_desc
*desc
)
586 unsigned int eax
= 0, ebx
= 0, ecx
= 0, edx
= 0;
587 char hyper_vendor_id
[13];
589 memset(hyper_vendor_id
, 0, sizeof(hyper_vendor_id
));
591 cpuid(HYPERVISOR_INFO_LEAF
, &eax
, &ebx
, &ecx
, &edx
);
592 memcpy(hyper_vendor_id
+ 0, &ebx
, 4);
593 memcpy(hyper_vendor_id
+ 4, &ecx
, 4);
594 memcpy(hyper_vendor_id
+ 8, &edx
, 4);
595 hyper_vendor_id
[12] = '\0';
597 if (!hyper_vendor_id
[0])
600 if (!strncmp("XenVMMXenVMM", hyper_vendor_id
, 12))
601 desc
->hyper
= HYPER_XEN
;
602 else if (!strncmp("KVMKVMKVM", hyper_vendor_id
, 9))
603 desc
->hyper
= HYPER_KVM
;
604 else if (!strncmp("Microsoft Hv", hyper_vendor_id
, 12))
605 desc
->hyper
= HYPER_MSHV
;
606 else if (!strncmp("VMwareVMware", hyper_vendor_id
, 12))
607 desc
->hyper
= HYPER_VMWARE
;
610 #else /* ! __x86_64__ */
612 read_hypervisor_cpuid(struct lscpu_desc
*desc
)
618 read_hypervisor(struct lscpu_desc
*desc
)
620 read_hypervisor_cpuid(desc
);
624 desc
->virtype
= VIRT_FULL
;
626 else if (path_exist(_PATH_PROC_XEN
)) {
627 /* Xen para-virt or dom0 */
628 FILE *fd
= path_fopen("r", 0, _PATH_PROC_XENCAP
);
634 if (fscanf(fd
, "%s", buf
) == 1 &&
635 !strcmp(buf
, "control_d"))
639 desc
->virtype
= dom0
? VIRT_NONE
: VIRT_PARA
;
640 desc
->hyper
= HYPER_XEN
;
642 } else if (has_pci_device(0x5853, 0x0001)) {
643 /* Xen full-virt on non-x86_64 */
644 desc
->hyper
= HYPER_XEN
;
645 desc
->virtype
= VIRT_FULL
;
646 } else if (path_exist(_PATH_PROC_SYSINFO
)) {
647 FILE *fd
= path_fopen("r", 0, _PATH_PROC_SYSINFO
);
650 desc
->hyper
= HYPER_IBM
;
651 desc
->virtype
= VIRT_FULL
;
652 while (fgets(buf
, sizeof(buf
), fd
) != NULL
) {
653 if (!strstr(buf
, "Control Program:"))
655 if (!strstr(buf
, "KVM"))
656 desc
->hyper
= HYPER_IBM
;
658 desc
->hyper
= HYPER_KVM
;
664 /* add @set to the @ary, unnecesary set is deallocated. */
665 static int add_cpuset_to_array(cpu_set_t
**ary
, int *items
, cpu_set_t
*set
)
668 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
673 for (i
= 0; i
< *items
; i
++) {
674 if (CPU_EQUAL_S(setsize
, set
, ary
[i
]))
687 read_topology(struct lscpu_desc
*desc
, int num
)
689 cpu_set_t
*thread_siblings
, *core_siblings
, *book_siblings
;
691 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/topology/thread_siblings", num
))
694 thread_siblings
= path_cpuset(_PATH_SYS_CPU
695 "/cpu%d/topology/thread_siblings", num
);
696 core_siblings
= path_cpuset(_PATH_SYS_CPU
697 "/cpu%d/topology/core_siblings", num
);
698 book_siblings
= NULL
;
699 if (path_exist(_PATH_SYS_CPU
"/cpu%d/topology/book_siblings", num
)) {
700 book_siblings
= path_cpuset(_PATH_SYS_CPU
701 "/cpu%d/topology/book_siblings", num
);
704 if (!desc
->coremaps
) {
705 int nbooks
, nsockets
, ncores
, nthreads
;
706 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
708 /* threads within one core */
709 nthreads
= CPU_COUNT_S(setsize
, thread_siblings
);
710 /* cores within one socket */
711 ncores
= CPU_COUNT_S(setsize
, core_siblings
) / nthreads
;
712 /* number of sockets within one book.
713 * Because of odd / non-present cpu maps and to keep
714 * calculation easy we make sure that nsockets and
715 * nbooks is at least 1.
717 nsockets
= desc
->ncpus
/ nthreads
/ ncores
?: 1;
718 /* number of books */
719 nbooks
= desc
->ncpus
/ nthreads
/ ncores
/ nsockets
?: 1;
721 /* all threads, see also read_basicinfo()
722 * -- fallback for kernels without
723 * /sys/devices/system/cpu/online.
726 desc
->nthreads
= nbooks
* nsockets
* ncores
* nthreads
;
727 /* For each map we make sure that it can have up to ncpus
728 * entries. This is because we cannot reliably calculate the
729 * number of cores, sockets and books on all architectures.
730 * E.g. completely virtualized architectures like s390 may
731 * have multiple sockets of different sizes.
733 desc
->coremaps
= xcalloc(desc
->ncpus
, sizeof(cpu_set_t
*));
734 desc
->socketmaps
= xcalloc(desc
->ncpus
, sizeof(cpu_set_t
*));
736 desc
->bookmaps
= xcalloc(desc
->ncpus
, sizeof(cpu_set_t
*));
739 add_cpuset_to_array(desc
->socketmaps
, &desc
->nsockets
, core_siblings
);
740 add_cpuset_to_array(desc
->coremaps
, &desc
->ncores
, thread_siblings
);
742 add_cpuset_to_array(desc
->bookmaps
, &desc
->nbooks
, book_siblings
);
745 read_polarization(struct lscpu_desc
*desc
, int num
)
749 if (desc
->dispatching
< 0)
751 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/polarization", num
))
753 if (!desc
->polarization
)
754 desc
->polarization
= xcalloc(desc
->ncpus
, sizeof(int));
755 path_getstr(mode
, sizeof(mode
), _PATH_SYS_CPU
"/cpu%d/polarization", num
);
756 if (strncmp(mode
, "vertical:low", sizeof(mode
)) == 0)
757 desc
->polarization
[num
] = POLAR_VLOW
;
758 else if (strncmp(mode
, "vertical:medium", sizeof(mode
)) == 0)
759 desc
->polarization
[num
] = POLAR_VMEDIUM
;
760 else if (strncmp(mode
, "vertical:high", sizeof(mode
)) == 0)
761 desc
->polarization
[num
] = POLAR_VHIGH
;
762 else if (strncmp(mode
, "horizontal", sizeof(mode
)) == 0)
763 desc
->polarization
[num
] = POLAR_HORIZONTAL
;
765 desc
->polarization
[num
] = POLAR_UNKNOWN
;
769 read_address(struct lscpu_desc
*desc
, int num
)
771 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/address", num
))
773 if (!desc
->addresses
)
774 desc
->addresses
= xcalloc(desc
->ncpus
, sizeof(int));
775 desc
->addresses
[num
] = path_getnum(_PATH_SYS_CPU
"/cpu%d/address", num
);
779 cachecmp(const void *a
, const void *b
)
781 struct cpu_cache
*c1
= (struct cpu_cache
*) a
;
782 struct cpu_cache
*c2
= (struct cpu_cache
*) b
;
784 return strcmp(c2
->name
, c1
->name
);
788 read_cache(struct lscpu_desc
*desc
, int num
)
793 if (!desc
->ncaches
) {
794 while(path_exist(_PATH_SYS_SYSTEM
"/cpu/cpu%d/cache/index%d",
801 desc
->caches
= xcalloc(desc
->ncaches
, sizeof(*desc
->caches
));
803 for (i
= 0; i
< desc
->ncaches
; i
++) {
804 struct cpu_cache
*ca
= &desc
->caches
[i
];
807 if (!path_exist(_PATH_SYS_SYSTEM
"/cpu/cpu%d/cache/index%d",
814 path_getstr(buf
, sizeof(buf
),
815 _PATH_SYS_CPU
"/cpu%d/cache/index%d/type",
817 if (!strcmp(buf
, "Data"))
819 else if (!strcmp(buf
, "Instruction"))
825 level
= path_getnum(_PATH_SYS_CPU
"/cpu%d/cache/index%d/level",
828 snprintf(buf
, sizeof(buf
), "L%d%c", level
, type
);
830 snprintf(buf
, sizeof(buf
), "L%d", level
);
832 ca
->name
= xstrdup(buf
);
835 path_getstr(buf
, sizeof(buf
),
836 _PATH_SYS_CPU
"/cpu%d/cache/index%d/size",
838 ca
->size
= xstrdup(buf
);
841 /* information about how CPUs share different caches */
842 map
= path_cpuset(_PATH_SYS_CPU
"/cpu%d/cache/index%d/shared_cpu_map",
846 ca
->sharedmaps
= xcalloc(desc
->ncpus
, sizeof(cpu_set_t
*));
847 add_cpuset_to_array(ca
->sharedmaps
, &ca
->nsharedmaps
, map
);
852 read_nodes(struct lscpu_desc
*desc
)
856 /* number of NUMA node */
857 while (path_exist(_PATH_SYS_SYSTEM
"/node/node%d", desc
->nnodes
))
863 desc
->nodemaps
= xcalloc(desc
->nnodes
, sizeof(cpu_set_t
*));
865 /* information about how nodes share different CPUs */
866 for (i
= 0; i
< desc
->nnodes
; i
++)
867 desc
->nodemaps
[i
] = path_cpuset(
868 _PATH_SYS_SYSTEM
"/node/node%d/cpumap",
873 print_parsable_cell(struct lscpu_desc
*desc
, int i
, int col
, int compatible
)
876 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
883 for (j
= 0; j
< desc
->ncores
; j
++) {
884 if (CPU_ISSET_S(i
, setsize
, desc
->coremaps
[j
])) {
891 for (j
= 0; j
< desc
->nsockets
; j
++) {
892 if (CPU_ISSET_S(i
, setsize
, desc
->socketmaps
[j
])) {
899 for (j
= 0; j
< desc
->nnodes
; j
++) {
900 if (CPU_ISSET_S(i
, setsize
, desc
->nodemaps
[j
])) {
907 for (j
= 0; j
< desc
->nbooks
; j
++) {
908 if (CPU_ISSET_S(i
, setsize
, desc
->bookmaps
[j
])) {
915 for (j
= desc
->ncaches
- 1; j
>= 0; j
--) {
916 struct cpu_cache
*ca
= &desc
->caches
[j
];
919 for (x
= 0; x
< ca
->nsharedmaps
; x
++) {
920 if (CPU_ISSET_S(i
, setsize
, ca
->sharedmaps
[x
])) {
926 putchar(compatible
? ',' : ':');
929 case COL_POLARIZATION
:
930 if (desc
->polarization
)
931 printf("%s", polar_modes
[desc
->polarization
[i
]]);
935 printf("%d", desc
->addresses
[i
]);
941 * We support two formats:
943 * 1) "compatible" -- this format is compatible with the original lscpu(1)
944 * output and it contains fixed set of the columns. The CACHE columns are at
945 * the end of the line and the CACHE is not printed if the number of the caches
946 * is zero. The CACHE columns are separated by two commas, for example:
949 * # CPU,Core,Socket,Node,,L1d,L1i,L2
953 * 2) "user defined output" -- this format prints always all columns without
954 * special prefix for CACHE column. If there are not CACHEs then the column is
955 * empty and the header "Cache" is printed rather than a real name of the cache.
956 * The CACHE columns are separated by ':'.
958 * $ lscpu --parse=CPU,CORE,SOCKET,NODE,CACHE
959 * # CPU,Core,Socket,Node,L1d:L1i:L2
964 print_parsable(struct lscpu_desc
*desc
, int cols
[], int ncols
, int compatible
)
969 "# The following is the parsable format, which can be fed to other\n"
970 "# programs. Each different item in every column has an unique ID\n"
971 "# starting from zero.\n"));
974 for (i
= 0; i
< ncols
; i
++) {
975 if (cols
[i
] == COL_CACHE
) {
976 if (compatible
&& !desc
->ncaches
)
980 if (compatible
&& i
!= 0)
982 for (c
= desc
->ncaches
- 1; c
>= 0; c
--) {
983 printf("%s", desc
->caches
[c
].name
);
985 putchar(compatible
? ',' : ':');
988 fputs(colnames
[cols
[i
]], stdout
);
992 fputs(colnames
[cols
[i
]], stdout
);
997 for (i
= 0; i
< desc
->ncpus
; i
++) {
998 if (desc
->online
&& !is_cpu_online(desc
, i
))
1000 for (c
= 0; c
< ncols
; c
++) {
1001 if (compatible
&& cols
[c
] == COL_CACHE
) {
1009 print_parsable_cell(desc
, i
, cols
[c
], compatible
);
1016 /* output formats "<key> <value>"*/
1017 #define print_s(_key, _val) printf("%-23s%s\n", _key, _val)
1018 #define print_n(_key, _val) printf("%-23s%d\n", _key, _val)
1021 print_cpuset(const char *key
, cpu_set_t
*set
, int hex
)
1023 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
1024 size_t setbuflen
= 7 * maxcpus
;
1025 char setbuf
[setbuflen
], *p
;
1028 p
= cpumask_create(setbuf
, setbuflen
, set
, setsize
);
1029 printf("%-23s0x%s\n", key
, p
);
1031 p
= cpulist_create(setbuf
, setbuflen
, set
, setsize
);
1038 print_readable(struct lscpu_desc
*desc
, int hex
)
1042 size_t setsize
= CPU_ALLOC_SIZE(maxcpus
);
1044 print_s(_("Architecture:"), desc
->arch
);
1047 char buf
[64], *p
= buf
;
1049 if (desc
->mode
& MODE_32BIT
) {
1050 strcpy(p
, "32-bit, ");
1053 if (desc
->mode
& MODE_64BIT
) {
1054 strcpy(p
, "64-bit, ");
1058 print_s(_("CPU op-mode(s):"), buf
);
1060 #if !defined(WORDS_BIGENDIAN)
1061 print_s(_("Byte Order:"), "Little Endian");
1063 print_s(_("Byte Order:"), "Big Endian");
1065 print_n(_("CPU(s):"), desc
->ncpus
);
1068 print_cpuset(hex
? _("On-line CPU(s) mask:") :
1069 _("On-line CPU(s) list:"),
1072 if (desc
->online
&& CPU_COUNT_S(setsize
, desc
->online
) != desc
->ncpus
) {
1075 /* Linux kernel provides cpuset of off-line CPUs that contains
1076 * all configured CPUs (see /sys/devices/system/cpu/offline),
1077 * but want to print real (present in system) off-line CPUs only.
1079 set
= cpuset_alloc(maxcpus
, NULL
, NULL
);
1081 err(EXIT_FAILURE
, _("failed to callocate cpu set"));
1082 CPU_ZERO_S(setsize
, set
);
1083 for (i
= 0; i
< desc
->ncpus
; i
++) {
1084 if (!is_cpu_online(desc
, i
))
1085 CPU_SET_S(i
, setsize
, set
);
1087 print_cpuset(hex
? _("Off-line CPU(s) mask:") :
1088 _("Off-line CPU(s) list:"),
1093 if (desc
->nsockets
) {
1094 int cores_per_socket
, sockets_per_book
, books
;
1096 cores_per_socket
= sockets_per_book
= books
= 0;
1097 /* s390 detects its cpu topology via /proc/sysinfo, if present.
1098 * Using simply the cpu topology masks in sysfs will not give
1099 * usable results since everything is virtualized. E.g.
1100 * virtual core 0 may have only 1 cpu, but virtual core 2 may
1102 * If the cpu topology is not exported (e.g. 2nd level guest)
1103 * fall back to old calculation scheme.
1105 if (path_exist(_PATH_PROC_SYSINFO
)) {
1106 FILE *fd
= path_fopen("r", 0, _PATH_PROC_SYSINFO
);
1110 while (fgets(buf
, sizeof(buf
), fd
) != NULL
) {
1111 if (sscanf(buf
, "CPU Topology SW:%d%d%d%d%d%d",
1112 &t0
, &t1
, &t2
, &books
, &sockets_per_book
,
1113 &cores_per_socket
) == 6)
1117 print_n(_("Thread(s) per core:"), desc
->nthreads
/ desc
->ncores
);
1118 print_n(_("Core(s) per socket:"),
1119 cores_per_socket
?: desc
->ncores
/ desc
->nsockets
);
1121 print_n(_("Socket(s) per book:"),
1122 sockets_per_book
?: desc
->nsockets
/ desc
->nbooks
);
1123 print_n(_("Book(s):"), books
?: desc
->nbooks
);
1125 print_n(_("Socket(s):"), sockets_per_book
?: desc
->nsockets
);
1129 print_n(_("NUMA node(s):"), desc
->nnodes
);
1131 print_s(_("Vendor ID:"), desc
->vendor
);
1133 print_s(_("CPU family:"), desc
->family
);
1135 print_s(_("Model:"), desc
->model
);
1137 print_s(_("Stepping:"), desc
->stepping
);
1139 print_s(_("CPU MHz:"), desc
->mhz
);
1141 print_s(_("BogoMIPS:"), desc
->bogomips
);
1142 if (desc
->virtflag
) {
1143 if (!strcmp(desc
->virtflag
, "svm"))
1144 print_s(_("Virtualization:"), "AMD-V");
1145 else if (!strcmp(desc
->virtflag
, "vmx"))
1146 print_s(_("Virtualization:"), "VT-x");
1149 print_s(_("Hypervisor vendor:"), hv_vendors
[desc
->hyper
]);
1150 print_s(_("Virtualization type:"), virt_types
[desc
->virtype
]);
1152 if (desc
->dispatching
>= 0)
1153 print_s(_("Dispatching mode:"), disp_modes
[desc
->dispatching
]);
1154 if (desc
->ncaches
) {
1158 for (i
= desc
->ncaches
- 1; i
>= 0; i
--) {
1159 snprintf(buf
, sizeof(buf
),
1160 _("%s cache:"), desc
->caches
[i
].name
);
1161 print_s(buf
, desc
->caches
[i
].size
);
1165 for (i
= 0; i
< desc
->nnodes
; i
++) {
1166 snprintf(buf
, sizeof(buf
), _("NUMA node%d CPU(s):"), i
);
1167 print_cpuset(buf
, desc
->nodemaps
[i
], hex
);
1171 static void __attribute__((__noreturn__
)) usage(FILE *out
)
1173 fputs(_("\nUsage:\n"), out
);
1175 _(" %s [options]\n"), program_invocation_short_name
);
1177 fputs(_("\nOptions:\n"), out
);
1178 fputs(_(" -h, --help print this help\n"
1179 " -p, --parse <list> print out a parsable instead of a readable format\n"
1180 " -s, --sysroot <dir> use directory DIR as system root\n"
1181 " -x, --hex print hexadecimal masks rather than lists of CPUs\n"
1182 " -V, --version print version information and exit\n\n"), out
);
1184 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
1187 int main(int argc
, char *argv
[])
1189 struct lscpu_desc _desc
, *desc
= &_desc
;
1190 int parsable
= 0, c
, i
, hex
= 0;
1191 int columns
[ARRAY_SIZE(colnames
)], ncolumns
= 0;
1194 static const struct option longopts
[] = {
1195 { "help", no_argument
, 0, 'h' },
1196 { "parse", optional_argument
, 0, 'p' },
1197 { "sysroot", required_argument
, 0, 's' },
1198 { "hex", no_argument
, 0, 'x' },
1199 { "version", no_argument
, 0, 'V' },
1203 setlocale(LC_ALL
, "");
1204 bindtextdomain(PACKAGE
, LOCALEDIR
);
1205 textdomain(PACKAGE
);
1207 while ((c
= getopt_long(argc
, argv
, "hp::s:xV", longopts
, NULL
)) != -1) {
1216 ncolumns
= string_to_idarray(optarg
,
1217 columns
, ARRAY_SIZE(columns
),
1220 return EXIT_FAILURE
;
1222 columns
[ncolumns
++] = COL_CPU
;
1223 columns
[ncolumns
++] = COL_CORE
;
1224 columns
[ncolumns
++] = COL_SOCKET
;
1225 columns
[ncolumns
++] = COL_NODE
;
1226 columns
[ncolumns
++] = COL_CACHE
;
1231 sysrootlen
= strlen(optarg
);
1232 strncpy(pathbuf
, optarg
, sizeof(pathbuf
));
1233 pathbuf
[sizeof(pathbuf
) - 1] = '\0';
1239 printf(_("%s from %s\n"), program_invocation_short_name
,
1241 return EXIT_SUCCESS
;
1247 memset(desc
, 0, sizeof(*desc
));
1249 read_basicinfo(desc
);
1251 for (i
= 0; i
< desc
->ncpus
; i
++) {
1252 if (desc
->online
&& !is_cpu_online(desc
, i
))
1254 read_topology(desc
, i
);
1255 read_cache(desc
, i
);
1256 read_polarization(desc
, i
);
1257 read_address(desc
, i
);
1260 qsort(desc
->caches
, desc
->ncaches
, sizeof(struct cpu_cache
), cachecmp
);
1264 read_hypervisor(desc
);
1268 print_parsable(desc
, columns
, ncolumns
, compatible
);
1270 print_readable(desc
, hex
);
1272 return EXIT_SUCCESS
;