diff --git a/src/common/cpu.h b/src/common/cpu.h index 011e1e6..1a45100 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -22,6 +22,7 @@ enum { CPU_VENDOR_PHYTIUM, // ARCH_RISCV CPU_VENDOR_RISCV, + CPU_VENDOR_SIFIVE, // OTHERS CPU_VENDOR_UNKNOWN, CPU_VENDOR_INVALID diff --git a/src/riscv/riscv.c b/src/riscv/riscv.c index ee0ec02..f314e4b 100644 --- a/src/riscv/riscv.c +++ b/src/riscv/riscv.c @@ -5,6 +5,8 @@ #include "../common/global.h" #include "../common/udev.h" +#include "udev.h" +#include "uarch.h" #include "soc.h" struct frequency* get_frequency_info(uint32_t core) { @@ -34,8 +36,10 @@ struct cpuInfo* get_cpu_info(void) { topo->cach = NULL; cpu->topo = topo; + char* cpuinfo_str = get_uarch_from_cpuinfo(); cpu->hv = emalloc(sizeof(struct hypervisor)); cpu->hv->present = false; + cpu->arch = get_uarch_from_cpuinfo_str(cpuinfo_str, cpu); cpu->soc = get_soc(); cpu->freq = get_frequency_info(0); cpu->peak_performance = get_peak_performance(cpu); @@ -46,7 +50,7 @@ struct cpuInfo* get_cpu_info(void) { //TODO: Might be worth refactoring with other archs char* get_str_topology(struct cpuInfo* cpu, struct topology* topo) { uint32_t size = 3+7+1; - char* string = emalloc(sizeof(char)*size); + char* string = emalloc(sizeof(char)*size); snprintf(string, size, "%d cores", topo->total_cores); return string; diff --git a/src/riscv/uarch.c b/src/riscv/uarch.c index a9aa42e..ed68ebf 100644 --- a/src/riscv/uarch.c +++ b/src/riscv/uarch.c @@ -1,18 +1,56 @@ -#include +#include +#include +#include +#include #include "uarch.h" #include "../common/global.h" +typedef uint32_t MICROARCH; + struct uarch { - //MICROARCH uarch; + MICROARCH uarch; char* uarch_str; - int32_t process; // measured in nanometers }; +enum { + UARCH_UNKNOWN, + // SIFIVE + UARCH_U74MC +}; + +#define UARCH_START if (false) {} +#define CHECK_UARCH(arch, cpu, cpuinfo_str, uarch_str, str, uarch, vendor) \ + else if (strcmp(cpuinfo_str, uarch_str) == 0) fill_uarch(arch, cpu, str, uarch, vendor); +#define UARCH_END else { printBug("Unknown microarchitecture detected: uarch='%s'", cpuinfo_str); fill_uarch(arch, cpu, "Unknown", UARCH_UNKNOWN, CPU_VENDOR_UNKNOWN); } + +void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u, VENDOR vendor) { + arch->uarch = u; + cpu->cpu_vendor = vendor; + arch->uarch_str = emalloc(sizeof(char) * (strlen(str)+1)); + strcpy(arch->uarch_str, str); +} + +struct uarch* get_uarch_from_cpuinfo_str(char* cpuinfo_str, struct cpuInfo* cpu) { + struct uarch* arch = emalloc(sizeof(struct uarch)); + if(cpuinfo_str == NULL) { + printWarn("get_uarch_from_cpuinfo: Unable to detect microarchitecture, cpuinfo_str is NULL"); + fill_uarch(arch, cpu, "Unknown", UARCH_UNKNOWN, CPU_VENDOR_UNKNOWN); + return arch; + } + + UARCH_START + CHECK_UARCH(arch, cpu, cpuinfo_str, "sifive,u74-mc", "U74-MC", UARCH_U74MC, CPU_VENDOR_SIFIVE) + UARCH_END + + return arch; +} + char* get_str_uarch(struct cpuInfo* cpu) { - return "Unknown"; + return cpu->arch->uarch_str; } void free_uarch_struct(struct uarch* arch) { - + free(arch->uarch_str); + free(arch); } diff --git a/src/riscv/uarch.h b/src/riscv/uarch.h index 02548f9..4a9aa24 100644 --- a/src/riscv/uarch.h +++ b/src/riscv/uarch.h @@ -8,5 +8,6 @@ struct uarch; char* get_str_uarch(struct cpuInfo* cpu); void free_uarch_struct(struct uarch* arch); +struct uarch* get_uarch_from_cpuinfo_str(char* cpuinfo_str, struct cpuInfo* cpu); #endif diff --git a/src/riscv/udev.c b/src/riscv/udev.c index 8724801..a880f7e 100644 --- a/src/riscv/udev.c +++ b/src/riscv/udev.c @@ -4,7 +4,9 @@ #include "../common/global.h" #include "udev.h" -#define _PATH_DEVTREE "/proc/device-tree/compatible" +#define _PATH_CPUINFO "/proc/cpuinfo" +#define _PATH_DEVTREE "/proc/device-tree/compatible" +#define CPUINFO_UARCH_STR "uarch\t\t: " #define DEVTREE_HARDWARE_FIELD 0 char* get_field_from_devtree(int DEVTREE_FIELD) { @@ -45,6 +47,40 @@ char* get_field_from_devtree(int DEVTREE_FIELD) { return hardware; } +char* parse_cpuinfo_field(char* field_str) { + int filelen; + char* buf; + if((buf = read_file(_PATH_CPUINFO, &filelen)) == NULL) { + printWarn("read_file: %s: %s", _PATH_CPUINFO, strerror(errno)); + return NULL; + } + + char* tmp = strstr(buf, field_str); + if(tmp == NULL) { + printWarn("parse_cpuinfo_field: Unable to find field %s", field_str); + return NULL; + } + + tmp += strlen(field_str); + char* end = strstr(tmp, "\n"); + + if(end == NULL) { + printWarn("parse_cpuinfo_field: Unable to find newline after field %s", field_str); + return NULL; + } + + int ret_strlen = (end-tmp); + char* ret = emalloc(sizeof(char) * (ret_strlen+1)); + memset(ret, 0, sizeof(char) * (ret_strlen+1)); + strncpy(ret, tmp, ret_strlen); + + return ret; +} + char* get_hardware_from_devtree(void) { return get_field_from_devtree(DEVTREE_HARDWARE_FIELD); } + +char* get_uarch_from_cpuinfo(void) { + return parse_cpuinfo_field(CPUINFO_UARCH_STR); +} diff --git a/src/riscv/udev.h b/src/riscv/udev.h index 343489f..33e1a19 100644 --- a/src/riscv/udev.h +++ b/src/riscv/udev.h @@ -6,5 +6,6 @@ #define UNKNOWN -1 char* get_hardware_from_devtree(void); +char* get_uarch_from_cpuinfo(void); #endif