diff --git a/.github/workflows/build-and-release.yaml b/.github/workflows/build-and-release.yaml index bb65780f..9326b061 100644 --- a/.github/workflows/build-and-release.yaml +++ b/.github/workflows/build-and-release.yaml @@ -39,7 +39,7 @@ on: default: false env: - BENV_IMAGE: public.ecr.aws/u7d6c4a3/solarwinds-opentelemetry-network:benv-exp + BENV_IMAGE: public.ecr.aws/u7d6c4a3/solarwinds-opentelemetry-network:buil-env-buildx DOCKER_REGISTRY: docker.io DOCKER_NAMESPACE: solarwinds IMAGE_PREFIX: "opentelemetry-ebpf-" @@ -88,6 +88,10 @@ jobs: echo "full_version_number = ${full_version_number}" echo "github_tag = ${github_tag}" + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Fetch build environment run: | @@ -100,6 +104,7 @@ jobs: --mount "type=bind,source=$GITHUB_WORKSPACE/src,destination=/root/src,readonly" \ --mount "type=bind,source=$GITHUB_WORKSPACE/out,destination=/root/out" \ --env EBPF_NET_SRC_ROOT=/root/src \ + --env ENABLE_ARM64_BUILD=TRUE \ $BENV_IMAGE \ ./build.sh pipeline-docker - name: Build packages @@ -108,6 +113,7 @@ jobs: --mount "type=bind,source=$GITHUB_WORKSPACE/src,destination=/root/src,readonly" \ --mount "type=bind,source=$GITHUB_WORKSPACE/out,destination=/root/out" \ --env EBPF_NET_SRC_ROOT=/root/src \ + --env ENABLE_ARM64_BUILD=TRUE \ --workdir /root/out \ $BENV_IMAGE \ cpack -G 'RPM;DEB' @@ -170,12 +176,32 @@ jobs: image_name="${IMAGE_PREFIX}${image}" image_path="${docker_registry}/${DOCKER_NAMESPACE}/${image_name}" + docker tag "${image}" ${image_path}:v${full_version_number}-amd64 + docker tag "${image}-arm64" ${image_path}:v${full_version_number}-arm64 + + if [[ "${{ inputs.dry_run }}" == "false" ]]; + then + docker push ${image_path}:v${full_version_number}-arm64 + docker push ${image_path}:v${full_version_number}-amd64 + else + echo "Would run: docker push ${image_path}:v${full_version_number}-{arm64,amd64}" + fi + for tag in ${tags[@]}; do - docker tag $image ${image_path}:${tag} + manifest_cmd="docker manifest create ${image_path}:${tag}" + manifest_cmd="${manifest_cmd} --amend ${image_path}:v${full_version_number}-arm64" + manifest_cmd="${manifest_cmd} --amend ${image_path}:v${full_version_number}-amd64" + + if [[ "${{ inputs.dry_run }}" == "false" ]]; then - docker push ${image_path}:${tag} + eval $manifest_cmd + docker manifest push ${image_path}:${tag} + else + echo "Would run: $manifest_cmd" + echo "Would run: docker manifest push ${image_path}:${tag}" fi done + done - docker images --no-trunc + docker images --no-trunc \ No newline at end of file diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index b22d57ea..72274b24 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -7,7 +7,7 @@ on: pull_request: env: - BENV_IMAGE: public.ecr.aws/u7d6c4a3/solarwinds-opentelemetry-network:benv-exp + BENV_IMAGE: public.ecr.aws/u7d6c4a3/solarwinds-opentelemetry-network:buil-env-buildx concurrency: group: build-and-test-${{ github.event.pull_request_number || github.ref }} diff --git a/cmake/docker-utils.cmake b/cmake/docker-utils.cmake index f7d1e897..6c35504d 100644 --- a/cmake/docker-utils.cmake +++ b/cmake/docker-utils.cmake @@ -147,6 +147,14 @@ function(build_custom_docker_image IMAGE_NAME) ) endforeach() + # Get the value of the environment variable ENABLE_ARM64_BUILD + if (DEFINED ENV{ENABLE_ARM64_BUILD} AND "$ENV{ENABLE_ARM64_BUILD}" STREQUAL "TRUE") + set(ENABLE_ARM64_BUILD TRUE) + else() + set(ENABLE_ARM64_BUILD FALSE) + endif() + + if (RUN_DOCKER_COMMANDS) add_custom_command( TARGET @@ -154,10 +162,22 @@ function(build_custom_docker_image IMAGE_NAME) WORKING_DIRECTORY "${out_path}" COMMAND - docker build -t "${IMAGE_NAME}" ${DOCKER_ARGS} . + docker buildx build --platform linux/amd64 -t "${IMAGE_NAME}" ${DOCKER_ARGS} . + ) + if (ENABLE_ARM64_BUILD) + add_custom_command( + TARGET + "${IMAGE_NAME}-docker" + WORKING_DIRECTORY + "${out_path}" + COMMAND + docker buildx build --platform linux/arm64 -t "${IMAGE_NAME}-arm64" ${DOCKER_ARGS} . ) + endif() endif() + + ########################### # push to docker registry # ########################### diff --git a/platform/generic.h b/platform/generic.h index 28814359..66597d1f 100644 --- a/platform/generic.h +++ b/platform/generic.h @@ -67,9 +67,17 @@ typedef FILE fp_outfile; /* compiler-gcc.h */ #ifdef __GNUC__ #define barrier() __asm__ __volatile__("" : : : "memory") + +#ifdef __aarch64__ +#define mb() asm volatile("dmb ish" : : : "memory") +#define rmb() asm volatile("dmb ishld" : : : "memory") +#define wmb() asm volatile("dmb ishst" : : : "memory") +#else #define mb() asm volatile("mfence" : : : "memory") #define rmb() asm volatile("lfence" : : : "memory") #define wmb() asm volatile("sfence" : : : "memory") +#endif + #define read_barrier_depends() \ do { \ } while (0) diff --git a/platform/userspace-time.h b/platform/userspace-time.h index 9b01e586..dff1381d 100644 --- a/platform/userspace-time.h +++ b/platform/userspace-time.h @@ -38,11 +38,21 @@ static inline __attribute__((always_inline)) u64 monotonic() return (u64)ts.tv_sec * (1000 * 1000 * 1000) + ts.tv_nsec; } +// For ARM64 +#ifdef __aarch64__ +static inline __attribute__((always_inline)) uint64_t fp_monotonic_time_ns(void) { + uint64_t cntvct; + asm volatile("mrs %0, cntvct_el0" : "=r" (cntvct)); + return cntvct; +} + +// For x86 +#else #include -static inline __attribute__((always_inline)) u64 fp_monotonic_time_ns(void) -{ +static inline __attribute__((always_inline)) uint64_t fp_monotonic_time_ns(void) { return __rdtsc(); } +#endif #ifdef __cplusplus } diff --git a/util/time.h b/util/time.h index 2e298b5a..c00d26d6 100644 --- a/util/time.h +++ b/util/time.h @@ -147,7 +147,9 @@ struct monotonic_clock { } }; +#ifndef __aarch64__ #include +#endif /** * Monotonic, std::chrono compatible clock using `__rdtsc()` as the backend. */ @@ -159,5 +161,13 @@ struct rdtsc_clock { using duration = std::chrono::duration; using time_point = std::chrono::time_point; +#ifdef __aarch64__ + static inline __attribute__((always_inline)) time_point now() { + uint64_t cntvct; + asm volatile ("mrs %0, cntvct_el0; " : "=r"(cntvct) :: "memory"); + return time_point{duration{cntvct}}; + } +#else static inline __attribute__((always_inline)) time_point now() { return time_point{duration{__rdtsc()}}; } +#endif };