diff --git a/.github/workflows/content-checks.yml b/.github/workflows/content-checks.yml index 949573cb31..fcb6c2fef9 100644 --- a/.github/workflows/content-checks.yml +++ b/.github/workflows/content-checks.yml @@ -59,6 +59,18 @@ jobs: name: spellcheck-output path: spellcheck-output.txt retention-days: 5 # Default is 90 days + - name: Scan for profanities + run: | + pip install better_profanity + python tools/profanity.py + cat profanity_log.txt + + - name: Export profanities + uses: actions/upload-artifact@v4 + with: + name: profanities + path: profanity_log.txt + retention-days: 5 - name: Scan for malware run: | diff --git a/.github/workflows/external-links.yml b/.github/workflows/external-links.yml deleted file mode 100644 index b0601c0f6c..0000000000 --- a/.github/workflows/external-links.yml +++ /dev/null @@ -1,39 +0,0 @@ - -name: external-links - -# Controls when the workflow will run -on: - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - check-external-links: - # The type of runner that the job will run on - runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: true - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.11.3 - - - name: Check external HTML links - continue-on-error: true - run: | - pip install linkchecker - linkchecker --no-robots --config .linkcheckerrc --check-extern https://learn.arm.com/learning-paths/laptops-and-desktops/ - linkchecker --no-robots --config .linkcheckerrc --check-extern https://learn.arm.com/learning-paths/servers-and-cloud-computing/ - linkchecker --no-robots --config .linkcheckerrc --check-extern https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ - linkchecker --no-robots --config .linkcheckerrc --check-extern https://learn.arm.com/learning-paths/embedded-and-microcontrollers/ - linkchecker --no-robots --config .linkcheckerrc --check-extern https://learn.arm.com/learning-paths/iot/ - linkchecker --no-robots --config .linkcheckerrc --check-extern https://learn.arm.com/learning-paths/automotive/ diff --git a/.github/workflows/maintenance.yml b/.github/workflows/maintenance.yml deleted file mode 100644 index 9edac85b41..0000000000 --- a/.github/workflows/maintenance.yml +++ /dev/null @@ -1,108 +0,0 @@ -# This workflow check instructions in articles - -name: Maintenance workflow - -# Controls when the action will run. -on: - # Triggers the workflow on the 1st every month. Disable for now - #schedule: - # - cron: '* * 1 * *' - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # Generate report of outdated articles - report: - # The type of runner that the job will run on - runs-on: ubuntu-latest - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Check out repo and the whole history - - name: Check out repository code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - # Report outdated files, store result as artifact and updates stats - - name: Report outdated files of more than 20 days - run: | - pip install -r tools/requirements.txt - python3 tools/maintenance.py -r 20 - - # Upload report as artifact - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: outdated - path: outdated_files.csv - - # Test content of outdated articles - test: - # The type of runner that the job will run on - runs-on: self-hosted - # Depends on report generated in previous step - needs: report - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Check out repo - - name: Check out repository code - uses: actions/checkout@v4 - - # Download list of outdated files to test - - name: Download a single artifact - uses: actions/download-artifact@v4 - with: - name: outdated - - # Run tests for install guides - - name: Test commands and output reports for intall-guides - run: | - for i in $(tree -i -f content/install-guides/ | tail -n +2 | grep ".md$"); do - python3 tools/maintenance.py -i $i -l ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - done - - # Run tests for learning paths - #- name: Test commands and output reports for learning paths - # run: | - # for i in $(tree -i -d -f content/learning-paths/ | tail -n +2); do - # python3 tools/maintenance.py -i $i -l ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - # done - - # Move reports to result folder - - name: Move reports - run: | - mkdir junit-reports - for i in $(tree -i -f | grep "_cmd.xml"); do - mv $i junit-reports/ - done - - # Upload test reports as artifact - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: results - path: junit-reports/*_cmd.xml - - # Publish Junit reports - - name: Publish Test Reports - id: junit - uses: mikepenz/action-junit-report@v3 - if: always() # always run even if the previous step fails - with: - report_paths: '**/junit-reports/*_cmd.xml' - detailed_summary: true - include_passed: true - - # Commit and push changes - - name: Commit test status - run: | - git config user.name github-actions - git config user.email github-actions@github.com - git ls-files --modified | xargs git add - git pull - if git commit -m "Add test status"; then - git push - fi diff --git a/.github/workflows/profanity.yml b/.github/workflows/profanity.yml deleted file mode 100644 index 025b508c77..0000000000 --- a/.github/workflows/profanity.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: profanity - -# Controls when the workflow will run -on: - - workflow_dispatch: - - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - profanity_scan: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: true # Fetch Hugo Themes - fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.11.3 - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install better_profanity - - name: Scan for profanities - run: | - python tools/profanity.py - cat profanity_log.txt - - - name: Export profanities - uses: actions/upload-artifact@v4 - with: - name: profanities - path: profanity_log.txt - retention-days: 5 diff --git a/.github/workflows/test-lp.yml b/.github/workflows/test-lp.yml index fd187b6ef5..4ed6b1d352 100644 --- a/.github/workflows/test-lp.yml +++ b/.github/workflows/test-lp.yml @@ -2,7 +2,7 @@ name: Test Learning Path on: pull_request env: HUGO_VERSION: 0.130.0 - + jobs: Test-Pull-Request: runs-on: ubuntu-24.04-arm @@ -58,6 +58,11 @@ jobs: - name: Install dependencies if: steps.changed-markdown-files.outputs.any_changed == 'true' run: pip install -r tools/requirements.txt + - name: Validate _index.md files + if: steps.changed-markdown-files.outputs.any_changed == 'true' + run: | + echo "Checking YAML fields for changed learning paths..." + python3 tools/verify_index_fields.py ${{ steps.changed-markdown-files.outputs.all_changed_files }} - name: Run test suite for all changed .md files id: run-suite if: steps.changed-markdown-files.outputs.any_changed == 'true' diff --git a/.gitignore b/.gitignore index c92386632d..0022932a69 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ package-lock.json .vscode .env startup.sh +data/ # macOS files *.DS_Store @@ -22,4 +23,4 @@ z_local_saved/ *.xml # CTags symbol index -tags +tags \ No newline at end of file diff --git a/.profanity_ignore.yml b/.profanity_ignore.yml index 8cde2313b4..cd7840829d 100644 --- a/.profanity_ignore.yml +++ b/.profanity_ignore.yml @@ -2,11 +2,25 @@ XX -kill kill KVM -#IO_L3N_T0_DQS_AD1N_35 -172.X.X.X +kvm +X.X.X +.xx. +.xxx. naked +facial +Facial +screw +len +LEN +test +TEST +Test +--strip- (x=x **VM Kill slave Slave +A55 +a55 +455 \ No newline at end of file diff --git a/assets/contributors.csv b/assets/contributors.csv index b31d993957..e65a28cb1c 100644 --- a/assets/contributors.csv +++ b/assets/contributors.csv @@ -95,4 +95,9 @@ Chenying Kuo,Adlink,evshary,evshary,, William Liang,,,wyliang,, Waheed Brown,Arm,https://github.com/armwaheed,https://www.linkedin.com/in/waheedbrown/,, Aryan Bhusari,Arm,,https://www.linkedin.com/in/aryanbhusari,, +Ken Zhang,Insyde,,kai-di-zhang-b1642a266,, +Ann Cheng,Arm,anncheng-arm,hello-ann,, Fidel Makatia Omusilibwa,,,,, +Ker Liu,,,,, +Rui Chang,,,,, + diff --git a/content/learning-paths/cross-platform/zenoh-multinode-ros2/_index.md b/content/learning-paths/cross-platform/zenoh-multinode-ros2/_index.md index 39f75a71da..f51f506190 100644 --- a/content/learning-paths/cross-platform/zenoh-multinode-ros2/_index.md +++ b/content/learning-paths/cross-platform/zenoh-multinode-ros2/_index.md @@ -51,7 +51,7 @@ further_reading: type: documentation - resource: title: Zenoh and ROS 2 Integration Guide - link: https://github.com/eclipse-zenoh/zenoh-plugin-ros2 + link: https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds type: documentation diff --git a/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/1-prerequisites.md b/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/1-prerequisites.md index fa250a8adf..470f7d0cfa 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/1-prerequisites.md +++ b/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/1-prerequisites.md @@ -13,7 +13,7 @@ This Learning Path demonstrates how to improve the performance of camera pipelin ## Install required software Make sure the following tools are installed: -- `git` - a version control system, for cloning the Voice Assistant codebase. +- `git` - a version control system, for cloning the AI camera pipelines codebase. - `git lfs` - an extension to `git` for managing large files by storing lightweight references instead of the files themselves. - `docker` - an open-source containerization platform for running applications in isolated environments. - `libomp` - LLVM's OpenMP runtime library, required for enabling parallel execution during application performance optimization. @@ -52,7 +52,7 @@ Once you have confirmed that Docker is installed on your machine, you can check docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world -c9c5fd25a1bd: Pull complete +c9c5fd25a1bd: Pull complete Digest: sha256:c41088499908a59aae84b0a49c70e86f4731e588a737f1637e73c8c09d995654 Status: Downloaded newer image for hello-world:latest diff --git a/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/3-build.md b/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/3-build.md index 04c311aaa9..6257f4cba2 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/3-build.md +++ b/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/3-build.md @@ -73,10 +73,14 @@ Leave the container by pressing `Ctrl+D`. ## Notes on the cmake configuration options -- `-DENABLE_SME2=$ENABLE_SME2` with `ENABLE_SME2=0`: SME2 (Scalable Matrix Extension 2) is disabled in this build (`0`). -- `-DARMNN_TFLITE_PARSER=0`: Configures the `ai-camera-pipelines` repository to use LiteRT with XNNPack instead of ArmNN. -- `-DENABLE_KLEIDICV:BOOL=ON`: Enables KleidiCV for optimized image processing. -- `-DXNNPACK_ENABLE_KLEIDIAI:BOOL=ON`: Enables KleidiAI acceleration for LiteRT workloads via XNNPack. +The `cmake` command line options relevant to this learning path are: + +| Command line option | Description | +|-------------------------------------|----------------------------------------------------------------------------------------------| +| `ENABLE_SME2=$ENABLE_SME2` | SME2 (Scalable Matrix Extension 2) is disabled in this build with `ENABLE_SME2=0`. | +| `ARMNN_TFLITE_PARSER=0` | Configures the `ai-camera-pipelines` repository to use LiteRT with XNNPack instead of ArmNN. | +| `ENABLE_KLEIDICV:BOOL=ON` | Enables KleidiCV for optimized image processing. | +| `XNNPACK_ENABLE_KLEIDIAI:BOOL=ON` | Enables KleidiAI acceleration for LiteRT workloads via XNNPack. | ## Install the pipelines @@ -84,4 +88,11 @@ Leave the container by pressing `Ctrl+D`. cd $HOME tar xfz ai-camera-pipelines.git/install.tar.gz mv install ai-camera-pipelines -``` \ No newline at end of file +``` + +## Diving further in the AI camera pipelines + +The AI camera pipelines +[repository](https://git.gitlab.arm.com/kleidi/kleidi-examples/ai-camera-pipelines) +contains more information in its README file should you wish to dive deeper into +it. \ No newline at end of file diff --git a/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/4-run.md b/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/4-run.md index 1b0745258f..828852f459 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/4-run.md +++ b/content/learning-paths/mobile-graphics-and-gaming/ai-camera-pipelines/4-run.md @@ -30,4 +30,5 @@ cd $HOME/ai-camera-pipelines bin/low_light_image_enhancement resources/test_input2.ppm test_output2_lime.ppm resources/HDRNetLIME_lr_coeffs_v1_1_0_mixed_low_light_perceptual_l2_loss_int8_only_ptq.tflite ``` +![example image alt-text#center](test_input2.png "Original picture") ![example image alt-text#center](test_output2_lime.png "Picture with low-light enhancement applied") \ No newline at end of file diff --git a/content/learning-paths/mobile-graphics-and-gaming/build-android-chat-app-using-onnxruntime/1-dev-env-setup.md b/content/learning-paths/mobile-graphics-and-gaming/build-android-chat-app-using-onnxruntime/1-dev-env-setup.md index cda690b6d0..32cde2851b 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/build-android-chat-app-using-onnxruntime/1-dev-env-setup.md +++ b/content/learning-paths/mobile-graphics-and-gaming/build-android-chat-app-using-onnxruntime/1-dev-env-setup.md @@ -34,7 +34,7 @@ Follow these steps to install and configure Android Studio: 5. Click **OK** and **Apply**. -## Install Python 3.15 +## Install Python 3.13 Download and install [Python version 3.13](https://www.python.org/downloads/release/python-3135/) diff --git a/content/learning-paths/servers-and-cloud-computing/cca-trustee/_index.md b/content/learning-paths/servers-and-cloud-computing/cca-trustee/_index.md new file mode 100644 index 0000000000..d0afe5fdc3 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/cca-trustee/_index.md @@ -0,0 +1,66 @@ +--- +title: Run an end-to-end Attestation Flow with Arm CCA and Trustee + +draft: true +cascade: + draft: true + +minutes_to_complete: 60 + +who_is_this_for: This Learning Path is for software developers who want to learn how Trustee services can be used to run an end-to-end attestation flow with Arm's Confidential Computing Architecture (CCA). + +learning_objectives: + - Describe how you can use attestation with Arm's Confidential Computing Architecture (CCA) and Trustee services. + - Deploy a simple workload in a CCA realm on an Armv9-A AEM Base Fixed Virtual Platform (FVP) that has support for RME extensions. + - Connect the workload with Trustee services to create an end-to-end example that uses attestation to unlock the confidential processing of data. + +prerequisites: + - An AArch64 or x86_64 computer running Linux or MacOS. You can use cloud instances, see this list of [Arm cloud service providers](/learning-paths/servers-and-cloud-computing/csp/). + - Completion of the [Get Started with CCA Attestation and Veraison](/learning-paths/servers-and-cloud-computing/cca-veraison) Learning Path. + - Completion of the [Run an end-to-end Attestation Flow with Arm CCA](/learning-paths/servers-and-cloud-computing/cca-essentials/) Learning Path. + +author: + - Anton Antonov + +### Tags +skilllevels: Advanced +subjects: Performance and Architecture +armips: + - Neoverse + - Cortex-A +operatingsystems: + - Linux + - MacOS +tools_software_languages: + - FVP + - RME + - CCA + - Docker + - Veraison + - Trustee + +further_reading: + - resource: + title: Arm Confidential Compute Architecture + link: https://www.arm.com/architecture/security-features/arm-confidential-compute-architecture + type: website + - resource: + title: Arm Confidential Compute Architecture open source enablement + link: https://www.youtube.com/watch?v=JXrNkYysuXw + type: video + - resource: + title: Learn the architecture - Realm Management Extension + link: https://developer.arm.com/documentation/den0126 + type: documentation + - resource: + title: Realm Management Monitor specification + link: https://developer.arm.com/documentation/den0137/latest/ + type: documentation + + +### FIXED, DO NOT MODIFY +# ================================================================================ +weight: 1 # _index.md always has weight of 1 to order correctly +layout: "learningpathall" # All files under learning paths have this same wrapper +learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/cca-trustee/_next-steps.md b/content/learning-paths/servers-and-cloud-computing/cca-trustee/_next-steps.md new file mode 100644 index 0000000000..c3db0de5a2 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/cca-trustee/_next-steps.md @@ -0,0 +1,8 @@ +--- +# ================================================================================ +# FIXED, DO NOT MODIFY THIS FILE +# ================================================================================ +weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. +title: "Next Steps" # Always the same, html page title. +layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/cca-trustee/attestation-services.png b/content/learning-paths/servers-and-cloud-computing/cca-trustee/attestation-services.png new file mode 100644 index 0000000000..3f21cd8f8c Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/cca-trustee/attestation-services.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/cca-trustee/cca-trustee.md b/content/learning-paths/servers-and-cloud-computing/cca-trustee/cca-trustee.md new file mode 100644 index 0000000000..428f0677d0 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/cca-trustee/cca-trustee.md @@ -0,0 +1,152 @@ +--- +# User change +title: "Overview of the Software Architecture" + +weight: 2 # 1 is first, 2 is second, etc. + +# Do not modify these elements +layout: "learningpathall" +--- + +## The role of Attestation +In this Learning Path, you will learn how attestation can control the release +of confidential data into a confidential Linux realm for processing. + +The role of attestation is to assess whether the target compute environment +offers a provable level of confidential isolation. In this Learning Path, +the target compute environment is a Linux realm. The assessment of a provable +level of confidential isolation needs to occur before the realm can be trusted +to receive confidential data or algorithms. This use of attestation to judge +the trustworthiness of a compute environment, before allowing it to do any +processing, is a common practice in confidential computing. + +## Understanding the key software components + +This Learning Path is similar to +[Run an end-to-end Attestation Flow with Arm CCA](/learning-paths/servers-and-cloud-computing/cca-essentials/). + +The main difference is that instead of KBS from the [Veraison](https://github.com/veraison) project you will use +the components implemented in the [confidential containers (CoCo)](https://github.com/confidential-containers) +to support the [IETF RATS model](https://datatracker.ietf.org/doc/rfc9334/) +(Remote ATtestation procedureS Architecture). The components include the Attestation Service (AS), +Key Broker Service (KBS), Reference Value Provider Service (RVPS), Attestation Agent (AA), and Confidential Data Hub (CDH). +The AS, KBS, and RVPS components are part of the [Trustee project](https://github.com/confidential-containers/trustee), +whereas the AA and CDH are part of the [Guest Components](https://github.com/confidential-containers/guest-components) project in CoCo. + +### RATS key components + +This is a list of components used in this Learning Path: + +- `Attester` - provides Evidence, which is evaluated and appraised to decide its + trustworthiness (for instance, a test to see whether it’s authorized to perform some action). + Evidence may include configuration data, measurements, telemetry, or inferences. +- `Verifier` - evaluates the validity of the evidence received from the attester + and produces attestation results, which are sent to the Relying party. + Attestation results typically include information regarding the Attester, + while the Verifier vouches for the validity of the results. +- `Relying party` - depends on the validity of information originating from + the attester for reliably applying an action. This information can come + from the verifier or directly through the attester. + +### Trustee components + +The Trustee project includes components deployed on a trusted side and used to verify +whether the remote workload is running in a trusted execution environment (TEE). +It also verifies that the remote environment uses the expected software and hardware versions. + +#### Key Broker Service (KBS) + +The Key Broker Service (KBS) facilitates remote attestation and managing +and delivering secrets. Equating this to the RATS model, the KBS is the +`relying party` entity. The KBS, however, doesn’t validate the attestation evidence. +Instead, it uses the attestation service (AS) to verify the TEE evidence. + +#### Attestation Service (AS) + +The Attestation Service (AS) is responsible for validating the TEE evidence. +When mapped to the RATS model, the AS is the equivalent of the `verifier`. +The AS receives attestation evidence and returns an attestation token +containing the results of a two-step verification process. + +The following diagram shows the AS components: + +![attestation-services](attestation-services.png "Attestation Service components") + +The AS runs the following verification process: + +1. Verify the formatting and the origin of the evidence - for example, checking the signature of the evidence. + This is accomplished by one of the platform-specific Verifier Drivers. +2. Evaluate the claims provided in the evidence - for example, validating that the measurements are what the + client expects. This is done by a Policy Engine with help from the RVPS. + +##### Verifier driver + +A verifier driver parses the attestation evidence provided by the hardware TEE. It performs the following tasks: + +1. Verifies the hardware TEE signature of the TEE quote and report provided in the evidence +2. Receives the evidence and organizes the status into a JSON format to be returned + +In this Learning Path, the AS is configured to use an external CCA verifer. + +[Linaro](https://www.linaro.org) provides such an attestation verifier for use with pre-silicon Arm CCA platforms. +This verifier is built from the Open-Source [Veraison project](https://github.com/veraison). +You can learn more about Veraison and Linaro attestation verifier service in +[Get Started with CCA Attestation and Veraison](https://learn.arm.com/learning-paths/servers-and-cloud-computing/cca-veraison/) + +##### Policy Engine + +The AS allows users to upload their own policies when performing evidence verification. +When an attestation request is received by the AS, it uses a policy ID in the request +to decide which policies should be evaluated. +The results of all policies evaluated are included in the attestation response. + +In this Learning Path the AS attestation policy includes specific Arm CCA rules. + +#### Reference Value Provider Service (RVPS) + +The reference value provider service (RVPS) is a component in the AS responsible for verifying, +storing, and providing reference values. RVPS receives and verifies inputs from the software +supply chain, stores the measurement values, and generates reference value claims for the AS. +This operation is performed based on the evidence verified by the AS. + + +### Guest components + +The guest components are the services/tools that run inside the realm (TEE). +When mapped to the RATS model, these components are the equivalent of the `Attester`. + +For simplicity instead of Attestation Agent (AA) and Confidential Data Hub (CDH) +you will use [KBS Client Tool](https://github.com/confidential-containers/trustee/tree/main/tools/kbs-client) + +This is a simple client for the KBS that facilitates basic attestation flows. +You will run this tool inside of a realm to make requests for an attestation result token (EAR) and a secret. + +The client tool can also be used to provision the KBS/AS with resources and policies. + +KBS Client connects to the KBS in order to perform attestation. To prove the trustworthiness of the environment +KBS Client sends the evidence (claims) from the TEE in the form of a CCA attestation token. +You can learn more about CCA attestation tokens in +[Get Started with CCA Attestation and Veraison](https://learn.arm.com/learning-paths/servers-and-cloud-computing/cca-veraison/) + +For convenience, Trustee services and the client software are packaged in +docker containers, which you can execute on any suitable AArch64 or x86_64 +development machine. Since the client software runs in a realm, it makes use +of the Fixed Virtual Platform (FVP) and the reference software stack for Arm CCA. +If you have not yet familiarized yourself with running applications in realms using +FVP and the reference software stack, see the +[Run an application in a Realm using the Arm Confidential Computing Architecture (CCA)](/learning-paths/servers-and-cloud-computing/cca-container) +Learning Path. + +When the AS receives an attestation token from the realm via KBS: +- it calls an external CCA verifer (the Linaro attestation verifier service) to obtain an attestation result. +- the external CCA verifer checks the token's cryptographic signature, + verifies that it denotes a confidential computing platform and provides an attestation result. +- it also checks the token evidences against its own attestation policies and updates attestation result status and trustworthiness vectors. + +When asked for a resource the KBS uses the attestation result to decide whether to release the secrets into the realm for processing. + +Figure 1 demonstrates the software architecture that you will construct to run the attestation example. + +![cca-trustee](trustee.png "Figure 1: Software architecture for running attestation.") + +You can now proceed to the next section to run the end-to-end attestation example with the software components and architecture as described here. diff --git a/content/learning-paths/servers-and-cloud-computing/cca-trustee/flow.md b/content/learning-paths/servers-and-cloud-computing/cca-trustee/flow.md new file mode 100644 index 0000000000..49f06e54db --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/cca-trustee/flow.md @@ -0,0 +1,316 @@ +--- +# User change +title: "Run an end-to-end Attestation with Arm CCA and Trustee" + +weight: 3 # 1 is first, 2 is second, etc. + +# Do not modify these elements +layout: "learningpathall" +--- + +### Run Trustee Services + +#### Prerequisites + +Install docker. For example, on your Ubuntu 24.04 LTS host machine, first set up Docker's apt repository: +``` bash +# Add Docker's official GPG key: +sudo apt-get update +sudo apt-get install ca-certificates curl +sudo install -m 0755 -d /etc/apt/keyrings +sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc +sudo chmod a+r /etc/apt/keyrings/docker.asc + +# Add the repository to Apt sources: +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt-get update +``` + +Install git and docker packages: +``` bash +sudo apt-get install git docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +``` + +Add your user name to the docker group: +``` bash +sudo usermod -aG docker $USER +newgrp docker +``` + +#### Start Trustee Services docker containers + +Clone the `cca-trustee` repository: +``` bash +git clone https://github.com/ArmDeveloperEcosystem/cca-trustee.git +``` + +This repository contains configuration files used for running Trustee services docker containers with CCA attestation support as a simple cluster. +The config files are based on the recommended configurations from [KBS Cluster](https://github.com/confidential-containers/trustee/blob/main/kbs/docs/cluster.md) + +In addition to the recommended configuration, the following changes were also made for this Learning Path: +- Included the external Linaro CCA verifier into AS configuration +- Included an attestation policy with CCA rules +- Defined an "affirming" resource policy +- Created a secret demo message. +- Defined a docker network shared by all containers in this demo. + +Go into the `cca-trustee` directory and start the Trustee services docker containers (as detached services): +``` bash { output_lines = "3-9" } +cd cca-trustee +docker compose up -d +[+] Running 6/6 + ✔ Network cca-trustee Created + ✔ Container cca-trustee-setup-1 Exited + ✔ Container cca-trustee-rvps-1 Started + ✔ Container cca-trustee-as-1 Started + ✔ Container cca-trustee-kbs-1 Started + ✔ Container cca-trustee-kbs-client-1 Started +``` + +While running the demo you can also check logs of the Trustee services in this termimal: +``` bash +docker compose logs +``` +Where `service` is either `as`,`kbs` or `rvps`. + +### Launch a CCA Realm with FVP + +With the Trustee Services running in one terminal, +open up a new terminal in which you will run CCA attestations. + +Pull the docker image with the pre-built FVP, +and then run the container connected to the same docker network: + +```bash +docker pull armswdev/cca-learning-path:cca-simulation-v2 +``` +```bash +docker run --rm -it --network cca-trustee armswdev/cca-learning-path:cca-simulation-v2 +``` + +Within your running container, +launch the `run-cca-fvp.sh` script to run the Arm CCA pre-built binaries on the FVP: + +```bash +./run-cca-fvp.sh +``` + +The `run-cca-fvp.sh` script uses the screen command to connect to the different UARTs in the FVP. + +You should see the host Linux kernel boot on your terminal. You will be prompted to log in to the host. + +Enter root as the username: +```output + +Welcome to the CCA host +host login: root +(host) # +``` + +Change directory to `/cca` and use `lkvm` to launch a guest Linux in a Realm: +```bash +cd /cca +./lkvm run --realm --disable-sve --irqchip=gicv3-its \ + --firmware KVMTOOL_EFI.fd -c 1 -m 512 --no-pvtime --pmu \ + --disk guest-disk.img --restricted_mem --virtio-transport pci +``` + +You should see the realm boot. + +The `realm` will take some time to boot, please be patient. +After boot up, you will be prompted to log in at the guest Linux prompt. + +Use root again as the username: + +```output + +Welcome to the CCA realm +realm login: root +(realm) # +``` + +### Try to use attestation to request a secret + +In this step, you will go through the process of using attestation to request +a secret from the KBS. This will not work on the first attempt. +But don't worry. You will learn why that is the case, and how to rectify the problem. +You will have a better understanding of the attestation process as a result. + +Change directory to `/cca` and use `openssl` to create a realm RSA key: +```bash +cd /cca +openssl genrsa -traditional -out realm.key +``` + +Run the attestation command and save the EAT Attestation Result (EAR) message in JWT (JSON Web Token) format in a file named `ear.jwt`: +```bash +./kbs-client --url http://kbs:8080 attest --tee-key-file realm.key >ear.jwt +``` + +Now try to request a secret demo message using the attestation result: +```bash +./kbs-client --url http://kbs:8080 get-resource \ + --tee-key-file realm.key --attestation-token ear.jwt \ + --path "cca-trustee/demo-message/message.txt" +``` + +The request will fail with `Access denied by policy` and `Token Verifier` errors: +```output +[2025-07-23T14:42:55Z WARN kbs_protocol::client::token_client] Authenticating with KBS failed. Get a new token from the token provider: ErrorInformation { + error_type: "https://github.com/confidential-containers/kbs/errors/PolicyDeny", + detail: "Access denied by policy", + } +[2025-07-23T14:42:55Z WARN kbs_protocol::client::token_client] Authenticating with KBS failed. Get a new token from the token provider: ErrorInformation { + error_type: "https://github.com/confidential-containers/kbs/errors/TokenVerifierError", + detail: "Token Verifier error", + } +[2025-07-23T14:42:55Z WARN kbs_protocol::client::token_client] Authenticating with KBS failed. Get a new token from the token provider: ErrorInformation { + error_type: "https://github.com/confidential-containers/kbs/errors/TokenVerifierError", + detail: "Token Verifier error", + } +Error: request unauthorized +``` + +Proceed to the next step to understand why the KBS did not grant access +to the requested secret, and how to resolve the problem. + +#### Evaluate the Attestation Result + +In the previous step, the KBS failed to provide the requested secret. +To understand why this happened, you need to learn more about how +the attestation result is used to evaluate the trustworthiness of a CCA realm. +In this step, you will examine the attestation result more closely. + +The following command will use the `arc` tool to verify the cryptographic signature on the attestation result and display the result in a human-readable format: + +```bash +./arc verify ear.jwt +``` + +{{% notice EAR expiry note %}} +The EAR message produced by Trustee AS in this Learning Path demo is valid for 30 minutes. +If you spend more time on analyzing the message you will start seeing errors from `arc verify` command: + +``` output +Using JWK key from JWT header +Error: verifying signed EAR from "ear.jwt" using "JWK header" key: failed verifying JWT message: jwt.Parse: failed to parse token: jwt.Validate: validation failed: "exp" not satisfied: token is expired +``` + +Please obtain a new EAR message by re-runing the attestation command. +{{% /notice %}} + + +The `arc verify` command produces quite a lot of output. +However, the main part is the CCA attestation token that is similar to the one you inspected in +[Get Started with CCA Attestation and Veraison](/learning-paths/servers-and-cloud-computing/cca-veraison) Learning Path. + +The most interesting part of the output is towards the bottom, and should look like this: + +```output +[trustworthiness vectors] +submod(cpu0): +Instance Identity [none]: no claim being made +Configuration [none]: no claim being made +Executables [warning]: unrecognized run-time +File System [none]: no claim being made +Hardware [affirming]: genuine +Runtime Opaque [none]: no claim being made +Storage Opaque [none]: no claim being made +Sourced Data [none]: no claim being made +``` + +This part of the output shows how the attestation service has compared the attestation token against its expectations of a trustworthy system. +These comparisons are known as "trustworthiness vectors". +It also shows the conclusions that were drawn from that comparison. + +Please notice these two trustworthiness vectors in the result: +- __Hardware [affirming]__. Evidence in the attestation token shows a good match against the expectations of CCA platform. +- __Executables [warning]__. Attestation token does not show a good match against the expectations of a recognized genuine set of approved executables have been loaded during the boot process. + +You can also check the status of the EAR: +```bash { output_lines = "2" } +./arc verify ear.jwt |grep ear.status + "ear.status": "warning", +``` + +The warning status is the reason why the KBS chose not to grant access +to the secret that you requested in the earlier step. +It has not concluded that the realm is trustworthy. +But this is simply because you have not supplied an expected reference measurement +for the realm. You will do this in the next step. + +### Endorse Realm Initial Measurement (RIM) + +For a successful attestation of your CCA real you need to provide +the Trustee Reference Values Provider Service (RVPS) with a known good reference value. + +In a production environment, the known good reference value is generated using a deployment-specific process, +but for demonstration purposes and simplification, you will use the value which was calculated by `kbs-client` +in the realm and included into the EAT. + +Get the RIM from the attestation token: +```bash { output_lines = "2" } +./arc verify ear.jwt |grep "cca-realm-initial-measurement" + "cca-realm-initial-measurement": "Nfpl4Y32d2hCpeYsarnnGv9xcbTMTBX90x0ZjnAMjLk=", +``` + +In the terminal where you started Trustee services, run `endorse-rim.sh` script with the RIM you copied from EAT as a parameter: + +```bash { output_lines = "2-9" } +./endorse-rim.sh "Nfpl4Y32d2hCpeYsarnnGv9xcbTMTBX90x0ZjnAMjLk=" +[+] Creating 4/4 + ✔ Container cca-trustee-setup-1 Created + ✔ Container cca-trustee-rvps-1 Running + ✔ Container cca-trustee-as-1 Running + ✔ Container cca-trustee-kbs-1 Running +[+] Running 1/1 + ✔ Container cca-trustee-setup-1 Exited +Reference Values Updated +``` + +### Re-run attestation and request a secret + +In the realm terminal re-run the attestation command: +```bash +./kbs-client --url http://kbs:8080 attest --tee-key-file realm.key >ear.jwt +``` + +Verify that the new EAR now contains `affirming` status: + +```bash { output_lines = "2" } +./arc verify ear.jwt |grep "ear.status" + "ear.status": "affirming", +``` + +and `affirming` result for the `Executables` trustworthness vector: +```bash { output_lines = "2-11" } +./arc verify ear.jwt |grep -A10 "trustworthiness vectors" +[trustworthiness vectors] +submod(cpu0): +Instance Identity [none]: no claim being made +Configuration [none]: no claim being made +Executables [affirming]: recognized and approved boot-time +File System [none]: no claim being made +Hardware [affirming]: genuine +Runtime Opaque [none]: no claim being made +Storage Opaque [none]: no claim being made +Sourced Data [none]: no claim being made +``` + +Request a secret demo message using the new attestation result: +```bash { output_lines = "4" } +./kbs-client --url http://kbs:8080 get-resource \ + --tee-key-file realm.key --attestation-token ear.jwt \ + --path "cca-trustee/demo-message/message.txt" |base64 -d +This is a CCA demo message obtained by using a valid EAR token +``` + +You have successfully run an end-to-end attestation flow with Arm CCA and obtained a secret. + +You can stop all Trustee containers with: +```bash +docker compose down +``` diff --git a/content/learning-paths/servers-and-cloud-computing/cca-trustee/trustee.png b/content/learning-paths/servers-and-cloud-computing/cca-trustee/trustee.png new file mode 100644 index 0000000000..3f8d9dae13 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/cca-trustee/trustee.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/_index.md b/content/learning-paths/servers-and-cloud-computing/github-on-arm/_index.md new file mode 100644 index 0000000000..3c68beb5c2 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/github-on-arm/_index.md @@ -0,0 +1,66 @@ +--- +title: Deploy GitHub Actions Self-Hosted Runner on Google Axion C4A virtual machine + +draft: true +cascade: + draft: true + +minutes_to_complete: 15 + +who_is_this_for: This is an introductory topic for developers who want to deploy GitHub Actions Self-Hosted Runner on an Arm-based Google Axion C4A instance. + +learning_objectives: + - Provision an Arm virtual machine on the Google Cloud Platform using the C4A Google Axion instance family. + - Set up and validate a GitHub Actions self-hosted runner on the Arm virtual machine. + - Deploy a basic CI workflow with NGINX and verify execution on Arm infrastructure. + +prerequisites: + - A [Google Cloud Platform (GCP)](https://cloud.google.com/free?utm_source=google&hl=en) account with billing enabled. + - A GitHub account. You can sign up [here](https://github.com/signup). + +author: Annie Tallund + +##### Tags +skilllevels: Introductory +subjects: CI-CD +cloud_service_providers: Google Cloud + +armips: + - Neoverse + +tools_software_languages: + - GitHub Actions + - GitHub CLI + +operatingsystems: + - Linux + +# ================================================================================ +# FIXED, DO NOT MODIFY +# ================================================================================ +further_reading: + - resource: + title: Google Cloud official website and documentation + link: https://cloud.google.com/docs + type: documentation + + - resource: + title: Github-action official website and documentation + link: https://docs.github.com/en/actions + type: documentation + + - resource: + title: GitHub Actions Arm runners + link: https://github.blog/news-insights/product-news/arm64-on-github-actions-powering-faster-more-efficient-build-systems/ + type: website + + - resource: + title: GCP Quickstart Guide to Create a virtual machine + link: https://cloud.google.com/compute/docs/instances/create-start-instance + type: website + + +weight: 1 # _index.md always has weight of 1 to order correctly +layout: "learningpathall" # All files under learning paths have this same wrapper +learning_path_main_page: "yes" # Indicates this should be surfaced when looking for related content. Only set for _index.md of learning path content. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/_next-steps.md b/content/learning-paths/servers-and-cloud-computing/github-on-arm/_next-steps.md new file mode 100644 index 0000000000..c3db0de5a2 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/github-on-arm/_next-steps.md @@ -0,0 +1,8 @@ +--- +# ================================================================================ +# FIXED, DO NOT MODIFY THIS FILE +# ================================================================================ +weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. +title: "Next Steps" # Always the same, html page title. +layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/background.md b/content/learning-paths/servers-and-cloud-computing/github-on-arm/background.md new file mode 100644 index 0000000000..e450977285 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/github-on-arm/background.md @@ -0,0 +1,27 @@ +--- +title: "About Google Axion and GitHub Actions" + +weight: 2 + +layout: "learningpathall" +--- + +## Google Axion C4A series + +The Google Axion C4A series is a family of Arm-based virtual machines built on Google’s custom Axion CPU, which is based on Arm Neoverse-V2 cores. Designed for high-performance and energy-efficient computing, these virtual machines offer strong performance ideal for modern cloud workloads such as CI/CD pipelines, microservices, media processing, and general-purpose applications. + +The C4A series provides offer a cost-effective virtual machine while leveraging the scalability and performance benefits of the Arm architecture in Google Cloud. + +To learn more about Google Axion, refer to the blog [Introducing Google Axion Processors, our new Arm-based CPUs](https://cloud.google.com/blog/products/compute/introducing-googles-new-arm-based-cpu). + +## GitHub Actions and CI/CD + +GitHub Actions is a powerful CI/CD (Continuous Integration and Continuous Delivery) platform built into GitHub. It allows developers to automate tasks such as building, testing, and deploying code in response to events like code pushes, pull requests, or scheduled jobs—directly from their GitHub repositories. This helps improve development speed, reliability, and collaboration. + +A key feature of GitHub Actions is [self-hosted runners](https://docs.github.com/en/actions/concepts/runners/about-self-hosted-runners), which let you run workflows on your own infrastructure instead of GitHub’s hosted servers. This is especially useful for: + +- Running on custom hardware, including Arm64-based systems (e.g., Google Axion virtual machine), to optimize performance and ensure architecture-specific compatibility. +- Private network access, allowing secure interaction with internal services or databases. +- Faster execution, especially for resource-intensive workflows, by using dedicated or high-performance machines. + +Self-hosted runners provide more control, flexibility, and cost-efficiency—making them ideal for advanced CI/CD pipelines and platform-specific testing. diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/deploy.md b/content/learning-paths/servers-and-cloud-computing/github-on-arm/deploy.md new file mode 100644 index 0000000000..348852d98b --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/github-on-arm/deploy.md @@ -0,0 +1,124 @@ +--- +title: Set up a GitHub Self-Hosted Runner +weight: 4 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + + +This section shows how to deploy a self-hosted GitHub Actions runner on your instance. It covers installing Git and GitHub CLI, authenticating with GitHub and configuring the runner on an Arm64 environment for optimized CI/CD workflows. + +### Set up development environment + +Start by installing the required dependencies using the `apt` package manager: + +```console +sudo apt update +sudo apt install -y git gh vim +``` + +Next step is to configure your git credentials. Update the command with your name and email. + +```bash +git config --global user.email "you@example.com" +git config --global user.name "Your Name" +``` + +Now you are ready to connect the machine to GitHub. The command below is used to authenticate the GitHub CLI with your GitHub account. It allows you to securely log in using a web browser or token, enabling the CLI to interact with repositories, actions, and other GitHub features on your behalf. + + +```console +gh auth login +``` + +The command will prompt you to make a few choices. For this use-case, you can use the default ones as shown in the image below. + +![Login to GitHub](./images/gh-auth.png) + +{{% notice %}} +If you get an error opening the browser on your virtual machine, you can navigate to the following URL on the host machine. +``` +https://github.com/login/device +``` +From there, you can enter the code displayed in the CLI of the virtual machine. +{{% /notice %}} + +If the log in was successful, you will see the following confirmation in your browser window. + +![GitHub UI](./images/login-page.png) + +### Test GitHub CLI and Git + +The command below creates a new public GitHub repository named **test-repo** using the GitHub CLI. It sets the repository visibility to public, meaning anyone can view it + +```console +gh repo create test-repo --public +``` +You should see an output similar to: +```output +✓ Created repository /test-repo on GitHub + https://github.com//test-repo +``` + + +### Configure the Self-Hosted Runner + +* Go to your repository's **Settings > Actions**, and under the **Runners** section +* Click on **Add Runner** or view existing self-hosted runners. + +{{% notice Note %}} +If the **Actions** tab is not visible, ensure Actions are enabled by navigating to **Settings > Actions > General**, and select **Allow all actions and reusable workflows**. +{{% /notice %}} + +![runner](./images/newsh-runner.png) + +Then, click on the **New self-hosted runner** button. In the **Add new self-hosted runner** section. Select Linux for the operating system, and choose ARM64 for the architecture. This will generate commands to set up the runner. Copy and run them on your Google Axion C4A virtual machine. + +![new-runner](./images/new-runner.png) + +The final command links the runner to your GitHub repo using a one-time registration token. + +During the command’s execution, you will be prompted to provide the runner group, the name of the runner, and the work folder name. You can accept the defaults by pressing **Enter** at each step. The output will resemble as below: + +```output +-------------------------------------------------------------------------------- +| ____ _ _ _ _ _ _ _ _ | +| / ___(_) |_| | | |_ _| |__ / \ ___| |_(_) ___ _ __ ___ | +| | | _| | __| |_| | | | | '_ \ / _ \ / __| __| |/ _ \| '_ \/ __| | +| | |_| | | |_| _ | |_| | |_) | / ___ \ (__| |_| | (_) | | | \__ \ | +| \____|_|\__|_| |_|\__,_|_.__/ /_/ \_\___|\__|_|\___/|_| |_|___/ | +| | +| Self-hosted runner registration | +| | +-------------------------------------------------------------------------------- + +# Authentication + +√ Connected to GitHub +# Runner Registration +Enter the name of the runner group to add this runner to: [press Enter for Default] +Enter the name of runner: [press Enter for lpprojectubuntuarm64] +This runner will have the following labels: 'self-hosted', 'Linux', 'ARM64' +Enter any additional labels (ex. label-1,label-2): [press Enter to skip] +√ Runner successfully added +√ Runner connection is good +``` + +Finally, start the runner by executing: +```console +./run.sh +``` +You should see an output similar to: + +```output +√ Connected to GitHub + +Current runner version: '2.326.0' +2025-07-15 05:51:13Z: Listening for Jobs +``` +The runner will now be visible in the GitHub actions: + +![final-runner](./images/final-runner.png) + +For now, you can terminate the `./run.sh` command with `Ctrl+C`. Move on to the next section to set up a simple web server using the runner. diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/final-runner.png b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/final-runner.png new file mode 100644 index 0000000000..40fa28b573 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/final-runner.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/gh-auth.png b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/gh-auth.png new file mode 100644 index 0000000000..3a99824831 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/gh-auth.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/login-page.png b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/login-page.png new file mode 100644 index 0000000000..f2bb1bd185 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/login-page.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/new-runner.png b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/new-runner.png new file mode 100644 index 0000000000..ce44dd35c2 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/new-runner.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/newsh-runner.png b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/newsh-runner.png new file mode 100644 index 0000000000..b507f32101 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/newsh-runner.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/nginx.png b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/nginx.png new file mode 100644 index 0000000000..83d940dc56 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/nginx.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/select-instance.png b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/select-instance.png new file mode 100644 index 0000000000..2a65bdcde8 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/github-on-arm/images/select-instance.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/instance.md b/content/learning-paths/servers-and-cloud-computing/github-on-arm/instance.md new file mode 100644 index 0000000000..b775ebc4f6 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/github-on-arm/instance.md @@ -0,0 +1,33 @@ +--- +title: Create the instance +weight: 3 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Introduction + +This guide walks you through provisioning **Google Axion C4A Arm virtual machine** on GCP with the **c4a-standard-4 (4 vCPUs, 16 GB Memory)** machine type, using the **Google Cloud Console**. + +If you haven't got a Google Cloud account, you can follow the Learning Path on [Getting Started with Google Cloud Platform](https://learn.arm.com/learning-paths/servers-and-cloud-computing/csp/google/) to get started. + +### Create an Arm-based Virtual Machine (C4A) + +To create a virtual machine based on the C4A Arm architecture: +1. Open the [Google Cloud Console](https://console.cloud.google.com/). +2. Navigate to the card **Compute Engine** and click on **Create Instance**. +3. Under the **Machine Configuration**: + - Fill in basic details like **Instance Name**, **Region**, and **Zone**. + - Choose the **Series** as `C4A`. + - Select a machine type such as `c4a-standard-4`. +![Instance Screenshot](./images/select-instance.png) +4. Under the **OS and Storage**, click on **Change**, pick **Ubuntu** as the Operating System with **Ubuntu 24.04 LTS Minimal** as the Version. Make sure you pick the version of image for Arm. +5. Under **Networking**, enable **Allow HTTP traffic** to test workloads like NGINX later. +6. Click on **Create**, and the instance will launch. + +{{% notice Important %}} +You should not enable the **Allow HTTP traffic** permanently, since this poses a security risk. For the long-term, you should only allow traffic from the IP address you use to connect to the instance. +{{% /notice %}} + +You can access the Google Cloud Console by clicking the **SSH** button in the instance overview. Use this command line interface (CLI) to run the commands in the remainder of this Learning Path. diff --git a/content/learning-paths/servers-and-cloud-computing/github-on-arm/nginx-deployment.md b/content/learning-paths/servers-and-cloud-computing/github-on-arm/nginx-deployment.md new file mode 100644 index 0000000000..8569893dfc --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/github-on-arm/nginx-deployment.md @@ -0,0 +1,77 @@ +--- +title: Deploy NGINX the GitHub Runner +weight: 5 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + + +This workflow installs and starts a basic NGINX web server on a self-hosted runner whenever code is pushed to the main branch. + +In your instance's console, create a directory for the repository: + +```console +mkdir test-repo && cd test-repo +echo "# test-repo" >> README.md +``` + +Then, create the GitHub Actions workflow file at `.github/workflows/deploy-nginx.yaml`. + +```console +mkdir .github && mkdir .github/workflows/ +vim .github/workflows/deploy-nginx.yaml +``` + +Paste the following code block into the file and save it. + +```yaml +name: Deploy NGINX + +on: + push: + branches: [ main ] + +jobs: + deploy: + runs-on: self-hosted + steps: + - name: Install NGINX + run: | + sudo apt update + sudo apt install -y nginx + + - name: Start NGINX + run: sudo systemctl start nginx +``` + +Now it's time to initiate your repository and push the changes. + +```console +git init +git add . +git commit -m "first commit" +git branch -M main +git remote add origin https://github.com/annietllnd/test-repo.git +git push -u origin main +``` + +This will trigger an actions job. The job will listen for a self-hosted runner to connect to the GitHub repository. Go back to the `actions-runner` directory and re-run the script from the previous section: + +```bash +cd .. +./run.sh +``` + +You will see in the output of the command that it identifies the a job called `deploy`, and that it finishes after having run the two steps. + +### Access the NGINX Server +Once the workflow completes, open your browser and navigate to your machine's external IP address. You will find the information in your instance overview, under **Network interfaces**. +``` +http:// +``` +You should see the NGINX welcome page confirming a successful deployment. + +![nginx](./images/nginx.png) + +You should now know how to set up a self-hosted runner with an Arm-based Google Cloud instance, and use it to run GitHub Actions workflows. From here, you can modify the workflow file to try out different commands. diff --git a/content/learning-paths/servers-and-cloud-computing/migrate-ease/3_migrate_ease_run.md b/content/learning-paths/servers-and-cloud-computing/migrate-ease/3_migrate_ease_run.md index 5be468e0d0..91cc7c5ed6 100644 --- a/content/learning-paths/servers-and-cloud-computing/migrate-ease/3_migrate_ease_run.md +++ b/content/learning-paths/servers-and-cloud-computing/migrate-ease/3_migrate_ease_run.md @@ -48,13 +48,13 @@ You can use migrate-ease from the command-line or through a Web GUI. You can scan local codebases written in a supported programming languages. By default, scan results from the code analysis are sent to the console. ```bash -python3 -m {scanner_name} --arch {arch} {scan_path} +python3 -m {scanner_name} --march {arch} {scan_path} ``` The result from the scan can be exported as `txt`, `csv`, `json` or `html`. Specify this using the `--output` option: To generate a JSON report: ```bash -python3 -m {scanner_name} --output {result_file_name}.json --arch {arch} {scan_path} +python3 -m {scanner_name} --output {result_file_name}.json --march {arch} {scan_path} ``` Here's an explanation of each of the arguments passed to the scanner tool: @@ -65,13 +65,13 @@ Here's an explanation of each of the arguments passed to the scanner tool: `{result_file_name}`: The name of the exported results file (without the extension). -`{arch}`: The architecture type; `aarch64` is the default. +`{arch}`: The architecture type; `armv8-a` is the default. `{scan_path}`: The path to the code you want to scan. To scan a remote Git repository: ```bash -python3 -m {scanner_name} --output {result_file_name}.json --arch {arch} --git-repo {repo} {clone_path} +python3 -m {scanner_name} --output {result_file_name}.json --march {arch} --git-repo {repo} {clone_path} ``` In the case of git repository scan, `{clone_path}` is a directory where the remote repo code is cloned into. This directory should be empty or must be created by the user. diff --git a/content/learning-paths/servers-and-cloud-computing/migrate-ease/4_migrate_ease_analysis.md b/content/learning-paths/servers-and-cloud-computing/migrate-ease/4_migrate_ease_analysis.md index 126a9c322e..3f6921b6a7 100644 --- a/content/learning-paths/servers-and-cloud-computing/migrate-ease/4_migrate_ease_analysis.md +++ b/content/learning-paths/servers-and-cloud-computing/migrate-ease/4_migrate_ease_analysis.md @@ -15,7 +15,7 @@ Support for AArch64 was added in Protobuf version v3.5.0 (November 2017). To dem Use migrate-ease to scan protobuf v2.5.0 and output the results to a JSON file named `result.json`: ```bash -python3 -m cpp --git-repo https://github.com/protocolbuffers/protobuf.git --branch v2.5.0 --output result.json --arch aarch64 protobuf +python3 -m cpp --git-repo https://github.com/protocolbuffers/protobuf.git --branch v2.5.0 --output result.json --march armv8-a protobuf ``` The scan will generate a file called `result.json` in your current directory. diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/_index.md b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/_index.md new file mode 100644 index 0000000000..37e306524b --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/_index.md @@ -0,0 +1,57 @@ +--- +title: Deploy MongoDB on Google Axion C4A virtual machine + +minutes_to_complete: 60 + +who_is_this_for: This Learning Path is designed for software developers looking to migrate their MongoDB workloads from x86_64 to Arm-based platforms, specifically on Google Axion-based C4A virtual machines. + +learning_objectives: + - Provision an Arm virtual machine on the Google Cloud Platform using the C4A Google Axion instance family, and RHEL 9 as the base image. + - Install and run MongoDB on an Arm-based GCP C4A instances. + - Validate the functionality of MongoDB through baseline testing. + - Benchmark the MongoDB performance on Arm using Yahoo Cloud Serving Benchmark (YCSB). + +prerequisites: + - A [Google Cloud Platform (GCP)](https://cloud.google.com/free?utm_source=google&hl=en) account with billing enabled. + - Basic understanding of Linux command line. + - Familiarity with the [MongoDB architecture](https://www.mongodb.com/) and deployment practices on Arm64 platforms. + +author: Jason Andrews + +##### Tags +skilllevels: Advanced +subjects: Databases +cloud_service_providers: Google Cloud + +armips: + - Neoverse + +tools_software_languages: + - MongoDB + - YCSB + +operatingsystems: + - Linux + +# ================================================================================ +# FIXED, DO NOT MODIFY +# ================================================================================ +further_reading: + - resource: + title: MongoDB Manual + link: https://www.mongodb.com/docs/manual/ + type: documentation + - resource: + title: MongoDB Performance Tool + link: https://github.com/idealo/mongodb-performance-test#readme + type: documentation + - resource: + title: YCSB + link: https://github.com/brianfrankcooper/YCSB/wiki/ + type: documentation + + +weight: 1 # _index.md always has weight of 1 to order correctly +layout: "learningpathall" # All files under learning paths have this same wrapper +learning_path_main_page: "yes" # Indicates this should be surfaced when looking for related content. Only set for _index.md of learning path content. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/_next-steps.md b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/_next-steps.md new file mode 100644 index 0000000000..c3db0de5a2 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/_next-steps.md @@ -0,0 +1,8 @@ +--- +# ================================================================================ +# FIXED, DO NOT MODIFY THIS FILE +# ================================================================================ +weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. +title: "Next Steps" # Always the same, html page title. +layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/background.md b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/background.md new file mode 100644 index 0000000000..99947c23e8 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/background.md @@ -0,0 +1,22 @@ +--- +title: "About Google Axion C4A series and MongoDB" + +weight: 2 + +layout: "learningpathall" +--- + +## Google Axion C4A series + +The Google Axion C4A series is a family of Arm-based virtual machines built on Google’s custom Axion CPU, which is based on Arm Neoverse-V2 cores. Designed for high-performance and energy-efficient computing, these virtual machine offer strong performance ideal for modern cloud workloads such as CI/CD pipelines, microservices, media processing, and general-purpose applications. + +The C4A series provides a cost-effective alternative to x86 virtual machine while leveraging the scalability and performance benefits of the Arm architecture in Google Cloud. + +To learn more about Google Axion, refer to the blog [Introducing Google Axion Processors, our new Arm-based CPUs](https://cloud.google.com/blog/products/compute/introducing-googles-new-arm-based-cpu). + +## MongoDB +MongoDB is a popular open-source NoSQL database designed for high performance, scalability, and flexibility. + +It stores data in JSON-like BSON documents, making it ideal for modern applications that require dynamic, schema-less data structures. + +MongoDB is widely used for web, mobile, IoT, and real-time analytics workloads. Learn more from the [MongoDB official website](https://www.mongodb.com/) and its [official documentation](https://www.mongodb.com/docs/). diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/baseline-testing.md b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/baseline-testing.md new file mode 100644 index 0000000000..842709484f --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/baseline-testing.md @@ -0,0 +1,212 @@ +--- +title: Baseline Testing +weight: 5 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + + +Since MongoDB is installed successfully on your GCP C4A Arm virtual machine, follow these steps to validate that the server is running and accepting local connections. + +## MongoDB Baseline Testing (Using **mongosh**) + +1. Connect to MongoDB + +Open a shell session to the local MongoDB instance: +```console +mongosh mongodb://127.0.0.1:27017 +``` + +2. Create a Test Database and Collection: + +```console +use baselineDB +db.createCollection("test") +``` +This creates a new database **baselineDB** and an empty collection named test. + +You should see an output similar to: + +```output +test> use baselineDB +... db.createCollection("test") +... +switched to db baselineDB +``` +3. Insert 10,000 Test Documents: + +```javascript +for (let i = 0; i < 10000; i++) { + db.test.insertOne({ + record: i, + status: "new", + timestamp: new Date() + }) +} +``` +This simulates basic write operations with timestamped records. +10,000 documents will be cretaed and inserted into the test collection of the currently selected database. +The record field would increment from 0 to 9999. The status is always "new". +The timestamp would capture the insertion time for each document using ***new Date()***. + +You should see an output similar to: + +```output +{ + acknowledged: true, + insertedId: ObjectId('6892dacfbd44e23df4750aa9') +} +``` + +4. Read (Query) a Subset of Documents: + +Fetch a few documents to verify read functionality. +```javascript +db.test.find({ status: "new" }).limit(5) +``` +This command is a simple read operation to verify that your data is inserted correctly. It queries the test collection in the current database, and only returns documents where the status is "new". ***limit(5)*** returns only the first 5 matching documents. + +You should see an output similar to: + +```output +[ + { + _id: ObjectId('6892dacbbd44e23df474e39a'), + record: 0, + status: 'new', + timestamp: ISODate('2025-08-06T04:32:11.090Z') + }, + { + _id: ObjectId('6892dacbbd44e23df474e39b'), + record: 1, + status: 'new', + timestamp: ISODate('2025-08-06T04:32:11.101Z') + }, + { + _id: ObjectId('6892dacbbd44e23df474e39c'), + record: 2, + status: 'new', + timestamp: ISODate('2025-08-06T04:32:11.103Z') + }, + { + _id: ObjectId('6892dacbbd44e23df474e39d'), + record: 3, + status: 'new', + timestamp: ISODate('2025-08-06T04:32:11.104Z') + }, + { + _id: ObjectId('6892dacbbd44e23df474e39e'), + record: 4, + status: 'new', + timestamp: ISODate('2025-08-06T04:32:11.106Z') + } +] +``` +5. Update a Document: + +Update a specific document's field to validate update capability. +```javascript +db.test.updateOne({ record: 100 }, { $set: { status: "processed" } }) +``` +Above command will find the first document where record is exactly 100, and updates that document by setting its status field to "processed". + +You should see an output similar to: + +```output +{ + acknowledged: true, + insertedId: null, + matchedCount: 1, + modifiedCount: 1, + upsertedCount: 0 +} +``` +6. View the Updated Document Before Deletion + +```console +db.test.findOne({ record: 100 }) +``` +This retrieves the document where record is 100, allowing you to verify that its status has been updated to "processed". + +You should see output similar to: + +```output +{ + _id: ObjectId('689490ddb7235c65ca74e3fe'), + record: 100, + status: 'processed', + timestamp: ISODate('2025-08-07T11:41:17.508Z') +} +``` + +7. Delete a Document: + +```javascript +db.test.deleteOne({ record: 100 }) +``` +This tells MongoDB to delete one document from the test collection, where record is exactly 100. + +You should see an output similar to: + +```output +{ acknowledged: true, deletedCount: 1 } +``` +Now, confirm the deletion: + +```console +db.test.findOne({ record: 100 }) +``` +The above command confirms that the document was successfully deleted. + +You should see an output similar to: +```output +null +``` + +8. Measure Execution Time (Optional): + +The below snippet measures how long it takes to insert documents for performance insight. +```javascript +var start = new Date() +for (let i = 0; i < 10000; i++) { + db.test.insertOne({ sample: i }) +} +print("Insert duration (ms):", new Date() - start) +``` +You should see an output similar to: + +```output +Insert duration (ms): 4427 +``` +9. Count Total Documents: + +Count total entries to confirm expected data volume. +```javascript +db.test.countDocuments() +``` +You should see an output similar to: + +```output +19999 +``` +The count **19999** reflects the total documents after inserting 10,000 initial records, adding 10,000 more (in point 8), and deleting one (record: 100). + +10. Clean Up (Optional): + +Deletes the **baselineDB** database and all its contents. +```javascript +db.dropDatabase() +``` +You should see an output similar to: + +```output +{ ok: 1, dropped: 'baselineDB' } +``` + +The above is a destructive command that completely deletes the current database you are connected to in mongosh. + +The above operations confirm that MongoDB is installed successfully and is functioning as expected on the GCP Arm64 environment. + +Using **mongosh**, you validated key database operations such as **insert**, **read**, **update**, **delete**, and **count**. +Now, your MongoDB instance is ready for further benchmarking and production use. diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/benchmarking.md b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/benchmarking.md new file mode 100644 index 0000000000..2ddf4990c6 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/benchmarking.md @@ -0,0 +1,124 @@ +--- +title: MongoDB Benchmarking +weight: 6 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## MongoDB Benchmarking with YCSB (Yahoo! Cloud Serving Benchmark) + +**YCSB (Yahoo! Cloud Serving Benchmark)** is an open-source benchmarking tool for evaluating the performance of NoSQL databases under different workloads. It supports operations like read, write, update, and scan to simulate real-world usage patterns. + +### Install YCSB (Build from Source) + +```console +sudo dnf install -y git maven java-11-openjdk-devel +git clone https://github.com/brianfrankcooper/YCSB.git +cd YCSB +mvn -pl site.ycsb:mongodb-binding -am clean package +``` + +### Load Phase – Insert Initial Dataset + +This phase inserts documents into MongoDB to simulate a typical workload. + +```console +./bin/ycsb load mongodb -s \ + -P workloads/workloada \ + -p mongodb.url=mongodb://127.0.0.1:27017/ycsb +``` +The core purpose of this phase is to prepare the database with initial records (default: 1,000) for benchmarking. + +### Execute Benchmark Workload + +This phase performs actual read/write operations and reports performance metrics. +```console +./bin/ycsb run mongodb -s \ + -P workloads/workloada \ + -p mongodb.url=mongodb://127.0.0.1:27017/ycsb +``` +Workload A (from workloads/workloada) simulates a balanced read/write workload: + +- 50% reads +- 50% updates/writes + +This is designed to mimic many real-world systems where reads and writes are equally important (e.g., session stores, shopping carts, etc.). +The above command measures latency and throughput of mixed read/write operations. + + +You should see an output similar to: + +```output +Loading workload... +Starting test. +2025-08-06 06:05:50:378 0 sec: 0 operations; est completion in 0 second +mongo client connection created with mongodb://127.0.0.1:27017/ycsb +DBWrapper: report latency for each error is false and specific error codes to track for latency are: [] +2025-08-06 06:05:50:874 0 sec: 1000 operations; 1953.12 current ops/sec; [READ: Count=534, Max=8279, Min=156, Avg=312.96, 50=261, 90=436, 99=758, 99.9=8279, 99.99=8279] [CLEANUP: Count=1, Max=4139, Min=4136, Avg=4138, 50=4139, 90=4139, 99=4139, 99.9=4139, 99.99=4139] [UPDATE: Count=466, Max=26543, Min=186, Avg=384.45, 50=296, 90=444, 99=821, 99.9=26543, 99.99=26543] +[OVERALL], RunTime(ms), 512 +[OVERALL], Throughput(ops/sec), 1953.125 +[TOTAL_GCS_G1_Young_Generation], Count, 2 +[TOTAL_GC_TIME_G1_Young_Generation], Time(ms), 3 +[TOTAL_GC_TIME_%_G1_Young_Generation], Time(%), 0.5859375 +[TOTAL_GCS_G1_Old_Generation], Count, 0 +[TOTAL_GC_TIME_G1_Old_Generation], Time(ms), 0 +[TOTAL_GC_TIME_%_G1_Old_Generation], Time(%), 0.0 +[TOTAL_GCs], Count, 2 +[TOTAL_GC_TIME], Time(ms), 3 +[TOTAL_GC_TIME_%], Time(%), 0.5859375 +[READ], Operations, 534 +[READ], AverageLatency(us), 312.96067415730334 +[READ], MinLatency(us), 156 +[READ], MaxLatency(us), 8279 +[READ], 50thPercentileLatency(us), 261 +[READ], 95thPercentileLatency(us), 524 +[READ], 99thPercentileLatency(us), 758 +[READ], Return=OK, 534 +[CLEANUP], Operations, 1 +[CLEANUP], AverageLatency(us), 4138.0 +[CLEANUP], MinLatency(us), 4136 +[CLEANUP], MaxLatency(us), 4139 +[CLEANUP], 50thPercentileLatency(us), 4139 +[CLEANUP], 95thPercentileLatency(us), 4139 +[CLEANUP], 99thPercentileLatency(us), 4139 +[UPDATE], Operations, 466 +[UPDATE], AverageLatency(us), 384.4527896995708 +[UPDATE], MinLatency(us), 186 +[UPDATE], MaxLatency(us), 26543 +[UPDATE], 50thPercentileLatency(us), 296 +[UPDATE], 95thPercentileLatency(us), 498 +[UPDATE], 99thPercentileLatency(us), 821 +[UPDATE], Return=OK, 466 +``` + +### YCSB Operations & Latency Metrics + +- **Operations Count**: Total number of operations performed by YCSB for each type. +- **Average Latency (us**): The average time (in microseconds) it took to complete each operation type. +- **Min Latency (us)**: The fastest (minimum) time observed for any single operation of that type. +- **Max Latency (us)**: The slowest (maximum) time recorded for any single operation of that type. + +### Benchmark summary on x86_64: +The following benchmark results are collected on a c3-standard-4 (4 vCPU, 2 core, 16 GB Memory) x86_64 environment, running RHEL 9. + +| Operation | Count | Avg Latency (us) | Min Latency (us) | Max Latency (us) | 50th Percentile (us) | 95th Percentile (us) | 99th Percentile (us) | +|-----------|-------|------------------|------------------|------------------|-----------------------|----------------------|-----------------------| +| READ | 472 | 672.27 | 177 | 56703 | 514 | 903 | 1331 | +| UPDATE | 528 | 621.27 | 214 | 12855 | 554 | 971 | 1224 | +| CLEANUP | 1 | 4702 | 4700 | 4703 | 4703 | 4703 | 4703 | + +### Benchmark summary on Arm64: +The following benchmark results are collected on a c4a-standard-4 (4 vCPU, 16 GB Memory) Arm64 environment, running RHEL 9. + +| Operation | Count | Avg Latency (us) | Min Latency (us) | Max Latency (us) | 50th Percentile (us) | 95th Percentile (us) | 99th Percentile (us) | +|----------|------------------|------------------|------------------|------------------|----------------------|----------------------|----------------------| +| READ | 534 | 312.96 | 156 | 8279 | 261 | 524 | 758 | +| UPDATE | 466 | 384.45 | 186 | 26543 | 296 | 498 | 821 | +| CLEANUP | 1 | 4138 | 4136 | 4139 | 4139 | 4139 | 4139 | + +### **Highlights from GCP C4A Arm virtual machine** + +- Arm results show low **average latencies**, **READ** at **313 us** and **UPDATE** at **384 us**. +- **50th** to **99th percentile** latencies remain stable, indicating consistent performance. +- **Max latency** spikes (**8279 us READ**, **26543 us UPDAT**E) suggest rare outliers. diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/create-instance.md b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/create-instance.md new file mode 100644 index 0000000000..3ca28709da --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/create-instance.md @@ -0,0 +1,29 @@ +--- +title: Create Google Axion C4A Arm virtual machine +weight: 3 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Introduction + +This guide walks you through provisioning **Google Axion C4A Arm virtual machine** on GCP with the **c4a-standard-4 (4 vCPUs, 16 GB Memory)** machine type, using the **Google Cloud Console**. + +If you are new to Google Cloud, it is recommended to follow the [GCP Quickstart Guide to Create a virtual machine](https://cloud.google.com/compute/docs/instances/create-start-instance). + +For more details, kindly follow the Learning Path on [Getting Started with Google Cloud Platform](https://learn.arm.com/learning-paths/servers-and-cloud-computing/csp/google/). + +### Create an Arm-based Virtual Machine (C4A) + +To create a virtual machine based on the C4A Arm architecture: +1. Navigate to the [Google Cloud Console](https://console.cloud.google.com/). +2. Go to **Compute Engine > VM Instances** and click on **Create Instance**. +3. Under the **Machine Configuration**: + - Fill in basic details like **Instance Name**, **Region**, and **Zone**. + - Choose the **Series** as `C4A`. + - Select a machine type such as `c4a-standard-4`. +![Instance Screenshot](./image1.png) +4. Under the **OS and Storage**, click on **Change**, and select Arm64 based OS Image of your choice. For this Learning Path, we pick **Red Hat Enterprise Linux** as the Operating System with **Red Hat Enterprise Linux 9** as the Version. Make sure you pick the version of image for Arm. +5. Under **Networking**, enable **Allow HTTP traffic** to allow HTTP communications. +6. Click on **Create**, and the instance will launch. diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/image1.png b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/image1.png new file mode 100644 index 0000000000..2a65bdcde8 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/image1.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/mongodb-deploy.md b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/mongodb-deploy.md new file mode 100644 index 0000000000..0725049259 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/mongodb-on-gcp/mongodb-deploy.md @@ -0,0 +1,119 @@ +--- +title: Install MongoDB on Google Axion C4A virtual machine +weight: 4 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + + +## Install MongoDB and mongosh on Google Axion C4A virtual machine + +Install MongoDB and mongosh on GCP RHEL 9 Arm64 by downloading the binaries, setting up environment paths, configuring data and log directories, and starting the server for local access and verification. + +1. Install System Dependencies + +Install required system packages to support MongoDB: +```console +sudo dnf install -y libcurl openssl tar wget curl +``` + +2. Download annd Extract MongoDB + +Fetch and unpack the MongoDB binaries for Arm64: +```console +wget https://fastdl.mongodb.org/linux/mongodb-linux-aarch64-rhel93-8.0.12.tgz +tar -xzf mongodb-linux-aarch64-rhel93-8.0.12.tgz +ls mongodb-linux-aarch64-rhel93-8.0.12/bin +``` + +3. Add MongoDB to System PATH + +Enable running mongod from any terminal session: +```console +echo 'export PATH=~/mongodb-linux-aarch64-rhel93-8.0.12/bin:$PATH' >> ~/.bashrc +source ~/.bashrc +``` + +4. Create a data Directory + +Set up the database data directory: +```console +mkdir -p ~/mongodb-data/db +``` + +5. Start MongoDB Server + +Start MongoDB in the **foreground** (without --fork) to view real-time output and ensure it starts correctly: +```console +~/mongodb-linux-aarch64-rhel93-8.0.12/bin/mongod --dbpath ~/mongodb-data/db +``` +Once confirmed it's working, you can start MongoDB in the **background** with logging: +```console +./mongodb-linux-aarch64-rhel93-8.0.12/bin/mongod --dbpath ~/mongodb-data/db --logpath ~/mongodb-data/mongod.log --fork +``` +{{% notice Note %}}Make sure the **~/mongodb-data/db** directory exists before starting.{{% /notice %}} + +6. Install mongosh + +**mongosh** is the MongoDB Shell used to interact with your MongoDB server. It provides a modern, user-friendly CLI for running queries and database operations. + +Download and install MongoDB’s command-line shell for Arm: +```console +wget https://github.com/mongodb-js/mongosh/releases/download/v2.5.6/mongodb-mongosh-2.5.6.aarch64.rpm +sudo dnf install -y ./mongodb-mongosh-2.5.6.aarch64.rpm +``` +### Verify Mongodb and mongosh Installation + +Check if MongoDb and mongosh is properly installed: +```console +mongod --version +mongosh --version +``` +You should see an output similar to: +```output +db version v8.0.12 +Build Info: { + "version": "8.0.12", + "gitVersion": "b60fc6875b5fb4b63cc0dbbd8dda0d6d6277921a", + "openSSLVersion": "OpenSSL 3.2.2 4 Jun 2024", + "modules": [], + "allocator": "tcmalloc-google", + "environment": { + "distmod": "rhel93", + "distarch": "aarch64", + "target_arch": "aarch64" + } +} +$ mongosh --version +2.5.6 +``` + +### Connect to MongoDB via mongosh + +Start interacting with MongoDB through its shell interface: +```console +mongosh mongodb://127.0.0.1:27017 +``` +You should see an output similar to: +```output +Current Mongosh Log ID: 6891ebb158db5b705d74e399 +Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.5.6 +Using MongoDB: 8.0.12 +Using Mongosh: 2.5.6 + +For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/ + +------ + The server generated these startup warnings when booting + 2025-08-05T07:17:45.864+00:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted + 2025-08-05T07:17:45.864+00:00: Soft rlimits for open file descriptors too low + 2025-08-05T07:17:45.864+00:00: For customers running the current memory allocator, we suggest changing the contents of the following sysfsFile + 2025-08-05T07:17:45.864+00:00: We suggest setting the contents of sysfsFile to 0. + 2025-08-05T07:17:45.864+00:00: Your system has glibc support for rseq built in, which is not yet supported by tcmalloc-google and has critical performance implications. Please set the environment variable GLIBC_TUNABLES=glibc.pthread.rseq=0 +------ + +test> +``` + +MongoDB installation is complete. You can now proceed with the baseline testing. diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/1_introduction_rdv3.md b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/1_introduction_rdv3.md new file mode 100644 index 0000000000..c36adf0b1a --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/1_introduction_rdv3.md @@ -0,0 +1,85 @@ +--- +title: Learn about the Arm RD‑V3 Platform +weight: 2 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Introduction to the Arm RD‑V3 Platform + +In this section, you will learn about the Arm [Neoverse CSS V3](https://www.arm.com/products/neoverse-compute-subsystems/css-v3) subsystem and the RD‑V3 [Reference Design Platform Software](https://neoverse-reference-design.docs.arm.com/en/latest/index.html) that implements it. You'll learn how these components enable scalable, server-class system design, and how to simulate and validate the full firmware stack using Fixed Virtual Platforms (FVP), well before hardware is available. + +Arm Neoverse is designed to meet the demanding requirements of data center and edge computing, delivering high performance and efficiency. Widely adopted in servers, networking, and edge devices, the Neoverse architecture provides a solid foundation for modern infrastructure. + +Using Arm Fixed Virtual Platforms (FVPs), you can explore system bring-up, boot flow, and firmware customization well before physical silicon becomes available. + +This module also introduces the key components involved, from Neoverse V3 cores to secure subsystem controllers, and shows how these elements work together in a fully virtualized system simulation. + +### Neoverse CSS-V3 Platform Overview + +[Neoverse CSS-V3](https://www.arm.com/products/neoverse-compute-subsystems/css-v3) (Compute Subsystem Version 3) is the core subsystem architecture underpinning the Arm RD-V3 platform. It is specifically optimized for high-performance server and data center applications, providing a highly integrated solution combining processing cores, memory management, and interconnect technology. + +CSS V3 forms the key building block for specialized computing systems. It reduces design and validation costs for the general-purpose compute subsystem, allowing partners to focus on their specialization and acceleration while reducing risk and accelerating time to deployment. + +CSS‑V3 is available in configurable subsystems, supporting up to 64 Neoverse V3 cores per die. It also enables integration of high-bandwidth DDR5/LPDDR5 memory (up to 12 channels), PCIe Gen5 or CXL I/O (up to 64 lanes), and high-speed die-to-die links with support for UCIe 1.1 or custom PHYs. Designs can be scaled down to smaller core-count configurations, such as 32-core SoCs, or expanded through multi-die integration. + +Key features of CSS-V3 include: + +* High-performance CPU clusters: Optimized for server workloads and data throughput. + +* Advanced memory management: Efficient handling of data across multiple processing cores. + +* Interconnect technology: Enabling high-speed, low-latency communication within the subsystem. + +The CSS‑V3 subsystem is fully supported by Arm's Fixed Virtual Platform, enabling pre-silicon testing of these capabilities. + +### RD‑V3 Platform Introduction + +The RD‑V3 platform is a comprehensive reference design built around Arm’s [Neoverse V3](https://www.arm.com/products/silicon-ip-cpu/neoverse/neoverse-v3) CPUs, along with [Cortex-M55](https://www.arm.com/products/silicon-ip-cpu/cortex-m/cortex-m55) and [Cortex-M7](https://www.arm.com/products/silicon-ip-cpu/cortex-m/cortex-m7) microcontrollers. This platform enables efficient high-performance computing and robust platform management: + + +| Component | Description | +|------------------|------------------------------------------------------------------------------------------------| +| Neoverse V3 | The primary application processor responsible for executing OS and payloads | +| Cortex M7 | Implements the System Control Processor (SCP) for power, clocks, and init | +| Cortex M55 | Hosts the Runtime Security Engine (RSE), providing secure boot and runtime integrity | +| Cortex M55 (LCP) | Acts as the Local Control Processor, enabling per-core power and reset management for AP cores | + + +These subsystems work together in a coordinated architecture, communicating through shared memory regions, control buses, and platform protocols. This enables multi-stage boot processes and robust secure boot implementations. + +Here is the Neoverse Reference Design Platform [Software Stack](https://neoverse-reference-design.docs.arm.com/en/latest/about/software_stack.html#sw-stack) for your reference. + +![img1 alt-text#center](rdinfra_sw_stack.jpg "Neoverse Reference Design Software Stack") + + +### Develop and Validate Without Hardware + +In traditional development workflows, system validation cannot begin until silicon is available, often introducing risk and delay. + +To address this, Arm provides Fixed Virtual Platforms ([FVP](https://developer.arm.com/Tools%20and%20Software/Fixed%20Virtual%20Platforms)), complete simulations model that emulates Arm SoC behavior on a host machine. The CSS‑V3 platform is available in multiple FVP configurations, allowing developers to select the model that best fits their specific development and validation needs. + + +Key Capabilities of FVP: +* Multi-core CPU simulation with SMP boot +* Multiple UART interfaces for serial debug and monitoring +* Compatible with TF‑A, UEFI, GRUB, and Linux kernel images +* Provides boot logs, trace outputs, and interrupt event visibility for debugging + +FVP enables developers to verify boot sequences, debug firmware handoffs, and even simulate RSE (Runtime Security Engine) behaviors, all pre-silicon. + +### Comparing different version of RD-V3 FVP + +To support different use cases and levels of platform complexity, Arm offers three virtual models based on the CSS V3 architecture: RD‑V3, RD-V3-Cfg1, and RD‑V3‑R1. While they share a common foundation, they differ in chip count, system topology, and simulation flexibility. + +| Model | Description | Recommended Use Cases | +|-------------|------------------------------------------------------------------|--------------------------------------------------------------------| +| RD‑V3 | Standard single-die platform with full processor and security blocks | Ideal for newcomers, firmware bring-up, and basic validation | +| RD‑V3‑R1 | Dual-die platform simulating chiplet-based architecture | Suitable for multi-node, interconnect, and advanced boot tests | +| CFG1 | Lightweight model with reduced control complexity for fast startup | Best for CI pipelines, unit testing, and quick validations | +| CFG2 | Quad-chip platform with 4×32-core Poseidon-V CPUs connected via CCG links | Designed for advanced multi-chip validation, CML-based coherence, and high-performance platform scaling | + + +In this Learning Path you will use RD‑V3 as the primary platform for foundational exercises, guiding you through the process of building the software stack and simulating it on an FVP to verify the boot sequence. +In later modules, you’ll transition to RD‑V3‑R1 to more advanced system simulation, multi-node bring-up, and firmware coordination across components like MCP and SCP. diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/2_rdv3_bootseq.md b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/2_rdv3_bootseq.md new file mode 100644 index 0000000000..eff3635e51 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/2_rdv3_bootseq.md @@ -0,0 +1,160 @@ +--- +title: Understanding the CSS V3 Boot Flow and Firmware Stack +weight: 3 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Firmware Stack Overview and Boot Sequence Coordination + +To ensure the platform transitions securely and reliably from power-on to operating system launch, this section introduces the roles and interactions of each firmware component within the RD‑V3 boot process. +You’ll learn how each component contributes to system initialization and how control is systematically handed off across the boot chain. + + +## How the System Boots Up + +In the RD‑V3 platform, each firmware component—such as TF‑A, RSE, SCP, LCP, and UEFI—operates independently but functions together through a well-defined sequence. +Each component is delivered as a separate firmware image, yet they coordinate tightly through a structured boot flow and inter-processor signaling. + +The following diagram from the [Neoverse Reference Design Documentation](https://neoverse-reference-design.docs.arm.com/en/latest/shared/boot_flow/rdv3_single_chip.html?highlight=boot) illustrates the progression of component activation from initial reset to OS handoff: + +![img1 alt-text#center](rdf_single_chip.png "Boot Flow for RD-V3 Single Chip") + +### Stage 1. Security Validation Starts First (RSE) + +The first firmware module triggered after BL2 is the Runtime Security Engine (RSE), executing on Cortex‑M55. RSE authenticates all critical firmware components—including SCP, UEFI, and kernel images—using secure boot mechanisms. It performs cryptographic measurements and builds a Root of Trust before allowing any other processors to start. + +***RSE acts as the platform’s security gatekeeper.*** + +### Stage 2. Early Hardware Initialization (SCP / MCP) + +Once RSE completes verification, the System Control Processor (SCP) and Management Control Processor (MCP) are released from reset. + +These controllers perform essential platform bring-up: +* Initialize clocks, reset lines, and power domains +* Prepare DRAM and interconnect +* Enable the application cores and signal readiness to TF‑A + +***SCP/MCP are the ground crew bringing hardware systems online.*** + +### Stage 3. Secure Execution Setup (TF‑A) + +Once the AP is released, it begins executing Trusted Firmware‑A (TF‑A) at EL3, starting from the reset vector address programmed during boot image layout. +TF‑A configures the secure world, sets up exception levels, and prepares for handoff to UEFI. + +***TF‑A is the ignition controller, launching the next stages securely.*** + +### Stage 4. Firmware and Bootloader (EDK2 / GRUB) + +TF‑A hands off control to UEFI firmware (EDK2), which performs device discovery and launches GRUB. + +Responsibilities: +* Detect and initialize memory, PCIe, and boot devices +* Generate ACPI and platform configuration tables +* Locate and launch GRUB from storage or flash + +***EDK2 and GRUB are like the first- and second-stage rockets launching the payload.*** + +### Stage 5. Linux Kernel Boot + +GRUB loads the Linux kernel and passes full control to the OS. + +Responsibilities: +* Initialize device drivers and kernel subsystems +* Mount the root filesystem +* Start user-space processes (e.g., BusyBox) + +***The Linux kernel is the spacecraft—it takes over and begins its mission.*** + +## Firmware Module Responsibilities in Detail + +Now that we’ve examined the high-level boot stages, let’s break down each firmware module’s role in more detail. + +Each stage of the boot chain is backed by a dedicated component—either a secure bootloader, platform controller, or operating system manager—working together to ensure a reliable system bring-up. + +### RSE: Runtime Security Engine (Cortex‑M55) (Stage 1: Security Validation) + +RSE firmware runs on the Cortex‑M55 and plays a critical role in platform attestation and integrity enforcement. +* Authenticates BL2, SCP, and UEFI firmware images (Secure Boot) +* Records boot-time measurements (e.g., PCRs, ROT) +* Releases boot authorization only after successful validation + +RSE acts as the second layer of the chain of trust, maintaining a monitored and secure environment throughout early boot. + + +### SCP: System Control Processor (Cortex‑M7) (Stage 2: Early Hardware Bring-up) + +SCP firmware runs on the Cortex‑M7 core and performs early hardware initialization and power domain control. +* Initializes clocks, reset controllers, and system interconnect +* Manages DRAM setup and enables power for the application processor +* Coordinates boot readiness with RSE via MHU (Message Handling Unit) + +SCP is central to bring-up operations and ensures the AP starts in a stable hardware environment. + +### TF-A: Trusted Firmware-A (BL1 / BL2) (Stage 3: Secure Execution Setup) + +TF‑A is the entry point of the boot chain and is responsible for establishing the system’s root of trust. +* BL1 (Boot Loader Stage 1): Executes from ROM, initializing minimal hardware such as clocks and serial interfaces, and loads BL2. +* BL2 (Boot Loader Stage 2): Validates and loads SCP, RSE, and UEFI images, setting up secure handover to later stages. + +TF‑A ensures all downstream components are authenticated and loaded from trusted sources, laying the foundation for a secure boot. + + +### UEFI / GRUB / Linux Kernel (Stage 4–5: Bootloader and OS Handoff) + +After SCP powers on the application processor, control passes to the main bootloader and operating system: +* UEFI (EDK2): Provides firmware abstraction, hardware discovery, and ACPI table generation +* GRUB: Selects and loads the Linux kernel image +* Linux Kernel: Initializes the OS, drivers, and launches the userland (e.g., BusyBox) + +On the FVP, you can observe this process via UART logs, helping validate each stage’s success. + + +### LCP: Low Power Controller (Optional Component) + +If present in the configuration, LCP handles platform power management at a finer granularity: +* Implements sleep/wake transitions +* Controls per-core power gating +* Manages transitions to ACPI power states (e.g., S3, S5) + +LCP support depends on the FVP model and may be omitted in simplified virtual setups. + + +### Coordination and Handoff Logic + +The RD‑V3 boot sequence follows a multi-stage, dependency-driven handshake model, where each firmware module validates, powers, or authorizes the next. + +| Stage | Dependency Chain | Description | +|-------|----------------------|-------------------------------------------------------------------------| +| 1 | RSE ← BL2 | RSE is loaded and triggered by BL2 to begin security validation | +| 2 | SCP ← BL2 + RSE | SCP initialization requires both BL2 and authorization from RSE | +| 3 | AP ← SCP + RSE | The application processor starts only after SCP sets power and RSE permits | +| 4 | UEFI → GRUB → Linux | UEFI launches GRUB, which loads the kernel and enters the OS | + +This handshake model ensures that no firmware stage proceeds unless its dependencies have securely initialized and authorized the next step. + +{{% notice Note %}} +In the table above, arrows (←) represent **dependency relationships**—the component on the left **depends on** the component(s) on the right to be triggered or authorized. +For example, `RSE ← BL2` means that RSE is loaded and triggered by BL2; +`AP ← SCP + RSE` means the application processor can only start after SCP has initialized the hardware and RSE has granted secure boot authorization. +These arrows do not represent execution order but indicate **which component must be ready for another to begin**. +{{% /notice %}} + +{{% notice Note %}} +Once the firmware stack reaches UEFI, it performs hardware discovery and launches GRUB. +GRUB then selects and boots the Linux kernel. Unlike the previous dependency arrows (←), this is a **direct execution path**—each stage passes control directly to the next. +{{% /notice %}} + +This layered approach supports modular testing, independent debugging, and early-stage simulation—all essential for secure and robust platform bring-up. + + +In this section, you have: + +* Explored the full boot sequence of the RD‑V3 platform, from power-on to Linux login +* Understood the responsibilities of key firmware components such as TF‑A, RSE, SCP, LCP, and UEFI +* Learned how secure boot is enforced and how each module hands off control to the next +* Interpreted boot dependencies using FVP simulation and UART logs + +With an understanding of full boot sequence and firmware responsibilities, you're ready to apply these insights. +In the next section, you'll fetch the RD‑V3 codebase and start building the firmware stack for simulation. diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/3_rdv3_sw_build.md b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/3_rdv3_sw_build.md new file mode 100644 index 0000000000..75a0c1de08 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/3_rdv3_sw_build.md @@ -0,0 +1,257 @@ +--- +title: Build the RD‑V3 Reference Platform Software Stack +weight: 4 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- +## Building the RD‑V3 Reference Platform Software Stack + +In this module, you’ll set up your development environment on any Arm-based server and build the firmware stack required to simulate the RD‑V3 platform. This Learning Path was tested on an AWS `m7g.4xlarge` Arm-based instance running Ubuntu 22.04 + + +### Step 1: Prepare the Development Environment + +First, ensure your system is up-to-date and install the required tools and libraries: + +```bash +sudo apt update +sudo apt install curl git +``` + +Configure git as follows. + +```bash +git config --global user.name "" +git config --global user.email "" +``` + +### Step 2: Fetch the Source Code + +The RD‑V3 platform firmware stack consists of many independent components—such as TF‑A, SCP, RSE, UEFI, Linux kernel, and Buildroot. Each component is maintained in a separate Git repository. To manage and synchronize these repositories efficiently, we use the `repo` tool. It simplifies syncing the full platform software stack from multiple upstreams. + +If repo is not installed, you can download it manually: + +```bash +mkdir -p ~/.bin +PATH="${HOME}/.bin:${PATH}" +curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo +chmod a+rx ~/.bin/repo +``` + +Once ready, create a workspace and initialize the repo manifest: + +We use a pinned manifest to ensure reproducibility across different environments. This locks all component repositories to known-good commits that are validated and aligned with a specific FVP version. + +For this session, we will use `pinned-rdv3.xml` and `RD-INFRA-2025.07.03`. + +```bash +cd ~ +mkdir rdv3 +cd rdv3 +``` +Initialize and sync the source code tree: +```bash +repo init -u https://git.gitlab.arm.com/infra-solutions/reference-design/infra-refdesign-manifests.git -m pinned-rdv3.xml -b refs/tags/RD-INFRA-2025.07.03 --depth=1 +repo sync -c -j $(nproc) --fetch-submodules --force-sync --no-clone-bundle --retry-fetches=5 +``` + +Once synced, the output should look like: +```output +Syncing: 95% (19/20), done in 2m36.453s +Syncing: 100% (83/83) 2:52 | 1 job | 0:01 platsw/edk2-platforms @ uefi/edk2/edk2-platformsrepo sync has finished successfully. +``` + +{{% notice Note %}} +As of the time of writing, the latest official release tag is RD-INFRA-2025.07.03. +Please note that newer tags may be available as future platform updates are published. +{{% /notice %}} + +This manifest will fetch all required sources including: +* TF‑A +* SCP / RSE firmware +* EDK2 (UEFI) +* Linux kernel +* Buildroot and platform scripts + + +### Step 3: Build the Docker Image + +There are two supported methods for building the reference firmware stack: **host-based** and **container-based**. + +- The **host-based** build installs all required dependencies directly on your local system and executes the build natively. +- The **container-based** build runs the compilation process inside a pre-configured Docker image, ensuring consistent results and isolation from host environment issues. + +In this Learning Path, you will use the **container-based** approach. + +The container image is designed to use the source directory from the host (`~/rdv3`) and perform the build process inside the container. Make sure Docker is installed on your Linux machine. You can follow this [installation guide](https://learn.arm.com/install-guides/docker/). + + +After Docker is installed, you’re ready to build the container image. + +The `container.sh` script is a wrapper that builds the container using default settings for the Dockerfile and image name. You can customize these by using the `-f` (Dockerfile) and `-i` (image name) options, or by editing the script directly. + +To view all available options: + +```bash +cd ~/rdv3/container-scripts +./container.sh -h +``` + +To build the container image: + +```bash +./container.sh build +``` + +The build procedure may take a few minutes, depending on network bandwidth and CPU performance. This Learning Path was tested on an AWS `m7g.4xlarge` instance, and the build took 250 seconds. The output from the build looks like: + +```output +Building docker image: rdinfra-builder ... +[+] Building 239.7s (19/19) FINISHED docker:default + => [internal] load build definition from rd-infra-arm64 0.0s + => => transferring dockerfile: 4.50kB 0.0s + => [internal] load metadata for docker.io/library/ubuntu:jammy-20240911.1 1.0s + => [internal] load .dockerignore 0.0s + => => transferring context: 2B 0.0s + => [internal] load build context 0.0s + => => transferring context: 10.80kB 0.0s + => [ 1/14] FROM docker.io/library/ubuntu:jammy-20240911.1@sha256:0e5e4a57c2499249aafc3b40fcd541e9a456aab7296681a3994d631587203f97 1.7s + => => resolve docker.io/library/ubuntu:jammy-20240911.1@sha256:0e5e4a57c2499249aafc3b40fcd541e9a456aab7296681a3994d631587203f97 0.0s + => => sha256:0e5e4a57c2499249aafc3b40fcd541e9a456aab7296681a3994d631587203f97 6.69kB / 6.69kB 0.0s + => => sha256:7c75ab2b0567edbb9d4834a2c51e462ebd709740d1f2c40bcd23c56e974fe2a8 424B / 424B 0.0s + => => sha256:981912c48e9a89e903c89b228be977e23eeba83d42e2c8e0593a781a2b251cba 2.31kB / 2.31kB 0.0s + => => sha256:a186900671ab62e1dea364788f4e84c156e1825939914cfb5a6770be2b58b4da 27.36MB / 27.36MB 1.1s + => => extracting sha256:a186900671ab62e1dea364788f4e84c156e1825939914cfb5a6770be2b58b4da 0.5s + => [ 2/14] RUN apt-get update -q=2 && apt-get install -q=2 --yes --no-install-recommends ca-certificates curl 12.5s + => [ 3/14] RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /etc/apt/trust 0.5s + => [ 4/14] RUN apt-get update -q=2 && apt-get install -q=2 --yes --no-install-recommends acpica-tools autoconf 40.0s + => [ 5/14] RUN pip3 install --no-cache-dir poetry 7.4s + => [ 6/14] RUN curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/bin/repo && chmod a+x /usr/bin/repo 0.3s + => [ 7/14] COPY common/install-openssl.sh /tmp/common/ 0.0s + => [ 8/14] RUN bash /tmp/common/install-openssl.sh /opt 32.7s + => [ 9/14] COPY common/install-gcc.sh /tmp/common/ 0.0s + => [10/14] COPY common/install-clang.sh /tmp/common/ 0.0s + => [11/14] RUN bash /tmp/common/install-gcc.sh /opt 13.2.rel1 "arm-none-eabi" 19.8s + => [12/14] RUN bash /tmp/common/install-gcc.sh /opt 13.2.rel1 "aarch64-none-elf" 13.4s + => [13/14] RUN bash /tmp/common/install-clang.sh /opt 15.0.6 101.2s + => [14/14] COPY common/entry.sh /root/entry.sh 0.0s + => exporting to image 9.2s + => => exporting layers 9.2s + => => writing image sha256:3a395c5a0b60248881f9ad06048b97ae3ed4d937ffb0c288ea90097b2319f2b8 0.0s + => => naming to docker.io/library/rdinfra-builder 0.0s +``` + +Verify the docker image build completed successfully: + +```bash +docker images +``` + +You should see a docker image called `rdinfra-builder`: + +```output +REPOSITORY TAG IMAGE ID CREATED SIZE +rdinfra-builder latest 3a395c5a0b60 4 minutes ago 8.12GB +``` + +To quickly test the Docker image you just built, run the following command to enter the docker container interactively: + +```bash +./container.sh -v ~/rdv3 run +``` + +This script mounts your source directory (~/rdv3) into the container and opens a shell session at that location. +Inside the container, you should see a prompt like this: + +```output +Running docker image: rdinfra-builder ... +To run a command as administrator (user "root"), use "sudo ". +See "man sudo_root" for details. + +your-username:hostname:/home/your-username/rdv3$ +``` + +You can explore the container environment if you wish, then type exit to return to the host system. + + +### Step 4: Build Firmware + +Building the full firmware stack involves compiling several components and preparing them for simulation. Rather than running each step manually, you can use a single Docker command to automate the build and package phases. + +- **build**: This phase compiles all individual components of the firmware stack, including TF‑A, SCP, RSE, UEFI, Linux kernel, and rootfs. + +- **package**: This phase consolidates the build outputs into simulation-ready formats and organizes boot artifacts for FVP. + +Ensure you’re back in the host OS, then run the following command: + +```bash +cd ~/rdv3 +docker run --rm \ + -v "$PWD:$PWD" \ + -w "$PWD" \ + --mount type=volume,dst="$HOME" \ + --env ARCADE_USER="$(id -un)" \ + --env ARCADE_UID="$(id -u)" \ + --env ARCADE_GID="$(id -g)" \ + -t -i rdinfra-builder \ + bash -c "./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 build && \ + ./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 package" +``` + +The build artifacts will be placed under `~/rdv3/output/rdv3/rdv3/`, where the last `rdv3` in the directory path corresponds to the selected platform name. + +After a successful build, inspect the artifacts generated under `~/rdv3/output/rdv3/rdv3/` + +```bash +ls ~/rdv3/output/rdv3/rdv3 -al +``` + +The directory contents should look like: +```output +total 7092 +drwxr-xr-x 2 ubuntu ubuntu 4096 Aug 12 13:15 . +drwxr-xr-x 4 ubuntu ubuntu 4096 Aug 12 13:15 .. +lrwxrwxrwx 1 ubuntu ubuntu 25 Aug 12 13:15 Image -> ../components/linux/Image +lrwxrwxrwx 1 ubuntu ubuntu 35 Aug 12 13:15 Image.defconfig -> ../components/linux/Image.defconfig +-rw-r--r-- 1 ubuntu ubuntu 7250838 Aug 12 13:15 fip-uefi.bin +lrwxrwxrwx 1 ubuntu ubuntu 32 Aug 12 13:15 lcp_ramfw.bin -> ../components/rdv3/lcp_ramfw.bin +lrwxrwxrwx 1 ubuntu ubuntu 26 Aug 12 13:15 lkvm -> ../components/kvmtool/lkvm +lrwxrwxrwx 1 ubuntu ubuntu 32 Aug 12 13:15 mcp_ramfw.bin -> ../components/rdv3/mcp_ramfw.bin +lrwxrwxrwx 1 ubuntu ubuntu 26 Aug 12 13:15 rmm.img -> ../components/rdv3/rmm.img +lrwxrwxrwx 1 ubuntu ubuntu 32 Aug 12 13:15 scp_ramfw.bin -> ../components/rdv3/scp_ramfw.bin +lrwxrwxrwx 1 ubuntu ubuntu 29 Aug 12 13:15 tf-bl1.bin -> ../components/rdv3/tf-bl1.bin +lrwxrwxrwx 1 ubuntu ubuntu 29 Aug 12 13:15 tf-bl2.bin -> ../components/rdv3/tf-bl2.bin +lrwxrwxrwx 1 ubuntu ubuntu 30 Aug 12 13:15 tf-bl31.bin -> ../components/rdv3/tf-bl31.bin +lrwxrwxrwx 1 ubuntu ubuntu 53 Aug 12 13:15 tf_m_flash.bin -> ../components/arm/rse/neoverse_rd/rdv3/tf_m_flash.bin +lrwxrwxrwx 1 ubuntu ubuntu 46 Aug 12 13:15 tf_m_rom.bin -> ../components/arm/rse/neoverse_rd/rdv3/rom.bin +lrwxrwxrwx 1 ubuntu ubuntu 48 Aug 12 13:15 tf_m_vm0_0.bin -> ../components/arm/rse/neoverse_rd/rdv3/vm0_0.bin +lrwxrwxrwx 1 ubuntu ubuntu 48 Aug 12 13:15 tf_m_vm1_0.bin -> ../components/arm/rse/neoverse_rd/rdv3/vm1_0.bin +lrwxrwxrwx 1 ubuntu ubuntu 33 Aug 12 13:15 uefi.bin -> ../components/css-common/uefi.bin +``` +Here's a reference of what each file refers to: + +| Component | Output Files | Description | +|----------------------|----------------------------------------------|-----------------------------| +| TF‑A | `bl1.bin`, `bl2.bin`, `bl31.bin`, `fip.bin` | Entry-level boot firmware | +| SCP and RSE firmware | `scp.bin`, `mcp_rom.bin`, etc. | Platform power/control | +| UEFI | `uefi.bin`, `flash0.img` | Boot device enumeration | +| Linux kernel | `Image` | OS payload | +| Initrd | `rootfs.cpio.gz` | Minimal filesystem | + + +### Optional: Run the Build Manually from Inside the Container + +You can also perform the build manually after entering the container: + +Start your docker container. In your running container shell: +```bash +cd ~/rdv3 +./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 build +./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 package +``` + +This manual workflow is useful for debugging, partial builds, or making custom modifications to individual components. + + +You’ve now successfully prepared and built the full RD‑V3 firmware stack. In the next section, you’ll install the appropriate FVP and simulate the full boot sequence, bringing the firmware to life on a virtual platform. diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/4_rdv3_on_fvp.md b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/4_rdv3_on_fvp.md new file mode 100644 index 0000000000..d773322a21 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/4_rdv3_on_fvp.md @@ -0,0 +1,171 @@ +--- +title: Simulate RD‑V3 Boot Flow on Arm FVP +weight: 5 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Simulating RD‑V3 with an Arm FVP + +In the previous section, you built the complete CSS‑V3 firmware stack. +Now, you’ll use Arm Fixed Virtual Platform (FVP) to simulate the system, allowing you to verify the boot sequence without any physical silicon. +This simulation brings up the full stack from BL1 to Linux shell using Buildroot. + +### Step 1: Download and Install the FVP Model + +Before downloading the RD‑V3 FVP, it’s important to understand that each reference design release tag corresponds to a specific version of the FVP model. + +For example, the **RD‑INFRA‑2025.07.03** release tag is designed to work with **FVP version 11.29.35**. + +You can refer to the [RD-V3 Release Tags](https://neoverse-reference-design.docs.arm.com/en/latest/platforms/rdv3.html#release-tags) for a full list of release tags, corresponding FVP versions, and their associated release notes, which summarize changes and validated test cases. + +Download the matching FVP binary for your selected release tag using the link provided: + +```bash +mkdir -p ~/fvp +cd ~/fvp +wget https://developer.arm.com/-/cdn-downloads/permalink/FVPs-Neoverse-Infrastructure/RD-V3/FVP_RD_V3_11.29_35_Linux64_armv8l.tgz + +tar -xvf FVP_RD_V3_11.29_35_Linux64_armv8l.tgz +./FVP_RD_V3.sh +``` + +The FVP installation may prompt you with a few questions,choosing the default options is sufficient for this learning path. By default, the FVP will be installed in `/home/ubuntu/FVP_RD_V3`. + +### Step 2: Remote Desktop Set Up + +The RD‑V3 FVP model launches multiple UART consoles—each mapped to a separate terminal window for different subsystems (e.g., Neoverse V3, Cortex‑M55, Cortex‑M7, panel). + +If you’re accessing the platform over SSH, these UART consoles can still be displayed, but network latency and graphical forwarding can severely degrade performance. + +To interact with different UARTs more efficiently, it is recommend to install a remote desktop environment using `XRDP`. This provides a smoother user experience when dealing with multiple terminal windows and system interactions. + +You will need to install the required packages: + + +```bash +sudo apt update +sudo apt install -y ubuntu-desktop xrdp xfce4 xfce4-goodies pv xterm sshpass socat retry +sudo systemctl enable --now xrdp +``` + +To allow remote desktop connections, you need to open port 3389 (RDP) in your AWS EC2 security group: +- Go to the EC2 Dashboard → Security Groups +- Select the security group associated with your instance +- Under the Inbound rules tab, click Edit inbound rules +- Add the following rule: + - Type: RDP + - Port: 3389 + - Source: your local machine IP + +For better security, limit the source to your current public IP instead of 0.0.0.0/0. + + +***Switch to Xorg (required on Ubuntu 22.04):*** + +Wayland is the default display server on Ubuntu 22.04, but it is not compatible with XRDP. +To enable XRDP remote sessions, you need to switch to Xorg by modifying the GDM configuration. + +Open the `/etc/gdm3/custom.conf` in a text editor. +Find the line: + +```output +#WaylandEnable=false +``` + +Uncomment it by removing the # so it becomes: + +```output +WaylandEnable=false +``` + +Then restart the GDM display manager for the change to take effect: +```bash +sudo systemctl restart gdm3 +``` + +After reboot, XRDP will use Xorg and you should be able to connect to the Arm server via Remote Desktop. + +### Step 3: Launch the Simulation + +Once connected via Remote Desktop, open a terminal and launch the RD‑V3 FVP simulation: + +```bash +cd ~/rdv3/model-scripts/rdinfra +export MODEL=/home/ubuntu/FVP_RD_V3/models/Linux64_armv8l_GCC-9.3/FVP_RD_V3 +./boot-buildroot.sh -p rdv3 & +``` + +The command will launch the simulation and open multiple xterm windows, each corresponding to a different CPU. +You can start by locating the ***terminal_ns_uart0*** window — in it, you should see the GRUB menu. + +From there, select RD-V3 Buildroot in the GRUB menu and press Enter to proceed. +![img3 alt-text#center](rdv3_sim_run.jpg "GRUB Menu") + +Booting Buildroot will take a little while — you’ll see typical Linux boot messages scrolling through. +Eventually, the system will stop at the `Welcome to Buildroot` message on the ***terminal_ns_uart0*** window. + +At the `buildroot login:` prompt, type `root` and press Enter to log in. +![img4 alt-text#center](rdv3_sim_login.jpg "Buildroot login") + +Congratulations — you’ve successfully simulated the boot process of the RD-V3 software you compiled earlier, all on FVP! + +### Step 4: Understand the UART Outputs + +When you launch the RD‑V3 FVP model, it opens multiple terminal windows—each connected to a different UART channel. +These UARTs provide console logs from various firmware components across the system. + +Below is the UART-to-terminal mapping based on the default FVP configuration: + +| Terminal Window Title | UART | Output Role | Connected Processor | +|----------------------------|------|------------------------------------|-----------------------| +| `FVP terminal_ns_uart0` | 0 | Linux Kernel Console (BusyBox) | Neoverse‑V3 (AP) | +| `FVP terminal_ns_uart1` | 1 | TF‑A / UEFI Logs | Neoverse‑V3 (AP) | +| `FVP terminal_uart_scp` | 2 | SCP Firmware Logs (power, clocks) | Cortex‑M7 (SCP) | +| `FVP terminal_rse_uart` | 3 | RSE Secure Boot Logs | Cortex‑M55 (RSE) | +| `FVP terminal_uart_mcp` | 4 | MCP Logs (management, telemetry) | Cortex‑M7 (MCP) | +| `FVP terminal_uart_lcp` | 5 | LCP Logs (per-core power control) | Cortex‑M55 (LCP) | +| `FVP terminal_sec_uart` | 6 | Secure World / TF‑M Logs | Cortex‑M55 | + + +Logs are also captured under `~/rdv3/model-scripts/rdinfra/platforms/rdv3/rdv3`, each UART redirected to its own log file. +You can also explore refinfra-*.txt log files to validate subsystem states. + +For example, if you’d like to verify that each CPU core has its GICv3 redistributor and LPI table correctly initialized, you can refer to the relevant messages in refinfra-24812-uart-0-nsec_.txt. + + +``` +[ 0.000056] Remapping and enabling EFI services. +[ 0.000078] smp: Bringing up secondary CPUs ... +[ 0.000095] Detected PIPT I-cache on CPU1 +[ 0.000096] GICv3: CPU1: found redistributor 10000 region 0:0x0000000030200000 +[ 0.000096] GICv3: CPU1: using allocated LPI pending table @0x0000008080200000 +[ 0.000109] CPU1: Booted secondary processor 0x0000010000 [0x410fd840] +[ 0.000125] Detected PIPT I-cache on CPU2 +[ 0.000126] GICv3: CPU2: found redistributor 20000 region 0:0x0000000030240000 +[ 0.000126] GICv3: CPU2: using allocated LPI pending table @0x0000008080210000 +[ 0.000139] CPU2: Booted secondary processor 0x0000020000 [0x410fd840] +[ 0.000155] Detected PIPT I-cache on CPU3 +[ 0.000156] GICv3: CPU3: found redistributor 30000 region 0:0x0000000030280000 +[ 0.000156] GICv3: CPU3: using allocated LPI pending table @0x0000008080220000 +[ 0.000169] CPU3: Booted secondary processor 0x0000030000 [0x410fd840] +[ 0.000185] Detected PIPT I-cache on CPU4 +[ 0.000186] GICv3: CPU4: found redistributor 40000 region 0:0x00000000302c0000 +[ 0.000186] GICv3: CPU4: using allocated LPI pending table @0x0000008080230000 +[ 0.000199] CPU4: Booted secondary processor 0x0000040000 [0x410fd840] +[ 0.000215] Detected PIPT I-cache on CPU5 +[ 0.000216] GICv3: CPU5: found redistributor 50000 region 0:0x0000000030300000 +[ 0.000216] GICv3: CPU5: using allocated LPI pending table @0x0000008080240000 +[ 0.000229] CPU5: Booted secondary processor 0x0000050000 [0x410fd840] +[ 0.000245] Detected PIPT I-cache on CPU6 +[ 0.000246] GICv3: CPU6: found redistributor 60000 region 0:0x0000000030340000 +[ 0.000246] GICv3: CPU6: using allocated LPI pending table @0x0000008080250000 +[ 0.000259] CPU6: Booted secondary processor 0x0000060000 [0x410fd840] +... + +``` + +You can try to identify the SCP, RSE, and kernel boot logs across their respective terminals. + +Successfully tracing these logs confirms your simulation environment and firmware stack are functioning correctly—all without physical silicon. diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/5_rdv3_modify.md b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/5_rdv3_modify.md new file mode 100644 index 0000000000..ca1d9d1bb6 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/5_rdv3_modify.md @@ -0,0 +1,132 @@ +--- +title: Simulate Dual Chip RD-V3-R1 Platform +weight: 6 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Build and Run RDV3-R1 Dual Chip Platform + +The RD‑V3‑R1 platform is a dual-chip simulation environment built to model multi-die Arm server SoCs. It expands on the single-die RD‑V3 design by introducing a second application processor and a Management Control Processor (MCP). + +***Key Use Cases*** + +- Simulate chiplet-style boot flow with two APs +- Observe coordination between SCP and MCP across dies +- Test secure boot in a distributed firmware environment + +***Differences from RD‑V3*** +- Dual AP boot flow instead of single AP +- Adds MCP (Cortex‑M7) to support cross-die management +- More complex power/reset coordination + +### Step 1: Clone the RD‑V3‑R1 Firmware Stack + +Initialize and sync the codebase for RD‑V3‑R1: + +```bash +cd ~ +mkdir rdv3r1 +cd rdv3r1 +repo init -u https://git.gitlab.arm.com/infra-solutions/reference-design/infra-refdesign-manifests.git -m pinned-rdv3r1.xml -b refs/tags/RD-INFRA-2025.07.03 --depth=1 +repo sync -c -j $(nproc) --fetch-submodules --force-sync --no-clone-bundle +``` + +### Step 2: Install RD-V3-R1 FVP + +Refer to the [RD-V3-R1 Release Tags](https://neoverse-reference-design.docs.arm.com/en/latest/platforms/rdv3.html#release-tags) to determine which FVP model version matches your selected release tag. +Then download and install the corresponding FVP binary. + +```bash +mkdir -p ~/fvp +cd ~/fvp +wget https://developer.arm.com/-/cdn-downloads/permalink/FVPs-Neoverse-Infrastructure/RD-V3-r1/FVP_RD_V3_R1_11.29_35_Linux64_armv8l.tgz +tar -xvf FVP_RD_V3_R1_11.29_35_Linux64_armv8l.tgz +./FVP_RD_V3_R1.sh +``` + +### Step 3: Build the Firmware + +Since you have already created the Docker image for firmware building in a previous section, there is no need to rebuild it for RD‑V3‑R1. + +Run the full firmware build and packaging process: + +```bash +cd ~/rdv3r1 +docker run --rm \ + -v "$PWD:$PWD" \ + -w "$PWD" \ + --mount type=volume,dst="$HOME" \ + --env ARCADE_USER="$(id -un)" \ + --env ARCADE_UID="$(id -u)" \ + --env ARCADE_GID="$(id -g)" \ + -t -i rdinfra-builder \ + bash -c "./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3r1 build && \ + ./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3r1 package" +``` + +### Step 4: Launch the Simulation + +Once connected via Remote Desktop, open a terminal and launch the RD‑V3‑R1 FVP simulation: + +```bash +cd ~/rdv3r1/model-scripts/rdinfra +export MODEL=/home/ubuntu/FVP_RD_V3_R1/models/Linux64_armv8l_GCC-9.3/FVP_RD_V3_R1_R1 +./boot-buildroot.sh -p rdv3r1 & +``` + +This command starts the dual-chip simulation. +You’ll observe additional UART consoles for components like the MCP, and you can verify that both application processors (AP0 and AP1) are brought up in a coordinated manner. + +![img5 alt-text#center](rdv3r1_sim_login.jpg "RDV3 R1 buildroot login") + +Similar to the previous session, the terminal logs are stored in `~/rdv3r1/model-scripts/rdinfra/platforms/rdv3r1/rdv3r1`. + + +### Step 5: Customize Firmware and Confirm MCP Execution + +To wrap up this learning path, let’s verify that your firmware changes can be compiled and simulated successfully within the RD‑V3‑R1 environment. + +Edit the MCP source file `~/rdv3r1/host/scp/framework/src/fwk_module.c` + +Locate the function `fwk_module_start()`. Add the following logging line just before `return FWK_SUCCESS;`: + +```c +int fwk_module_start(void) +{ + ... + FWK_LOG_CRIT("[FWK] Module initialization complete!"); + + // Custom log message for validation + FWK_LOG_CRIT("[FWK] Customer code here"); + return FWK_SUCCESS; +} +``` + +Rebuild and repackage the firmware: + +```bash +cd ~/rdv3r1 +docker run --rm \ + -v "$PWD:$PWD" \ + -w "$PWD" \ + --mount type=volume,dst="$HOME" \ + --env ARCADE_USER="$(id -un)" \ + --env ARCADE_UID="$(id -u)" \ + --env ARCADE_GID="$(id -g)" \ + -t -i rdinfra-builder \ + bash -c "./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3r1 build && \ + ./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3r1 package" +``` + +Launch the FVP simulation again and observe the UART output for MCP. + +![img6 alt-text#center](rdv3r1_sim_codechange.jpg "RDV3 R1 modify firmware") + + +If the change was successful, your custom log line will appear in the MCP console—confirming that your code was integrated and executed as part of the firmware boot process. + +You’ve now successfully simulated a dual-chip Arm server platform using RD‑V3‑R1 on FVP—from cloning firmware sources to modifying secure control logic. + +This foundation sets the stage for deeper exploration, such as customizing platform firmware or integrating BMC workflows in future development cycles. diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/_index.md b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/_index.md new file mode 100644 index 0000000000..170db4c0df --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/_index.md @@ -0,0 +1,60 @@ +--- +title: CSS-V3 Pre-Silicon Software Development Using Neoverse Servers + +draft: true +cascade: + draft: true + +minutes_to_complete: 90 + +who_is_this_for: This Learning Path is for firmware developers, system architects, and silicon validation engineers building Arm Neoverse CSS platforms. It focuses on pre-silicon development using Fixed Virtual Platforms (FVPs) for the CSS‑V3 reference design. You’ll learn how to build, customize, and validate firmware on the RD‑V3 platform using Fixed Virtual Platforms (FVPs) before hardware is available. + +learning_objectives: + - Understand the architecture of Arm Neoverse CSS‑V3 as the foundation for scalable server-class platforms + - Build and boot the RD‑V3 firmware stack using TF‑A, SCP, RSE, and UEFI + - Simulate multi-core, multi-chip systems with Arm FVP models and interpret boot logs + - Modify platform control firmware to test custom logic and validate it via pre-silicon simulation + +prerequisites: + - Access to an Arm Neoverse-based Linux machine (cloud or local), with at least 80 GB of storage + - Familiarity with Linux command-line tools and basic scripting + - Understanding of firmware boot stages and SoC-level architecture + - Docker installed, or GitHub Codespaces-compatible development environment + +author: + - Odin Shen + - Ann Cheng + +### Tags +skilllevels: Advanced +subjects: Containers and Virtualization +armips: + - Neoverse +tools_software_languages: + - C + - Docker + - FVP +peratingsystems: + - Linux + +further_reading: + - resource: + title: Neoverse Compute Subsystems V3 + link: https://www.arm.com/products/neoverse-compute-subsystems/css-v3 + type: website + - resource: + title: Reference Design software stack architecture + link: https://neoverse-reference-design.docs.arm.com/en/latest/about/software_stack.html + type: website + - resource: + title: GitLab infra-refdesign-manifests + link: https://git.gitlab.arm.com/infra-solutions/reference-design/infra-refdesign-manifests + type: gitlab + + +### FIXED, DO NOT MODIFY +# ================================================================================ +weight: 1 # _index.md always has weight of 1 to order correctly +layout: "learningpathall" # All files under learning paths have this same wrapper +learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/_next-steps.md b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/_next-steps.md new file mode 100644 index 0000000000..c3db0de5a2 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/_next-steps.md @@ -0,0 +1,8 @@ +--- +# ================================================================================ +# FIXED, DO NOT MODIFY THIS FILE +# ================================================================================ +weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. +title: "Next Steps" # Always the same, html page title. +layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. +--- diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdf_single_chip.png b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdf_single_chip.png new file mode 100644 index 0000000000..85937be535 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdf_single_chip.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdinfra_sw_stack.jpg b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdinfra_sw_stack.jpg new file mode 100644 index 0000000000..780c21f291 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdinfra_sw_stack.jpg differ diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3_sim_login.jpg b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3_sim_login.jpg new file mode 100644 index 0000000000..0bfc8474fc Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3_sim_login.jpg differ diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3_sim_run.jpg b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3_sim_run.jpg new file mode 100644 index 0000000000..0178bb8228 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3_sim_run.jpg differ diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3r1_sim_codechange.jpg b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3r1_sim_codechange.jpg new file mode 100644 index 0000000000..3278620e94 Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3r1_sim_codechange.jpg differ diff --git a/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3r1_sim_login.jpg b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3r1_sim_login.jpg new file mode 100644 index 0000000000..610e5ac73d Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/rdv3r1_sim_login.jpg differ diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/1_setup.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/1_setup.md index 737df21707..907cb17e68 100644 --- a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/1_setup.md +++ b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/1_setup.md @@ -1,5 +1,5 @@ --- -title: Tomcat benchmark set up +title: Set up Tomcat weight: 2 ### FIXED, DO NOT MODIFY @@ -9,16 +9,16 @@ layout: learningpathall ## Overview -There are numerouse client-server and network-based workloads, and Tomcat is a typical example of such applications, which provide services via HTTP/HTTPS network requests. +There are numerous client-server and network-based workloads, with Tomcat being a typical example of such applications. Tomcat provides services via HTTP/HTTPS network requests. -In this section, you'll set up a benchmark environment using Apache Tomcat and `wrk2` to simulate HTTP load and evaluate performance on an Arm-based bare-metal (**__`Nvidia-Grace`__**). +In this section, you will set up a benchmark environment using `Apache Tomcat` and `wrk2` to simulate an HTTP load and evaluate performance on an Arm-based bare metal instance. This Learning Path was tested on an AWS `c8g.metal-48xl` instance. -## Set up the Tomcat benchmark server on **Nvidia Grace** +## Set up the Tomcat benchmark server [Apache Tomcat](https://tomcat.apache.org/) is an open-source Java Servlet container that runs Java web applications, handles HTTP requests, and serves dynamic content. It supports technologies such as Servlet, JSP, and WebSocket. ## Install the Java Development Kit (JDK) -Install OpenJDK 21 on your Arm-based Ubuntu 24 bare-metal: +Install OpenJDK 21 on your Arm-based Ubuntu 24.04 bare-metal instance: ```bash sudo apt update @@ -30,8 +30,8 @@ sudo apt install -y openjdk-21-jdk Download and extract Tomcat: ```bash -wget -c https://dlcdn.apache.org/tomcat/tomcat-11/v11.0.9/bin/apache-tomcat-11.0.9.tar.gz -tar xzf apache-tomcat-11.0.9.tar.gz +wget -c https://dlcdn.apache.org/tomcat/tomcat-11/v11.0.10/bin/apache-tomcat-11.0.10.tar.gz +tar xzf apache-tomcat-11.0.10.tar.gz ``` Alternatively, you can build Tomcat [from source](https://github.com/apache/tomcat). @@ -41,16 +41,19 @@ To access the built-in examples from your local network or external IP, use a te The file is at: ```bash -apache-tomcat-11.0.9/webapps/examples/META-INF/context.xml +~/apache-tomcat-11.0.10/webapps/examples/META-INF/context.xml ``` +Replace the existing allow value as shown: ```xml - +``` - +With: +```xml ``` +Save the changes to your file. ## Start the Tomcat server {{% notice Note %}} @@ -60,17 +63,17 @@ To achieve maximum performance of Tomcat, the maximum number of file descriptors Start the server: ```bash -ulimit -n 65535 && ./apache-tomcat-11.0.9/bin/startup.sh +ulimit -n 65535 && ~/apache-tomcat-11.0.10/bin/startup.sh ``` You should see output like: ```output -Using CATALINA_BASE: /home/ubuntu/apache-tomcat-11.0.9 -Using CATALINA_HOME: /home/ubuntu/apache-tomcat-11.0.9 -Using CATALINA_TMPDIR: /home/ubuntu/apache-tomcat-11.0.9/temp +Using CATALINA_BASE: /home/ubuntu/apache-tomcat-11.0.10 +Using CATALINA_HOME: /home/ubuntu/apache-tomcat-11.0.10 +Using CATALINA_TMPDIR: /home/ubuntu/apache-tomcat-11.0.10/temp Using JRE_HOME: /usr -Using CLASSPATH: /home/ubuntu/apache-tomcat-11.0.9/bin/bootstrap.jar:/home/ubuntu/apache-tomcat-11.0.9/bin/tomcat-juli.jar +Using CLASSPATH: /home/ubuntu/apache-tomcat-11.0.10/bin/bootstrap.jar:/home/ubuntu/apache-tomcat-11.0.10/bin/tomcat-juli.jar Using CATALINA_OPTS: Tomcat started. ``` @@ -91,7 +94,7 @@ You should see the Tomcat welcome page and examples, as shown below: [Wrk2](https://github.com/giltene/wrk2) is a high-performance HTTP benchmarking tool specialized in generating constant throughput loads and measuring latency percentiles for web services. `wrk2` is an enhanced version of `wrk` that provides accurate latency statistics under controlled request rates, ideal for performance testing of HTTP servers. {{% notice Note %}} -Currently `wrk2` is only supported on x86 machines. Run the benchmark client steps below on an `x86_64` server running Ubuntu 24. +Currently `wrk2` is only supported on x86 machines. Run the benchmark client steps below on a bare metal `x86_64` server running Ubuntu 24.04 {{% /notice %}} ## Install dependencies @@ -132,28 +135,28 @@ ulimit -n 65535 && wrk -c32 -t16 -R50000 -d60 http://${tomcat_ip}:8080/examples/ You should see output similar to: ```console -Running 1m test @ http://172.26.203.139:8080/examples/servlets/servlet/HelloWorldExample +Running 1m test @ http://172.31.46.193:8080/examples/servlets/servlet/HelloWorldExample 16 threads and 32 connections - Thread calibration: mean lat.: 0.986ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.984ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.999ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.994ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.983ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.989ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.991ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.993ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.985ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.990ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.987ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.990ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.984ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.991ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.978ms, rate sampling interval: 10ms - Thread calibration: mean lat.: 0.976ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.381ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.626ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.020ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.578ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.166ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.275ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.454ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.655ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.334ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.089ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.365ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.382ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.342ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.349ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.023ms, rate sampling interval: 10ms + Thread calibration: mean lat.: 3.275ms, rate sampling interval: 10ms Thread Stats Avg Stdev Max +/- Stdev - Latency 1.00ms 454.90us 5.09ms 63.98% - Req/Sec 3.31k 241.68 4.89k 63.83% - 2999817 requests in 1.00m, 1.56GB read -Requests/sec: 49997.08 + Latency 1.02ms 398.88us 4.24ms 66.77% + Req/Sec 3.30k 210.16 4.44k 70.04% + 2999776 requests in 1.00m, 1.56GB read +Requests/sec: 49996.87 Transfer/sec: 26.57MB ``` diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/2_baseline.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/2_baseline.md index 970ee2e10a..b0701374ad 100644 --- a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/2_baseline.md +++ b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/2_baseline.md @@ -1,80 +1,116 @@ --- -title: Optimal baseline before tuning +title: Establish baseline performance weight: 3 ### FIXED, DO NOT MODIFY layout: learningpathall --- +In this section you will start by setting up a baseline configuration before using advanced techniques to tune the performance of network workloads. + {{% notice Note %}} To achieve maximum performance, ulimit -n 65535 must be executed on both server and client! {{% /notice %}} -## Optimal baseline before tuning -- Baseline on Grace bare-metal (default configuration) -- Baseline on Grace bare-metal (access logging disabled) -- Baseline on Grace bare-metal (optimal thread count) +## Optimal baseline configuration before tuning +This includes: +- Aligning the IOMMU settings with default Ubuntu settings +- Setting up a default configuration +- Disabling access logging +- Setting up an optimal thread count + +### Align the IOMMU settings with default Ubuntu settings -### Baseline on Grace bare-metal (default configuration) {{% notice Note %}} -To align with the typical deployment scenario of Tomcat, reserve 8 cores online and set all other cores offline +As you are using a custom Ubuntu distribution on AWS, you will first need to align the IOMMU settings with default Ubuntu settings for IOMMU: iommu.strict=1 and iommu.passthrough=0. {{% /notice %}} -1. You can offline the CPU cores using the below command. +1. To change the IOMMU settings, use a text editor to modify the `grub` file by adding or updating the `GRUB_CMDLINE_LINUX` configuration: + ```bash -for no in {8..143}; do sudo bash -c "echo 0 > /sys/devices/system/cpu/cpu${no}/online"; done +sudo vi /etc/default/grub ``` -2. Use the following commands to verify that cores 0-7 are online and the remaining cores are offline. +Depending on what's in your `grub` file you will need to add or update `GRUB_CMDLINE_LINUX`: ```bash -lscpu +GRUB_CMDLINE_LINUX="iommu.strict=1 iommu.passthrough=0" ``` -You can check the following information: + +2. Update GRUB and reboot your system to apply the default settings. ```bash -Architecture: aarch64 - CPU op-mode(s): 64-bit - Byte Order: Little Endian -CPU(s): 144 - On-line CPU(s) list: 0-7 - Off-line CPU(s) list: 8-143 -Vendor ID: ARM - Model name: Neoverse-V2 +sudo update-grub && sudo reboot +``` + +3. Verify that the default settings have been successfully applied: +```bash +sudo dmesg | grep iommu +``` +You should see that under the default configuration, `iommu.strict` is enabled, and `iommu.passthrough` is disabled: +```output +[ 0.877401] iommu: Default domain type: Translated (set via kernel command line) +[ 0.877404] iommu: DMA domain TLB invalidation policy: strict mode (set via kernel command line) ... ``` -3. Use the following command on the Grace bare-metal where `Tomcat` is on +### Establish a baseline configuration on Arm Neoverse bare-metal instances + +{{% notice Note %}} +To align with typical deployment scenario of Tomcat, you will need to reserve 8 cores on your instance to be online and set all other cores to be offline +{{% /notice %}} + +1. To set the remaining CPU cores on your instance to be offline, run: ```bash -~/apache-tomcat-11.0.9/bin/shutdown.sh 2>/dev/null -ulimit -n 65535 && ~/apache-tomcat-11.0.9/bin/startup.sh +for no in {8..191}; do sudo bash -c "echo 0 > /sys/devices/system/cpu/cpu${no}/online"; done +``` +2. Use the following commands to verify that cores 0-7 are online and the remaining cores are offline. +```bash +lscpu +``` +The output should look like: +```output +Architecture: aarch64 + CPU op-mode(s): 64-bit + Byte Order: Little Endian +CPU(s): 192 + On-line CPU(s) list: 0-7 + Off-line CPU(s) list: 8-191 +Vendor ID: ARM + Model name: Neoverse-V2 +... ``` -4. And use the following command on the `x86_64` bare-metal where `wrk2` is on +3. Now shutdown and restart `Tomcat` on your Arm Neoverse bare-metal instance as shown: ```bash -tomcat_ip=10.169.226.181 +~/apache-tomcat-11.0.10/bin/shutdown.sh 2>/dev/null +ulimit -n 65535 && ~/apache-tomcat-11.0.10/bin/startup.sh ``` + +4. On your `x86_64` bare-metal instance, run `wrk2` as shown: + ```bash ulimit -n 65535 && wrk -c1280 -t128 -R500000 -d60 http://${tomcat_ip}:8080/examples/servlets/servlet/HelloWorldExample ``` +Replace `{tomcat_ip}` in the command above with the IP address of your Arm-based instance where the Tomcat server is running. -The result of default configuration is: -```bash +The result with this baseline configuration should look like: +```output Thread Stats Avg Stdev Max +/- Stdev - Latency 13.29s 3.25s 19.07s 57.79% - Req/Sec 347.59 430.94 0.97k 66.67% - 3035300 requests in 1.00m, 1.58GB read - Socket errors: connect 1280, read 0, write 0, timeout 21760 -Requests/sec: 50517.09 -Transfer/sec: 26.84MB + Latency 16.76s 6.59s 27.56s 56.98% + Req/Sec 1.97k 165.05 2.33k 89.90% + 14680146 requests in 1.00m, 7.62GB read + Socket errors: connect 1264, read 0, write 0, timeout 1748 +Requests/sec: 244449.62 +Transfer/sec: 129.90MB ``` -### Baseline on Grace bare-metal (access logging disabled) -To disable the access logging, use a text editor to modify the `server.xml` file by commenting out or removing the **`org.apache.catalina.valves.AccessLogValve`** configuration. +### Disable Access logging +To disable access logging, use a text editor to modify the `server.xml` file by commenting out or removing the **`org.apache.catalina.valves.AccessLogValve`** configuration. The file is at: ```bash -vi ~/apache-tomcat-11.0.9/conf/server.xml +vi ~/apache-tomcat-11.0.10/conf/server.xml ``` -The configuratin is at the end of the file, and common out or remove it. +Either comment out or delete the configuration shown at the end of the file: ```xml ``` -1. Use the following command on the Grace bare-metal where `Tomcat` is on +1. Shutdown and restart `Tomcat` on your Arm Neoverse bare-metal instance as shown: ```bash -~/apache-tomcat-11.0.9/bin/shutdown.sh 2>/dev/null -ulimit -n 65535 && ~/apache-tomcat-11.0.9/bin/startup.sh +~/apache-tomcat-11.0.10/bin/shutdown.sh 2>/dev/null +ulimit -n 65535 && ~/apache-tomcat-11.0.10/bin/startup.sh ``` -2. And use the following command on the `x86_64` bare-metal where `wrk2` is on +2. Run `wrk2` on the `x86_64` bare-metal instance: ```bash ulimit -n 65535 && wrk -c1280 -t128 -R500000 -d60 http://${tomcat_ip}:8080/examples/servlets/servlet/HelloWorldExample ``` -The result of access logging disabled is: +The result with access logging disabled should look like: ```bash Thread Stats Avg Stdev Max +/- Stdev - Latency 12.66s 3.05s 17.87s 57.47% - Req/Sec 433.69 524.91 1.18k 66.67% - 3572200 requests in 1.00m, 1.85GB read - Socket errors: connect 1280, read 0, write 0, timeout 21760 -Requests/sec: 59451.85 -Transfer/sec: 31.59MB + Latency 16.16s 6.45s 28.26s 57.85% + Req/Sec 2.16k 5.91 2.17k 77.50% + 16291136 requests in 1.00m, 8.45GB read + Socket errors: connect 0, read 0, write 0, timeout 75 +Requests/sec: 271675.12 +Transfer/sec: 144.36MB ``` -### Baseline on Grace bare-metal (optimal thread count) +### Set up optimal thread counts To minimize resource contention between threads and overhead from thread context switching, the number of CPU-intensive threads in Tomcat should be aligned with the number of CPU cores. -1. When using `wrk` to perform pressure testing on `Tomcat`: +1. When using `wrk` to perform pressure testing on `Tomcat`, use `top` to identify the CPU-intensive threads : ```bash top -H -p$(pgrep java) ``` -You can see the below information +The output from `top` will look like: ```bash -top - 12:12:45 up 1 day, 7:04, 5 users, load average: 7.22, 3.46, 1.75 -Threads: 79 total, 8 running, 71 sleeping, 0 stopped, 0 zombie -%Cpu(s): 3.4 us, 1.9 sy, 0.0 ni, 94.1 id, 0.0 wa, 0.0 hi, 0.5 si, 0.0 st -MiB Mem : 964975.5 total, 602205.6 free, 12189.5 used, 356708.3 buff/cache -MiB Swap: 0.0 total, 0.0 free, 0.0 used. 952786.0 avail Mem +top - 08:57:29 up 20 min, 1 user, load average: 4.17, 2.35, 1.22 +Threads: 231 total, 8 running, 223 sleeping, 0 stopped, 0 zombie +%Cpu(s): 31.7 us, 20.2 sy, 0.0 ni, 31.0 id, 0.0 wa, 0.0 hi, 17.2 si, 0.0 st +MiB Mem : 386127.8 total, 380676.0 free, 4040.7 used, 2801.1 buff/cache +MiB Swap: 0.0 total, 0.0 free, 0.0 used. 382087.0 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND - 53254 yinyu01 20 0 38.0g 1.4g 28288 R 96.7 0.1 2:30.70 http-nio-8080-e - 53255 yinyu01 20 0 38.0g 1.4g 28288 R 96.7 0.1 2:30.62 http-nio-8080-e - 53256 yinyu01 20 0 38.0g 1.4g 28288 R 96.7 0.1 2:30.64 http-nio-8080-e - 53258 yinyu01 20 0 38.0g 1.4g 28288 R 96.7 0.1 2:30.62 http-nio-8080-e - 53260 yinyu01 20 0 38.0g 1.4g 28288 R 96.7 0.1 2:30.69 http-nio-8080-e - 53257 yinyu01 20 0 38.0g 1.4g 28288 R 96.3 0.1 2:30.59 http-nio-8080-e - 53259 yinyu01 20 0 38.0g 1.4g 28288 R 96.3 0.1 2:30.63 http-nio-8080-e - 53309 yinyu01 20 0 38.0g 1.4g 28288 R 95.3 0.1 2:29.69 http-nio-8080-P - 53231 yinyu01 20 0 38.0g 1.4g 28288 S 0.3 0.1 0:00.10 VM Thread - 53262 yinyu01 20 0 38.0g 1.4g 28288 S 0.3 0.1 0:00.12 GC Thread#2 + 4677 ubuntu 20 0 36.0g 1.4g 24452 R 89.0 0.4 1:18.71 http-nio-8080-P + 4685 ubuntu 20 0 36.0g 1.4g 24452 R 4.7 0.4 0:04.42 http-nio-8080-A + 4893 ubuntu 20 0 36.0g 1.4g 24452 S 3.3 0.4 0:00.60 http-nio-8080-e + 4963 ubuntu 20 0 36.0g 1.4g 24452 S 3.3 0.4 0:00.66 http-nio-8080-e + 4924 ubuntu 20 0 36.0g 1.4g 24452 S 3.0 0.4 0:00.59 http-nio-8080-e + 4955 ubuntu 20 0 36.0g 1.4g 24452 S 3.0 0.4 0:00.60 http-nio-8080-e + 5061 ubuntu 20 0 36.0g 1.4g 24452 S 3.0 0.4 0:00.61 http-nio-8080-e + 4895 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.58 http-nio-8080-e + 4907 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.59 http-nio-8080-e + 4940 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.58 http-nio-8080-e + 4946 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.59 http-nio-8080-e + 4956 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.65 http-nio-8080-e + 4959 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.59 http-nio-8080-e + 4960 ubuntu 20 0 36.0g 1.4g 24452 R 2.7 0.4 0:00.60 http-nio-8080-e + 4962 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.57 http-nio-8080-e + 4982 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.63 http-nio-8080-e + 4983 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.58 http-nio-8080-e + 4996 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.60 http-nio-8080-e + 5033 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.59 http-nio-8080-e + 5036 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.66 http-nio-8080-e + 5056 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.61 http-nio-8080-e + 5065 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.56 http-nio-8080-e + 5068 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.61 http-nio-8080-e + 5070 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.60 http-nio-8080-e + 5071 ubuntu 20 0 36.0g 1.4g 24452 S 2.7 0.4 0:00.61 http-nio-8080-e +... ``` -It can be observed that **`http-nio-8080-e`** and **`http-nio-8080-P`** threads are CPU-intensive. -Since the __`http-nio-8080-P`__ thread is fixed at 1 in current version of Tomcat, and the current number of CPU cores is 8, the http-nio-8080-e thread count should be configured to 7. +You can observe from the output that **`http-nio-8080-e`** and **`http-nio-8080-P`** threads are CPU-intensive. +As the __`http-nio-8080-P`__ thread is fixed at 1 in current version of Tomcat, and the current number of CPU cores is 8, the `http-nio-8080-e` thread count should be configured to 7. -To configure the `http-nio-8080-e` thread count, use a text editor to modify the `context.xml` file by updating the ` ``` +With the updated setting: + ```xml ``` -2. Use the following command on the Grace bare-metal where `Tomcat` is on +Save the changes to `server.xml`. + +2. Now shutdown and restart `Tomcat` on your Arm Neoverse bare-metal instance as shown: ```bash -~/apache-tomcat-11.0.9/bin/shutdown.sh 2>/dev/null -ulimit -n 65535 && ~/apache-tomcat-11.0.9/bin/startup.sh +~/apache-tomcat-11.0.10/bin/shutdown.sh 2>/dev/null +ulimit -n 65535 && ~/apache-tomcat-11.0.10/bin/startup.sh ``` -3. And use the following command on the `x86_64` bare-metal where `wrk2` is on +3. Run `wrk2` on the`x86_64` bare-metal instance: ```bash ulimit -n 65535 && wrk -c1280 -t128 -R500000 -d60 http://${tomcat_ip}:8080/examples/servlets/servlet/HelloWorldExample ``` -The result of optimal thread count is: -```bash +The result with the optimal thread count settings should look like: +```output Thread Stats Avg Stdev Max +/- Stdev - Latency 24.34s 9.91s 41.81s 57.77% - Req/Sec 1.22k 4.29 1.23k 71.09% - 9255672 requests in 1.00m, 4.80GB read -Requests/sec: 154479.07 -Transfer/sec: 82.06MB + Latency 10.26s 4.55s 19.81s 62.51% + Req/Sec 2.86k 89.49 3.51k 77.06% + 21458421 requests in 1.00m, 11.13GB read +Requests/sec: 357835.75 +Transfer/sec: 190.08MB ``` + +Now that you have established some baseline settings you can proceed to further tuning your setup. diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/3_nic-queue.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/3_nic-queue.md index a2ead0e5fc..4aa434ddbd 100644 --- a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/3_nic-queue.md +++ b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/3_nic-queue.md @@ -7,10 +7,9 @@ layout: learningpathall --- ## Tuning via NIC queue count -- Setting NIC queue count -- The result after tuning NIC queue count +To further optmize your settings, you can set the NIC queue count and observe the performance uplift: -Typically, the number of transmit/receive queues for network cards in bare-metal environments is relatively large, reaching 63 on Grace. Each transmit/receive queue corresponds to one interrupt number. Before CPU cores are taken offline, there are sufficient cores to handle these interrupt numbers. However, when only 8 cores are retained, it results in a single core having to handle multiple interrupt numbers, thereby triggering more context switches. +Typically, the number of transmit/receive queues for network cards in bare-metal environments is relatively large, reaching 63 on Arm Neoverse. Each transmit/receive queue corresponds to one interrupt number. Before CPU cores are taken offline, there are sufficient cores to handle these interrupt numbers. However, when only 8 cores are retained, it results in a single core having to handle multiple interrupt numbers, thereby triggering more context switches. ### Setting NIC queue count @@ -18,19 +17,19 @@ Typically, the number of transmit/receive queues for network cards in bare-metal ```bash ip addr ``` -It can be observed that the NIC name `enp1s0f0np0` corresponsed to the IP address `10.169.226.181`. -```bash +From the output you can see that the NIC name `enp1s0f0np0` corresponds to the IP address `10.169.226.181`. +```output 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever -2: enp1s0f0np0: mtu 1500 qdisc mq state UP group default qlen 1000 - link/ether b8:e9:24:67:d5:3a brd ff:ff:ff:ff:ff:ff - inet 10.169.226.181/24 brd 10.169.226.255 scope global enp1s0f0np0 - valid_lft forever preferred_lft forever - inet6 fe80::bae9:24ff:fe67:d53a/64 scope link +2: enP11p4s0: mtu 9001 qdisc mq state UP group default qlen 1000 + link/ether 0e:cc:0b:ff:f6:57 brd ff:ff:ff:ff:ff:ff + inet 172.31.46.193/20 metric 100 brd 172.31.47.255 scope global dynamic enP11p4s0 + valid_lft 1938sec preferred_lft 1938sec + inet6 fe80::ccc:bff:feff:f657/64 scope link valid_lft forever preferred_lft forever ``` @@ -45,17 +44,17 @@ sudo ethtool -l ${net} ``` It can be observed that the number of transmit/receive queues for the ${net} network interface is currently 63. ```bash -Channel parameters for enp1s0f0np0: +Channel parameters for enP11p4s0: Pre-set maximums: RX: n/a TX: n/a Other: n/a -Combined: 63 +Combined: 32 Current hardware settings: RX: n/a TX: n/a Other: n/a -Combined: 63 +Combined: 32 ``` 4. Use the following command to reset the number of transmit/receive queues for the ${net} to match the number of CPUs, which is 8. @@ -66,14 +65,14 @@ sudo ethtool -L ${net} combined 8 ```bash sudo ethtool -l ${net} ``` -It can be observed that the number of combined Rx/Tx queues has been updated to 8. -```bash -Channel parameters for enp1s0f0np0: +You should see that the number of combined Rx/Tx queues has been updated to 8. +```output +Channel parameters for enP11p4s0: Pre-set maximums: RX: n/a TX: n/a Other: n/a -Combined: 63 +Combined: 32 Current hardware settings: RX: n/a TX: n/a @@ -81,25 +80,25 @@ Other: n/a Combined: 8 ``` -### The result after tuning NIC queue count +### The performance uplift after tuning NIC queue count -1. Use the following command on the Grace bare-metal where `Tomcat` is on +1. Shutdown and restart `Tomcat` on your Arm Neoverse bare-metal instance as shown: ```bash -~/apache-tomcat-11.0.9/bin/shutdown.sh 2>/dev/null -ulimit -n 65535 && ~/apache-tomcat-11.0.9/bin/startup.sh +~/apache-tomcat-11.0.10/bin/shutdown.sh 2>/dev/null +ulimit -n 65535 && ~/apache-tomcat-11.0.10/bin/startup.sh ``` -2. And use the following command on the `x86_64` bare-metal where `wrk2` is on +2. Run `wrk2` on your `x86_64` bare-metal instance: ```bash ulimit -n 65535 && wrk -c1280 -t128 -R500000 -d60 http://${tomcat_ip}:8080/examples/servlets/servlet/HelloWorldExample ``` -The result after NIC queue count tuned: -```bash +Notice the performance uplift after tuning the NIC queue count: +```output Thread Stats Avg Stdev Max +/- Stdev - Latency 21.64s 8.71s 37.22s 57.82% - Req/Sec 1.53k 5.70 1.55k 77.15% - 11562557 requests in 1.00m, 6.00GB read -Requests/sec: 192932.92 -Transfer/sec: 102.49MB + Latency 8.35s 4.14s 16.33s 61.16% + Req/Sec 2.96k 73.02 3.24k 89.16% + 22712999 requests in 1.00m, 11.78GB read +Requests/sec: 378782.37 +Transfer/sec: 201.21MB ``` diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/4_local-numa.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/4_local-numa.md new file mode 100644 index 0000000000..de7a370226 --- /dev/null +++ b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/4_local-numa.md @@ -0,0 +1,95 @@ +--- +title: NUMA-based Tuning +weight: 5 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Tuning via local (Non-Uniform Memory Access) NUMA +In this section you will learn how to configure local NUMA and assess performance uplift acheieved through tuning. + +Typically, cross-NUMA data transfers within the CPU incur higher latency than intra-NUMA transfers. Therefore, Tomcat should be deployed on the NUMA node where the network interface resides. + +### Setting local NUMA + +1. Use the following command to check that the latency for cross-NUMA transfers is greater than the latency for intra-NUMA transfers: +```bash +numactl -H +``` + +It can be observed that the cross-NUMA latency to intra-NUMA latency ratio is 10:100. +```output +available: 2 nodes (0-1) +node 0 cpus: 0 1 2 3 4 5 6 7 +node 0 size: 193502 MB +node 0 free: 188478 MB +node 1 cpus: +node 1 size: 192625 MB +node 1 free: 192338 MB +node distances: +node 0 1 + 0: 10 100 + 1: 100 10 +``` + +2. Use the following command to check the NUMA node where the ${net} network interface resides. +```bash +cat /sys/class/net/${net}/device/numa_node +``` +You will notice that the NUMA node where the ${net} network interface resides is 1. +```output +1 +``` + +3. As a result, allocate the reserved 8 cores to NUMA node 1. +```bash +for no in {96..103}; do sudo bash -c "echo 1 > /sys/devices/system/cpu/cpu${no}/online"; done +for no in {0..95} {104..191}; do sudo bash -c "echo 0 > /sys/devices/system/cpu/cpu${no}/online"; done +``` + +4. Verify whether the settings have been successfully applied. +```bash +lscpu +``` + +From the output you will see that the only online CPUs are 72-79 on NUMA node 1. +```bash +Architecture: aarch64 + CPU op-mode(s): 64-bit + Byte Order: Little Endian +CPU(s): 192 + On-line CPU(s) list: 96-103 + Off-line CPU(s) list: 0-95,104-191 +Vendor ID: ARM + Model name: Neoverse-V2 +... +NUMA: + NUMA node(s): 2 + NUMA node0 CPU(s): + NUMA node1 CPU(s): 96-103 +... +``` + +### The result after tuning local NUMA + +1. Shutdown and start Tomcat on the Arm Neoverse bare-metal instance: +```bash +~/apache-tomcat-11.0.10/bin/shutdown.sh 2>/dev/null +ulimit -n 65535 && ~/apache-tomcat-11.0.10/bin/startup.sh +``` + +2. Run `wrk2` on the `x86_64` bare-metal instance: +```bash +ulimit -n 65535 && wrk -c1280 -t128 -R500000 -d60 http://${tomcat_ip}:8080/examples/servlets/servlet/HelloWorldExample +``` + +The result after configuring NUMA node should look like: +```output + Thread Stats Avg Stdev Max +/- Stdev + Latency 9.41s 4.71s 18.02s 61.07% + Req/Sec 2.84k 76.55 3.06k 72.37% + 21814220 requests in 1.00m, 11.32GB read +Requests/sec: 363744.39 +Transfer/sec: 193.22MB +``` diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/4_local-numa1.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/4_local-numa1.md deleted file mode 100644 index f657d11456..0000000000 --- a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/4_local-numa1.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Tuning via local NUMA -weight: 5 - -### FIXED, DO NOT MODIFY -layout: learningpathall ---- - -## Tuning via local NUMA -- Setting local NUMA -- The result after tuning local NUMA - -Typically, cross-NUMA data transfers within the CPU incur higher latency than intra-NUMA transfers. Therefore, Tomcat should be deployed on the NUMA node where the network interface resides. - -### Setting local NUMA - -1. Use the following command to check that the latency for cross-NUMA transfers is greater than the latency for intra-NUMA transfers. -```bash -numactl -H -``` - -It can be observed that the cross-NUMA latency to intra-NUMA latency ratio is 10:40. -```bash -available: 2 nodes (0-1) -node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 -node 0 size: 483129 MB -node 0 free: 462395 MB -node 1 cpus: 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 -node 1 size: 481845 MB -node 1 free: 472013 MB -node distances: -node 0 1 - 0: 10 40 - 1: 40 10 -``` - -2. Use the following command to check the NUMA node where the ${net} network interface resides. -```bash -cat /sys/class/net/${net}/device/numa_node -``` -It can be observed that the NUMA node where the ${net} network interface resides is 1. -```bash -1 -``` - -3. Therefore, allocate the reserved 8 cores to NUMA node 1. -```bash -for no in {72..79}; do sudo bash -c "echo 1 > /sys/devices/system/cpu/cpu${no}/online"; done -for no in {0..71} {80..143}; do sudo bash -c "echo 0 > /sys/devices/system/cpu/cpu${no}/online"; done -``` - -4. Verify whether the settings have been successfully applied. -```bash -lscpu -``` - -It can be observed that the only online CPUs are 72-79 on NUMA node 1. -```bash -Architecture: aarch64 - CPU op-mode(s): 64-bit - Byte Order: Little Endian -CPU(s): 144 - On-line CPU(s) list: 72-79 - Off-line CPU(s) list: 0-71,80-143 -Vendor ID: ARM - Model name: Neoverse-V2 -... -NUMA: - NUMA node(s): 2 - NUMA node0 CPU(s): - NUMA node1 CPU(s): 72-79 -... -``` - -### The result after tuning local NUMA - -1. Use the following command on the Grace bare-metal where `Tomcat` is on -```bash -~/apache-tomcat-11.0.9/bin/shutdown.sh 2>/dev/null -ulimit -n 65535 && ~/apache-tomcat-11.0.9/bin/startup.sh -``` - -2. And use the following command on the `x86_64` bare-metal where `wrk2` is on -```bash -ulimit -n 65535 && wrk -c1280 -t128 -R500000 -d60 http://${tomcat_ip}:8080/examples/servlets/servlet/HelloWorldExample -``` - -The result after NUMA node tuned: -```bash - Thread Stats Avg Stdev Max +/- Stdev - Latency 18.72s 7.76s 33.78s 57.93% - Req/Sec 1.87k 59.38 2.08k 58.75% - 14111369 requests in 1.00m, 7.32GB read - Socket errors: connect 0, read 0, write 0, timeout 64 -Requests/sec: 235505.32 -Transfer/sec: 125.10MB -``` diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/5_iommu.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/5_iommu.md index 7de6c80961..af6b695888 100644 --- a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/5_iommu.md +++ b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/5_iommu.md @@ -1,76 +1,66 @@ --- -title: Tuning via iommu +title: IOMMU-based tuning weight: 6 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Tuning via iommu -- Setting iommu -- The result after tuning iommu +## IOMMU-based tuning +IOMMU (Input-Output Memory Management Unit) is a hardware feature that manages how I/O devices access memory. +In cloud environments, SmartNICs are typically used to offload the IOMMU workload. On bare-metal systems, to align performance with the cloud, you should disable `iommu.strict` and enable `iommu.passthrough` settings to achieve better performance. -In cloud environments, SmartNICs are typically used to offload the IOMMU workload. On bare-metal systems, to align performance with the cloud, you should disable iommu.strict and enable iommu.passthrough. +### Setting IOMMU -### Setting iommu - -1. Use the following command to verify the default IOMMU status on the bare-metal -```bash -sudo dmesg | grep iommu -``` -It can be observed that under the default configuration, iommu.strict is enabled, and iommu.passthrough is disabled. -```bash -[ 11.558455] iommu: Default domain type: Translated -[ 11.563355] iommu: DMA domain TLB invalidation policy: strict mode -``` - -2. To set IOMMU status, use a text editor to modify the `grub` file by adding or updating the `GRUB_CMDLINE_LINUX` configuration. +1. To configure the IOMMU setting, use a text editor to modify the `grub` file by adding or updating the `GRUB_CMDLINE_LINUX` configuration. ```bash sudo vi /etc/default/grub ``` -then add or update +then add or update: ```bash GRUB_CMDLINE_LINUX="iommu.strict=0 iommu.passthrough=1" ``` -3. Update GRUB and reboot to apply the settings. +2. Update GRUB and reboot to apply the settings. ```bash -sudo update-grub -sudo reboot +sudo update-grub && sudo reboot ``` -4. Verify whether the settings have been successfully applied. +3. Verify if the settings have been successfully applied: ```bash sudo dmesg | grep iommu ``` -It can be observed that the IOMMU is already in passthrough mode. +You will notice that the IOMMU is already in passthrough mode: ```bash -[ 0.000000] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-6.8.0-71-generic root=UUID=a9adbbfa-892b-473d-906f-8bc0250bf544 ro iommu.strict=0 iommu.passthrough=1 -[ 11.565539] iommu: Default domain type: Passthrough (set via kernel command line) +[ 0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-6.14.0-1011-aws root=PARTUUID=1c3f3c20-db6b-497c-8727-f6702f73a5b2 ro iommu.strict=0 iommu.passthrough=1 console=tty1 console=ttyS0 nvme_core.io_timeout=4294967295 panic=-1 +[ 0.855658] iommu: Default domain type: Passthrough (set via kernel command line) ``` -### The result after tuning local NUMA +### The result after configuring IOMMU -1. Use the following command on the Grace bare-metal where `Tomcat` is on +1. Run the following command on the Arm Neoverse bare-metal where `Tomcat` is on: ```bash -~/apache-tomcat-11.0.9/bin/shutdown.sh 2>/dev/null -ulimit -n 65535 && ~/apache-tomcat-11.0.9/bin/startup.sh +for no in {96..103}; do sudo bash -c "echo 1 > /sys/devices/system/cpu/cpu${no}/online"; done +for no in {0..95} {104..191}; do sudo bash -c "echo 0 > /sys/devices/system/cpu/cpu${no}/online"; done +net=$(ls /sys/class/net/ | grep 'en') +sudo ethtool -L ${net} combined 8 +~/apache-tomcat-11.0.10/bin/shutdown.sh 2>/dev/null +ulimit -n 65535 && ~/apache-tomcat-11.0.10/bin/startup.sh ``` -2. And use the following command on the `x86_64` bare-metal where `wrk2` is on +2. Run run `wrk2` on the `x86_64` bare-metal instance as shown: ```bash ulimit -n 65535 && wrk -c1280 -t128 -R500000 -d60 http://${tomcat_ip}:8080/examples/servlets/servlet/HelloWorldExample ``` -The result after iommu tuned: -```bash +The result after iommu tuning should look like: +```output Thread Stats Avg Stdev Max +/- Stdev - Latency 10.52s 4.83s 22.43s 61.31% - Req/Sec 2.75k 67.27 2.97k 70.85% - 20917980 requests in 1.00m, 10.85GB read - Socket errors: connect 0, read 0, write 0, timeout 16 -Requests/sec: 349085.30 -Transfer/sec: 185.43MB + Latency 4.92s 2.49s 10.08s 62.27% + Req/Sec 3.36k 56.23 3.58k 69.64% + 25703668 requests in 1.00m, 13.33GB read +Requests/sec: 428628.50 +Transfer/sec: 227.69MB ``` diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/6_summary.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/6_summary.md index 5fecaf9bf1..0a5decc13c 100644 --- a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/6_summary.md +++ b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/6_summary.md @@ -7,13 +7,14 @@ layout: learningpathall --- ## Summary -It can be observed that each step of the tuning method can bring significant performance improvements to Tomcat. **Similarly, these methods are equally applicable to other network-based workloads.** +You will observe that each tuning method can bring significant performance improvements while running Tomcat as shown in the results summary below: | Method | Requests/sec | Latency-Avg | |:----------------|:-------------|:------------| -| default | 154479.07 | 24.34s | -| NIC-Rx/Tx-Queue | 192932.92 | 21.64s | -| NUMA-local | 235505.32 | 18.72s | -| IOMMU | 349085.30 | 10.52s | +| Baseline | 357835.75 | 10.26s | +| NIC-Queue | 378782.37 | 8.35s | +| NUMA-Local | 363744.39 | 9.41s | +| IOMMU | 428628.50 | 4.92s | +The same tuning methods can be applied as general guidance to help optimize and tune other network-based workloads. diff --git a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/_index.md b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/_index.md index 843fbcc314..e50b10a75b 100644 --- a/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/_index.md +++ b/content/learning-paths/servers-and-cloud-computing/tune-network-workloads-on-bare-metal/_index.md @@ -1,32 +1,27 @@ --- -title: Tune network workloads on Arm bare-metal - -draft: true -cascade: - draft: true +title: Tune network workloads on Arm-based bare metal instances minutes_to_complete: 60 -who_is_this_for: This is an advanced topic for engineers who want to tune the performance of network workloads on Arm Neoverse-based bare-metal. +who_is_this_for: This is an advanced topic for engineers who want to tune the performance of network workloads on Arm Neoverse-based bare-metal instances. learning_objectives: - Set up a benchmarking environment using Tomcat and wrk2 - - Baseline of optimal performance configuration before tuning - - Tune network workloads performance with NIC queue + - Set up a baseline performance configuration before tuning + - Tune network workloads performance using NIC queues - Tune network workloads performance with local NUMA - - Tune network workloads performance with iommu.strict and iommu.passthrough + - Tune network workloads performance with IOMMU prerequisites: - - Access to an Arm-based bare-metal running Ubuntu-24 (you can use a Grace) (for Tomcat) - - Access to a x86-based bare-metal running Ubuntu-24 (you can use an any x86_64 bare-metal) (for wrk2) + - An Arm Neoverse-based bare-metal server running Ubuntu 24.04 to run Tomcat. This Learning Path was tested with an AWS c8g.metal-48xl instance + - Access to a x86_64 bare-metal server running Ubuntu 24.04 to run wrk2 - Basic familiarity with Java applications - - Basic familiarity with computer system, network communication, etc. author: Ying Yu, Ker Liu, Rui Chang ### Tags skilllevels: Advanced -subjects: Performance tuning +subjects: Performance and Architecture armips: - Neoverse tools_software_languages: @@ -44,6 +39,10 @@ further_reading: link: https://wiki.openjdk.org/ type: documentation + - resource: + title: Apache Tomcat documentation + link: https://tomcat.apache.org/tomcat-11.0-doc/index.html + type: documentation ### FIXED, DO NOT MODIFY diff --git a/data/stats_current_test_info.yml b/data/stats_current_test_info.yml index 784f2c1c93..38e4eef117 100644 --- a/data/stats_current_test_info.yml +++ b/data/stats_current_test_info.yml @@ -1,7 +1,7 @@ summary: - content_total: 401 + content_total: 405 content_with_all_tests_passing: 0 - content_with_tests_enabled: 62 + content_with_tests_enabled: 61 sw_categories: automotive: {} cross-platform: @@ -100,9 +100,6 @@ sw_categories: kubectl: readable_title: Kubectl tests_and_status: [] - llm-jetson-xavier: - readable_title: AWS CLI - tests_and_status: [] multipass: readable_title: Multipass tests_and_status: [] diff --git a/data/stats_weekly_data.yml b/data/stats_weekly_data.yml index 1b86054d52..0c72e162fc 100644 --- a/data/stats_weekly_data.yml +++ b/data/stats_weekly_data.yml @@ -7375,3 +7375,126 @@ avg_close_time_hrs: 0 num_issues: 23 percent_closed_vs_total: 0.0 +- a_date: '2025-08-25' + content: + automotive: 3 + cross-platform: 34 + embedded-and-microcontrollers: 45 + install-guides: 105 + iot: 6 + laptops-and-desktops: 39 + mobile-graphics-and-gaming: 37 + servers-and-cloud-computing: 136 + total: 405 + contributions: + external: 99 + internal: 530 + github_engagement: + num_forks: 30 + num_prs: 15 + individual_authors: + adnan-alsinan: 2 + alaaeddine-chakroun: 2 + albin-bernhardsson: 1 + albin-bernhardsson,-julie-gaskin: 1 + alex-su: 1 + alexandros-lamprineas: 1 + andrew-choi: 2 + andrew-kilroy: 1 + annie-tallund: 6 + arm: 3 + arnaud-de-grandmaison: 6 + aryan-bhusari: 1 + aude-vuilliomenet: 1 + avin-zarlez: 1 + barbara-corriero: 1 + basma-el-gaabouri: 1 + ben-clark: 1 + bolt-liu: 2 + brenda-strech: 1 + bright-edudzi-gershon-kordorwu: 1 + chaodong-gong: 1 + chen-zhang: 1 + chenying-kuo: 1 + christophe-favergeon: 1 + christopher-seidl: 7 + cyril-rohr: 1 + daniel-gubay: 1 + daniel-nguyen: 2 + david-spickett: 2 + dawid-borycki: 33 + diego-russo: 2 + dominica-abena-o.-amanfo: 1 + elham-harirpoush: 2 + fidel-makatia-omusilibwa: 1 + florent-lebeau: 5 + "fr\xE9d\xE9ric--lefred--descamps": 2 + gabriel-peterson: 5 + gayathri-narayana-yegna-narayanan: 2 + georgios-mermigkis: 1 + geremy-cohen: 3 + gian-marco-iodice: 1 + graham-woodward: 1 + han-yin: 1 + iago-calvo-lista: 1 + james-whitaker: 1 + jason-andrews: 107 + jeff-young: 1 + joana-cruz: 1 + joe-stech: 7 + johanna-skinnider: 2 + jonathan-davies: 2 + jose-emilio-munoz-lopez: 1 + julie-gaskin: 5 + julien-jayat: 1 + julien-simon: 2 + julio-suarez: 6 + jun-he: 1 + kasper-mecklenburg: 1 + kieran-hejmadi: 12 + koki-mitsunami: 2 + konstantinos-margaritis: 8 + kristof-beyls: 1 + leandro-nunes: 1 + liliya-wu: 1 + mark-thurman: 1 + martin-ma: 1 + masoud-koleini: 1 + mathias-brossard: 1 + michael-hall: 5 + na-li: 1 + nader-zouaoui: 2 + nikhil-gupta: 1 + nina-drozd: 1 + nobel-chowdary-mandepudi: 6 + odin-shen: 9 + owen-wu: 2 + pareena-verma: 48 + paul-howard: 3 + peter-harris: 1 + pranay-bakre: 5 + preema-merlin-dsouza: 1 + przemyslaw-wirkus: 2 + qixiang-xu: 1 + rani-chowdary-mandepudi: 1 + rin-dobrescu: 1 + roberto-lopez-mendez: 2 + ronan-synnott: 45 + shuheng-deng: 1 + thirdai: 1 + tianyu-li: 2 + tom-pilar: 1 + uma-ramalingam: 1 + varun-chari: 2 + visualsilicon: 1 + waheed-brown: 1 + willen-yang: 1 + william-liang: 1 + ying-yu: 3 + yiyang-fan: 1 + zach-lasiuk: 2 + zhengjun-xing: 2 + issues: + avg_close_time_hrs: 0 + num_issues: 25 + percent_closed_vs_total: 0.0 diff --git a/tools/profanity.py b/tools/profanity.py index 39c495bee1..bab7323ec5 100644 --- a/tools/profanity.py +++ b/tools/profanity.py @@ -8,6 +8,7 @@ def load_excluded_words(file_path): def scan_for_profanities(directory, log_file, excluded_words_file=None): exclude_words = None + profanities = None if excluded_words_file: exclude_words = load_excluded_words(excluded_words_file) @@ -17,23 +18,21 @@ def scan_for_profanities(directory, log_file, excluded_words_file=None): if file.endswith('.md'): # Read only markdown files file_path = os.path.join(root, file) with open(file_path, 'r') as code_file: + profanities = None content = code_file.read() if exclude_words: excluded_content = content for word in exclude_words: excluded_content = excluded_content.replace(word, '') if profanity.contains_profanity(excluded_content): - f.write(f"Profanity found in file: {file_path}\n") - f.write("Profanities found: ") profanities = set(word for word in excluded_content.split() if profanity.contains_profanity(word)) - f.write(", ".join(profanities)) - f.write("\n\n") else: if profanity.contains_profanity(content): - f.write(f"Profanity found in file: {file_path}\n") - f.write("Profanities found: ") profanities = set(word for word in content.split() if profanity.contains_profanity(word)) - f.write(", ".join(profanities)) - f.write("\n\n") + if profanities: + f.write(f"Profanity found in file: {file_path}\n") + f.write("Profanities found: ") + f.write(", ".join(profanities)) + f.write("\n\n") -scan_for_profanities("./content/", "./profanity_log.txt", excluded_words_file="./.profanity_ignore.yml") +scan_for_profanities("./content/", "./profanity_log.txt", excluded_words_file="./.profanity_ignore.yml") \ No newline at end of file diff --git a/tools/verify_index_fields.py b/tools/verify_index_fields.py new file mode 100644 index 0000000000..58808669a4 --- /dev/null +++ b/tools/verify_index_fields.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 + +import sys +import yaml +import os +import re + +ALLOWLIST_FILE = "tools/closed-filters-allow-list.yml" +REQUIRED_FIELDS = [ + "title", "minutes_to_complete", "who_is_this_for", "learning_objectives", + "prerequisites", "author", "skilllevels", "subjects", "armips", "tools_software_languages", + "operatingsystems", "further_reading", "weight", "layout", "learning_path_main_page" +] +VALID_SKILLLEVELS = {"Introductory", "Advanced"} + +def load_allowlist(): + with open(ALLOWLIST_FILE, 'r') as f: + data = yaml.safe_load(f) + + flat_subjects = set() + for _, subjects in data.get('subjects', {}).items(): + flat_subjects.update(subjects) + + return { + "subjects_by_category": data.get("subjects", {}), + "flat_subjects": flat_subjects, + "operatingsystems": set(data.get("operatingsystems", [])), + "cloud_service_providers": set(data.get("cloud_service_providers", [])), + } + +def extract_frontmatter(path): + with open(path, 'r') as f: + content = f.read() + if not content.startswith('---'): + return None + parts = content.split('---', 2) + if len(parts) < 3: + return None + return yaml.safe_load(parts[1]) + +def get_category_from_path(path): + match = re.match(r"content/learning-paths/([^/]+)/", path) + return match.group(1) if match else None + +import os + +def is_valid_index_path(path): + norm_path = os.path.normpath(path) + parts = norm_path.split(os.sep) + + try: + lp_index = parts.index("learning-paths") + # Ensure path is: .../learning-paths///_index.md + return ( + parts[-1] == "_index.md" and + len(parts) == lp_index + 4 # learning-paths + category + tutorial + _index.md + ) + except ValueError: + return False + +def validate_file(path, allowlist): + if not is_valid_index_path(path): + print(f"Skipping {path} as it is not a learning path index file.") + return + + data = extract_frontmatter(path) + if not data: + print(f"❌ Invalid or missing YAML frontmatter: {path}") + return True + + errors = [] + # Check for required fields + for field in REQUIRED_FIELDS: + if field not in data: + errors.append(f"Missing required field: {field}") + + # Validate skilllevels + skill = data.get("skilllevels") + if skill and skill not in VALID_SKILLLEVELS: + errors.append(f"Invalid skilllevels: {skill}. Please choose from {', '.join(VALID_SKILLLEVELS)}") + + # Validate subjects + subject = data.get("subjects") + if subject and subject not in allowlist["flat_subjects"]: + errors.append(f"Invalid subjects: {subject}.") + + # Validate OS if present + osys = data.get("operatingsystems", []) + if isinstance(osys, list): + for os_entry in osys: + if os_entry not in allowlist["operatingsystems"]: + errors.append(f"Invalid operatingsystem: {os_entry}. Please choose from {', '.join(allowlist['operatingsystems'])}") + + # Validate subject/category mapping + category = get_category_from_path(path) + if category and subject: + category_subjects = allowlist["subjects_by_category"].get(category) + if category_subjects and subject not in category_subjects: + errors.append(f"Subject '{subject}' not allowed for category '{category}'. Please choose from {', '.join(category_subjects)}") + + if errors: + print(f"❌ Validation errors in {path}:") + for e in errors: + print(f" - {e}") + return True + + print(f"✅ {path} fields are verified.") + return False + +if __name__ == "__main__": + files = sys.argv[1:] + allowlist = load_allowlist() + any_errors = False + + for f in files: + if "content/" in f and f.endswith("_index.md") and os.path.exists(f): + if validate_file(f, allowlist): + any_errors = True + + if any_errors: + sys.exit(1) \ No newline at end of file