From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by sourceware.org (Postfix) with ESMTPS id BE6403858D37 for ; Sun, 12 Jul 2020 08:25:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org BE6403858D37 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=andrew.burgess@embecosm.com Received: by mail-wm1-x342.google.com with SMTP id f18so9982889wml.3 for ; Sun, 12 Jul 2020 01:25:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=+VsROJCcUv78FnvU9wEYfJ0gBWJFdaQ0ooSJsVlJcvM=; b=c8Vuyo/lbRBqLjbP6Ov3hH/lDTg+hhx9gSgkC8tZUwzShYqCux9CrSBh2M8CFlvpq9 BejAzlolZKn9adfMTYvtWHjzaU+G5YF75ZeYzAlpT7kW40o/yzFCI+84pqmSoq1L3V3w 550Qj/jVwIdTFXG4K+n/WXoCNKS10SHxXOqFbT3fzRfAY8qq630kvHN5euf+aMxHB65e DYWWr3Hd3u4rOCDJXF8j7w8gcpFtubdRxPdC8FDS98ngdJwLaFaNJCJGrAVs5x5Ewnms QdZtTIGsP00xdfjVNAEzSPwkcXYNHhmY2WKYWM49wTfZ+OYNYBVHiTq9QvgxPtda70Rv 5JHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=+VsROJCcUv78FnvU9wEYfJ0gBWJFdaQ0ooSJsVlJcvM=; b=CF7BC4tALuZqeCOoPcapSVZEX66exUU+agzX0onzmRyFzBqcdb5E1nP4RONoTp2NA0 8i2u8UO5vAPX5XIq4qRp0vJI8fJPX8sj2y1kTSQOrNwF/zOcIP4W5YSgUuj+/eO2tJWC tW6rwY/82jNiqV+qld09o7p2nRhJWDfsSA0LI5VIZ8njuG2W2LRjyzXWGYUsT0vcop6K D82pU7PjCMxPGIwwiACu4YzMCxqScw5Kmj3ynlbfuaTph43hB6Ol0u6kD1WAKFWwTACT +4VEHIFPzFhlFXdLIUEDp8TpwM4JW7ALsMRqDscZQRawszKZtmbMaVP8krLs9iSf7o/9 iP6g== X-Gm-Message-State: AOAM533dp1NqsADxUIKLwO03HfCqQ+GNwIBWo/p1dYFBVzDFgrc9o7At AdSa7Mcbv5cmDhtxAIN1zDrD6SAKIGo= X-Google-Smtp-Source: ABdhPJxfuFicEbg3YhyKYlkpZWnJizTFZE8wsfPb1VLUM3nI8VtneREKiE4WyTuS4VyQ2uyQM2qROQ== X-Received: by 2002:a1c:47:: with SMTP id 68mr13153141wma.106.1594542305409; Sun, 12 Jul 2020 01:25:05 -0700 (PDT) Received: from localhost (host109-154-20-168.range109-154.btcentralplus.com. [109.154.20.168]) by smtp.gmail.com with ESMTPSA id u8sm17980422wrt.28.2020.07.12.01.25.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 12 Jul 2020 01:25:04 -0700 (PDT) Date: Sun, 12 Jul 2020 09:25:03 +0100 From: Andrew Burgess To: "Jose E. Marchesi" Cc: gdb-patches@sourceware.org Subject: Re: [PATCH V4 2/3] sim: eBPF simulator Message-ID: <20200712082503.GC2737@embecosm.com> References: <20200710122530.32541-1-jose.marchesi@oracle.com> <20200710122530.32541-3-jose.marchesi@oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200710122530.32541-3-jose.marchesi@oracle.com> X-Operating-System: Linux/5.6.15-200.fc31.x86_64 (x86_64) X-Uptime: 16:06:22 up 32 days, 5:13, X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] X-Spam-Status: No, score=-9.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 12 Jul 2020 08:25:16 -0000 * Jose E. Marchesi via Gdb-patches [2020-07-10 14:25:29 +0200]: > This patch introduces the basics of an instruction-simulator for eBPF. > The simulator is based on CGEN. Thanks I took a look through and I'm basically happy. There's a few small issues that I've highlighted inline below. Thanks, Andrew > > sim/ChangeLog: > > 2020-07-10 Jose E. Marchesi > David Faust > > * configure.tgt (sim_arch): Add entry for bpf-*-*. > * configure: Regenerate. > * MAINTAINERS: Add maintainer for the BPF simulator. > * bpf/Makefile.in: New file. > * bpf/bpf-helpers.c: Likewise. > * bpf/bpf-helpers.def: Likewise. > * bpf/bpf-helpers.h: Likewise. > * bpf/bpf-sim.h: Likewise. > * bpf/bpf.c: Likewise. > * bpf/config.in: Likewise. > * bpf/configure.ac: Likewise. > * bpf/decode.h: Likewise. > * bpf/eng.h: Likewise. > * bpf/mloop.in: Likewise. > * bpf/sim-if.c: Likewise. > * bpf/sim-main.h: Likewise. > * bpf/traps.c: Likewise. > * bpf/configure: Generate. This file is missing from this message. > * bpf/aclocal.m4: Likewise. > > sim/testsuite/ChangeLog: > > 2020-07-10 David Faust > Jose E. Marchesi > > * configure: Regenerate. > * sim/bpf/allinsn.exp: New file. > * sim/bpf/alu.s: Likewise. > * sim/bpf/alu32.s: Likewise. > * sim/bpf/endbe.s: Likewise. > * sim/bpf/endle.s: Likewise. > * sim/bpf/jmp.s: Likewise. > * sim/bpf/jmp32.s: Likewise. > * sim/bpf/ldabs.s: Likewise. > * sim/bpf/mem.s: Likewise. > * sim/bpf/mov.s: Likewise. > * sim/bpf/testutils.inc: Likewise. > * sim/bpf/xadd.s: Likewise. > --- > sim/ChangeLog | 23 + > sim/MAINTAINERS | 1 + > sim/bpf/Makefile.in | 205 + > sim/bpf/aclocal.m4 | 119 + > sim/bpf/bpf-helpers.c | 175 + > sim/bpf/bpf-helpers.def | 194 + > sim/bpf/bpf-helpers.h | 31 + > sim/bpf/bpf-sim.h | 31 + > sim/bpf/bpf.c | 327 + > sim/bpf/config.in | 248 + > sim/bpf/configure | 15942 ++++++++++++++++++++++++++ > sim/bpf/configure.ac | 13 + > sim/bpf/decode.h | 37 + > sim/bpf/eng.h | 24 + > sim/bpf/mloop.in | 165 + > sim/bpf/sim-if.c | 216 + > sim/bpf/sim-main.h | 51 + > sim/bpf/traps.c | 33 + > sim/configure | 8 + > sim/configure.tgt | 3 + > sim/testsuite/ChangeLog | 17 + > sim/testsuite/configure | 9 +- > sim/testsuite/sim/bpf/allinsn.exp | 26 + > sim/testsuite/sim/bpf/alu.s | 109 + > sim/testsuite/sim/bpf/alu32.s | 99 + > sim/testsuite/sim/bpf/endbe.s | 46 + > sim/testsuite/sim/bpf/endle.s | 43 + > sim/testsuite/sim/bpf/jmp.s | 120 + > sim/testsuite/sim/bpf/jmp32.s | 120 + > sim/testsuite/sim/bpf/ldabs.s | 87 + > sim/testsuite/sim/bpf/mem.s | 56 + > sim/testsuite/sim/bpf/mov.s | 54 + > sim/testsuite/sim/bpf/testutils.inc | 38 + > sim/testsuite/sim/bpf/xadd.s | 44 + > 34 files changed, 18711 insertions(+), 3 deletions(-) > create mode 100644 sim/bpf/Makefile.in > create mode 100644 sim/bpf/aclocal.m4 > create mode 100644 sim/bpf/bpf-helpers.c > create mode 100644 sim/bpf/bpf-helpers.def > create mode 100644 sim/bpf/bpf-helpers.h > create mode 100644 sim/bpf/bpf-sim.h > create mode 100644 sim/bpf/bpf.c > create mode 100644 sim/bpf/config.in > create mode 100755 sim/bpf/configure > create mode 100644 sim/bpf/configure.ac > create mode 100644 sim/bpf/decode.h > create mode 100644 sim/bpf/eng.h > create mode 100644 sim/bpf/mloop.in > create mode 100644 sim/bpf/sim-if.c > create mode 100644 sim/bpf/sim-main.h > create mode 100644 sim/bpf/traps.c > create mode 100644 sim/testsuite/sim/bpf/allinsn.exp > create mode 100644 sim/testsuite/sim/bpf/alu.s > create mode 100644 sim/testsuite/sim/bpf/alu32.s > create mode 100644 sim/testsuite/sim/bpf/endbe.s > create mode 100644 sim/testsuite/sim/bpf/endle.s > create mode 100644 sim/testsuite/sim/bpf/jmp.s > create mode 100644 sim/testsuite/sim/bpf/jmp32.s > create mode 100644 sim/testsuite/sim/bpf/ldabs.s > create mode 100644 sim/testsuite/sim/bpf/mem.s > create mode 100644 sim/testsuite/sim/bpf/mov.s > create mode 100644 sim/testsuite/sim/bpf/testutils.inc > create mode 100644 sim/testsuite/sim/bpf/xadd.s > > diff --git a/sim/MAINTAINERS b/sim/MAINTAINERS > index 4ca67cfd1d..7dcd88422c 100644 > --- a/sim/MAINTAINERS > +++ b/sim/MAINTAINERS > @@ -17,6 +17,7 @@ aarch64 Nick Clifton > aarch64 Jim Wilson > arm Nick Clifton > bfin Mike Frysinger > +bpf Jose E. Marchesi > cr16 M R Swami Reddy > frv Dave Brolley > ft32 James Bowman > diff --git a/sim/bpf/Makefile.in b/sim/bpf/Makefile.in > new file mode 100644 > index 0000000000..b12bb6a7d5 > --- /dev/null > +++ b/sim/bpf/Makefile.in > @@ -0,0 +1,205 @@ > +# Makefile template for configure for the eBPF simulator > +# Copyright (C) 2019 Free Software Foundation, Inc. This should probably be 2020 here. > +# > +# This file is part of GDB, the GNU debugger. > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. If not, see . > + > +## COMMON_PRE_CONFIG_FRAG > + > +CGEN_STD_OBJS = cgen-run.o cgen-scache.o cgen-trace.o cgen-utils.o > +BPF_GEN_OBJS = arch.o cpu.o \ > + decode-le.o decode-be.o \ > + sem-le.o sem-be.o \ > + mloop-le.o mloop-be.o > +BPF_HAND_OBJS = bpf.o sim-if.o traps.o bpf-helpers.o > + > +SIM_OBJS = \ > + $(SIM_NEW_COMMON_OBJS) \ > + $(CGEN_STD_OBJS) \ > + $(BPF_GEN_OBJS) \ > + $(BPF_HAND_OBJS) > + > +SIM_EXTRA_DEPS = \ > + $(CGEN_INCLUDE_DEPS) \ > + arch.h \ > + bpf-sim.h \ > + $(srcdir)/../../opcodes/bpf-desc.h \ > + $(srcdir)/../../opcodes/bpf-opc.h > + > +SIM_EXTRA_CLEAN = bpf-clean > + > +## COMMON_POST_CONFIG_FRAG > + > +# cgen support, enable with --enable-cgen-maint > +CGEN_MAIN = ; @true This is a typo, should be CGEN_MAINT here. > +# The following line is commented in or out depending upon --enable-cgen-maint. > +@CGEN_MAINT@CGEN_MAINT = > + > +# BPF headers > + > +BPF_INCLUDE_DEPS = \ > + $(CGEN_MAIN_CPU_DEPS) \ > + $(SIM_EXTRA_DEPS) \ > + cpu.h cpuall.h \ > + decode-le.h decode-be.h \ > + defs-le.h defs-be.h \ > + eng-le.h eng-be.h \ > + config.h > + > +# Dependencies for binaries from CGEN generated source > + > +arch.o: arch.c $(SIM_MAIN_DEPS) > +cpu.o: cpu.c $(BPF_INCLUDE_DEPS) > +decode-le.o: decode-le.c $(BPF_INCLUDE_DEPS) > +decode-be.o: decode-be.c $(BPF_INCLUDE_DEPS) > +# XXX sem-switch.o: sem-switch.c $(BPF_INCLUDE_DEPS) > +# XXX model.o: model.c $(BPF_INCLUDE_DEPS) As I mentioned in my review of patch #1, I'm not a fan of these XXX comments. I'm not going to insist these be removed (where they are limited to the bpf directories), but I don't think things like the above add any value, so I'd prefer they be removed, and you shouldn't assume that these wont be removed in the future. > + > +sim-if.o: sim-if.c $(SIM_MAIN_DEPS) $(srcdir)/../common/sim-core.h eng.h > + $(COMPILE) $< > + $(POSTCOMPILE) > + > +traps.o: traps.c $(SIM_MAIN_DEPS) eng.h > + $(COMPILE) $< > + $(POSTCOMPILE) > + > +mloop-le.o: mloop-le.c $(BPF_INCLUDE_DEPS) > + $(CC) -c mloop-le.c $(ALL_CFLAGS) -DWANT_ISA_EBPFLE > +mloop-be.o: mloop-be.c $(BPF_INCLUDE_DEPS) > + $(CC) -c mloop-be.c $(ALL_CFLAGS) -DWANT_ISA_EBPFBE > + > +decode-le.o: decode-le.c $(BPF_INCLUDE_DEPS) > + $(CC) -c $(srcdir)/decode-le.c $(ALL_CFLAGS) -DWANT_ISA_EBPFLE > +decode-be.o: decode-be.c $(BPF_INCLUDE_DEPS) > + $(CC) -c $(srcdir)/decode-be.c $(ALL_CFLAGS) -DWANT_ISA_EBPFBE > + > +sem-le.o: sem-le.c $(BPF_INCLUDE_DEPS) > + $(CC) -c $(srcdir)/sem-le.c $(ALL_CFLAGS) -DWANT_ISA_EBPFLE > +sem-be.o: sem-be.c $(BPF_INCLUDE_DEPS) > + $(CC) -c $(srcdir)/sem-be.c $(ALL_CFLAGS) -DWANT_ISA_EBPFBE > + > +arch = bpf > + > +CGEN_COMMON_DEPS = \ > + $(CGEN_READ_SCM) \ > + $(srcdir)/../../cpu/bpf.cpu \ > + $(srcdir)/../../cpu/bpf.opc \ > + Makefile > + > +stamp-arch: $(CGEN_COMMON_DEPS) $(CGEN_ARCH_SCM) > + $(MAKE) cgen-arch $(CGEN_FLAGS_TO_PASS) \ > + mach=bpf cpu=bpfbf \ > + archfile=$(srcdir)/../../cpu/bpf.cpu \ > + FLAGS="with-scache" > + touch $@ > +$(srcdir)/arch.h $(srcdir)/arch.c $(srcdir)/cpuall.h: $(CGEN_MAINT) stamp-arch > + @true > + > +stamp-cpu: $(CGEN_COMMON_DEPS) $(CGEN_CPU_SCM) > + $(MAKE) cgen-cpu $(CGEN_FLAGS_TO_PASS) \ > + isa=ebpfle,ebpfbe cpu=bpfbf mach=bpf \ > + archfile=$(srcdir)/../../cpu/bpf.cpu \ > + FLAGS="with-multiple-isa with-scache" > + rm -f $(srcdir)/model.c > + touch $@ > +$(srcdir)/cpu.h $(srcdir)/cpu.c $(srcdir)/model.c: $(CGEN_MAINT) stamp-cpu > + @true > + > +# We need to generate a group of files per ISA. > +# For eBPF little-endian: > +# defs-le.h > +# sem-le.c, decode-le.c, decode-le.h > +# $(objdir)/mloop-le.c $(objdir)/eng-le.h > +# For eBPF big-endian: > +# defs-be.h > +# sem-be.c, decode-be.c, decode-be.h > +# $(objdir)/mloop-be.c $(objdir)/eng-le.h > +# > +# The rules below take care of that. > + > +stamp-defs-le: $(CGEN_COMMON_DEPS) $(CGEN_CPU_SCM) > + $(MAKE) cgen-defs $(CGEN_FLAGS_TO_PASS) \ > + isa=ebpfle cpu=bpfbf mach=bpf \ > + archfile=$(srcdir)/../../cpu/bpf.cpu \ > + FLAGS="with-scache" \ > + SUFFIX="-le" > + touch $@ > +$(srcdir)/defs-le.h: $(CGEN_MAINT) stamp-defs-le > + @true > + > + > +stamp-defs-be: $(CGEN_COMMON_DEPS) $(CGEN_CPU_SCM) > + $(MAKE) cgen-defs $(CGEN_FLAGS_TO_PASS) \ > + isa=ebpfbe cpu=bpfbf mach=bpf \ > + archfile=$(srcdir)/../../cpu/bpf.cpu \ > + FLAGS="with-scache" \ > + SUFFIX="-be" > + touch $@ > +$(srcdir)/defs-be.h: $(CGEN_MAINT) stamp-defs-be > + @true > + > +stamp-decode-le: $(CGEN_COMMON_DEPS) $(CGEN_CPU_SCM) $(GEN_DECODE_SCM) > + $(MAKE) cgen-decode $(CGEN_FLAGS_TO_PASS) \ > + isa=ebpfle cpu=bpfbf mach=bpf \ > + archfile=$(srcdir)/../../cpu/bpf.cpu \ > + FLAGS="with-scache" \ > + SUFFIX="-le" \ > + EXTRAFILES="$(CGEN_CPU_SEM)" > + touch $@ > +$(srcdir)/sem-le.c $(srcdir)/decode-le.c $(srcdir)/decode-le.h: \ > + $(CGEN_MAINT) stamp-decode-le > + @true > + > + > +stamp-decode-be: $(CGEN_COMMON_DEPS) $(CGEN_CPU_SCM) $(GEN_DECODE_SCM) > + $(MAKE) cgen-decode $(CGEN_FLAGS_TO_PASS) \ > + isa=ebpfbe cpu=bpfbf mach=bpf \ > + archfile=$(srcdir)/../../cpu/bpf.cpu \ > + FLAGS="with-scache" \ > + SUFFIX="-be" \ > + EXTRAFILES="$(CGEN_CPU_SEM)" > + touch $@ > +$(srcdir)/sem-be.c $(srcdir)/decode-be.c $(srcdir)/decode-be.h: \ > + $(CGEN_MAINT) stamp-decode-be > + @true > + > +# Note the following files are generated in objdir, not srcdir. > + > +stamp-mloop: stamp-mloop-le stamp-mloop-be > + > +stamp-mloop-le: $(srcdir)/../common/genmloop.sh mloop.in Makefile > + $(SHELL) $(srccom)/genmloop.sh -shell $(SHELL) \ > + -mono -scache -prefix bpfbf_ebpfle -cpu bpfbf \ > + -infile $(srcdir)/mloop.in > + $(SHELL) $(srcroot)/move-if-change eng.hin eng-le.h > + $(SHELL) $(srcroot)/move-if-change mloop.cin mloop-le.c > + touch $@ > +mloop-le.c eng-le.h: stamp-mloop-le > + @true > + > +stamp-mloop-be: $(srcdir)/../common/genmloop.sh mloop.in Makefile > + $(SHELL) $(srccom)/genmloop.sh -shell $(SHELL) \ > + -mono -scache -prefix bpfbf_ebpfbe -cpu bpfbf \ > + -infile $(srcdir)/mloop.in > + $(SHELL) $(srcroot)/move-if-change eng.hin eng-be.h > + $(SHELL) $(srcroot)/move-if-change mloop.cin mloop-be.c > + touch $@ > +mloop-be.c eng-be.h: stamp-mloop-be > + @true > + > +.PHONY = bpf-clean > + > +bpf-clean: > + rm -f stamp-arch stamp-cpu stamp-decode stamp-defs stamp-mloop > diff --git a/sim/bpf/aclocal.m4 b/sim/bpf/aclocal.m4 > new file mode 100644 > index 0000000000..e9f11c775c > --- /dev/null > +++ b/sim/bpf/aclocal.m4 > @@ -0,0 +1,119 @@ > +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- > + > +# Copyright (C) 1996-2017 Free Software Foundation, Inc. > + > +# This file is free software; the Free Software Foundation > +# gives unlimited permission to copy and/or distribute it, > +# with or without modifications, as long as this notice is preserved. > + > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without > +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A > +# PARTICULAR PURPOSE. > + > +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) > +# AM_CONDITIONAL -*- Autoconf -*- > + > +# Copyright (C) 1997-2017 Free Software Foundation, Inc. > +# > +# This file is free software; the Free Software Foundation > +# gives unlimited permission to copy and/or distribute it, > +# with or without modifications, as long as this notice is preserved. > + > +# AM_CONDITIONAL(NAME, SHELL-CONDITION) > +# ------------------------------------- > +# Define a conditional. > +AC_DEFUN([AM_CONDITIONAL], > +[AC_PREREQ([2.52])dnl > + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], > + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl > +AC_SUBST([$1_TRUE])dnl > +AC_SUBST([$1_FALSE])dnl > +_AM_SUBST_NOTMAKE([$1_TRUE])dnl > +_AM_SUBST_NOTMAKE([$1_FALSE])dnl > +m4_define([_AM_COND_VALUE_$1], [$2])dnl > +if $2; then > + $1_TRUE= > + $1_FALSE='#' > +else > + $1_TRUE='#' > + $1_FALSE= > +fi > +AC_CONFIG_COMMANDS_PRE( > +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then > + AC_MSG_ERROR([[conditional "$1" was never defined. > +Usually this means the macro was only invoked conditionally.]]) > +fi])]) > + > +# Copyright (C) 2003-2017 Free Software Foundation, Inc. > +# > +# This file is free software; the Free Software Foundation > +# gives unlimited permission to copy and/or distribute it, > +# with or without modifications, as long as this notice is preserved. > + > +# Check whether the underlying file-system supports filenames > +# with a leading dot. For instance MS-DOS doesn't. > +AC_DEFUN([AM_SET_LEADING_DOT], > +[rm -rf .tst 2>/dev/null > +mkdir .tst 2>/dev/null > +if test -d .tst; then > + am__leading_dot=. > +else > + am__leading_dot=_ > +fi > +rmdir .tst 2>/dev/null > +AC_SUBST([am__leading_dot])]) > + > +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- > +# From Jim Meyering > + > +# Copyright (C) 1996-2017 Free Software Foundation, Inc. > +# > +# This file is free software; the Free Software Foundation > +# gives unlimited permission to copy and/or distribute it, > +# with or without modifications, as long as this notice is preserved. > + > +# AM_MAINTAINER_MODE([DEFAULT-MODE]) > +# ---------------------------------- > +# Control maintainer-specific portions of Makefiles. > +# Default is to disable them, unless 'enable' is passed literally. > +# For symmetry, 'disable' may be passed as well. Anyway, the user > +# can override the default with the --enable/--disable switch. > +AC_DEFUN([AM_MAINTAINER_MODE], > +[m4_case(m4_default([$1], [disable]), > + [enable], [m4_define([am_maintainer_other], [disable])], > + [disable], [m4_define([am_maintainer_other], [enable])], > + [m4_define([am_maintainer_other], [enable]) > + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) > +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) > + dnl maintainer-mode's default is 'disable' unless 'enable' is passed > + AC_ARG_ENABLE([maintainer-mode], > + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], > + am_maintainer_other[ make rules and dependencies not useful > + (and sometimes confusing) to the casual installer])], > + [USE_MAINTAINER_MODE=$enableval], > + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) > + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) > + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) > + MAINT=$MAINTAINER_MODE_TRUE > + AC_SUBST([MAINT])dnl > +] > +) > + > +# Copyright (C) 2006-2017 Free Software Foundation, Inc. > +# > +# This file is free software; the Free Software Foundation > +# gives unlimited permission to copy and/or distribute it, > +# with or without modifications, as long as this notice is preserved. > + > +# _AM_SUBST_NOTMAKE(VARIABLE) > +# --------------------------- > +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. > +# This macro is traced by Automake. > +AC_DEFUN([_AM_SUBST_NOTMAKE]) > + > +# AM_SUBST_NOTMAKE(VARIABLE) > +# -------------------------- > +# Public sister of _AM_SUBST_NOTMAKE. > +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) > + > diff --git a/sim/bpf/bpf-helpers.c b/sim/bpf/bpf-helpers.c > new file mode 100644 > index 0000000000..8d979e0fe0 > --- /dev/null > +++ b/sim/bpf/bpf-helpers.c > @@ -0,0 +1,175 @@ > +/* Emulation of eBPF helpers. > + Copyright (C) 2020 Free Software Foundation, Inc. > + > + This file is part of GDB, the GNU debugger. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +/* BPF programs rely on the existence of several helper functions, > + which are provided by the kernel. This simulator provides an > + implementation of the helpers, which can be customized by the > + user. */ > + > +#define WANT_CPU_BPFBF > +#define WANT_CPU bpfbf > + > +#include "sim-main.h" > +#include "cgen-mem.h" > +#include "cgen-ops.h" > +#include "cpu.h" > + > +/* bpf_trace_printk is a printk-like facility for debugging. > + > + In the kernel, it appends a line to the Linux's tracing debugging > + interface. > + > + In this simulator, it uses the simulator's tracing interface > + instead. > + > + The format tags recognized by this helper are: > + %d, %i, %u, %x, %ld, %li, %lu, %lx, %lld, %lli, %llu, %llx, > + %p, %s > + > + A maximum of three tags are supported. > + > + This helper returns the number of bytes written, or a negative > + value in case of failure. */ > + > +int > +bpf_trace_printk (SIM_CPU *current_cpu) > +{ > + va_list ap; > + SIM_DESC sd = CPU_STATE (current_cpu); > + > + DI fmt_address; > + uint32_t size, tags_processed; > + size_t i, bytes_written = 0; > + > + /* The first argument is the format string, which is passed as a > + pointer in %r1. */ > + fmt_address = GET_H_GPR (1); > + > + /* The second argument is the length of the format string, as an > + unsigned 32-bit number in %r2. */ > + size = GET_H_GPR (2); > + > + /* Read the format string from the memory pointed by %r2, printing > + out the stuff as we go. There is a maximum of three format tags > + supported, which are read from %r3, %r4 and %r5 respectively. */ > + for (i = 0, tags_processed = 0; i < size;) > + { > + QI c = GETMEMUQI (current_cpu, CPU_PC_GET (current_cpu), > + fmt_address + i); > + > + switch (c) > + { > + case '%': > + /* Check we are not exceeding the limit of three format > + tags. */ > + if (tags_processed > 2) > + return -1; /* XXX look for kernel error code. */ > + > + /* Depending on the kind of tag, extract the value from the > + proper argument. */ > + if (i++ >= size) > + return -1; /* XXX look for kernel error code. */ > + > + UDI value = GET_H_GPR (3 + tags_processed); > + > + switch ((GETMEMUQI (current_cpu, CPU_PC_GET (current_cpu), > + fmt_address + i))) > + { > + case 'd': > + trace_printf (sd, current_cpu, "%d", value); > + break; > + case 'i': > + trace_printf (sd, current_cpu, "%i", value); > + break; > + case 'u': > + trace_printf (sd, current_cpu, "%u", value); > + break; > + case 'x': > + trace_printf (sd, current_cpu, "%x", value); > + break; > + case 'l': > + { > + if (i++ >= size) > + return -1; > + switch (GETMEMUQI (current_cpu, CPU_PC_GET (current_cpu), > + fmt_address + i)) > + { > + case 'd': > + trace_printf (sd, current_cpu, "%ld", value); > + break; > + case 'i': > + trace_printf (sd, current_cpu, "%li", value); > + break; > + case 'u': > + trace_printf (sd, current_cpu, "%lu", value); > + break; > + case 'x': > + trace_printf (sd, current_cpu, "%lx", value); > + break; > + case 'l': > + { > + if (i++ >= size) > + return -1; > + switch (GETMEMUQI (current_cpu, CPU_PC_GET (current_cpu), > + fmt_address + i)) { > + case 'd': > + trace_printf (sd, current_cpu, "%lld", value); > + break; > + case 'i': > + trace_printf (sd, current_cpu, "%lli", value); > + break; > + case 'u': > + trace_printf (sd, current_cpu, "%llu", value); > + break; > + case 'x': > + trace_printf (sd, current_cpu, "%llx", value); > + break; > + default: > + assert (0); > + break; > + } > + break; > + } > + default: > + assert (0); > + break; > + } > + break; > + } > + default: > + /* XXX completeme */ > + assert (0); > + break; > + } > + > + tags_processed++; > + i++; > + break; > + case '\0': > + i = size; > + break; > + default: > + trace_printf (sd, current_cpu, "%c", c); > + bytes_written++; > + i++; > + break; > + } > + } > + > + return bytes_written; > +} > diff --git a/sim/bpf/bpf-helpers.def b/sim/bpf/bpf-helpers.def > new file mode 100644 > index 0000000000..6106ac794a > --- /dev/null > +++ b/sim/bpf/bpf-helpers.def > @@ -0,0 +1,194 @@ > +/* BPF helpers database. > + Copyright (C) 2019-2020 Free Software Foundation, Inc. Is this really 2019-2020? If it's copied from some other file that is 2019-2020 then could you mention on the preceding line, just to make it clear. > + > +This file is part of the GNU simulator. > + > +GCC is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3, or (at your option) > +any later version. > + > +GCC is distributed in the hope that it will be useful, > +but WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +GNU General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +. */ > + > +/* This file contains the definition of the helpers that are available > + to BPF programs. > + > + The primary source for information on kernel helpers is the > + linux/include/uapi/linux/bpf.h file in the Linux source tree. > + Please keep this database in sync. > + > + The first column is the first kernel version featuring the helper > + function. This should be an enumerate from bpf_kernel_version, > + defined in bpf-opts.h. Note that the backend assumes that helpers > + never get deprecated in the kernel. If that eventually happens, > + then we will need to use a bitmask here instead of an enumerate. > + > + The second column is the constant-name for the helper. > + The third column is the program-name of the helper. > + > + The fourth column is a list of names describing the types of the > + values returned and accepted by the helper, in one of these forms: > + > + TYPES (type1, type2, ..., 0) > + VTYPES (type1, type2, ..., 0) > + > + VTYPES should be used should the helper accept a variable number of > + arguments, TYPES otherwise. The valid type names are: > + > + `vt' for void. > + `it' for signed int. > + `ut' for unsigned int. > + `pt' for void*. > + `cpt' for const void*. > + `st' for short int. > + `ust' for unsigned short int. > + `cst' for const char *. > + `ullt' for unsigned long long. > + `llt' for long long. > + `u32t' for uint32. > + `u64t' for uint64. > + > + In types descriptions, the firt entry corresponds to the value > + returned by the helper. Subsequent names correspond to the helper > + arguments. Finally, a 0 should close the list. > + > + VERY IMPORTANT: the helper entries should be listed in the same > + order than in the definition of __BPF_FUNC_MAPPER in > + linux/include/uapi/linux/bpf.h! */ > + > +DEF_HELPER (LINUX_V4_0, MAP_LOOKUP_ELEM, map_lookup_elem, TYPES (pt, pt, pt, 0)) > +DEF_HELPER (LINUX_V4_0, MAP_UPDATE_ELEM, map_update_elem, TYPES (it, pt, pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V4_0, MAP_DELETE_ELEM, map_delete_elem, TYPES (it, pt, pt, 0)) > +DEF_HELPER (LINUX_V4_1, PROBE_READ, probe_read, TYPES (it, pt, ut, cpt, 0)) > +DEF_HELPER (LINUX_V4_1, KTIME_GET_NS, ktime_get_ns, TYPES (ullt, 0)) > +DEF_HELPER (LINUX_V4_1, TRACE_PRINTK, trace_printk, VTYPES (it, cst, it, 0)) > +DEF_HELPER (LINUX_V4_1, GET_PRANDOM_U32, get_prandom_u32, TYPES (ullt, 0)) > +DEF_HELPER (LINUX_V4_1, GET_SMP_PROCESSOR_ID, get_smp_processor_id, TYPES (ullt, 0)) > +DEF_HELPER (LINUX_V4_1, SKB_STORE_BYTES, skb_store_bytes, TYPES (it, pt, it, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_1, L3_CSUM_REPLACE, l3_csum_replace, TYPES (it, pt, it, it ,it ,it, 0)) > +DEF_HELPER (LINUX_V4_1, L4_CSUM_REPLACE, l4_csum_replace, TYPES (it, pt, it, it, it, it, 0)) > +DEF_HELPER (LINUX_V4_2, TAIL_CALL, tail_call, TYPES (vt, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_2, CLONE_REDIRECT, clone_redirect, TYPES (it, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_2, GET_CURRENT_PID_TGID, get_current_pid_tgid, TYPES (ullt, 0)) > +DEF_HELPER (LINUX_V4_2, GET_CURRENT_UID_GID, get_current_uid_gid, TYPES (ullt, 0)) > +DEF_HELPER (LINUX_V4_2, GET_CURRENT_COMM, get_current_comm, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_3, GET_CGROUP_CLASSID, get_cgroup_classid, TYPES (it, pt, 0)) > +DEF_HELPER (LINUX_V4_3, SKB_VLAN_PUSH, skb_vlan_push, TYPES (it, pt, st, ust, 0)) > +DEF_HELPER (LINUX_V4_3, SKB_VLAN_POP, skb_vlan_pop, TYPES (it, pt, 0)) > +DEF_HELPER (LINUX_V4_3, SKB_GET_TUNNEL_KEY, skb_get_tunnel_key, TYPES (it, pt, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_3, SKB_SET_TUNNEL_KEY, skb_set_tunnel_key, TYPES (it, pt, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_3, PERF_EVENT_READ, perf_event_read, TYPES (ullt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V4_4, REDIRECT, redirect, TYPES (it, it, it, 0)) > +DEF_HELPER (LINUX_V4_4, GET_ROUTE_REALM, get_route_realm, TYPES (ut, pt, 0)) > +DEF_HELPER (LINUX_V4_4, PERF_EVENT_OUTPUT, perf_event_output, \ > + TYPES (it, pt, pt, ullt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_5, SKB_LOAD_BYTES, skb_load_bytes, TYPES (it, pt, it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_6, GET_STACKID, get_stackid, TYPES (it, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_6, CSUM_DIFF, csum_diff, TYPES (it, pt, it, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_6, SKB_GET_TUNNEL_OPT, skb_get_tunnel_opt, TYPES (it, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_6, SKB_SET_TUNNEL_OPT, skb_set_tunnel_opt, TYPES (it, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_8, SKB_CHANGE_PROTO, skb_change_proto, TYPES (it, pt, st, u64t, 0)) > +DEF_HELPER (LINUX_V4_8, SKB_CHANGE_TYPE, skb_change_type, TYPES (it, pt, u32t, 0)) > +DEF_HELPER (LINUX_V4_8, SKB_UNDER_CGROUP, skb_under_cgroup, TYPES (it, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_8, GET_HASH_RECALC, get_hash_recalc, TYPES (ut, pt, 0)) > +DEF_HELPER (LINUX_V4_8, GET_CURRENT_TASK, get_current_task, TYPES (ullt, 0)) > +DEF_HELPER (LINUX_V4_8, PROBE_WRITE_USER, probe_write_user, TYPES (it, pt, cpt, ut, 0)) > +DEF_HELPER (LINUX_V4_9, CURRENT_TASK_UNDER_CGROUP, current_task_under_cgroup, \ > + TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_9, SKB_CHANGE_TAIL, skb_change_tail, TYPES (it, pt, ut, u64t, 0)) > +DEF_HELPER (LINUX_V4_9, SKB_PULL_DATA, skb_pull_data, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_9, CSUM_UPDATE, csum_update, TYPES (llt, pt, u32t, 0)) > +DEF_HELPER (LINUX_V4_9, SET_HASH_INVALID, set_hash_invalid, TYPES (vt, pt, 0)) > +DEF_HELPER (LINUX_V4_10, GET_NUMA_NODE_ID, get_numa_node_id, TYPES (it, 0)) > +DEF_HELPER (LINUX_V4_10, SKB_CHANGE_HEAD, skb_change_head, TYPES (it, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_10, XDP_ADJUST_HEAD, xdp_adjust_head, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_11, PROBE_READ_STR, probe_read_str, TYPES (it, pt, u32t, cpt, 0)) > +DEF_HELPER (LINUX_V4_12, GET_SOCKET_COOKIE, get_socket_cookie, TYPES (it, pt, 0)) > +DEF_HELPER (LINUX_V4_12, GET_SOCKET_UID, get_socket_uid, TYPES (ut, pt, 0)) > +DEF_HELPER (LINUX_V4_13, SET_HASH, set_hash, TYPES (ut, pt, u32t, 0)) > +DEF_HELPER (LINUX_V4_13, SETSOCKOPT, setsockopt, TYPES (it, pt, it, it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_13, SKB_ADJUST_ROOM, skb_adjust_room, TYPES (it, pt, st, u32t, ullt, 0)) > +DEF_HELPER (LINUX_V4_14, REDIRECT_MAP, redirect_map, TYPES (it, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_14, SK_REDIRECT_MAP, sk_redirect_map, TYPES (it, pt, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_14, SOCK_MAP_UPDATE, sock_map_update, TYPES (it, pt, pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V4_15, XDP_ADJUST_META, xdp_adjust_meta, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_15, PERF_EVENT_READ_VALUE, perf_event_read_value, > + TYPES (it, pt, ullt, pt, ut, 0)) > +DEF_HELPER (LINUX_V4_15, PERF_PROG_READ_VALUE, perf_prog_read_value, > + TYPES (it, pt, pt, ut, 0)) > +DEF_HELPER (LINUX_V4_15, GETSOCKOPT, getsockopt, TYPES (it, pt, it, it, pt, it, 0)) > + > +DEF_HELPER (LINUX_V4_16, OVERRIDE_RETURN, override_return, TYPES (it, pt, ult, 0)) > +DEF_HELPER (LINUX_V4_16, SOCK_OPS_CB_FLAGS_SET, sock_ops_cb_flags_set, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_17, MSG_REDIRECT_MAP, msg_redirect_map, TYPES (it, pt, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_17, MSG_APPLY_BYTES, msg_apply_bytes, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_17, MSG_CORK_BYTES, msg_cork_bytes, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_17, MSG_PULL_DATA, msg_pull_data, TYPES (it, pt, it, it, it, 0)) > +DEF_HELPER (LINUX_V4_17, BIND, bind, TYPES (it, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_18, XDP_ADJUST_TAIL, xdp_adjust_tail, TYPES (it, pt, it, 0)) > +DEF_HELPER (LINUX_V4_18, SKB_GET_XFRM_STATE, > + skb_get_xfrm_state, TYPES (it, pt, it, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_18, GET_STACK, get_stack, TYPES (it, pt, pt, it, it, 0)) > +DEF_HELPER (LINUX_V4_18, SKB_LOAD_BYTES_RELATIVE, skb_load_bytes_relative, > + TYPES (it, pt, it, pt, it, ut, 0)) > +DEF_HELPER (LINUX_V4_18, FIB_LOOKUP, fib_lookup, TYPES (it, pt, pt, it, ut, 0)) > +DEF_HELPER (LINUX_V4_18, SOCK_HASH_UPDATE, sock_hash_update, TYPES (it, pt, pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V4_18, MSG_REDIRECT_HASH, msg_redirect_hash, TYPES (it, pt, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_18, SK_REDIRECT_HASH, sk_redirect_hash, TYPES (it, pt, pt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_18, LWT_PUSH_ENCAP, lwt_push_encap, TYPES (it, pt, ut, pt, ut, 0)) > +DEF_HELPER (LINUX_V4_18, LWT_SEG6_STORE_BYTES, lwt_seg6_store_bytes, > + TYPES (it, pt, ut, pt, ut, 0)) > +DEF_HELPER (LINUX_V4_18, LWT_SEG6_ADJUST_SRH, lwt_seg6_adjust_srh, TYPES (it, pt, ut, ut, 0)) > +DEF_HELPER (LINUX_V4_18, LWT_SEG6_ACTION, lwt_seg6_action, TYPES (it, pt, ut, pt, ut, 0)) > +DEF_HELPER (LINUX_V4_18, RC_REPEAT, rc_repeat, TYPES (it, pt, 0)) > +DEF_HELPER (LINUX_V4_18, RC_KEYDOWN, rc_keydown, TYPES (it, pt, ut, ullt, ut, 0)) > +DEF_HELPER (LINUX_V4_18, SKB_CGROUP_ID, skb_cgroup_id, TYPES (ullt, pt, 0)) > +DEF_HELPER (LINUX_V4_18, GET_CURRENT_CGROUP_ID, get_current_cgroup_id, TYPES (ullt, 0)) > +DEF_HELPER (LINUX_V4_19, GET_LOCAL_STORAGE, get_local_storage, TYPES (pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V4_19, SK_SELECT_REUSEPORT, sk_select_reuseport, > + TYPES (it, pt, pt, pt, ut, 0)) > +DEF_HELPER (LINUX_V4_19, SKB_ANCESTOR_CGROUP_ID, skb_ancestor_cgroup_id, > + TYPES (ullt, pt, it, 0)) > +DEF_HELPER (LINUX_V4_20, SK_LOOKUP_TCP, sk_lookup_tcp, TYPES (pt, pt, pt, it, ullt, ullt, 0)) > +DEF_HELPER (LINUX_V4_20, SK_LOOKUP_UDP, sk_lookup_udp, TYPES (pt, pt, pt, it, ullt, ullt, 0)) > +DEF_HELPER (LINUX_V4_20, SK_RELEASE, sk_release, TYPES (it, pt, 0)) > +DEF_HELPER (LINUX_V4_20, MAP_PUSH_ELEM, map_push_elem, TYPES (it, pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V4_20, MAP_POP_ELEM, map_pop_elem, TYPES (it, pt, pt, 0)) > +DEF_HELPER (LINUX_V4_20, MAP_PEEK_ELEM, map_peek_elem, TYPES (it, pt, pt, 0)) > +DEF_HELPER (LINUX_V4_20, MSG_PUSH_DATA, msg_push_data, TYPES (it, pt, it, it, it, 0)) > +DEF_HELPER (LINUX_V5_0, MSG_POP_DATA, msg_pop_data, TYPES (it, pt, it, it, it, 0)) > +DEF_HELPER (LINUX_V5_0, RC_POINTER_REL, rc_pointer_rel, TYPES (it, pt, it, it, 0)) > +DEF_HELPER (LINUX_V5_1, SPIN_LOCK, spin_lock, TYPES (vt, pt, 0)) > +DEF_HELPER (LINUX_V5_1, SPIN_UNLOCK, spin_unlock, TYPES (vt, pt, 0)) > +DEF_HELPER (LINUX_V5_1, SK_FULLSOCK, sk_fullsock, TYPES (pt, pt, 0)) > +DEF_HELPER (LINUX_V5_1, TCP_SOCK, tcp_sock, TYPES (pt, pt, 0)) > +DEF_HELPER (LINUX_V5_1, SKB_ECN_SET_CE, skb_ecn_set_ce, TYPES (it, pt, 0)) > +DEF_HELPER (LINUX_V5_1, GET_LISTENER_SOCK, get_listener_sock, TYPES (pt, pt, 0)) > +DEF_HELPER (LINUX_V5_2, SKC_LOOKUP_TCP, skc_lookup_tcp, > + TYPES (pt, pt, pt, u32t, u64t, u64t, 0)) > +DEF_HELPER (LINUX_V5_2, TCP_CHECK_SYNCOOKIE, tcp_check_syncookie, > + TYPES (it, pt, pt, u32t, pt, u32t, 0)) > +DEF_HELPER (LINUX_V5_2, SYSCTL_GET_NAME, sysctl_get_name, TYPES (it, pt, pt, ullt, u64t, 0)) > +DEF_HELPER (LINUX_V5_2, SYSCTL_GET_CURRENT_VALUE, sysctl_get_current_value, > + TYPES (it, pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V5_2, SYSCTL_GET_NEW_VALUE, sysctl_get_new_value, > + TYPES (it, pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V5_2, SYSCTL_SET_NEW_VALUE, sysctl_set_new_value, > + TYPES (it, pt, pt, ullt, 0)) > +DEF_HELPER (LINUX_V5_2, STRTOL, strtol, TYPES (it, cst, ullt, u64t, pt, 0)) > +DEF_HELPER (LINUX_V5_2, STRTOUL, strtoul, TYPES (it, pt, ullt, u64t, pt, 0)) > +DEF_HELPER (LINUX_V5_2, SK_STORAGE_GET, sk_storage_get, TYPES (pt, pt, pt, pt, u64t, 0)) > +DEF_HELPER (LINUX_V5_2, SK_STORAGE_DELETE, sk_storage_delete, TYPES (it, pt, pt, 0)) > + > +/* > +Local variables: > +mode:c > +End: > +*/ > diff --git a/sim/bpf/bpf-helpers.h b/sim/bpf/bpf-helpers.h > new file mode 100644 > index 0000000000..fe9413f266 > --- /dev/null > +++ b/sim/bpf/bpf-helpers.h > @@ -0,0 +1,31 @@ > +/* Emulation of eBPF helpers. Interface. > + Copyright (C) 2020 Free Software Foundation, Inc. > + > + This file is part of GDB, the GNU debugger. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#ifndef BPF_HELPERS_H > +#define BPF_HELPERS_H > + > +enum bpf_kernel_helper > + { > +#define DEF_HELPER(kver, name, fn, types) name, > +#include "bpf-helpers.def" > +#undef DEF_HELPER > + }; > + > +/* void bpf_trace_printk (const char *fmt); */ > + > +#endif /* ! BPF_HELPERS_H */ > diff --git a/sim/bpf/bpf-sim.h b/sim/bpf/bpf-sim.h > new file mode 100644 > index 0000000000..6b5c275cd5 > --- /dev/null > +++ b/sim/bpf/bpf-sim.h > @@ -0,0 +1,31 @@ > +/* eBPF simulator support code header > + Copyright (C) 2020 Free Software Foundation, Inc. > + > + This file is part of GDB, the GNU debugger. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#ifndef BPF_SIM_H > +#define BPF_SIM_H > + > +void bpfbf_insn_before (sim_cpu* current_cpu, SEM_PC vpc, const IDESC *idesc); > +void bpfbf_insn_after (sim_cpu* current_cpu, SEM_PC vpc, const IDESC *idesc); > + > +DI bpfbf_endbe (SIM_CPU *, DI, UINT); > +DI bpfbf_endle (SIM_CPU *, DI, UINT); > +DI bpfbf_skb_data_offset (SIM_CPU *); > +VOID bpfbf_call (SIM_CPU *, INT, UINT); > +VOID bpfbf_exit (SIM_CPU *); > + > +#endif /* ! BPF_SIM_H */ > diff --git a/sim/bpf/bpf.c b/sim/bpf/bpf.c > new file mode 100644 > index 0000000000..766b7ddc1c > --- /dev/null > +++ b/sim/bpf/bpf.c > @@ -0,0 +1,327 @@ > +/* eBPF simulator support code > + Copyright (C) 2020 Free Software Foundation, Inc. > + > + This file is part of GDB, the GNU debugger. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#define WANT_CPU_BPFBF > +#define WANT_CPU bpfbf > + > +#include "sim-main.h" > +#include "sim-fpu.h" > +#include "cgen-mem.h" > +#include "cgen-ops.h" > +#include "cpuall.h" > +#include "decode.h" > + > +#include "defs-le.h" /* For SCACHE */ > + > +/* It is not possible to include both defs-le.h and defs-be.h due to > + duplicated definitions, so we need a bunch of forward declarations > + here. */ > +extern void bpfbf_ebpfle_init_idesc_table (SIM_CPU *); > +extern void bpfbf_ebpfbe_init_idesc_table (SIM_CPU *); > + > +uint64_t skb_data_offset; > + > +IDESC *bpf_idesc_le; > +IDESC *bpf_idesc_be; > + > + > +int > +bpfbf_fetch_register (SIM_CPU *current_cpu, > + int rn, > + unsigned char *buf, > + int len) > +{ > + if (rn == 11) > + SETTDI (buf, CPU_PC_GET (current_cpu)); > + else if (0 <= rn && rn < 10) > + SETTDI (buf, GET_H_GPR (rn)); > + else > + return 0; > + > + return len; > +} > + > +int > +bpfbf_store_register (SIM_CPU *current_cpu, > + int rn, > + unsigned char *buf, > + int len) > +{ > + if (rn == 11) > + CPU_PC_SET (current_cpu, GETTDI (buf)); > + else if (0 <= rn && rn < 10) > + SET_H_GPR (rn, GETTDI (buf)); > + else > + return 0; > + > + return len; > +} > + > +void > +bpfbf_model_insn_before (SIM_CPU *current_cpu, int first_p) > +{ > + /* XXX */ > +} > + > +void > +bpfbf_model_insn_after (SIM_CPU *current_cpu, int first_p) > +{ > + /* XXX */ > +} > + > + > +/***** Instruction helpers. *****/ > + > +/* The semantic routines for most instructions are expressed in RTL in > + the cpu/bpf.cpu file, and automatically translated to C in the > + sem-*.c files in this directory. > + > + However, some of the semantic routines make use of helper C > + functions. This happens when the semantics of the instructions > + can't be expressed in RTL alone in a satisfactory way, or not at > + all. > + > + The following functions implement these C helpers. */ > + > +DI > +bpfbf_endle (SIM_CPU *current_cpu, DI value, UINT bitsize) > +{ > + switch (bitsize) > + { > + case 16: return endian_h2le_2(endian_t2h_2(value)); > + case 32: return endian_h2le_4(endian_t2h_4(value)); > + case 64: return endian_h2le_8(endian_t2h_8(value)); > + default: assert(0); > + } > + return value; > +} > + > +DI > +bpfbf_endbe (SIM_CPU *current_cpu, DI value, UINT bitsize) > +{ > + switch (bitsize) > + { > + case 16: return endian_h2be_2(endian_t2h_2(value)); > + case 32: return endian_h2be_4(endian_t2h_4(value)); > + case 64: return endian_h2be_8(endian_t2h_8(value)); > + default: assert(0); > + } > + return value; > +} > + > +DI > +bpfbf_skb_data_offset (SIM_CPU *current_cpu) > +{ > + /* Simply return the user-configured value. > + This will be 0 if it has not been set. */ > + return skb_data_offset; > +} > + > + > +VOID > +bpfbf_call (SIM_CPU *current_cpu, INT disp32, UINT src) > +{ > + /* eBPF supports two kind of CALL instructions: the so called pseudo > + calls ("bpf to bpf") and external calls ("bpf to helper"). > + > + Both kind of calls use the same instruction (CALL). However, > + external calls are constructed by passing a constant argument to > + the instruction, that identifies the helper, whereas pseudo calls > + result from expressions involving symbols. > + > + We distinguish calls from pseudo-calls with the later having a 1 > + stored in the SRC field of the instruction. */ > + > + if (src == 1) > + { > + /* This is a pseudo-call. */ > + > + /* XXX allocate a new stack frame and transfer control. For > + that we need to analyze the target function, like the kernel > + verifier does. We better populate a cache > + (function_start_address -> frame_size) so we avoid > + calculating this more than once. */ > + /* XXX note that disp32 is PC-relative in number of 64-bit > + words, _minus one_. */ > + } > + else > + { > + /* This is a call to a helper. > + > + DISP32 contains the helper number. Dispatch to the > + corresponding helper emulator in bpf-helpers.c. */ > + > + switch (disp32) { > + /* case TRACE_PRINTK: */ > + case 7: > + bpf_trace_printk (current_cpu); > + break; > + default:; > + } > + } > +} > + > +VOID > +bpfbf_exit (SIM_CPU *current_cpu) > +{ > + SIM_DESC sd = CPU_STATE (current_cpu); > + > + /* r0 holds "return code" */ > + DI r0 = GET_H_GPR (0); > + > + printf ("exit %ld (0x%lx)\n", r0, r0); > + > + sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu), > + sim_exited, 0 /* sigrc */); > +} > + > +VOID > +bpfbf_breakpoint (SIM_CPU *current_cpu) > +{ > + SIM_DESC sd = CPU_STATE (current_cpu); > + > + sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu), > + sim_stopped, SIM_SIGTRAP); > +} > + > +/* We use the definitions below instead of the cgen-generated model.c, > + because the later is not really able to work with cpus featuring > + several ISAs. This should be fixed in CGEN. */ > + > +static void > +bpf_def_model_init () > +{ > + /* Do nothing. */ > +} > + > +static void > +bpfbf_prepare_run (SIM_CPU *cpu) > +{ > + /* Nothing. */ > +} > + > +void > +bpf_engine_run_full (SIM_CPU *cpu) > +{ > + if (current_target_byte_order == BFD_ENDIAN_LITTLE) > + { > + if (!bpf_idesc_le) > + { > + bpfbf_ebpfle_init_idesc_table (cpu); > + bpf_idesc_le = CPU_IDESC (cpu); > + } > + else > + CPU_IDESC (cpu) = bpf_idesc_le; > + > + bpfbf_ebpfle_engine_run_full (cpu); > + } > + else > + { > + if (!bpf_idesc_be) > + { > + bpfbf_ebpfbe_init_idesc_table (cpu); > + bpf_idesc_be = CPU_IDESC (cpu); > + } > + else > + CPU_IDESC (cpu) = bpf_idesc_be; > + > + bpfbf_ebpfbe_engine_run_full (cpu); > + } > +} > + > +#if WITH_FAST > + > +void > +bpf_engine_run_fast (SIM_CPU *cpu) > +{ > + if (current_target_byte_order == BFD_ENDIAN_LITTLE) > + { > + if (!bpf_idesc_le) > + { > + bpfbf_ebpfle_init_idesc_table (cpu); > + bpf_idesc_le = CPU_IDESC (cpu); > + } > + else > + CPU_IDESC (cpu) = bpf_idesc_le; > + > + bpfbf_ebpfle_engine_run_fast (cpu); > + } > + else > + { > + if (!bpf_idesc_be) > + { > + bpfbf_ebpfbe_init_idesc_table (cpu); > + bpf_idesc_be = CPU_IDESC (cpu); > + } > + else > + CPU_IDESC (cpu) = bpf_idesc_be; > + > + bpfbf_ebpfbe_engine_run_fast (cpu); > + } > +} > + > +#endif /* WITH_FAST */ > + > +static const CGEN_INSN * > +bpfbf_get_idata (SIM_CPU *cpu, int inum) > +{ > + return CPU_IDESC (cpu) [inum].idata; > +} > + > +static void > +bpf_init_cpu (SIM_CPU *cpu) > +{ > + CPU_REG_FETCH (cpu) = bpfbf_fetch_register; > + CPU_REG_STORE (cpu) = bpfbf_store_register; > + CPU_PC_FETCH (cpu) = bpfbf_h_pc_get; > + CPU_PC_STORE (cpu) = bpfbf_h_pc_set; > + CPU_GET_IDATA (cpu) = bpfbf_get_idata; > + /* Only used by profiling. 0 disables it. */ > + CPU_MAX_INSNS (cpu) = 0; > + CPU_INSN_NAME (cpu) = cgen_insn_name; > + CPU_FULL_ENGINE_FN (cpu) = bpf_engine_run_full; > +#if WITH_FAST > + CPU_FAST_ENGINE_FN (cpu) = bpf_engine_run_fast; > +#else > + CPU_FAST_ENGINE_FN (cpu) = bpf_engine_run_full; > +#endif > +} > + > +static const SIM_MODEL bpf_models[] = > +{ > + { "bpf-def", & bpf_mach, MODEL_BPF_DEF, NULL, bpf_def_model_init }, > + { 0 } > +}; > + > +static const SIM_MACH_IMP_PROPERTIES bpfbf_imp_properties = > +{ > + sizeof (SIM_CPU), > +#if WITH_SCACHE > + sizeof (SCACHE) > +#else > + 0 > +#endif > +}; > + > +const SIM_MACH bpf_mach = > +{ > + "bpf", "bpf", MACH_BPF, > + 32, 32, & bpf_models[0], & bpfbf_imp_properties, > + bpf_init_cpu, > + bpfbf_prepare_run > +}; > diff --git a/sim/bpf/config.in b/sim/bpf/config.in > new file mode 100644 > index 0000000000..7c667a1c0d > --- /dev/null > +++ b/sim/bpf/config.in > @@ -0,0 +1,248 @@ > +/* config.in. Generated from configure.ac by autoheader. */ > + > +/* Define if building universal (internal helper macro) */ > +#undef AC_APPLE_UNIVERSAL_BUILD > + > +/* Sim debug setting */ > +#undef DEBUG > + > +/* Define to 1 if translation of program messages to the user's native > + language is requested. */ > +#undef ENABLE_NLS > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_DLFCN_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_ERRNO_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_FCNTL_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_FPU_CONTROL_H > + > +/* Define to 1 if you have the `ftruncate' function. */ > +#undef HAVE_FTRUNCATE > + > +/* Define to 1 if you have the `getrusage' function. */ > +#undef HAVE_GETRUSAGE > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_INTTYPES_H > + > +/* Define to 1 if you have the `nsl' library (-lnsl). */ > +#undef HAVE_LIBNSL > + > +/* Define to 1 if you have the `socket' library (-lsocket). */ > +#undef HAVE_LIBSOCKET > + > +/* Define to 1 if you have the `lstat' function. */ > +#undef HAVE_LSTAT > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_MEMORY_H > + > +/* Define to 1 if you have the `mmap' function. */ > +#undef HAVE_MMAP > + > +/* Define to 1 if you have the `munmap' function. */ > +#undef HAVE_MUNMAP > + > +/* Define to 1 if you have the `posix_fallocate' function. */ > +#undef HAVE_POSIX_FALLOCATE > + > +/* Define to 1 if you have the `sigaction' function. */ > +#undef HAVE_SIGACTION > + > +/* Define to 1 if the system has the type `socklen_t'. */ > +#undef HAVE_SOCKLEN_T > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_STDINT_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_STDLIB_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_STRINGS_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_STRING_H > + > +/* Define to 1 if `st_atime' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_ATIME > + > +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_BLKSIZE > + > +/* Define to 1 if `st_blocks' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_BLOCKS > + > +/* Define to 1 if `st_ctime' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_CTIME > + > +/* Define to 1 if `st_dev' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_DEV > + > +/* Define to 1 if `st_gid' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_GID > + > +/* Define to 1 if `st_ino' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_INO > + > +/* Define to 1 if `st_mode' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_MODE > + > +/* Define to 1 if `st_mtime' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_MTIME > + > +/* Define to 1 if `st_nlink' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_NLINK > + > +/* Define to 1 if `st_rdev' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_RDEV > + > +/* Define to 1 if `st_size' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_SIZE > + > +/* Define to 1 if `st_uid' is a member of `struct stat'. */ > +#undef HAVE_STRUCT_STAT_ST_UID > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_SYS_MMAN_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_SYS_RESOURCE_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_SYS_STAT_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_SYS_TIMES_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_SYS_TIME_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_SYS_TYPES_H > + > +/* Define to 1 if you have the `time' function. */ > +#undef HAVE_TIME > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_TIME_H > + > +/* Define to 1 if you have the `truncate' function. */ > +#undef HAVE_TRUNCATE > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_UNISTD_H > + > +/* Define to 1 if you have the header file. */ > +#undef HAVE_WINDOWS_H > + > +/* Define to 1 if you have the `__setfpucw' function. */ > +#undef HAVE___SETFPUCW > + > +/* Define to the sub-directory in which libtool stores uninstalled libraries. > + */ > +#undef LT_OBJDIR > + > +/* Name of this package. */ > +#undef PACKAGE > + > +/* Define to the address where bug reports for this package should be sent. */ > +#undef PACKAGE_BUGREPORT > + > +/* Define to the full name of this package. */ > +#undef PACKAGE_NAME > + > +/* Define to the full name and version of this package. */ > +#undef PACKAGE_STRING > + > +/* Define to the one symbol short name of this package. */ > +#undef PACKAGE_TARNAME > + > +/* Define to the home page for this package. */ > +#undef PACKAGE_URL > + > +/* Define to the version of this package. */ > +#undef PACKAGE_VERSION > + > +/* Additional package description */ > +#undef PKGVERSION > + > +/* Sim profile settings */ > +#undef PROFILE > + > +/* Bug reporting address */ > +#undef REPORT_BUGS_TO > + > +/* Define as the return type of signal handlers (`int' or `void'). */ > +#undef RETSIGTYPE > + > +/* Define to 1 if you have the ANSI C header files. */ > +#undef STDC_HEADERS > + > +/* Enable extensions on AIX 3, Interix. */ > +#ifndef _ALL_SOURCE > +# undef _ALL_SOURCE > +#endif > +/* Enable GNU extensions on systems that have them. */ > +#ifndef _GNU_SOURCE > +# undef _GNU_SOURCE > +#endif > +/* Enable threading extensions on Solaris. */ > +#ifndef _POSIX_PTHREAD_SEMANTICS > +# undef _POSIX_PTHREAD_SEMANTICS > +#endif > +/* Enable extensions on HP NonStop. */ > +#ifndef _TANDEM_SOURCE > +# undef _TANDEM_SOURCE > +#endif > +/* Enable general extensions on Solaris. */ > +#ifndef __EXTENSIONS__ > +# undef __EXTENSIONS__ > +#endif > + > + > +/* Sim assert settings */ > +#undef WITH_ASSERT > + > +/* Sim debug setting */ > +#undef WITH_DEBUG > + > +/* Sim default environment */ > +#undef WITH_ENVIRONMENT > + > +/* Sim profile settings */ > +#undef WITH_PROFILE > + > +/* How to route I/O */ > +#undef WITH_STDIO > + > +/* Sim trace settings */ > +#undef WITH_TRACE > + > +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most > + significant byte first (like Motorola and SPARC, unlike Intel). */ > +#if defined AC_APPLE_UNIVERSAL_BUILD > +# if defined __BIG_ENDIAN__ > +# define WORDS_BIGENDIAN 1 > +# endif > +#else > +# ifndef WORDS_BIGENDIAN > +# undef WORDS_BIGENDIAN > +# endif > +#endif > + > +/* Define to 1 if on MINIX. */ > +#undef _MINIX > + > +/* Define to 2 if the system does not provide POSIX.1 features except with > + this defined. */ > +#undef _POSIX_1_SOURCE > + > +/* Define to 1 if you need to in order for `stat' and other things to work. */ > +#undef _POSIX_SOURCE > diff --git a/sim/bpf/configure.ac b/sim/bpf/configure.ac > new file mode 100644 > index 0000000000..16ca54e86c > --- /dev/null > +++ b/sim/bpf/configure.ac > @@ -0,0 +1,13 @@ > +dnl Process this file with autoconf to produce a configure script. > +AC_INIT(Makefile.in) > +sinclude(../common/acinclude.m4) > + > +SIM_AC_COMMON > + > +SIM_AC_OPTION_ENDIAN([], [LITTLE]) > +SIM_AC_OPTION_ALIGNMENT(NONSTRICT_ALIGNMENT) > +SIM_AC_OPTION_SCACHE(16384) > +SIM_AC_OPTION_DEFAULT_MODEL([bpf-def]) > +SIM_AC_OPTION_CGEN_MAINT > + > +SIM_AC_OUTPUT > diff --git a/sim/bpf/decode.h b/sim/bpf/decode.h > new file mode 100644 > index 0000000000..74d31cbdfe > --- /dev/null > +++ b/sim/bpf/decode.h > @@ -0,0 +1,37 @@ > +/* Decode declarations. > + Copyright (C) 2020 Free Software Foundation, Inc. > + Contributed by Oracle, Inc. > + > +This file is part of the GNU simulators. > + > +This program is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3 of the License, or > +(at your option) any later version. > + > +This program is distributed in the hope that it will be useful, > +but WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +GNU General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with this program. If not, see . */ > + > +/* Include declarations for eBPF LE and eBPF BE ISAs. */ > + > +#ifndef DECODE_H > +#define DECODE_H > + > +#undef WITH_PROFILE_MODEL_P > + > +#ifdef WANT_ISA_EBPFLE > +#include "decode-le.h" > +#include "defs-le.h" > +#endif /* WANT_ISA_EBPFLE */ > + > +#ifdef WANT_ISA_EBPFBE > +#include "decode-be.h" > +#include "defs-be.h" > +#endif /* WANT_ISA_EBPFBE */ > + > +#endif /* DECODE_H */ > diff --git a/sim/bpf/eng.h b/sim/bpf/eng.h > new file mode 100644 > index 0000000000..08e29f99a8 > --- /dev/null > +++ b/sim/bpf/eng.h > @@ -0,0 +1,24 @@ > +/* Engine declarations. > + Copyright (C) 2020 Free Software Foundation, Inc. > + Contributed by Oracle, Inc. > + > +This file is part of the GNU simulators. > + > +This program is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3 of the License, or > +(at your option) any later version. > + > +This program is distributed in the hope that it will be useful, > +but WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +GNU General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with this program. If not, see . */ > + > +/* Include declarations for eBPF LE and eBPF BE ISAs. */ > + > +#include "eng-le.h" > +#include "eng-be.h" > + > diff --git a/sim/bpf/mloop.in b/sim/bpf/mloop.in > new file mode 100644 > index 0000000000..2661eed8a8 > --- /dev/null > +++ b/sim/bpf/mloop.in > @@ -0,0 +1,165 @@ > +# Simulator main loop for eBPF. -*- C -*- > +# > +# Copyright (C) 2020 Free Software Foundation, Inc. > +# > +# This file is part of the GNU Simulators. > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. If not, see . > + > +# Syntax: > +# /bin/sh mloop.in command > +# > +# Command is one of: > +# > +# init > +# support > +# extract-{simple,scache,pbb} > +# {full,fast}-exec-{simple,scache,pbb} > +# > +# A target need only provide a "full" version of one of simple,scache,pbb. > +# If the target wants it can also provide a fast version of same, or if > +# the slow (full featured) version is `simple', then the fast version can be > +# one of scache/pbb. > +# A target can't provide more than this. > +# However for illustration's sake this file provides examples of all. > + > +# ??? After a few more ports are done, revisit. > +# Will eventually need to machine generate a lot of this. > + > +case "x$1" in > + > +xsupport) > + > +cat < + > +static INLINE const IDESC * > +extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_WORD insn, > + ARGBUF *abuf, int fast_p) > +{ > + const IDESC *id = @prefix@_decode (current_cpu, pc, insn, abuf); > + @prefix@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); > + if (!fast_p) > + { > + int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); > + int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); > + @prefix@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); > + } > + return id; > +} > + > +static INLINE SEM_PC > +execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) > +{ > + SEM_PC vpc; > + > + if (fast_p) > + vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); > + else > + { > + ARGBUF *abuf = &sc->argbuf; > + const IDESC *idesc = abuf->idesc; > + const CGEN_INSN *idata = idesc->idata; > + int virtual_p = 0; > + > + if (! virtual_p) > + { > + /* FIXME: call x-before */ > + if (ARGBUF_PROFILE_P (abuf)) > + PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); > + /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ > + if (PROFILE_MODEL_P (current_cpu) > + && ARGBUF_PROFILE_P (abuf)) > + @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); > + CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); > + CGEN_TRACE_INSN (current_cpu, idata, > + (const struct argbuf *) abuf, abuf->addr); > + } > + vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); > + if (! virtual_p) > + { > + /* FIXME: call x-after */ > + if (PROFILE_MODEL_P (current_cpu) > + && ARGBUF_PROFILE_P (abuf)) > + { > + int cycles; > + > + cycles = (*idesc->timing->model_fn) (current_cpu, sc); > + @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); > + } > + CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); > + } > + } > + > + return vpc; > +} > + > +EOF > + > +;; > + > +xinit) > + > +# Nothing needed. > + > +;; > + > +xextract-scache) > + > +cat < +{ > + > + UDI insn = GETIMEMUDI (current_cpu, vpc); > + > + if (current_target_byte_order == BFD_ENDIAN_BIG) > + { > + /* eBPF instructions are little-endian, but GETIMEMUDI reads according > + to target byte order. Swap to little-endian. */ > + insn = SWAP_8 (insn); > + > + /* But, the imm32 and offset16 fields within instructions follow target > + byte order. Swap those fields back. */ > + UHI off16 = (UHI) ((insn & 0x00000000ffff0000) >> 16); > + USI imm32 = (USI) ((insn & 0xffffffff00000000) >> 32); > + off16 = SWAP_2 (off16); > + imm32 = SWAP_4 (imm32); > + > + insn = (((UDI) imm32) << 32) | (((UDI) off16) << 16) | (insn & 0xffff); > + } > + > + extract (current_cpu, vpc, insn, sc, FAST_P); > + > + //XXX SEM_SKIP_COMPILE (current_cpu, sc, 1); Comments are /* ... */ please. Please don't leave random lines commented out like this though. There should be a comment that explains why the lines commented out. > +} > +EOF > + > +;; > + > +xfull-exec-* | xfast-exec-*) > + > +# Inputs: current_cpu, vpc, sc, FAST_P > +# Outputs: vpc > +# vpc is the virtual program counter. > + > +cat < + vpc = execute (current_cpu, sc, FAST_P); > +EOF > + > +;; > + > +*) > + echo "Invalid argument to mainloop.in: $1" >&2 > + exit 1 > + ;; > + > +esac > diff --git a/sim/bpf/sim-if.c b/sim/bpf/sim-if.c > new file mode 100644 > index 0000000000..964cc705eb > --- /dev/null > +++ b/sim/bpf/sim-if.c > @@ -0,0 +1,216 @@ > +/* Main simulator entry points specific to the eBPF. > + Copyright (C) 2020 Free Software Foundation, Inc. > + > + This file is part of GDB, the GNU debugger. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#include "sim-main.h" > +#include "sim-options.h" > +#include "libiberty.h" > +#include "bfd.h" > + > +/* Globals. */ > + > +/* String with the name of the section containing the BPF program to > + run. */ > +static char *bpf_program_section = NULL; > + > +extern uint64_t skb_data_offset; > + > + > +/* Handle BPF-specific options. */ > + > +static SIM_RC bpf_option_handler (SIM_DESC, sim_cpu *, int, char *, int); > + > +typedef enum > +{ > + OPTION_BPF_SET_PROGRAM = OPTION_START, > + OPTION_BPF_LIST_PROGRAMS, > + OPTION_BPF_VERIFY_PROGRAM, > + OPTION_BPF_SKB_DATA_OFFSET, > +} BPF_OPTION; > + > +static const OPTION bpf_options[] = > +{ > + { {"bpf-set-program", required_argument, NULL, OPTION_BPF_SET_PROGRAM}, > + '\0', "SECTION_NAME", "Set the entry point", > + bpf_option_handler }, > + { {"bpf-list-programs", no_argument, NULL, OPTION_BPF_LIST_PROGRAMS}, > + '\0', "", "List loaded bpf programs", > + bpf_option_handler }, > + { {"bpf-verify-program", required_argument, NULL, OPTION_BPF_VERIFY_PROGRAM}, > + '\0', "PROGRAM", "Run the verifier on the given BPF program", > + bpf_option_handler }, > + { {"skb-data-offset", required_argument, NULL, OPTION_BPF_SKB_DATA_OFFSET}, > + '\0', "OFFSET", "Configure offsetof(struct sk_buff, data)", > + bpf_option_handler }, > + > + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } > +}; > + > +static SIM_RC > +bpf_option_handler (SIM_DESC sd, sim_cpu *cpu ATTRIBUTE_UNUSED, int opt, > + char *arg, int is_command ATTRIBUTE_UNUSED) > +{ > + switch ((BPF_OPTION) opt) > + { > + case OPTION_BPF_VERIFY_PROGRAM: > + /* XXX call the verifier. */ > + sim_io_printf (sd, "Verifying BPF program %s...\n", arg); > + break; > + > + case OPTION_BPF_LIST_PROGRAMS: > + /* XXX list programs. */ > + sim_io_printf (sd, "BPF programs available:\n"); > + break; > + > + case OPTION_BPF_SET_PROGRAM: > + /* XXX: check that the section exists and tell the user about a > + new start_address. */ > + bpf_program_section = xstrdup (arg); > + break; > + > + case OPTION_BPF_SKB_DATA_OFFSET: > + skb_data_offset = strtoul (arg, NULL, 0); > + break; > + > + default: > + sim_io_eprintf (sd, "Unknown option `%s'\n", arg); > + return SIM_RC_FAIL; > + } > + > + return SIM_RC_OK; > +} > + > +/* Like sim_state_free, but free the cpu buffers as well. */ > + > +static void > +bpf_free_state (SIM_DESC sd) > +{ > + if (STATE_MODULES (sd) != NULL) > + sim_module_uninstall (sd); > + > + sim_cpu_free_all (sd); > + sim_state_free (sd); > +} > + > +/* Create an instance of the simulator. */ > + > +SIM_DESC > +sim_open (SIM_OPEN_KIND kind, > + host_callback *callback, > + struct bfd *abfd, > + char * const *argv) > +{ > + /* XXX Analyze the program, and collect per-function information > + like the kernel verifier does. The implementation of the CALL > + instruction will need that information, to update %fp. */ > + > + SIM_DESC sd = sim_state_alloc (kind, callback); > + > + /* ... */ > + > + if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) > + != SIM_RC_OK) > + goto error; > + > + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) > + goto error; > + > + /* Add the BPF-specific option list to the simulator. */ > + if (sim_add_option_table (sd, NULL, bpf_options) != SIM_RC_OK) > + { > + bpf_free_state (sd); > + return 0; > + } > + > + if (sim_parse_args (sd, argv) != SIM_RC_OK) > + goto error; > + > + if (sim_analyze_program (sd, > + (STATE_PROG_ARGV (sd) != NULL > + ? *STATE_PROG_ARGV (sd) > + : NULL), abfd) != SIM_RC_OK) > + goto error; > + > + if (sim_config (sd) != SIM_RC_OK) > + goto error; > + > + if (sim_post_argv_init (sd) != SIM_RC_OK) > + goto error; > + > + /* ... */ Could you delete this comment? > + > + /* Initialize the CPU descriptors and the disassemble in the cpu > + descriptor table entries. */ > + { > + int i; > + CGEN_CPU_DESC cd = bpf_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name, > + CGEN_ENDIAN_LITTLE); > + > + /* We have one cpu per installed program! MAX_NR_PROCESSORS is an > + arbitrary upper limit. XXX where is it defined? */ > + for (i = 0; i < MAX_NR_PROCESSORS; ++i) > + { > + SIM_CPU *cpu = STATE_CPU (sd, i); > + > + CPU_CPU_DESC (cpu) = cd; > + CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn; > + } > + > + bpf_cgen_init_dis (cd); > + } > + > + /* Initialize various cgen things not done by common framework. > + Must be done after bpf_cgen_cpu_open. */ > + cgen_init (sd); > + > + /* XXX do eBPF sim specific initializations. */ > + > + return sd; > + > + error: > + bpf_free_state (sd); > + return NULL; > +} > + > + > +SIM_RC > +sim_create_inferior (SIM_DESC sd, struct bfd *abfd, > + char *const *argv, char *const *envp) > +{ > + SIM_CPU *current_cpu = STATE_CPU (sd, 0); > + SIM_ADDR addr; > + > + /* Determine the start address. > + > + XXX acknowledge bpf_program_section. If it is NULL, emit a > + warning explaining that we are using the ELF file start address, > + which often is not what is actually wanted. */ > + if (abfd != NULL) > + addr = bfd_get_start_address (abfd); > + else > + addr = 0; > + > + sim_pc_set (current_cpu, addr); > + > + if (STATE_PROG_ARGV (sd) != argv) > + { > + freeargv (STATE_PROG_ARGV (sd)); > + STATE_PROG_ARGV (sd) = dupargv (argv); > + } > + > + return SIM_RC_OK; > +} > diff --git a/sim/bpf/sim-main.h b/sim/bpf/sim-main.h > new file mode 100644 > index 0000000000..fc1e69f6f3 > --- /dev/null > +++ b/sim/bpf/sim-main.h > @@ -0,0 +1,51 @@ > +/* eBPF simulator main header > + Copyright (C) 2020 Free Software Foundation, Inc. > + > + This file is part of GDB, the GNU debugger. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#ifndef SIM_MAIN_H > +#define SIM_MAIN_H > + > +#include "sim-basics.h" > +#include "cgen-types.h" > +#include "bpf-desc.h" > +#include "bpf-opc.h" > +#include "arch.h" > +#include "sim-base.h" > +#include "cgen-sim.h" > +#include "bpf-sim.h" > + > + > +struct _sim_cpu > +{ > + sim_cpu_base base; > + CGEN_CPU cgen_cpu; > + > +#if defined (WANT_CPU_BPFBF) > + BPFBF_CPU_DATA cpu_data; > +#endif > +}; > + > + > + > +struct sim_state > +{ > + sim_cpu *cpu[MAX_NR_PROCESSORS]; > + CGEN_STATE cgen_state; > + sim_state_base base; > +}; > + > +#endif /* ! SIM_MAIN_H */ > diff --git a/sim/bpf/traps.c b/sim/bpf/traps.c > new file mode 100644 > index 0000000000..e7ac0c2838 > --- /dev/null > +++ b/sim/bpf/traps.c > @@ -0,0 +1,33 @@ > +/* Trap handlers for eBPF. > + Copyright (C) 2020 Free Software Foundation, Inc. > + > + This file is part of GDB, the GNU debugger. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#define WANT_CPU bpfbf > +#define WANT_CPU_BPFBF > + > +#include "sim-main.h" > + > +SEM_PC > +sim_engine_invalid_insn (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, > + IADDR cia ATTRIBUTE_UNUSED, > + SEM_PC pc ATTRIBUTE_UNUSED) > +{ > + /* Can't just return 0 here: the return value is used to set vpc > + (see decdde-{le,be}.c) > + Returning 0 will cause an infinite loop! */ > + abort(); > +} > diff --git a/sim/configure b/sim/configure > index 72f95cd5c7..37a86f435c 100755 > --- a/sim/configure > +++ b/sim/configure > @@ -669,6 +669,7 @@ ac_subdirs_all='aarch64 > arm > avr > bfin > +bpf > cr16 > cris > d10v > @@ -3717,6 +3718,13 @@ subdirs="$subdirs aarch64" > subdirs="$subdirs bfin" > > > + ;; > + bpf-*-*) > + > + sim_arch=bpf > + subdirs="$subdirs bpf" > + > + > ;; > cr16*-*-*) > > diff --git a/sim/configure.tgt b/sim/configure.tgt > index 8a8e03d96f..c115c3c8dd 100644 > --- a/sim/configure.tgt > +++ b/sim/configure.tgt > @@ -26,6 +26,9 @@ case "${target}" in > bfin-*-*) > SIM_ARCH(bfin) > ;; > + bpf-*-*) > + SIM_ARCH(bpf) > + ;; > cr16*-*-*) > SIM_ARCH(cr16) > ;; > diff --git a/sim/testsuite/configure b/sim/testsuite/configure > index a3e7fa7131..c3674c2fa0 100755 > --- a/sim/testsuite/configure > +++ b/sim/testsuite/configure > @@ -1875,6 +1875,9 @@ case "${target}" in > bfin-*-*) > sim_arch=bfin > ;; > + bpf-*-*) > + sim_arch=bpf > + ;; > cr16*-*-*) > sim_arch=cr16 > ;; > @@ -1928,6 +1931,9 @@ case "${target}" in > or1k-*-* | or1knd-*-*) > sim_arch=or1k > ;; > + pru*-*-*) > + sim_arch=pru > + ;; > rl78-*-*) > sim_arch=rl78 > ;; > @@ -1946,9 +1952,6 @@ case "${target}" in > powerpc*-*-*) > sim_arch=ppc > ;; > - pru*-*-*) > - sim_arch=pru > - ;; > ft32-*-*) > sim_arch=ft32 > ;; > diff --git a/sim/testsuite/sim/bpf/allinsn.exp b/sim/testsuite/sim/bpf/allinsn.exp > new file mode 100644 > index 0000000000..2cca77021a > --- /dev/null > +++ b/sim/testsuite/sim/bpf/allinsn.exp > @@ -0,0 +1,26 @@ > +# eBPF simulator testsuite > + > +if [istarget bpf-unknown-none] { > + # all machines > + set all_machs "bpf" > + > + global global_sim_options > + if ![info exists global_sim_options] { > + set global_sim_options "--memory-size=4Mb" > + } > + > + global global_ld_options > + if ![info exists global_ld_options] { > + set global_ld_options "-Ttext=0x0" > + } > + > + foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.s]] { > + # If we're only testing specific files and this isn't one of them, > + # skip it. > + if ![runtest_file_p $runtests $src] { > + continue > + } > + > + run_sim_test $src $all_machs > + } > +} > diff --git a/sim/testsuite/sim/bpf/alu.s b/sim/testsuite/sim/bpf/alu.s > new file mode 100644 > index 0000000000..6013ac7eb9 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/alu.s > @@ -0,0 +1,109 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;;; alu.s > +;;; Tests for ALU64 BPF instructions in simulator > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + mov %r1, 0 > + mov %r2, -1 > + > + ;; add > + add %r1, 1 > + add %r2, -1 > + add %r1, %r2 > + fail_ne %r1, -1 > + > + ;; sub > + sub %r1, %r1 > + fail_ne %r1, 0 > + sub %r1, 10 > + sub %r2, %r1 > + fail_ne %r2, 8 > + > + ;; mul > + mul %r2, %r2 ; r2 = 64 > + mul %r2, 3 ; r2 = 192 > + mov %r1, -3 > + mul %r1, %r2 ; r1 = -576 > + mul %r2, 0 > + fail_ne %r1, -576 > + fail_ne %r2, 0 > + mul %r1, %r1 > + mul %r1, %r1 > + fail_ne %r1, 110075314176 > + > + ;; div > + div %r2, %r1 > + fail_ne %r2, 0 > + div %r1, -10000 > + fail_ne %r1, -11007531 > + div %r1, %r1 > + fail_ne %r1, 1 > + > + ;; and > + lddw %r1, 0xaaaaaaaa55555555 > + and %r1, 0x55aaaaaa ; we still only have 32-bit imm. > + fail_ne %r1, 0x0000000055000000 > + lddw %r2, 0x5555555a5aaaaaaa > + and %r2, %r1 > + fail_ne %r2, 0x0000000050000000 > + > + ;; or > + or %r2, 0xdeadbeef > + fail_ne %r2, 0xffffffffdeadbeef ; 0xdeadbeef gets sign extended > + lddw %r1, 0xdead00000000beef > + lddw %r2, 0x0000123456780000 > + or %r1, %r2 > + fail_ne %r1, 0xdead12345678beef > + > + ;; lsh > + mov %r1, 0xdeadbeef > + lsh %r1, 11 > + fail_ne %r1, 0xfffffef56df77800 ; because deadbeef gets sign ext. > + mov %r2, 21 > + lsh %r1, %r2 > + fail_ne %r1, 0xdeadbeef00000000 > + > + ;; rsh > + rsh %r1, 11 > + fail_ne %r1, 0x001bd5b7dde00000 ; 0xdeadbeef 00000000 >> 0xb > + rsh %r1, %r2 > + fail_ne %r1, 0x00000000deadbeef > + > + ;; arsh > + arsh %r1, 8 > + fail_ne %r1, 0x0000000000deadbe > + lsh %r1, 40 ; r1 = 0xdead be00 0000 0000 > + arsh %r1, %r2 ; r1 arsh (r2 == 21) > + fail_ne %r1, 0xfffffef56df00000 > + > + ;; mod > + mov %r1, 1025 > + mod %r1, -16 > + fail_ne %r1, 1 > + mov %r1, -25 > + mov %r2, 5 > + mod %r1, %r2 > + fail_ne %r1, 0 > + > + ;; xor > + xor %r1, %r2 > + fail_ne %r1, 5 > + xor %r1, 0x7eadbeef > + fail_ne %r1, 0x7eadbeea > + xor %r1, %r1 > + fail_ne %r1, 0 > + > + ;; neg > + neg %r2 > + fail_ne %r2, -5 > + mov %r1, -1025 > + neg %r1 > + fail_ne %r1, 1025 > + > + pass > diff --git a/sim/testsuite/sim/bpf/alu32.s b/sim/testsuite/sim/bpf/alu32.s > new file mode 100644 > index 0000000000..a611abd6f6 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/alu32.s > @@ -0,0 +1,99 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;; alu32.s > +;; Tests for ALU(32) BPF instructions in simulator > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + mov32 %r1, 10 ; r1 = 10 > + mov32 %r2, -5 ; r2 = -5 > + > + ;; add > + add32 %r1, 1 ; r1 += 1 (r1 = 11) > + add32 %r2, -1 ; r2 += -1 (r2 = -6) > + add32 %r1, %r2 ; r1 += r2 (r1 = 11 + -6 = 5) > + fail_ne32 %r1, 5 > + > + ;; sub > + sub32 %r1, 5 ; r1 -= 5 (r1 = 0) > + sub32 %r1, -5 ; r1 -= -5 (r1 = 5) > + sub32 %r1, %r2 ; r1 -= r2 (r1 = 5 - -6 = 11) > + fail_ne32 %r1, 11 > + > + ;; mul > + mul32 %r1, 2 ; r1 *= 2 (r1 = 22) > + mul32 %r1, -2 ; r1 *= -2 (r1 = -44) > + mul32 %r1, %r2 ; r1 *= r2 (r1 = -44 * -6 = 264) > + fail_ne32 %r1, 264 > + > + ;; div > + div32 %r1, %r2 ; r1 /= r2 (r1 = 264 / -6 = -44) > + div32 %r1, -2 ; r1 /= -2 (r1 = 22) > + div32 %r1, 2 ; r1 /= 2 (r1 = 11) > + fail_ne32 %r1, 11 > + > + ;; and (bitwise) > + mov32 %r1, 0xb ; r1 = (0xb = 0b1011) > + mov32 %r2, 0x5 ; r2 = (0x5 = 0b0101) > + and32 %r1, 0xa ; r1 &= (0xa = 0b1010) = (0b1010 = 0xa) > + fail_ne32 %r1, 0xa > + and32 %r1, %r2 ; r1 &= r2 = 0x0 > + fail_ne32 %r1, 0x0 > + > + ;; or (bitwise) > + or32 %r1, 0xb > + or32 %r1, %r2 > + fail_ne32 %r1, 0xf > + > + ;; lsh (left shift) > + lsh32 %r1, 4 ; r1 <<= 4 (r1 = 0xf0) > + mov32 %r2, 24 ; r2 = 24 > + lsh32 %r1, %r2 > + fail_ne32 %r1, 0xf0000000 > + > + ;; rsh (right logical shift) > + rsh32 %r1, 2 > + rsh32 %r1, %r2 > + fail_ne32 %r1, 0x3c ; (0xf000 0000 >> 26) > + > + ;; arsh (right arithmetic shift) > + arsh32 %r1, 1 > + or32 %r1, 0x80000000 > + mov32 %r2, 3 > + arsh32 %r1, %r2 > + fail_ne %r1, 0x00000000F0000003 > + ; Note: make sure r1 is NOT sign-extended > + ; i.e. upper-32 bits should be untouched > + > + ;; mod > + mov32 %r1, -25 > + mov32 %r2, 4 > + mod32 %r1, %r2 > + fail_ne32 %r1, -1 > + mov32 %r1, 25 > + mod32 %r1, 5 > + fail_ne32 %r1, 0 > + > + ;; xor > + xor32 %r1, %r2 > + fail_ne32 %r1, 4 > + xor32 %r1, 0xF000000F > + fail_ne %r1, 0xF000000B ; Note: check for (bad) sign-extend > + xor32 %r1, %r1 > + fail_ne %r1, 0 > + > + ;; neg > + mov32 %r1, -1 > + mov32 %r2, 0x7fffffff > + neg32 %r1 > + neg32 %r2 > + fail_ne32 %r1, 1 > + fail_ne %r2, 0x80000001 ; Note: check for (bad) sign-extend > + neg32 %r2 > + fail_ne32 %r2, 0x7fffffff > + > + pass > diff --git a/sim/testsuite/sim/bpf/endbe.s b/sim/testsuite/sim/bpf/endbe.s > new file mode 100644 > index 0000000000..2f662aec02 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/endbe.s > @@ -0,0 +1,46 @@ > +# mach: bpf > +# as: --EB > +# ld: --EB > +# sim: -E big > +# output: pass\nexit 0 (0x0)\n > +;;; endbe.s > +;;; Tests for BPF endianness-conversion instructions in simulator > +;;; running in BIG ENDIAN > +;;; > +;;; Both 'be' and 'le' ISAs have both endbe and endle instructions. > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + lddw %r1, 0x12345678deadbeef > + endle %r1, 64 > + fail_ne %r1, 0xefbeadde78563412 > + endle %r1, 64 > + fail_ne %r1, 0x12345678deadbeef > + > + ;; `bitsize` < 64 will truncate > + endle %r1, 32 > + fail_ne %r1, 0xefbeadde > + endle %r1, 32 > + fail_ne %r1, 0xdeadbeef > + > + endle %r1, 16 > + fail_ne %r1, 0xefbe > + endle %r1, 16 > + fail_ne %r1, 0xbeef > + > + ;; endbe on be should be noop (except truncate) > + lddw %r1, 0x12345678deadbeef > + endbe %r1, 64 > + fail_ne %r1, 0x12345678deadbeef > + > + endbe %r1, 32 > + fail_ne %r1, 0xdeadbeef > + > + endbe %r1, 16 > + fail_ne %r1, 0xbeef > + > + pass > diff --git a/sim/testsuite/sim/bpf/endle.s b/sim/testsuite/sim/bpf/endle.s > new file mode 100644 > index 0000000000..d8f5ceb977 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/endle.s > @@ -0,0 +1,43 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;;; endle.s > +;;; Tests for BPF endianness-conversion instructions in simulator > +;;; running in LITTLE ENDIAN > +;;; > +;;; Both 'be' and 'le' ISAs have both endbe and endle instructions. > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + lddw %r1, 0x12345678deadbeef > + endbe %r1, 64 > + fail_ne %r1, 0xefbeadde78563412 > + endbe %r1, 64 > + fail_ne %r1, 0x12345678deadbeef > + > + ;; `bitsize` < 64 will truncate > + endbe %r1, 32 > + fail_ne %r1, 0xefbeadde > + endbe %r1, 32 > + fail_ne %r1, 0xdeadbeef > + > + endbe %r1, 16 > + fail_ne %r1, 0xefbe > + endbe %r1, 16 > + fail_ne %r1, 0xbeef > + > + ;; endle on le should be noop (except truncate) > + lddw %r1, 0x12345678deadbeef > + endle %r1, 64 > + fail_ne %r1, 0x12345678deadbeef > + > + endle %r1, 32 > + fail_ne %r1, 0xdeadbeef > + > + endle %r1, 16 > + fail_ne %r1, 0xbeef > + > + pass > diff --git a/sim/testsuite/sim/bpf/jmp.s b/sim/testsuite/sim/bpf/jmp.s > new file mode 100644 > index 0000000000..a9fe88be4a > --- /dev/null > +++ b/sim/testsuite/sim/bpf/jmp.s > @@ -0,0 +1,120 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;;; jmp.s > +;;; Tests for eBPF JMP instructions in simulator > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + mov %r1, 5 > + mov %r2, 2 > + mov %r3, 7 > + mov %r4, -1 > + > + ;; ja - jump absolute (unconditional) > + ja 2f > +1: fail > + > +2: ;; jeq - jump eq > + jeq %r1, 4, 1b ; no > + jeq %r1, %r2, 1b ; no > + jeq %r1, 5, 2f ; yes > + fail > +2: jeq %r1, %r1, 2f ; yes > + fail > + > +2: ;; jgt - jump (unsigned) greater-than > + jgt %r1, 6, 1b ; no > + jgt %r1, -5, 1b ; no - unsigned > + jgt %r1, %r4, 1b ; no - unsigned > + jgt %r1, 4, 2f ; yes > + fail > +2: jgt %r1, %r2, 2f ; yes > + fail > + > +2: ;; jge - jump (unsigned) greater-than-or-equal-to > + jge %r1, 6, 1b ; no > + jge %r1, 5, 2f ; yes > + fail > +2: jge %r1, %r3, 1b ; no > + jge %r1, -5, 1b ; no - unsigned > + jge %r1, %r2, 2f ; yes > + fail > + > +2: ;; jlt - jump (unsigned) less-than > + jlt %r1, 5, 1b ; no > + jlt %r1, %r2, 1b ; no > + jlt %r4, %r1, 1b ; no - unsigned > + jlt %r1, 6, 2f ; yes > + fail > +2: > + jlt %r1, %r3, 2f ; yes > + fail > + > +2: ;; jle - jump (unsigned) less-than-or-equal-to > + jle %r1, 4, 1b ; no > + jle %r1, %r2, 1b ; no > + jle %r4, %r1, 1b ; no > + jle %r1, 5, 2f ; yes > + fail > +2: jle %r1, %r1, 2f ; yes > + fail > + > +2: ;; jset - jump "test" (AND) > + jset %r1, 2, 1b ; no (5 & 2 = 0) > + jset %r1, %r2, 1b ; no (same) > + jset %r1, 4, 2f ; yes (5 & 4 != 0) > + fail > + > +2: ;; jne - jump not-equal-to > + jne %r1, 5, 1b ; no > + jne %r1, %r1, 1b ; no > + jne %r1, 6, 2f ; yes > + fail > +2: jne %r1, %r4, 2f ; yes > + fail > + > +2: ;; jsgt - jump (signed) greater-than > + jsgt %r1, %r3, 1b ; no > + jsgt %r1, %r1, 1b ; no > + jsgt %r1, 5, 1b ; no > + jsgt %r1, -4, 2f ; yes > + fail > +2: jsgt %r1, %r4, 2f ; yes > + fail > + > +2: ;; jsge - jump (signed) greater-than-or-equal-to > + jsge %r1, %r3, 1b ; no > + jsge %r1, %r1, 2f ; yes > + fail > +2: jsge %r1, 7, 1b ; no > + jsge %r1, -4, 2f ; yes > + fail > +2: jsge %r1, %r4, 2f ; yes > + fail > + > +2: ;; jslt - jump (signed) less-than > + jslt %r1, 5, 1b ; no > + jslt %r1, %r2, 1b ; no > + jslt %r4, %r1, 2f ; yes > + fail > +2: jslt %r1, 6, 2f ; yes > + fail > +2: jslt %r1, %r3, 2f ; yes > + fail > + > +2: ;; jsle - jump (signed) less-than-or-equal-to > + jsle %r1, 4, 1b ; no > + jsle %r1, %r2, 1b ; no > + jsle %r4, %r1, 2f ; yes > + fail > +2: jsle %r1, 5, 2f ; yes > + fail > +2: jsle %r1, %r3, 2f ; yes > + fail > + > +2: > + pass > diff --git a/sim/testsuite/sim/bpf/jmp32.s b/sim/testsuite/sim/bpf/jmp32.s > new file mode 100644 > index 0000000000..3621295129 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/jmp32.s > @@ -0,0 +1,120 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;;; jmp32.s > +;;; Tests for eBPF JMP32 instructions in simulator > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + mov32 %r1, 5 > + mov32 %r2, 2 > + mov32 %r3, 7 > + mov32 %r4, -1 > + > + ;; ja - jump absolute (unconditional) > + ja 2f > +1: fail > + > +2: ;; jeq - jump eq > + jeq32 %r1, 4, 1b ; no > + jeq32 %r1, %r2, 1b ; no > + jeq32 %r1, 5, 2f ; yes > + fail > +2: jeq32 %r1, %r1, 2f ; yes > + fail > + > +2: ;; jgt - jump (unsigned) greater-than > + jgt32 %r1, 6, 1b ; no > + jgt32 %r1, -5, 1b ; no - unsigned > + jgt32 %r1, %r4, 1b ; no - unsigned > + jgt32 %r1, 4, 2f ; yes > + fail > +2: jgt32 %r1, %r2, 2f ; yes > + fail > + > +2: ;; jge - jump (unsigned) greater-than-or-equal-to > + jge32 %r1, 6, 1b ; no > + jge32 %r1, 5, 2f ; yes > + fail > +2: jge32 %r1, %r3, 1b ; no > + jge32 %r1, -5, 1b ; no - unsigned > + jge32 %r1, %r2, 2f ; yes > + fail > + > +2: ;; jlt - jump (unsigned) less-than > + jlt32 %r1, 5, 1b ; no > + jlt32 %r1, %r2, 1b ; no > + jlt32 %r4, %r1, 1b ; no - unsigned > + jlt32 %r1, 6, 2f ; yes > + fail > +2: > + jlt32 %r1, %r3, 2f ; yes > + fail > + > +2: ;; jle - jump (unsigned) less-than-or-equal-to > + jle32 %r1, 4, 1b ; no > + jle32 %r1, %r2, 1b ; no > + jle32 %r4, %r1, 1b ; no > + jle32 %r1, 5, 2f ; yes > + fail > +2: jle32 %r1, %r1, 2f ; yes > + fail > + > +2: ;; jset - jump "test" (AND) > + jset32 %r1, 2, 1b ; no (5 & 2 = 0) > + jset32 %r1, %r2, 1b ; no (same) > + jset32 %r1, 4, 2f ; yes (5 & 4 != 0) > + fail > + > +2: ;; jne - jump not-equal-to > + jne32 %r1, 5, 1b ; no > + jne32 %r1, %r1, 1b ; no > + jne32 %r1, 6, 2f ; yes > + fail > +2: jne32 %r1, %r4, 2f ; yes > + fail > + > +2: ;; jsgt - jump (signed) greater-than > + jsgt32 %r1, %r3, 1b ; no > + jsgt32 %r1, %r1, 1b ; no > + jsgt32 %r1, 5, 1b ; no > + jsgt32 %r1, -4, 2f ; yes > + fail > +2: jsgt32 %r1, %r4, 2f ; yes > + fail > + > +2: ;; jsge - jump (signed) greater-than-or-equal-to > + jsge32 %r1, %r3, 1b ; no > + jsge32 %r1, %r1, 2f ; yes > + fail > +2: jsge32 %r1, 7, 1b ; no > + jsge32 %r1, -4, 2f ; yes > + fail > +2: jsge32 %r1, %r4, 2f ; yes > + fail > + > +2: ;; jslt - jump (signed) less-than > + jslt32 %r1, 5, 1b ; no > + jslt32 %r1, %r2, 1b ; no > + jslt32 %r4, %r1, 2f ; yes > + fail > +2: jslt32 %r1, 6, 2f ; yes > + fail > +2: jslt32 %r1, %r3, 2f ; yes > + fail > + > +2: ;; jsle - jump (signed) less-than-or-equal-to > + jsle32 %r1, 4, 1b ; no > + jsle32 %r1, %r2, 1b ; no > + jsle32 %r4, %r1, 2f ; yes > + fail > +2: jsle32 %r1, 5, 2f ; yes > + fail > +2: jsle32 %r1, %r3, 2f ; yes > + fail > + > +2: > + pass > diff --git a/sim/testsuite/sim/bpf/ldabs.s b/sim/testsuite/sim/bpf/ldabs.s > new file mode 100644 > index 0000000000..ae777f1cf5 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/ldabs.s > @@ -0,0 +1,87 @@ > +# mach: bpf > +# sim: --skb-data-offset=0x20 > +# output: pass\nexit 0 (0x0)\n > +;;; ldabs.s > +;;; Tests for non-generic BPF load instructions in simulator. > +;;; These instructions (ld{abs,ind}{b,h,w,dw}) are used to access > +;;; kernel socket data from BPF programs for high performance filters. > +;;; > +;;; Register r6 is an implicit input holding a pointer to a struct sk_buff. > +;;; Register r0 is an implicit output, holding the fetched data. > +;;; > +;;; e.g. > +;;; ldabsw means: > +;;; r0 = ntohl (*(u32 *) (((struct sk_buff *)r6)->data + imm32)) > +;;; > +;;; ldindw means > +;;; r0 = ntohl (*(u32 *) (((struct sk_buff *)r6)->data + src_reg + imm32)) > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + ;; R6 holds a pointer to a struct sk_buff, which we pretend > + ;; exists at 0x1000 > + mov %r6, 0x1000 > + > + ;; We configure skb-data-offset=0x20 > + ;; This specifies offsetof(struct sk_buff, data), where the field 'data' > + ;; is a pointer a data buffer, in this case at 0x2000 > + stw [%r6+0x20], 0x2000 > + > + ;; Write the value 0x7eadbeef into memory at 0x2004 > + ;; i.e. offset 4 within the data buffer pointed to by > + ;; ((struct sk_buff *)r6)->data > + stw [%r6+0x1004], 0xdeadbeef > + > + ;; Now load data[4] into r0 using the ldabsw instruction > + ldabsw 0x4 > + > + ;; ...and compare to what we expect > + fail_ne32 %r0, 0xdeadbeef > + > + ;; Repeat for a half-word (2-bytes) > + sth [%r6+0x1008], 0x1234 > + ldabsh 0x8 > + fail_ne32 %r0, 0x1234 > + > + ;; Repeat for a single byte > + stb [%r6+0x1010], 0x5a > + ldabsb 0x10 > + fail_ne32 %r0, 0x5a > + > + ;; Repeat for a double-word (8-byte) > + ;; (note: fail_ne macro uses r0, so copy to another r1 to compare) > + lddw %r2, 0x1234deadbeef5678 > + stxdw [%r6+0x1018], %r2 > + ldabsdw 0x18 > + mov %r1, %r0 > + fail_ne %r1, 0x1234deadbeef5678 > + > + ;; Now, we do the same for the indirect loads > + mov %r7, 0x100 > + stw [%r6+0x1100], 0xfeedbeef > + > + ldindw %r7, 0x0 > + fail_ne32 %r0, 0xfeedbeef > + > + ;; half-word > + sth [%r6+0x1104], 0x6789 > + ldindh %r7, 0x4 > + fail_ne32 %r0, 0x6789 > + > + ;; byte > + stb [%r6+0x1108], 0x5f > + ldindb %r7, 0x8 > + fail_ne32 %r0, 0x5f > + > + ;; double-word > + lddw %r2, 0xcafe12345678d00d > + stxdw [%r6+0x1110], %r2 > + ldinddw %r7, 0x10 > + mov %r1, %r0 > + fail_ne %r1, 0xcafe12345678d00d > + > + pass > diff --git a/sim/testsuite/sim/bpf/mem.s b/sim/testsuite/sim/bpf/mem.s > new file mode 100644 > index 0000000000..2dea57d227 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/mem.s > @@ -0,0 +1,56 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;;; mem.s > +;;; Tests for BPF memory (ldx, stx, ..) instructions in simulator > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + lddw %r1, 0x1234deadbeef5678 > + mov %r2, 0x1000 > + > + ;; basic store/load check > + stxb [%r2+0], %r1 > + stxh [%r2+2], %r1 > + stxw [%r2+4], %r1 > + stxdw [%r2+8], %r1 > + > + stb [%r2+16], 0x5a > + sth [%r2+18], 0xcafe > + stw [%r2+20], 0xbeefface > + stdw [%r2+24], 0x7eadbeef > + > + ldxb %r1, [%r2+16] > + fail_ne %r1, 0x5a > + ldxh %r1, [%r2+18] > + fail_ne %r1, 0xffffffffffffcafe > + ldxw %r1, [%r2+20] > + fail_ne %r1, 0xffffffffbeefface > + ldxdw %r1, [%r2+24] > + fail_ne %r1, 0x7eadbeef > + > + ldxb %r3, [%r2+0] > + fail_ne %r3, 0x78 > + ldxh %r3, [%r2+2] > + fail_ne %r3, 0x5678 > + ldxw %r3, [%r2+4] > + fail_ne %r3, 0xffffffffbeef5678 > + ldxdw %r3, [%r2+8] > + fail_ne %r3, 0x1234deadbeef5678 > + > + ldxw %r4, [%r2+10] > + fail_ne %r4, 0xffffffffdeadbeef > + > + ;; negative offsets > + add %r2, 16 > + ldxh %r5, [%r2+-14] > + fail_ne %r5, 0x5678 > + ldxw %r5, [%r2+-12] > + fail_ne %r5, 0xffffffffbeef5678 > + ldxdw %r5, [%r2+-8] > + fail_ne %r5, 0x1234deadbeef5678 > + > + pass > diff --git a/sim/testsuite/sim/bpf/mov.s b/sim/testsuite/sim/bpf/mov.s > new file mode 100644 > index 0000000000..6665450468 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/mov.s > @@ -0,0 +1,54 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;; mov.s > +;; Tests for mov and mov32 instructions > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + ;; some basic sanity checks > + mov32 %r1, 5 > + fail_ne %r1, 5 > + > + mov32 %r2, %r1 > + fail_ne %r2, 5 > + > + mov %r2, %r1 > + fail_ne %r2, 5 > + > + mov %r1, -666 > + fail_ne %r1, -666 > + > + ;; should NOT sign extend > + mov32 %r1, -1 > + fail_ne %r1, 0x00000000ffffffff > + > + ;; should sign extend > + mov %r2, -1 > + fail_ne %r2, 0xffffffffffffffff > + > + mov %r3, 0x80000000 > + > + ;; should NOT sign extend > + mov32 %r4, %r3 > + fail_ne %r4, 0x0000000080000000 > + > + ;; should sign extend > + mov %r5, %r3 > + fail_ne %r5, 0xffffffff80000000 > + > + mov32 %r1, -2147483648 > + mov32 %r1, %r1 > + fail_ne32 %r1, -2147483648 > + > + ;; casting shenanigans > + mov %r1, %r1 > + fail_ne %r1, +2147483648 > + mov32 %r2, -1 > + mov %r2, %r2 > + fail_ne %r2, +4294967295 > + > + pass > diff --git a/sim/testsuite/sim/bpf/testutils.inc b/sim/testsuite/sim/bpf/testutils.inc > new file mode 100644 > index 0000000000..d3d6b17b5b > --- /dev/null > +++ b/sim/testsuite/sim/bpf/testutils.inc > @@ -0,0 +1,38 @@ > + > + ;; Print "pass\n" and 'exit 0' > + .macro pass > + .data > +mpass: > + .string "pass\n" > + .text > +_pass: > + mov %r1, mpass ; point to "pass\n" string > + mov %r2, 5 ; strlen mpass > + call 7 ; printk > + mov %r0, 0 ; > + exit ; exit 0 > + .endm > + > +;;; MACRO fail > +;;; Exit with status 1 > + .macro fail > + mov %r0, 1 > + exit > + .endm > + > +;;; MACRO fail_ne32 > +;;; Exit with status 1 if \reg32 != \val > + .macro fail_ne32 reg val > + jeq32 \reg, \val, 2 > + mov %r0, 1 > + exit > + .endm > + > +;;; MACRO fail_ne > +;;; Exit with status1 if \reg ne \val > + .macro fail_ne reg val > + lddw %r0, \val > + jeq \reg, %r0, 2 > + mov %r0, 1 > + exit > + .endm > diff --git a/sim/testsuite/sim/bpf/xadd.s b/sim/testsuite/sim/bpf/xadd.s > new file mode 100644 > index 0000000000..1ca7577145 > --- /dev/null > +++ b/sim/testsuite/sim/bpf/xadd.s > @@ -0,0 +1,44 @@ > +# mach: bpf > +# output: pass\nexit 0 (0x0)\n > +;;; xadd.s > +;;; Tests for BPF atomic exchange-and-add instructions in simulator > +;;; > +;;; The xadd instructions (XADDW, XADDDW) operate on a memory location > +;;; specified in $dst + offset16, atomically adding the value in $src. > +;;; > +;;; In the simulator, there isn't anything else happening. The atomic > +;;; instructions are identical to a non-atomic load/add/store. > + > + .include "testutils.inc" > + > + .text > + .global main > + .type main, @function > +main: > + mov %r1, 0x1000 > + mov %r2, 5 > + > + ;; basic xadd w > + stw [%r1+0], 10 > + xaddw [%r1+0], %r2 > + ldxw %r3, [%r1+0] > + fail_ne %r3, 15 > + > + ;; basic xadd dw > + stdw [%r1+8], 42 > + xadddw [%r1+8], %r2 > + ldxdw %r3, [%r1+8] > + fail_ne %r3, 47 > + > + ;; xadd w negative value > + mov %r4, -1 > + xaddw [%r1+0], %r4 > + ldxw %r3, [%r1+0] > + fail_ne %r3, 14 > + > + ;; xadd dw negative val > + xadddw [%r1+8], %r4 > + ldxdw %r3, [%r1+8] > + fail_ne %r3, 46 > + > + pass > -- > 2.25.0.2.g232378479e >