From acb933b5ac129932a37ab79b6e672b5156dd1510 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 7 Jun 2023 11:40:08 -0700 Subject: [ci] Add a LLVM toolchain CI configuration file This only builds a subset of all targets for now since the remaining ones (32-bit targets) would require libgcc/compiler-rt for the 64-bit integer and/or double-precision float helper functions. Currently, only aarch64 targets build with clang, but with follow-up this can be extended to include x86_64 and RISCV64. --- .github/workflows/github-ci-clang.yml | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/github-ci-clang.yml diff --git a/.github/workflows/github-ci-clang.yml b/.github/workflows/github-ci-clang.yml new file mode 100644 index 00000000..404005fb --- /dev/null +++ b/.github/workflows/github-ci-clang.yml @@ -0,0 +1,72 @@ +name: LK CI (Clang) + +# Brute force build a bunch of variants of LK in parallel jobs. + +on: [ push, pull_request ] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + toolchain-ver: [13, 14, 15] + debug: [2] + project: + # Note: Clang toolchains do not ship with a compiler-rt (libgcc) for + # all targets, so we have to restrict this build matrix to targets + # that build without requiring these functions (i.e. 64-bit targets, + # since 32-bit ones require functions such as __divdi3). + - qemu-virt-arm64-test + # TODO: Add x86_64 once clang assembler issues have been fixed. + # - pc-x86-64-test + # TODO: Add riscv64 once clang assembler issues have been fixed. + # - qemu-virt-riscv64-test + # - qemu-virt-riscv64-supervisor-test + env: + PROJECT: ${{ matrix.project }} + TOOLCHAIN_VER: ${{ matrix.toolchain-ver }} + DEBUG: ${{ matrix.debug }} + UBSAN: 0 # UBSan runtimes for baremetal are not part of the toolchain + steps: + - name: banner + shell: bash + run: | + printf "Building with %d processors\n" "$(nproc)" + grep -oP '(?<=model name\t: ).*' /proc/cpuinfo|head -n1 + echo PROJECT = $PROJECT + echo TOOLCHAIN_VER = $TOOLCHAIN_VER + echo DEBUG = $DEBUG + echo UBSAN = $UBSAN + + - name: checkout + uses: actions/checkout@v3 + + # Install LLVM and set up the required environment variables + - name: compute toolchain + shell: bash + run: | + sudo apt install clang-${{ matrix.toolchain-ver }} lld-${{ matrix.toolchain-ver }} + GCC_TOOLCHAIN_PREFIX=$(make list-toolchain | grep TOOLCHAIN_PREFIX | tail -1 | cut -d ' ' -f 3) + # Map the GCC toolchain prefix to a clang --target argument: + CLANG_TRIPLE=$(echo "${GCC_TOOLCHAIN_PREFIX}" | sed 's/-elf-/-unknown-elf/g') + LLVM_BINDIR=/usr/lib/llvm-${{ matrix.toolchain-ver }}/bin + echo "CC=${LLVM_BINDIR}/clang --target=${CLANG_TRIPLE}" >> $GITHUB_ENV + echo "LD=${LLVM_BINDIR}/ld.lld" >> $GITHUB_ENV + echo "OBJDUMP=${LLVM_BINDIR}/llvm-objdump" >> $GITHUB_ENV + echo "OBJCOPY=${LLVM_BINDIR}/llvm-objcopy" >> $GITHUB_ENV + echo "CPPFILT=${LLVM_BINDIR}/llvm-cxxfilt" >> $GITHUB_ENV + echo "SIZE=${LLVM_BINDIR}/llvm-size" >> $GITHUB_ENV + echo "NM=${LLVM_BINDIR}/llvm-nm" >> $GITHUB_ENV + echo "STRIP=${LLVM_BINDIR}/llvm-strip" >> $GITHUB_ENV + echo "TOOLCHAIN_PREFIX=/invalid/prefix/should/not/be/used" >> $GITHUB_ENV + echo "LIBGCC=" >> $GITHUB_ENV + cat "$GITHUB_ENV" + + # build it + - name: build + shell: bash + run: | + make -j $(nproc) + +# vim: ts=2 sw=2 expandtab -- cgit v1.2.3 From 4a9d0c33bd3e532aa369d8362a7faf1ba3cfd26a Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 7 Jun 2023 13:25:01 -0700 Subject: [make] Build with -ffreestanding We should build with -ffreestanding since we are building an OS kernel and cannot rely on all hosted environment functionality being present. Specifically this fixes a compilation error with clang caused by the the #include_next : ``` In file included from target/pc-x86/config.c:9: In file included from dev/include/dev/driver.h:10: In file included from lib/libc/include/sys/types.h:10: In file included from lib/libc/include/limits.h:5: In file included from /usr/lib/llvm-15/lib/clang/15.0.7/include/limits.h:21: /usr/include/limits.h:26:10: fatal error: 'bits/libc-header-start.h' file not found #include ``` The flag fixes this issue by ensuring that __STDC_HOSTED__ is no longer set to 1, so Clang's limits.h will not try to include the host system one. --- engine.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine.mk b/engine.mk index 950af50e..cde3a250 100644 --- a/engine.mk +++ b/engine.mk @@ -66,6 +66,9 @@ GLOBAL_COMPILEFLAGS := -g -include $(CONFIGHEADER) GLOBAL_COMPILEFLAGS += -Wextra -Wall -Werror=return-type -Wshadow -Wdouble-promotion GLOBAL_COMPILEFLAGS += -Wno-multichar -Wno-unused-parameter -Wno-unused-function -Wno-unused-label GLOBAL_COMPILEFLAGS += -fno-common +# Build with -ffreestanding since we are building an OS kernel and cannot +# rely on all hosted environment functionality being present. +GLOBAL_COMPILEFLAGS += -ffreestanding GLOBAL_CFLAGS := --std=gnu11 -Werror-implicit-function-declaration -Wstrict-prototypes -Wwrite-strings GLOBAL_CPPFLAGS := --std=c++14 -fno-exceptions -fno-rtti -fno-threadsafe-statics GLOBAL_ASMFLAGS := -DASSEMBLY -- cgit v1.2.3 From c2a31bf8a6bbced04d9c63325a2de24842dbb780 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 7 Jun 2023 13:30:11 -0700 Subject: [x86][clang] Make return mnemonic compatible with clang GCC appears to accept the Intel retf syntax in AT&T mode but clang is stricter and requires use of lret. --- arch/x86/64/start.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/64/start.S b/arch/x86/64/start.S index b11e8bca..7637525a 100644 --- a/arch/x86/64/start.S +++ b/arch/x86/64/start.S @@ -74,7 +74,7 @@ real_start: /* far jump to load the CS from our GDT */ pushl $CODE_SELECTOR pushl $PHYS(.Lfarjump) - retf + lret .Lfarjump: @@ -185,7 +185,7 @@ paging_setup: /* Use a far jump to get into 64bit mode */ pushl $CODE_64_SELECTOR pushl $PHYS(farjump64) - retf + lret .align 8 .code64 -- cgit v1.2.3 From e3a463e5857fb2ff736c21a00ab69cb6a20f9938 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 7 Jun 2023 14:31:07 -0700 Subject: [x86][clang] Allow clang to evaluate isr_stub_len The current code results in `error: invalid reassignment of non-absolute variable 'isr_stub_start'`. Use a numbered label instead (as that can be reassigned) and reference the last occurrence using the b suffix. --- arch/x86/32/exceptions.S | 9 ++++----- arch/x86/64/exceptions.S | 8 ++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/x86/32/exceptions.S b/arch/x86/32/exceptions.S index 8ca8771b..98ac81f1 100644 --- a/arch/x86/32/exceptions.S +++ b/arch/x86/32/exceptions.S @@ -21,8 +21,7 @@ _isr: .set i, 0 .rept NUM_INT -.set isr_stub_start, . - +100: /* unnamed label for start of isr stub */ .if i == 8 || (i >= 10 && i <= 14) || i == 17 nop /* error code pushed by exception */ nop /* 2 nops are the same length as push byte */ @@ -34,12 +33,12 @@ _isr: jmp interrupt_common .endif -/* figure out the length of a single isr stub (usually 6 or 9 bytes) */ -.set isr_stub_len, . - isr_stub_start - .set i, i + 1 .endr +/* figure out the length of a single isr stub (usually 6 or 9 bytes) */ +.set isr_stub_len, . - 100b + /* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */ .fill 256 diff --git a/arch/x86/64/exceptions.S b/arch/x86/64/exceptions.S index e66c53ce..86a54827 100644 --- a/arch/x86/64/exceptions.S +++ b/arch/x86/64/exceptions.S @@ -26,7 +26,7 @@ _isr: .set i, 0 .rept NUM_INT -.set isr_stub_start, . +100: /* unnamed label for start of isr stub */ .if i == 8 || (i >= 10 && i <= 14) || i == 17 .align 16 @@ -43,12 +43,12 @@ _isr: .align 16 .endif -/* figure out the length of a single isr stub (usually 6 or 9 bytes) */ -.set isr_stub_len, . - isr_stub_start - .set i, i + 1 .endr +/* figure out the length of a single isr stub (usually 6 or 9 bytes) */ +.set isr_stub_len, . - 100b + /* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */ .fill 256 -- cgit v1.2.3 From 6025bec3a1a295deacb8e3479957176c89f5068d Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 7 Jun 2023 15:45:10 -0700 Subject: [ci] Add pc-x86-64-test to the Clang CI job --- .github/workflows/github-ci-clang.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/github-ci-clang.yml b/.github/workflows/github-ci-clang.yml index 404005fb..c14e9b10 100644 --- a/.github/workflows/github-ci-clang.yml +++ b/.github/workflows/github-ci-clang.yml @@ -17,9 +17,8 @@ jobs: # all targets, so we have to restrict this build matrix to targets # that build without requiring these functions (i.e. 64-bit targets, # since 32-bit ones require functions such as __divdi3). + - pc-x86-64-test - qemu-virt-arm64-test - # TODO: Add x86_64 once clang assembler issues have been fixed. - # - pc-x86-64-test # TODO: Add riscv64 once clang assembler issues have been fixed. # - qemu-virt-riscv64-test # - qemu-virt-riscv64-supervisor-test -- cgit v1.2.3 From 496e2f4b8c82f30464c3cdfa3c7a65e6e2ac55c2 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Thu, 9 Dec 2021 11:14:22 +0000 Subject: [riscv][clang] Use a CSR name instead of a numeric expression Clang's assembler rejects expressions containing e.g. (1u << N) in the assembler. Instead using numeric expressions for per-privilege level CSRs, we can prepend `m` or `s`. This also lets the compiler assign the CSR encoding instead of having to hardcode it in the source code. --- arch/riscv/include/arch/riscv.h | 20 +++++++++++--------- .../rp2_common/pico_platform/include/pico/platform.h | 1 - platform/rp20xx/include/sys/cdefs.h | 6 ------ top/include/lk/compiler.h | 3 +++ 4 files changed, 14 insertions(+), 16 deletions(-) delete mode 100644 platform/rp20xx/include/sys/cdefs.h diff --git a/arch/riscv/include/arch/riscv.h b/arch/riscv/include/arch/riscv.h index 340284d4..ac265f0d 100644 --- a/arch/riscv/include/arch/riscv.h +++ b/arch/riscv/include/arch/riscv.h @@ -19,9 +19,11 @@ #if RISCV_M_MODE # define RISCV_XMODE_OFFSET (RISCV_MACH_OFFSET) # define RISCV_XRET mret +# define RISCV_MODE_PREFIX m #elif RISCV_S_MODE # define RISCV_XMODE_OFFSET (RISCV_SUPER_OFFSET) # define RISCV_XRET sret +# define RISCV_MODE_PREFIX s #else # error Unrecognized RISC-V privilege level selected #endif @@ -36,14 +38,14 @@ #define RISCV_CSR_TIMEH (0xc81) #define RISCV_CSR_INSRETH (0xc82) -#define RISCV_CSR_XSTATUS (0x000 | RISCV_CSR_XMODE_BITS) -#define RISCV_CSR_XIE (0x004 | RISCV_CSR_XMODE_BITS) -#define RISCV_CSR_XTVEC (0x005 | RISCV_CSR_XMODE_BITS) -#define RISCV_CSR_XSCRATCH (0x040 | RISCV_CSR_XMODE_BITS) -#define RISCV_CSR_XEPC (0x041 | RISCV_CSR_XMODE_BITS) -#define RISCV_CSR_XCAUSE (0x042 | RISCV_CSR_XMODE_BITS) -#define RISCV_CSR_XTVAL (0x043 | RISCV_CSR_XMODE_BITS) -#define RISCV_CSR_XIP (0x044 | RISCV_CSR_XMODE_BITS) +#define RISCV_CSR_XSTATUS __CONCAT(RISCV_MODE_PREFIX, status) +#define RISCV_CSR_XIE __CONCAT(RISCV_MODE_PREFIX, ie) +#define RISCV_CSR_XTVEC __CONCAT(RISCV_MODE_PREFIX, tvec) +#define RISCV_CSR_XSCRATCH __CONCAT(RISCV_MODE_PREFIX, scratch) +#define RISCV_CSR_XEPC __CONCAT(RISCV_MODE_PREFIX, epc) +#define RISCV_CSR_XCAUSE __CONCAT(RISCV_MODE_PREFIX, cause) +#define RISCV_CSR_XTVAL __CONCAT(RISCV_MODE_PREFIX, tval) +#define RISCV_CSR_XIP __CONCAT(RISCV_MODE_PREFIX, ip) #if RISCV_M_MODE // Machine-mode only CSRs #define RISCV_CSR_MCYCLE (0xb00) @@ -55,7 +57,7 @@ #endif // RISCV_M_MODE #if RISCV_S_MODE // Supervisor-mode only CSRs -#define RISCV_CSR_SATP (0x180) +#define RISCV_CSR_SATP satp #endif #define RISCV_CSR_XSTATUS_IE (1ul << (RISCV_XMODE_OFFSET + 0)) diff --git a/external/platform/pico/rp2_common/pico_platform/include/pico/platform.h b/external/platform/pico/rp2_common/pico_platform/include/pico/platform.h index 2ed5e212..d0771e1e 100644 --- a/external/platform/pico/rp2_common/pico_platform/include/pico/platform.h +++ b/external/platform/pico/rp2_common/pico_platform/include/pico/platform.h @@ -7,7 +7,6 @@ #ifndef _PICO_PLATFORM_H_ #define _PICO_PLATFORM_H_ -#include #include "pico/types.h" #include "hardware/platform_defs.h" diff --git a/platform/rp20xx/include/sys/cdefs.h b/platform/rp20xx/include/sys/cdefs.h deleted file mode 100644 index 9fc7e4f4..00000000 --- a/platform/rp20xx/include/sys/cdefs.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#ifndef __CONCAT -#define __CONCAT1(x,y) x ## y -#define __CONCAT(x,y) __CONCAT1(x,y) -#endif diff --git a/top/include/lk/compiler.h b/top/include/lk/compiler.h index 45b1dc81..04236826 100644 --- a/top/include/lk/compiler.h +++ b/top/include/lk/compiler.h @@ -11,6 +11,9 @@ #pragma once +#define __CONCAT1(x, y) x ## y +#define __CONCAT(x, y) __CONCAT1(x, y) + #ifndef __ASSEMBLY__ #if __GNUC__ || __clang__ -- cgit v1.2.3 From 8c20e005ca0f6459670f0a7c449cc2988f3e04a6 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Thu, 9 Dec 2021 11:23:47 +0000 Subject: [make] Set LINKER_TYPE to lld when building with ld.lld This will be needed in a follow-up commit to disable linker relaxations for RISC-V since ld.ldd does not support them yet. --- engine.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/engine.mk b/engine.mk index cde3a250..c89d1a2c 100644 --- a/engine.mk +++ b/engine.mk @@ -195,6 +195,12 @@ SIZE ?= $(TOOLCHAIN_PREFIX)size NM ?= $(TOOLCHAIN_PREFIX)nm STRIP ?= $(TOOLCHAIN_PREFIX)strip +# Detect whether we are using ld.lld. If we don't detect ld.lld, we assume +# it's ld.bfd. This check can be refined in the future if we need to handle +# more cases (e.g. ld.gold). +LINKER_TYPE := $(shell $(LD) -v 2>&1 | grep -q "LLD" && echo lld || echo bfd) +$(info LINKER_TYPE=$(LINKER_TYPE)) + # Now that CC is defined we can check if warning flags are supported and add # them to GLOBAL_COMPILEFLAGS if they are. ifeq ($(call is_warning_flag_supported,-Wnonnull-compare),yes) -- cgit v1.2.3 From 135479c70ec6e4e3384b1bb8433a12e587667d30 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Thu, 9 Dec 2021 11:43:39 +0000 Subject: [riscv] Disable linker relaxations when linking with ld.lld We have to compile RISC-V code with -mno-relax when linking with ld.lld since ld.lld does not yet support RISC-V linker relaxations. Without this change, linking with ld.lld results in many errors such as: `relocation R_RISCV_ALIGN requires unimplemented linker relaxation`. This support was implemented as part of LLVM 15, but to support older versions of ld.lld we add the flag unconditionally for now. --- engine.mk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/engine.mk b/engine.mk index c89d1a2c..25384b83 100644 --- a/engine.mk +++ b/engine.mk @@ -216,6 +216,14 @@ ARCH_COMPILEFLAGS += -Wno-asm-operand-widths endif endif +ifeq ($(ARCH),riscv) +# ld.lld does not support linker relaxations yet. +# TODO: This is no longer true as of LLVM 15, so should add a version check +ifeq ($(LINKER_TYPE),lld) +ARCH_COMPILEFLAGS += -mno-relax +endif +endif + $(info PROJECT = $(PROJECT)) $(info PLATFORM = $(PLATFORM)) $(info TARGET = $(TARGET)) -- cgit v1.2.3 From 69111c40f5fbde5ffcdcc1a3ba84789a04f260e1 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Fri, 10 Mar 2023 03:55:58 -0800 Subject: [make] Add a COMPILER_TYPE variable This can be used to change compiler flags for GCC vs Clang. --- engine.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine.mk b/engine.mk index 25384b83..29823452 100644 --- a/engine.mk +++ b/engine.mk @@ -200,6 +200,9 @@ STRIP ?= $(TOOLCHAIN_PREFIX)strip # more cases (e.g. ld.gold). LINKER_TYPE := $(shell $(LD) -v 2>&1 | grep -q "LLD" && echo lld || echo bfd) $(info LINKER_TYPE=$(LINKER_TYPE)) +# Detect whether we are compiling with GCC or Clang +COMPILER_TYPE := $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) +$(info COMPILER_TYPE=$(COMPILER_TYPE)) # Now that CC is defined we can check if warning flags are supported and add # them to GLOBAL_COMPILEFLAGS if they are. -- cgit v1.2.3 From bf6ab93088f7efe7c66f88b71d87b09893ee32e3 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Thu, 9 Dec 2021 04:05:29 -0800 Subject: [riscv] Workaround for undef-weak symbol relocations with clang+lld When building with clang -mcmodel=medany and linking with ld.lld, we get out-of-range relocation errors for undefined __start_
symbols since 0 cannot be represented as a PC-relative offset). This is not a problem with ld.bfd since ld.bfd rewrites the instructions to avoid the out-of-range PC-relative relocation. For now, the simplest workaround is to build with -fpie -mcmodel=medany (thus indirecting these symbols via the GOT). This will be done automatically once clang includes https://reviews.llvm.org/D107280. Without this change I get the following linker errors: ld.lld: error: dev/driver.c:21:(.text+0x1E): relocation R_RISCV_PCREL_HI20 out of range: -524295 is not in [-524288, 524287]; references __start_devices See https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/126 and https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/201. --- engine.mk | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/engine.mk b/engine.mk index 29823452..20176a49 100644 --- a/engine.mk +++ b/engine.mk @@ -224,6 +224,18 @@ ifeq ($(ARCH),riscv) # TODO: This is no longer true as of LLVM 15, so should add a version check ifeq ($(LINKER_TYPE),lld) ARCH_COMPILEFLAGS += -mno-relax +# Work around out-of-range undef-weak relocations when building with clang and +# linking with ld.lld. This is not a problem with ld.bfd since ld.bfd rewrites +# the instructions to avoid the out-of-range PC-relative relocation +# See https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/126 for more +# details. For now, the simplest workaround is to build with -fpie when using +# a version of clang that does not include https://reviews.llvm.org/D107280. +# TODO: Add a clang 17 version check now that the review has been merged. +ifeq ($(COMPILER_TYPE),clang) +# We also add the -fdirect-access-external-data flag is added to avoid the +# majority of the performance overhead caused by -fPIE. +ARCH_COMPILEFLAGS += -fPIE -fdirect-access-external-data +endif endif endif -- cgit v1.2.3 From 3b215c398e582765ea33331369250ace997dcf98 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 7 Jun 2023 16:07:37 -0700 Subject: [ci] Add 64-bit RISC-V to Clang CI --- .github/workflows/github-ci-clang.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/github-ci-clang.yml b/.github/workflows/github-ci-clang.yml index c14e9b10..19dc5612 100644 --- a/.github/workflows/github-ci-clang.yml +++ b/.github/workflows/github-ci-clang.yml @@ -19,9 +19,8 @@ jobs: # since 32-bit ones require functions such as __divdi3). - pc-x86-64-test - qemu-virt-arm64-test - # TODO: Add riscv64 once clang assembler issues have been fixed. - # - qemu-virt-riscv64-test - # - qemu-virt-riscv64-supervisor-test + - qemu-virt-riscv64-test + - qemu-virt-riscv64-supervisor-test env: PROJECT: ${{ matrix.project }} TOOLCHAIN_VER: ${{ matrix.toolchain-ver }} -- cgit v1.2.3