Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/riscv_linux_cmake.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: RISCV Linux CMake

on:
push:
pull_request:
schedule:
# min hours day(month) month day(week)
- cron: '0 0 7,22 * *'

jobs:
# Building using the github runner environement directly.
make:
runs-on: ubuntu-latest
strategy:
matrix:
targets: [
[riscv32],
[riscv64],
]
fail-fast: false
env:
TARGET: ${{ matrix.targets[0] }}
steps:
- uses: actions/checkout@v2
- name: Build
run: make --directory=cmake/ci ${TARGET}_build
- name: Test
run: make --directory=cmake/ci ${TARGET}_test
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ set(PROCESSOR_IS_AARCH64 FALSE)
set(PROCESSOR_IS_X86 FALSE)
set(PROCESSOR_IS_POWER FALSE)
set(PROCESSOR_IS_S390X FALSE)
set(PROCESSOR_IS_RISCV FALSE)

if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE)
Expand All @@ -63,6 +64,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(PROCESSOR_IS_POWER TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)")
set(PROCESSOR_IS_S390X TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv")
set(PROCESSOR_IS_RISCV TRUE)
endif()

macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
Expand All @@ -84,6 +87,8 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
elseif(PROCESSOR_IS_S390X)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h)
elseif(PROCESSOR_IS_RISCV)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_riscv.h)
else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif()
Expand Down
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ instructions) at runtime.

[comment]: <> (The following lines are generated by "scripts/generate_badges.d" that you can run online https://run.dlang.io/)

| Os | amd64 | AArch64 | ARM | MIPS | s390x | POWER |
| :-- | --: | --: | --: | --: | --: | --: |
| Linux | [![][i1a0]][l1a0]<br/>[![][i1a1]][l1a1] | [![][i1b0]][l1b0]<br/>![][d1] | [![][i1c0]][l1c0]<br/>![][d1] | [![][i1d0]][l1d0]<br/>![][d1] | [![][i1e0]][l1e0]<br/>![][d1] | [![][i1f0]][l1f0]<br/>![][d1] |
| FreeBSD | [![][i2a0]][l2a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
| MacOS | [![][i3a0]][l3a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
| Windows | [![][i4a0]][l4a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
| Os | amd64 | AArch64 | ARM | MIPS | POWER | RISCV | s390x |
| :-- | --: | --: | --: | --: | --: | --: | --: |
| Linux | [![][i1a0]][l1a0]<br/>[![][i1a1]][l1a1] | [![][i1b0]][l1b0]<br/>![][d1] | [![][i1c0]][l1c0]<br/>![][d1] | [![][i1d0]][l1d0]<br/>![][d1] | [![][i1e0]][l1e0]<br/>![][d1] | [![][i1f0]][l1f0]<br/>![][d1] | [![][i1g0]][l1g0]<br/>![][d1] |
| FreeBSD | [![][i2a0]][l2a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
| MacOS | [![][i3a0]][l3a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
| Windows | [![][i4a0]][l4a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |

[d0]: https://img.shields.io/badge/CMake-N%2FA-lightgrey
[d1]: https://img.shields.io/badge/Bazel-N%2FA-lightgrey
Expand All @@ -21,8 +21,9 @@ instructions) at runtime.
[i1b0]: https://img.shields.io/github/workflow/status/google/cpu_features/AArch64%20Linux%20CMake/main?label=CMake
[i1c0]: https://img.shields.io/github/workflow/status/google/cpu_features/ARM%20Linux%20CMake/main?label=CMake
[i1d0]: https://img.shields.io/github/workflow/status/google/cpu_features/MIPS%20Linux%20CMake/main?label=CMake
[i1e0]: https://img.shields.io/github/workflow/status/google/cpu_features/s390x%20Linux%20CMake/main?label=CMake
[i1f0]: https://img.shields.io/github/workflow/status/google/cpu_features/POWER%20Linux%20CMake/main?label=CMake
[i1e0]: https://img.shields.io/github/workflow/status/google/cpu_features/POWER%20Linux%20CMake/main?label=CMake
[i1f0]: https://img.shields.io/github/workflow/status/google/cpu_features/RISCV%20Linux%20CMake/main?label=CMake
[i1g0]: https://img.shields.io/github/workflow/status/google/cpu_features/s390x%20Linux%20CMake/main?label=CMake
[i2a0]: https://img.shields.io/github/workflow/status/google/cpu_features/amd64%20FreeBSD%20CMake/main?label=CMake
[i3a0]: https://img.shields.io/github/workflow/status/google/cpu_features/amd64%20MacOS%20CMake/main?label=CMake
[i4a0]: https://img.shields.io/github/workflow/status/google/cpu_features/amd64%20Windows%20CMake/main?label=CMake
Expand All @@ -31,8 +32,9 @@ instructions) at runtime.
[l1b0]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_cmake.yml
[l1c0]: https://github.com/google/cpu_features/actions/workflows/arm_linux_cmake.yml
[l1d0]: https://github.com/google/cpu_features/actions/workflows/mips_linux_cmake.yml
[l1e0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml
[l1f0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml
[l1e0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml
[l1f0]: https://github.com/google/cpu_features/actions/workflows/riscv_linux_cmake.yml
[l1g0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml
[l2a0]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd_cmake.yml
[l3a0]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_cmake.yml
[l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml
Expand Down Expand Up @@ -176,14 +178,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
<a name="support"></a>
## What's supported

| | x86³ | AArch64 | ARM | MIPS⁴ | s390x | POWER |
|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
| FreeBSD | yes² | not yet | not yet | not yet | not yet | not yet |
| MacOs | yes² | not yet | N/A | N/A | no | no |
| Windows | yes² | not yet | not yet | N/A | N/A | N/A |
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A |
| iOS | N/A | not yet | not yet | N/A | N/A | N/A |
| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | s390x |
|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet |
| MacOs | yes² | not yet | N/A | N/A | no | N/A | no |
| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A |
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A |
| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A |

1. **Features revealed from Linux.** We gather data from several sources
depending on availability:
Expand Down
3 changes: 3 additions & 0 deletions cmake/ci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ help:
@echo -e "\t\t${BOLD}ppc${RESET} (bootlin toolchain)"
@echo -e "\t\t${BOLD}ppc64${RESET} (bootlin toolchain)"
@echo -e "\t\t${BOLD}ppc64le${RESET} (bootlin toolchain)"
@echo -e "\t\t${BOLD}riscv32${RESET} (bootlin toolchain)"
@echo -e "\t\t${BOLD}riscv64${RESET} (bootlin toolchain)"
@echo -e "\t\t${BOLD}s390x${RESET} (bootlin toolchain)"
@echo
@echo -e "\tWith ${BOLD}<toolchain_stage>${RESET}:"
Expand Down Expand Up @@ -154,6 +156,7 @@ TOOLCHAIN_TARGETS = \
aarch64-linux-gnu aarch64_be-linux-gnu \
mips32 mips32el mips64 mips64el \
ppc ppc64 ppc64le \
riscv32 riscv64 \
s390x
TOOLCHAIN_STAGES = env devel build test
define toolchain-stage-target =
Expand Down
70 changes: 70 additions & 0 deletions include/cpuinfo_riscv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_

#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"

#if !defined(CPU_FEATURES_ARCH_RISCV)
#error "Including cpuinfo_riscv.h from a non-riscv target."
#endif

CPU_FEATURES_START_CPP_NAMESPACE

typedef struct {
// Base
int RV32I : 1; // Base Integer Instruction Set, 32-bit
int RV64I : 1; // Base Integer Instruction Set, 64-bit

// Extension
int M : 1; // Standard Extension for Integer Multiplication/Division
int A : 1; // Standard Extension for Atomic Instructions
int F : 1; // Standard Extension for Single-Precision Floating-Point
int D : 1; // Standard Extension for Double-Precision Floating-Point
int Q : 1; // Standard Extension for Quad-Precision Floating-Point
int C : 1; // Standard Extension for Compressed Instructions
int Zicsr : 1; // Control and Status Register (CSR)
int Zifencei : 1; // Instruction-Fetch Fence
} RiscvFeatures;

typedef struct {
RiscvFeatures features;
char uarch[64]; // 0 terminated string
char vendor[64]; // 0 terminated string
} RiscvInfo;

typedef enum {
RISCV_RV32I,
RISCV_RV64I,
RISCV_M,
RISCV_A,
RISCV_F,
RISCV_D,
RISCV_Q,
RISCV_C,
RISCV_Zicsr,
RISCV_Zifencei,
RISCV_LAST_,
} RiscvFeaturesEnum;

RiscvInfo GetRiscvInfo(void);
int GetRiscvFeaturesEnumValue(const RiscvFeatures* features,
RiscvFeaturesEnum value);
const char* GetRiscvFeaturesEnumName(RiscvFeaturesEnum);

CPU_FEATURES_END_CPP_NAMESPACE

#endif // CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
12 changes: 6 additions & 6 deletions include/internal/hwcaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,15 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define HWCAP_S390_SIE 4194304

// https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/uapi/asm/hwcap.h
#define RISCV_HWCAP_32 0x32
#define RISCV_HWCAP_64 0x64
#define RISCV_HWCAP_128 0x128
#define RISCV_HWCAP_M (1UL << ('M' - 'A'))
#define RISCV_HWCAP_A (1UL << ('A' - 'A'))
#define RISCV_HWCAP_C (1UL << ('C' - 'A'))
#define RISCV_HWCAP_D (1UL << ('D' - 'A'))
#define RISCV_HWCAP_E (1UL << ('E' - 'A'))
#define RISCV_HWCAP_F (1UL << ('F' - 'A'))
#define RISCV_HWCAP_I (1UL << ('I' - 'A'))
#define RISCV_HWCAP_M (1UL << ('M' - 'A'))
#define RISCV_HWCAP_V (1UL << ('V' - 'A'))
#define RISCV_HWCAP_D (1UL << ('D' - 'A'))
#define RISCV_HWCAP_Q (1UL << ('Q' - 'A'))
#define RISCV_HWCAP_C (1UL << ('C' - 'A'))

typedef struct {
unsigned long hwcaps;
Expand Down
3 changes: 2 additions & 1 deletion scripts/generate_badges.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ enum Cpu
AArch64,
ARM,
MIPS,
s390x,
POWER,
RISCV,
s390x,
}

enum Os
Expand Down
15 changes: 15 additions & 0 deletions scripts/run_integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ function expand_bootlin_config() {
local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc-440fp/tarballs/powerpc-440fp--glibc--stable-2021.11-1.tar.bz2"
local -r GCC_PREFIX="powerpc"
;;
"riscv32")
local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/riscv32-ilp32d/tarballs/riscv32-ilp32d--glibc--bleeding-edge-2022.08-1.tar.bz2"
local -r GCC_PREFIX="riscv32"
;;
"riscv64")
local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/riscv64-lp64d/tarballs/riscv64-lp64d--glibc--stable-2022.08-1.tar.bz2"
local -r GCC_PREFIX="riscv64"
;;
"s390x")
local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/s390x-z13/tarballs/s390x-z13--glibc--stable-2022.08-1.tar.bz2"
local -r GCC_PREFIX="s390x"
Expand Down Expand Up @@ -362,6 +370,7 @@ DESCRIPTION
\t\tmips64 mips64el (codespace)
\t\tppc (bootlin)
\t\tppc64 ppc64le (bootlin)
\t\triscv32 riscv64 (bootlin)
\t\ts390x (bootlin)

OPTIONS
Expand Down Expand Up @@ -448,6 +457,12 @@ function main() {
ppc)
expand_bootlin_config
declare -r QEMU_ARCH=ppc ;;
riscv32)
expand_bootlin_config
declare -r QEMU_ARCH=riscv32 ;;
riscv64)
expand_bootlin_config
declare -r QEMU_ARCH=riscv64 ;;
s390x)
expand_bootlin_config
declare -r QEMU_ARCH=s390x ;;
Expand Down
110 changes: 110 additions & 0 deletions src/impl_riscv_linux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cpu_features_macros.h"

#ifdef CPU_FEATURES_ARCH_RISCV
#if defined(CPU_FEATURES_OS_LINUX)

#include "cpuinfo_riscv.h"

// According to
// https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/riscv/cpus.yaml
// isa string should match the following regex
// ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$
//
// This means we can test for features in this exact order except for Z
// extensions.

////////////////////////////////////////////////////////////////////////////////
// Definitions for introspection.
////////////////////////////////////////////////////////////////////////////////
#define INTROSPECTION_TABLE \
LINE(RISCV_RV32I, RV32I, "rv32i", RISCV_HWCAP_32, 0) \
LINE(RISCV_RV64I, RV64I, "rv64i", RISCV_HWCAP_64, 0) \
LINE(RISCV_M, M, "m", RISCV_HWCAP_M, 0) \
LINE(RISCV_A, A, "a", RISCV_HWCAP_A, 0) \
LINE(RISCV_F, F, "f", RISCV_HWCAP_F, 0) \
LINE(RISCV_D, D, "d", RISCV_HWCAP_D, 0) \
LINE(RISCV_Q, Q, "q", RISCV_HWCAP_Q, 0) \
LINE(RISCV_C, C, "c", RISCV_HWCAP_C, 0) \
LINE(RISCV_Zicsr, Zicsr, "_zicsr", 0, 0) \
LINE(RISCV_Zifencei, Zifencei, "_zifencei", 0, 0)
#define INTROSPECTION_PREFIX Riscv
#define INTROSPECTION_ENUM_PREFIX RISCV
#include "define_introspection_and_hwcaps.inl"

////////////////////////////////////////////////////////////////////////////////
// Implementation.
////////////////////////////////////////////////////////////////////////////////

#include <stdbool.h>
#include <stdio.h>

#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"

static const RiscvInfo kEmptyRiscvInfo;

static void HandleRiscVIsaLine(StringView line, RiscvFeatures* const features) {
for (size_t i = 0; i < RISCV_LAST_; ++i) {
StringView flag = str(kCpuInfoFlags[i]);
int index_of_flag = CpuFeatures_StringView_IndexOf(line, flag);
bool is_set = index_of_flag != -1;
kSetters[i](features, is_set);
if (is_set)
line = CpuFeatures_StringView_PopFront(line, index_of_flag + flag.size);
}
}

static bool HandleRiscVLine(const LineResult result, RiscvInfo* const info) {
StringView line = result.line;
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("isa"))) {
HandleRiscVIsaLine(value, &info->features);
} else if (CpuFeatures_StringView_IsEquals(key, str("uarch"))) {
int index = CpuFeatures_StringView_IndexOfChar(value, ',');
if (index == -1) return true;
StringView vendor = CpuFeatures_StringView_KeepFront(value, index);
StringView uarch = CpuFeatures_StringView_PopFront(value, index + 1);
CpuFeatures_StringView_CopyString(vendor, info->vendor,
sizeof(info->vendor));
CpuFeatures_StringView_CopyString(uarch, info->uarch,
sizeof(info->uarch));
}
}
return !result.eof;
}

static void FillProcCpuInfoData(RiscvInfo* const info) {
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0) {
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;) {
if (!HandleRiscVLine(StackLineReader_NextLine(&reader), info)) break;
}
CpuFeatures_CloseFile(fd);
}
}

RiscvInfo GetRiscvInfo(void) {
RiscvInfo info = kEmptyRiscvInfo;
FillProcCpuInfoData(&info);
return info;
}

#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#endif // CPU_FEATURES_ARCH_RISCV
Loading