pax_global_header 0000666 0000000 0000000 00000000064 14154076152 0014517 g ustar 00root root 0000000 0000000 52 comment=40b13bc60c2eba3a0856d06e5a9f4d5ad81ad01e cpufetch-master/ 0000775 0000000 0000000 00000000000 14154076152 0014155 5 ustar 00root root 0000000 0000000 cpufetch-master/.github/ 0000775 0000000 0000000 00000000000 14154076152 0015515 5 ustar 00root root 0000000 0000000 cpufetch-master/.github/workflows/ 0000775 0000000 0000000 00000000000 14154076152 0017552 5 ustar 00root root 0000000 0000000 cpufetch-master/.github/workflows/lockdown.yml 0000664 0000000 0000000 00000001742 14154076152 0022121 0 ustar 00root root 0000000 0000000 name: 'Disable PR in cpufetch' on: issues: types: opened pull_request_target: types: opened permissions: issues: write pull-requests: write jobs: action: runs-on: ubuntu-latest steps: - uses: dessant/repo-lockdown@v2 with: github-token: ${{ github.token }} exclude-issue-created-before: '' exclude-issue-labels: '' issue-labels: '' issue-comment: '' skip-closed-issue-comment: false close-issue: false lock-issue: true issue-lock-reason: '' exclude-pr-created-before: '' exclude-pr-labels: '' pr-labels: '' pr-comment: 'cpufetch does not accept pull requests, see [the contributing guidelines](https://github.com/Dr-Noob/cpufetch/blob/master/CONTRIBUTING.md) for details' skip-closed-pr-comment: false close-pr: true lock-pr: false pr-lock-reason: '' process-only: 'prs' cpufetch-master/.gitignore 0000664 0000000 0000000 00000000015 14154076152 0016141 0 ustar 00root root 0000000 0000000 cpufetch *.o cpufetch-master/CONTRIBUTING.md 0000664 0000000 0000000 00000005651 14154076152 0016415 0 ustar 00root root 0000000 0000000 # cpufetch contributing guidelines - [1. cpufetch does not accept pull requests](#1-cpufetch-does-not-accept-pull-requests) - [2. Creating an issue](#2-creating-an-issue) - [2.1: I found a bug in cpufetch (the program provides incorrect / invalid information)](#21-i-found-a-bug-in-cpufetch-the-program-provides-incorrect--invalid-information) - [2.2: I found a bug in cpufetch (the program crashes / does not work properly)](#22-i-found-a-bug-in-cpufetch-the-program-crashes--does-not-work-properly) - [Stacktrace option 1 (best)](#stacktrace-option-1-best) - [Stacktrace option 2 (use this option if option 1 does not work)](#stacktrace-option-2-use-this-option-if-option-1-does-not-work) - [2.3: I have an idea for a new feature in cpufetch / I want to suggest a change in cpufetch](#23-i-have-an-idea-for-a-new-feature-in-cpufetch--i-want-to-suggest-a-change-in-cpufetch) Thanks for your interest in contributing to cpufetch! Please, read this page carefully to understand how to contribute to cpufetch. ## 1. cpufetch does not accept pull requests cpufetch is a small project, and I enjoy developing it. There are for sure some bugs and exciting features to add, but I prefer to make these changes myself. For that reason, you should always use the issues page to report anything related to cpufetch. In the rare case that there is a concise bug or feature that I am unable to implement myself, I will enable pull requests for this. ## 2. Creating an issue ### 2.1: I found a bug in cpufetch (the program provides incorrect / invalid information) In the github issue **you must include**: - Exact CPU model. - Operating system. - The output of `cpufetch`. - The output of `cpufetch --debug`. ### 2.2: I found a bug in cpufetch (the program crashes / does not work properly) - Exact CPU model. - Operating system. - The output of `cpufetch`. - The output of `cpufetch --debug`. - A stacktrace (if program crashes): #### Stacktrace option 1 (best) 1. Build cpufetch with debug symbols (`make clean; make debug`). 2. Install valgrind (if it is not already installed) 3. Run cpufetch with valgrind (`valgrind ./cpufetch`) 4. Paste the complete output (preferably on a platform like pastebin) #### Stacktrace option 2 (use this option if option 1 does not work) 1. Build cpufetch with debug symbols (`make clean; make debug`). 2. Install gdb (if it is not already installed) 3. Debug cpufetch with gdb (`gdb cpufetch`) 3. Run cpufetch (just r inside gdb console) 4. Paste the complete output (preferably on a platform like pastebin) ### 2.3: I have an idea for a new feature in cpufetch / I want to suggest a change in cpufetch Just explain the feature in the issue and include references (links) to relevant sources if appropriate. cpufetch-master/LICENSE 0000664 0000000 0000000 00000002050 14154076152 0015157 0 ustar 00root root 0000000 0000000 MIT License Copyright (c) 2018 Dr-Noob Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cpufetch-master/Makefile 0000664 0000000 0000000 00000007441 14154076152 0015623 0 ustar 00root root 0000000 0000000 CC ?= gcc CFLAGS+=-Wall -Wextra -pedantic SANITY_FLAGS=-Wfloat-equal -Wshadow -Wpointer-arith PREFIX ?= /usr SRC_COMMON=src/common/ COMMON_SRC = $(SRC_COMMON)main.c $(SRC_COMMON)cpu.c $(SRC_COMMON)udev.c $(SRC_COMMON)printer.c $(SRC_COMMON)args.c $(SRC_COMMON)global.c COMMON_HDR = $(SRC_COMMON)ascii.h $(SRC_COMMON)cpu.h $(SRC_COMMON)udev.h $(SRC_COMMON)printer.h $(SRC_COMMON)args.h $(SRC_COMMON)global.h ifneq ($(OS),Windows_NT) arch := $(shell uname -m) ifeq ($(arch), $(filter $(arch), x86_64 amd64 i386 i486 i586 i686)) SRC_DIR=src/x86/ SOURCE += $(COMMON_SRC) $(SRC_DIR)cpuid.c $(SRC_DIR)apic.c $(SRC_DIR)cpuid_asm.c $(SRC_DIR)uarch.c HEADERS += $(COMMON_HDR) $(SRC_DIR)cpuid.h $(SRC_DIR)apic.h $(SRC_DIR)cpuid_asm.h $(SRC_DIR)uarch.h $(SRC_DIR)freq/freq.h os := $(shell uname -s) ifeq ($(os), Linux) SOURCE += $(SRC_DIR)freq/freq.c freq_nov.o freq_avx.o freq_avx512.o HEADERS += $(SRC_DIR)freq/freq.h CFLAGS += -pthread endif CFLAGS += -DARCH_X86 -std=c99 -fstack-protector-all else ifeq ($(arch), $(filter $(arch), ppc64le ppc64 ppcle ppc)) SRC_DIR=src/ppc/ SOURCE += $(COMMON_SRC) $(SRC_DIR)ppc.c $(SRC_DIR)uarch.c $(SRC_DIR)udev.c HEADERS += $(COMMON_HDR) $(SRC_DIR)ppc.h $(SRC_DIR)uarch.h $(SRC_DIR)udev.c CFLAGS += -DARCH_PPC -std=gnu99 -fstack-protector-all else ifeq ($(arch), $(filter $(arch), arm aarch64_be aarch64 arm64 armv8b armv8l armv7l armv6l)) SRC_DIR=src/arm/ SOURCE += $(COMMON_SRC) $(SRC_DIR)midr.c $(SRC_DIR)uarch.c $(SRC_DIR)soc.c $(SRC_DIR)udev.c HEADERS += $(COMMON_HDR) $(SRC_DIR)midr.h $(SRC_DIR)uarch.h $(SRC_DIR)soc.h $(SRC_DIR)udev.c $(SRC_DIR)socs.h CFLAGS += -DARCH_ARM -Wno-unused-parameter -std=c99 -fstack-protector-all os := $(shell uname -s) ifeq ($(os), Darwin) SOURCE += $(SRC_DIR)sysctl.c HEADERS += $(SRC_DIR)sysctl.h endif else # Error lines should not be tabulated because Makefile complains about it $(warning Unsupported arch detected: $(arch). See https://github.com/Dr-Noob/cpufetch#1-support) $(warning If your architecture is supported but the compilation fails, please open an issue in https://github.com/Dr-Noob/cpufetch/issues) $(error Aborting compilation) endif OUTPUT=cpufetch else # Assume x86_64 SRC_DIR=src/x86/ SOURCE += $(COMMON_SRC) $(SRC_DIR)cpuid.c $(SRC_DIR)apic.c $(SRC_DIR)cpuid_asm.c $(SRC_DIR)uarch.c HEADERS += $(COMMON_HDR) $(SRC_DIR)cpuid.h $(SRC_DIR)apic.h $(SRC_DIR)cpuid_asm.h $(SRC_DIR)uarch.h CFLAGS += -DARCH_X86 -std=c99 SANITY_FLAGS += -Wno-pedantic-ms-format OUTPUT=cpufetch.exe endif all: CFLAGS += -O2 all: $(OUTPUT) debug: CFLAGS += -g -O0 debug: $(OUTPUT) static: CFLAGS += -static -O2 static: $(OUTPUT) strict: CFLAGS += -O2 -Werror -fsanitize=undefined -D_FORTIFY_SOURCE=2 strict: $(OUTPUT) freq_nov.o: Makefile $(SRC_DIR)freq/freq_nov.c $(SRC_DIR)freq/freq_nov.h $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -pthread $(SRC_DIR)freq/freq_nov.c -o $@ freq_avx.o: Makefile $(SRC_DIR)freq/freq_avx.c $(SRC_DIR)freq/freq_avx.h $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -mavx -pthread $(SRC_DIR)freq/freq_avx.c -o $@ freq_avx512.o: Makefile $(SRC_DIR)freq/freq_avx512.c $(SRC_DIR)freq/freq_avx512.h $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -mavx512f -pthread $(SRC_DIR)freq/freq_avx512.c -o $@ $(OUTPUT): Makefile $(SOURCE) $(HEADERS) $(CC) $(CFLAGS) $(SANITY_FLAGS) $(SOURCE) -o $(OUTPUT) run: $(OUTPUT) ./$(OUTPUT) clean: @rm -f $(OUTPUT) *.o install: $(OUTPUT) install -Dm755 "cpufetch" "$(DESTDIR)$(PREFIX)/bin/cpufetch" install -Dm644 "LICENSE" "$(DESTDIR)$(PREFIX)/share/licenses/cpufetch-git/LICENSE" install -Dm644 "cpufetch.1" "$(DESTDIR)$(PREFIX)/share/man/man1/cpufetch.1.gz" uninstall: rm -f "$(DESTDIR)$(PREFIX)/bin/cpufetch" rm -f "$(DESTDIR)$(PREFIX)/share/licenses/cpufetch-git/LICENSE" rm -f "$(DESTDIR)$(PREFIX)/share/man/man1/cpufetch.1.gz" cpufetch-master/README.md 0000664 0000000 0000000 00000013651 14154076152 0015442 0 ustar 00root root 0000000 0000000
cpufetch is a command-line tool written in C that displays the CPU information in a clean and beautiful way
AMD EPYC HPC server
Intel Xeon HPC server
### 3.2 ARM
Samsung Galaxy S8 (left) Xiaomi Redmi Note 7 (right)
### 3.3 PowerPCTalos II
## 4. Colors By default, `cpufetch` will print the CPU logo with the system colorscheme. However, you can set a custom color scheme in two different ways: ### 4.1 Specifying a name By specifying a name, cpufetch will use the specific colors of each manufacture. Valid values are: - intel - intel-new - amd - ibm - arm ``` ./cpufetch --color intel (default color for Intel) ``` ### 4.2 Specifying the colors in RGB format 5 colors must be given in RGB with the format: ``[R,G,B:R,G,B:R,G,B:R,G,B:R,G,B]``. These colors correspond to the CPU logo color (first 3 colors) and for the text colors (following 2). ``` ./cpufetch --color 239,90,45:210,200,200:0,0,0:100,200,45:0,200,200 ``` ## 5. Implementation See [cpufetch programming documentation](https://github.com/Dr-Noob/cpufetch/tree/master/doc). ## 6. Bugs or improvements See [cpufetch contributing guidelines](https://github.com/Dr-Noob/cpufetch/blob/master/CONTRIBUTING.md). ## 7. Acknowledgements Thanks to the fellow contributors and interested people in the project. Special thanks to: - [Gonzalocl](https://github.com/Gonzalocl), [OdnetninI](https://github.com/OdnetninI): Tested cpufetch in the earlier versions of the project in many different CPUs. - [Kyngo](https://github.com/Kyngo): Tested cpufetch in the Apple M1 CPU. - [avollmerhaus](https://github.com/avollmerhaus): Gave me ssh acess to a PowerPC machine, allowing me to develop the PowerPC port. - [bbonev](https://github.com/bbonev), [stephan-cr](https://github.com/stephan-cr): Reviewed the source code. ## 8. cpufetch for GPUs (gpufetch) See [gpufetch](https://github.com/Dr-Noob/gpufetch) project! cpufetch-master/cpufetch.1 0000664 0000000 0000000 00000006570 14154076152 0016050 0 ustar 00root root 0000000 0000000 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.3. It was also manually adapted to look correctly .\" help2man -N -n "Simple yet fancy CPU architecture fetching tool" ./cpufetch > cpufetch.1 .TH CPUFETCH "1" "September 2021" "cpufetch v1.00 (Linux x86_64 build)" "User Commands" .SH NAME cpufetch \- Simple yet fancy CPU architecture fetching tool .SH SYNOPSIS .B cpufetch [\fI\,OPTION\/\fR]... .SH DESCRIPTION cpufetch is a command-line tool written in C that displays the CPU information in a clean and beautiful way .SH OPTIONS .TP \fB\-c\fR, \fB\-\-color\fR Set the color scheme (by default, cpufetch uses the system color scheme) .TP \fB\-s\fR, \fB\-\-style\fR Set the style of CPU logo .TP \fB\-d\fR, \fB\-\-debug\fR Print CPU model and cpuid levels (debug purposes) .TP \fB\-\-logo\-short\fR Show the short version of the logo .TP \fB\-\-logo\-long\fR Show the long version of the logo .TP \fB\-v\fR, \fB\-\-verbose\fR Print extra information (if available) about how cpufetch tried fetching information .TP \fB\-\-logo\-intel\-old\fR Show the old Intel logo .TP \fB\-\-logo\-intel\-new\fR Show the new Intel logo .TP \fB\-F\fR, \fB\-\-full\-cpu\-name\fR Show the full CPU name (do not abbreviate it) .TP \fB\-r\fR, \fB\-\-raw\fR Print raw cpuid data (debug purposes) .TP \fB\-h\fR, \fB\-\-help\fR Print this help and exit .TP \fB\-V\fR, \fB\-\-version\fR Print cpufetch version and exit .SH COLORS .TP * "intel": Use Intel default color scheme .TP * "amd": Use AMD default color scheme .TP * "ibm", Use IBM default color scheme .TP * "arm": Use ARM default color scheme .TP * custom: If the argument of \fB\-\-color\fR does not match any of the previous strings, a custom scheme can be specified. 5 colors must be given in RGB with the format: R,G,B:R,G,B:...The first 3 colors are the CPU art color and the next 2 colors are the text colors .SH STYLES .TP * "fancy": Default style .TP * "retro": Old cpufetch style .TP * "legacy": Fallback style for terminals that do not support colors .SH LOGOS .TP cpufetch will try to adapt the logo size and the text to the terminal width. When the output (logo and text) is wider than the terminal width, cpufetch will print a smaller version of the logo (if it exists). This behavior can be overridden by \fB\-\-logo\-short\fR and \fB\-\-logo\-long\fR, which always sets the logo size as specified by the user, even if it is too big. After the logo selection (either automatically or set by the user), cpufetch will check again if the output fits in the terminal. If not, it will use a shorter name for the fields (the left part of the text). If, after all of this, the output still does not fit, cpufetch will cut the text and will only print the text until there is no space left in each line .SH EXAMPLES .TP Run cpufetch with Intel color scheme: .IP \&./cpufetch \fB\-\-color\fR intel .TP Run cpufetch with a custom color scheme: .IP \&./cpufetch \fB\-\-color\fR 239,90,45:210,200,200:0,0,0:100,200,45:0,200,200 .SH BUGS .TP Report bugs to https://github.com/Dr\-Noob/cpufetch/issues .SH NOTE .TP Peak performance information is NOT accurate. cpufetch computes peak performance using the max frequency of the CPU. However, to compute the peak performance, you need to know the frequency of the CPU running AVX code. This value is not be fetched by cpufetch since it depends on each specific CPU. To correctly measure peak performance, see: https://github.com/Dr\-Noob/peakperf cpufetch-master/doc/ 0000775 0000000 0000000 00000000000 14154076152 0014722 5 ustar 00root root 0000000 0000000 cpufetch-master/doc/DOCUMENTATION_ARM.md 0000664 0000000 0000000 00000014574 14154076152 0017767 0 ustar 00root root 0000000 0000000 ### 2. Why ARM cpufetch works on Linux based systems? CPUID instructions (present in x86 architectures) [[1](#references)] allow user level applications to obtain information about the CPU. In ARM architectures, there are many registers (MIDR [[2](#references)], CCSIDR [[3](#references)]) that provide information about the CPU too. However, those registers can only be read from privilege mode (PL1 or higher). Therefore, any user level tool which can actually read information about the running CPU must use the operating system to do so. cpufetch uses some Linux kernel features (see the remaining sections). Therefore, cpufetch in ARM processors is limited to Linux kernel based systems, such as __GNU/Linux__ and __Android__ ### 3. How to get CPU microarchitecture? __Involved code: [get_midr_from_cpuinfo (udev.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/arm/udev.c), [midr.c](https://github.com/Dr-Noob/cpufetch/blob/master/src/arm/midr.c)__ Microarchitecture information is acquired from the Main ID Register (MIDR) [[2](#references)]. Currently, cpufetch rebuilds this register using `/proc/cpuinfo` file. While this file does not contain the value of the register per se, it contains the following fields: - `CPU implementer`, - `CPU architecture` - `CPU variant` - `CPU part` - `CPU revision` The MIDR register can be built with this information. Another possible approach is to read MIDR directly from `/sys/devices/system/cpu/cpu*/regs/identification/midr_el1` With the MIDR available, the approach is the same as the one used in x86_64 architectures. cpufetch has a file that acts like a database that tries to match the MIDR register with the specific CPU microarchitecture. ### 4. How to get CPU topology? __Involved code: [get_ncores_from_cpuinfo (udev.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/arm/udev.c), [midr.c](https://github.com/Dr-Noob/cpufetch/blob/master/src/arm/midr.c)__ ARM provides a new interesting architecture feature: big.LITTLE architectures [[4](#references)]. An ARM CPU can be organized like a typical x86_64 CPU, where all cores share the same microarchitecture. However, ARM big.LITTLE architecture breaks this schema. In a big.LITTLE CPU, two or more CPUs microarchitecture live in the same chip. This means that cpufetch can't just read which microarchitecture is the first core and assume that the rest of them shares the same microarchitecture. To get the CPU topology, cpufetch first reads the number of CPU cores. This can be obtained from `/sys/devices/system/cpu/present` Then, for each core, cpufetch reads the MIDR and also the frequency (see section 5). Then, cpufetch assumes that two cores are different when their MIDR are different. This idea allows cpufetch to detect big.LITTLE architectures, and to know how many cores of each architecture the running CPU has. ### 5. How to get the frequency? Frequency is read directly from `/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq` ### 6. How to get system on chip model? __Involved code: [soc.c](https://github.com/Dr-Noob/cpufetch/blob/master/src/arm/soc.c)__ System on chip (SoC) model is obtained using the same idea as the microarchitecture. First, SoC string is read. Then, the string has to be matched against a database-like function (__parse_soc_from_string__). The SoC string of the running CPU can be obtained using two different approaches: - Using `/proc/cpuinfo`. This is the first thing to try. Linux kernel usually provides the string under the `Hardware` keyword. However, the Linux kernel may be unable to provide this information, or this string may not be found in the database-like function. - Using Android properties: This only works on Android systems. Android properties can be read using `__system_property_get` function. cpufetch tries to read two properties: - `ro.mediatek.platform` - `ro.product.board` If any string is returned, cpufetch tries to find a match in the database (using the same database as in the case of `/proc/cpuinfo`). The expected strings have to be hardcoded. I found two ways of knowing which string should correspond to which SoC: - Searching on the internet. Manufacturers __usually__ provide this information. For example, Qualcomm usually publishes the chip name along with other characteristics (under the `Part` or `Part number` keyword [[6](#references)]). - "Hunting" for the strings. For example, finding smartphones with a given SoC and manually reading the `/proc/cpuinfo` or the `build.prop` file. A very good resource to do this is the SpecDevice webpage [[7](#references)]). ### 7. How to get cache size and topology? ARM architecture supports reading the cache information via some registers (for example, the CCSIDR register [[3](#references)]). As mentioned earlier, user level applications are not able to read these registers directly. The remaining option is to ask the operating system for this information. However, at the moment, the __Linux kernel does not provide cache information__. Therefore, cpufetch does not print any cache information on ARM CPUs at the moment. There are, however, other approaches to be explored: - Read the registers in kernel mode. This can be accomplished by running a kernel module [[4](#references)]. Unfortunately, running a custom kernel module is tricky, and sometimes impossible to do reasonably (for example, in Android devices). In any case, my decision is to run cpufetch on user level only. - Hardcode the cache information for each SoC: Sometimes, manufacturers publish technical information about the chips, where cache topology and size are shown. This method is impractical, since this kind of information is very hard (or impossible) to find online, and the number of SoC is huge. #### References - [1] [cpufetch x86_64 documentation](https://github.com/Dr-Noob/cpufetch/blob/master/doc/DOCUMENTATION_X86.md) - [2] [Main ID Register](https://developer.arm.com/documentation/ddi0433/c/system-control/register-descriptions/main-id-register) - [3] [Cache size ID Register](https://developer.arm.com/documentation/100403/0200/register-descriptions/aarch32-system-registers/ccsidr--cache-size-id-register) - [4] [How to get the size of the CPU cache in Linux](https://stackoverflow.com/a/63474811/9975463) - [5] [ARM big.LITTLE](https://en.wikipedia.org/wiki/ARM_big.LITTLE) - [6] [Snapdragon 855+ Mobile Platform](https://www.qualcomm.com/products/snapdragon-855-plus-mobile-platform) - [7] [SpecDevice](http://specdevice.com/unmoderated.php) cpufetch-master/doc/DOCUMENTATION_PPC.md 0000664 0000000 0000000 00000004061 14154076152 0017760 0 ustar 00root root 0000000 0000000 ### 2. How to get CPU microarchitecture? __Involved code: [get_uarch_from_pvr (uarch.c)](https://github.com/Dr-Noob/cpufetch/src/ppc/uarch.c)__ Microarchitecture is deduced from the PVR register, which is read using the `mfpvr` instruction. The correspondence between the PVR and the specific microarchitecture has been implemented using the values in `arch/powerpc/kernel/cputable.c` in the Linux kernel. Some of them have been removed. The manufacturing process has been queried by searching on the internet. ### 3. How to get CPU topology? __Involved code: [get_topology_info (ppc.c)](https://github.com/Dr-Noob/cpufetch/src/ppc/ppc.c)__ The total number of cores is queried using `sysconf(_SC_NPROCESSORS_ONLN)`. Then, with the number of sockets and the number of physical cores, we can calculate the number of threads per core. The number of sockets is queried using `/sys/devices/system/cpu/cpu*/topology/physical_package_id`. Once this file has been read for all of the cores, a simple custom algorithm is used to determine the number of sockets. The number of physical cores is queried using `/sys/devices/system/cpu/cpu*/topology/core_id`. Again, a custom algorithm is used to determine the number of physical cores. ### 4. How to get the frequency? Frequency is read directly from `/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq` ### 5. How to get cache size and topology? Cache size is retrieved directly from Linux (using `/sys/devices/system/cpu/cpu0/cache/index*/size`). To find the cache topology, the files `/sys/devices/system/cpu/cpu0/cache/index*/shared_cpu_map` are used, and a custom algorithm is used to determine how many caches are there at each level. _NOTE_: To avoid Linux dependencies at this point, it looks like it is possible to derive the cache size and topology from the microarchitecture. For example, in the POWER9 architecture, wikichip assumes that all the POWER9 CPUs have the same cache size for each core and topology [[1](#references)]. #### References - [1] [POWER9 - wikichip](https://en.wikichip.org/wiki/ibm/microarchitectures/power9) cpufetch-master/doc/DOCUMENTATION_X86.md 0000664 0000000 0000000 00000020173 14154076152 0017725 0 ustar 00root root 0000000 0000000 ### 2. Why differences between Intel and AMD? There are many different CPUID leaves [[1](#references)]. In some cases, a given leaf does the same thing in Intel and AMD processors, but in the majority of them, they don't. For example, leaf 0x4 gives you the caches information, but in AMD is a reserved (invalid) leaf! In the case of AMD, is more common to fetch information using extended levels than using the standard levels (the other way around with Intel). ### 3. How to get the frequency? __Involved code: [get_frequency_info (cpuid.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/cpuid.c)__ CPUID leaf 0x16 is used. If the CPU does not support supports such level: - Linux: cpufetch will try to obtain this information using `/sys` filesystem in Linux. I think that Linux knows the frequency using model specific registers (MSRs), which you can't read at the user level. - Windows: cpufetch can't obtain CPU frequency. This means that peak performance can't be computed because the frequency is needed to compute it. ### 4. How to get cache sizes? __Involved code: [get_cache_info (cpuid.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/cpuid.c)__ - Intel: CPUID leaf 0x4 is used (using __get_cache_info_general__). If the CPU does not support it, cpufetch can't get this information. - AMD: Extended CPUID leaf 0x1D is used (using __get_cache_info_general__). If the CPU does not support this level, cpufetch uses a fallback method, which uses extended leaves 0x5 and 0x6. This fallback method uses __get_cache_info_amd_fallback__. ### 5. How to get CPU microarchitecture? __Involved code: [get_cpu_uarch (cpuid.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/cpuid.c), [get_uarch_from_cpuid (uarch.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/uarch.c)__ CPUID leaf 0x1 is used. From there, we get: - Model - Extended Model - Family - Extended Family - Stepping Knowing this information, we can distinguish any CPU microarchitecture. Inside __uarch.c__ there is a function that behaves like a database or a lookup table. The function of this database is to find a match between the information obtained from 0x1 and what kind of microarchitecture the current CPU is. I got the data using and adapting the code from Todd Allen's cpuid program [[5](#references)]. Knowing the microarchitecture, we can obtain the manufacturing process (or technology, the size in nm of the transistors). ### 6. How to get CPU topology? __Involved code: [cpuid.h](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/cpuid.h), [get_topology_info (cpuid.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/cpuid.c), [apic.c](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/apic.c)__ cpufetch aims to support the most complex systems, so it supports multi-socket CPUs and detailed SMT (Intel HyperThreading) information. The CPU topology is stored in the following struct: ``` struct topology { int64_t total_cores; uint32_t physical_cores; uint32_t logical_cores; uint32_t smt_available; uint32_t smt_supported; uint32_t sockets; }; ``` This structure needs a bit of explanation, to know what are we looking for: - `physical_cores`: Number of physical cores. In a multi socket system, this field stores the number of cores for just one socket. - `logical_cores`: Number of logical cores. In a multi socket system, this field stores the number of logical cores for just one socket. - `total_cores`: Total number of logical cores. In a multi socket system, this field stores the number of logical cores for the entire system. - `sockets`: How many sockets the system has. - `smt_supported`: Stores if SMT (or Intel HT) is supported in the CPU, storing the number of threads per core. So, if `smt_supported == 1`, it means that there is 1 thread per core, and SMT is not supported. If SMT is supported, then `smt_supported >= 1`. Note this field tells if the CPU if supports it, but not if SMT is activated or not. - `smt_available`: The same idea as `smt_supported`, but it stores if SMT is available. If SMT is not supported, then `smt_available` is always `1`. The differentiation between supported and available lets cpufetch distinguish when a CPU has SMT capabilities, but are disabled (probably in the BIOS). Let's give two CPU examples and the values that `struct topology` would have in these CPUs. - Example 1: Dual Socket Intel Xeon 6248: ``` total_cores = 80 physical_cores = 20 logical_cores = 40 smt_available = 2 smt_supported = 2 sockets = 2 ``` - Example 2: Intel Core i7-4790K with SMT disabled in BIOS: ``` total_cores = 8 physical_cores = 4 logical_cores = 8 smt_available = 1 smt_supported = 2 sockets = 1 ``` Now that we know what data are we looking for, let's see how we get it: - __Intel__: The methodology used is explained in the Intel webpage [[2](#references)]. Intel explains how to do it and also gives an example source code. I used it and modified it to fit cpufetch style. The core of this methodology is the usage of the APIC id, so the code is inside __apic.c__. - __AMD__: Intel's algorithm using APIC does not work for AMD. To get the same information in AMD, I used the reference from OSdev [[3](#references)] and also ideas from lscpu [[4](#references)]. This uses: - CPUID extended leaf 0x8: Fill `logical_cores` - CPUID extended leaf 0x1E: Fill `smt_supported` - CPUID standard leaf 0x1 (APIC): Fill `smt_available` If any of these levels are not supported, these fields are just guessed. For example, if we are not able to know if SMT is supported, we guess it is not. With all of these data, we can calculate the rest of the fields: ``` physical_cores = logical_cores / smt_available; if(topo->smt_supported > 1) sockets = total_cores / smt_supported / physical_cores; // Idea borrowed from lscpu else sockets = total_cores / physical_cores; ``` ### 7. How to get cache topology? __Involved code: [get_cache_topology_amd (cpuid.c)](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/cpuid.c), [apic.c](https://github.com/Dr-Noob/cpufetch/blob/master/src/x86/apic.c)__ The topology of a cache gives us information about how many caches we have at a given level. It usually follows the rule of: - L1: The same as the number of cores (one L1i and one L1d per core). - L2: If L2 is the last level cache, one L2. If not, the same as the number of cores (one L2 per core). - L3: One L3 cache per socket (shared among all cores). These assumptions are generally (but not always) true. For example, for the AMD Zen generation, or the Intel Xeon Phi KNL. Thus, cpufetch does not assume the topology but obtains it instead. - __Intel__: The idea is similar to the mentioned in CPU topology [[2](#references)](it also covers how to get cache topology using APIC id). - __AMD__: Again, we have to look for another path for AMD. This time, the way to do it is easier and (I think) more solid and future proof. The idea is to use extended CPUID leaf 0x1D. If the CPU does not support it, we can still guess the topology of the caches (as mentioned earlier). If it does, CPUID can give us how many cores shares a given level of cache. So, if we have the number of cores, we can guess how many caches are there for any given level (see __get_cache_topology_amd__). #### References - [1] [sandpile CPUID webpage](https://www.sandpile.org/x86/cpuid.htm) - [2] [CPU topology and cache topology: Intel](https://software.intel.com/content/www/us/en/develop/articles/intel-64-architecture-processor-topology-enumeration.html) - [3] [CPU topology: AMD](https://wiki.osdev.org/Detecting_CPU_Topology_(80x86)) - [4] [lscpu](https://github.com/karelzak/util-linux/blob/master/sys-utils/lscpu.c) - [5] [Todd Allen's cpuid](http://www.etallen.com/cpuid.html) - [6] [AMD specific CPUID specification](https://www.amd.com/system/files/TechDocs/25481.pdf) - [7] [Intel vs AMD CPU Architectural Differences: Chips and Chiplets](https://c.mi.com/thread-2585048-1-0.html) In addition to all these resources, I found it very interesting to search in the Linux kernel source code (for example, the directory [`arch/x86/kernel/cpu/`](https://elixir.bootlin.com/linux/latest/source/arch/x86/kernel/cpu)), because sometimes you can find ideas that cannot be found anywhere else! cpufetch-master/doc/README.md 0000664 0000000 0000000 00000007174 14154076152 0016212 0 ustar 00root root 0000000 0000000 # cpufetch programming documentation (v0.98) This documentation explains how cpufetch works internally and all the design decisions I made. This document intends to be useful for me in the future, for everyone interested in the project, and for anyone who is trying to obtain any specific information from the CPU. In this way, this can be used as a manual or a page that collects interesting material in this area. ### 1. Basics cpufetch works for __x86_64__ (Intel and AMD), __ARM__ and __PowerPC__ CPUs. However, cpufetch is expected to work better on x86_64, because the codebase is older and has been tested much more than the ARM and PowerPC versions. Depending on the architecture, cpufetch choose certain files to be compiled. A summarized tree of the source code of cpufetch is shown below. ``` cpufetch/ ├── doc │ ├── DOCUMENTATION_ARM.md | ├── DOCUMENTATION_PPC.md │ ├── DOCUMENTATION_X86.md │ └── README.md ├── Makefile ├── README.md └── src/ ├── arm/ │ ├── midr.c │ ├── midr.h │ └── other files ... ├── common/ │ └── common files ... ├── ppc/ | ├── ppc.c | ├── ppc.h | └── other files ... └── x86/ ├── cpuid.c ├── cpuid.h └── other files ... ``` Source code is divided into four directories: - `common/`: Source code shared between all architectures - `arm/`: ARM source code - `ppc/`: PowerPC source code - `x86/`: x86 source code ##### 1.1 Basics (x86_64) In x86, __cpufetch works using the CPUID instruction__. It is called directly using assembly (see `src/x86/cpuid_asm.c`). To understand how CPUID works, see [DOCUMENTATION_X86.md](https://github.com/Dr-Noob/cpufetch/blob/master/doc/DOCUMENTATION_X86.md). At the beginning of execution, cpufetch needs to know the max standard CPUID level and max CPUID extended level supported in the running CPU. We also need to know if the x86 CPU is Intel or AMD because sometimes, the way to obtain the information depends on the manufacturer. This information will be stored in: ``` struct cpuInfo { ... VENDOR cpu_vendor; uint32_t maxLevels; uint32_t maxExtendedLevels; ... }; ``` To use any CPUID leaf, cpufetch always needs to check that it is supported in the current CPU. ##### 1.2 Basics (ARM) In ARM, __cpufetch works using the MIDR register and Linux filesystem__. MIDR (Main ID Register) is read from `/proc/cpuinfo`. It allows the detection of the microarchitecture of the cores. Furthermore, Linux filesystem `/sys/devices/system/cpu/` is used to fetch the number of cores and other information. This is the main reason to explain __why `cpufetch` for ARM only works on Linux systems.__ ##### 1.3 Basics (PowerPC) In PowerPC, __cpufetch works using the PVR register and Linux filesystem__. PVR (Processor Version Register) is read using assembly and it is used to identify the microarchitecture of the CPU. Linux is also used to query the rest of the information, like the CPU topology, frequency, etc. This is the main reason to explain __why `cpufetch` for PowerPC only works on Linux systems.__ ##### 1.4 Documentation organization The rest of the documentation is divided in specific files for each architecture, since each one needs different implementations: - [DOCUMENTATION_ARM.md](https://github.com/Dr-Noob/cpufetch/blob/master/doc/DOCUMENTATION_ARM.md) - [DOCUMENTATION_PPC.md](https://github.com/Dr-Noob/cpufetch/blob/master/doc/DOCUMENTATION_PPC.md) - [DOCUMENTATION_X86.md](https://github.com/Dr-Noob/cpufetch/blob/master/doc/DOCUMENTATION_X86.md) cpufetch-master/pictures/ 0000775 0000000 0000000 00000000000 14154076152 0016013 5 ustar 00root root 0000000 0000000 cpufetch-master/pictures/cascade_lake.jpg 0000664 0000000 0000000 00000600477 14154076152 0021112 0 ustar 00root root 0000000 0000000 'Exif MM * b j( 1 r2 i O ' O 'Adobe Photoshop CS6 (Windows) 2021:08:23 19:38:08 m &( . H H XICC_PROFILE HLino mntrRGB XYZ 1 acspMSFT IEC sRGB -HP cprt P 3desc lwtpt bkpt rXYZ gXYZ , bXYZ @ dmnd T pdmdd vued L view $lumi meas $tech 0 rTRC <