* Re: [PATCH 5/7] KVM: arm64: guest debug, add support for single-step
From: Peter Maydell @ 2014-11-26 19:27 UTC (permalink / raw)
To: Alex Bennée
Cc: kvm-devel, arm-mail-list,
kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg@public.gmane.org,
Christoffer Dall, Marc Zyngier, Alexander Graf, J. Kiszka,
David Hildenbrand, Bharat Bhushan, bp-l3A5Bk7waGM, Paolo Bonzini,
Gleb Natapov, Russell King, Catalin Marinas, Will Deacon,
Lorenzo Pieralisi, open list, open list:ABI/API
In-Reply-To: <1416931805-23223-6-git-send-email-alex.bennee-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 25 November 2014 at 16:10, Alex Bennée <alex.bennee-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> This adds support for single-stepping the guest. As userspace can and
> will manipulate guest registers before restarting any tweaking of the
> registers has to occur just before control is passed back to the guest.
> Furthermore while guest debugging is in effect we need to squash the
> ability of the guest to single-step itself as we have no easy way of
> re-entering the guest after the exception has been delivered to the
> hypervisor.
A corner case I don't think this patch handles: if the debugger
tries to single step an insn which is emulated by the
hypervisor (because it's a load/store which is trapped and
handled as emulated mmio in userspace) then we won't
correctly update the single-step state machine (and so we'll end
up incorrectly stopping after the following insn rather than
before, I think).
You should be able to achieve this effect by simply always clearing
the guest's PSTATE.SS when you advance the PC to skip the emulated
instruction (cf the comment in the pseudocode SSAdvance() function).
I think we should also be doing this PC advance on return from
userspace's handling of the mmio rather than before we drop back
to userspace as we do now, but I can't remember why I think that.
Christoffer, I don't suppose you recall, do you? I think it was
you I had this conversation with on IRC a month or so back...
-- PMM
^ permalink raw reply
* [PATCH 1/2] iio: Add support for waveform output
From: George McCollister @ 2014-11-26 21:45 UTC (permalink / raw)
Cc: Daniel Baluta, open list:STAGING SUBSYSTEM, Lars-Peter Clausen,
Reyad Attiyat, open list:IIO SUBSYSTEM AND..., Greg Kroah-Hartman,
Srinivas Pandruvada, open list, Harald Geyer, George McCollister,
Sebastian Reichel, Peter Meerwald, Hartmut Knaack,
open list:ABI/API, Jonathan Cameron
Output can be held high or low for a specified period of time.
Support for waveform capture could be added in the future.
Signed-off-by: George McCollister <george.mccollister@gmail.com>
---
Documentation/ABI/testing/sysfs-bus-iio | 7 +++++++
drivers/iio/industrialio-core.c | 3 +++
drivers/staging/iio/Documentation/iio_event_monitor.c | 2 ++
include/linux/iio/types.h | 5 ++++-
4 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index d760b02..47df169 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1028,3 +1028,10 @@ Contact: linux-iio@vger.kernel.org
Description:
Raw value of rotation from true/magnetic north measured with
or without compensation from tilt sensors.
+
+What: /sys/bus/iio/devices/iio:deviceX/out_waveformY_hightime_raw
+What: /sys/bus/iio/devices/iio:deviceX/out_waveformY_lowtime_raw
+KernelVersion: 3.18
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw value of time for output to be held high or low.
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index af3e76d..343e784 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -70,6 +70,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CCT] = "cct",
[IIO_PRESSURE] = "pressure",
[IIO_HUMIDITYRELATIVE] = "humidityrelative",
+ [IIO_WAVEFORM] = "waveform",
};
static const char * const iio_modifier_names[] = {
@@ -91,6 +92,8 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_NORTH_TRUE] = "from_north_true",
[IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
[IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
+ [IIO_MOD_HIGHTIME] = "hightime",
+ [IIO_MOD_LOWTIME] = "lowtime",
};
/* relies on pairs of these shared then separate */
diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c
index 569d6f8..690f261 100644
--- a/drivers/staging/iio/Documentation/iio_event_monitor.c
+++ b/drivers/staging/iio/Documentation/iio_event_monitor.c
@@ -49,6 +49,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CCT] = "cct",
[IIO_PRESSURE] = "pressure",
[IIO_HUMIDITYRELATIVE] = "humidityrelative",
+ [IIO_WAVEFORM] = "waveform",
};
static const char * const iio_ev_type_text[] = {
@@ -108,6 +109,7 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_CCT:
case IIO_PRESSURE:
case IIO_HUMIDITYRELATIVE:
+ case IIO_WAVEFORM:
break;
default:
return false;
diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
index 4a2af8a..d3b0af1 100644
--- a/include/linux/iio/types.h
+++ b/include/linux/iio/types.h
@@ -30,6 +30,7 @@ enum iio_chan_type {
IIO_CCT,
IIO_PRESSURE,
IIO_HUMIDITYRELATIVE,
+ IIO_WAVEFORM,
};
enum iio_modifier {
@@ -59,7 +60,9 @@ enum iio_modifier {
IIO_MOD_NORTH_MAGN,
IIO_MOD_NORTH_TRUE,
IIO_MOD_NORTH_MAGN_TILT_COMP,
- IIO_MOD_NORTH_TRUE_TILT_COMP
+ IIO_MOD_NORTH_TRUE_TILT_COMP,
+ IIO_MOD_HIGHTIME,
+ IIO_MOD_LOWTIME,
};
enum iio_event_type {
--
2.1.0
^ permalink raw reply related
* Re: [PATCH 1/2] iio: Add support for waveform output
From: Lars-Peter Clausen @ 2014-11-26 22:06 UTC (permalink / raw)
To: George McCollister
Cc: Daniel Baluta, STAGING SUBSYSTEM, list, Reyad Attiyat,
open list:IIO SUBSYSTEM AND..., Greg Kroah-Hartman,
Hartmut Knaack, open list, Harald Geyer, Sebastian Reichel,
Peter Meerwald, Srinivas Pandruvada, open, ABI/API,
Jonathan Cameron
In-Reply-To: <1417038344-3801-1-git-send-email-george.mccollister@gmail.com>
On 11/26/2014 10:45 PM, George McCollister wrote:
> Output can be held high or low for a specified period of time.
> Support for waveform capture could be added in the future.
>
That's a PWM device?
^ permalink raw reply
* Re: [PATCH v14 0/3] Add drm driver for Rockchip Socs
From: Dave Airlie @ 2014-11-26 22:53 UTC (permalink / raw)
To: Joerg Roedel
Cc: Heiko Stübner, Mark Yao, Boris BREZILLON, Rob Clark,
Daniel Vetter, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Randy Dunlap, Grant Likely,
Greg Kroah-Hartman, John Stultz, Rom Lemarchand,
devicetree@vger.kernel.org, linux-doc, LKML, dri-devel, linux-api,
linux-rockchip, Douglas Anderson
In-Reply-To: <20141126073430.GD3156@suse.de>
On 26 November 2014 at 17:34, Joerg Roedel <jroedel@suse.de> wrote:
> On Wed, Nov 26, 2014 at 01:37:51AM +0100, Heiko Stübner wrote:
>>
>> Joerg, is your arm/rockchip branch [0] considered stable?
>>
>> [0] https://git.kernel.org/cgit/linux/kernel/git/joro/iommu.git/log/?h=arm/rockchip
>>
>
> Yes, this branch will not be rebased. It can be pulled into another
> tree.
Great, so if we can get a rockchip drm tree based on drm-next with
that tree pulled into it
that would be good.
Dave.
^ permalink raw reply
* Re: [PATCHv2 0/7] CGroup Namespaces
From: Richard Weinberger @ 2014-11-26 22:58 UTC (permalink / raw)
To: Aditya Kali
Cc: Linux API, Linux Containers, Serge Hallyn,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Andy Lutomirski, Eric W. Biederman, Tejun Heo,
cgroups mailinglist, Ingo Molnar
In-Reply-To: <CAGr1F2Hm4+aCUz3RqkgUhbJAQtWvUbb2CRDkW5rJSZkwLM_huw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Thu, Nov 6, 2014 at 6:33 PM, Aditya Kali <adityakali-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
> On Tue, Nov 4, 2014 at 5:10 AM, Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>> On Fri, Oct 31, 2014 at 12:18:54PM -0700, Aditya Kali wrote:
>> [..]
>>> fs/kernfs/dir.c | 194 ++++++++++++++++++++++++++++++++++-----
>>> fs/kernfs/mount.c | 48 ++++++++++
>>> fs/proc/namespaces.c | 1 +
>>> include/linux/cgroup.h | 41 ++++++++-
>>> include/linux/cgroup_namespace.h | 36 ++++++++
>>> include/linux/kernfs.h | 5 +
>>> include/linux/nsproxy.h | 2 +
>>> include/linux/proc_ns.h | 4 +
>>> include/uapi/linux/sched.h | 3 +-
>>> kernel/Makefile | 2 +-
>>> kernel/cgroup.c | 108 +++++++++++++++++-----
>>> kernel/cgroup_namespace.c | 148 +++++++++++++++++++++++++++++
>>> kernel/fork.c | 2 +-
>>> kernel/nsproxy.c | 19 +++-
>>
>> Hi Aditya,
>>
>> Can we provide a documentation file for cgroup namespace behavior. Say,
>> Documentation/namespaces/cgroup-namespace.txt.
>>
> Yes, definitely. I will add it as soon as we have a consensus on the
> overall series.
Do you have a public git repository which contains your patches?
--
Thanks,
//richard
^ permalink raw reply
* Re: [tpmdd-devel] [PATCH v7 09/10] tpm: TPM 2.0 FIFO Interface
From: Stefan Berger @ 2014-11-27 1:38 UTC (permalink / raw)
To: Jarkko Sakkinen, Peter Huewe, Ashley Lai, Marcel Selhorst
Cc: christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
josh.triplett-ral2JQCrhuEAvxtiuMwx3w,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Arthur,
tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
jason.gunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/,
trousers-tech-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1415713513-16524-10-git-send-email-jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
On 11/11/2014 08:45 AM, Jarkko Sakkinen wrote:
> From: Will Arthur <will.c.arthur-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
>
> Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0,
> instead of calling tpm_get_timeouts(), assign duration and timeout
> values defined in the TPM 2.0 PTP specification.
>
> Signed-off-by: Will Arthur <will.c.arthur-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> ---
> drivers/char/tpm/tpm_tis.c | 71 ++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 56 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> index 7a2c59b..0b3c089 100644
> --- a/drivers/char/tpm/tpm_tis.c
> +++ b/drivers/char/tpm/tpm_tis.c
> @@ -1,5 +1,6 @@
> /*
> * Copyright (C) 2005, 2006 IBM Corporation
> + * Copyright (C) 2014 Intel Corporation
> *
> * Authors:
> * Leendert van Doorn <leendert-aZOuKsOsJu3MbYB6QlFGEg@public.gmane.org>
> @@ -44,6 +45,10 @@ enum tis_status {
> TPM_STS_DATA_EXPECT = 0x08,
> };
>
> +enum tis_status3 {
> + TPM_STS3_TPM2_FAM = 0x04,
> +};
> +
I just looked at the specs: You have to define a mask for bits 2 and 3
-> 0xc0.
> @@ -554,11 +567,28 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
> if (!chip->vendor.iobase)
> return -EIO;
>
> + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1));
> + if (sts3 & TPM_STS3_TPM2_FAM)
> + chip->flags = TPM_CHIP_FLAG_TPM2;
And use the mask here.
((sts3 & XYZ_MASK) == TPM_STS3_TPM2_FAM)
chip->flags = TPM_CHIP_FLAG_TPM2;
Since the bits 00 indicate TPM 1.2, 01 TPM2 and 10 and 11 are reserved!
Stefan
^ permalink raw reply
* Re: [PATCH v14 0/3] Add drm driver for Rockchip Socs
From: Mark yao @ 2014-11-27 1:40 UTC (permalink / raw)
To: Dave Airlie, Joerg Roedel
Cc: Heiko Stübner, Boris BREZILLON, Rob Clark, Daniel Vetter,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Randy Dunlap, Grant Likely, Greg Kroah-Hartman, John Stultz,
Rom Lemarchand,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA, LKML, dri-devel,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Douglas Anderson
In-Reply-To: <CAPM=9tzhZLShA5=ShGTKhyZR6ddKycQDUWBZxXpUBb+1tGp-mQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On 2014年11月27日 06:53, Dave Airlie wrote:
> On 26 November 2014 at 17:34, Joerg Roedel <jroedel-l3A5Bk7waGM@public.gmane.org> wrote:
>> On Wed, Nov 26, 2014 at 01:37:51AM +0100, Heiko Stübner wrote:
>>> Joerg, is your arm/rockchip branch [0] considered stable?
>>>
>>> [0] https://git.kernel.org/cgit/linux/kernel/git/joro/iommu.git/log/?h=arm/rockchip
>>>
>> Yes, this branch will not be rebased. It can be pulled into another
>> tree.
> Great, so if we can get a rockchip drm tree based on drm-next with
> that tree pulled into it
> that would be good.
>
> Dave.
>
>
>
Hi Dave
Do you mean that I need send you a branch, based on drm-next, merge
with iommu tree and rockchip drm?
- Mark
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v14 0/3] Add drm driver for Rockchip Socs
From: Dave Airlie @ 2014-11-27 2:12 UTC (permalink / raw)
To: Mark yao
Cc: Joerg Roedel, Heiko Stübner, Boris BREZILLON, Rob Clark,
Daniel Vetter, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Randy Dunlap, Grant Likely,
Greg Kroah-Hartman, John Stultz, Rom Lemarchand,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA, LKML, dri-devel,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Douglas Anderson
In-Reply-To: <54768107.2090402-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
>>
>>
> Hi Dave
> Do you mean that I need send you a branch, based on drm-next, merge with
> iommu tree and rockchip drm?
Yes, grab drm-next, git pull the arm/rockchip branch from Joerg's
tree, put rockchip drm
patches on top, send me pull request.
I'll validate it then.
Dave.
^ permalink raw reply
* [PATCH v4] selftest: size: Add size test for Linux kernel
From: Tim Bird @ 2014-11-27 4:27 UTC (permalink / raw)
To: Shuah Khan
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-embedded-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Josh Triplett
This test shows the amount of memory used by the system.
Note that this is dependent on the user-space that is loaded
when this program runs. Optimally, this program would be
run as the init program itself.
The program is optimized for size itself, to avoid conflating
its own execution with that of the system software.
The code is compiled statically, with no stdlibs. On my x86_64 system,
this results in a statically linked binary of less than 5K.
Signed-off-by: Tim Bird <tim.bird-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
---
Changes from v3:
- fix copyright string (again!)
- use __builtin_strlen instead of my own strlen
- replace main with _start
- add more human-readable output
- put libgcc reference into a variable in Makefile
Changes from v2:
- add return values to print routines
- add .gitignore file
Changes from v1:
- use more correct Copyright string in get_size.c
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/size/.gitignore | 1 +
tools/testing/selftests/size/Makefile | 23 +++++++
tools/testing/selftests/size/get_size.c | 111 ++++++++++++++++++++++++++++++++
4 files changed, 136 insertions(+)
create mode 100644 tools/testing/selftests/size/.gitignore
create mode 100644 tools/testing/selftests/size/Makefile
create mode 100644 tools/testing/selftests/size/get_size.c
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 45f145c..fa91aef 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -15,6 +15,7 @@ TARGETS += user
TARGETS += sysctl
TARGETS += firmware
TARGETS += ftrace
+TARGETS += size
TARGETS_HOTPLUG = cpu-hotplug
TARGETS_HOTPLUG += memory-hotplug
diff --git a/tools/testing/selftests/size/.gitignore b/tools/testing/selftests/size/.gitignore
new file mode 100644
index 0000000..189b781
--- /dev/null
+++ b/tools/testing/selftests/size/.gitignore
@@ -0,0 +1 @@
+get_size
diff --git a/tools/testing/selftests/size/Makefile b/tools/testing/selftests/size/Makefile
new file mode 100644
index 0000000..1862786
--- /dev/null
+++ b/tools/testing/selftests/size/Makefile
@@ -0,0 +1,23 @@
+#ifndef CC
+ CC = $(CROSS_COMPILE)gcc
+#endif
+
+#ifndef STRIP
+ STRIP = $(CROSS_COMPILE)strip
+#endif
+
+all: get_size
+
+LIBGCC=$(shell $(CC) -print-libgcc-file-name)
+
+get_size: get_size.c
+ $(CC) --static -ffreestanding -nostartfiles \
+ -Wl,--entry=_start get_size.c $(LIBGCC) \
+ -o get_size
+ $(STRIP) -s get_size
+
+run_tests: all
+ ./get_size
+
+clean:
+ $(RM) get_size
diff --git a/tools/testing/selftests/size/get_size.c b/tools/testing/selftests/size/get_size.c
new file mode 100644
index 0000000..7e9bbb4
--- /dev/null
+++ b/tools/testing/selftests/size/get_size.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014 Sony Mobile Communications Inc.
+ *
+ * Licensed under the terms of the GNU GPL License version 2
+ *
+ * Selftest for runtime system size
+ *
+ * Prints the amount of RAM that the currently running system is using.
+ *
+ * This program tries to be as small as possible itself, to
+ * avoid perturbing the system memory utilization with its
+ * own execution. It also attempts to have as few dependencies
+ * on kernel features as possible.
+ *
+ * It should be statically linked, with startup libs avoided.
+ * It uses no library calls, and only the following 3 syscalls:
+ * sysinfo(), write(), and _exit()
+ *
+ * For output, it avoids printf (which in some C libraries
+ * has large external dependencies) by implementing it's own
+ * number output and print routines, and using __builtin_strlen()
+ */
+
+#include <sys/sysinfo.h>
+#include <unistd.h>
+
+#define STDOUT_FILENO 1
+
+int print(const char *s)
+{
+ return write(STDOUT_FILENO, s, __builtin_strlen(s));
+}
+
+
+/*
+ * num_to_str - put digits from num into *s, left to right
+ * do this by dividing the number by powers of 10
+ * the tricky part is to omit leading zeros
+ * don't print zeros until we've started printing any numbers at all
+ */
+void num_to_str(unsigned long num, char *s)
+{
+ unsigned long long temp, div;
+ int started;
+
+ temp = num;
+ div = 1000000000000000000LL;
+ started = 0;
+ while (div) {
+ if (temp/div || started) {
+ *s++ = (unsigned char)(temp/div + '0');
+ started = 1;
+ }
+ temp -= (temp/div)*div;
+ div /= 10;
+ }
+ *s = 0;
+}
+
+int print_num(unsigned long num)
+{
+ char num_buf[30];
+
+ num_to_str(num, num_buf);
+ return print(num_buf);
+}
+
+int print_k_value(const char *s, unsigned long num, unsigned long units)
+{
+ unsigned long long temp;
+ int ccode;
+
+ print(s);
+
+ temp = num;
+ temp = (temp * units)/1024;
+ num = temp;
+ ccode = print_num(num);
+ print("\n");
+ return ccode;
+}
+
+/* this program has no main(), as startup libraries are not used */
+void _start(void)
+{
+ int ccode;
+ struct sysinfo info;
+ unsigned long used;
+
+ print("Testing system size.\n");
+ print("1..1\n");
+
+ ccode = sysinfo(&info);
+ if (ccode < 0) {
+ print("not ok 1 get size runtime size\n");
+ print("# could not get sysinfo\n");
+ _exit(ccode);
+ }
+ /* ignore cache complexities for now */
+ used = info.totalram - info.freeram - info.bufferram;
+ print_k_value("ok 1 get runtime memory use # size = ", used,
+ info.mem_unit);
+
+ print("# System runtime memory report (units in Kilobytes):\n");
+ print_k_value("# Total: ", info.totalram, info.mem_unit);
+ print_k_value("# Free: ", info.freeram, info.mem_unit);
+ print_k_value("# Buffer: ", info.bufferram, info.mem_unit);
+ print_k_value("# In use: ", used, info.mem_unit);
+
+ _exit(0);
+}
--
1.8.2.2
^ permalink raw reply related
* Re: [PATCH v2 02/19] kbuild: kselftest_install - add a new make target to install selftests
From: Masami Hiramatsu @ 2014-11-27 5:32 UTC (permalink / raw)
To: Shuah Khan
Cc: gregkh, akpm, mmarek, davem, keescook, tranmanphong, dh.herrmann,
hughd, bobby.prani, ebiederm, serge.hallyn, linux-kbuild,
linux-kernel, linux-api, netdev
In-Reply-To: <a2344d4df903d673afe1631118f40917f773cc9a.1415735831.git.shuahkh@osg.samsung.com>
(2014/11/12 5:27), Shuah Khan wrote:
> Add a new make target to install to install kernel selftests.
> This new target will build and install selftests. kselftest
> target now depends on kselftest_install and runs the generated
> kselftest script to reduce duplicate work and for common look
> and feel when running tests.
>
> Approach:
>
> make kselftest_target:
kselftest_install?
> -- exports kselftest INSTALL_KSFT_PATH
> default $(INSTALL_MOD_PATH)/lib/kselftest/$(KERNELRELEASE)
> -- exports path for ksefltest.sh
> -- runs selftests make install target:
This direction is OK to me.
BTW, I've found another path to make selftest in Makefile,
Actually you can do
make -C tools/ selftest
And there are selftest_install and selftest_clean targets (but
currently it has a bug and doesn't work, anyway)
I think we'd better do subdir make instead of adding these targets.
This means that "make kselftest*" should be an alias of "make -C tools/ selftest*"
Also, I'd like to request passing some options like as O=$(objtree)
so that we can make test kmodules in selftests.
Thank you,
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
^ permalink raw reply
* [PATCH net-next 0/6] allow eBPF programs to be attached to sockets
From: Alexei Starovoitov @ 2014-11-27 5:42 UTC (permalink / raw)
To: David S. Miller
Cc: Ingo Molnar, Andy Lutomirski, Daniel Borkmann,
Hannes Frederic Sowa, Eric Dumazet,
linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Introduce BPF_PROG_TYPE_SOCKET_FILTER type of eBPF programs that can be
attached to sockets with setsockopt().
Allow such programs to access maps via lookup/update/delete helpers.
This feature was previewed by bpf manpage in commit b4fc1a460f30("Merge branch 'bpf-next'")
Now it can actually run.
1st patch adds LD_ABS/LD_IND instruction verification and
2nd patch adds new setsockopt() flag.
Patches 3-6 are examples in assembler and in C.
Though native eBPF programs are way more powerful than classic filters
(attachable through similar setsockopt() call), they don't have skb field
accessors yet. Like skb->pkt_type, skb->dev->ifindex are not accessible.
There are sevaral ways to achieve that. That will be in the next set of patches.
So in this set native eBPF programs can only read data from packet and
access maps.
The most powerful example is sockex2_kern.c from patch 6 where ~200 lines of C
are compiled into ~300 of eBPF instructions.
It shows how quite complex packet parsing can be done.
LLVM used to build examples is at https://github.com/iovisor/llvm
which is fork of llvm trunk that I'm cleaning up for upstreaming.
Alexei Starovoitov (6):
bpf: verifier: add checks for BPF_ABS | BPF_IND instructions
net: sock: allow eBPF programs to be attached to sockets
samples: bpf: example of stateful socket filtering
samples: bpf: elf_bpf file loader
samples: bpf: trivial eBPF program in C
samples: bpf: large eBPF program in C
arch/alpha/include/uapi/asm/socket.h | 3 +
arch/avr32/include/uapi/asm/socket.h | 3 +
arch/cris/include/uapi/asm/socket.h | 3 +
arch/frv/include/uapi/asm/socket.h | 3 +
arch/ia64/include/uapi/asm/socket.h | 3 +
arch/m32r/include/uapi/asm/socket.h | 3 +
arch/mips/include/uapi/asm/socket.h | 3 +
arch/mn10300/include/uapi/asm/socket.h | 3 +
arch/parisc/include/uapi/asm/socket.h | 3 +
arch/powerpc/include/uapi/asm/socket.h | 3 +
arch/s390/include/uapi/asm/socket.h | 3 +
arch/sparc/include/uapi/asm/socket.h | 3 +
arch/xtensa/include/uapi/asm/socket.h | 3 +
include/linux/bpf.h | 4 +
include/linux/filter.h | 1 +
include/uapi/asm-generic/socket.h | 3 +
include/uapi/linux/bpf.h | 1 +
kernel/bpf/verifier.c | 70 ++++++++++-
net/core/filter.c | 97 +++++++++++++-
net/core/sock.c | 13 ++
samples/bpf/Makefile | 20 +++
samples/bpf/bpf_helpers.h | 40 ++++++
samples/bpf/bpf_load.c | 203 ++++++++++++++++++++++++++++++
samples/bpf/bpf_load.h | 24 ++++
samples/bpf/libbpf.c | 28 +++++
samples/bpf/libbpf.h | 15 ++-
samples/bpf/sock_example.c | 97 ++++++++++++++
samples/bpf/sockex1_kern.c | 23 ++++
samples/bpf/sockex1_user.c | 49 ++++++++
samples/bpf/sockex2_kern.c | 215 ++++++++++++++++++++++++++++++++
samples/bpf/sockex2_user.c | 44 +++++++
31 files changed, 981 insertions(+), 5 deletions(-)
create mode 100644 samples/bpf/bpf_helpers.h
create mode 100644 samples/bpf/bpf_load.c
create mode 100644 samples/bpf/bpf_load.h
create mode 100644 samples/bpf/sock_example.c
create mode 100644 samples/bpf/sockex1_kern.c
create mode 100644 samples/bpf/sockex1_user.c
create mode 100644 samples/bpf/sockex2_kern.c
create mode 100644 samples/bpf/sockex2_user.c
--
1.7.9.5
^ permalink raw reply
* [PATCH net-next 1/6] bpf: verifier: add checks for BPF_ABS | BPF_IND instructions
From: Alexei Starovoitov @ 2014-11-27 5:42 UTC (permalink / raw)
To: David S. Miller
Cc: Ingo Molnar, Andy Lutomirski, Daniel Borkmann,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1417066951-1999-1-git-send-email-ast@plumgrid.com>
introduce program type BPF_PROG_TYPE_SOCKET_FILTER that is used
for attaching programs to sockets where ctx == skb.
add verifier checks for ABS/IND instructions which can only be seen
in socket filters, therefore the check:
if (env->prog->aux->prog_type != BPF_PROG_TYPE_SOCKET_FILTER)
verbose("BPF_LD_ABS|IND instructions are only allowed in socket filters\n");
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
include/uapi/linux/bpf.h | 1 +
kernel/bpf/verifier.c | 70 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 4a3d0f84f178..45da7ec7d274 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -117,6 +117,7 @@ enum bpf_map_type {
enum bpf_prog_type {
BPF_PROG_TYPE_UNSPEC,
+ BPF_PROG_TYPE_SOCKET_FILTER,
};
/* flags for BPF_MAP_UPDATE_ELEM command */
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b6a1f7c14a67..a28e09c7825d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1172,6 +1172,70 @@ static int check_ld_imm(struct verifier_env *env, struct bpf_insn *insn)
return 0;
}
+/* verify safety of LD_ABS|LD_IND instructions:
+ * - they can only appear in the programs where ctx == skb
+ * - since they are wrappers of function calls, they scratch R1-R5 registers,
+ * preserve R6-R9, and store return value into R0
+ *
+ * Implicit input:
+ * ctx == skb == R6 == CTX
+ *
+ * Explicit input:
+ * SRC == any register
+ * IMM == 32-bit immediate
+ *
+ * Output:
+ * R0 - 8/16/32-bit skb data converted to cpu endianness
+ */
+static int check_ld_abs(struct verifier_env *env, struct bpf_insn *insn)
+{
+ struct reg_state *regs = env->cur_state.regs;
+ u8 mode = BPF_MODE(insn->code);
+ struct reg_state *reg;
+ int i, err;
+
+ if (env->prog->aux->prog_type != BPF_PROG_TYPE_SOCKET_FILTER) {
+ verbose("BPF_LD_ABS|IND instructions are only allowed in socket filters\n");
+ return -EINVAL;
+ }
+
+ if (insn->dst_reg != BPF_REG_0 || insn->off != 0 ||
+ (mode == BPF_ABS && insn->src_reg != BPF_REG_0)) {
+ verbose("BPF_LD_ABS uses reserved fields\n");
+ return -EINVAL;
+ }
+
+ /* check whether implicit source operand (register R6) is readable */
+ err = check_reg_arg(regs, BPF_REG_6, SRC_OP);
+ if (err)
+ return err;
+
+ if (regs[BPF_REG_6].type != PTR_TO_CTX) {
+ verbose("at the time of BPF_LD_ABS|IND R6 != pointer to skb\n");
+ return -EINVAL;
+ }
+
+ if (mode == BPF_IND) {
+ /* check explicit source operand */
+ err = check_reg_arg(regs, insn->src_reg, SRC_OP);
+ if (err)
+ return err;
+ }
+
+ /* reset caller saved regs to unreadable */
+ for (i = 0; i < CALLER_SAVED_REGS; i++) {
+ reg = regs + caller_saved[i];
+ reg->type = NOT_INIT;
+ reg->imm = 0;
+ }
+
+ /* mark destination R0 register as readable, since it contains
+ * the value fetched from the packet
+ */
+ regs[BPF_REG_0].type = UNKNOWN_VALUE;
+ return 0;
+}
+
/* non-recursive DFS pseudo code
* 1 procedure DFS-iterative(G,v):
* 2 label v as discovered
@@ -1677,8 +1741,10 @@ process_bpf_exit:
u8 mode = BPF_MODE(insn->code);
if (mode == BPF_ABS || mode == BPF_IND) {
- verbose("LD_ABS is not supported yet\n");
- return -EINVAL;
+ err = check_ld_abs(env, insn);
+ if (err)
+ return err;
+
} else if (mode == BPF_IMM) {
err = check_ld_imm(env, insn);
if (err)
--
1.7.9.5
^ permalink raw reply related
* [PATCH net-next 2/6] net: sock: allow eBPF programs to be attached to sockets
From: Alexei Starovoitov @ 2014-11-27 5:42 UTC (permalink / raw)
To: David S. Miller
Cc: Ingo Molnar, Andy Lutomirski, Daniel Borkmann,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1417066951-1999-1-git-send-email-ast@plumgrid.com>
introduce new setsockopt() command:
setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, sizeof(prog_fd))
where prog_fd was received from syscall bpf(BPF_PROG_LOAD, attr, ...)
and attr->prog_type == BPF_PROG_TYPE_SOCKET_FILTER
setsockopt() calls bpf_prog_get() which increments refcnt of the program,
so it doesn't get unloaded while socket is using the program.
The same eBPF program can be attached to multiple sockets.
User task exit automatically closes socket which calls sk_filter_uncharge()
which decrements refcnt of eBPF program
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
Note, I'm not happy about 'ifdef', but 'select or depend BPF_SYSCALL' will
make tinification folks cringe, so use ifdef until native eBPF use cases
become widespread.
---
arch/alpha/include/uapi/asm/socket.h | 3 +
arch/avr32/include/uapi/asm/socket.h | 3 +
arch/cris/include/uapi/asm/socket.h | 3 +
arch/frv/include/uapi/asm/socket.h | 3 +
arch/ia64/include/uapi/asm/socket.h | 3 +
arch/m32r/include/uapi/asm/socket.h | 3 +
arch/mips/include/uapi/asm/socket.h | 3 +
arch/mn10300/include/uapi/asm/socket.h | 3 +
arch/parisc/include/uapi/asm/socket.h | 3 +
arch/powerpc/include/uapi/asm/socket.h | 3 +
arch/s390/include/uapi/asm/socket.h | 3 +
arch/sparc/include/uapi/asm/socket.h | 3 +
arch/xtensa/include/uapi/asm/socket.h | 3 +
include/linux/bpf.h | 4 ++
include/linux/filter.h | 1 +
include/uapi/asm-generic/socket.h | 3 +
net/core/filter.c | 97 +++++++++++++++++++++++++++++++-
net/core/sock.c | 13 +++++
18 files changed, 155 insertions(+), 2 deletions(-)
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index e2fe0700b3b4..9a20821b111c 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -89,4 +89,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index 92121b0f5b98..2b65ed6b277c 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -82,4 +82,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _UAPI__ASM_AVR32_SOCKET_H */
diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h
index 60f60f5b9b35..e2503d9f1869 100644
--- a/arch/cris/include/uapi/asm/socket.h
+++ b/arch/cris/include/uapi/asm/socket.h
@@ -84,6 +84,9 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index 2c6890209ea6..4823ad125578 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -82,5 +82,8 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 09a93fb566f6..59be3d87f86d 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -91,4 +91,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h
index e8589819c274..7bc4cb273856 100644
--- a/arch/m32r/include/uapi/asm/socket.h
+++ b/arch/m32r/include/uapi/asm/socket.h
@@ -82,4 +82,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 2e9ee8c55a10..dec3c850f36b 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -100,4 +100,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index f3492e8c9f70..cab7d6d50051 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -82,4 +82,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 7984a1cab3da..a5cd40cd8ee1 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -81,4 +81,7 @@
#define SO_INCOMING_CPU 0x402A
+#define SO_ATTACH_BPF 0x402B
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index 3474e4ef166d..c046666038f8 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -89,4 +89,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 8457636c33e1..296942d56e6a 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -88,4 +88,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 4a8003a94163..e6a16c40be5f 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -78,6 +78,9 @@
#define SO_INCOMING_CPU 0x0033
+#define SO_ATTACH_BPF 0x0034
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index c46f6a696849..4120af086160 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -93,4 +93,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* _XTENSA_SOCKET_H */
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 75e94eaa228b..bbfceb756452 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -128,7 +128,11 @@ struct bpf_prog_aux {
struct work_struct work;
};
+#ifdef CONFIG_BPF_SYSCALL
void bpf_prog_put(struct bpf_prog *prog);
+#else
+static inline void bpf_prog_put(struct bpf_prog *prog) {}
+#endif
struct bpf_prog *bpf_prog_get(u32 ufd);
/* verify correctness of eBPF program */
int bpf_check(struct bpf_prog *fp, union bpf_attr *attr);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index ca95abd2bed1..caac2087a4d5 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -381,6 +381,7 @@ int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog);
void bpf_prog_destroy(struct bpf_prog *fp);
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
+int sk_attach_bpf(u32 ufd, struct sock *sk);
int sk_detach_filter(struct sock *sk);
int bpf_check_classic(const struct sock_filter *filter, unsigned int flen);
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index f541ccefd4ac..5c15c2a5c123 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -84,4 +84,7 @@
#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/net/core/filter.c b/net/core/filter.c
index 647b12265e18..8cc3c03078b3 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -44,6 +44,7 @@
#include <linux/ratelimit.h>
#include <linux/seccomp.h>
#include <linux/if_vlan.h>
+#include <linux/bpf.h>
/**
* sk_filter - run a packet through a socket filter
@@ -813,8 +814,12 @@ static void bpf_release_orig_filter(struct bpf_prog *fp)
static void __bpf_prog_release(struct bpf_prog *prog)
{
- bpf_release_orig_filter(prog);
- bpf_prog_free(prog);
+ if (prog->aux->prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
+ bpf_prog_put(prog);
+ } else {
+ bpf_release_orig_filter(prog);
+ bpf_prog_free(prog);
+ }
}
static void __sk_filter_release(struct sk_filter *fp)
@@ -1088,6 +1093,94 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
}
EXPORT_SYMBOL_GPL(sk_attach_filter);
+#ifdef CONFIG_BPF_SYSCALL
+int sk_attach_bpf(u32 ufd, struct sock *sk)
+{
+ struct sk_filter *fp, *old_fp;
+ struct bpf_prog *prog;
+
+ if (sock_flag(sk, SOCK_FILTER_LOCKED))
+ return -EPERM;
+
+ prog = bpf_prog_get(ufd);
+ if (!prog)
+ return -EINVAL;
+
+ if (prog->aux->prog_type != BPF_PROG_TYPE_SOCKET_FILTER) {
+ /* valid fd, but invalid program type */
+ bpf_prog_put(prog);
+ return -EINVAL;
+ }
+
+ fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ if (!fp) {
+ bpf_prog_put(prog);
+ return -ENOMEM;
+ }
+ fp->prog = prog;
+
+ atomic_set(&fp->refcnt, 0);
+
+ if (!sk_filter_charge(sk, fp)) {
+ __sk_filter_release(fp);
+ return -ENOMEM;
+ }
+
+ old_fp = rcu_dereference_protected(sk->sk_filter,
+ sock_owned_by_user(sk));
+ rcu_assign_pointer(sk->sk_filter, fp);
+
+ if (old_fp)
+ sk_filter_uncharge(sk, old_fp);
+
+ return 0;
+}
+
+/* allow socket filters to call
+ * bpf_map_lookup_elem(), bpf_map_update_elem(), bpf_map_delete_elem()
+ */
+static const struct bpf_func_proto *sock_filter_func_proto(enum bpf_func_id func_id)
+{
+ switch (func_id) {
+ case BPF_FUNC_map_lookup_elem:
+ return &bpf_map_lookup_elem_proto;
+ case BPF_FUNC_map_update_elem:
+ return &bpf_map_update_elem_proto;
+ case BPF_FUNC_map_delete_elem:
+ return &bpf_map_delete_elem_proto;
+ default:
+ return NULL;
+ }
+}
+
+static bool sock_filter_is_valid_access(int off, int size, enum bpf_access_type type)
+{
+ /* skb fields cannot be accessed yet */
+ return false;
+}
+
+static struct bpf_verifier_ops sock_filter_ops = {
+ .get_func_proto = sock_filter_func_proto,
+ .is_valid_access = sock_filter_is_valid_access,
+};
+
+static struct bpf_prog_type_list tl = {
+ .ops = &sock_filter_ops,
+ .type = BPF_PROG_TYPE_SOCKET_FILTER,
+};
+
+static int __init register_sock_filter_ops(void)
+{
+ bpf_register_prog_type(&tl);
+ return 0;
+}
+late_initcall(register_sock_filter_ops);
+#else
+int sk_attach_bpf(u32 ufd, struct sock *sk)
+{
+ return -EOPNOTSUPP;
+}
+#endif
int sk_detach_filter(struct sock *sk)
{
int ret = -ENOENT;
diff --git a/net/core/sock.c b/net/core/sock.c
index 0725cf0cb685..9a56b2000c3f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -888,6 +888,19 @@ set_rcvbuf:
}
break;
+ case SO_ATTACH_BPF:
+ ret = -EINVAL;
+ if (optlen == sizeof(u32)) {
+ u32 ufd;
+
+ ret = -EFAULT;
+ if (copy_from_user(&ufd, optval, sizeof(ufd)))
+ break;
+
+ ret = sk_attach_bpf(ufd, sk);
+ }
+ break;
+
case SO_DETACH_FILTER:
ret = sk_detach_filter(sk);
break;
--
1.7.9.5
^ permalink raw reply related
* [PATCH net-next 3/6] samples: bpf: example of stateful socket filtering
From: Alexei Starovoitov @ 2014-11-27 5:42 UTC (permalink / raw)
To: David S. Miller
Cc: Ingo Molnar, Andy Lutomirski, Daniel Borkmann,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1417066951-1999-1-git-send-email-ast@plumgrid.com>
this socket filter example does:
- creates arraymap in kernel with key 4 bytes and value 8 bytes
- loads eBPF program:
r0 = skb[14 + 9]; // load one byte of ip->proto
*(u32*)(fp - 4) = r0;
value = bpf_map_lookup_elem(map_fd, fp - 4);
if (value)
(*(u64*)value) += 1;
- attaches this program to raw socket
- every second user space reads map[tcp], map[udp], map[icmp] to see
how many packets of given protocol were seen on loopback interface
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
samples/bpf/Makefile | 2 +
samples/bpf/libbpf.c | 28 +++++++++++++
samples/bpf/libbpf.h | 13 ++++++
samples/bpf/sock_example.c | 97 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 140 insertions(+)
create mode 100644 samples/bpf/sock_example.c
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 0718d9ce4619..f46d3492d032 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -3,9 +3,11 @@ obj- := dummy.o
# List of programs to build
hostprogs-y := test_verifier test_maps
+hostprogs-y += sock_example
test_verifier-objs := test_verifier.o libbpf.o
test_maps-objs := test_maps.o libbpf.o
+sock_example-objs := sock_example.o libbpf.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c
index 17bb520eb57f..46d50b7ddf79 100644
--- a/samples/bpf/libbpf.c
+++ b/samples/bpf/libbpf.c
@@ -7,6 +7,10 @@
#include <linux/netlink.h>
#include <linux/bpf.h>
#include <errno.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#include <arpa/inet.h>
#include "libbpf.h"
static __u64 ptr_to_u64(void *ptr)
@@ -93,3 +97,27 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
}
+
+int open_raw_sock(const char *name)
+{
+ struct sockaddr_ll sll;
+ int sock;
+
+ sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, htons(ETH_P_ALL));
+ if (sock < 0) {
+ printf("cannot create raw socket\n");
+ return -1;
+ }
+
+ memset(&sll, 0, sizeof(sll));
+ sll.sll_family = AF_PACKET;
+ sll.sll_ifindex = if_nametoindex(name);
+ sll.sll_protocol = htons(ETH_P_ALL);
+ if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
+ printf("bind to %s: %s\n", name, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index f8678e5f48bf..cc62ad4d95de 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -99,6 +99,16 @@ extern char bpf_log_buf[LOG_BUF_SIZE];
BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
+/* Direct packet access, R0 = *(uint *) (skb->data + imm32) */
+
+#define BPF_LD_ABS(SIZE, IMM) \
+ ((struct bpf_insn) { \
+ .code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \
+ .dst_reg = 0, \
+ .src_reg = 0, \
+ .off = 0, \
+ .imm = IMM })
+
/* Memory load, dst_reg = *(uint *) (src_reg + off16) */
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
@@ -169,4 +179,7 @@ extern char bpf_log_buf[LOG_BUF_SIZE];
.off = 0, \
.imm = 0 })
+/* create RAW socket and bind to interface 'name' */
+int open_raw_sock(const char *name);
+
#endif
diff --git a/samples/bpf/sock_example.c b/samples/bpf/sock_example.c
new file mode 100644
index 000000000000..d74b58523458
--- /dev/null
+++ b/samples/bpf/sock_example.c
@@ -0,0 +1,97 @@
+/* eBPF example program:
+ * - creates arraymap in kernel with key 4 bytes and value 8 bytes
+ *
+ * - loads eBPF program:
+ * r0 = skb[14 + 9]; // load one byte of ip->proto
+ * *(u32*)(fp - 4) = r0;
+ * value = bpf_map_lookup_elem(map_fd, fp - 4);
+ * if (value)
+ * (*(u64*)value) += 1;
+ *
+ * - attaches this program to eth0 raw socket
+ *
+ * - every second user space reads map[tcp], map[udp], map[icmp] to see
+ * how many packets of given protocol were seen on eth0
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <linux/bpf.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include "libbpf.h"
+
+static int test_sock(void)
+{
+ int sock = -1, map_fd, prog_fd, i, key;
+ long long value = 0, tcp_cnt, udp_cnt, icmp_cnt;
+
+ map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
+ 256);
+ if (map_fd < 0) {
+ printf("failed to create map '%s'\n", strerror(errno));
+ goto cleanup;
+ }
+
+ struct bpf_insn prog[] = {
+ BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+ BPF_LD_ABS(BPF_B, 14 + 9 /* R0 = ip->proto */),
+ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */
+ BPF_LD_MAP_FD(BPF_REG_1, map_fd),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+ BPF_MOV64_IMM(BPF_REG_1, 1), /* r1 = 1 */
+ BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */
+ BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 */
+ BPF_EXIT_INSN(),
+ };
+
+ prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog),
+ "GPL");
+ if (prog_fd < 0) {
+ printf("failed to load prog '%s'\n", strerror(errno));
+ goto cleanup;
+ }
+
+ sock = open_raw_sock("lo");
+
+ if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
+ sizeof(prog_fd)) < 0) {
+ printf("setsockopt %s\n", strerror(errno));
+ goto cleanup;
+ }
+
+ for (i = 0; i < 10; i++) {
+ key = IPPROTO_TCP;
+ assert(bpf_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
+
+ key = IPPROTO_UDP;
+ assert(bpf_lookup_elem(map_fd, &key, &udp_cnt) == 0);
+
+ key = IPPROTO_ICMP;
+ assert(bpf_lookup_elem(map_fd, &key, &icmp_cnt) == 0);
+
+ printf("TCP %lld UDP %lld ICMP %lld packets\n",
+ tcp_cnt, udp_cnt, icmp_cnt);
+ sleep(1);
+ }
+
+cleanup:
+ /* maps, programs, raw sockets will auto cleanup on process exit */
+ return 0;
+}
+
+int main(void)
+{
+ FILE *f;
+
+ f = popen("ping -c5 localhost", "r");
+ (void)f;
+
+ return test_sock();
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH net-next 4/6] samples: bpf: elf_bpf file loader
From: Alexei Starovoitov @ 2014-11-27 5:42 UTC (permalink / raw)
To: David S. Miller
Cc: Ingo Molnar, Andy Lutomirski, Daniel Borkmann,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1417066951-1999-1-git-send-email-ast@plumgrid.com>
simple .o parser and loader using BPF syscall.
.o is a standard ELF generated by LLVM backend
It parses elf file compiled by llvm .c->.o
- parses 'maps' section and creates maps via BPF syscall
- parses 'license' section and passes it to syscall
- parses elf relocations for BPF maps and adjusts BPF_LD_IMM64 insns
by storing map_fd into insn->imm and marking such insns as BPF_PSEUDO_MAP_FD
- loads eBPF programs via BPF syscall
One ELF file can contain multiple BPF programs.
int load_bpf_file(char *path);
populates prog_fd[] and map_fd[] with FDs received from bpf syscall
bpf_helpers.h - helper functions available to eBPF programs written in C
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
These helpers and loader are done as separate patch to make eBPF C examples
(that follow in the next patches) to focus on demonstrating programming
of eBPF in restricted C.
---
samples/bpf/bpf_helpers.h | 40 +++++++++
samples/bpf/bpf_load.c | 203 +++++++++++++++++++++++++++++++++++++++++++++
samples/bpf/bpf_load.h | 24 ++++++
3 files changed, 267 insertions(+)
create mode 100644 samples/bpf/bpf_helpers.h
create mode 100644 samples/bpf/bpf_load.c
create mode 100644 samples/bpf/bpf_load.h
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
new file mode 100644
index 000000000000..ca0333146006
--- /dev/null
+++ b/samples/bpf/bpf_helpers.h
@@ -0,0 +1,40 @@
+#ifndef __BPF_HELPERS_H
+#define __BPF_HELPERS_H
+
+/* helper macro to place programs, maps, license in
+ * different sections in elf_bpf file. Section names
+ * are interpreted by elf_bpf loader
+ */
+#define SEC(NAME) __attribute__((section(NAME), used))
+
+/* helper functions called from eBPF programs written in C */
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+ (void *) BPF_FUNC_map_lookup_elem;
+static int (*bpf_map_update_elem)(void *map, void *key, void *value,
+ unsigned long long flags) =
+ (void *) BPF_FUNC_map_update_elem;
+static int (*bpf_map_delete_elem)(void *map, void *key) =
+ (void *) BPF_FUNC_map_delete_elem;
+
+/* llvm builtin functions that eBPF C program may use to
+ * emit BPF_LD_ABS and BPF_LD_IND instructions
+ */
+struct sk_buff;
+unsigned long long load_byte(void *skb,
+ unsigned long long off) asm("llvm.bpf.load.byte");
+unsigned long long load_half(void *skb,
+ unsigned long long off) asm("llvm.bpf.load.half");
+unsigned long long load_word(void *skb,
+ unsigned long long off) asm("llvm.bpf.load.word");
+
+/* a helper structure used by eBPF C program
+ * to describe map attributes to elf_bpf loader
+ */
+struct bpf_map_def {
+ unsigned int type;
+ unsigned int key_size;
+ unsigned int value_size;
+ unsigned int max_entries;
+};
+
+#endif
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
new file mode 100644
index 000000000000..1831d236382b
--- /dev/null
+++ b/samples/bpf/bpf_load.c
@@ -0,0 +1,203 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <gelf.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <linux/bpf.h>
+#include <linux/filter.h>
+#include "libbpf.h"
+#include "bpf_helpers.h"
+#include "bpf_load.h"
+
+static char license[128];
+static bool processed_sec[128];
+int map_fd[MAX_MAPS];
+int prog_fd[MAX_PROGS];
+int prog_cnt;
+
+static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
+{
+ int fd;
+ bool is_socket = strncmp(event, "socket", 6) == 0;
+
+ if (!is_socket)
+ /* tracing events tbd */
+ return -1;
+
+ fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
+ prog, size, license);
+
+ if (fd < 0) {
+ printf("bpf_prog_load() err=%d\n%s", errno, bpf_log_buf);
+ return -1;
+ }
+
+ prog_fd[prog_cnt++] = fd;
+
+ return 0;
+}
+
+static int load_maps(struct bpf_map_def *maps, int len)
+{
+ int i;
+
+ for (i = 0; i < len / sizeof(struct bpf_map_def); i++) {
+
+ map_fd[i] = bpf_create_map(maps[i].type,
+ maps[i].key_size,
+ maps[i].value_size,
+ maps[i].max_entries);
+ if (map_fd[i] < 0)
+ return 1;
+ }
+ return 0;
+}
+
+static int get_sec(Elf *elf, int i, GElf_Ehdr *ehdr, char **shname,
+ GElf_Shdr *shdr, Elf_Data **data)
+{
+ Elf_Scn *scn;
+
+ scn = elf_getscn(elf, i);
+ if (!scn)
+ return 1;
+
+ if (gelf_getshdr(scn, shdr) != shdr)
+ return 2;
+
+ *shname = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name);
+ if (!*shname || !shdr->sh_size)
+ return 3;
+
+ *data = elf_getdata(scn, 0);
+ if (!*data || elf_getdata(scn, *data) != NULL)
+ return 4;
+
+ return 0;
+}
+
+static int parse_relo_and_apply(Elf_Data *data, Elf_Data *symbols,
+ GElf_Shdr *shdr, struct bpf_insn *insn)
+{
+ int i, nrels;
+
+ nrels = shdr->sh_size / shdr->sh_entsize;
+
+ for (i = 0; i < nrels; i++) {
+ GElf_Sym sym;
+ GElf_Rel rel;
+ unsigned int insn_idx;
+
+ gelf_getrel(data, i, &rel);
+
+ insn_idx = rel.r_offset / sizeof(struct bpf_insn);
+
+ gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym);
+
+ if (insn[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
+ printf("invalid relo for insn[%d].code 0x%x\n",
+ insn_idx, insn[insn_idx].code);
+ return 1;
+ }
+ insn[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
+ insn[insn_idx].imm = map_fd[sym.st_value / sizeof(struct bpf_map_def)];
+ }
+
+ return 0;
+}
+
+int load_bpf_file(char *path)
+{
+ int fd, i;
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr, shdr_prog;
+ Elf_Data *data, *data_prog, *symbols = NULL;
+ char *shname, *shname_prog;
+
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ return 1;
+
+ fd = open(path, O_RDONLY, 0);
+ if (fd < 0)
+ return 1;
+
+ elf = elf_begin(fd, ELF_C_READ, NULL);
+
+ if (!elf)
+ return 1;
+
+ if (gelf_getehdr(elf, &ehdr) != &ehdr)
+ return 1;
+
+ /* scan over all elf sections to get license and map info */
+ for (i = 1; i < ehdr.e_shnum; i++) {
+
+ if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
+ continue;
+
+ if (0) /* helpful for llvm debugging */
+ printf("section %d:%s data %p size %zd link %d flags %d\n",
+ i, shname, data->d_buf, data->d_size,
+ shdr.sh_link, (int) shdr.sh_flags);
+
+ if (strcmp(shname, "license") == 0) {
+ processed_sec[i] = true;
+ memcpy(license, data->d_buf, data->d_size);
+ } else if (strcmp(shname, "maps") == 0) {
+ processed_sec[i] = true;
+ if (load_maps(data->d_buf, data->d_size))
+ return 1;
+ } else if (shdr.sh_type == SHT_SYMTAB) {
+ symbols = data;
+ }
+ }
+
+ /* load programs that need map fixup (relocations) */
+ for (i = 1; i < ehdr.e_shnum; i++) {
+
+ if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
+ continue;
+ if (shdr.sh_type == SHT_REL) {
+ struct bpf_insn *insns;
+
+ if (get_sec(elf, shdr.sh_info, &ehdr, &shname_prog,
+ &shdr_prog, &data_prog))
+ continue;
+
+ insns = (struct bpf_insn *) data_prog->d_buf;
+
+ processed_sec[shdr.sh_info] = true;
+ processed_sec[i] = true;
+
+ if (parse_relo_and_apply(data, symbols, &shdr, insns))
+ continue;
+
+ if (memcmp(shname_prog, "events/", 7) == 0 ||
+ memcmp(shname_prog, "socket", 6) == 0)
+ load_and_attach(shname_prog, insns, data_prog->d_size);
+ }
+ }
+
+ /* load programs that don't use maps */
+ for (i = 1; i < ehdr.e_shnum; i++) {
+
+ if (processed_sec[i])
+ continue;
+
+ if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
+ continue;
+
+ if (memcmp(shname, "events/", 7) == 0 ||
+ memcmp(shname, "socket", 6) == 0)
+ load_and_attach(shname, data->d_buf, data->d_size);
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/samples/bpf/bpf_load.h b/samples/bpf/bpf_load.h
new file mode 100644
index 000000000000..27789a34f5e6
--- /dev/null
+++ b/samples/bpf/bpf_load.h
@@ -0,0 +1,24 @@
+#ifndef __BPF_LOAD_H
+#define __BPF_LOAD_H
+
+#define MAX_MAPS 32
+#define MAX_PROGS 32
+
+extern int map_fd[MAX_MAPS];
+extern int prog_fd[MAX_PROGS];
+
+/* parses elf file compiled by llvm .c->.o
+ * . parses 'maps' section and creates maps via BPF syscall
+ * . parses 'license' section and passes it to syscall
+ * . parses elf relocations for BPF maps and adjusts BPF_LD_IMM64 insns by
+ * storing map_fd into insn->imm and marking such insns as BPF_PSEUDO_MAP_FD
+ * . loads eBPF programs via BPF syscall
+ *
+ * One ELF file can contain multiple BPF programs which will be loaded
+ * and their FDs stored stored in prog_fd array
+ *
+ * returns zero on success
+ */
+int load_bpf_file(char *path);
+
+#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH net-next 5/6] samples: bpf: trivial eBPF program in C
From: Alexei Starovoitov @ 2014-11-27 5:42 UTC (permalink / raw)
To: David S. Miller
Cc: Ingo Molnar, Andy Lutomirski, Daniel Borkmann,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1417066951-1999-1-git-send-email-ast@plumgrid.com>
this example does the same task as previous socket example
in assembler, but this one does it in C.
eBPF program in kernel does:
int index = load_byte(skb, 14 + 9); /* ip_proto */
long *value;
value = bpf_map_lookup_elem(&my_map, &index);
if (value)
__sync_fetch_and_add(value, 1);
Corresponding user space reads map[tcp], map[udp], map[icmp]
and prints protocol stats every second
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
samples/bpf/Makefile | 14 +++++++++++++
samples/bpf/libbpf.h | 2 +-
samples/bpf/sockex1_kern.c | 23 +++++++++++++++++++++
samples/bpf/sockex1_user.c | 49 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 1 deletion(-)
create mode 100644 samples/bpf/sockex1_kern.c
create mode 100644 samples/bpf/sockex1_user.c
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index f46d3492d032..770d145186c3 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -4,12 +4,26 @@ obj- := dummy.o
# List of programs to build
hostprogs-y := test_verifier test_maps
hostprogs-y += sock_example
+hostprogs-y += sockex1
test_verifier-objs := test_verifier.o libbpf.o
test_maps-objs := test_maps.o libbpf.o
sock_example-objs := sock_example.o libbpf.o
+sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
+always += sockex1_kern.o
HOSTCFLAGS += -I$(objtree)/usr/include
+
+HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
+HOSTLOADLIBES_sockex1 += -lelf
+
+# point this to your LLVM backend with bpf support
+LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
+
+%.o: %.c
+ clang $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) \
+ -D__KERNEL__ -Wno-unused-value -Wno-pointer-sign \
+ -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index cc62ad4d95de..58c5fe1bdba1 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -15,7 +15,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
const struct bpf_insn *insns, int insn_len,
const char *license);
-#define LOG_BUF_SIZE 8192
+#define LOG_BUF_SIZE 65536
extern char bpf_log_buf[LOG_BUF_SIZE];
/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
diff --git a/samples/bpf/sockex1_kern.c b/samples/bpf/sockex1_kern.c
new file mode 100644
index 000000000000..e662779467de
--- /dev/null
+++ b/samples/bpf/sockex1_kern.c
@@ -0,0 +1,23 @@
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+struct bpf_map_def SEC("maps") my_map = {
+ .type = BPF_MAP_TYPE_ARRAY,
+ .key_size = sizeof(u32),
+ .value_size = sizeof(long),
+ .max_entries = 256,
+};
+
+SEC("socket1")
+int bpf_prog1(struct sk_buff *skb)
+{
+ int index = load_byte(skb, 14 + 9);
+ long *value;
+
+ value = bpf_map_lookup_elem(&my_map, &index);
+ if (value)
+ __sync_fetch_and_add(value, 1);
+
+ return 0;
+}
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/sockex1_user.c b/samples/bpf/sockex1_user.c
new file mode 100644
index 000000000000..34a443ff3831
--- /dev/null
+++ b/samples/bpf/sockex1_user.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <assert.h>
+#include <linux/bpf.h>
+#include "libbpf.h"
+#include "bpf_load.h"
+#include <unistd.h>
+#include <arpa/inet.h>
+
+int main(int ac, char **argv)
+{
+ char filename[256];
+ FILE *f;
+ int i, sock;
+
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+ if (load_bpf_file(filename)) {
+ printf("%s", bpf_log_buf);
+ return 1;
+ }
+
+ sock = open_raw_sock("lo");
+
+ assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd,
+ sizeof(prog_fd[0])) == 0);
+
+ f = popen("ping -c5 localhost", "r");
+ (void) f;
+
+ for (i = 0; i < 5; i++) {
+ long long tcp_cnt, udp_cnt, icmp_cnt;
+ int key;
+
+ key = IPPROTO_TCP;
+ assert(bpf_lookup_elem(map_fd[0], &key, &tcp_cnt) == 0);
+
+ key = IPPROTO_UDP;
+ assert(bpf_lookup_elem(map_fd[0], &key, &udp_cnt) == 0);
+
+ key = IPPROTO_ICMP;
+ assert(bpf_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0);
+
+ printf("TCP %lld UDP %lld ICMP %lld packets\n",
+ tcp_cnt, udp_cnt, icmp_cnt);
+ sleep(1);
+ }
+
+ return 0;
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH net-next 6/6] samples: bpf: large eBPF program in C
From: Alexei Starovoitov @ 2014-11-27 5:42 UTC (permalink / raw)
To: David S. Miller
Cc: Ingo Molnar, Andy Lutomirski, Daniel Borkmann,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1417066951-1999-1-git-send-email-ast@plumgrid.com>
sockex2_kern.c is purposefully large eBPF program in C.
llvm compiles ~200 lines of C code into ~300 eBPF instructions.
It's similar to __skb_flow_dissect() to demonstrate that complex packet parsing
can be done by eBPF.
Then it uses (struct flow_keys)->dst IP address (or hash of ipv6 dst) to keep
stats of number of packets per IP.
User space loads eBPF program, attaches it to loopback interface and prints
dest_ip->#packets stats every second.
Usage:
$sudo samples/bpf/sockex2
ip 127.0.0.1 count 19
ip 127.0.0.1 count 178115
ip 127.0.0.1 count 369437
ip 127.0.0.1 count 559841
ip 127.0.0.1 count 750539
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
samples/bpf/Makefile | 4 +
samples/bpf/sockex2_kern.c | 215 ++++++++++++++++++++++++++++++++++++++++++++
samples/bpf/sockex2_user.c | 44 +++++++++
3 files changed, 263 insertions(+)
create mode 100644 samples/bpf/sockex2_kern.c
create mode 100644 samples/bpf/sockex2_user.c
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 770d145186c3..b5b3600dcdf5 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -5,20 +5,24 @@ obj- := dummy.o
hostprogs-y := test_verifier test_maps
hostprogs-y += sock_example
hostprogs-y += sockex1
+hostprogs-y += sockex2
test_verifier-objs := test_verifier.o libbpf.o
test_maps-objs := test_maps.o libbpf.o
sock_example-objs := sock_example.o libbpf.o
sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
+sockex2-objs := bpf_load.o libbpf.o sockex2_user.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
always += sockex1_kern.o
+always += sockex2_kern.o
HOSTCFLAGS += -I$(objtree)/usr/include
HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
HOSTLOADLIBES_sockex1 += -lelf
+HOSTLOADLIBES_sockex2 += -lelf
# point this to your LLVM backend with bpf support
LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c
new file mode 100644
index 000000000000..6f0135f0f217
--- /dev/null
+++ b/samples/bpf/sockex2_kern.c
@@ -0,0 +1,215 @@
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+#include <uapi/linux/in.h>
+#include <uapi/linux/if.h>
+#include <uapi/linux/if_ether.h>
+#include <uapi/linux/ip.h>
+#include <uapi/linux/ipv6.h>
+#include <uapi/linux/if_tunnel.h>
+#define IP_MF 0x2000
+#define IP_OFFSET 0x1FFF
+
+struct vlan_hdr {
+ __be16 h_vlan_TCI;
+ __be16 h_vlan_encapsulated_proto;
+};
+
+struct flow_keys {
+ __be32 src;
+ __be32 dst;
+ union {
+ __be32 ports;
+ __be16 port16[2];
+ };
+ __u16 thoff;
+ __u8 ip_proto;
+};
+
+static inline int proto_ports_offset(__u64 proto)
+{
+ switch (proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_DCCP:
+ case IPPROTO_ESP:
+ case IPPROTO_SCTP:
+ case IPPROTO_UDPLITE:
+ return 0;
+ case IPPROTO_AH:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+static inline int ip_is_fragment(struct sk_buff *ctx, __u64 nhoff)
+{
+ return load_half(ctx, nhoff + offsetof(struct iphdr, frag_off))
+ & (IP_MF | IP_OFFSET);
+}
+
+static inline __u32 ipv6_addr_hash(struct sk_buff *ctx, __u64 off)
+{
+ __u64 w0 = load_word(ctx, off);
+ __u64 w1 = load_word(ctx, off + 4);
+ __u64 w2 = load_word(ctx, off + 8);
+ __u64 w3 = load_word(ctx, off + 12);
+
+ return (__u32)(w0 ^ w1 ^ w2 ^ w3);
+}
+
+static inline __u64 parse_ip(struct sk_buff *skb, __u64 nhoff, __u64 *ip_proto,
+ struct flow_keys *flow)
+{
+ __u64 verlen;
+
+ if (unlikely(ip_is_fragment(skb, nhoff)))
+ *ip_proto = 0;
+ else
+ *ip_proto = load_byte(skb, nhoff + offsetof(struct iphdr, protocol));
+
+ if (*ip_proto != IPPROTO_GRE) {
+ flow->src = load_word(skb, nhoff + offsetof(struct iphdr, saddr));
+ flow->dst = load_word(skb, nhoff + offsetof(struct iphdr, daddr));
+ }
+
+ verlen = load_byte(skb, nhoff + 0/*offsetof(struct iphdr, ihl)*/);
+ if (likely(verlen == 0x45))
+ nhoff += 20;
+ else
+ nhoff += (verlen & 0xF) << 2;
+
+ return nhoff;
+}
+
+static inline __u64 parse_ipv6(struct sk_buff *skb, __u64 nhoff, __u64 *ip_proto,
+ struct flow_keys *flow)
+{
+ *ip_proto = load_byte(skb,
+ nhoff + offsetof(struct ipv6hdr, nexthdr));
+ flow->src = ipv6_addr_hash(skb,
+ nhoff + offsetof(struct ipv6hdr, saddr));
+ flow->dst = ipv6_addr_hash(skb,
+ nhoff + offsetof(struct ipv6hdr, daddr));
+ nhoff += sizeof(struct ipv6hdr);
+
+ return nhoff;
+}
+
+static inline bool flow_dissector(struct sk_buff *skb, struct flow_keys *flow)
+{
+ __u64 nhoff = ETH_HLEN;
+ __u64 ip_proto;
+ __u64 proto = load_half(skb, 12);
+ int poff;
+
+ if (proto == ETH_P_8021AD) {
+ proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
+ h_vlan_encapsulated_proto));
+ nhoff += sizeof(struct vlan_hdr);
+ }
+
+ if (proto == ETH_P_8021Q) {
+ proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
+ h_vlan_encapsulated_proto));
+ nhoff += sizeof(struct vlan_hdr);
+ }
+
+ if (likely(proto == ETH_P_IP))
+ nhoff = parse_ip(skb, nhoff, &ip_proto, flow);
+ else if (proto == ETH_P_IPV6)
+ nhoff = parse_ipv6(skb, nhoff, &ip_proto, flow);
+ else
+ return false;
+
+ switch (ip_proto) {
+ case IPPROTO_GRE: {
+ struct gre_hdr {
+ __be16 flags;
+ __be16 proto;
+ };
+
+ __u64 gre_flags = load_half(skb,
+ nhoff + offsetof(struct gre_hdr, flags));
+ __u64 gre_proto = load_half(skb,
+ nhoff + offsetof(struct gre_hdr, proto));
+
+ if (gre_flags & (GRE_VERSION|GRE_ROUTING))
+ break;
+
+ proto = gre_proto;
+ nhoff += 4;
+ if (gre_flags & GRE_CSUM)
+ nhoff += 4;
+ if (gre_flags & GRE_KEY)
+ nhoff += 4;
+ if (gre_flags & GRE_SEQ)
+ nhoff += 4;
+
+ if (proto == ETH_P_8021Q) {
+ proto = load_half(skb,
+ nhoff + offsetof(struct vlan_hdr,
+ h_vlan_encapsulated_proto));
+ nhoff += sizeof(struct vlan_hdr);
+ }
+
+ if (proto == ETH_P_IP)
+ nhoff = parse_ip(skb, nhoff, &ip_proto, flow);
+ else if (proto == ETH_P_IPV6)
+ nhoff = parse_ipv6(skb, nhoff, &ip_proto, flow);
+ else
+ return false;
+ break;
+ }
+ case IPPROTO_IPIP:
+ nhoff = parse_ip(skb, nhoff, &ip_proto, flow);
+ break;
+ case IPPROTO_IPV6:
+ nhoff = parse_ipv6(skb, nhoff, &ip_proto, flow);
+ break;
+ default:
+ break;
+ }
+
+ flow->ip_proto = ip_proto;
+ poff = proto_ports_offset(ip_proto);
+ if (poff >= 0) {
+ nhoff += poff;
+ flow->ports = load_word(skb, nhoff);
+ }
+
+ flow->thoff = (__u16) nhoff;
+
+ return true;
+}
+
+struct bpf_map_def SEC("maps") hash_map = {
+ .type = BPF_MAP_TYPE_HASH,
+ .key_size = sizeof(__be32),
+ .value_size = sizeof(long),
+ .max_entries = 1024,
+};
+
+SEC("socket2")
+int bpf_prog2(struct sk_buff *skb)
+{
+ struct flow_keys flow;
+ long *value;
+ u32 key;
+
+ if (!flow_dissector(skb, &flow))
+ return 0;
+
+ key = flow.dst;
+ value = bpf_map_lookup_elem(&hash_map, &key);
+ if (value) {
+ __sync_fetch_and_add(value, 1);
+ } else {
+ long val = 1;
+
+ bpf_map_update_elem(&hash_map, &key, &val, BPF_ANY);
+ }
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/sockex2_user.c b/samples/bpf/sockex2_user.c
new file mode 100644
index 000000000000..d2d5f5a790d3
--- /dev/null
+++ b/samples/bpf/sockex2_user.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <assert.h>
+#include <linux/bpf.h>
+#include "libbpf.h"
+#include "bpf_load.h"
+#include <unistd.h>
+#include <arpa/inet.h>
+
+int main(int ac, char **argv)
+{
+ char filename[256];
+ FILE *f;
+ int i, sock;
+
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+ if (load_bpf_file(filename)) {
+ printf("%s", bpf_log_buf);
+ return 1;
+ }
+
+ sock = open_raw_sock("lo");
+
+ assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd,
+ sizeof(prog_fd[0])) == 0);
+
+ f = popen("ping -c5 localhost", "r");
+ (void) f;
+
+ for (i = 0; i < 5; i++) {
+ int key = 0, next_key;
+ long long value;
+
+ while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
+ bpf_lookup_elem(map_fd[0], &next_key, &value);
+ printf("ip %s count %lld\n",
+ inet_ntoa((struct in_addr){htonl(next_key)}),
+ value);
+ key = next_key;
+ }
+ sleep(1);
+ }
+ return 0;
+}
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH v2 03/19] selftests: add install target to enable installing selftests
From: Masami Hiramatsu @ 2014-11-27 5:45 UTC (permalink / raw)
To: Shuah Khan
Cc: gregkh, akpm, mmarek, davem, keescook, tranmanphong, dh.herrmann,
hughd, bobby.prani, ebiederm, serge.hallyn, linux-kbuild,
linux-kernel, linux-api, netdev, yrl.pp-manager.tt@hitachi.com
In-Reply-To: <5e33b40696debde24fd04f6711e795a8860b7aee.1415735831.git.shuahkh@osg.samsung.com>
(2014/11/12 5:27), Shuah Khan wrote:
> Add a new make target to enable installing selftests. This
> new target will call install targets for the tests that are
> specified in INSTALL_TARGETS. During install, a script is
> generated to run tests that are installed. This script will
> be installed in the selftest install directory. Individual
> test Makefiles are changed to add to the script. This will
> allow new tests to add install and run test commands to the
> generated kselftest script. run_tests target runs the
> generated kselftest script to run tests when it is initiated
> from from "make kselftest" from top level source directory.
>
> Approach:
>
> make kselftest_target:
> -- exports kselftest INSTALL_KSFT_PATH
> default $(INSTALL_MOD_PATH)/lib/kselftest/$(KERNELRELEASE)
> -- exports path for ksefltest.sh
> -- runs selftests make install target:
>
> selftests make install target
> -- creates kselftest.sh script in install install dir
> -- runs install targets for all INSTALL_TARGETS
> (Note: ftrace and powerpc aren't included in INSTALL_TARGETS,
> to not add more content to patch v1 series. This work
> will happen soon. In this series these two targets are
> run after running the generated kselftest script, without
> any regression in the way these tests are run with
> "make kselftest" prior to this work.)
> -- install target can be run only from top level source dir.
>
> Individual test make install targets:
> -- install test programs and/or scripts in install dir
> -- append to the ksefltest.sh file to add commands to run test
> -- install target can be run only from top level source dir.
>
> Adds the following new ways to initiate selftests:
> -- Installing and running kselftest from install directory
> by running "make kselftest"
> -- Running kselftest script from install directory
>
> Maintains the following ways to run tests:
> -- make -C tools/testing/selftests run_tests
> -- make -C tools/testing/selftests TARGETS=target run_tests
> Ability specify targets: e.g TARGETS=net
> -- make run_tests from tools/testing/selftests
> -- make run_tests from individual test directories:
> e.g: make run_tests in tools/testing/selftests/breakpoints
>
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
> tools/testing/selftests/Makefile | 31 ++++++++++++++++++++++++++++++-
> 1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
> index 45f145c..b9bdc1d 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -16,6 +16,10 @@ TARGETS += sysctl
> TARGETS += firmware
> TARGETS += ftrace
>
> +INSTALL_TARGETS = breakpoints cpu-hotplug efivarfs firmware ipc
> +INSTALL_TARGETS += kcmp memfd memory-hotplug mqueue mount net
> +INSTALL_TARGETS += ptrace sysctl timers user vm
> +
> TARGETS_HOTPLUG = cpu-hotplug
> TARGETS_HOTPLUG += memory-hotplug
>
I think KSELFTEST itself should be defined here, since that is not
a parameter.
> @@ -24,10 +28,35 @@ all:
> make -C $$TARGET; \
> done;
>
> -run_tests: all
> +install:
> +ifdef INSTALL_KSFT_PATH
> + make all
> + @echo #!/bin/sh\n# Kselftest Run Tests .... >> $(KSELFTEST)
> + @echo # This file is generated during kselftest_install >> $(KSELFTEST)
> + @echo # Please don't change it !!\n >> $(KSELFTEST)
> + @echo echo ============================== >> $(KSELFTEST)
> + for TARGET in $(INSTALL_TARGETS); do \
> + echo Installing $$TARGET; \
> + make -C $$TARGET install; \
Please pass O= option and others here.
> + done;
> + chmod +x $(KSELFTEST)
> +else
> + @echo Run make kselftest_install in top level source directory
> +endif
> +
> +run_tests:
> +ifdef INSTALL_KSFT_PATH
> + @cd $(INSTALL_KSFT_PATH); ./kselftest.sh; cd -
We'd better use some macro instead of ./kselftest.sh?
Thank you,
> +# TODO: include ftrace and powerpc in install targets
> + for TARGET in ftrace powerpc; do \
> + make -C $$TARGET run_tests; \
> + done;
> +else
> + make all
> for TARGET in $(TARGETS); do \
> make -C $$TARGET run_tests; \
> done;
> +endif
>
> hotplug:
> for TARGET in $(TARGETS_HOTPLUG); do \
>
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
^ permalink raw reply
* Re: [PATCH v2 11/19] selftests/memory-hotplug: add install target to enable installing test
From: Masami Hiramatsu @ 2014-11-27 5:49 UTC (permalink / raw)
To: Shuah Khan
Cc: gregkh, akpm, mmarek, davem, keescook, tranmanphong, dh.herrmann,
hughd, bobby.prani, ebiederm, serge.hallyn, linux-kbuild,
linux-kernel, linux-api, netdev, yrl.pp-manager.tt@hitachi.com
In-Reply-To: <8cdb2abb6eaa794801548e04ee6b9f403778e126.1415735831.git.shuahkh@osg.samsung.com>
(2014/11/12 5:27), Shuah Khan wrote:
> Add a new make target to enable installing test. This target
> installs test in the kselftest install location and add to the
> kselftest script to run the test. Install target can be run
> only from top level source dir.
>
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> ---
> tools/testing/selftests/memory-hotplug/Makefile | 17 +-
> .../selftests/memory-hotplug/mem-on-off-test.sh | 238 +++++++++++++++++++++
> .../selftests/memory-hotplug/on-off-test.sh | 238 ---------------------
> 3 files changed, 253 insertions(+), 240 deletions(-)
> create mode 100644 tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
> delete mode 100644 tools/testing/selftests/memory-hotplug/on-off-test.sh
>
> diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile
> index d46b8d4..8921631 100644
> --- a/tools/testing/selftests/memory-hotplug/Makefile
> +++ b/tools/testing/selftests/memory-hotplug/Makefile
> @@ -1,9 +1,22 @@
> +TEST_STR=/bin/bash ./mem-on-off-test.sh -r 2 || echo memory-hotplug selftests: [FAIL]
> +
> all:
>
> +install:
> +ifdef INSTALL_KSFT_PATH
> + install ./mem-on-off-test.sh $(INSTALL_KSFT_PATH)/mem-on-off-test.sh
> + @echo echo Start memory hotplug test .... >> $(KSELFTEST)
> + @echo "$(TEST_STR)" >> $(KSELFTEST) >> $(KSELFTEST)
> + @echo echo End memory hotplug test .... >> $(KSELFTEST)
> + @echo echo ============================== >> $(KSELFTEST)
> +else
> + @echo Run make kselftest_install in top level source directory
> +endif
I saw this pattern repeated many times in this series.
Can we make it a macro and include it instead of repeating this code?
Thank you,
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
^ permalink raw reply
* Re: [PATCH v4] selftest: size: Add size test for Linux kernel
From: Josh Triplett @ 2014-11-27 6:04 UTC (permalink / raw)
To: Tim Bird
Cc: Shuah Khan, linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-embedded-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <5476A82B.2060903-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
On Wed, Nov 26, 2014 at 08:27:23PM -0800, Tim Bird wrote:
> --- /dev/null
> +++ b/tools/testing/selftests/size/Makefile
[...]
> +LIBGCC=$(shell $(CC) -print-libgcc-file-name)
> +
> +get_size: get_size.c
> + $(CC) --static -ffreestanding -nostartfiles \
> + -Wl,--entry=_start get_size.c $(LIBGCC) \
> + -o get_size
You don't need -Wl,--entry=_start; that's the default.
You shouldn't need to manually find libgcc, either; the compiler should
do that for you. What goes wrong if you don't include that? If you're
trying to link libgcc statically, try -static-libgcc.
Also, static is normally spelled -static, not --static.
> --- /dev/null
> +++ b/tools/testing/selftests/size/get_size.c
[...]
> +int print(const char *s)
This function, and all the others apart from _start, should be declared
static.
> +void num_to_str(unsigned long num, char *s)
Likewise, static.
> +{
> + unsigned long long temp, div;
> + int started;
> +
> + temp = num;
> + div = 1000000000000000000LL;
> + started = 0;
> + while (div) {
> + if (temp/div || started) {
> + *s++ = (unsigned char)(temp/div + '0');
> + started = 1;
> + }
> + temp -= (temp/div)*div;
> + div /= 10;
> + }
> + *s = 0;
> +}
You'd probably end up with significantly smaller code (and no divisions,
and thus no corner cases on architectures that need a special function
to do unsigned long long division) if you print in hex. You could also
drop the "no leading zeros" logic, and just *always* print a 64-bit
value as 16 hex digits.
> +int print_num(unsigned long num)
Likewise, static.
> +{
> + char num_buf[30];
> +
> + num_to_str(num, num_buf);
> + return print(num_buf);
> +}
> +
> +int print_k_value(const char *s, unsigned long num, unsigned long units)
> +{
> + unsigned long long temp;
> + int ccode;
> +
> + print(s);
> +
> + temp = num;
> + temp = (temp * units)/1024;
> + num = temp;
> + ccode = print_num(num);
> + print("\n");
> + return ccode;
> +}
I'd suggest dropping this entirely, and just always printing the exact
values returned by sysinfo. Drop the multiply, too, and just print
info.mem_unit as well. It's easy to post-process the value in a more
capable environment.
> +/* this program has no main(), as startup libraries are not used */
> +void _start(void)
> +{
> + int ccode;
> + struct sysinfo info;
> + unsigned long used;
> +
> + print("Testing system size.\n");
> + print("1..1\n");
> +
> + ccode = sysinfo(&info);
> + if (ccode < 0) {
> + print("not ok 1 get size runtime size\n");
Shouldn't the "not ok" here and the "ok" below have the same test
description?
> + print("# could not get sysinfo\n");
> + _exit(ccode);
> + }
> + /* ignore cache complexities for now */
> + used = info.totalram - info.freeram - info.bufferram;
> + print_k_value("ok 1 get runtime memory use # size = ", used,
> + info.mem_unit);
> +
> + print("# System runtime memory report (units in Kilobytes):\n");
> + print_k_value("# Total: ", info.totalram, info.mem_unit);
> + print_k_value("# Free: ", info.freeram, info.mem_unit);
> + print_k_value("# Buffer: ", info.bufferram, info.mem_unit);
> + print_k_value("# In use: ", used, info.mem_unit);
> +
> + _exit(0);
> +}
> --
> 1.8.2.2
>
^ permalink raw reply
* [GIT PULL] core drm support for Rockchip SoCs v14
From: Mark yao @ 2014-11-27 7:01 UTC (permalink / raw)
To: heiko, Boris BREZILLON, David Airlie, Rob Clark, Daniel Vetter,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Randy Dunlap, Grant Likely, Greg Kroah-Hartman, John Stultz,
Rom Lemarchand
Cc: devicetree, linux-doc, linux-kernel, dri-devel, linux-api,
linux-rockchip, dianders, marcheu, dbehr, olof, djkurtz, cf, xxm,
huangtao, kever.yang, yxj, xw, Mark Yao
In-Reply-To: <1416447994-9921-1-git-send-email-mark.yao@rock-chips.com>
Hi Dave
this pull request is for rockchip drm v14, based on Joerg's iommu
arm/rockchip branch.
The following changes since commit 656d7077d8ffd1c2492d4a0a354367ab2e545059:
dt-bindings: iommu: Add documentation for rockchip iommu (2014-11-03
17:29:09 +0100)
are available in the git repository at:
https://github.com/markyzq/kernel-drm-rockchip.git drm_iommu
for you to fetch changes up to aab18af3a93353bc43897b716fd7e12d5998b9bc:
dt-bindings: video: Add documentation for rockchip vop (2014-11-27
13:38:17 +0800)
----------------------------------------------------------------
Mark Yao (3):
drm: rockchip: Add basic drm driver
dt-bindings: video: Add for rockchip display subsytem
dt-bindings: video: Add documentation for rockchip vop
.../devicetree/bindings/video/rockchip-drm.txt | 19 +
.../devicetree/bindings/video/rockchip-vop.txt | 58 +
drivers/gpu/drm/Kconfig | 2 +
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/rockchip/Kconfig | 17 +
drivers/gpu/drm/rockchip/Makefile | 8 +
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 483 +++++++
drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 55 +
drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 200 +++
drivers/gpu/drm/rockchip/rockchip_drm_fb.h | 28 +
drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c | 210 +++
drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h | 21 +
drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 294 ++++
drivers/gpu/drm/rockchip/rockchip_drm_gem.h | 54 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 1459
++++++++++++++++++++
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 201 +++
16 files changed, 3110 insertions(+)
create mode 100644
Documentation/devicetree/bindings/video/rockchip-drm.txt
create mode 100644
Documentation/devicetree/bindings/video/rockchip-vop.txt
create mode 100644 drivers/gpu/drm/rockchip/Kconfig
create mode 100644 drivers/gpu/drm/rockchip/Makefile
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_drv.c
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_drv.h
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_fb.c
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_fb.h
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_gem.c
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_gem.h
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop.c
create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop.h
^ permalink raw reply
* Re: [PATCH v14 0/3] Add drm driver for Rockchip Socs
From: Mark yao @ 2014-11-27 7:08 UTC (permalink / raw)
To: Dave Airlie
Cc: Joerg Roedel, Heiko Stübner, Boris BREZILLON, Rob Clark,
Daniel Vetter, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Randy Dunlap, Grant Likely,
Greg Kroah-Hartman, John Stultz, Rom Lemarchand,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA, LKML, dri-devel,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Douglas Anderson
In-Reply-To: <CAPM=9tyZpDEPcipYDq2_qdQ9zK2bnPFYTUL2qDvAd7QoUOm-QQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On 2014年11月27日 10:12, Dave Airlie wrote:
>>>
>> Hi Dave
>> Do you mean that I need send you a branch, based on drm-next, merge with
>> iommu tree and rockchip drm?
> Yes, grab drm-next, git pull the arm/rockchip branch from Joerg's
> tree, put rockchip drm
> patches on top, send me pull request.
>
> I'll validate it then.
>
> Dave.
>
Hi Dave
I have send a pull request to you, with Joerg's iommu arm/rockchip
branch.
I got a same problem when use "make multi_v7_defconfig" as Heiko said:
drivers/video/fbdev/Kconfig:5:error: recursive dependency detected!
drivers/video/fbdev/Kconfig:5: symbol FB is selected by
DRM_KMS_FB_HELPER
drivers/gpu/drm/Kconfig:34: symbol DRM_KMS_FB_HELPER is
selected by DRM_ROCKCHIP
drivers/gpu/drm/rockchip/Kconfig:1: symbol DRM_ROCKCHIP
depends on ARM_DMA_USE_IOMMU
arch/arm/Kconfig:95: symbol ARM_DMA_USE_IOMMU is selected by
VIDEO_OMAP3
drivers/media/platform/Kconfig:96: symbol VIDEO_OMAP3
depends on VIDEO_V4L2
drivers/media/v4l2-core/Kconfig:6: symbol VIDEO_V4L2 depends
on I2C
drivers/i2c/Kconfig:7: symbol I2C is selected by FB_DDC
drivers/video/fbdev/Kconfig:59: symbol FB_DDC is selected by
FB_CYBER2000_DDC
drivers/video/fbdev/Kconfig:374: symbol FB_CYBER2000_DDC
depends on FB_CYBER2000
drivers/video/fbdev/Kconfig:362: symbol FB_CYBER2000 depends
on FB
I was confused how to solve the recursive dependency, remove
depends on ARM_DMA_USE_IOMMU & IOMMU_API?
- Mark
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 5/5] tty/serial: Add Spreadtrum sc9836-uart driver support
From: Lyra Zhang @ 2014-11-27 11:05 UTC (permalink / raw)
To: Greg KH
Cc: Chunyan Zhang, Grant Likely, robh+dt@kernel.org, Catalin Marinas,
ijc+devicetree@hellion.org.uk, jslaby@suse.cz, Kumar Gala,
Mark Brown, Mark Rutland, m-karicheri2@ti.com, Pawel Moll,
Ramkumar Ramachandra, rrichter@cavium.com, Will Deacon,
Arnd Bergmann, gnomes, Jonathan Corbet, jason, Mark Brown,
Heiko Stübner, shawn.guo, florian.vaussard, andrew,
Hayato Suzuki
In-Reply-To: <20141125200353.GA7653@kroah.com>
2014-11-26 4:03 GMT+08:00 Greg KH <gregkh@linuxfoundation.org>:
> On Tue, Nov 25, 2014 at 08:16:58PM +0800, Chunyan Zhang wrote:
>> Add a full sc9836-uart driver for SC9836 SoC which is based on the
>> spreadtrum sharkl64 platform.
>> This driver also support earlycon.
>>
>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
>> Signed-off-by: Orson Zhai <orson.zhai@spreadtrum.com>
>> Originally-by: Lanqing Liu <lanqing.liu@spreadtrum.com>
>
> Some objections:
>
>> +static struct platform_driver sprd_platform_driver = {
>> + .probe = sprd_probe,
>> + .remove = sprd_remove,
>> + .suspend = sprd_suspend,
>> + .resume = sprd_resume,
>> + .driver = {
>> + .name = "sprd_serial",
>> + .owner = THIS_MODULE,
>
> platform drivers don't need .owner in them anymore, it's handled by the
> driver core automatically.
>
OK, will remove it in v4.
>
>> + .of_match_table = of_match_ptr(serial_ids),
>> + },
>> +};
>> +
>> +static int __init sprd_serial_init(void)
>> +{
>> + int ret = 0;
>> +
>> + ret = uart_register_driver(&sprd_uart_driver);
>> + if (unlikely(ret != 0))
>> + return ret;
>
> NEVER use unlikely unless you can measure the difference without it.
> And even then, you better be able to justify it. For something as dumb
> as this type of check, youare working against the complier and cpu which
> already knows that 0 is the usual response.
>
> So please remove all usages of likely/unlikely in this patch series.
>
OK, will remove it.
>> +
>> + ret = platform_driver_register(&sprd_platform_driver);
>> + if (unlikely(ret != 0))
>> + uart_unregister_driver(&sprd_uart_driver);
>> +
>> + return ret;
>> +}
>> +
>> +static void __exit sprd_serial_exit(void)
>> +{
>> + platform_driver_unregister(&sprd_platform_driver);
>> + uart_unregister_driver(&sprd_uart_driver);
>> +}
>> +
>> +module_init(sprd_serial_init);
>> +module_exit(sprd_serial_exit);
>> +
>> +MODULE_LICENSE("GPL");
>> +MODULE_DESCRIPTION("Spreadtrum SoC serial driver series");
>> diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
>> index 16ad852..d9a8c88 100644
>> --- a/include/uapi/linux/serial_core.h
>> +++ b/include/uapi/linux/serial_core.h
>> @@ -247,4 +247,7 @@
>> /* MESON */
>> #define PORT_MESON 109
>>
>> +/* SPRD SERIAL */
>> +#define PORT_SPRD 110
>
> Please use a tab character here.
OK.
Thanks for your comments!
Chunyan
^ permalink raw reply
* Re: [PATCH v3 1/5] Documentation: DT: Renamed of-serial.txt to 8250.txt
From: Mark Rutland @ 2014-11-27 11:38 UTC (permalink / raw)
To: Chunyan Zhang
Cc: grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Catalin Marinas,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org,
ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org,
jslaby-AlSwsSmVLrQ@public.gmane.org,
galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org,
broonie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
m-karicheri2-l0cyMroinI0@public.gmane.org, Pawel Moll,
artagnon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
rrichter-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org, Will Deacon,
arnd-r2nGTMty4D4@public.gmane.org,
gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org,
corbet-T1hC0tSOHrs@public.gmane.org,
jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org,
broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org,
"shawn.guo-KZfg59tc24xl57MIdRCFDg@public.gmane.org" <shawn.g>
In-Reply-To: <1416917818-10506-2-git-send-email-chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
On Tue, Nov 25, 2014 at 12:16:54PM +0000, Chunyan Zhang wrote:
> The file of-serial.txt was only for 8250 compatible UART implementations,
> so renamed it to 8250.txt to avoid confusing other persons.
> This is recommended by Arnd, see:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/291455.html
>
> Signed-off-by: Chunyan Zhang <chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
My prior Ack [1] still applies (given you've just changed the way the
patch was generated, as Arnd and I suggested).
Mark.
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2014-October/295152.html
> ---
> .../bindings/serial/{of-serial.txt => 8250.txt} | 0
> 1 file changed, 0 insertions(+), 0 deletions(-)
> rename Documentation/devicetree/bindings/serial/{of-serial.txt => 8250.txt} (100%)
>
> diff --git a/Documentation/devicetree/bindings/serial/of-serial.txt b/Documentation/devicetree/bindings/serial/8250.txt
> similarity index 100%
> rename from Documentation/devicetree/bindings/serial/of-serial.txt
> rename to Documentation/devicetree/bindings/serial/8250.txt
> --
> 1.7.9.5
>
>
^ permalink raw reply
* Re: [PATCH v3 5/5] tty/serial: Add Spreadtrum sc9836-uart driver support
From: Lyra Zhang @ 2014-11-27 11:39 UTC (permalink / raw)
To: Tobias Klauser
Cc: Chunyan Zhang, Grant Likely, robh+dt@kernel.org, Catalin Marinas,
gregkh@linuxfoundation.org, ijc+devicetree@hellion.org.uk,
jslaby@suse.cz, Kumar Gala, Mark Brown, Mark Rutland,
m-karicheri2@ti.com, Pawel Moll, Ramkumar Ramachandra,
rrichter@cavium.com, Will Deacon, Arnd Bergmann, gnomes,
Jonathan Corbet, jason, Mark Brown, Heiko Stübner, shawn.guo
In-Reply-To: <20141126094838.GB17980@distanz.ch>
2014-11-26 17:48 GMT+08:00 Tobias Klauser <tklauser@distanz.ch>:
> On 2014-11-25 at 13:16:58 +0100, Chunyan Zhang <chunyan.zhang@spreadtrum.com> wrote:
>> ---
[...]
>> +
>> +config SERIAL_SPRD_CONSOLE
>> + bool "SPRD UART console support"
>> + depends on SERIAL_SPRD=y
>> + select SERIAL_CORE_CONSOLE
>> + select SERIAL_EARLYCON
>> + help
>> + Support for early debug console using Spreadtrum's serial. This enables
>> + the console before standard serial driver is probed. This is enabled
>> + with "earlycon" on the kernel command line. The console is
>> + enabled when early_param is processed.
>> +
>> endmenu
>
> Please consistently use tabs instead of spaces for indentation. The help
> text should be indented by one tabe + 2 spaces.
>
OK, I will note it later.
[...]
>> +static inline int handle_lsr_errors(struct uart_port *port,
>> + unsigned int *flag, unsigned int *lsr)
>
> This line should be aligned with the opening ( above.
>
OK, will change.
>> +static inline void sprd_rx(int irq, void *dev_id)
>> +{
>> + struct uart_port *port = (struct uart_port *)dev_id;
>
> No need to cast a void pointer.
>
>> +static void sprd_console_write(struct console *co, const char *s,
>> + unsigned int count)
>> +{
>> + struct uart_port *port = (struct uart_port *)sprd_port[co->index];
>
> Better explicitly access the .port member of sprd_port[co->index] here
> instead of casting.
>
>> + port = (struct uart_port *)sprd_port[co->index];
>
> Same here, use the .port member of struct sprd_port[co->index].
>
>> + if (port == NULL) {
>> + pr_info("srial port %d not yet initialized\n", co->index);
>
> Typo: should be serial instead of srial.
>
>> + up->mapbase = mem->start;
>> + up->membase = ioremap(mem->start, resource_size(mem));
>
> Return value of ioremap() should be checked for NULL.
>
>> +static int sprd_resume(struct platform_device *dev)
>> +{
>> + int id = dev->id;
>> + struct uart_port *port = (struct uart_port *)sprd_port[id];
>
> Access the .port member instead of the cast.
>
OK, will change all of the problems you pointed out in v4.
Thanks for your review.
Chunyan
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox