#include "closestream.h"
#include "optutils.h"
+#include "fileutils.h"
#include "lscpu.h"
COL_CPU_MINMHZ,
};
+enum {
+ COL_CACHE_ALLSIZE,
+ COL_CACHE_LEVEL,
+ COL_CACHE_NAME,
+ COL_CACHE_ONESIZE,
+ COL_CACHE_TYPE,
+ COL_CACHE_WAYS,
+ COL_CACHE_ALLOCPOL,
+ COL_CACHE_WRITEPOL,
+ COL_CACHE_PHYLINE,
+ COL_CACHE_SETS,
+ COL_CACHE_COHERENCYSIZE
+};
+
+
/* column description
*/
struct lscpu_coldesc {
const char *name;
const char *help;
+ int flags;
unsigned int is_abbr:1; /* name is abbreviation */
};
static struct lscpu_coldesc coldescs_cpu[] =
{
- [COL_CPU_CPU] = { "CPU", N_("logical CPU number"), 1 },
- [COL_CPU_CORE] = { "CORE", N_("logical core number") },
- [COL_CPU_SOCKET] = { "SOCKET", N_("logical socket number") },
- [COL_CPU_NODE] = { "NODE", N_("logical NUMA node number") },
- [COL_CPU_BOOK] = { "BOOK", N_("logical book number") },
- [COL_CPU_DRAWER] = { "DRAWER", N_("logical drawer number") },
+ [COL_CPU_CPU] = { "CPU", N_("logical CPU number"), SCOLS_FL_RIGHT, 1 },
+ [COL_CPU_CORE] = { "CORE", N_("logical core number"), SCOLS_FL_RIGHT },
+ [COL_CPU_SOCKET] = { "SOCKET", N_("logical socket number"), SCOLS_FL_RIGHT },
+ [COL_CPU_NODE] = { "NODE", N_("logical NUMA node number"), SCOLS_FL_RIGHT },
+ [COL_CPU_BOOK] = { "BOOK", N_("logical book number"), SCOLS_FL_RIGHT },
+ [COL_CPU_DRAWER] = { "DRAWER", N_("logical drawer number"), SCOLS_FL_RIGHT },
[COL_CPU_CACHE] = { "CACHE", N_("shows how caches are shared between CPUs") },
[COL_CPU_POLARIZATION] = { "POLARIZATION", N_("CPU dispatching mode on virtual hardware") },
[COL_CPU_ADDRESS] = { "ADDRESS", N_("physical address of a CPU") },
[COL_CPU_CONFIGURED] = { "CONFIGURED", N_("shows if the hypervisor has allocated the CPU") },
- [COL_CPU_ONLINE] = { "ONLINE", N_("shows if Linux currently makes use of the CPU") },
- [COL_CPU_MAXMHZ] = { "MAXMHZ", N_("shows the maximum MHz of the CPU") },
- [COL_CPU_MINMHZ] = { "MINMHZ", N_("shows the minimum MHz of the CPU") }
+ [COL_CPU_ONLINE] = { "ONLINE", N_("shows if Linux currently makes use of the CPU"), SCOLS_FL_RIGHT },
+ [COL_CPU_MAXMHZ] = { "MAXMHZ", N_("shows the maximum MHz of the CPU"), SCOLS_FL_RIGHT },
+ [COL_CPU_MINMHZ] = { "MINMHZ", N_("shows the minimum MHz of the CPU"), SCOLS_FL_RIGHT }
};
+static struct lscpu_coldesc coldescs_cache[] =
+{
+ [COL_CACHE_ALLSIZE] = { "ALL-SIZE", N_("size of all system caches"), SCOLS_FL_RIGHT },
+ [COL_CACHE_LEVEL] = { "LEVEL", N_("cache level"), SCOLS_FL_RIGHT },
+ [COL_CACHE_NAME] = { "NAME", N_("cache name") },
+ [COL_CACHE_ONESIZE] = { "ONE-SIZE", N_("size of one cache"), SCOLS_FL_RIGHT },
+ [COL_CACHE_TYPE] = { "TYPE", N_("cache type") },
+ [COL_CACHE_WAYS] = { "WAYS", N_("ways of associativity"), SCOLS_FL_RIGHT },
+ [COL_CACHE_ALLOCPOL] = { "ALLOC-POLICY", N_("allocation policy") },
+ [COL_CACHE_WRITEPOL] = { "WRITE-POLICY", N_("write policy") },
+ [COL_CACHE_PHYLINE] = { "PHY-LINE", N_("number of physical cache line per cache t"), SCOLS_FL_RIGHT },
+ [COL_CACHE_SETS] = { "SETS", N_("number of sets in the cache; set lines has the same cache index"), SCOLS_FL_RIGHT },
+ [COL_CACHE_COHERENCYSIZE] = { "COHERENCY-SIZE", N_("minimum amount of data in bytes transferred from memory to cache"), SCOLS_FL_RIGHT }
+};
+
+
+static int get_cache_full_size(struct lscpu_desc *desc, struct cpu_cache *ca, uint64_t *res);
+
static int
cpu_column_name_to_id(const char *name, size_t namesz)
{
return -1;
}
+static int
+cache_column_name_to_id(const char *name, size_t namesz)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(coldescs_cache); i++) {
+ const char *cn = coldescs_cache[i].name;
+
+ if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
+ return i;
+ }
+ warnx(_("unknown column: %s"), name);
+ return -1;
+}
+
/* Lookup a pattern and get the value from cpuinfo.
* Format is:
*
type = 0;
if (strncmp(p, "Data", 4) == 0)
type = 'd';
- if (strncmp(p, "Instruction", 11) == 0)
+ else if (strncmp(p, "Instruction", 11) == 0)
type = 'i';
+ else if (strncmp(p, "Unified", 7) == 0)
+ type = 'u';
p = strstr(line, "size=");
if (!p || sscanf(p, "size=%lld", &size) != 1)
return 0;
desc->necaches * sizeof(struct cpu_cache));
cache = &desc->ecaches[desc->necaches - 1];
memset(cache, 0 , sizeof(*cache));
- if (type)
+
+ if (type == 'i' || type == 'd')
xasprintf(&cache->name, "L%d%c", level, type);
else
xasprintf(&cache->name, "L%d", level);
- xasprintf(&cache->size, "%lldK", size);
+
+ cache->level = level;
+ cache->size = size * 1024;
+
+ cache->type = type == 'i' ? xstrdup("Instruction") :
+ type == 'd' ? xstrdup("Data") :
+ type == 'u' ? xstrdup("Unified") : NULL;
return 1;
}
}
#endif
+static int cmp_vulnerability_name(const void *a0, const void *b0)
+{
+ const struct cpu_vulnerability *a = (const struct cpu_vulnerability *) a0,
+ *b = (const struct cpu_vulnerability *) b0;
+ return strcmp(a->name, b->name);
+}
+
+static void read_vulnerabilities(struct lscpu_desc *desc)
+{
+ struct dirent *d;
+ DIR *dir = ul_path_opendir(desc->syscpu, "vulnerabilities");
+ int n = 0;
+
+ if (!dir)
+ return;
+
+ desc->nvuls = n = 0;
+
+ while (xreaddir(dir))
+ n++;
+ if (!n)
+ return;
+
+ rewinddir(dir);
+ desc->vuls = xcalloc(n, sizeof(struct cpu_vulnerability));
+
+ while (desc->nvuls < n && (d = xreaddir(dir))) {
+ char *str, *p;
+ struct cpu_vulnerability *vu;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (d->d_type == DT_DIR || d->d_type == DT_UNKNOWN)
+ continue;
+#endif
+ if (ul_path_readf_string(desc->syscpu, &str,
+ "vulnerabilities/%s", d->d_name) <= 0)
+ continue;
+
+ vu = &desc->vuls[desc->nvuls++];
+
+ /* Name */
+ vu->name = xstrdup(d->d_name);
+ *vu->name = toupper(*vu->name);
+ strrep(vu->name, '_', ' ');
+
+ /* Description */
+ vu->text = str;
+ p = (char *) startswith(vu->text, "Mitigation");
+ if (p) {
+ *p = ';';
+ strrem(vu->text, ':');
+ }
+ }
+ closedir(dir);
+
+ qsort(desc->vuls, desc->nvuls,
+ sizeof(struct cpu_vulnerability), cmp_vulnerability_name);
+}
+
+
+
static void
read_basicinfo(struct lscpu_desc *desc, struct lscpu_modifier *mod)
read_physical_info_powerpc(desc);
if ((fp = ul_path_fopen(desc->procfs, "r", "sysinfo"))) {
- while (fgets(buf, sizeof(buf), fp) != NULL && !desc->machinetype)
- lookup(buf, "Type", &desc->machinetype);
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (lookup(buf, "Type", &desc->machinetype))
+ break;
+ }
fclose(fp);
}
+
+ /* vulnerabilities */
+ if (ul_path_access(desc->syscpu, F_OK, "vulnerabilities") == 0)
+ read_vulnerabilities(desc);
}
static int
"cpu%d/cache/index%d", num, i) != 0)
continue;
if (!ca->name) {
- int type = 0, level;
+ int type = 0;
/* cache type */
- if (ul_path_readf_buffer(desc->syscpu, buf, sizeof(buf),
+ if (ul_path_readf_string(desc->syscpu, &ca->type,
"cpu%d/cache/index%d/type", num, i) > 0) {
- if (!strcmp(buf, "Data"))
+ if (!strcmp(ca->type, "Data"))
type = 'd';
- else if (!strcmp(buf, "Instruction"))
+ else if (!strcmp(ca->type, "Instruction"))
type = 'i';
}
/* cache level */
- ul_path_readf_s32(desc->syscpu, &level,
+ ul_path_readf_s32(desc->syscpu, &ca->level,
"cpu%d/cache/index%d/level", num, i);
if (type)
- snprintf(buf, sizeof(buf), "L%d%c", level, type);
+ snprintf(buf, sizeof(buf), "L%d%c", ca->level, type);
else
- snprintf(buf, sizeof(buf), "L%d", level);
+ snprintf(buf, sizeof(buf), "L%d", ca->level);
ca->name = xstrdup(buf);
+ ul_path_readf_u32(desc->syscpu, &ca->ways_of_associativity,
+ "cpu%d/cache/index%d/ways_of_associativity", num, i);
+ ul_path_readf_u32(desc->syscpu, &ca->physical_line_partition,
+ "cpu%d/cache/index%d/physical_line_partition", num, i);
+ ul_path_readf_u32(desc->syscpu, &ca->number_of_sets,
+ "cpu%d/cache/index%d/number_of_sets", num, i);
+ ul_path_readf_u32(desc->syscpu, &ca->coherency_line_size,
+ "cpu%d/cache/index%d/coherency_line_size", num, i);
+
+ ul_path_readf_string(desc->syscpu, &ca->allocation_policy,
+ "cpu%d/cache/index%d/allocation_policy", num, i);
+ ul_path_readf_string(desc->syscpu, &ca->write_policy,
+ "cpu%d/cache/index%d/write_policy", num, i);
+
/* cache size */
- if (ul_path_readf_string(desc->syscpu, &ca->size,
- "cpu%d/cache/index%d/size", num, i) < 0)
- ca->size = xstrdup("unknown size");
+ if (ul_path_readf_buffer(desc->syscpu, buf, sizeof(buf),
+ "cpu%d/cache/index%d/size", num, i) > 0)
+ parse_size(buf, &ca->size, NULL);
+ else
+ ca->size = 0;
}
/* information about how CPUs share different caches */
return buf;
}
+/*
+ * [-C] backend
+ */
+static void
+print_caches_readable(struct lscpu_desc *desc, int cols[], int ncols,
+ struct lscpu_modifier *mod)
+{
+ int i;
+ struct libscols_table *table;
+
+ scols_init_debug(0);
+
+ table = scols_new_table();
+ if (!table)
+ err(EXIT_FAILURE, _("failed to allocate output table"));
+ if (mod->json) {
+ scols_table_enable_json(table, 1);
+ scols_table_set_name(table, "caches");
+ }
+
+ for (i = 0; i < ncols; i++) {
+ struct lscpu_coldesc *cd = &coldescs_cache[cols[i]];
+ if (!scols_table_new_column(table, cd->name, 0, cd->flags))
+ err(EXIT_FAILURE, _("failed to allocate output column"));
+ }
+
+ for (i = desc->ncaches - 1; i >= 0; i--) {
+ struct cpu_cache *ca = &desc->caches[i];
+ struct libscols_line *line;
+ int c;
+
+ line = scols_table_new_line(table, NULL);
+ if (!line)
+ err(EXIT_FAILURE, _("failed to allocate output line"));
+
+ for (c = 0; c < ncols; c++) {
+ char *data = NULL;
+ int col = cols[c];
+
+ switch (col) {
+ case COL_CACHE_NAME:
+ if (ca->name)
+ data = xstrdup(ca->name);
+ break;
+ case COL_CACHE_ONESIZE:
+ if (!ca->size)
+ break;
+ if (mod->bytes)
+ xasprintf(&data, "%" PRIu64, ca->size);
+ else
+ data = size_to_human_string(SIZE_SUFFIX_1LETTER, ca->size);
+ break;
+ case COL_CACHE_ALLSIZE:
+ {
+ uint64_t sz = 0;
+
+ if (get_cache_full_size(desc, ca, &sz) != 0)
+ break;
+ if (mod->bytes)
+ xasprintf(&data, "%" PRIu64, sz);
+ else
+ data = size_to_human_string(SIZE_SUFFIX_1LETTER, sz);
+ break;
+ }
+ case COL_CACHE_WAYS:
+ if (ca->ways_of_associativity)
+ xasprintf(&data, "%u", ca->ways_of_associativity);
+ break;
+
+ case COL_CACHE_TYPE:
+ if (ca->type)
+ data = xstrdup(ca->type);
+ break;
+ case COL_CACHE_LEVEL:
+ if (ca->level)
+ xasprintf(&data, "%d", ca->level);
+ break;
+ case COL_CACHE_ALLOCPOL:
+ if (ca->allocation_policy)
+ data = xstrdup(ca->allocation_policy);
+ break;
+ case COL_CACHE_WRITEPOL:
+ if (ca->write_policy)
+ data = xstrdup(ca->write_policy);
+ break;
+ case COL_CACHE_PHYLINE:
+ if (ca->physical_line_partition)
+ xasprintf(&data, "%u", ca->physical_line_partition);
+ break;
+ case COL_CACHE_SETS:
+ if (ca->number_of_sets)
+ xasprintf(&data, "%u", ca->number_of_sets);
+ break;
+ case COL_CACHE_COHERENCYSIZE:
+ if (ca->coherency_line_size)
+ xasprintf(&data, "%u", ca->coherency_line_size);
+ break;
+ }
+
+ if (data && scols_line_refer_data(line, c, data))
+ err(EXIT_FAILURE, _("failed to add output data"));
+ }
+ }
+
+ scols_print_table(table);
+ scols_unref_table(table);
+}
+
/*
* [-p] backend, we support two parsable formats:
*
int c;
int cpu = real_cpu_num(desc, i);
- if (!mod->offline && desc->online && !is_cpu_online(desc, cpu))
- continue;
- if (!mod->online && desc->online && is_cpu_online(desc, cpu))
- continue;
+ if (desc->online) {
+ if (!mod->offline && !is_cpu_online(desc, cpu))
+ continue;
+ if (!mod->online && is_cpu_online(desc, cpu))
+ continue;
+ }
if (desc->present && !is_cpu_present(desc, cpu))
continue;
for (c = 0; c < ncols; c++) {
for (i = 0; i < ncols; i++) {
data = get_cell_header(desc, cols[i], mod, buf, sizeof(buf));
- if (!scols_table_new_column(table, data, 0, 0))
+ if (!scols_table_new_column(table, data, 0, coldescs_cpu[cols[i]].flags))
err(EXIT_FAILURE, _("failed to allocate output column"));
}
struct libscols_line *line;
int cpu = real_cpu_num(desc, i);
- if (!mod->offline && desc->online && !is_cpu_online(desc, cpu))
- continue;
- if (!mod->online && desc->online && is_cpu_online(desc, cpu))
- continue;
+ if (desc->online) {
+ if (!mod->offline && !is_cpu_online(desc, cpu))
+ continue;
+ if (!mod->online && is_cpu_online(desc, cpu))
+ continue;
+ }
if (desc->present && !is_cpu_present(desc, cpu))
continue;
err(EXIT_FAILURE, _("failed to allocate output line"));
/* description column */
- scols_line_set_data(ln, 0, txt);
+ if (txt && scols_line_set_data(ln, 0, txt))
+ err(EXIT_FAILURE, _("failed to add output data"));
/* data column */
va_start(args, fmt);
}
}
-static int get_cache_full_size(struct lscpu_desc *desc, int idx, uint64_t *res)
+static int get_cache_full_size(struct lscpu_desc *desc,
+ struct cpu_cache *ca, uint64_t *res)
{
- struct cpu_cache *ca = &desc->caches[idx];
size_t setsize = CPU_ALLOC_SIZE(maxcpus);
- int i, nshares = 0, rc;
- uint64_t sz;
-
- /* Convert size to number */
- rc = parse_size(ca->size, &sz, NULL);
- if (rc)
- return rc;
+ int i, nshares = 0;
/* Count number of CPUs which shares the cache */
for (i = 0; i < desc->ncpuspos; i++) {
/* Correction for CPU threads */
if (desc->nthreads > desc->ncores)
nshares /= (desc->nthreads / desc->ncores);
+ if (nshares < 1)
+ nshares = 1;
- *res = (desc->ncores / nshares) * sz;
+ *res = (desc->ncores / nshares) * ca->size;
return 0;
}
}
if (scols_table_new_column(tb, "field", 0, 0) == NULL ||
- scols_table_new_column(tb, "data", 0, SCOLS_FL_NOEXTREMES) == NULL)
+ scols_table_new_column(tb, "data", 0, SCOLS_FL_NOEXTREMES | SCOLS_FL_WRAP) == NULL)
err(EXIT_FAILURE, _("failed to initialize output column"));
add_summary_s(tb, _("Architecture:"), desc->arch);
for (i = desc->ncaches - 1; i >= 0; i--) {
uint64_t sz = 0;
char *tmp;
+ struct cpu_cache *ca = &desc->caches[i];
- if (get_cache_full_size(desc, i, &sz) != 0)
+ if (ca->size == 0)
+ continue;
+ if (get_cache_full_size(desc, ca, &sz) != 0 || sz == 0)
continue;
- tmp = size_to_human_string(
+ if (mod->bytes)
+ xasprintf(&tmp, "%" PRIu64, sz);
+ else
+ tmp = size_to_human_string(
SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE,
sz);
- snprintf(buf, sizeof(buf),
- _("%s cache: "), desc->caches[i].name);
+ snprintf(buf, sizeof(buf), _("%s cache:"), ca->name);
add_summary_s(tb, buf, tmp);
free(tmp);
}
}
if (desc->necaches) {
for (i = desc->necaches - 1; i >= 0; i--) {
- snprintf(buf, sizeof(buf),
- _("%s cache:"), desc->ecaches[i].name);
- add_summary_s(tb, buf, desc->ecaches[i].size);
+ char *tmp;
+ struct cpu_cache *ca = &desc->ecaches[i];
+
+ if (ca->size == 0)
+ continue;
+ if (mod->bytes)
+ xasprintf(&tmp, "%" PRIu64, ca->size);
+ else
+ tmp = size_to_human_string(
+ SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE,
+ ca->size);
+ snprintf(buf, sizeof(buf), _("%s cache:"), ca->name);
+ add_summary_s(tb, buf, tmp);
+ free(tmp);
}
}
add_summary_n(tb, _("Physical cores/chip:"), desc->physcoresperchip);
}
+ if (desc->vuls) {
+ for (i = 0; i < desc->nvuls; i++) {
+ snprintf(buf, sizeof(buf), ("Vulnerability %s:"), desc->vuls[i].name);
+ add_summary_s(tb, buf, desc->vuls[i].text);
+ }
+ }
+
if (desc->flags)
add_summary_s(tb, _("Flags:"), desc->flags);
fputs(USAGE_OPTIONS, out);
fputs(_(" -a, --all print both online and offline CPUs (default for -e)\n"), out);
fputs(_(" -b, --online print online CPUs only (default for -p)\n"), out);
+ fputs(_(" -B, --bytes print sizes in bytes rather than in human readable format\n"), out);
+ fputs(_(" -C, --caches[=<list>] info about caches in extended readable format\n"), out);
fputs(_(" -c, --offline print offline CPUs only\n"), out);
fputs(_(" -J, --json use JSON for default or extended format\n"), out);
fputs(_(" -e, --extended[=<list>] print out an extended readable format\n"), out);
fputs(_(" -s, --sysroot <dir> use specified directory as system root\n"), out);
fputs(_(" -x, --hex print hexadecimal masks rather than lists of CPUs\n"), out);
fputs(_(" -y, --physical print physical instead of logical IDs\n"), out);
+ fputs(_(" --output-all print all available columns for -e, -p or -C\n"), out);
fputs(USAGE_SEPARATOR, out);
printf(USAGE_HELP_OPTIONS(25));
for (i = 0; i < ARRAY_SIZE(coldescs_cpu); i++)
fprintf(out, " %13s %s\n", coldescs_cpu[i].name, _(coldescs_cpu[i].help));
+ fputs(_("\nAvailable output columns for -C:\n"), out);
+ for (i = 0; i < ARRAY_SIZE(coldescs_cache); i++)
+ fprintf(out, " %13s %s\n", coldescs_cache[i].name, _(coldescs_cache[i].help));
+
printf(USAGE_MAN_TAIL("lscpu(1)"));
exit(EXIT_SUCCESS);
{
struct lscpu_modifier _mod = { .mode = OUTPUT_SUMMARY }, *mod = &_mod;
struct lscpu_desc _desc = { .flags = NULL }, *desc = &_desc;
- int c, i;
+ int c, i, all = 0;
int columns[ARRAY_SIZE(coldescs_cpu)], ncolumns = 0;
int cpu_modifier_specified = 0;
size_t setsize;
static const struct option longopts[] = {
{ "all", no_argument, NULL, 'a' },
{ "online", no_argument, NULL, 'b' },
+ { "bytes", no_argument, NULL, 'B' },
+ { "caches", optional_argument, NULL, 'C' },
{ "offline", no_argument, NULL, 'c' },
{ "help", no_argument, NULL, 'h' },
{ "extended", optional_argument, NULL, 'e' },
};
static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
+ { 'C','e','p' },
{ 'a','b','c' },
- { 'e','p' },
{ 0 }
};
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
- while ((c = getopt_long(argc, argv, "abce::hJp::s:xyV", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "aBbC::ce::hJp::s:xyV", longopts, NULL)) != -1) {
err_exclusive_options(c, longopts, excl, excl_st);
mod->online = mod->offline = 1;
cpu_modifier_specified = 1;
break;
+ case 'B':
+ mod->bytes = 1;
+ break;
case 'b':
mod->online = 1;
cpu_modifier_specified = 1;
mod->offline = 1;
cpu_modifier_specified = 1;
break;
- case 'h':
- usage();
+ case 'C':
+ if (optarg) {
+ if (*optarg == '=')
+ optarg++;
+ ncolumns = string_to_idarray(optarg,
+ columns, ARRAY_SIZE(columns),
+ cache_column_name_to_id);
+ if (ncolumns < 0)
+ return EXIT_FAILURE;
+ }
+ mod->mode = OUTPUT_CACHES;
+ break;
case 'J':
mod->json = 1;
break;
case 'y':
mod->physical = 1;
break;
- case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
case OPT_OUTPUT_ALL:
- {
- size_t sz;
- for (sz = 0; sz < ARRAY_SIZE(coldescs_cpu); sz++)
- columns[sz] = 1;
+ all = 1;
break;
- }
+
+ case 'h':
+ usage();
+ case 'V':
+ print_version(EXIT_SUCCESS);
default:
errtryhelp(EXIT_FAILURE);
}
}
+ if (all && ncolumns == 0) {
+ size_t sz, maxsz = mod->mode == OUTPUT_CACHES ?
+ ARRAY_SIZE(coldescs_cache) :
+ ARRAY_SIZE(coldescs_cpu);
+
+ for (sz = 0; sz < maxsz; sz++)
+ columns[ncolumns++] = sz;
+ }
+
if (cpu_modifier_specified && mod->mode == OUTPUT_SUMMARY) {
fprintf(stderr,
_("%s: options --all, --online and --offline may only "
case OUTPUT_SUMMARY:
print_summary(desc, mod);
break;
+ case OUTPUT_CACHES:
+ if (!ncolumns) {
+ columns[ncolumns++] = COL_CACHE_NAME;
+ columns[ncolumns++] = COL_CACHE_ONESIZE;
+ columns[ncolumns++] = COL_CACHE_ALLSIZE;
+ columns[ncolumns++] = COL_CACHE_WAYS;
+ columns[ncolumns++] = COL_CACHE_TYPE;
+ columns[ncolumns++] = COL_CACHE_LEVEL;
+ columns[ncolumns++] = COL_CACHE_SETS;
+ columns[ncolumns++] = COL_CACHE_PHYLINE;
+ columns[ncolumns++] = COL_CACHE_COHERENCYSIZE;
+ }
+ print_caches_readable(desc, columns, ncolumns, mod);
+ break;
case OUTPUT_PARSABLE:
if (!ncolumns) {
columns[ncolumns++] = COL_CPU_CPU;