From: Andrew Burgess <andrew.burgess@embecosm.com>
To: "Jose E. Marchesi" <jose.marchesi@oracle.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH V4 2/3] sim: eBPF simulator
Date: Sun, 12 Jul 2020 09:25:03 +0100 [thread overview]
Message-ID: <20200712082503.GC2737@embecosm.com> (raw)
In-Reply-To: <20200710122530.32541-3-jose.marchesi@oracle.com>
* Jose E. Marchesi via Gdb-patches <gdb-patches@sourceware.org> [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 <jose.marchesi@oracle.com>
> David Faust <david.faust@oracle.com>
>
> * 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 <david.faust@oracle.com>
> Jose E. Marchesi <jose.marchesi@oracle.com>
>
> * 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 <nickc@redhat.com>
> aarch64 Jim Wilson <wilson@tuliptree.org>
> arm Nick Clifton <nickc@redhat.com>
> bfin Mike Frysinger <vapier@gentoo.org>
> +bpf Jose E. Marchesi <jose.marchesi@oracle.com>
> cr16 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
> frv Dave Brolley <brolley@redhat.com>
> ft32 James Bowman <james.bowman@ftdichip.com>
> 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 <http://www.gnu.org/licenses/>.
> +
> +## 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 <http://www.gnu.org/licenses/>. */
> +
> +/* 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
> +<http://www.gnu.org/licenses/>. */
> +
> +/* 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 <http://www.gnu.org/licenses/>. */
> +
> +#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 <http://www.gnu.org/licenses/>. */
> +
> +#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 <http://www.gnu.org/licenses/>. */
> +
> +#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 */
> +}
> +
> +\f
> +/***** 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 <dlfcn.h> header file. */
> +#undef HAVE_DLFCN_H
> +
> +/* Define to 1 if you have the <errno.h> header file. */
> +#undef HAVE_ERRNO_H
> +
> +/* Define to 1 if you have the <fcntl.h> header file. */
> +#undef HAVE_FCNTL_H
> +
> +/* Define to 1 if you have the <fpu_control.h> 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 <inttypes.h> 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 <memory.h> 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 <stdint.h> header file. */
> +#undef HAVE_STDINT_H
> +
> +/* Define to 1 if you have the <stdlib.h> header file. */
> +#undef HAVE_STDLIB_H
> +
> +/* Define to 1 if you have the <strings.h> header file. */
> +#undef HAVE_STRINGS_H
> +
> +/* Define to 1 if you have the <string.h> 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 <sys/mman.h> header file. */
> +#undef HAVE_SYS_MMAN_H
> +
> +/* Define to 1 if you have the <sys/resource.h> header file. */
> +#undef HAVE_SYS_RESOURCE_H
> +
> +/* Define to 1 if you have the <sys/stat.h> header file. */
> +#undef HAVE_SYS_STAT_H
> +
> +/* Define to 1 if you have the <sys/times.h> header file. */
> +#undef HAVE_SYS_TIMES_H
> +
> +/* Define to 1 if you have the <sys/time.h> header file. */
> +#undef HAVE_SYS_TIME_H
> +
> +/* Define to 1 if you have the <sys/types.h> 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 <time.h> 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 <unistd.h> header file. */
> +#undef HAVE_UNISTD_H
> +
> +/* Define to 1 if you have the <windows.h> 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 <http://www.gnu.org/licenses/>. */
> +
> +/* 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 <http://www.gnu.org/licenses/>. */
> +
> +/* 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 <http://www.gnu.org/licenses/>.
> +
> +# 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 <<EOF
> +
> +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 <<EOF
> +{
> +
> + 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 <<EOF
> + 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 <http://www.gnu.org/licenses/>. */
> +
> +#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;
> +
> +\f
> +/* 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;
> +}
> +\f
> +
> +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 <http://www.gnu.org/licenses/>. */
> +
> +#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
> +};
> +
> +\f
> +
> +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 <http://www.gnu.org/licenses/>. */
> +
> +#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
>
next prev parent reply other threads:[~2020-07-12 8:25 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-10 12:25 [PATCH V4 0/3] eBPF support Jose E. Marchesi
2020-07-10 12:25 ` [PATCH V4 1/3] gdb: support for eBPF Jose E. Marchesi
2020-07-10 12:38 ` Eli Zaretskii
2020-07-10 13:51 ` Simon Marchi
2020-07-10 14:29 ` Jose E. Marchesi
2020-07-10 14:49 ` Simon Marchi
2020-07-10 12:25 ` [PATCH V4 2/3] sim: eBPF simulator Jose E. Marchesi
2020-07-12 8:25 ` Andrew Burgess [this message]
2020-07-12 10:06 ` Jose E. Marchesi
2020-07-10 12:25 ` [PATCH V4 3/3] sim: generated files for the " Jose E. Marchesi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200712082503.GC2737@embecosm.com \
--to=andrew.burgess@embecosm.com \
--cc=gdb-patches@sourceware.org \
--cc=jose.marchesi@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox