From ae7b689bfad8d1821356ad70c949e66616652e41 Mon Sep 17 00:00:00 2001 From: Gregor Haas Date: Sat, 6 Jan 2024 11:28:03 -0800 Subject: [PATCH] Implement new CI on Github Actions (#399) This PR creates a new efficient CI system for the Buildroot-based build system introduced a while ago. It includes full build tests for each supported platform (currently `generic` and `unmatched`, with `cva6` and `mpfs` landing soon) as well as full-stack runtime tests for the 32 and 64-bit generic platforms. CI times are kept low by heavily relying on Github Actions caching, where we save the latest compiler cache and Buildroot package cache at the end of each run. On average, the `generic` platforms build in 10 minutes while the `unmatched` platform builds in 13 (with a hot cache). With a cold cache, the builds take about an hour but will then refresh the caches so that future ones take much less time. --- .circleci/config.yml | 369 ------------------ .github/workflows/build-runtime.yml | 84 ++++ .github/workflows/main.yml | 165 ++++++++ .github/workflows/test-system.yml | 67 ++++ Makefile | 7 +- examples/CMakeLists.txt | 10 +- examples/attestation/CMakeLists.txt | 7 +- examples/hello-native/CMakeLists.txt | 7 +- examples/hello/CMakeLists.txt | 7 +- examples/tests/CMakeLists.txt | 7 +- examples/tests/test-runner.cpp | 2 +- mkutils/plat/generic/run.mk | 12 +- overlays/keystone/configs/linux32-defconfig | 7 + .../keystone-examples/keystone-examples.mk | 6 +- .../package/keystone-sdk/keystone-sdk.mk | 4 +- runtime/CMakeLists.txt | 1 - runtime/call/linux_wrap.c | 2 +- runtime/call/syscall.c | 2 +- runtime/include/crypto/merkle.h | 2 +- runtime/include/mm/freemem.h | 3 - runtime/include/mm/mm.h | 2 - runtime/include/mm/paging.h | 2 +- runtime/loader-binary/CMakeLists.txt | 2 +- runtime/loader-binary/loader.lds | 10 +- runtime/loader/CMakeLists.txt | 7 +- runtime/mm/CMakeLists.txt | 13 +- runtime/mm/freemem.c | 2 - runtime/mm/freemem_ld.c | 3 - runtime/mm/mm.c | 5 +- runtime/mm/page_swap.c | 2 +- runtime/mm/paging.c | 10 +- runtime/mm/vm.c | 3 - runtime/sys/boot.c | 11 - runtime/test/CMakeLists.txt | 4 +- runtime/util/printf.c | 2 + scripts/ci/build-runtime.sh | 36 ++ scripts/ci/expected.log | 25 ++ scripts/gdb.sh | 3 - scripts/gdb/pmp.py | 51 ++- scripts/run-qemu.sh.in | 34 -- scripts/test-qemu.sh.in | 32 -- scripts/travis.sh | 19 - sdk/CMakeLists.txt | 10 +- sdk/macros.cmake | 2 +- 44 files changed, 481 insertions(+), 580 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/build-runtime.yml create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/test-system.yml create mode 100755 scripts/ci/build-runtime.sh create mode 100644 scripts/ci/expected.log delete mode 100755 scripts/gdb.sh delete mode 100755 scripts/run-qemu.sh.in delete mode 100755 scripts/test-qemu.sh.in delete mode 100755 scripts/travis.sh diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 546a2e207..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,369 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference -version: 2.1 - -# prebuilt docker images with toolchain -executors: - setup-rv64gc: - docker: - - image: keystoneenclaveorg/keystone:init-rv64gc - setup-rv32gc: - docker: - - image: keystoneenclaveorg/keystone:init-rv32gc - - -commands: - ###################### - ## General commands ## - ###################### - - update-riscv-toolchain-path-64: - steps: - - run: echo 'export PATH=/keystone/riscv64/bin:$PATH' >> $BASH_ENV - update-riscv-toolchain-path-32: - steps: - - run: echo 'export PATH=/keystone/riscv32/bin:$PATH' >> $BASH_ENV - - ###################### - ## Runtime commands ## - ###################### - - build-sdk: - steps: - - run: | - cd /keystone/sdk - rm -rf build - mkdir build - cd build - KEYSTONE_SDK_DIR=$(pwd) cmake .. - make install - build-runtime: - parameters: - build-name: - type: string - build-dir: - type: string - default: build - build-args: - type: string - default: '' - steps: - - run: - name: << parameters.build-name >> - environment: - KEYSTONE_SDK_DIR: /keystone/sdk/build - command: | - cd runtime - mkdir -p << parameters.build-dir >> - cd << parameters.build-dir >> - cmake -DCMAKE_C_COMPILER=$(which riscv64-unknown-linux-gnu-gcc) \ - -DCMAKE_OBJCOPY=$(which riscv64-unknown-linux-gnu-objcopy) \ - << parameters.build-args >> .. - make - no-output-timeout: 120m - -jobs: - update-dockerhub-image: - parameters: - dockerfile: - type: string - tag: - type: string - docker: - - image: "cimg/base:2022.09" - working_directory: "~/project/keystone" - steps: - - checkout - - setup_remote_docker: - docker_layer_caching: true - - run: - name: "Build and push Docker image (<< parameters.tag >>)" - command: | - cd "docker" - echo "$DOCKER_ACCESS_TOKEN" | \ - docker login -u "$DOCKER_USERNAME" --password-stdin - docker build \ - -t keystoneenclaveorg/keystone:<< parameters.tag >> \ - --build-arg CHECKOUT=master \ - . \ - --platform linux/x86_64 \ - -f << parameters.dockerfile >> - docker push keystoneenclaveorg/keystone:<< parameters.tag >> - - ###################### - ## Full stack tests ## - ###################### - - build-and-test-rv64-qemu: - executor: setup-rv64gc - working_directory: /keystone - steps: - - checkout - - update-riscv-toolchain-path-64 - - run: - name: "Build rv64 and run tests" - command: | - source ./source.sh - ./fast-setup.sh - mkdir build64 - cd build64 - cmake /keystone - make -j$(nproc) - make run-tests - no_output_timeout: 120m - build-rv64-fu540: - executor: setup-rv64gc - working_directory: /keystone - steps: - - checkout - - update-riscv-toolchain-path-64 - - run: - name: "Build rv64 sifive FU540" - command: | - source ./source.sh - ./fast-setup.sh - mkdir build64-fu540 - cd build64-fu540 - cmake /keystone -DLINUX_SIFIVE=y -DSM_PLATFORM=sifive/fu540 - make -j$(nproc) - build-and-test-rv32-qemu: - executor: setup-rv32gc - working_directory: /keystone - steps: - - checkout - - update-riscv-toolchain-path-32 - - run: - name: "Build rv32 and run tests" - command: | - source ./source.sh - BITS=32 ./fast-setup.sh - mkdir build32 - cd build32 - cmake /keystone -DRISCV32=y - make -j$(nproc) - make run-tests - no_output_timeout: 120m - - ################### - ## Runtime tests ## - ################### - - # The format job essentially runs clang-format against the Eyrie codebase. To - # do so, we first query which clang-format git prefers. Then, we run git with - # this clang-format. This ensures that the tool only checks files that have - # been modified. Finally, we check the output of the tool and return an error - # if some formatting changes are necessary. - - format: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - run: apt-get install clang-format -y - - run: - name: "test" - environment: - KEYSTONE_SDK_DIR: /keystone/sdk/build - command: | - FORMAT=$(git help -a | grep clang-format | tail -n1) - FORMAT_RESULT=$(git $FORMAT) - [ "$FORMAT_RESULT" = "no modified files to format" ] || [ "$FORMAT_RESULT" = "clang-format did not modify any files" ] - no_output_timeout: 120m - default-build: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - build-runtime: - build-name: "Default build" - use-freemem: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - build-runtime: - build-name: "USE_FREEMEM" - build-dir: build_freemem - build-args: -DFREEMEM=on - use_linux_syscall_use_freemem: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - build-runtime: - build-name: "USE_LINUX_SYSCALL + USE_FREEMEM" - build-dir: build_syscall_freemem - build-args: -DLINUX_SYSCALL=on -DFREEMEM=on - use_paging: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - build-runtime: - build-name: "USE_PAGING" - build-dir: build_paging - build-args: -DFREEMEM=on -DPAGING=on - use_package_crypto: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - build-runtime: - build-name: "USE_PAGE_CRYPTO" - build-dir: build_paging_crypto - build-args: -DFREEMEM=on -DPAGING=on -DPAGE_CRYPTO=on - use_page_hash: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - build-runtime: - build-name: "USE_PAGE_HASH" - build-dir: build_paging_hash - build-args: -DFREEMEM=on -DPAGING=on -DPAGE_HASH=on - use_page_crypto_use_page_hash: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - build-runtime: - build-name: "USE_PAGE_CRYPTO + USE_PAGE_HASH" - build-dir: build_paging_crypto_hash - build-args: -DFREEMEM=on -DPAGING=on -DPAGE_CRYPTO=on -DPAGE_HASH=on - test: - executor: setup-rv64gc - steps: - - checkout - - update-riscv-toolchain-path-64 - - build-sdk - - run: - name: "test" - environment: - KEYSTONE_SDK_DIR: /keystone/sdk/build - command: | - cd runtime - git submodule sync - git submodule update --init ./test/cmocka - mkdir -p obj/test - pushd obj/test - cmake ../../test - make - ctest -VV || ( cat obj/test/Testing/Temporary/LastTest.log && false ) - popd - no_output_timeout: 120m - -# If the `master` branch is updated, we update the Docker images. As we use -# these images for testing, we have two workflows -- one for the `master` -# branch and one for the all others. -# -# For `master`: -# - Update the Docker images. -# - Once done, run the tests. - -# For all others: -# - Just run the tests. -# -# We accomplish this by filtering by branch, but CircleCI only allows filtering -# by job, so we have repetitions of `only: master` and `ignore: master` for -# `master` and non-`master` branches, respectively. Also note that the `requires` -# key can only refer to jobs in the same workflow. This is why jobs such as -# `use-freemem` need to be duplicated in both workflows. -workflows: - # For the `master` branch only. - update-dockerhub-then-build-and-test: - jobs: - - update-dockerhub-image: - name: update-dockerhub-image-rv64 - dockerfile: Dockerfile.nobuild - tag: init-rv64gc - filters: - branches: - only: master - - update-dockerhub-image: - name: update-dockerhub-image-rv32 - dockerfile: Dockerfile.32.nobuild - tag: init-rv32gc - filters: - branches: - only: master - - update-dockerhub-image: - name: update-dockerhub-image-master - dockerfile: Dockerfile - tag: master - filters: - branches: - only: master - - build-and-test-rv64-qemu: - requires: - - update-dockerhub-image-rv64 - filters: - branches: - only: master - - default-build: - requires: - - update-dockerhub-image-rv64 - filters: - branches: - only: master - - use-freemem: - requires: - - default-build - - use_linux_syscall_use_freemem: - requires: - - default-build - - use_package_crypto: - requires: - - default-build - - use_paging: - requires: - - default-build - - use_page_hash: - requires: - - default-build - - use_page_crypto_use_page_hash: - requires: - - default-build - - test: - requires: - - default-build - # For all other branches. - build-and-test: - jobs: - - build-and-test-rv64-qemu: - filters: - branches: - ignore: master - - default-build: - filters: - branches: - ignore: master - - use-freemem: - requires: - - default-build - - use_linux_syscall_use_freemem: - requires: - - default-build - - use_package_crypto: - requires: - - default-build - - use_paging: - requires: - - default-build - - use_page_hash: - requires: - - default-build - - use_page_crypto_use_page_hash: - requires: - - default-build - - test: - requires: - - default-build - check-code-quality: - jobs: - - format diff --git a/.github/workflows/build-runtime.yml b/.github/workflows/build-runtime.yml new file mode 100644 index 000000000..ef78fc04b --- /dev/null +++ b/.github/workflows/build-runtime.yml @@ -0,0 +1,84 @@ + +on: + workflow_call: + +jobs: + build-runtime: + runs-on: ubuntu-latest + strategy: + matrix: + platform: [generic, unmatched] + bits: [32, 64] + exclude: + # unmatched is not 32 bit + - platform: unmatched + bits: 32 + + steps: + # We don't need submodules here since Keystone is a monorepo! + - name: Checkout Keystone + uses: actions/checkout@v3 + with: + submodules: 'false' + + # Install build dependencies + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y uuid + + - name: Restore build directory + uses: actions/download-artifact@v4 + with: + name: keystone-${{ matrix.platform }}${{ matrix.bits }}-builddir + path: . + + - name: Decompress build directory + run: cat build.tar.xz | xz -d -T0 | tar -xf - + + - name: Build default + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} + + - name: Build USE_ENV_SETUP + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DENV_SETUP=on + + - name: Build USE_LINUX_SYSCALL + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DLINUX_SYSCALL=on + + - name: Build USE_IO_SYSCALL + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DIO_SYSCALL=on + + - name: Build USE_NET_SYSCALL + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DNET_SYSCALL=on + + - name: Build USE_ALL_SYSCALL + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DLINUX_SYSCALL=on -DIO_SYSCALL=on -DNET_SYSCALL=on + + - name: Build USE_PAGING + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DPAGING=on + + - name: Build USE_PAGE_CRYPTO + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DPAGING=on -DPAGE_CRYPTO=on + + - name: Build USE_PAGE_HASH + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DPAGING=on -DPAGE_HASH=on + + - name: Build USE_PAGE_CRYPTO_HASH + run: | + ./scripts/ci/build-runtime.sh $PWD/runtime ${{ matrix.platform }} ${{ matrix.bits }} \ + -DPAGING=on -DPAGE_CRYPTO=on -DPAGE_HASH=on diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..c121f27a0 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,165 @@ +# Run this job on pushes to master and all PRs +name: Build and Test +on: + push: + branches: + - master + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + # Define the strategy for the build job. We generally want to cover each + # platform that we support here + strategy: + matrix: + platform: [generic, unmatched] + bits: [32, 64] + exclude: + # unmatched is not 32 bit + - platform: unmatched + bits: 32 + + steps: + +########### +## Setup ## +########### + + # First, we need to get the version of Keystone we are working on. We + # will also need submodules here since we are doing full builds + - name: Checkout Keystone + uses: actions/checkout@v3 + with: + submodules: 'true' + + # Get various keys for various caches + - name: Get cache keys + id: cache-keys + run: | + # Grab some timestamps for compiler caches + echo "YMDH=$(date -u +'%Y-%m-%d-%H')" >> "$GITHUB_OUTPUT" + echo "YMD=$(date -u +'%Y-%m-%d')" >> "$GITHUB_OUTPUT" + echo "YM=$(date -u +'%Y-%m')" >> "$GITHUB_OUTPUT" + echo "Y=$(date -u +'%Y')" >> "$GITHUB_OUTPUT" + + # Install build dependencies + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y cpio rsync bc makeself + + # Restore build and download caches. We key these based on timestamps and build + # target, since these essentially "accumulate" useful information (such as source + # packages or cached compiled objects) over time. With this scheme, we'll pretty + # much always be using the max Github Action cache limit (10GB), but this is okay + # since we really only care about keeping the latest cache anyways. + - name: Restore buildroot packages + uses: actions/cache@v3 + with: + path: buildroot/dl + key: buildroot-dl-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.YMDH }} + restore-keys: | + buildroot-dl-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.YMD }} + buildroot-dl-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.YM }} + buildroot-dl-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.Y }} + buildroot-dl-${{ matrix.platform }}${{ matrix.bits }}- + + - name: Restore ccache + uses: actions/cache@v3 + with: + path: ~/.buildroot-ccache + key: ccache-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.YMDH }} + restore-keys: | + ccache-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.YMD }} + ccache-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.YM }} + ccache-${{ matrix.platform }}${{ matrix.bits }}-${{ steps.cache-keys.outputs.Y }} + ccache-${{ matrix.platform }}${{ matrix.bits }}- + +############## +## Keystone ## +############## + + # Build Keystone and upload the results log if we fail to do so + - name: Build Keystone + run: | + KEYSTONE_PLATFORM=${{ matrix.platform }} \ + KEYSTONE_BITS=${{ matrix.bits }} make -j$(nproc) + + - name: Upload build log + if: failure() + uses: actions/upload-artifact@v4 + with: + name: build-keystone-${{ matrix.platform }}${{ matrix.bits }}.log + path: build-${{ matrix.platform }}${{ matrix.bits }}/build.log + + # We need parts of the build directory for future tests + - name: Compress build directory + run: | + # Convenient vars + BASEDIR="build-${{ matrix.platform }}${{ matrix.bits }}/buildroot.build" + PERPACKAGEDIR="$BASEDIR/per-package" + + # Needed by most tests + COMPRESSDIRS="$BASEDIR/host $BASEDIR/images" + # Needed by runtime build tests + COMPRESSDIRS="$COMPRESSDIRS $PERPACKAGEDIR/keystone-examples/host/usr/share/keystone/sdk" + # Needed by end-to-end tests + COMPRESSDIRS="$COMPRESSDIRS $BASEDIR/target/root/" + + tar -cf - $COMPRESSDIRS | xz -9 -T0 > build.tar.xz + + - name: Upload build directory + uses: actions/upload-artifact@v4 + with: + name: keystone-${{ matrix.platform }}${{ matrix.bits }}-builddir + path: build.tar.xz + retention-days: 1 + +########### +## Tests ## +########### + + # Generic runtime tests, which only need to run once (on the host) + test-runtime-format: + runs-on: ubuntu-latest + steps: + # We don't need submodules here since Keystone is a monorepo! + - name: Checkout Keystone + uses: actions/checkout@v3 + with: + submodules: 'false' + + - name: Check format + run: | + sudo apt-get update && sudo apt-get install -y clang-format + FORMAT=$(git help -a | grep clang-format | tail -n1) + cd runtime ; FORMAT_RESULT=$(git $FORMAT) + [ "$FORMAT_RESULT" = "no modified files to format" ] || [ "$FORMAT_RESULT" = "clang-format did not modify any files" ] + + test-runtime-functionality: + runs-on: ubuntu-latest + steps: + - name: Checkout Keystone + uses: actions/checkout@v3 + with: + submodules: 'recursive' + + - name: Run ctest + run: | + cd runtime + mkdir -p obj/test + pushd obj/test + cmake ../../test + make + ctest -VV || ( cat obj/test/Testing/Temporary/LastTest.log && false ) + popd + + # Build tests, which are run for each supported platform + test-runtime-build: + needs: build + uses: ./.github/workflows/build-runtime.yml + + # System tests, which are run for simulatable platforms + test-system: + needs: build + uses: ./.github/workflows/test-system.yml diff --git a/.github/workflows/test-system.yml b/.github/workflows/test-system.yml new file mode 100644 index 000000000..9af0847dd --- /dev/null +++ b/.github/workflows/test-system.yml @@ -0,0 +1,67 @@ + +on: + workflow_call: + +jobs: + test-system: + runs-on: ubuntu-latest + strategy: + matrix: + platform: [generic] + bits: [32, 64] + + steps: + # We don't need submodules here since Keystone is a monorepo! + - name: Checkout Keystone + uses: actions/checkout@v3 + with: + submodules: 'false' + + - name: Restore build directory + uses: actions/download-artifact@v4 + with: + name: keystone-${{ matrix.platform }}${{ matrix.bits }}-builddir + path: . + + - name: Decompress build directory + run: cat build.tar.xz | xz -d -T0 | tar -xf - + + - name: Test Keystone system + run: | + # Fix permissions on the key + chmod 600 build-${{ matrix.platform }}${{ matrix.bits }}/buildroot.build/target/root/.ssh/id-rsa + + # Launch QEMU + export KEYSTONE_PLATFORM=${{ matrix.platform }} + export KEYSTONE_BITS=${{ matrix.bits }} + export LD_LIBRARY_PATH=build-${{ matrix.platform }}${{ matrix.bits }}/buildroot.build/host/lib + screen -L -dmS qemu bash -c "make run 2>&1 | tee run.log" + + # TODO: check for connectivity instead of sleeping + sleep 20 + + export CALL_LOGFILE=cmd.log + echo "" > $CALL_LOGFILE + + KEYSTONE_COMMAND="modprobe keystone-driver" make call + KEYSTONE_COMMAND="/usr/share/keystone/examples/tests.ke" make call + KEYSTONE_COMMAND="/usr/share/keystone/examples/attestor.ke" make call + KEYSTONE_COMMAND="poweroff" make call + + - name: Check expected + run: | + [[ -z $(diff cmd.log scripts/ci/expected.log) ]] + + - name: Upload run log + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-keystone-${{ matrix.platform }}${{ matrix.bits }}-run.log + path: run.log + + - name: Upload cmd log + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-keystone-${{ matrix.platform }}${{ matrix.bits }}-cmd.log + path: cmd.log diff --git a/Makefile b/Makefile index 71a8df1aa..38db144d8 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,11 @@ ## Configuration variables ## ############################# -export SHELL := /bin/bash +# Useful globals +export SHELL := /bin/bash +export TERM := xterm-256color +# Keystone configuration export KEYSTONE ?= $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) export KEYSTONE_BUILDROOT ?= $(KEYSTONE)/buildroot export KEYSTONE_BR2_EXT ?= $(KEYSTONE)/overlays @@ -84,7 +87,7 @@ BUILDROOT_TARGET ?= all .PHONY: buildroot buildroot: $(BUILDROOT_BUILDDIR)/.config $(BUILDROOT_OVERLAYDIR)/.done $(call log,info,Building Buildroot) - $(MAKE) $(BUILDROOT_MAKEFLAGS) $(BUILDROOT_TARGET) 2>&1 | \ + set -o pipefail ; $(MAKE) $(BUILDROOT_MAKEFLAGS) $(BUILDROOT_TARGET) 2>&1 | \ tee $(BUILDDIR)/build.log | LC_ALL=C grep -of scripts/grep.patterns # Useful configuration target. This is meant as a development helper to keep diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9b34d0a2c..6806081fd 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -16,15 +16,7 @@ include(${KEYSTONE_SDK_DIR}/cmake/macros.cmake) include(ExternalProject) find_package(Git REQUIRED) -if(RISCV32) - message(STATUS "riscv32") - set(BITS 32) -else() - message(STATUS "riscv64") - set(BITS 64) -endif() - -use_riscv_toolchain(${BITS}) +use_riscv_toolchain(${KEYSTONE_BITS}) # export include directory include_directories(AFTER ${KEYSTONE_SDK_DIR}/include) diff --git a/examples/attestation/CMakeLists.txt b/examples/attestation/CMakeLists.txt index 7da2c9f03..710c4eca0 100644 --- a/examples/attestation/CMakeLists.txt +++ b/examples/attestation/CMakeLists.txt @@ -4,12 +4,7 @@ set(host_bin attestor-runner) set(host_src host/attestor-runner.cpp host/host.cpp host/verifier.cpp) set(package_name "attestor.ke") set(package_script "./attestor-runner attestor eyrie-rt loader.bin --sm-bin fw_jump.bin") - -if(RISCV32) - set(eyrie_plugins "freemem rv32") -else() - set(eyrie_plugins "freemem") -endif() +set(eyrie_plugins "none") # eapp diff --git a/examples/hello-native/CMakeLists.txt b/examples/hello-native/CMakeLists.txt index 5c88a9709..4740488f3 100644 --- a/examples/hello-native/CMakeLists.txt +++ b/examples/hello-native/CMakeLists.txt @@ -4,12 +4,7 @@ set(host_bin hello-native-runner) set(host_src host/host_native.cpp) set(package_name "hello-native.ke") set(package_script "./hello-native-runner hello-native eyrie-rt loader.bin") - -if(RISCV32) - set(eyrie_plugins "rv32 freemem") -else() - set(eyrie_plugins "freemem") -endif() +set(eyrie_plugins "none") # eapp diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt index ff45519c0..ca6485de9 100644 --- a/examples/hello/CMakeLists.txt +++ b/examples/hello/CMakeLists.txt @@ -4,12 +4,7 @@ set(host_bin hello-runner) set(host_src host/host.cpp) set(package_name "hello.ke") set(package_script "./hello-runner hello eyrie-rt loader.bin") - -if(RISCV32) - set(eyrie_plugins "freemem io_syscall linux_syscall env_setup rv32") -else() - set(eyrie_plugins "freemem io_syscall linux_syscall env_setup") -endif() +set(eyrie_plugins "io_syscall linux_syscall env_setup") # eapp diff --git a/examples/tests/CMakeLists.txt b/examples/tests/CMakeLists.txt index 4117ffa8e..2112642aa 100644 --- a/examples/tests/CMakeLists.txt +++ b/examples/tests/CMakeLists.txt @@ -1,11 +1,6 @@ set(host_bin test-runner) set(host_src test-runner.cpp edge_wrapper.cpp) - -if(RISCV32) - set(eyrie_plugins "freemem rv32") -else() - set(eyrie_plugins "freemem") -endif() +set(eyrie_plugins "none") set(package_name "tests.ke") set(package_script "./run-test.sh") diff --git a/examples/tests/test-runner.cpp b/examples/tests/test-runner.cpp index a98385d70..2a17bbea1 100644 --- a/examples/tests/test-runner.cpp +++ b/examples/tests/test-runner.cpp @@ -134,7 +134,7 @@ main(int argc, char** argv) { asm volatile("rdcycle %0" : "=r"(cycles3)); } - unsigned long encl_ret; + uintptr_t encl_ret; if (!load_only) enclave.run(&encl_ret); if (retval_exist && encl_ret != retval) { diff --git a/mkutils/plat/generic/run.mk b/mkutils/plat/generic/run.mk index 32f15236d..6b02e6f8f 100644 --- a/mkutils/plat/generic/run.mk +++ b/mkutils/plat/generic/run.mk @@ -27,10 +27,18 @@ endif run: $(call log,info,Starting QEMU) - $(BUILDROOT_BUILDDIR)/host/bin/qemu-system-riscv64 $(QEMU_FLAGS) + $(BUILDROOT_BUILDDIR)/host/bin/qemu-system-riscv$(KEYSTONE_BITS) $(QEMU_FLAGS) + +CALL_LOGFILE ?= $(shell mktemp) +call: + $(call log,info,Calling command in QEMU) + ssh -i $(BUILDROOT_BUILDDIR)/target/root/.ssh/id-rsa \ + -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -p $(QEMU_PORT) root@localhost $(KEYSTONE_COMMAND) 2>&1 | \ + grep -v "Warning: Permanently added" | tee -a $(CALL_LOGFILE) debug-connect: $(call log,info,Connecting to QEMU) - $(BUILDROOT_BUILDDIR)/host/bin/riscv64-buildroot-linux-gnu-gdb \ + $(BUILDROOT_BUILDDIR)/host/bin/riscv$(KEYSTONE_BITS)-buildroot-linux-gnu-gdb \ -iex "set KEYSTONE=$(KEYSTONE)" \ -x $(KEYSTONE)/scripts/gdb/generic.cfg diff --git a/overlays/keystone/configs/linux32-defconfig b/overlays/keystone/configs/linux32-defconfig index 92cd94694..bd68a7fcc 100644 --- a/overlays/keystone/configs/linux32-defconfig +++ b/overlays/keystone/configs/linux32-defconfig @@ -12,9 +12,12 @@ CONFIG_USER_NS=y CONFIG_CHECKPOINT_RESTORE=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y +CONFIG_NONPORTABLE=y CONFIG_ARCH_RV32I=y CONFIG_CMODEL_MEDANY=y CONFIG_SMP=y +CONFIG_NR_CPUS=64 +CONFIG_ARCH_MMAP_RND_BITS=17 # CONFIG_GCC_PLUGINS is not set CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y @@ -81,7 +84,11 @@ CONFIG_NFS_V4_2=y CONFIG_ROOT_NFS=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_DEV_VIRTIO=y +# CONFIG_XZ_DEC_IA64 is not set CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=512 CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y +CONFIG_GDB_SCRIPTS=y +CONFIG_FRAME_WARN=2048 # CONFIG_RCU_TRACE is not set diff --git a/overlays/keystone/package/keystone-examples/keystone-examples.mk b/overlays/keystone/package/keystone-examples/keystone-examples.mk index 253f97924..c95c7460b 100644 --- a/overlays/keystone/package/keystone-examples/keystone-examples.mk +++ b/overlays/keystone/package/keystone-examples/keystone-examples.mk @@ -10,9 +10,11 @@ else include $(KEYSTONE)/mkutils/pkg-keystone.mk endif -KEYSTONE_EXAMPLES_DEPENDENCIES += host-keystone-sdk keystone-runtime +KEYSTONE_EXAMPLES_DEPENDENCIES += host-keystone-sdk keystone-runtime opensbi KEYSTONE_EXAMPLES_CONF_OPTS += -DKEYSTONE_SDK_DIR=$(HOST_DIR)/usr/share/keystone/sdk \ - -DKEYSTONE_EYRIE_RUNTIME=$(KEYSTONE_RUNTIME_BUILDDIR) + -DKEYSTONE_EYRIE_RUNTIME=$(KEYSTONE_RUNTIME_BUILDDIR) \ + -DKEYSTONE_BITS=${KEYSTONE_BITS} + KEYSTONE_EXAMPLES_MAKE_ENV += KEYSTONE_SDK_DIR=$(HOST_DIR)/usr/share/keystone/sdk KEYSTONE_EXAMPLES_MAKE_OPTS += examples diff --git a/overlays/keystone/package/keystone-sdk/keystone-sdk.mk b/overlays/keystone/package/keystone-sdk/keystone-sdk.mk index 1fd02f3e0..443db702e 100644 --- a/overlays/keystone/package/keystone-sdk/keystone-sdk.mk +++ b/overlays/keystone/package/keystone-sdk/keystone-sdk.mk @@ -10,7 +10,9 @@ else include $(KEYSTONE)/mkutils/pkg-keystone.mk endif -HOST_KEYSTONE_SDK_CONF_OPTS += -DKEYSTONE_SDK_DIR=$(HOST_DIR)/usr/share/keystone/sdk +HOST_KEYSTONE_SDK_CONF_OPTS += -DKEYSTONE_SDK_DIR=$(HOST_DIR)/usr/share/keystone/sdk \ + -DKEYSTONE_BITS=${KEYSTONE_BITS} + HOST_KEYSTONE_SDK_DEPENDENCIES += toolchain # Clean the examples too if we clean this package diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index f8816d257..f248e919b 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -25,7 +25,6 @@ add_custom_target(options_log COMMAND touch ${CMAKE_BINARY_DIR}/.options_log) # Memory management options -rt_option(FREEMEM "Use freemem allocator" OFF) rt_option(PAGING "Enable runtime paging" OFF) rt_option(PAGE_CRYPTO "Enable page confidentiality" OFF) rt_option(PAGE_HASH "Enable page integrity" OFF) diff --git a/runtime/call/linux_wrap.c b/runtime/call/linux_wrap.c index 92cd0a863..19dc912c7 100644 --- a/runtime/call/linux_wrap.c +++ b/runtime/call/linux_wrap.c @@ -192,7 +192,7 @@ uintptr_t syscall_brk(void* addr){ uintptr_t req_break = (uintptr_t)addr; uintptr_t current_break = get_program_break(); - uintptr_t ret; + uintptr_t ret = -1; int req_page_count = 0; // Return current break if null or current break diff --git a/runtime/call/syscall.c b/runtime/call/syscall.c index eed63fb2b..5a88c1e33 100644 --- a/runtime/call/syscall.c +++ b/runtime/call/syscall.c @@ -157,7 +157,7 @@ void handle_syscall(struct encl_ctx* ctx) uintptr_t arg4 = ctx->regs.a4; // We only use arg5 in these for now, keep warnings happy. -#if defined(USE_LINUX_SYSCALL) || defined(USE_IO_SYSCALL) +#if defined(USE_LINUX_SYSCALL) || defined(USE_NET_SYSCALL) uintptr_t arg5 = ctx->regs.a5; #endif /* IO_SYSCALL */ uintptr_t ret = 0; diff --git a/runtime/include/crypto/merkle.h b/runtime/include/crypto/merkle.h index d35ea2f85..464834955 100644 --- a/runtime/include/crypto/merkle.h +++ b/runtime/include/crypto/merkle.h @@ -1,6 +1,6 @@ #pragma once -#if defined(USE_FREEMEM) && defined(USE_PAGING) +#ifdef USE_PAGING #include #include diff --git a/runtime/include/mm/freemem.h b/runtime/include/mm/freemem.h index deb205e42..30fa1b868 100644 --- a/runtime/include/mm/freemem.h +++ b/runtime/include/mm/freemem.h @@ -1,5 +1,3 @@ -#ifdef USE_FREEMEM - #ifndef __FREEMEM_H__ #define __FREEMEM_H__ @@ -23,4 +21,3 @@ uintptr_t spa_get_zero(void); void spa_put(uintptr_t page); unsigned int spa_available(); #endif -#endif diff --git a/runtime/include/mm/mm.h b/runtime/include/mm/mm.h index ac2b5c42a..c326640d4 100644 --- a/runtime/include/mm/mm.h +++ b/runtime/include/mm/mm.h @@ -7,7 +7,6 @@ uintptr_t translate(uintptr_t va); pte* pte_of_va(uintptr_t va); -#ifdef USE_FREEMEM uintptr_t map_page(uintptr_t vpn, uintptr_t ppn, int flags); uintptr_t alloc_page(uintptr_t vpn, int flags); uintptr_t realloc_page(uintptr_t vpn, int flags); @@ -20,6 +19,5 @@ uintptr_t get_program_break(); void set_program_break(uintptr_t new_break); void map_with_reserved_page_table(uintptr_t base, uintptr_t size, uintptr_t ptr, pte* l2_pt, pte* l3_pt); -#endif /* USE_FREEMEM */ #endif /* _MM_H_ */ diff --git a/runtime/include/mm/paging.h b/runtime/include/mm/paging.h index e83d4580b..263de6e29 100644 --- a/runtime/include/mm/paging.h +++ b/runtime/include/mm/paging.h @@ -1,4 +1,4 @@ -#if defined(USE_FREEMEM) && defined(USE_PAGING) +#ifdef USE_PAGING #ifndef __PAGING_H__ #define __PAGING_H__ diff --git a/runtime/loader-binary/CMakeLists.txt b/runtime/loader-binary/CMakeLists.txt index 2e6ff8971..f54fec8a7 100644 --- a/runtime/loader-binary/CMakeLists.txt +++ b/runtime/loader-binary/CMakeLists.txt @@ -1,6 +1,6 @@ set(LOADER_SOURCES loader.S loader-binary.c) -set(LOADER_LINK_SCRIPT loader.lds) +set(LOADER_LINK_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/loader.lds) add_executable(loader ${LOADER_SOURCES}) target_link_libraries(loader rt_call ld_mm rt_util rt_loader) diff --git a/runtime/loader-binary/loader.lds b/runtime/loader-binary/loader.lds index 622d1692b..a353fe7de 100644 --- a/runtime/loader-binary/loader.lds +++ b/runtime/loader-binary/loader.lds @@ -3,15 +3,19 @@ OUTPUT_ARCH("riscv") ENTRY( _start ) PAGE_SIZE = 0x1000; /* TODO: figure out the page size to use here */ -STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0100; +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x1000; SECTIONS { .text : { PROVIDE( _start = . ); - *(._start); - *(*); + *(._start) + *(.text) + *(.rdata) + *(.rodata) + *(.data) + *(.bss) /* * Only text section is copied into final loader binary diff --git a/runtime/loader/CMakeLists.txt b/runtime/loader/CMakeLists.txt index 59e2c388f..72162f1a6 100644 --- a/runtime/loader/CMakeLists.txt +++ b/runtime/loader/CMakeLists.txt @@ -1,8 +1,3 @@ -set(LOADER_SOURCES elf.c elf32.c elf64.c) - -if(FREEMEM) - list(APPEND LOADER_SOURCES loader.c) -endif() - +set(LOADER_SOURCES elf.c elf32.c elf64.c loader.c) add_library(rt_loader ${LOADER_SOURCES}) diff --git a/runtime/mm/CMakeLists.txt b/runtime/mm/CMakeLists.txt index 3f9550e7a..b4ef6bcbe 100644 --- a/runtime/mm/CMakeLists.txt +++ b/runtime/mm/CMakeLists.txt @@ -1,9 +1,5 @@ -set(MM_SOURCES vm.c page_swap.c) - -if(FREEMEM) - list(APPEND MM_SOURCES mm.c freemem.c) -endif() +set(MM_SOURCES vm.c page_swap.c mm.c freemem.c) if(PAGING) list(APPEND MM_SOURCES paging.c) @@ -13,4 +9,9 @@ add_library(rt_mm ${MM_SOURCES}) set(LD_MM_SOURCES vm.c freemem_ld.c mm.c) add_library(ld_mm ${LD_MM_SOURCES}) -target_compile_options(ld_mm PUBLIC -DLOADER_BIN -DUSE_FREEMEM) +target_compile_options(ld_mm PUBLIC -DLOADER_BIN) + +# Filter out any externally defined use flags +get_target_property(LD_MM_CFLAGS ld_mm COMPILE_OPTIONS) +list(FILTER LD_MM_CFLAGS EXCLUDE REGEX "-DUSE_.*") +set_target_properties(ld_mm PROPERTIES COMPILE_OPTIONS "${LD_MM_CFLAGS}") diff --git a/runtime/mm/freemem.c b/runtime/mm/freemem.c index 9b7337f83..10f06728f 100644 --- a/runtime/mm/freemem.c +++ b/runtime/mm/freemem.c @@ -1,4 +1,3 @@ -#ifdef USE_FREEMEM #include "util/string.h" #include "mm/common.h" #include "mm/vm.h" @@ -110,4 +109,3 @@ spa_init(uintptr_t base, size_t size) spa_put(cur); } } -#endif // USE_FREEMEM diff --git a/runtime/mm/freemem_ld.c b/runtime/mm/freemem_ld.c index 5cf98a809..be0052fe4 100644 --- a/runtime/mm/freemem_ld.c +++ b/runtime/mm/freemem_ld.c @@ -1,4 +1,3 @@ -#ifdef USE_FREEMEM #include "mm/freemem.h" #include "mm/common.h" #include "mm/vm_defs.h" @@ -39,5 +38,3 @@ unsigned int spa_available() { return (freeEnd - freeBase) / RISCV_PAGE_SIZE; } - -#endif diff --git a/runtime/mm/mm.c b/runtime/mm/mm.c index cefe1bef3..280c9c1c0 100644 --- a/runtime/mm/mm.c +++ b/runtime/mm/mm.c @@ -4,8 +4,6 @@ #include "mm/freemem.h" #include "mm/paging.h" -#ifdef USE_FREEMEM - /* Page table utilities */ static pte* __walk_create(pte* root, uintptr_t addr); @@ -49,7 +47,7 @@ __walk_internal(pte* root, uintptr_t addr, int create) t = (pte*) __va(pte_ppn(t[idx]) << RISCV_PAGE_BITS); } - return &t[RISCV_GET_PT_INDEX(addr, 3)]; + return &t[RISCV_GET_PT_INDEX(addr, RISCV_PT_LEVELS)]; } /* walk the page table and return PTE @@ -319,4 +317,3 @@ map_with_reserved_page_table(uintptr_t dram_base, #endif } -#endif /* USE_FREEMEM */ diff --git a/runtime/mm/page_swap.c b/runtime/mm/page_swap.c index 307f84a6a..86504d475 100644 --- a/runtime/mm/page_swap.c +++ b/runtime/mm/page_swap.c @@ -1,6 +1,6 @@ #include "mm/page_swap.h" -#if defined(USE_FREEMEM) && defined(USE_PAGING) +#ifdef USE_PAGING #include #include diff --git a/runtime/mm/paging.c b/runtime/mm/paging.c index a5dfebc4d..e983eac28 100644 --- a/runtime/mm/paging.c +++ b/runtime/mm/paging.c @@ -1,8 +1,4 @@ -#if defined(USE_PAGING) && !defined(USE_FREEMEM) -#error "paging requires freemem" -#endif - -#if defined(USE_FREEMEM) && defined(USE_PAGING) +#ifdef USE_PAGING #include "mm/paging.h" @@ -123,7 +119,7 @@ __traverse_page_table_and_pick_internal( /* extending MSB */ if(level == 3 && (i&0x100)) - vaddr = 0xffffffffffffffffUL; + vaddr = -1; ret = __traverse_page_table_and_pick_internal( level - 1, @@ -290,4 +286,4 @@ paging_backing_region_size(void) { return paging_backing_storage_size; } -#endif //USE_FREEMEM +#endif // USE_PAGING diff --git a/runtime/mm/vm.c b/runtime/mm/vm.c index 589565163..e775ef7ce 100644 --- a/runtime/mm/vm.c +++ b/runtime/mm/vm.c @@ -43,15 +43,12 @@ uintptr_t __pa(uintptr_t va) return (va - EYRIE_LOAD_START) + load_pa_start; } -#ifdef USE_FREEMEM - /* Program break */ uintptr_t program_break; /* freemem */ uintptr_t freemem_va_start; size_t freemem_size; -#endif // USE_FREEMEM /* shared buffer */ uintptr_t shared_buffer; diff --git a/runtime/sys/boot.c b/runtime/sys/boot.c index 20b4020d3..1310e3017 100644 --- a/runtime/sys/boot.c +++ b/runtime/sys/boot.c @@ -24,8 +24,6 @@ size_t utm_size; /* defined in entry.S */ extern void* encl_trap_handler; -#ifdef USE_FREEMEM - int verify_and_load_elf_file(uintptr_t ptr, size_t file_size, bool is_eapp) { int ret = 0; // validate elf @@ -57,28 +55,21 @@ init_freemem() spa_init(freemem_va_start, freemem_size); } -#endif // USE_FREEMEM - /* initialize user stack */ void init_user_stack_and_env(ELF(Ehdr) *hdr) { void* user_sp = (void*) EYRIE_USER_STACK_START; - -#ifdef USE_FREEMEM size_t count; uintptr_t stack_end = EYRIE_USER_STACK_END; size_t stack_count = EYRIE_USER_STACK_SIZE >> RISCV_PAGE_BITS; - // allocated stack pages right below the runtime count = alloc_pages(vpn(stack_end), stack_count, PTE_R | PTE_W | PTE_D | PTE_A | PTE_U); assert(count == stack_count); -#endif // USE_FREEMEM - // setup user stack env/aux user_sp = setup_start(user_sp, hdr); @@ -111,7 +102,6 @@ eyrie_boot(uintptr_t dummy, // $a0 contains the return value from the SBI /* set trap vector */ csr_write(stvec, &encl_trap_handler); -#ifdef USE_FREEMEM freemem_va_start = __va(free_paddr); freemem_size = dram_base + dram_size - free_paddr; @@ -134,7 +124,6 @@ eyrie_boot(uintptr_t dummy, // $a0 contains the return value from the SBI #ifdef USE_PAGING init_paging(user_paddr, free_paddr); #endif /* USE_PAGING */ -#endif /* USE_FREEMEM */ /* initialize user stack */ init_user_stack_and_env((ELF(Ehdr) *) __va(user_paddr)); diff --git a/runtime/test/CMakeLists.txt b/runtime/test/CMakeLists.txt index e71420640..ac16d49b3 100644 --- a/runtime/test/CMakeLists.txt +++ b/runtime/test/CMakeLists.txt @@ -13,10 +13,10 @@ include_directories(../include) add_cmocka_test(test_string SOURCES string.c COMPILE_OPTIONS -I${CMAKE_BINARY_DIR}/cmocka/include LINK_LIBRARIES cmocka) add_cmocka_test(test_merkle SOURCES merkle.c ../crypto/sha256.c - COMPILE_OPTIONS -DUSE_PAGE_HASH -DUSE_PAGING -DUSE_FREEMEM -D__riscv_xlen=64 -I${CMAKE_BINARY_DIR}/cmocka/include -g + COMPILE_OPTIONS -DUSE_PAGE_HASH -DUSE_PAGING -D__riscv_xlen=64 -I${CMAKE_BINARY_DIR}/cmocka/include -g LINK_LIBRARIES cmocka) add_cmocka_test(test_pageswap SOURCES page_swap.c ../crypto/merkle.c ../crypto/sha256.c ../crypto/aes.c - COMPILE_OPTIONS -DUSE_PAGE_HASH -DUSE_PAGE_CRYPTO -DUSE_PAGING -DUSE_FREEMEM -D__riscv_xlen=64 -I${CMAKE_BINARY_DIR}/cmocka/include -g + COMPILE_OPTIONS -DUSE_PAGE_HASH -DUSE_PAGE_CRYPTO -DUSE_PAGING -D__riscv_xlen=64 -I${CMAKE_BINARY_DIR}/cmocka/include -g LINK_LIBRARIES cmocka) diff --git a/runtime/util/printf.c b/runtime/util/printf.c index 42fee9800..eaaf05e56 100644 --- a/runtime/util/printf.c +++ b/runtime/util/printf.c @@ -49,7 +49,9 @@ #define PRINTF_SUPPORT_FLOAT // define this to support long long types (%llu or %p) +#if __riscv_xlen == 64 #define PRINTF_SUPPORT_LONG_LONG +#endif // define this to support the ptrdiff_t type (%t) // ptrdiff_t is normally defined in as long or long long type diff --git a/scripts/ci/build-runtime.sh b/scripts/ci/build-runtime.sh new file mode 100755 index 000000000..5f88cd8ba --- /dev/null +++ b/scripts/ci/build-runtime.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -e + +# Arguments: +# 1. Runtime source directory +# 2. Platform (i.e. generic, mpfs, etc) +# 3. Bitness (i.e. 32, 64) +# 4... variable number of args with USE flags + +if [[ "$#" -lt 3 ]]; then + echo "usage: build-runtime.sh [src dir] [platform] [bits] [build args ...]" + exit 1 +fi + +# Parse arguments +KEYSTONE_RUNTIME="$1" ; shift +KEYSTONE_PLATFORM="$1" ; shift +KEYSTONE_BITS="$1" ; shift +BUILD_UUID=$(uuid) + +# Create build directory +mkdir -p "build-runtime-$BUILD_UUID" +cd "build-runtime-$BUILD_UUID" || exit 1 + +# Configure cmake +BUILDDIR="$KEYSTONE_RUNTIME/../build-$KEYSTONE_PLATFORM$KEYSTONE_BITS/buildroot.build" +export PATH="$BUILDDIR/host/bin:$PATH" + +cmake "$@" \ + -DCMAKE_C_COMPILER="$(which riscv$KEYSTONE_BITS-buildroot-linux-gnu-gcc)" \ + -DCMAKE_OBJCOPY="$(which riscv$KEYSTONE_BITS-buildroot-linux-gnu-objcopy)" \ + -DKEYSTONE_SDK_DIR="$BUILDDIR/per-package/keystone-examples/host/usr/share/keystone/sdk" \ + ../runtime + +# Build +make -j$(nproc) diff --git a/scripts/ci/expected.log b/scripts/ci/expected.log new file mode 100644 index 000000000..a4bcaf3b6 --- /dev/null +++ b/scripts/ci/expected.log @@ -0,0 +1,25 @@ + +Verifying archive integrity... MD5 checksums are OK. All good. +Uncompressing Keystone Enclave Package +testing test-stack +testing test-loop +testing test-malloc +testing test-long-nop +testing test-fibonacci +testing test-fib-bench +testing test-attestation +Attestation report SIGNATURE is valid +testing test-untrusted +Enclave said: hello world! +Enclave said: 2nd hello world! +Enclave said value: 13 +Enclave said value: 20 +testing test-data-sealing +Enclave said: Sealing key derivation successful! +Verifying archive integrity... MD5 checksums are OK. All good. +Uncompressing Keystone Enclave Package +Enclave said value: 5000 +Enclave said value: 10000 +Attestation report SIGNATURE is valid +Enclave and SM hashes match with expected. +Returned data in the report match with the nonce sent. diff --git a/scripts/gdb.sh b/scripts/gdb.sh deleted file mode 100755 index 035a3f09a..000000000 --- a/scripts/gdb.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -riscv64-unknown-elf-gdb $1 diff --git a/scripts/gdb/pmp.py b/scripts/gdb/pmp.py index 68673c23f..d41681f44 100644 --- a/scripts/gdb/pmp.py +++ b/scripts/gdb/pmp.py @@ -1,11 +1,19 @@ import gdb NUM_PMP_REGISTERS = 16 -NUM_PMP_CONFIGS = int(NUM_PMP_REGISTERS / 8) + +def cfg_regs(bits): + if bits == 32: + return [f'pmpcfg{i}' for i in range(0, int(NUM_PMP_REGISTERS / 4))] + elif bits == 64: + return [f'pmpcfg{2 * i}' for i in range(0, int(NUM_PMP_REGISTERS / 8))] + else: + return None class PMPClear(gdb.Command): - def __init__(self): + def __init__(self, bits): super(PMPClear, self).__init__("pmp-clear", gdb.COMMAND_NONE) + self.cfg_regs = cfg_regs(bits) def invoke(self, arg, from_tty): # Clear addresses @@ -13,12 +21,20 @@ def invoke(self, arg, from_tty): gdb.execute(f'set $pmpaddr{i} = 0') # Clear configuratoins - for i in range(0, int(NUM_PMP_CONFIGS)): - gdb.execute(f'set $pmpcfg{2 * i} = 0') + for reg in self.cfg_regs: + gdb.execute(f'set ${reg} = 0') class PMPDump(gdb.Command): - def __init__(self): + def __init__(self, bits): super(PMPDump, self).__init__("pmp-dump", gdb.COMMAND_NONE) + self.bits = bits + self.cfg_regs = cfg_regs(bits) + if bits == 32: + self.pmp_per_group = 4 + elif bits == 64: + self.pmp_per_group = 8 + else: + self.pmp_per_group = None def invoke(self, arg, from_tty): f = gdb.selected_frame() @@ -27,11 +43,11 @@ def invoke(self, arg, from_tty): prev_addr = None # Parse configurations first - for i in range(0, int(NUM_PMP_CONFIGS)): - cfg_val = f.read_register(f'pmpcfg{2 * i}') + for i, reg in enumerate(self.cfg_regs): + cfg_val = f.read_register(f'{reg}') # Now parse addresses - for j in range(8): + for j in range(self.pmp_per_group): reg_cfg = (cfg_val >> (8 * j)) & 0xFF r = (reg_cfg & 0b00000001) != 0 w = (reg_cfg & 0b00000010) != 0 @@ -39,7 +55,7 @@ def invoke(self, arg, from_tty): a = (reg_cfg & 0b00011000) >> 3 l = (reg_cfg & 0b10000000) != 0 - reg_addr = f.read_register(f'pmpaddr{8 * i + j}') + reg_addr = f.read_register(f'pmpaddr{self.pmp_per_group * i + j}') if a == 0: # Disabled region, continue type = "disabled" @@ -58,7 +74,7 @@ def invoke(self, arg, from_tty): elif a == 3: # NAPOT region. First, find the leftmost 1 type = "NAPOT" - for k in range(64): + for k in range(self.bits): if (reg_addr >> k) & 0b1 == 0: break @@ -69,11 +85,20 @@ def invoke(self, arg, from_tty): print('error: unknown type!') continue - print(f'PMP reg {8 * i + j} {type}') + print(f'PMP reg {self.pmp_per_group * i + j} {type}') print(f'\tcfg\t{hex(reg_cfg)} {"R" if r else ""}{"W" if w else ""}{"X" if x else ""}{"L" if l else ""}') print(f'\taddr\t{hex(reg_addr)} = {hex(range_bottom)} -> {hex(range_top)}') prev_addr = reg_addr -PMPClear() -PMPDump() +# Figure out whether we are in 32-bit or 64-bit mode +misa = int(gdb.selected_frame().read_register('misa')) +print(hex(misa)) +if misa & (0b11 << 30) == 1 << 30: + PMPClear(32) + PMPDump(32) +elif misa & (0b11 << 62) == 2 << 62: + PMPClear(64) + PMPDump(64) +else: + print('Unsupported MISA size') diff --git a/scripts/run-qemu.sh.in b/scripts/run-qemu.sh.in deleted file mode 100755 index 5d625d109..000000000 --- a/scripts/run-qemu.sh.in +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -export HOST_PORT=@qemu_ssh_port@; - -echo "**** Running QEMU SSH on port ${HOST_PORT} ****"; - -export SMP=1; - -while [ "$1" != "" ]; do - if [ "$1" = "-debug" ]; - then - echo "**** GDB port $((HOST_PORT + 1)) ****"; - DEBUG="-gdb tcp::$((HOST_PORT + 1)) -S -d in_asm -D debug.log"; - fi; - if [ "$1" = "-smp" ]; - then - SMP="$2"; - shift; - fi; - shift; -done; - -@qemu_system@ \ - $DEBUG \ - -m 2G \ - -nographic \ - -machine virt,rom=@bootrom_wrkdir@/bootrom.bin \ - -bios @fw_elf@ \ - -kernel @linux_image@ \ - @extra_qemu_options@ \ - -netdev user,id=net0,net=192.168.100.1/24,dhcpstart=192.168.100.128,hostfwd=tcp::${HOST_PORT}-:22 \ - -device virtio-net-device,netdev=net0 \ - -device virtio-rng-pci \ - -smp $SMP diff --git a/scripts/test-qemu.sh.in b/scripts/test-qemu.sh.in deleted file mode 100755 index 15c34529e..000000000 --- a/scripts/test-qemu.sh.in +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -SSH_VERSION_MAJOR=$(ssh -V 2>&1 | sed 's/^OpenSSH_\([0-9]*\).*$/\1/') - -SSH_OPTIONS="-i @overlay_root@/.ssh/id_rsa" -SSH_OPTIONS+=" -o StrictHostKeyChecking=no" -SSH_OPTIONS+=" -o UserKnownHostsFile=/dev/null" - -upload_to_qemu() { - # See "Potentially incompatible changes" section in - # https://www.openssh.com/txt/release-9.0 - SCP_OPTIONS= - if [ $SSH_VERSION_MAJOR -ge 9 ]; then - SCP_OPTIONS+=" -O" - fi - echo "Uploading \"$(basename $1)\" to QEMU ..." - scp ${SSH_OPTIONS} ${SCP_OPTIONS} -P @qemu_ssh_port@ $1 root@localhost:. -} - -run_in_qemu() { - echo "Running \"$1\" in QEMU ..." - ssh ${SSH_OPTIONS} -p @qemu_ssh_port@ root@localhost "$1" -} - -run_in_qemu "modprobe keystone-driver" - -run_in_qemu "/usr/share/keystone/examples/tests.ke" - -upload_to_qemu "@fw_bin@" -run_in_qemu "/usr/share/keystone/examples/attestor.ke" - -run_in_qemu "poweroff" diff --git a/scripts/travis.sh b/scripts/travis.sh deleted file mode 100755 index f7040c893..000000000 --- a/scripts/travis.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -EXPECTED_LOG_DIR=$1 - -# Launch QEMU test -screen -L -dmS qemu ./scripts/run-qemu.sh -# TODO: check for connectivity before starting, instead of sleeping -sleep 20 -./scripts/test-qemu.sh 2>&1 | grep -v "Warning: Permanently added" | tee output.log - -diff output.log $EXPECTED_LOG_DIR/test-qemu.expected.log -if [ $? -eq 0 ] -then - echo "[PASS] output.log matches with the expected output" - exit 0 -else - echo "[FAIL] output.log does not match with the expected output" - exit 1 -fi diff --git a/sdk/CMakeLists.txt b/sdk/CMakeLists.txt index d141040e2..2c4345a1d 100644 --- a/sdk/CMakeLists.txt +++ b/sdk/CMakeLists.txt @@ -6,14 +6,6 @@ include(macros.cmake) # BASIC SETUP #------------------------------------------------------------------------------- -if(RISCV32) - message(STATUS "riscv32") - set(BITS 32) -else() - message(STATUS "riscv64") - set(BITS 64) -endif() - set(prog_name keystone-sdk) set(src_dir ${CMAKE_CURRENT_LIST_DIR}) set(scripts_dir ${src_dir}/scripts) @@ -53,7 +45,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -g) endif() -use_riscv_toolchain(${BITS}) +use_riscv_toolchain(${KEYSTONE_BITS}) ################################################################################ # BUILD PROJECTS ################################################################################ diff --git a/sdk/macros.cmake b/sdk/macros.cmake index 1c7f92ed4..561f2d448 100644 --- a/sdk/macros.cmake +++ b/sdk/macros.cmake @@ -118,7 +118,7 @@ macro(add_eyrie_runtime target_name plugins) # the files are passed via ${ARGN} ExternalProject_Add(eyrie-${target_name} PREFIX ${runtime_prefix} DOWNLOAD_COMMAND rm -rf ${eyrie_src} && cp -ar ${KEYSTONE_EYRIE_RUNTIME} ${eyrie_src} - CMAKE_ARGS "${PLUGIN_FLAGS}" -DEYRIE_SRCDIR=${KEYSTONE_EYRIE_RUNTIME} -DKEYSTONE_SDK_DIR=${KEYSTONE_SDK_DIR} + CMAKE_ARGS "${PLUGIN_FLAGS}" -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS}" -DEYRIE_SRCDIR=${KEYSTONE_EYRIE_RUNTIME} -DKEYSTONE_SDK_DIR=${KEYSTONE_SDK_DIR} BUILD_IN_SOURCE TRUE BUILD_BYPRODUCTS ${eyrie_src}/eyrie-rt ${eyrie_src}/.options_log ${eyrie_src}/loader.bin INSTALL_COMMAND "")