diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile new file mode 100644 index 00000000000000..aa00e3ed88db18 --- /dev/null +++ b/.github/workflows/Dockerfile @@ -0,0 +1,37 @@ +FROM alpine:3.20.3 + +ARG MODE= +ADD vmlinux /root/. +ADD inittab /etc/inittab +RUN mkdir /etc/init.d +ADD rcS /etc/init.d/. +RUN sed "s/\'/\"/g" /etc/profile > /.profile + +ADD bench.sh / +ADD iperf3.sh /root/ +ADD iperf3.static /root/ +ADD do_getpid /root/. +ADD clone /root/. +ADD futex /root/. +ADD nullptr /root/. +ADD ctest /root/. +ADD stackp /root/. +ADD init_array /root/. +ADD entropy /root/. +ADD locale /root/. +ADD vdso_test /root/. +ADD Makefile /root/. +ADD lmbench2/ /lmbench2 +ADD lmbench_run.sh /lmbench2/bin/x86_64-linux-gnulibc1/ + + +RUN apk update && apk add utmps-libs libtirpc curl make iperf3 + +RUN if [[ ${MODE} == "um-nommu" ]]; then mkdir -p setup && cd setup && curl -L -o output.zip \ + 'https://gitlab.alpinelinux.org/thehajime/aports/-/jobs/1619053/artifacts/download?file_type=archive' \ + && unzip output.zip ; fi +RUN if [[ ${MODE} == "um-nommu" ]]; then apk add --allow-untrusted \ + setup/packages/main/x86_64/busybox-nommu-1.36.1-r29.apk \ + setup/packages/main/x86_64/musl-nommu-1.2.5-r0.apk && rm -rf setup; fi + +ENTRYPOINT ["/root/vmlinux", "vec0:transport=tap,ifname=tap100,depth=128,gro=1", "root=/dev/root", "rootflags=/", "rootfstype=hostfs", "rw", "mem=1024m", "loglevel=0", "init=/sbin/init"] diff --git a/.github/workflows/Makefile b/.github/workflows/Makefile new file mode 100644 index 00000000000000..9459fde01e0723 --- /dev/null +++ b/.github/workflows/Makefile @@ -0,0 +1,25 @@ +SRCS := clone.c futex.c nullptr.c ctest.c stackp.c do_getpid.c init_array.c entropy.c locale.c vdso_test.c +BKUP := exit.c noop.c +TARGETS := $(SRCS:.c=) + +CFLAGS_exit = -nostdlib -pie -fPIE -fomit-frame-pointer +all: ${TARGETS} + +tests: ${TARGETS} + set +x + ./clone host + ./futex + ./nullptr 1 0 || RET=$$? ; echo "code="$$RET && if [ "$$RET" -ne "139" ] ; then false ; fi + ./nullptr 1 1 || RET=$$? ; echo "code="$$RET && if [ "$$RET" -ne "11" ] ; then false ; fi + ./nullptr 0 0 || RET=$$? ; echo "code="$$RET && if [ "$$RET" -ne "139" ] ; then false ; fi + ./nullptr 0 1 || RET=$$? ; echo "code="$$RET && if [ "$$RET" -ne "11" ] ; then false ; fi + ./nullptr + echo "test" | ./ctest + ./stackp + ./entropy 10000 + ./locale + ./vdso_test -c 10000 + set -x + +clean: + rm -f ${TARGETS} diff --git a/.github/workflows/bench.sh b/.github/workflows/bench.sh new file mode 100755 index 00000000000000..015d3f1d9d2d73 --- /dev/null +++ b/.github/workflows/bench.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +mount proc /proc -t proc +export PATH=/home:/sbin:/usr/sbin:/bin:/usr/bin + + +cd /lmbench2/bin/x86_64-linux-gnulibc1 +sh lmbench_run.sh + +/root/do_getpid -c 10000 + +make -C /root tests +halt -f diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000000..e27162b5603a86 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,343 @@ +on: + push: + branches: + - '**' + #pull_request: + # branches: + # - master + workflow_dispatch: + inputs: + debug_enabled: + description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + required: false + default: true + +jobs: + tests: + runs-on: ${{ matrix.runs_on }} + strategy: + fail-fast: false + matrix: + include: + - displayTargetName: ubuntu-22.04 + os: unix + runs_on: ubuntu-22.04 + shell: bash + defconfig: defconfig + add_configs: CONFIG_UML_NET_VECTOR=y CFLAGS+="-DCONFIG_UML_NET_VECTOR" + testname: um-mmu + - displayTargetName: ubuntu-22.04 (nommu) + os: unix + runs_on: ubuntu-22.04 + shell: bash + defconfig: x86_64_nommu_defconfig + add_configs: CONFIG_UML_NET_VECTOR=y CFLAGS+="-DCONFIG_UML_NET_VECTOR" + kunit_opts: --kconfig_add CONFIG_MMU=n + testname: um-nommu + timeout-minutes: 100 + env: + CCACHE_DIR: ${{ github.workspace }}/.ccache + USE_CCACHE: 1 + + defaults: + run: + shell: ${{ matrix.shell }} + + steps: + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} + with: + detached: true + - name: Set env + shell: bash + run: | + echo "/usr/lib/ccache/bin:/usr/lib/ccache:${{ github.workspace }}/bin" >> $GITHUB_PATH + echo "export PATH=/usr/lib/ccache/bin:/usr/lib/ccache:${{ github.workspace }}/bin:$PATH" >> $HOME/.bashrc + - name: Checkout + uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ runner.os }}-${{ matrix.defconfig }}-ccache-build-${{ github.sha }} + restore-keys: ${{ runner.os }}-${{ matrix.defconfig }}-ccache-build- + - name: Install packages + run: | + sudo apt update -y + sudo apt install -y ccache iperf3 + - name: Setup latest Alpine Linux + uses: jirutka/setup-alpine@v1 + with: + branch: v3.20 + packages: > + alpine-sdk + doas + libtirpc-dev + linux-headers + - name: build bench tools + run: | + git clone https://github.com/ricarkol/lmbench2.git + cd lmbench2 + touch src/Makefile + touch Makefile + make + cd .. + make -C .github/workflows/ + shell: alpine.sh {0} + # --root {0} + - name: Setup faketty + uses: Yuri6037/Action-FakeTTY@v1.1 + - name: setup tap interface + run: | + set -x + sudo ip tuntap add dev tap100 mode tap user ${USER} + sudo ip add add 192.168.122.1/24 dev tap100 + sudo ip link set up dev tap100 + iperf3 -s & + - name: build-0 (static) + run: | + make ARCH=um ${{ matrix.defconfig }} O=build + cat build/.config | sed "s/.*CONFIG_STATIC_LINK.*/CONFIG_STATIC_LINK=y/" > /tmp/a; mv /tmp/a build/.config + make -j8 ARCH=um O=build ${{ matrix.add_configs }} + - name: prep for docker build + run: | + cp build/vmlinux .github/workflows/ + cp -rpf lmbench2 .github/workflows/ + - name: Build and push Docker image (no push) + uses: docker/build-push-action@v6 + with: + context: .github/workflows + build-args: "MODE=${{ matrix.testname }}" + push: false + tags: | + ghcr.io/thehajime/alpine:3.20.3-${{ matrix.testname }} + - name: image for test + run: | + docker create --name alpine-nommu ghcr.io/thehajime/alpine:3.20.3-${{ matrix.testname }} + docker start alpine-nommu + docker wait alpine-nommu + docker logs alpine-nommu + docker export alpine-nommu > alpine.tar + docker rm alpine-nommu + mnt=$(mktemp -d) + dd if=/dev/zero of=alpine.ext4 bs=1 count=0 seek=1G + sudo chmod og+wr "alpine.ext4" + yes 2>/dev/null | mkfs.ext4 "alpine.ext4" || true + sudo mount "alpine.ext4" $mnt + sudo tar -xf alpine.tar -C $mnt + sudo umount $mnt + mkdir -p rootfs + sudo tar -xf alpine.tar -C rootfs + sudo chown -R ${USER} rootfs + - name: test-0 (static) + run: | + sudo sh -c "echo 0 > /proc/sys/vm/mmap_min_addr" + faketty ./build/vmlinux vec0:transport=tap,ifname=tap100,depth=128,gro=1 ubd0=./alpine.ext4 rw mem=1024m loglevel=8 console=tty init=/sbin/init 2>&1 | tee /tmp/log.txt & + sleep 10 && pkill vmlinux + echo "=========" + cat /tmp/log.txt + - name: kunit test + run: | + for config in `find ./ -name .kunitconfig | grep -v -E "kfence|sunrpc|handshake|kcsan|gpu|damon" `; do \ + echo "==" $config "==" ; \ + ./tools/testing/kunit/kunit.py run --kunitconfig=$config ${{ matrix.kunit_opts }} + done + - name: build-1 + run: | + make ARCH=um ${{ matrix.defconfig }} + make -j8 ARCH=um ${{ matrix.add_configs }} + - name: test-1 + run: | + faketty ./vmlinux vec0:transport=tap,ifname=tap100,depth=128,gro=1 ubd0=./alpine.ext4 rw mem=1024m loglevel=8 init=/sbin/init 2>&1 | tee /tmp/log.txt & + sleep 10 && pkill vmlinux + echo "=========" + cat /tmp/log.txt + - name: benchmark-0 + if: matrix.testname == 'um-nommu' + run: | + mkdir -p output + ## disable zpoline test for a while + faketty ./vmlinux ubd0=./alpine.ext4 rw mem=1024m loglevel=8 console=tty zpoline=1 init=/bench.sh \ + | tee output/${{ matrix.testname }}-zpoline.dat || true # XXX: until 6.12 pulled + faketty ./vmlinux ubd0=./alpine.ext4 rw mem=1024m loglevel=8 console=tty zpoline=0 init=/bench.sh \ + | tee output/${{ matrix.testname }}-seccomp.dat || true # XXX: until 6.12 pulled + - name: benchmark-1 + if: matrix.testname == 'um-mmu' + run: | + mkdir -p output + faketty ./vmlinux ubd0=./alpine.ext4 rw mem=1024m loglevel=0 console=tty init=/bench.sh \ + | tee output/${{ matrix.testname }}.dat + - name: benchmark-2-iperf3 + run: | + mkdir -p output + if [ "${{ matrix.testname }}" == "um-nommu" ] ; then + faketty ./vmlinux vec0:transport=tap,ifname=tap100,depth=128,gro=1 mem=1024m \ + root=/dev/root rootflags=`pwd`/rootfs rootfstype=hostfs rw \ + loglevel=0 console=tty init=/root/iperf3.sh \ + | tee output/${{ matrix.testname }}-seccomp-iperf3.dat + faketty ./vmlinux vec0:transport=tap,ifname=tap100,depth=128,gro=1 mem=1024m \ + root=/dev/root rootflags=`pwd`/rootfs rootfstype=hostfs rw \ + loglevel=0 console=tty zpoline=1 init=/root/iperf3.sh \ + | tee output/${{ matrix.testname }}-zpoline-iperf3.dat + else + faketty ./vmlinux vec0:transport=tap,ifname=tap100,depth=128,gro=1 mem=1024m \ + root=/dev/root rootflags=`pwd`/rootfs rootfstype=hostfs rw \ + loglevel=0 console=tty init=/root/iperf3.sh \ + | tee output/${{ matrix.testname }}-iperf3.dat + fi + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver-opts: network=host + - name: Log in to the ghcr.io + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: .github/workflows + build-args: "MODE=${{ matrix.testname }}" + push: true + tags: | + ghcr.io/thehajime/alpine:3.20.3-${{ matrix.testname }} + - uses: actions/upload-artifact@v4 + with: + name: bench-result-${{ matrix.testname }} + path: output/${{ matrix.testname }}* + + checkpatch: + runs-on: ubuntu-22.04 + name: checkpatch and co + env: + CCACHE_DIR: ${{ github.workspace }}/.ccache + USE_CCACHE: 1 + steps: + - name: Set env + shell: bash + run: | + echo "/usr/lib/ccache/bin:/usr/lib/ccache:${{ github.workspace }}/bin" >> $GITHUB_PATH + echo "export PATH=/usr/lib/ccache/bin:/usr/lib/ccache:${{ github.workspace }}/bin:$PATH" >> $HOME/.bashrc + - name: Checkout + with: + fetch-depth: 0 + uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ runner.os }}-checkpatch-ccache-build-${{ github.sha }} + restore-keys: ${{ runner.os }}-checkpatch-ccache-build- + - name: Install packages + run: | + sudo pip install ply GitPython mypy + sudo apt update -y + sudo apt install -y aspell ccache sparse + git clone https://github.com/daxtens/smart-sparse-diff + #- name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 + # with: + # detached: true + - name: checkout trees + run: | + #git remote add linus git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + #git fetch linus + #git format-patch -o p1 linus/master..HEAD~1 + git remote add uml git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux.git + git fetch uml + git checkout uml/next + git checkout zpoline-nommu-v6.10 + #- name: build (sparse) + # run: | + # make ARCH=um W=1 C=2 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__ -fmax-errors=unlimited -fmax-warnings=unlimited' defconfig O=build-sparse + # make ARCH=um W=1 C=2 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__ -fmax-errors=unlimited -fmax-warnings=unlimited' O=build-sparse clean + # make ARCH=um W=1 C=2 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__ -fmax-errors=unlimited -fmax-warnings=unlimited' O=build-sparse -j8 2> old-sparse.log 1> /dev/null + # git checkout zpoline-nommu-v6.10 + # git checkout HEAD~1 + # make ARCH=um W=1 C=2 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__ -fmax-errors=unlimited -fmax-warnings=unlimited' O=build-sparse -j8 2> new-sparse.log 1> /dev/null + # ./smart-sparse-diff/smart-sparse-diff.py old-sparse.log new-sparse.log + - name: check coding style + run: | + git format-patch -o p1 uml/next..HEAD~1 + ./scripts/checkpatch.pl --summary-file --ignore FILE_PATH_CHANGES \ + --ignore AVOID_EXTERNS p1/*.patch + - name: check spells on commit message + continue-on-error: true + run: | + git log uml/next..HEAD |grep -v -E "^commit" > /tmp/a + aspell list /tmp/a + exit 1 + + bench-result: + runs-on: ubuntu-22.04 + name: bench-result + needs: tests + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + path: output + pattern: bench-result-* + merge-multiple: true + - name: Display structure of downloaded files + run: ls -R output + - name: Install packages + run: | + sudo apt update -y + sudo apt install -y gnuplot lmbench iperf3 + - name: benchmark-host + run: | + mkdir -p output + sudo ln -s /usr/include/x86_64-linux-gnu/sys /usr/include/sys + sudo mkdir -p /var/tmp/lmbench/ + sudo chown ${USER} /var/tmp/lmbench/ + sh .github/workflows/lmbench_run.sh |& tee output/native.dat + gcc -o do_getpid .github/workflows/do_getpid.c + ./do_getpid -c 100 | tee -a output/native.dat + iperf3 -s & + iperf3 -c localhost -fm | tee output/native-iperf3.dat + iperf3 -c localhost -fm -R | tee -a output/native-iperf3.dat + - name: bench data parse/out + run: | + export TMP_OUTPUT=$(bash .github/workflows/um-nommu-plot.sh output) + echo "TMP_OUTPUT<> $GITHUB_ENV + echo "$TMP_OUTPUT" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo ${{env.TMP_OUTPUT}} + - uses: actions/upload-artifact@v4 + with: + name: bench-result-all + path: output/out/lmbench.* + - name: publish to imgur + uses: devicons/public-upload-to-imgur@v2.2.2 + id: lmbench-imgur + with: + path: "output/out/lmbench.png" + client_id: ${{secrets.IMGUR_CLIENT_ID}} + - name: publish to imgur-iperf + uses: devicons/public-upload-to-imgur@v2.2.2 + id: iperf3-imgur + with: + path: "output/out/iperf3.png" + client_id: ${{secrets.IMGUR_CLIENT_ID}} + - name: bench data parse/out + run: | + export SCRIPT_OUTPUT="${{ join(fromJSON(steps.lmbench-imgur.outputs.markdown_urls)) }} ${{ join(fromJSON(steps.iperf3-imgur.outputs.markdown_urls)) }}" + echo "SCRIPT_OUTPUT<> $GITHUB_ENV + echo "$TMP_OUTPUT" >> $GITHUB_ENV + echo "" >> $GITHUB_ENV + echo "$SCRIPT_OUTPUT" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo ${{env.SCRIPT_OUTPUT}} + - uses: actions/github-script@v7 + env: + COMMENT_BODY: ${{env.SCRIPT_OUTPUT}} + with: + script: | + github.rest.issues.createComment({ + issue_number: 1, + owner: context.repo.owner, + repo: context.repo.repo, + body: process.env.COMMENT_BODY + }) diff --git a/.github/workflows/clone.c b/.github/workflows/clone.c new file mode 100644 index 00000000000000..811b61f6b105f6 --- /dev/null +++ b/.github/workflows/clone.c @@ -0,0 +1,85 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ +} while (0) + + static int /* Start function for cloned child */ +childFunc(void *arg) +{ + struct utsname uts; + + printf("arg=%lx\n", (unsigned long)arg); + + /* Change hostname in UTS namespace of child */ + + if (sethostname(arg, strlen(arg)) == -1) + errExit("sethostname"); + + /* Retrieve and display hostname */ + + if (uname(&uts) == -1) + errExit("uname"); + printf("uts.nodename in child: %s\n", uts.nodename); + + /* Keep the namespace open for a while, by sleeping. + This allows some experimentation--for example, another + process might join the namespace. */ + + return 0; /* Child terminates now */ +} + +#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */ + + int +main(int argc, char *argv[]) +{ + char *stack; /* Start of stack buffer */ + char *stackTop; /* End of stack buffer */ + pid_t pid; + struct utsname uts; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_SUCCESS); + } + + /* Allocate stack for child */ + + stack = malloc(STACK_SIZE); + if (stack == NULL) + errExit("malloc"); + stackTop = stack + STACK_SIZE; /* Assume stack grows downward */ + + /* Create child that has its own UTS namespace; + child commences execution in childFunc() */ + + printf("arg=%lx\n", (unsigned long)argv[1]); + pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]); + if (pid == -1) + errExit("clone"); + sleep(1); + printf("clone() returned %ld\n", (long) pid); + + /* Parent falls through to here */ + + /* Display hostname in parent's UTS namespace. This will be + different from hostname in child's UTS namespace. */ + + if (uname(&uts) == -1) + errExit("uname"); + printf("uts.nodename in parent: %s\n", uts.nodename); + + if (waitpid(pid, NULL, 0) == -1) /* Wait for child */ + errExit("waitpid"); + printf("child has terminated\n"); + + exit(EXIT_SUCCESS); +} + diff --git a/.github/workflows/ctest.c b/.github/workflows/ctest.c new file mode 100644 index 00000000000000..791c27a6869938 --- /dev/null +++ b/.github/workflows/ctest.c @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +static void __kill(int pid, int sig) { + register int syscall_no asm("rax") = 62; + register int arg1 asm("rdi") = pid; + register int arg2 asm("rsi") = sig; + asm("syscall"); +} + +static void exit_host(int r){ + __kill(0, 9); + return; +} + +int vfork1() +{ + int a = 0; + int ret = 0xfafafafa; + ret = vfork(); + return ret; +} + +int vfork2() +{ + return vfork(); +} + +void test_files(); + +char *argv[3] = {"/ctest", "noop", NULL}; +char *env[2] = {"PATH=/", NULL}; + +int test_vfork() +{ + int i, ret; + int status; + + ret = vfork(); + if (ret == 0) { + printf("child: ret=%d\r\n", ret); + //printf("got %c\n", getchar()); + ret = execve("./ctest", argv, env); + if (ret != 0) { + printf("child: exec ret=%d\r\n", ret); + while(1); + _exit(0); + } + + // should not be here + test_files(); + _exit(0); + } else if (ret < 0) { + printf("error %d\r\n", ret); + while(1); + _exit(0); + } else { + wait(&status); + //while(1); + printf("parent (%s): fork status=%d child_pid=%d\r\n", __FUNCTION__, status, ret); + } + return ret; +} + +void test_files() +{ + printf("opening\r\n"); + char *tmpname = "/files/mifile"; + char buf[128]; + int fd = open("/files/mifile2", O_RDONLY, 0); + if (fd < 1) { + printf("could not open %d\n", fd); + return; + } + //write(fd, "_*_", 3); + fsync(fd); + close(fd); + printf("opening\r\n"); + fd = open("/files/mifile2", O_RDONLY, 0); + if (fd < 1) { + printf("could not open %d\n", fd); + return; + } + + memset(buf, 0, 128); + read(fd, buf, 64); + printf("%s\r\n", buf); +} + +int test_vfork_only() +{ + int i, ret; + int status; + + ret = vfork1(); + if (ret == 0) { + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + printf("child %s\n", __FUNCTION__); + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + sleep(1); + _exit(0); + } else if (ret < 0) { + printf("error %d\r\n", ret); + while(1); + _exit(0); + } else { + sleep(1); + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + printf("parent (%s): fork status=%d child_pid=%d\r\n", __FUNCTION__, status, ret); + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + } + return ret; +} + + + +int test_vfork_sleeping() +{ + int i, ret; + int status; + + ret = vfork(); + if (ret == 0) { + ret = execve("./ctest", argv, env); + _exit(0); + } else if (ret < 0) { + printf("error %d\r\n", ret); + while(1); + _exit(0); + } else { + printf("parent (%s): fork status=%d child_pid=%d\r\n", __FUNCTION__, status, ret); + } + return ret; +} + + +int test_vfork_in_vfork() +{ + int i, ret; + int status; + + ret = vfork(); + if (ret == 0) { + printf("child 1\n"); + ret = vfork(); + if (ret == 0) { + printf("child 2\n"); + _exit(0); + } else if (ret < 0) { + printf("error %d\r\n", ret); + while(1); + _exit(0); + } else { + printf("parent: fork status=%d child_pid=%d\r\n", status, ret); + } + _exit(0); + } else if (ret < 0) { + printf("error %d\r\n", ret); + while(1); + _exit(0); + } else { + printf("parent (%s): fork status=%d child_pid=%d\r\n", __FUNCTION__, status, ret); + } + return ret; +} + +int test_exec_with_vfork_in_vfork() +{ + int i, ret; + int status; + + char *argv[3] = {"/ctest", "fork", NULL}; + char *env[2] = {"PATH=/", NULL}; + + ret = vfork(); + if (ret == 0) { + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + printf("child %s\n", __FUNCTION__); + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + ret = execve("./ctest", argv, env); + while(1); // should not be reached + } else if (ret < 0) { + printf("error %d\r\n", ret); + while(1); + _exit(0); + } else { + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + printf("parent (%s): fork status=%d child_pid=%d\r\n", __FUNCTION__, status, ret); + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + } + return ret; +} + + +int main(int argc, char **argv) +{ + int i, ret; + int iterations; + + if (argc < 2) { + iterations = 10; + } else if (strcmp(argv[1], "files") == 0) { + test_files(); + exit(0); + } else if (strcmp(argv[1], "loop") == 0) { + printf("looping forever\n"); + //printf("got %c\n", getchar()); + while(1); + exit(0); + } else if (strcmp(argv[1], "fork") == 0) { + //test_vfork_only(); + test_vfork(); + exit(0); + } else if (strcmp(argv[1], "exec") == 0) { + test_exec_with_vfork_in_vfork(); + test_files(); + exit(0); + } else if (strcmp(argv[1], "noop") == 0) { + printf("noop\n"); + exit(0); + } else if (strcmp(argv[1], "exit") == 0) { + printf("exit"); + exit_host(0); + } else if (strcmp(argv[1], "time") == 0) { + struct timeval current_time; + gettimeofday(¤t_time, NULL); + printf("seconds : %ld\nmicro seconds : %ld\n", + current_time.tv_sec, current_time.tv_usec); + exit(0); + } else { + printf("default arg\n"); + } + + test_exec_with_vfork_in_vfork(); + + test_vfork(); + test_vfork(); + test_vfork(); + test_vfork(); + test_vfork_sleeping(); + + test_files(); + + printf("got %c\n", getchar()); + + //while(1); + exit(0); +} diff --git a/.github/workflows/do_getpid.c b/.github/workflows/do_getpid.c new file mode 100644 index 00000000000000..9a1171ded536ed --- /dev/null +++ b/.github/workflows/do_getpid.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include + + +#ifndef BENCH_LDPRELOAD +extern pid_t do_getpid(void); + +void __do_getpid(void) +{ + asm volatile (".globl do_getpid"); + asm volatile ("do_getpid:"); + asm volatile ("movq $39, %rax"); + asm volatile ("syscall"); + asm volatile ("ret"); +} +#else +pid_t do_getpid(void) +{ + return getpid(); +} +#endif + +int main(int argc, char* const* argv) +{ + int ch; + unsigned long loopcnt = 0; + + while ((ch = getopt(argc, argv, "c:")) != -1) { + switch (ch) { + case 'c': + loopcnt = atol(optarg); + break; + + default: + printf("unknown option\n"); + exit(1); + } + } + + if (!loopcnt) { + printf("please specify loop count by -c\n"); + exit(0); + } + + { + pid_t my_pid = getpid(); + { + unsigned long t; + { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + t = ts.tv_sec * 1000000000UL + ts.tv_nsec; + } + { + unsigned long i; + for (i = 0; i < loopcnt; i++) + assert(my_pid == do_getpid()); + } + { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + t = ts.tv_sec * 1000000000UL + ts.tv_nsec - t; + } + printf("average %5lu nsec\n", t / loopcnt); + } + } + + return 0; +} diff --git a/.github/workflows/entropy.c b/.github/workflows/entropy.c new file mode 100644 index 00000000000000..59ae1da93239c9 --- /dev/null +++ b/.github/workflows/entropy.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 256 + +struct rand_pool_info { + int entropy_count; + int buf_size; + unsigned int buf[256]; +}; + +uint8_t prng(void) { + static uint8_t seed=19; + seed = 311 * seed + 17; + return seed; +} + +#define BUF_SIZE 256 +#define MAX_ITERS 10000 + +#define RNDADDENTROPY 0x40085203 + +int main(int argc, char **argv) +{ + struct rand_pool_info *output; + int max_iters = MAX_ITERS; + int iters = 0, ret; + int fd = open("/dev/random", O_WRONLY); + + if (argc == 2) + max_iters = atoi(argv[1]); + + printf("generating \"entropy\"..."); + output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + + BUF_SIZE); + do { + int i; + output->entropy_count = BUF_SIZE * 8; + output->buf_size = BUF_SIZE; + for (i=0; i< BUF_SIZE; i++) + output->buf[i] = prng(); + ret = ioctl(fd, RNDADDENTROPY, &output); + iters++; + } while((ret >= 0) && (iters < max_iters)); + + printf("for %d iters\n", iters); +} + diff --git a/.github/workflows/exit.c b/.github/workflows/exit.c new file mode 100644 index 00000000000000..b60675e1e7d381 --- /dev/null +++ b/.github/workflows/exit.c @@ -0,0 +1,13 @@ + +static void kill(int pid, int sig) { + register int syscall_no asm("rax") = 62; + register int arg1 asm("rdi") = pid; + register int arg2 asm("rsi") = sig; + asm("syscall"); +} + +void _start() +{ + kill(0, 9); + return; +} diff --git a/.github/workflows/futex.c b/.github/workflows/futex.c new file mode 100644 index 00000000000000..566e61c8773bee --- /dev/null +++ b/.github/workflows/futex.c @@ -0,0 +1,55 @@ +#include +#include + +/* this function is run by the second thread */ +void *inc_x(void *x_void_ptr) +{ + + /* increment x to 100 */ + int *x_ptr = (int *)x_void_ptr; + while(++(*x_ptr) < 100); + + printf("x increment finished\n"); + + /* the function must return something - NULL will do */ + return NULL; + +} + +int main() +{ + + int x = 0, y = 0; + + /* show the initial values of x and y */ + printf("x: %d, y: %d\n", x, y); + + /* this variable is our reference to the second thread */ + pthread_t inc_x_thread; + + /* create a second thread which executes inc_x(&x) */ + if(pthread_create(&inc_x_thread, NULL, inc_x, &x)) { + + fprintf(stderr, "Error creating thread\n"); + return 1; + + } + /* increment y to 100 in the first thread */ + while(++y < 100); + + printf("y increment finished\n"); + + /* wait for the second thread to finish */ + if(pthread_join(inc_x_thread, NULL)) { + + fprintf(stderr, "Error joining thread\n"); + return 2; + + } + + /* show the results - x is now 100 thanks to the second thread */ + printf("x: %d, y: %d\n", x, y); + + return 0; + +} diff --git a/.github/workflows/gdbinit b/.github/workflows/gdbinit new file mode 100644 index 00000000000000..d202e29a1e2867 --- /dev/null +++ b/.github/workflows/gdbinit @@ -0,0 +1,221 @@ +#add-auto-load-safe-path /home/tazaki/gitworks/osv/scripts/loader.py + +handle SIGUSR1 nostop +#set annotate 1 +set history save on +set history size 10000 +set history filename ~tazaki/.gdb_history +set print pretty on +set print static-members off +set charset ASCII +set print thread-events off +directory /home/tazaki/work/nabla-linux/tests/busybox.git:/home/tazaki/work/nabla-linux/tests/musl-git/:/home/tazaki/work/deb-src/glibc-2.39/ + +define ntoa + set $ipv4 = $arg0 + echo IPV4 =. + p $ipv4 + set $val1 = ($ipv4 >> 24) & 0xff + set $val2 = ($ipv4 >> 16) & 0xff + set $val3 = ($ipv4 >> 8) & 0xff + set $val4 = ($ipv4 >> 0) & 0xff + printf "IPV4=%u=0x%02x.%02x.%02x.%02x =%d.%d.%d.%d\n", $ipv4, $val1, $val2, $val3, $val4, $val1, $val2, $val3, $val4 + end + +# change prompt +#source /home/tazaki/gdb-prompt.py + +define walk_list + set $temp = $arg0 + while ($temp) + printf "(%d,0x%X)-->",((sll*)$temp)->data,((sll*)$temp)->next + set $temp = ((sll*)$temp)->next + end + printf "Done\n" +end + +define walk_tailq + set $temp = $arg0->tqh_first + while ($temp) + printf "(%s,0x%lx,runnable=%d)-->", ((struct thread *)$temp)->name,(struct thread *)$temp, is_runnable((struct thread *)$temp) + set $temp = ((struct thread *)$temp)->thread_list->tqe_next + end + printf "Done\n" +end + +define lkl_hijack + set environment LD_LIBRARY_PATH=../openssl:tools/lkl/lib/hijack/:lib/hijack/ + set exec-wrapper env 'LD_PRELOAD=liblkl-hijack.so' +end + +define zpoline + set exec-wrapper env 'LD_PRELOAD=./libzpoline.so' + set environment LIBZPHOOK=libzphook_basic.so + set environment LD_LIBRARY_PATH=/home/tazaki/work/zpoline/zpoline/apps/basic/ +end + +define zpoline_lkl + set environment LKL_HIJACK_ZPOLINE=1 + set environment LIBZPHOOK=liblkl-zpoline.so + set environment LD_LIBRARY_PATH=../openssl:tools/lkl/lib/hijack/:lib/hijack/:/home/tazaki/work/zpoline/zpoline + set exec-wrapper env 'LD_PRELOAD=libzpoline.so' +end + +define zpoline_rsocket + set environment LIBZPHOOK=librszpoline.so + set environment LD_LIBRARY_PATH=./build/lib/:/home/tazaki/work/zpoline/zpoline + set exec-wrapper env 'LD_PRELOAD=libzpoline.so' +end + +define rsocket + set environment LD_LIBRARY_PATH=./build/lib/ + set exec-wrapper env 'LD_PRELOAD=librspreload.so' +end + +define upregs + set $regs = 0 + if $argc == 0 + set $regs = (((struct pt_regs *)current_ptregs)->regs->gp) + else + set $regs = ((struct uml_pt_regs *)$arg0)->gp + end + + printf "rax=0x%08lx\t\tAX[10]=0x%08lx\t\tO_AX[15]=0x%lx\n", $rax, $regs[10], $regs[15] + printf "rbx=0x%08lx\t\tBX[5]=0x%08lx\n", $rbx, $regs[5] + printf "rcx=0x%08lx\t\tCX[11]=0x%08lx\n", $rcx,$regs[11] + printf "rdx=0x%08lx\t\tDX[12]=0x%08lx\n", $rdx,$regs[12] + printf "rsi=0x%08lx\t\tSI[13]=0x%08lx\n", $rsi, $regs[13] + printf "rdi=0x%08lx\t\tDI[14]=0x%08lx\n", $rdi, $regs[14] + printf "rbp=0x%08lx\t\tBP[4]=0x%08lx\n", $rbp, $regs[4] + printf "rsp=0x%08lx\t\tSP[19]=0x%08lx\n", $rsp, $regs[19] + printf " r8=0x%08lx\t\tR8[9]=0x%08lx\n", $r8,$regs[9] + printf " r9=0x%08lx\t\tR9[8]=0x%08lx\n", $r9,$regs[8] + printf "r10=0x%08lx\t\tR10[7]=0x%08lx\n", $r10,$regs[7] + printf "r11=0x%08lx\t\tR11[6]=0x%08lx\n", $r11,$regs[6] + printf "r12=0x%08lx\t\tR12[3]=0x%08lx\n", $r12,$regs[3] + printf "r13=0x%08lx\t\tR13[2]=0x%08lx\n", $r13,$regs[2] + printf "r14=0x%08lx\t\tR14[1]=0x%08lx\n", $r14,$regs[1] + printf "r15=0x%08lx\t\tR15[0]=0x%08lx\n", $r15,$regs[0] + printf "rip=0x%08lx\t\tIP[16]=0x%08lx\n", $rip,$regs[16] + printf "eflags=0x%08lx\t\tEFLAGS[18]=0x%lx\n", $eflags,$regs[18] + printf "CS[17]=0x%lx, ", $regs[17] + printf "SS[20]=0x%lx\n", $regs[20] +end + +define pregs + if $argc == 1 + print $arg0 *(struct pt_regs *)current_ptregs + else + print *(struct pt_regs *)current_ptregs + end + printf "pregs=0x%x, AX[10]=%ld, CX[11]=0x%lx, DX[12]=0x%lx, ORIG_AX[15]=%ld, IP[16]=0x%x, SP[19]=0x%x HOST_FS[25]=0x%x, FS[21]=0x%x, FP=0x%x\n", \ + current_ptregs, ((struct pt_regs *)current_ptregs)->regs.gp[10], \ + ((struct pt_regs *)current_ptregs)->regs.gp[11], ((struct pt_regs *)current_ptregs)->regs.gp[12],\ + ((struct pt_regs *)current_ptregs)->regs.gp[15], ((struct pt_regs *)current_ptregs)->regs.gp[16],\ + ((struct pt_regs *)current_ptregs)->regs.gp[19], ((struct pt_regs *)current_ptregs)->regs.gp[25],\ + ((struct pt_regs *)current_ptregs)->regs.gp[21], ((struct pt_regs *)current_ptregs)->regs.fp +end + +## source /home/tazaki/.gdbinit_defs +## +## define syscall +## printf "syscall/rax\t = %d(%s)\n", ((struct pt_regs *)current_ptregs)->regs.gp[15], \ +## $syscall_tbl[((struct pt_regs *)current_ptregs)->regs.gp[15]] +## printf "ret/rax\t\t\t = %d\n", $rax +## printf "retp/rcx\t\t = 0x%x\n", $rcx +## printf "arg0/rdi\t\t = 0x%x\n", $rdi +## printf "arg1/rsi\t\t = 0x%x\n", $rsi +## printf "arg2/rdx\t\t = 0x%x\n", $rdx +## printf "arg3/r10\t\t = 0x%x\n", $r10 +## printf "arg4/r8\t\t\t = 0x%x\n", $r8 +## printf "arg5/r9\t\t\t = 0x%x\n", $r9 +## end + +source /home/tazaki/work/mino/mino/gdbinit-minoc + +python +import subprocess +import re + +def relocatesections(filename, addr): + p = subprocess.Popen(["readelf", "-S", filename], stdout = subprocess.PIPE) + + sections = [] + textaddr = '0' + for line in p.stdout.readlines(): + line = line.decode("utf-8").strip() + if not line.startswith('[') or line.startswith('[Nr]'): + continue + + line = re.sub(r' +', ' ', line) + line = re.sub(r'\[ *(\d+)\]', r"\g<1>", line) + fieldsvalue = line.split(' ') + fieldsname = ['number', 'name', 'type', 'addr', 'offset', 'size', 'entsize', 'flags', 'link', 'info', 'addralign'] + sec = dict(zip(fieldsname, fieldsvalue)) + + if sec['number'] == '0': + continue + + sections.append(sec) + + if sec['name'] == '.text': + textaddr = sec['addr'] + + return (textaddr, sections) + + +class AddSymbolFileAll(gdb.Command): + """The right version for add-symbol-file""" + + def __init__(self): + super(AddSymbolFileAll, self).__init__("add-symbol-file-all", gdb.COMMAND_USER) + self.dont_repeat() + + def invoke(self, arg, from_tty): + argv = gdb.string_to_argv(arg) + filename = argv[0] + + if len(argv) > 1: + offset = int(str(gdb.parse_and_eval(argv[1])), 0) + else: + offset = 0 + + (textaddr, sections) = relocatesections(filename, offset) + + cmd = "add-symbol-file %s 0x%08x" % (filename, int(textaddr, 16) + offset) + + for s in sections: + addr = int(s['addr'], 16) + if s['name'] == '.text' or addr == 0: + continue + + cmd += " -s %s 0x%08x" % (s['name'], addr + offset) + + gdb.execute(cmd) + +class RemoveSymbolFileAll(gdb.Command): + """The right version for remove-symbol-file""" + + def __init__(self): + super(RemoveSymbolFileAll, self).__init__("remove-symbol-file-all", gdb.COMMAND_USER) + self.dont_repeat() + + def invoke(self, arg, from_tty): + argv = gdb.string_to_argv(arg) + filename = argv[0] + + if len(argv) > 1: + offset = int(str(gdb.parse_and_eval(argv[1])), 0) + else: + offset = 0 + + (textaddr, _) = relocatesections(filename, offset) + + cmd = "remove-symbol-file -a 0x%08x" % (int(textaddr, 16) + offset) + gdb.execute(cmd) + + +AddSymbolFileAll() +RemoveSymbolFileAll() +end +#source /home/tazaki/work/gdb-symbols.py diff --git a/.github/workflows/init_array.c b/.github/workflows/init_array.c new file mode 100644 index 00000000000000..8faf546c978cb6 --- /dev/null +++ b/.github/workflows/init_array.c @@ -0,0 +1,19 @@ +#include + +static void init(int argc, char **argv, char **envp) { + printf("> l:%s\n", __FUNCTION__); +} + +static void fini(void) { + printf("< l:%s\n", __FUNCTION__); +} + + +__attribute__((section(".init_array"), used)) static typeof(init) *init_p = init; +__attribute__((section(".fini_array"), used)) static typeof(fini) *fini_p = fini; + +int main (int argc, char *argv[]) +{ + return 0; +} + diff --git a/.github/workflows/inittab b/.github/workflows/inittab new file mode 100644 index 00000000000000..81eef106465f99 --- /dev/null +++ b/.github/workflows/inittab @@ -0,0 +1,13 @@ +# /etc/inittab + +::sysinit:/etc/init.d/rcS + +::respawn:-/bin/sh + +# Stuff to do when restarting the init process +::restart:/sbin/init + +# Stuff to do before rebooting +::ctrlaltdel:/sbin/reboot +::shutdown:/bin/umount -a -r +::shutdown:/sbin/swapoff -a diff --git a/.github/workflows/iperf3.sh b/.github/workflows/iperf3.sh new file mode 100755 index 00000000000000..4a8a2f264897d1 --- /dev/null +++ b/.github/workflows/iperf3.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +NIC=vec0 +mount proc /proc -t proc +echo "nameserver 8.8.8.8" > /etc/resolv.conf +/sbin/ifconfig lo 127.0.0.1 up +/sbin/ifconfig $NIC 192.168.122.2 up + +sleep 5 +IPERF=/root/iperf3.static +echo "===iperf3 forward===" +$IPERF -c 192.168.122.1 -fm +echo "===iperf3 reverse===" +$IPERF -c 192.168.122.1 -R -fm +/sbin/halt -f diff --git a/.github/workflows/iperf3.static b/.github/workflows/iperf3.static new file mode 100755 index 00000000000000..79155612c05c8a Binary files /dev/null and b/.github/workflows/iperf3.static differ diff --git a/.github/workflows/lmbench_run.sh b/.github/workflows/lmbench_run.sh new file mode 100644 index 00000000000000..26596236ed4bf6 --- /dev/null +++ b/.github/workflows/lmbench_run.sh @@ -0,0 +1,26 @@ + +PATH=/usr/lib/lmbench/bin/x86_64-linux-gnu/:/lmbench2/bin/x86_64-linux-gnulibc1:$PATH +mkdir -p /var/tmp/lmbench +cp `which hello` /var/tmp/lmbench/hello +cp `which hello` /tmp/hello + +mkdir -p /usr/include/sys/ || true +touch /usr/include/sys/types.h || true + +if [ -d "/usr/lib/lmbench/bin/x86_64-linux-gnu/" ] ; then +ENOUGH=10000 lat_select -n 10 file +ENOUGH=10000 lat_select -n 100 file +ENOUGH=10000 lat_select -n 1000 file +else +ENOUGH=10000 lat_select file 10 +ENOUGH=10000 lat_select file 100 +ENOUGH=10000 lat_select file 1000 +fi + +ENOUGH=100000 lat_syscall null +ENOUGH=100000 lat_syscall read +ENOUGH=100000 lat_syscall write +ENOUGH=100000 lat_syscall stat +ENOUGH=100000 lat_syscall open +ENOUGH=10000 lat_proc shell +ENOUGH=10000 lat_proc exec diff --git a/.github/workflows/locale.c b/.github/workflows/locale.c new file mode 100644 index 00000000000000..1d4d83c71ff4fa --- /dev/null +++ b/.github/workflows/locale.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +int main (int argc, char *argv[]) +{ + int ret = getpid(); + printf("strerr = %s\n", strerror(errno)); + return 0; +} diff --git a/.github/workflows/noop.c b/.github/workflows/noop.c new file mode 100644 index 00000000000000..23d5b86bec1197 --- /dev/null +++ b/.github/workflows/noop.c @@ -0,0 +1,38 @@ +#include "syscall_nr.h" + +static unsigned long __sysinfo = 0; +#include "syscall-x86_64.h" + +typedef unsigned long size_t; + +#define AUX_CNT 64 +#define DYN_CNT 32 + +#define AT_NULL 0 +#define AT_SYSINFO 32 + +void _start_c(size_t *sp) +{ + size_t i, aux[AUX_CNT], dyn[DYN_CNT]; + size_t *rel, rel_size, base; + + int argc = *sp; + char **argv = (void *)(sp+1); + + for (i=argc+1; argv[i]; i++); + size_t *auxv = (void *)(argv+i+1); + + for (i=0; i +#include +#include +#include +#include + +static void segv_handler (int cause, siginfo_t * info, void *uap) +{ + //For test. Never ever call stdio functions in a signal handler otherwise*/ + printf ("SIGSEGV handled\n"); + printf ("SIGSEGV raised at address 0x%lx\n", (unsigned long)info->si_addr); + ucontext_t *context = uap; + /*On my particular system, compiled with gcc -O2, the offending instruction + generated for "*f = 16;" is 6 bytes. Lets try to set the instruction + pointer to the next instruction (general register 14 is EIP, on linux x86) */ + context->uc_mcontext.gregs[16] += 14; + //alternativly, try to jump to a "safe place" + //context->uc_mcontext.gregs[14] = (unsigned int)safe_func; + exit(cause); +} + +/* XXX: this code doesn't work as 2nd fprintf() causes SEGV + * (probably) due to alignment issue of xmm0/rsp register + * + * https://stackoverflow.com/questions/5397041/getting-the-saved-instruction-pointer-address-from-a-signal-handler + */ +static void signal_segv(int signum, siginfo_t *info, void *ptr) +{ + static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"}; + int i, f = 0; + ucontext_t *ucontext = (ucontext_t*)ptr; + void **bp = 0; + void *ip = 0; + + fprintf(stderr, "Segmentation Fault!\n"); + fprintf(stderr, "info.si_signo = %d\n", signum); + fprintf(stderr, "info.si_errno = %d\n", info->si_errno); + fprintf(stderr, "info.si_code = %d (%s)\n", info->si_code, si_codes[info->si_code]); + fprintf(stderr, "info.si_addr = %p\n", info->si_addr); + for(i = 0; i < NGREG; i++) + fprintf(stderr, "reg[%02d] = 0x%016llx\n", i, ucontext->uc_mcontext.gregs[i]); + + ucontext->uc_mcontext.gregs[16] += 14; + exit(signum); +} + +int main (int argc, char *argv[]) +{ + char *ptr = NULL; + struct sigaction sa; + int *f = NULL; + + if (argc != 3) { + printf("%s [nullptr or raise] [handler or not]\n", argv[0]); + return 0; + } + + if (atoi(argv[2]) >= 1) { + printf("register handler\n"); + if (atoi(argv[2]) == 1) + sa.sa_sigaction = segv_handler; + else + sa.sa_sigaction = signal_segv; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + if (sigaction (SIGSEGV, &sa, 0)) { + perror ("sigaction"); + return -1; + } + } + + if (atoi(argv[1]) == 0) + memcpy(ptr, 0, 8); + else { + printf("raising signal\n"); + raise(SIGSEGV); + } + return 0; +} diff --git a/.github/workflows/rcS b/.github/workflows/rcS new file mode 100755 index 00000000000000..a7efe02c4c20c9 --- /dev/null +++ b/.github/workflows/rcS @@ -0,0 +1,16 @@ +#!/bin/sh + +NIC=vec0 +mount proc /proc -t proc +echo "nameserver 8.8.8.8" > /etc/resolv.conf +/sbin/ifconfig lo 127.0.0.1 up +/sbin/ifconfig $NIC 192.168.122.2 up +/sbin/ip route add default via 192.168.122.1 dev $NIC + +export PATH=/home:/sbin:/usr/sbin:/bin:/usr/bin +export TERM=linux + +# hanging +#export PS1="\[$(tput bold)\]\[$(tput setaf 4)\][\[$(tput setaf 5)\]\u\[$(tput setaf 4)\]@\[$(tput setaf 5)\]\h \[$(tput setaf 2)\]\W\[$(tput setaf 4)\]]\\$ \[$(tput sgr0)\]" + +exec "$@" diff --git a/.github/workflows/stackp.c b/.github/workflows/stackp.c new file mode 100644 index 00000000000000..df058766eecf69 --- /dev/null +++ b/.github/workflows/stackp.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include +#include +#include + + +int main(int argc, char *argv[]) +{ + char str[64]; + + write(2, "Done\nChild\n", 11); +} diff --git a/.github/workflows/um-nommu-bench.sh b/.github/workflows/um-nommu-bench.sh new file mode 100755 index 00000000000000..601e128ccbb9f5 --- /dev/null +++ b/.github/workflows/um-nommu-bench.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +SCRIPT_DIR="$(cd $(dirname "${BASH_SOURCE[0]}"); pwd)" + +# macos has different syntax +OUTPUT=$SCRIPT_DIR/$(date "+%Y-%m-%d") +mkdir -p $OUTPUT + +TRIALS="1" +ENTRIES="1000000" +VSIZES="1 8 256 1024 8192" +RUNTIMES="build/mmu build" + + +echo "$(tput bold)== um (mmu) ($test-$num-$vsize) ==$(tput sgr0)" +../linux-um-nommu/build-mmu/vmlinux ubd0=./alpine-test.ext3 rw mem=1024m loglevel=0 init=/bench.sh \ + | tee "$OUTPUT/um-mmu.dat" + +echo "$(tput bold)== um (nommu) ($test-$num-$vsize) ==$(tput sgr0)" +../linux-um-nommu/build/vmlinux ubd0=./alpine-test.ext3 rw mem=1024m loglevel=0 init=/bench.sh \ + | tee "$OUTPUT/um-nommu.dat" + +echo "$(tput bold)== host (mmu) ($test-$num-$vsize) ==$(tput sgr0)" +sh docker/alpine/lmbench_run.sh \ + |& tee "$OUTPUT/native.dat" +./zpoline-bench/do_getpid -c 100 | tee -a "$OUTPUT/native.dat" + +bash ${SCRIPT_DIR}/um-nommu-plot.sh ${OUTPUT} diff --git a/.github/workflows/um-nommu-plot.sh b/.github/workflows/um-nommu-plot.sh new file mode 100755 index 00000000000000..c148b408e95eb9 --- /dev/null +++ b/.github/workflows/um-nommu-plot.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" + +OUTPUT="$1" +DIRS="read fill" + +mkdir -p "$OUTPUT/out/" + +# parse outputs + +for f in `ls $OUTPUT/*.dat |grep -v iperf3` +do + cat $f | grep microsec | sed "s/.*:\(.*\)/\1/" | awk '{print $1}' \ + > $OUTPUT/out/`basename $f .dat`-lmbench-out.dat + + cat $f | grep average |grep -v time | awk '{print $2 $3}' \ + > $OUTPUT/out/`basename $f .dat`-getpid-out.dat +done + +# parse iperf3 result +for f in `ls $OUTPUT/*-iperf3.dat` +do + cat $f | grep receiver | awk '{print $7}' \ + > $OUTPUT/out/`basename $f .dat`-out.dat +done + +gnuplot << EndGNUPLOT +set terminal postscript eps lw 3 "Helvetica" 24 +set output "${OUTPUT}/out/lmbench.eps" +#set xtics font "Helvetica,14" +set pointsize 2 +set xzeroaxis +set grid ytics + +set boxwidth 0.2 +set style fill pattern + +set size 1.0,0.8 +set key top left + +set xrange [-0.5:10] +set xtics ('select-10' 0, 'select-100' 1, 'select-1000' 2, 'syscall' 3, 'read' 4, 'write' 5, 'stat' 6, 'open/close' 7, 'fork+sh' 8, 'fork+execve' 9) +set xtics rotate by 45 right +set yrange [0.01:100000] +set ylabel "Latency (usec)" +set logscale y + +plot \ + '${OUTPUT}/out/um-mmu-lmbench-out.dat' usin (\$0-0.3):(\$1) w boxes fill patter 2 lt 1 lc rgb "green" title "um(mmu)" ,\ + '${OUTPUT}/out/um-nommu-zpoline-lmbench-out.dat' usin (\$0-0.1):(\$1) w boxes fill patter 2 lt 1 lc rgb "blue" title "um(nommu(z))" ,\ + '${OUTPUT}/out/um-nommu-seccomp-lmbench-out.dat' usin (\$0+0.1):(\$1) w boxes fill patter 2 lt 1 lc rgb "royalblue" title "um(nommu(s))" ,\ + '${OUTPUT}/out/native-lmbench-out.dat' usin (\$0+0.3):(\$1) w boxes fill patter 2 lt 1 lc rgb "red" title "native" + +set terminal png lw 3 14 crop +set output "${OUTPUT}/out/lmbench.png" +replot + +EndGNUPLOT + +echo -e "### lmbench (usec)\n" +echo -e "|select-10\n|select-100\n|select-1000\n|syscall\n|read\n|write\n|stat\n|open/close\n|fork+sh\n|fork+execve" > /tmp/a + +echo -e "||native|um|um-nommu(s)|um-nommu(z)|\n|--|--|--|--|--|"; paste -d "|" `ls ${OUTPUT}/out/*-lmbench-out.dat` | sed "s/\(.*\)/\|\1\|/" | paste /tmp/a - | column -t + +rm -f /tmp/a + +echo "" +echo -e "### do_getpid bench (nsec)\n" +for f in `ls $OUTPUT/*.dat |grep -v iperf3` +do + export $(basename $f .dat|sed "s/-/_/g")=`grep aver $f | grep -v time | awk '{print $2}'` +done +echo -e "||native|um|um-nommu(s)|um-nommu(z)|\n|--|--|--|--|--|" +echo "|getpid | ${native} | ${um_mmu} | ${um_nommu_seccomp}| ${um_nommu_zpoline}|" + + +# iperf result + +gnuplot << EndGNUPLOT +set terminal postscript eps lw 3 "Helvetica" 24 +set output "${OUTPUT}/out/iperf3.eps" +#set xtics font "Helvetica,14" +set pointsize 2 +set xzeroaxis + +set boxwidth 0.2 +set style fill pattern + +set size 1.0,0.8 +set key top left + +set xrange [-0.5:1.5] +set xtics ('iperf(f)' 0, 'iperf(r)' 1) +#set xtics rotate by 45 right +set yrange [:50] +set ytics 10 +set ylabel "Goodput (Gbps)" + +plot \ + '${OUTPUT}/out/um-mmu-iperf3-out.dat' usin (\$0-0.3):(\$1/1000) w boxes fill patter 2 lt 1 lc rgb "green" title "um(mmu)" ,\ + '${OUTPUT}/out/um-nommu-zpoline-iperf3-out.dat' usin (\$0-0.1):(\$1/1000) w boxes fill patter 2 lt 1 lc rgb "blue" title "um(nommu(z))" ,\ + '${OUTPUT}/out/um-nommu-seccomp-iperf3-out.dat' usin (\$0+0.1):(\$1/1000) w boxes fill patter 2 lt 1 lc rgb "royalblue" title "um(nommu(s))" ,\ + '${OUTPUT}/out/native-iperf3-out.dat' usin (\$0+0.3):(\$1/1000) w boxes fill patter 2 lt 1 lc rgb "red" title "native" + +set terminal png lw 3 14 crop +set output "${OUTPUT}/out/iperf3.png" +replot + +EndGNUPLOT + +echo "" +echo -e "### iperf3 bench (Mbps)\n" +for f in `ls $OUTPUT/out/*iperf3*.dat` +do + export $(basename $f .dat|sed "s/-/_/g" | sed "s/_iperf3_out/_f/")=`cat $f|head -1` + export $(basename $f .dat|sed "s/-/_/g" | sed "s/_iperf3_out/_r/")=`cat $f|tail -1` +done +echo -e "||native|um|um-nommu(s)|um-nommu(z)|\n|--|--|--|--|--|" +echo "|iperf3(f) | ${native_f} | ${um_mmu_f} | ${um_nommu_seccomp_f}| ${um_nommu_zpoline_f}|" +echo "|iperf3(r) | ${native_r} | ${um_mmu_r} | ${um_nommu_seccomp_r}| ${um_nommu_zpoline_r}|" diff --git a/.github/workflows/vdso_test.c b/.github/workflows/vdso_test.c new file mode 100644 index 00000000000000..f5891cfe5445e2 --- /dev/null +++ b/.github/workflows/vdso_test.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + + +int main(int argc, char* const* argv) +{ + int ch; + unsigned long loopcnt = 0; + + while ((ch = getopt(argc, argv, "c:")) != -1) { + switch (ch) { + case 'c': + loopcnt = atol(optarg); + break; + + default: + printf("unknown option\n"); + exit(1); + } + } + + if (!loopcnt) { + printf("please specify loop count by -c\n"); + exit(0); + } + + unsigned long t; + struct timespec ts; + struct timeval tv; + + unsigned long i, j; + for (j = 0; j < 2; j++) { + clock_gettime(CLOCK_REALTIME, &ts); + t = ts.tv_sec * 1000000000UL + ts.tv_nsec; + + for (i = 0; i < loopcnt; i++) { + if (j == 0) + clock_gettime(CLOCK_REALTIME, &ts); + else + gettimeofday(&tv, NULL); + } + + clock_gettime(CLOCK_REALTIME, &ts); + t = ts.tv_sec * 1000000000UL + ts.tv_nsec - t; + printf("average[%s] %5lu nsec\n", j == 0 ? "clock_gettime" + : "gettimeofday", t / loopcnt); + } + + + return 0; +}