lscpu: convert ARM decoding to new API
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
a94bb4357e
commit
504de58512
|
@ -403,6 +403,7 @@ check_PROGRAMS += test_cputype
|
|||
test_cputype_SOURCES = sys-utils/lscpu-cputype.c \
|
||||
sys-utils/lscpu-cpu.c \
|
||||
sys-utils/lscpu-virt.c \
|
||||
sys-utils/lscpu-arm.c \
|
||||
sys-utils/lscpu-api.h
|
||||
test_cputype_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_CPUTYPE
|
||||
test_cputype_LDADD = $(LDADD) libcommon.la
|
||||
|
|
|
@ -191,9 +191,50 @@ int lscpu_add_cpu(struct lscpu_cxt *cxt,
|
|||
struct lscpu_cputype *ct);
|
||||
int lscpu_cpus_apply_type(struct lscpu_cxt *cxt, struct lscpu_cputype *type);
|
||||
|
||||
void lscpu_decode_arm(struct lscpu_cxt *cxt);
|
||||
|
||||
struct lscpu_cxt *lscpu_new_context(void);
|
||||
void lscpu_free_context(struct lscpu_cxt *cxt);
|
||||
|
||||
int lookup(char *line, char *pattern, char **value);
|
||||
|
||||
/*
|
||||
* Firmware stuff
|
||||
*/
|
||||
#define _PATH_SYS_DMI_TYPE4 "/sys/firmware/dmi/entries/4-0/raw"
|
||||
#define _PATH_SYS_DMI "/sys/firmware/dmi/tables/DMI"
|
||||
|
||||
struct lscpu_dmi_header
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint16_t handle;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
static inline void to_dmi_header(struct lscpu_dmi_header *h, uint8_t *data)
|
||||
{
|
||||
h->type = data[0];
|
||||
h->length = data[1];
|
||||
memcpy(&h->handle, data + 2, sizeof(h->handle));
|
||||
h->data = data;
|
||||
}
|
||||
|
||||
static inline char *dmi_string(const struct lscpu_dmi_header *dm, uint8_t s)
|
||||
{
|
||||
char *bp = (char *)dm->data;
|
||||
|
||||
if (!s || !bp)
|
||||
return NULL;
|
||||
|
||||
bp += dm->length;
|
||||
while (s > 1 && *bp) {
|
||||
bp += strlen(bp);
|
||||
bp++;
|
||||
s--;
|
||||
}
|
||||
|
||||
return !*bp ? NULL : bp;
|
||||
}
|
||||
|
||||
#endif /* LSCPU_API_H */
|
||||
|
|
|
@ -24,14 +24,7 @@
|
|||
* - Ancient wisdom
|
||||
* - SMBIOS tables (if applicable)
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "lscpu.h"
|
||||
#include "lscpu-api.h"
|
||||
|
||||
struct id_part {
|
||||
const int id;
|
||||
|
@ -216,72 +209,102 @@ static const struct hw_impl hw_implementer[] = {
|
|||
{ -1, unknown_part, "unknown" },
|
||||
};
|
||||
|
||||
static void __arm_cpu_decode(struct lscpu_desc *desc)
|
||||
static int parse_id(const char *str)
|
||||
{
|
||||
int j, impl = 0;
|
||||
int id;
|
||||
char *end = NULL;
|
||||
|
||||
if (!str || strncmp(str, "0x",2) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
id = (int) strtol(str, &end, 0);
|
||||
if (errno || str == end)
|
||||
return -EINVAL;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
#define parse_implementer_id(_cxt) (parse_id((_cxt)->vendor))
|
||||
#define parse_model_id(_cxt) (parse_id((_cxt)->model))
|
||||
|
||||
/*
|
||||
* Use model and vendor IDs to decode to human readable names.
|
||||
*/
|
||||
static int arm_ids_decode(struct lscpu_cputype *ct)
|
||||
{
|
||||
int impl, part, j;
|
||||
const struct id_part *parts = NULL;
|
||||
char *end;
|
||||
|
||||
if (desc->vendor && startswith(desc->vendor, "0x")) {
|
||||
errno = 0;
|
||||
impl = (int) strtol(desc->vendor, &end, 0);
|
||||
if (errno || desc->vendor == end)
|
||||
return;
|
||||
}
|
||||
impl = parse_implementer_id(ct);
|
||||
if (impl <= 0)
|
||||
return -EINVAL; /* no ARM or missing ID */
|
||||
|
||||
/* model and modelname */
|
||||
if (impl && desc->model && startswith(desc->model, "0x")) {
|
||||
int part;
|
||||
|
||||
errno = 0;
|
||||
|
||||
part = (int) strtol(desc->model, &end, 0);
|
||||
if (errno || desc->model == end)
|
||||
return;
|
||||
|
||||
for (j = 0; hw_implementer[j].id != -1; j++) {
|
||||
if (hw_implementer[j].id == impl) {
|
||||
parts = hw_implementer[j].parts;
|
||||
desc->vendor = (char *) hw_implementer[j].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parts == NULL)
|
||||
return;
|
||||
|
||||
for (j = 0; parts[j].id != -1; j++) {
|
||||
if (parts[j].id == part) {
|
||||
desc->modelname = (char *) parts[j].name;
|
||||
break;
|
||||
}
|
||||
/* decode vendor */
|
||||
for (j = 0; hw_implementer[j].id != -1; j++) {
|
||||
if (hw_implementer[j].id == impl) {
|
||||
parts = hw_implementer[j].parts;
|
||||
free(ct->vendor);
|
||||
ct->vendor = xstrdup(hw_implementer[j].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print out the rXpY string for ARM cores */
|
||||
if (impl == 0x41 && desc->revision && desc->stepping) {
|
||||
int revision, variant;
|
||||
char buf[8];
|
||||
/* decode model */
|
||||
if (!parts)
|
||||
goto done;
|
||||
|
||||
errno = 0;
|
||||
revision = (int) strtol(desc->revision, &end, 10);
|
||||
if (errno || desc->revision == end)
|
||||
return;
|
||||
part = parse_model_id(ct);
|
||||
if (part <= 0)
|
||||
goto done;
|
||||
|
||||
errno = 0;
|
||||
variant = (int) strtol(desc->stepping, &end, 0);
|
||||
if (errno || desc->stepping == end)
|
||||
return;
|
||||
|
||||
snprintf(buf, sizeof(buf), "r%dp%d", variant, revision);
|
||||
desc->stepping = xstrdup(buf);
|
||||
for (j = 0; parts[j].id != -1; j++) {
|
||||
if (parts[j].id == part) {
|
||||
free(ct->modelname);
|
||||
ct->modelname = xstrdup(parts[j].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* use "rXpY" string as stepping */
|
||||
static int arm_decode_rXpY(struct lscpu_cputype *ct)
|
||||
{
|
||||
int impl, revision, variant;
|
||||
char *end = NULL;
|
||||
char buf[8];
|
||||
|
||||
impl = parse_implementer_id(ct);
|
||||
|
||||
if (impl != 0x41 || !ct->revision || !ct->stepping)
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
revision = (int) strtol(ct->revision, &end, 10);
|
||||
if (errno || ct->revision == end)
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
variant = (int) strtol(ct->stepping, &end, 0);
|
||||
if (errno || ct->stepping == end)
|
||||
return -EINVAL;
|
||||
|
||||
snprintf(buf, sizeof(buf), "r%dp%d", variant, revision);
|
||||
free(ct->stepping);
|
||||
ct->stepping = xstrdup(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PROC_MFR_OFFSET 0x07
|
||||
#define PROC_VERSION_OFFSET 0x10
|
||||
|
||||
static int __arm_cpu_smbios(struct lscpu_desc *desc)
|
||||
/*
|
||||
* Use firmware to get human readable names
|
||||
*/
|
||||
static int arm_smbios_decode(struct lscpu_cputype *ct)
|
||||
{
|
||||
uint8_t data[8192];
|
||||
char buf[128], *str;
|
||||
|
@ -304,28 +327,37 @@ static int __arm_cpu_smbios(struct lscpu_desc *desc)
|
|||
str = dmi_string(&h, data[PROC_MFR_OFFSET]);
|
||||
if (str) {
|
||||
xstrncpy(buf, str, 127);
|
||||
desc->vendor = xstrdup(buf);
|
||||
ct->vendor = xstrdup(buf);
|
||||
}
|
||||
|
||||
str = dmi_string(&h, data[PROC_VERSION_OFFSET]);
|
||||
if (str) {
|
||||
xstrncpy(buf, str, 127);
|
||||
desc->modelname = xstrdup(buf);
|
||||
ct->modelname = xstrdup(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arm_cpu_decode(struct lscpu_desc *desc, struct lscpu_modifier *mod)
|
||||
static void arm_decode(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
/* use SMBIOS Type 4 data if available,
|
||||
* else fall back to manual decoding using the tables above */
|
||||
if (mod->system == SYSTEM_LIVE &&
|
||||
access(_PATH_SYS_DMI_TYPE4, R_OK) == 0)
|
||||
rc = __arm_cpu_smbios(desc);
|
||||
|
||||
/* use SMBIOS Type 4 data if available, else fall back to manual
|
||||
* decoding using the tables above
|
||||
*/
|
||||
if (!cxt->noalive && access(_PATH_SYS_DMI_TYPE4, R_OK) == 0)
|
||||
rc = arm_smbios_decode(ct);
|
||||
if (rc)
|
||||
__arm_cpu_decode(desc);
|
||||
arm_ids_decode(ct);
|
||||
|
||||
arm_decode_rXpY(ct);
|
||||
}
|
||||
|
||||
void lscpu_decode_arm(struct lscpu_cxt *cxt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < cxt->ncputypes; i++)
|
||||
arm_decode(cxt, cxt->cputypes[i]);
|
||||
}
|
||||
|
|
|
@ -343,6 +343,7 @@ static int cpuinfo_parse_line( struct lscpu_cputype **ct,
|
|||
break;
|
||||
default:
|
||||
/* set value as a string and cleanup */
|
||||
fprintf(stderr, "str=%s\n", str);
|
||||
strdup_to_offset(stru, pat->offset, v);
|
||||
data = (char **) ((char *) stru + pat->offset);
|
||||
rtrim_whitespace((unsigned char *) *data);
|
||||
|
@ -812,6 +813,7 @@ int main(int argc, char **argv)
|
|||
lscpu_read_extra(cxt);
|
||||
lscpu_read_vulnerabilities(cxt);
|
||||
lscpu_read_numas(cxt);
|
||||
lscpu_decode_arm(cxt);
|
||||
|
||||
cxt->virt = lscpu_read_virtualization(cxt);
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
|
||||
#include "lscpu-api.h"
|
||||
|
||||
#define _PATH_SYS_DMI "/sys/firmware/dmi/tables/DMI"
|
||||
|
||||
/* Xen Domain feature flag used for /sys/hypervisor/properties/features */
|
||||
#define XENFEAT_supervisor_mode_kernel 3
|
||||
#define XENFEAT_mmu_pt_update_preserve_ad 5
|
||||
|
@ -40,14 +38,6 @@ static const int hv_graphics_pci[] = {
|
|||
#define WORD(x) (uint16_t)(*(const uint16_t *)(x))
|
||||
#define DWORD(x) (uint32_t)(*(const uint32_t *)(x))
|
||||
|
||||
struct dmi_header
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint16_t handle;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
static void *get_mem_chunk(size_t base, size_t len, const char *devmem)
|
||||
{
|
||||
void *p = NULL;
|
||||
|
@ -72,35 +62,6 @@ nothing:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void to_dmi_header(struct dmi_header *h, uint8_t *data)
|
||||
{
|
||||
h->type = data[0];
|
||||
h->length = data[1];
|
||||
memcpy(&h->handle, data + 2, sizeof(h->handle));
|
||||
h->data = data;
|
||||
}
|
||||
|
||||
static char *dmi_string(const struct dmi_header *dm, uint8_t s)
|
||||
{
|
||||
char *bp = (char *)dm->data;
|
||||
|
||||
if (s == 0)
|
||||
return NULL;
|
||||
|
||||
bp += dm->length;
|
||||
while (s > 1 && *bp)
|
||||
{
|
||||
bp += strlen(bp);
|
||||
bp++;
|
||||
s--;
|
||||
}
|
||||
|
||||
if (!*bp)
|
||||
return NULL;
|
||||
|
||||
return bp;
|
||||
}
|
||||
|
||||
static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
|
||||
uint16_t num, const char *devmem)
|
||||
{
|
||||
|
@ -119,7 +80,7 @@ static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
|
|||
/* 4 is the length of an SMBIOS structure header */
|
||||
while (i < num && data + 4 <= buf + len) {
|
||||
uint8_t *next;
|
||||
struct dmi_header h;
|
||||
struct lscpu_dmi_header h;
|
||||
|
||||
to_dmi_header(&h, data);
|
||||
|
||||
|
|
|
@ -212,7 +212,6 @@ extern int read_hypervisor_dmi(void);
|
|||
extern void arm_cpu_decode(struct lscpu_desc *desc, struct lscpu_modifier *mod);
|
||||
|
||||
#define _PATH_SYS_DMI "/sys/firmware/dmi/tables/DMI"
|
||||
#define _PATH_SYS_DMI_TYPE4 "/sys/firmware/dmi/entries/4-0/raw"
|
||||
|
||||
struct lscpu_dmi_header
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue