* Re: [Qemu-arm] [PATCH 03/20] target/arm: Prepare for CONTROL.SPSEL being nonzero in Handler mode
From: Philippe Mathieu-Daudé @ 2017-10-05 3:25 UTC (permalink / raw)
To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches
In-Reply-To: <1506092407-26985-4-git-send-email-peter.maydell@linaro.org>
On 09/22/2017 11:59 AM, Peter Maydell wrote:
> In the v7M architecture, there is an invariant that if the CPU is
> in Handler mode then the CONTROL.SPSEL bit cannot be nonzero.
> This in turn means that the current stack pointer is always
> indicated by CONTROL.SPSEL, even though Handler mode always uses
> the Main stack pointer.
>
> In v8M, this invariant is removed, and CONTROL.SPSEL may now
> be nonzero in Handler mode (though Handler mode still always
> uses the Main stack pointer). In preparation for this change,
> change how we handle this bit: rename switch_v7m_sp() to
> the now more accurate write_v7m_control_spsel(), and make it
> check both the handler mode state and the SPSEL bit.
>
> Note that this implicitly changes the point at which we switch
> active SP on exception exit from before we pop the exception
> frame to after it.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> ---
> target/arm/cpu.h | 8 ++++++-
> hw/intc/armv7m_nvic.c | 2 +-
> target/arm/helper.c | 65 ++++++++++++++++++++++++++++++++++-----------------
> 3 files changed, 51 insertions(+), 24 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 8afceca..ad6eff4 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -991,6 +991,11 @@ void pmccntr_sync(CPUARMState *env);
> #define PSTATE_MODE_EL1t 4
> #define PSTATE_MODE_EL0t 0
>
> +/* Write a new value to v7m.exception, thus transitioning into or out
> + * of Handler mode; this may result in a change of active stack pointer.
> + */
> +void write_v7m_exception(CPUARMState *env, uint32_t new_exc);
> +
> /* Map EL and handler into a PSTATE_MODE. */
> static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
> {
> @@ -1071,7 +1076,8 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
> env->condexec_bits |= (val >> 8) & 0xfc;
> }
> if (mask & XPSR_EXCP) {
> - env->v7m.exception = val & XPSR_EXCP;
> + /* Note that this only happens on exception exit */
> + write_v7m_exception(env, val & XPSR_EXCP);
> }
> }
>
> diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
> index bc7b66d..a1041c2 100644
> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -616,7 +616,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
> vec->active = 1;
> vec->pending = 0;
>
> - env->v7m.exception = s->vectpending;
> + write_v7m_exception(env, s->vectpending);
>
> nvic_irq_update(s);
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index f13b99d..509a1aa 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -6052,21 +6052,44 @@ static bool v7m_using_psp(CPUARMState *env)
> env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
> }
>
> -/* Switch to V7M main or process stack pointer. */
> -static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
> +/* Write to v7M CONTROL.SPSEL bit. This may change the current
> + * stack pointer between Main and Process stack pointers.
> + */
> +static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel)
> {
> uint32_t tmp;
> - uint32_t old_control = env->v7m.control[env->v7m.secure];
> - bool old_spsel = old_control & R_V7M_CONTROL_SPSEL_MASK;
> + bool new_is_psp, old_is_psp = v7m_using_psp(env);
> +
> + env->v7m.control[env->v7m.secure] =
> + deposit32(env->v7m.control[env->v7m.secure],
> + R_V7M_CONTROL_SPSEL_SHIFT,
> + R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
> +
> + new_is_psp = v7m_using_psp(env);
>
> - if (old_spsel != new_spsel) {
> + if (old_is_psp != new_is_psp) {
> tmp = env->v7m.other_sp;
> env->v7m.other_sp = env->regs[13];
> env->regs[13] = tmp;
> + }
> +}
> +
> +void write_v7m_exception(CPUARMState *env, uint32_t new_exc)
> +{
> + /* Write a new value to v7m.exception, thus transitioning into or out
> + * of Handler mode; this may result in a change of active stack pointer.
> + */
> + bool new_is_psp, old_is_psp = v7m_using_psp(env);
> + uint32_t tmp;
>
> - env->v7m.control[env->v7m.secure] = deposit32(old_control,
> - R_V7M_CONTROL_SPSEL_SHIFT,
> - R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
> + env->v7m.exception = new_exc;
> +
> + new_is_psp = v7m_using_psp(env);
> +
> + if (old_is_psp != new_is_psp) {
> + tmp = env->v7m.other_sp;
> + env->v7m.other_sp = env->regs[13];
> + env->regs[13] = tmp;
> }
> }
>
> @@ -6149,13 +6172,11 @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
> bool want_psp = threadmode && spsel;
>
> if (secure == env->v7m.secure) {
> - /* Currently switch_v7m_sp switches SP as it updates SPSEL,
> - * so the SP we want is always in regs[13].
> - * When we decouple SPSEL from the actually selected SP
> - * we need to check want_psp against v7m_using_psp()
> - * to see whether we need regs[13] or v7m.other_sp.
> - */
> - return &env->regs[13];
> + if (want_psp == v7m_using_psp(env)) {
> + return &env->regs[13];
> + } else {
> + return &env->v7m.other_sp;
> + }
> } else {
> if (want_psp) {
> return &env->v7m.other_ss_psp;
> @@ -6198,7 +6219,7 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
> uint32_t addr;
>
> armv7m_nvic_acknowledge_irq(env->nvic);
> - switch_v7m_sp(env, 0);
> + write_v7m_control_spsel(env, 0);
> arm_clear_exclusive(env);
> /* Clear IT bits */
> env->condexec_bits = 0;
> @@ -6344,11 +6365,11 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
> return;
> }
>
> - /* Set CONTROL.SPSEL from excret.SPSEL. For QEMU this currently
> - * causes us to switch the active SP, but we will change this
> - * later to not do that so we can support v8M.
> + /* Set CONTROL.SPSEL from excret.SPSEL. Since we're still in
> + * Handler mode (and will be until we write the new XPSR.Interrupt
> + * field) this does not switch around the current stack pointer.
> */
> - switch_v7m_sp(env, return_to_sp_process);
> + write_v7m_control_spsel(env, return_to_sp_process);
>
> {
> /* The stack pointer we should be reading the exception frame from
> @@ -9163,11 +9184,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
> case 20: /* CONTROL */
> /* Writing to the SPSEL bit only has an effect if we are in
> * thread mode; other bits can be updated by any privileged code.
> - * switch_v7m_sp() deals with updating the SPSEL bit in
> + * write_v7m_control_spsel() deals with updating the SPSEL bit in
> * env->v7m.control, so we only need update the others.
> */
> if (!arm_v7m_is_handler_mode(env)) {
> - switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
> + write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
> }
> env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
> env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
>
^ permalink raw reply
* Re: [Outreachy kernel] [PATCH] nftables: Change size_t len to size_t size
From: Meghana Madhyastha @ 2017-10-05 3:25 UTC (permalink / raw)
To: Julia Lawall, pablo, outreachy-kernel
In-Reply-To: <alpine.DEB.2.20.1710042213520.2358@hadrien>
On Wed, Oct 04, 2017 at 10:15:00PM +0200, Julia Lawall wrote:
>
>
> On Wed, 4 Oct 2017, Meghana Madhyastha wrote:
>
> > Change the variable name from size_t len to
> > size_t size in the sprintf functions for
> > consistency.
>
> It looks like a lot of changes. Is size_t size already used in a lot of
> other places?
size_t size is used in most of the other places (in more places than size_t
len in other parts of the codebase) so Pablo had asked me to convert size_t
len to size_t size.
Regards,
Meghana
> Try to make log messages the use more of the horizontal space.
>
> julia
>
> >
> > Signed-off-by: Meghana Madhyastha <meghana.madhyastha@gmail.com>
> > ---
> > src/expr/counter.c | 12 ++++++------
> > src/expr/ct.c | 8 ++++----
> > src/expr/dup.c | 16 ++++++++--------
> > src/expr/exthdr.c | 14 +++++++-------
> > src/expr/fib.c | 8 ++++----
> > src/expr/fwd.c | 12 ++++++------
> > src/expr/hash.c | 8 ++++----
> > src/expr/immediate.c | 12 ++++++------
> > src/expr/limit.c | 12 ++++++------
> > src/expr/log.c | 8 ++++----
> > src/expr/masq.c | 14 +++++++-------
> > src/expr/match.c | 8 ++++----
> > src/expr/meta.c | 14 +++++++-------
> > src/expr/numgen.c | 8 ++++----
> > src/expr/objref.c | 14 +++++++-------
> > src/expr/payload.c | 10 +++++-----
> > src/expr/queue.c | 24 ++++++++++++------------
> > src/expr/quota.c | 12 ++++++------
> > src/expr/redir.c | 18 +++++++++---------
> > src/expr/reject.c | 12 ++++++------
> > src/expr/rt.c | 12 ++++++------
> > src/expr/target.c | 8 ++++----
> > 22 files changed, 132 insertions(+), 132 deletions(-)
> >
> > diff --git a/src/expr/counter.c b/src/expr/counter.c
> > index 5c196d4..4de6b92 100644
> > --- a/src/expr/counter.c
> > +++ b/src/expr/counter.c
> > @@ -151,28 +151,28 @@ static int nftnl_expr_counter_export(char *buf, size_t size,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_counter_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_counter_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_counter *ctr = nftnl_expr_data(e);
> >
> > - return snprintf(buf, len, "pkts %"PRIu64" bytes %"PRIu64" ",
> > + return snprintf(buf, size, "pkts %"PRIu64" bytes %"PRIu64" ",
> > ctr->pkts, ctr->bytes);
> > }
> >
> > -static int nftnl_expr_counter_snprintf(char *buf, size_t len, uint32_t type,
> > +static int nftnl_expr_counter_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags,
> > const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_counter_snprintf_default(buf, len, e);
> > + return nftnl_expr_counter_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_counter_export(buf, len, e, type);
> > + return nftnl_expr_counter_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/ct.c b/src/expr/ct.c
> > index 021a277..396bee0 100644
> > --- a/src/expr/ct.c
> > +++ b/src/expr/ct.c
> > @@ -314,18 +314,18 @@ nftnl_expr_ct_snprintf_default(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_ct_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_ct_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_ct_snprintf_default(buf, len, e);
> > + return nftnl_expr_ct_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_ct_export(buf, len, e, type);
> > + return nftnl_expr_ct_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/dup.c b/src/expr/dup.c
> > index e2171f4..f67331b 100644
> > --- a/src/expr/dup.c
> > +++ b/src/expr/dup.c
> > @@ -147,38 +147,38 @@ static int nftnl_expr_dup_export(char *buf, size_t size,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_dup_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_dup_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e,
> > uint32_t flags)
> > {
> > - int remain = len, offset = 0, ret;
> > + int remain = size, offset = 0, ret;
> > struct nftnl_expr_dup *dup = nftnl_expr_data(e);
> >
> > if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_ADDR)) {
> > - ret = snprintf(buf + offset, len, "sreg_addr %u ", dup->sreg_addr);
> > + ret = snprintf(buf + offset, size, "sreg_addr %u ", dup->sreg_addr);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> >
> > if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_DEV)) {
> > - ret = snprintf(buf + offset, len, "sreg_dev %u ", dup->sreg_dev);
> > + ret = snprintf(buf + offset, size, "sreg_dev %u ", dup->sreg_dev);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> >
> > return offset;
> > }
> >
> > -static int nftnl_expr_dup_snprintf(char *buf, size_t len, uint32_t type,
> > +static int nftnl_expr_dup_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_dup_snprintf_default(buf, len, e, flags);
> > + return nftnl_expr_dup_snprintf_default(buf, size, e, flags);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_dup_export(buf, len, e, type);
> > + return nftnl_expr_dup_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c
> > index 11766fa..12f49d8 100644
> > --- a/src/expr/exthdr.c
> > +++ b/src/expr/exthdr.c
> > @@ -317,37 +317,37 @@ static int nftnl_expr_exthdr_export(char *buf, size_t len,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_exthdr_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_exthdr_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e);
> >
> > if (e->flags & (1 << NFTNL_EXPR_EXTHDR_DREG))
> > - return snprintf(buf, len, "load%s %ub @ %u + %u%s => reg %u ",
> > + return snprintf(buf, size, "load%s %ub @ %u + %u%s => reg %u ",
> > op2str(exthdr->op), exthdr->len, exthdr->type,
> > exthdr->offset,
> > exthdr->flags & NFT_EXTHDR_F_PRESENT ? " present" : "",
> > exthdr->dreg);
> > else
> > - return snprintf(buf, len, "write%s reg %u => %ub @ %u + %u ",
> > + return snprintf(buf, size, "write%s reg %u => %ub @ %u + %u ",
> > op2str(exthdr->op), exthdr->sreg, exthdr->len, exthdr->type,
> > exthdr->offset);
> >
> > }
> >
> > static int
> > -nftnl_expr_exthdr_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_exthdr_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_exthdr_snprintf_default(buf, len, e);
> > + return nftnl_expr_exthdr_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_exthdr_export(buf, len, e, type);
> > + return nftnl_expr_exthdr_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/fib.c b/src/expr/fib.c
> > index cbadeef..cb62020 100644
> > --- a/src/expr/fib.c
> > +++ b/src/expr/fib.c
> > @@ -233,18 +233,18 @@ static int nftnl_expr_fib_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_fib_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_fib_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_fib_snprintf_default(buf, len, e);
> > + return nftnl_expr_fib_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_fib_export(buf, len, e, type);
> > + return nftnl_expr_fib_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/fwd.c b/src/expr/fwd.c
> > index 38923df..9b5e555 100644
> > --- a/src/expr/fwd.c
> > +++ b/src/expr/fwd.c
> > @@ -128,11 +128,11 @@ static int nftnl_expr_fwd_export(char *buf, size_t size,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_fwd_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_fwd_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e,
> > uint32_t flags)
> > {
> > - int remain = len, offset = 0, ret;
> > + int remain = size, offset = 0, ret;
> > struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
> >
> > if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV)) {
> > @@ -144,18 +144,18 @@ static int nftnl_expr_fwd_snprintf_default(char *buf, size_t len,
> > return offset;
> > }
> >
> > -static int nftnl_expr_fwd_snprintf(char *buf, size_t len, uint32_t type,
> > +static int nftnl_expr_fwd_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_fwd_snprintf_default(buf, len, e, flags);
> > + return nftnl_expr_fwd_snprintf_default(buf, size, e, flags);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_fwd_export(buf, len, e, type);
> > + return nftnl_expr_fwd_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/hash.c b/src/expr/hash.c
> > index 066c790..6a52308 100644
> > --- a/src/expr/hash.c
> > +++ b/src/expr/hash.c
> > @@ -285,18 +285,18 @@ static int nftnl_expr_hash_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_hash_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_hash_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_hash_snprintf_default(buf, len, e);
> > + return nftnl_expr_hash_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_hash_export(buf, len, e, type);
> > + return nftnl_expr_hash_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/immediate.c b/src/expr/immediate.c
> > index aba84ea..5cdad03 100644
> > --- a/src/expr/immediate.c
> > +++ b/src/expr/immediate.c
> > @@ -229,11 +229,11 @@ nftnl_expr_immediate_export(char *buf, size_t size, const struct nftnl_expr *e,
> > }
> >
> > static int
> > -nftnl_expr_immediate_snprintf_default(char *buf, size_t len,
> > +nftnl_expr_immediate_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e,
> > uint32_t flags)
> > {
> > - int remain = len, offset = 0, ret;
> > + int remain = size, offset = 0, ret;
> > struct nftnl_expr_immediate *imm = nftnl_expr_data(e);
> >
> > ret = snprintf(buf, remain, "reg %u ", imm->dreg);
> > @@ -259,18 +259,18 @@ nftnl_expr_immediate_snprintf_default(char *buf, size_t len,
> > }
> >
> > static int
> > -nftnl_expr_immediate_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_immediate_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch(type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_immediate_snprintf_default(buf, len, e, flags);
> > + return nftnl_expr_immediate_snprintf_default(buf, size, e, flags);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_immediate_export(buf, len, e, type);
> > + return nftnl_expr_immediate_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/limit.c b/src/expr/limit.c
> > index 8e1f02a..3927dbf 100644
> > --- a/src/expr/limit.c
> > +++ b/src/expr/limit.c
> > @@ -229,29 +229,29 @@ static const char *limit_to_type(enum nft_limit_type type)
> > }
> > }
> >
> > -static int nftnl_expr_limit_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_limit_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_limit *limit = nftnl_expr_data(e);
> >
> > - return snprintf(buf, len, "rate %"PRIu64"/%s burst %u type %s flags 0x%x ",
> > + return snprintf(buf, size, "rate %"PRIu64"/%s burst %u type %s flags 0x%x ",
> > limit->rate, get_unit(limit->unit), limit->burst,
> > limit_to_type(limit->type), limit->flags);
> > }
> >
> > static int
> > -nftnl_expr_limit_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_limit_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch(type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_limit_snprintf_default(buf, len, e);
> > + return nftnl_expr_limit_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_limit_export(buf, len, e, type);
> > + return nftnl_expr_limit_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/log.c b/src/expr/log.c
> > index 161327b..48abc9c 100644
> > --- a/src/expr/log.c
> > +++ b/src/expr/log.c
> > @@ -298,18 +298,18 @@ static int nftnl_expr_log_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_log_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_log_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch(type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_log_snprintf_default(buf, len, e);
> > + return nftnl_expr_log_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_log_export(buf, len, e, type);
> > + return nftnl_expr_log_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/masq.c b/src/expr/masq.c
> > index 1c75ee9..76d3eea 100644
> > --- a/src/expr/masq.c
> > +++ b/src/expr/masq.c
> > @@ -171,15 +171,15 @@ static int nftnl_expr_masq_export(char *buf, size_t size,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_masq_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_masq_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_masq *masq = nftnl_expr_data(e);
> >
> > if (e->flags & (1 << NFTNL_EXPR_MASQ_FLAGS))
> > - return snprintf(buf, len, "flags 0x%x ", masq->flags);
> > + return snprintf(buf, size, "flags 0x%x ", masq->flags);
> > if (e->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MIN)) {
> > - return snprintf(buf, len,
> > + return snprintf(buf, size,
> > "proto_min reg %u proto_max reg %u ",
> > masq->sreg_proto_min, masq->sreg_proto_max);
> > }
> > @@ -187,18 +187,18 @@ static int nftnl_expr_masq_snprintf_default(char *buf, size_t len,
> > return 0;
> > }
> >
> > -static int nftnl_expr_masq_snprintf(char *buf, size_t len, uint32_t type,
> > +static int nftnl_expr_masq_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_masq_snprintf_default(buf, len, e);
> > + return nftnl_expr_masq_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_masq_export(buf, len, e, type);
> > + return nftnl_expr_masq_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/match.c b/src/expr/match.c
> > index af659b3..431c339 100644
> > --- a/src/expr/match.c
> > +++ b/src/expr/match.c
> > @@ -195,21 +195,21 @@ static int nftnl_expr_match_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_match_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_match_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_match *match = nftnl_expr_data(e);
> >
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return snprintf(buf, len, "name %s rev %u ",
> > + return snprintf(buf, size, "name %s rev %u ",
> > match->name, match->rev);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_match_export(buf, len, e, type);
> > + return nftnl_expr_match_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/meta.c b/src/expr/meta.c
> > index b5c27e6..95e84ad 100644
> > --- a/src/expr/meta.c
> > +++ b/src/expr/meta.c
> > @@ -216,17 +216,17 @@ static int nftnl_expr_meta_json_parse(struct nftnl_expr *e, json_t *root,
> > }
> >
> > static int
> > -nftnl_expr_meta_snprintf_default(char *buf, size_t len,
> > +nftnl_expr_meta_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_meta *meta = nftnl_expr_data(e);
> >
> > if (e->flags & (1 << NFTNL_EXPR_META_SREG)) {
> > - return snprintf(buf, len, "set %s with reg %u ",
> > + return snprintf(buf, size, "set %s with reg %u ",
> > meta_key2str(meta->key), meta->sreg);
> > }
> > if (e->flags & (1 << NFTNL_EXPR_META_DREG)) {
> > - return snprintf(buf, len, "load %s => reg %u ",
> > + return snprintf(buf, size, "load %s => reg %u ",
> > meta_key2str(meta->key), meta->dreg);
> > }
> > return 0;
> > @@ -249,18 +249,18 @@ static int nftnl_expr_meta_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_meta_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_meta_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_meta_snprintf_default(buf, len, e);
> > + return nftnl_expr_meta_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_meta_export(buf, len, e, type);
> > + return nftnl_expr_meta_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/numgen.c b/src/expr/numgen.c
> > index 9b5b1b7..83c493a 100644
> > --- a/src/expr/numgen.c
> > +++ b/src/expr/numgen.c
> > @@ -221,18 +221,18 @@ static int nftnl_expr_ng_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_ng_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_ng_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_ng_snprintf_default(buf, len, e);
> > + return nftnl_expr_ng_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_ng_export(buf, len, e, type);
> > + return nftnl_expr_ng_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/objref.c b/src/expr/objref.c
> > index b4b3383..340dc67 100644
> > --- a/src/expr/objref.c
> > +++ b/src/expr/objref.c
> > @@ -219,32 +219,32 @@ static int nftnl_expr_objref_export(char *buf, size_t size,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_objref_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_objref_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_objref *objref = nftnl_expr_data(e);
> >
> > if (e->flags & (1 << NFTNL_EXPR_OBJREF_SET_SREG))
> > - return snprintf(buf, len, "sreg %u set %s id %u ",
> > + return snprintf(buf, size, "sreg %u set %s id %u ",
> > objref->set.sreg, objref->set.name, objref->set.id);
> > else
> > - return snprintf(buf, len, "type %u name %s ",
> > + return snprintf(buf, size, "type %u name %s ",
> > objref->imm.type, objref->imm.name);
> > }
> >
> > -static int nftnl_expr_objref_snprintf(char *buf, size_t len, uint32_t type,
> > +static int nftnl_expr_objref_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags,
> > const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_objref_snprintf_default(buf, len, e);
> > + return nftnl_expr_objref_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_objref_export(buf, len, e, type);
> > + return nftnl_expr_objref_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/payload.c b/src/expr/payload.c
> > index 897fc77..d61e854 100644
> > --- a/src/expr/payload.c
> > +++ b/src/expr/payload.c
> > @@ -285,30 +285,30 @@ static int nftnl_expr_payload_export(char *buf, size_t size, uint32_t flags,
> > }
> >
> > static int
> > -nftnl_expr_payload_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_payload_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_payload *payload = nftnl_expr_data(e);
> >
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > if (payload->sreg)
> > - return snprintf(buf, len, "write reg %u => %ub @ %s header + %u csum_type %u csum_off %u csum_flags 0x%x ",
> > + return snprintf(buf, size, "write reg %u => %ub @ %s header + %u csum_type %u csum_off %u csum_flags 0x%x ",
> > payload->sreg,
> > payload->len, base2str(payload->base),
> > payload->offset, payload->csum_type,
> > payload->csum_offset,
> > payload->csum_flags);
> > else
> > - return snprintf(buf, len, "load %ub @ %s header + %u => reg %u ",
> > + return snprintf(buf, size, "load %ub @ %s header + %u => reg %u ",
> > payload->len, base2str(payload->base),
> > payload->offset, payload->dreg);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_payload_export(buf, len, flags, e, type);
> > + return nftnl_expr_payload_export(buf, size, flags, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/queue.c b/src/expr/queue.c
> > index e0fb785..acb42e9 100644
> > --- a/src/expr/queue.c
> > +++ b/src/expr/queue.c
> > @@ -172,41 +172,41 @@ nftnl_expr_queue_json_parse(struct nftnl_expr *e, json_t *root,
> > #endif
> > }
> >
> > -static int nftnl_expr_queue_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_queue_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_queue *queue = nftnl_expr_data(e);
> > - int ret, remain = len, offset = 0;
> > + int ret, remain = size, offset = 0;
> > uint16_t total_queues;
> >
> > if (e->flags & (1 << NFTNL_EXPR_QUEUE_NUM)) {
> > total_queues = queue->queuenum + queue->queues_total - 1;
> >
> > - ret = snprintf(buf + offset, len, "num %u", queue->queuenum);
> > + ret = snprintf(buf + offset, size, "num %u", queue->queuenum);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> >
> > if (queue->queues_total && total_queues != queue->queuenum) {
> > - ret = snprintf(buf + offset, len, "-%u", total_queues);
> > + ret = snprintf(buf + offset, size, "-%u", total_queues);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> >
> > - ret = snprintf(buf + offset, len, " ");
> > + ret = snprintf(buf + offset, size, " ");
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> >
> > if (e->flags & (1 << NFTNL_EXPR_QUEUE_SREG_QNUM)) {
> > - ret = snprintf(buf + offset, len, "sreg_qnum %u ",
> > + ret = snprintf(buf + offset, size, "sreg_qnum %u ",
> > queue->sreg_qnum);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> >
> > if (e->flags & (1 << NFTNL_EXPR_QUEUE_FLAGS)) {
> > if (queue->flags & (NFT_QUEUE_FLAG_BYPASS)) {
> > - ret = snprintf(buf + offset, len, "bypass ");
> > + ret = snprintf(buf + offset, size, "bypass ");
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> > if (queue->flags & (NFT_QUEUE_FLAG_CPU_FANOUT)) {
> > - ret = snprintf(buf + offset, len, "fanout ");
> > + ret = snprintf(buf + offset, size, "fanout ");
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> > }
> > @@ -232,18 +232,18 @@ static int nftnl_expr_queue_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_queue_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_queue_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_queue_snprintf_default(buf, len, e);
> > + return nftnl_expr_queue_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_queue_export(buf, len, e, type);
> > + return nftnl_expr_queue_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/quota.c b/src/expr/quota.c
> > index c247b0a..e9cc708 100644
> > --- a/src/expr/quota.c
> > +++ b/src/expr/quota.c
> > @@ -169,29 +169,29 @@ static int nftnl_expr_quota_export(char *buf, size_t size,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_quota_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_quota_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_quota *quota = nftnl_expr_data(e);
> >
> > - return snprintf(buf, len,
> > + return snprintf(buf, size,
> > "bytes %"PRIu64" consumed %"PRIu64" flags %u ",
> > quota->bytes, quota->consumed, quota->flags);
> > }
> >
> > -static int nftnl_expr_quota_snprintf(char *buf, size_t len, uint32_t type,
> > +static int nftnl_expr_quota_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags,
> > const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_quota_snprintf_default(buf, len, e);
> > + return nftnl_expr_quota_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_quota_export(buf, len, e, type);
> > + return nftnl_expr_quota_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/redir.c b/src/expr/redir.c
> > index 9fb634a..b58635c 100644
> > --- a/src/expr/redir.c
> > +++ b/src/expr/redir.c
> > @@ -173,26 +173,26 @@ static int nftnl_expr_redir_export(char *buf, size_t size,
> > return nftnl_buf_done(&b);
> > }
> >
> > -static int nftnl_expr_redir_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_redir_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > - int ret, remain = len, offset = 0;
> > + int ret, remain = size, offset = 0;
> > struct nftnl_expr_redir *redir = nftnl_expr_data(e);
> >
> > if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_REG_PROTO_MIN)) {
> > - ret = snprintf(buf + offset, len, "proto_min reg %u ",
> > + ret = snprintf(buf + offset, size, "proto_min reg %u ",
> > redir->sreg_proto_min);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> >
> > if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_REG_PROTO_MAX)) {
> > - ret = snprintf(buf + offset, len, "proto_max reg %u ",
> > + ret = snprintf(buf + offset, size, "proto_max reg %u ",
> > redir->sreg_proto_max);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> >
> > if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_FLAGS)) {
> > - ret = snprintf(buf + offset, len, "flags 0x%x ",
> > + ret = snprintf(buf + offset, size, "flags 0x%x ",
> > redir->flags);
> > SNPRINTF_BUFFER_SIZE(ret, remain, offset);
> > }
> > @@ -201,18 +201,18 @@ static int nftnl_expr_redir_snprintf_default(char *buf, size_t len,
> > }
> >
> > static int
> > -nftnl_expr_redir_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_redir_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_redir_snprintf_default(buf, len, e);
> > + return nftnl_expr_redir_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_redir_export(buf, len, e, type);
> > + return nftnl_expr_redir_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/reject.c b/src/expr/reject.c
> > index 1e6fdf5..01bafb4 100644
> > --- a/src/expr/reject.c
> > +++ b/src/expr/reject.c
> > @@ -137,12 +137,12 @@ nftnl_expr_reject_json_parse(struct nftnl_expr *e, json_t *root,
> > #endif
> > }
> >
> > -static int nftnl_expr_reject_snprintf_default(char *buf, size_t len,
> > +static int nftnl_expr_reject_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_reject *reject = nftnl_expr_data(e);
> >
> > - return snprintf(buf, len, "type %u code %u ",
> > + return snprintf(buf, size, "type %u code %u ",
> > reject->type, reject->icmp_code);
> > }
> >
> > @@ -161,18 +161,18 @@ static int nftnl_expr_reject_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_reject_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_reject_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_reject_snprintf_default(buf, len, e);
> > + return nftnl_expr_reject_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_reject_export(buf, len, e, type);
> > + return nftnl_expr_reject_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/rt.c b/src/expr/rt.c
> > index 10cb1e2..408b9a9 100644
> > --- a/src/expr/rt.c
> > +++ b/src/expr/rt.c
> > @@ -173,13 +173,13 @@ static int nftnl_expr_rt_json_parse(struct nftnl_expr *e, json_t *root,
> > }
> >
> > static int
> > -nftnl_expr_rt_snprintf_default(char *buf, size_t len,
> > +nftnl_expr_rt_snprintf_default(char *buf, size_t size,
> > const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_rt *rt = nftnl_expr_data(e);
> >
> > if (e->flags & (1 << NFTNL_EXPR_RT_DREG)) {
> > - return snprintf(buf, len, "load %s => reg %u ",
> > + return snprintf(buf, size, "load %s => reg %u ",
> > rt_key2str(rt->key), rt->dreg);
> > }
> > return 0;
> > @@ -200,18 +200,18 @@ static int nftnl_expr_rt_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_rt_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_rt_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return nftnl_expr_rt_snprintf_default(buf, len, e);
> > + return nftnl_expr_rt_snprintf_default(buf, size, e);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_expr_rt_export(buf, len, e, type);
> > + return nftnl_expr_rt_export(buf, size, e, type);
> > default:
> > break;
> > }
> > diff --git a/src/expr/target.c b/src/expr/target.c
> > index 3c58b03..524b378 100644
> > --- a/src/expr/target.c
> > +++ b/src/expr/target.c
> > @@ -195,21 +195,21 @@ static int nftnl_rule_exp_target_export(char *buf, size_t size,
> > }
> >
> > static int
> > -nftnl_expr_target_snprintf(char *buf, size_t len, uint32_t type,
> > +nftnl_expr_target_snprintf(char *buf, size_t size, uint32_t type,
> > uint32_t flags, const struct nftnl_expr *e)
> > {
> > struct nftnl_expr_target *target = nftnl_expr_data(e);
> >
> > - if (len)
> > + if (size)
> > buf[0] = '\0';
> >
> > switch (type) {
> > case NFTNL_OUTPUT_DEFAULT:
> > - return snprintf(buf, len, "name %s rev %u ",
> > + return snprintf(buf, size, "name %s rev %u ",
> > target->name, target->rev);
> > case NFTNL_OUTPUT_XML:
> > case NFTNL_OUTPUT_JSON:
> > - return nftnl_rule_exp_target_export(buf, len, e, type);
> > + return nftnl_rule_exp_target_export(buf, size, e, type);
> > default:
> > break;
> > }
> > --
> > 2.7.4
> >
> > --
> > You received this message because you are subscribed to the Google Groups "outreachy-kernel" group.
> > To unsubscribe from this group and stop receiving emails from it, send an email to outreachy-kernel+unsubscribe@googlegroups.com.
> > To post to this group, send email to outreachy-kernel@googlegroups.com.
> > To view this discussion on the web visit https://groups.google.com/d/msgid/outreachy-kernel/20171004182138.GA24970%40meghana-HP-Pavilion-Notebook.
> > For more options, visit https://groups.google.com/d/optout.
> >
^ permalink raw reply
* Re: [Qemu-devel] [Qemu-arm] [PATCH 03/20] target/arm: Prepare for CONTROL.SPSEL being nonzero in Handler mode
From: Philippe Mathieu-Daudé @ 2017-10-05 3:25 UTC (permalink / raw)
To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches
In-Reply-To: <1506092407-26985-4-git-send-email-peter.maydell@linaro.org>
On 09/22/2017 11:59 AM, Peter Maydell wrote:
> In the v7M architecture, there is an invariant that if the CPU is
> in Handler mode then the CONTROL.SPSEL bit cannot be nonzero.
> This in turn means that the current stack pointer is always
> indicated by CONTROL.SPSEL, even though Handler mode always uses
> the Main stack pointer.
>
> In v8M, this invariant is removed, and CONTROL.SPSEL may now
> be nonzero in Handler mode (though Handler mode still always
> uses the Main stack pointer). In preparation for this change,
> change how we handle this bit: rename switch_v7m_sp() to
> the now more accurate write_v7m_control_spsel(), and make it
> check both the handler mode state and the SPSEL bit.
>
> Note that this implicitly changes the point at which we switch
> active SP on exception exit from before we pop the exception
> frame to after it.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> ---
> target/arm/cpu.h | 8 ++++++-
> hw/intc/armv7m_nvic.c | 2 +-
> target/arm/helper.c | 65 ++++++++++++++++++++++++++++++++++-----------------
> 3 files changed, 51 insertions(+), 24 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 8afceca..ad6eff4 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -991,6 +991,11 @@ void pmccntr_sync(CPUARMState *env);
> #define PSTATE_MODE_EL1t 4
> #define PSTATE_MODE_EL0t 0
>
> +/* Write a new value to v7m.exception, thus transitioning into or out
> + * of Handler mode; this may result in a change of active stack pointer.
> + */
> +void write_v7m_exception(CPUARMState *env, uint32_t new_exc);
> +
> /* Map EL and handler into a PSTATE_MODE. */
> static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
> {
> @@ -1071,7 +1076,8 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
> env->condexec_bits |= (val >> 8) & 0xfc;
> }
> if (mask & XPSR_EXCP) {
> - env->v7m.exception = val & XPSR_EXCP;
> + /* Note that this only happens on exception exit */
> + write_v7m_exception(env, val & XPSR_EXCP);
> }
> }
>
> diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
> index bc7b66d..a1041c2 100644
> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -616,7 +616,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
> vec->active = 1;
> vec->pending = 0;
>
> - env->v7m.exception = s->vectpending;
> + write_v7m_exception(env, s->vectpending);
>
> nvic_irq_update(s);
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index f13b99d..509a1aa 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -6052,21 +6052,44 @@ static bool v7m_using_psp(CPUARMState *env)
> env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
> }
>
> -/* Switch to V7M main or process stack pointer. */
> -static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
> +/* Write to v7M CONTROL.SPSEL bit. This may change the current
> + * stack pointer between Main and Process stack pointers.
> + */
> +static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel)
> {
> uint32_t tmp;
> - uint32_t old_control = env->v7m.control[env->v7m.secure];
> - bool old_spsel = old_control & R_V7M_CONTROL_SPSEL_MASK;
> + bool new_is_psp, old_is_psp = v7m_using_psp(env);
> +
> + env->v7m.control[env->v7m.secure] =
> + deposit32(env->v7m.control[env->v7m.secure],
> + R_V7M_CONTROL_SPSEL_SHIFT,
> + R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
> +
> + new_is_psp = v7m_using_psp(env);
>
> - if (old_spsel != new_spsel) {
> + if (old_is_psp != new_is_psp) {
> tmp = env->v7m.other_sp;
> env->v7m.other_sp = env->regs[13];
> env->regs[13] = tmp;
> + }
> +}
> +
> +void write_v7m_exception(CPUARMState *env, uint32_t new_exc)
> +{
> + /* Write a new value to v7m.exception, thus transitioning into or out
> + * of Handler mode; this may result in a change of active stack pointer.
> + */
> + bool new_is_psp, old_is_psp = v7m_using_psp(env);
> + uint32_t tmp;
>
> - env->v7m.control[env->v7m.secure] = deposit32(old_control,
> - R_V7M_CONTROL_SPSEL_SHIFT,
> - R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
> + env->v7m.exception = new_exc;
> +
> + new_is_psp = v7m_using_psp(env);
> +
> + if (old_is_psp != new_is_psp) {
> + tmp = env->v7m.other_sp;
> + env->v7m.other_sp = env->regs[13];
> + env->regs[13] = tmp;
> }
> }
>
> @@ -6149,13 +6172,11 @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
> bool want_psp = threadmode && spsel;
>
> if (secure == env->v7m.secure) {
> - /* Currently switch_v7m_sp switches SP as it updates SPSEL,
> - * so the SP we want is always in regs[13].
> - * When we decouple SPSEL from the actually selected SP
> - * we need to check want_psp against v7m_using_psp()
> - * to see whether we need regs[13] or v7m.other_sp.
> - */
> - return &env->regs[13];
> + if (want_psp == v7m_using_psp(env)) {
> + return &env->regs[13];
> + } else {
> + return &env->v7m.other_sp;
> + }
> } else {
> if (want_psp) {
> return &env->v7m.other_ss_psp;
> @@ -6198,7 +6219,7 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
> uint32_t addr;
>
> armv7m_nvic_acknowledge_irq(env->nvic);
> - switch_v7m_sp(env, 0);
> + write_v7m_control_spsel(env, 0);
> arm_clear_exclusive(env);
> /* Clear IT bits */
> env->condexec_bits = 0;
> @@ -6344,11 +6365,11 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
> return;
> }
>
> - /* Set CONTROL.SPSEL from excret.SPSEL. For QEMU this currently
> - * causes us to switch the active SP, but we will change this
> - * later to not do that so we can support v8M.
> + /* Set CONTROL.SPSEL from excret.SPSEL. Since we're still in
> + * Handler mode (and will be until we write the new XPSR.Interrupt
> + * field) this does not switch around the current stack pointer.
> */
> - switch_v7m_sp(env, return_to_sp_process);
> + write_v7m_control_spsel(env, return_to_sp_process);
>
> {
> /* The stack pointer we should be reading the exception frame from
> @@ -9163,11 +9184,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
> case 20: /* CONTROL */
> /* Writing to the SPSEL bit only has an effect if we are in
> * thread mode; other bits can be updated by any privileged code.
> - * switch_v7m_sp() deals with updating the SPSEL bit in
> + * write_v7m_control_spsel() deals with updating the SPSEL bit in
> * env->v7m.control, so we only need update the others.
> */
> if (!arm_v7m_is_handler_mode(env)) {
> - switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
> + write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
> }
> env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
> env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
>
^ permalink raw reply
* Re: [PATCH 6/6] drm: Add four ioctls for managing drm mode object leases [v3]
From: Dave Airlie @ 2017-10-05 3:24 UTC (permalink / raw)
To: Keith Packard; +Cc: LKML, Dave Airlie, Daniel Vetter, dri-devel
In-Reply-To: <CAPM=9txb8p0McchfwMc3Z+-OSqEJvgd32sAmmV_x+xmiYpJ2Og@mail.gmail.com>
On 5 October 2017 at 13:17, Dave Airlie <airlied@gmail.com> wrote:
>> ---
>> drivers/gpu/drm/drm_ioctl.c | 4 +
>> drivers/gpu/drm/drm_lease.c | 270 ++++++++++++++++++++++++++++++++++++++++++++
>> include/drm/drm_lease.h | 12 ++
>> include/uapi/drm/drm.h | 5 +
>> include/uapi/drm/drm_mode.h | 64 +++++++++++
>> 5 files changed, 355 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
>> index a5a259964c7d..0a43e82d3f06 100644
>> --- a/drivers/gpu/drm/drm_ioctl.c
>> +++ b/drivers/gpu/drm/drm_ioctl.c
>> @@ -657,6 +657,10 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
>> DRM_UNLOCKED|DRM_RENDER_ALLOW),
>> DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl,
>> DRM_UNLOCKED|DRM_RENDER_ALLOW),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> };
>>
>> #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
>> diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
>> index a8bd4bdd2977..f233d8b488f2 100644
>> --- a/drivers/gpu/drm/drm_lease.c
>> +++ b/drivers/gpu/drm/drm_lease.c
>> @@ -23,6 +23,8 @@
>> #define drm_for_each_lessee(lessee, lessor) \
>> list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
>>
>> +static uint64_t drm_lease_idr_object;
>
> What is this for? ^^
>
>> + ret = idr_alloc(&leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
>
> You can just pass NULL here.
>
Just read the comment, this smells a bit of black magic, I'll spend
some time staring at it :-)
Dave.
^ permalink raw reply
* Re: [PATCH 6/6] drm: Add four ioctls for managing drm mode object leases [v3]
From: Dave Airlie @ 2017-10-05 3:24 UTC (permalink / raw)
To: Keith Packard; +Cc: Dave Airlie, dri-devel, LKML
In-Reply-To: <CAPM=9txb8p0McchfwMc3Z+-OSqEJvgd32sAmmV_x+xmiYpJ2Og@mail.gmail.com>
On 5 October 2017 at 13:17, Dave Airlie <airlied@gmail.com> wrote:
>> ---
>> drivers/gpu/drm/drm_ioctl.c | 4 +
>> drivers/gpu/drm/drm_lease.c | 270 ++++++++++++++++++++++++++++++++++++++++++++
>> include/drm/drm_lease.h | 12 ++
>> include/uapi/drm/drm.h | 5 +
>> include/uapi/drm/drm_mode.h | 64 +++++++++++
>> 5 files changed, 355 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
>> index a5a259964c7d..0a43e82d3f06 100644
>> --- a/drivers/gpu/drm/drm_ioctl.c
>> +++ b/drivers/gpu/drm/drm_ioctl.c
>> @@ -657,6 +657,10 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
>> DRM_UNLOCKED|DRM_RENDER_ALLOW),
>> DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl,
>> DRM_UNLOCKED|DRM_RENDER_ALLOW),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>> };
>>
>> #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
>> diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
>> index a8bd4bdd2977..f233d8b488f2 100644
>> --- a/drivers/gpu/drm/drm_lease.c
>> +++ b/drivers/gpu/drm/drm_lease.c
>> @@ -23,6 +23,8 @@
>> #define drm_for_each_lessee(lessee, lessor) \
>> list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
>>
>> +static uint64_t drm_lease_idr_object;
>
> What is this for? ^^
>
>> + ret = idr_alloc(&leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
>
> You can just pass NULL here.
>
Just read the comment, this smells a bit of black magic, I'll spend
some time staring at it :-)
Dave.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* [U-Boot] [PATCH v2 0/8] Sync and consolidate Linux-derived printk, BUILD_BUG, BUG, WARN, etc.
From: Masahiro Yamada @ 2017-10-05 3:20 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20171005030636.GE13661@bill-the-cat>
Hi Tom,
2017-10-05 12:06 GMT+09:00 Tom Rini <trini@konsulko.com>:
> On Wed, Oct 04, 2017 at 02:15:19PM +0900, Masahiro Yamada wrote:
>> 2017-09-16 14:10 GMT+09:00 Masahiro Yamada <yamada.masahiro@socionext.com>:
>> >
>> > I tested this series with buildman.
>> >
>> >
>> >
>> > Masahiro Yamada (8):
>> > stdio.h: move printf() stuff from <common.h> to <stdio.h>
>> > printk: collect printk stuff into <linux/printk.h> with loglevel
>> > support
>> > treewide: replace with error() with pr_err()
>> > common.h: remove error()
>> > vsprintf.h: include <linux/types.h>
>> > bug.h: sync BUILD_BUG stuff with Linux 4.13
>> > bug.h: move runtime BUG/WARN macros into <linux/bug.h>
>> > dm: define dev_*() log functions in DM header
>>
>> I am still worried if this series is dismissed.
>>
>> I am being blocked from importing NAND code from Linux
>> due to missing/incompatible Linux-derived macros.
>
> I am looking at this, but a default LOGLEVEL of 5 is just too high and
> I'm seeing what's reasonable now.
>
No. I set the default to 6, not 5.
The reason why I chose 6 was to suppress a bunch of pr_info()
from drivers/mtd/nand/, which is a copy of Linux.
If you change it to a bigger number,
some annoying logs would be displayed after NAND: tag.
If you change it to a smaller number,
pr_notice() would be suppressed.
The Linux doc says:
5 (KERN_NOTICE) normal but significant condition
So, I think this is worth printing by default.
If you do not like it, you can change it,
but please make sure to adjust git-log.
--
Best Regards
Masahiro Yamada
^ permalink raw reply
* [PATCH v2] soc: mediatek: place Kconfig for all SoC drivers under menu
From: sean.wang @ 2017-10-05 3:17 UTC (permalink / raw)
To: matthias.bgg, linux-mediatek, jdelvare, arnd
Cc: linux-arm-kernel, linux-kernel, Sean Wang
From: Sean Wang <sean.wang@mediatek.com>
Add cleanup for placing all Kconfig for all MediaTek SoC drivers under
the independent menu as other SoCs vendor usually did. Since the menu
would be shown depending on "ARCH_MEDIATEK || COMPILE_TEST" selected and
MTK_PMIC_WRAP is still safe compiling with the case of "COMPILE_TEST"
only, the superfluous dependency for those items under the menu also is
also being removed for the sake of simplicity.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/soc/mediatek/Kconfig | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 609bb34..a7d0667 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,9 +1,11 @@
#
# MediaTek SoC drivers
#
+menu "MediaTek SoC drivers"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+
config MTK_INFRACFG
bool "MediaTek INFRACFG Support"
- depends on ARCH_MEDIATEK || COMPILE_TEST
select REGMAP
help
Say yes here to add support for the MediaTek INFRACFG controller. The
@@ -12,7 +14,6 @@ config MTK_INFRACFG
config MTK_PMIC_WRAP
tristate "MediaTek PMIC Wrapper Support"
- depends on ARCH_MEDIATEK
depends on RESET_CONTROLLER
select REGMAP
help
@@ -22,7 +23,6 @@ config MTK_PMIC_WRAP
config MTK_SCPSYS
bool "MediaTek SCPSYS Support"
- depends on ARCH_MEDIATEK || COMPILE_TEST
default ARCH_MEDIATEK
select REGMAP
select MTK_INFRACFG
@@ -30,3 +30,5 @@ config MTK_SCPSYS
help
Say yes here to add support for the MediaTek SCPSYS power domain
driver.
+
+endmenu
--
2.7.4
^ permalink raw reply related
* [PATCH v2] soc: mediatek: place Kconfig for all SoC drivers under menu
From: sean.wang at mediatek.com @ 2017-10-05 3:17 UTC (permalink / raw)
To: linux-arm-kernel
From: Sean Wang <sean.wang@mediatek.com>
Add cleanup for placing all Kconfig for all MediaTek SoC drivers under
the independent menu as other SoCs vendor usually did. Since the menu
would be shown depending on "ARCH_MEDIATEK || COMPILE_TEST" selected and
MTK_PMIC_WRAP is still safe compiling with the case of "COMPILE_TEST"
only, the superfluous dependency for those items under the menu also is
also being removed for the sake of simplicity.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/soc/mediatek/Kconfig | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 609bb34..a7d0667 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,9 +1,11 @@
#
# MediaTek SoC drivers
#
+menu "MediaTek SoC drivers"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+
config MTK_INFRACFG
bool "MediaTek INFRACFG Support"
- depends on ARCH_MEDIATEK || COMPILE_TEST
select REGMAP
help
Say yes here to add support for the MediaTek INFRACFG controller. The
@@ -12,7 +14,6 @@ config MTK_INFRACFG
config MTK_PMIC_WRAP
tristate "MediaTek PMIC Wrapper Support"
- depends on ARCH_MEDIATEK
depends on RESET_CONTROLLER
select REGMAP
help
@@ -22,7 +23,6 @@ config MTK_PMIC_WRAP
config MTK_SCPSYS
bool "MediaTek SCPSYS Support"
- depends on ARCH_MEDIATEK || COMPILE_TEST
default ARCH_MEDIATEK
select REGMAP
select MTK_INFRACFG
@@ -30,3 +30,5 @@ config MTK_SCPSYS
help
Say yes here to add support for the MediaTek SCPSYS power domain
driver.
+
+endmenu
--
2.7.4
^ permalink raw reply related
* [PATCH v2] soc: mediatek: place Kconfig for all SoC drivers under menu
From: sean.wang @ 2017-10-05 3:17 UTC (permalink / raw)
To: matthias.bgg, linux-mediatek, jdelvare, arnd
Cc: linux-arm-kernel, linux-kernel, Sean Wang
From: Sean Wang <sean.wang@mediatek.com>
Add cleanup for placing all Kconfig for all MediaTek SoC drivers under
the independent menu as other SoCs vendor usually did. Since the menu
would be shown depending on "ARCH_MEDIATEK || COMPILE_TEST" selected and
MTK_PMIC_WRAP is still safe compiling with the case of "COMPILE_TEST"
only, the superfluous dependency for those items under the menu also is
also being removed for the sake of simplicity.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/soc/mediatek/Kconfig | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 609bb34..a7d0667 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,9 +1,11 @@
#
# MediaTek SoC drivers
#
+menu "MediaTek SoC drivers"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+
config MTK_INFRACFG
bool "MediaTek INFRACFG Support"
- depends on ARCH_MEDIATEK || COMPILE_TEST
select REGMAP
help
Say yes here to add support for the MediaTek INFRACFG controller. The
@@ -12,7 +14,6 @@ config MTK_INFRACFG
config MTK_PMIC_WRAP
tristate "MediaTek PMIC Wrapper Support"
- depends on ARCH_MEDIATEK
depends on RESET_CONTROLLER
select REGMAP
help
@@ -22,7 +23,6 @@ config MTK_PMIC_WRAP
config MTK_SCPSYS
bool "MediaTek SCPSYS Support"
- depends on ARCH_MEDIATEK || COMPILE_TEST
default ARCH_MEDIATEK
select REGMAP
select MTK_INFRACFG
@@ -30,3 +30,5 @@ config MTK_SCPSYS
help
Say yes here to add support for the MediaTek SCPSYS power domain
driver.
+
+endmenu
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 6/6] drm: Add four ioctls for managing drm mode object leases [v3]
From: Dave Airlie @ 2017-10-05 3:17 UTC (permalink / raw)
To: Keith Packard; +Cc: LKML, Dave Airlie, Daniel Vetter, dri-devel
In-Reply-To: <20170705222406.28124-7-keithp@keithp.com>
> ---
> drivers/gpu/drm/drm_ioctl.c | 4 +
> drivers/gpu/drm/drm_lease.c | 270 ++++++++++++++++++++++++++++++++++++++++++++
> include/drm/drm_lease.h | 12 ++
> include/uapi/drm/drm.h | 5 +
> include/uapi/drm/drm_mode.h | 64 +++++++++++
> 5 files changed, 355 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index a5a259964c7d..0a43e82d3f06 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -657,6 +657,10 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
> DRM_UNLOCKED|DRM_RENDER_ALLOW),
> DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl,
> DRM_UNLOCKED|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> };
>
> #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
> diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
> index a8bd4bdd2977..f233d8b488f2 100644
> --- a/drivers/gpu/drm/drm_lease.c
> +++ b/drivers/gpu/drm/drm_lease.c
> @@ -23,6 +23,8 @@
> #define drm_for_each_lessee(lessee, lessor) \
> list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
>
> +static uint64_t drm_lease_idr_object;
What is this for? ^^
> + ret = idr_alloc(&leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
You can just pass NULL here.
Dave.
^ permalink raw reply
* Re: [kernel-hardening] [RFC V2 0/6] add more kernel pointer filter options
From: Kees Cook @ 2017-10-05 3:15 UTC (permalink / raw)
To: Linus Torvalds
Cc: Tobin C. Harding, Roberts, William C, Tejun Heo, Jordan Glover,
Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
Sergey Senozhatsky, kernel-hardening@lists.openwall.com,
Catalin Marinas, Will Deacon, Steven Rostedt, Chris Fries,
Dave Weinstein
In-Reply-To: <CA+55aFwac2BzgZs-X1_VhekkuGfuLqNui2+2DbvLiDyptS-rXQ@mail.gmail.com>
On Wed, Oct 4, 2017 at 8:10 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> But plain %p has definitely been a problem, and I don't think %pa is
> great either. So aiming to get rid of them entirely is probably a good
> idea.
As you've hinted, doing this will make %x use go up, of course, so I
remain convinced that we need some kind of at-runtime evaluation of
the arguments coming into v*sprintf(). If we removed the raw %p format
string, we'd want to stop %x from being used on memory addresses too.
-Kees
--
Kees Cook
Pixel Security
^ permalink raw reply
* Re: [PATCH] kconfig: Document the 'symbol' struct
From: Ulf Magnusson @ 2017-10-05 3:14 UTC (permalink / raw)
To: yann.morin.1998, linux-kbuild
Cc: linux-kernel, Ulf Magnusson, Masahiro Yamada, Arnaud Lacombe
In-Reply-To: <1507096094-14953-1-git-send-email-ulfalizer@gmail.com>
On Wed, Oct 4, 2017 at 7:48 AM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
> Visibility and choices in particular might be a bit tricky to figure
> out.
>
> Also fix existing comment to point out that P_MENU is also used for
> menus.
>
> Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
> ---
> scripts/kconfig/expr.h | 45 ++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
> index a73f762..6344067 100644
> --- a/scripts/kconfig/expr.h
> +++ b/scripts/kconfig/expr.h
> @@ -74,17 +74,60 @@ enum {
> S_DEF_COUNT
> };
>
> +/*
> + * Represents a configuration symbol.
> + *
> + * Choices are represented as a special kind of symbol and have the
> + * SYMBOL_CHOICE bit set in 'flags'.
> + */
> struct symbol {
> + /* The next symbol in the same bucket in the symbol hash table */
> struct symbol *next;
> +
> + /* The name of the symbol, e.g. "FOO" for 'config FOO' */
> char *name;
> +
> + /* S_BOOLEAN, S_TRISTATE, ... */
> enum symbol_type type;
> +
> + /*
> + * The calculated value of the symbol. The SYMBOL_VALID bit is set in
> + * 'flags' when this is up to date. Note that this value might differ
> + * from the user value set in e.g. a .config file, due to visibility.
> + */
> struct symbol_value curr;
> +
> + /*
> + * Values for the symbol provided from outside. def[S_DEF_USER] holds
> + * the .config value.
> + */
> struct symbol_value def[S_DEF_COUNT];
> +
> + /*
> + * An upper bound on the tristate value the user can set for the symbol
> + * if it is a boolean or tristate. Calculated from prompt dependencies,
> + * which also inherit dependencies from enclosing menus, choices, and
> + * ifs. If 'n', the user value will be ignored.
> + *
> + * Symbols lacking prompts always have visibility 'n'.
> + */
> tristate visible;
> +
> + /* SYMBOL_* flags */
> int flags;
> +
> + /* List of properties. See prop_type. */
> struct property *prop;
> +
> + /* Dependencies from enclosing menus, choices, and ifs */
> struct expr_value dir_dep;
> +
> + /* Reverse dependencies through being selected by other symbols */
> struct expr_value rev_dep;
> +
> + /*
> + * "Weak" reverse dependencies through being implied by other symbols
> + */
> struct expr_value implied;
> };
>
> @@ -133,7 +176,7 @@ enum prop_type {
> P_UNKNOWN,
> P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
> P_COMMENT, /* text associated with a comment */
> - P_MENU, /* prompt associated with a menuconfig option */
> + P_MENU, /* prompt associated with a menu or menuconfig symbol */
> P_DEFAULT, /* default y */
> P_CHOICE, /* choice value */
> P_SELECT, /* select BAR */
> --
> 2.7.4
>
Adding some CCs just because I forgot. No panic.
Cheers,
Ulf
^ permalink raw reply
* Re: [PATCH v7 7/8] net/i40e: add cloud filter parsing function for GTP
From: Wu, Jingjing @ 2017-10-05 3:13 UTC (permalink / raw)
To: Xing, Beilei; +Cc: Chilikin, Andrey, dev@dpdk.org
In-Reply-To: <1506700252-34949-8-git-send-email-beilei.xing@intel.com>
> -----Original Message-----
> From: Xing, Beilei
> Sent: Friday, September 29, 2017 11:51 PM
> To: Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Chilikin, Andrey <andrey.chilikin@intel.com>; dev@dpdk.org
> Subject: [PATCH v7 7/8] net/i40e: add cloud filter parsing function for GTP
>
> This patch adds i40e_flow_parse_gtp_filter parsing
> function for GTP-C and GTP-U to support cloud filter.
>
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
^ permalink raw reply
* Re: [PATCH] kconfig: Document the 'menu' struct
From: Ulf Magnusson @ 2017-10-05 3:13 UTC (permalink / raw)
To: yann.morin.1998, linux-kbuild
Cc: linux-kernel, Ulf Magnusson, Masahiro Yamada, Arnaud Lacombe
In-Reply-To: <1507088232-8510-1-git-send-email-ulfalizer@gmail.com>
On Wed, Oct 4, 2017 at 5:37 AM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
> Understanding what it represents helps a lot when reading the code, and
> it's not obvious, so document it.
>
> The ROOT_MENU flag is only set and tested by the gconf and qconf front
> ends, so leave it undocumented here. The obvious guess for what it means
> is correct.
>
> Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
> ---
> scripts/kconfig/expr.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 45 insertions(+)
>
> diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
> index a73f762..ae7583c 100644
> --- a/scripts/kconfig/expr.h
> +++ b/scripts/kconfig/expr.h
> @@ -166,22 +166,67 @@ struct property {
> for (st = sym->prop; st; st = st->next) \
> if (st->text)
>
> +/*
> + * Represents a node in the menu tree, as seen in e.g. menuconfig (though used
> + * for all front ends). Each symbol, menu, etc. defined in the Kconfig files
> + * gets a node. A symbol defined in multiple locations gets one node at each
> + * location.
> + */
> struct menu {
> + /* The next menu node at the same level */
> struct menu *next;
> +
> + /* The parent menu node, corresponding to e.g. a menu or choice */
> struct menu *parent;
> +
> + /* The first child menu node, for e.g. menus and choices */
> struct menu *list;
> +
> + /*
> + * The symbol associated with the menu node. Choices are implemented as
> + * a special kind of symbol. NULL for menus, comments, and ifs.
> + */
> struct symbol *sym;
> +
> + /*
> + * The prompt associated with the node. This holds the prompt for a
> + * symbol as well as the text for a menu or comment, along with the
> + * type (P_PROMPT, P_MENU, etc.)
> + */
> struct property *prompt;
> +
> + /*
> + * 'visible if' dependencies. If more than one is given, they will be
> + * ANDed together.
> + */
> struct expr *visibility;
> +
> + /*
> + * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed
> + * together
> + */
> struct expr *dep;
> +
> + /* MENU_* flags */
> unsigned int flags;
> +
> + /* Any help text associated with the node */
> char *help;
> +
> + /* The location where the menu node appears in the Kconfig files */
> struct file *file;
> int lineno;
> +
> + /* For use by front ends that need to store auxiliary data */
> void *data;
> };
>
> +/*
> + * Set on a menu node when the corresponding symbol changes state in some way.
> + * Can be checked by front ends.
> + */
> #define MENU_CHANGED 0x0001
> +
> #define MENU_ROOT 0x0002
>
> struct jump_key {
> --
> 2.7.4
>
Adding some CCs just because I forgot. No panic.
Cheers,
Ulf
^ permalink raw reply
* Re: [PATCH] kconfig: Warn if choice default is not in choice
From: Ulf Magnusson @ 2017-10-05 3:12 UTC (permalink / raw)
To: yann.morin.1998, linux-kbuild
Cc: linux-kernel, Arnd Bergmann, Ulf Magnusson, Masahiro Yamada,
Arnaud Lacombe
In-Reply-To: <CAFkk2KRAMu43Y87C+0CrNU3xs63bWuN=+kkVm0wsug95KwOi2A@mail.gmail.com>
On Wed, Oct 4, 2017 at 2:10 AM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
> On Wed, Oct 4, 2017 at 1:25 AM, Ulf Magnusson <ulfalizer@gmail.com> wrote:
>> This will catch mistakes like in the following real-world example, where
>> a "CONFIG_" prefix snuck in, making an undefined symbol the default:
>>
>> choice
>> prompt "Compiler optimization level"
>> default CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
>>
>> config CC_OPTIMIZE_FOR_PERFORMANCE
>> ...
>>
>> config CC_OPTIMIZE_FOR_SIZE
>> ...
>>
>> endchoice
>>
>> This now prints the following warning:
>>
>> init/Kconfig:1036:warning: choice default symbol 'CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE' is not contained in the choice
>>
>> Cases where the default symbol belongs to the wrong choice are also
>> detected.
>>
>> (The mistake is harmless here: Since the default symbol is not visible,
>> the choice falls back on using the first visible symbol as the default,
>> which is CC_OPTIMIZE_FOR_PERFORMANCE, as intended.)
>>
>> Discovered while playing around with Kconfiglib
>> (https://github.com/ulfalizer/Kconfiglib).
>>
>> Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
>> ---
>> scripts/kconfig/menu.c | 10 ++++++++++
>> 1 file changed, 10 insertions(+)
>>
>> diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
>> index e935793..ce88de8 100644
>> --- a/scripts/kconfig/menu.c
>> +++ b/scripts/kconfig/menu.c
>> @@ -252,6 +252,16 @@ static void sym_check_prop(struct symbol *sym)
>> "'%s': number is invalid",
>> sym->name);
>> }
>> + if (sym_is_choice(sym)) {
>> + struct property *choice_prop =
>> + sym_get_choice_prop(sym2);
>> +
>> + if (!choice_prop ||
>> + prop_get_symbol(choice_prop) != sym)
>> + prop_warn(prop,
>> + "choice default symbol '%s' is not contained in the choice",
>> + sym2->name);
>> + }
>> break;
>> case P_SELECT:
>> case P_IMPLY:
>> --
>> 2.7.4
>>
>
> A patch to fix the compiler optimization level choice has been
> submitted as well:
> https://lkml.org/lkml/2017/10/3/991
>
> Cheers,
> Ulf
Adding some CCs just because I forgot. No panic.
Cheers,
Ulf
^ permalink raw reply
* [PATCH v3 0/2] Qualcomm SMEM cached item support
From: Bjorn Andersson @ 2017-10-05 3:11 UTC (permalink / raw)
To: Andy Gross, David Brown
Cc: Stephen Boyd, Arun Kumar Neelakantam, linux-arm-msm, linux-soc,
linux-kernel
When writing the SMEM implementation no public kernel had a consumer specifying
the "cached" flag, so I ommitted this part of the implementation. On MSM8996
this has changed, where we have one user of this - namely the GLINK RX FIFO.
The remote is supposedly scanning both lists for the GLINK descriptors and TX
FIFO, so we don't need to support allocating from this list at this point. This
has been confirmed in initial testing (by booting the ADSP)
Bjorn Andersson (2):
soc: qcom: smem: Rename "uncached" accessors
soc: qcom: smem: Support getting cached entries
drivers/soc/qcom/smem.c | 93 ++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 73 insertions(+), 20 deletions(-)
--
2.12.0
^ permalink raw reply
* [PATCH v3 2/2] soc: qcom: smem: Support getting cached entries
From: Bjorn Andersson @ 2017-10-05 3:11 UTC (permalink / raw)
To: Andy Gross, David Brown
Cc: Stephen Boyd, Arun Kumar Neelakantam, linux-arm-msm, linux-soc,
linux-kernel
In-Reply-To: <20171005031128.11658-1-bjorn.andersson@linaro.org>
On msm8996 cached SMEM items are used for storing the GLINK FIFOs, so
for items not found in the uncached list we need to also search the
cased list for these items.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
Changes since v2:
- None
Changes since v1:
- phdr_to_first_cached_entry() endian conversion
- e->size is a le32, not le16
drivers/soc/qcom/smem.c | 69 +++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 61 insertions(+), 8 deletions(-)
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index b451dbc4aa39..c28275be0038 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -52,7 +52,8 @@
*
* Items in the non-cached region are allocated from the start of the partition
* while items in the cached region are allocated from the end. The free area
- * is hence the region between the cached and non-cached offsets.
+ * is hence the region between the cached and non-cached offsets. The header of
+ * cached items comes after the data.
*
*
* To synchronize allocations in the shared memory heaps a remote spinlock must
@@ -140,6 +141,7 @@ struct smem_header {
* @flags: flags for the partition (currently unused)
* @host0: first processor/host with access to this partition
* @host1: second processor/host with access to this partition
+ * @cacheline: alignment for "cached" entries
* @reserved: reserved entries for later use
*/
struct smem_ptable_entry {
@@ -148,7 +150,8 @@ struct smem_ptable_entry {
__le32 flags;
__le16 host0;
__le16 host1;
- __le32 reserved[8];
+ __le32 cacheline;
+ __le32 reserved[7];
};
/**
@@ -230,6 +233,7 @@ struct smem_region {
* @hwlock: reference to a hwspinlock
* @partitions: list of pointers to partitions affecting the current
* processor/host
+ * @cacheline: list of cacheline sizes for each host
* @num_regions: number of @regions
* @regions: list of the memory regions defining the shared memory
*/
@@ -239,6 +243,7 @@ struct qcom_smem {
struct hwspinlock *hwlock;
struct smem_partition_header *partitions[SMEM_HOST_COUNT];
+ size_t cacheline[SMEM_HOST_COUNT];
unsigned num_regions;
struct smem_region regions[0];
@@ -252,6 +257,14 @@ phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
return p + le32_to_cpu(phdr->offset_free_uncached);
}
+static void *phdr_to_first_cached_entry(struct smem_partition_header *phdr,
+ size_t cacheline)
+{
+ void *p = phdr;
+
+ return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*phdr), cacheline);
+}
+
static void *phdr_to_last_cached_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
@@ -276,6 +289,14 @@ uncached_entry_next(struct smem_private_entry *e)
le32_to_cpu(e->size);
}
+static struct smem_private_entry *
+cached_entry_next(struct smem_private_entry *e, size_t cacheline)
+{
+ void *p = e;
+
+ return p - le32_to_cpu(e->size) - ALIGN(sizeof(*e), cacheline);
+}
+
static void *uncached_entry_to_item(struct smem_private_entry *e)
{
void *p = e;
@@ -283,6 +304,13 @@ static void *uncached_entry_to_item(struct smem_private_entry *e)
return p + sizeof(*e) + le16_to_cpu(e->padding_hdr);
}
+static void *cached_entry_to_item(struct smem_private_entry *e)
+{
+ void *p = e;
+
+ return p - le32_to_cpu(e->size);
+}
+
/* Pointer to the one and only smem handle */
static struct qcom_smem *__smem;
@@ -458,18 +486,17 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
{
struct smem_partition_header *phdr;
struct smem_private_entry *e, *end;
+ size_t cacheline;
phdr = smem->partitions[host];
+ cacheline = smem->cacheline[host];
+
e = phdr_to_first_uncached_entry(phdr);
end = phdr_to_last_uncached_entry(phdr);
while (e < end) {
- if (e->canary != SMEM_PRIVATE_CANARY) {
- dev_err(smem->dev,
- "Found invalid canary in host %d partition\n",
- host);
- return ERR_PTR(-EINVAL);
- }
+ if (e->canary != SMEM_PRIVATE_CANARY)
+ goto invalid_canary;
if (le16_to_cpu(e->item) == item) {
if (size != NULL)
@@ -482,7 +509,32 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
e = uncached_entry_next(e);
}
+ /* Item was not found in the uncached list, search the cached list */
+
+ e = phdr_to_first_cached_entry(phdr, cacheline);
+ end = phdr_to_last_cached_entry(phdr);
+
+ while (e > end) {
+ if (e->canary != SMEM_PRIVATE_CANARY)
+ goto invalid_canary;
+
+ if (le16_to_cpu(e->item) == item) {
+ if (size != NULL)
+ *size = le32_to_cpu(e->size) -
+ le16_to_cpu(e->padding_data);
+
+ return cached_entry_to_item(e);
+ }
+
+ e = cached_entry_next(e, cacheline);
+ }
+
return ERR_PTR(-ENOENT);
+
+invalid_canary:
+ dev_err(smem->dev, "Found invalid canary in host %d partition\n", host);
+
+ return ERR_PTR(-EINVAL);
}
/**
@@ -659,6 +711,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
}
smem->partitions[remote_host] = header;
+ smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline);
}
return 0;
--
2.12.0
^ permalink raw reply related
* [PATCH v3 1/2] soc: qcom: smem: Rename "uncached" accessors
From: Bjorn Andersson @ 2017-10-05 3:11 UTC (permalink / raw)
To: Andy Gross, David Brown
Cc: Stephen Boyd, Arun Kumar Neelakantam, linux-arm-msm, linux-soc,
linux-kernel
In-Reply-To: <20171005031128.11658-1-bjorn.andersson@linaro.org>
In preparation for adding accessors for "cached" entries rename the
"uncached" accessors. Also rename "first" cached entry to "last", as
the cached list grows backwards.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
Changes since v2:
- Updated commit message, per Stephen's review.
Chances since v1:
- None
drivers/soc/qcom/smem.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 18ec52f2078a..b451dbc4aa39 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -245,14 +245,14 @@ struct qcom_smem {
};
static struct smem_private_entry *
-phdr_to_last_private_entry(struct smem_partition_header *phdr)
+phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
return p + le32_to_cpu(phdr->offset_free_uncached);
}
-static void *phdr_to_first_cached_entry(struct smem_partition_header *phdr)
+static void *phdr_to_last_cached_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
@@ -260,7 +260,7 @@ static void *phdr_to_first_cached_entry(struct smem_partition_header *phdr)
}
static struct smem_private_entry *
-phdr_to_first_private_entry(struct smem_partition_header *phdr)
+phdr_to_first_uncached_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
@@ -268,7 +268,7 @@ phdr_to_first_private_entry(struct smem_partition_header *phdr)
}
static struct smem_private_entry *
-private_entry_next(struct smem_private_entry *e)
+uncached_entry_next(struct smem_private_entry *e)
{
void *p = e;
@@ -276,7 +276,7 @@ private_entry_next(struct smem_private_entry *e)
le32_to_cpu(e->size);
}
-static void *entry_to_item(struct smem_private_entry *e)
+static void *uncached_entry_to_item(struct smem_private_entry *e)
{
void *p = e;
@@ -300,9 +300,9 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
void *cached;
phdr = smem->partitions[host];
- hdr = phdr_to_first_private_entry(phdr);
- end = phdr_to_last_private_entry(phdr);
- cached = phdr_to_first_cached_entry(phdr);
+ hdr = phdr_to_first_uncached_entry(phdr);
+ end = phdr_to_last_uncached_entry(phdr);
+ cached = phdr_to_last_cached_entry(phdr);
while (hdr < end) {
if (hdr->canary != SMEM_PRIVATE_CANARY) {
@@ -315,7 +315,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
if (le16_to_cpu(hdr->item) == item)
return -EEXIST;
- hdr = private_entry_next(hdr);
+ hdr = uncached_entry_next(hdr);
}
/* Check that we don't grow into the cached region */
@@ -460,8 +460,8 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
struct smem_private_entry *e, *end;
phdr = smem->partitions[host];
- e = phdr_to_first_private_entry(phdr);
- end = phdr_to_last_private_entry(phdr);
+ e = phdr_to_first_uncached_entry(phdr);
+ end = phdr_to_last_uncached_entry(phdr);
while (e < end) {
if (e->canary != SMEM_PRIVATE_CANARY) {
@@ -476,10 +476,10 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
*size = le32_to_cpu(e->size) -
le16_to_cpu(e->padding_data);
- return entry_to_item(e);
+ return uncached_entry_to_item(e);
}
- e = private_entry_next(e);
+ e = uncached_entry_next(e);
}
return ERR_PTR(-ENOENT);
--
2.12.0
^ permalink raw reply related
* Re: [kernel-hardening] [RFC V2 0/6] add more kernel pointer filter options
From: Linus Torvalds @ 2017-10-05 3:10 UTC (permalink / raw)
To: Tobin C. Harding
Cc: Roberts, William C, Tejun Heo, Jordan Glover, Greg KH,
Petr Mladek, Joe Perches, Ian Campbell, Sergey Senozhatsky,
kernel-hardening@lists.openwall.com, Catalin Marinas, Will Deacon,
Steven Rostedt, Chris Fries, Dave Weinstein
In-Reply-To: <20171005021915.GK16685@eros>
On Wed, Oct 4, 2017 at 7:19 PM, Tobin C. Harding <me@tobin.cc> wrote:
>
> This sounds like just the job for an upcoming kernel hacker, with a lot of time
> and not much experience, to do something laborious that no one else wants to do
> and learn a bunch about the kernel.
Heh.
We _have_ been doing it, but we definitely have only done it on a
random case-by-cased basis as something comes up.
So what would be great is to have something actively looking for these
things - and by "something" I mean mostly scripting.
And yes, as Kees and Daniel mentioned, it's definitely not just dmesg.
In fact, the primary things tend to be /proc and /sys, not dmesg
itself.
Another example of this would be commit 31b0b385f69d ("nf_conntrack:
avoid kernel pointer value leak in slab name"), where the fact that
the slab name had a pointer in it leaked it in the _filenames_ in
/sys, because we export slab statistics under /sys/kernel/slab/. And
each file was readable only by root, but the file *names* were
readable by everybody.
(That separate slab thing then got removed entirely later, so that
slab no longer exists at all, but it's an odd example of how the leaks
can be in the meta-data, not in the file contents themselves.
But again, I think that kind of leak would have been fairly obvious if
we just had some scripting that looked for interfaces that the kernel
exposed, and looked for that hex pattern.
In fact, that was how I noticved that one: not a grep, but an entirely
unrelated "find /sys..." that made me go "why are there kernel
addresses in there.."
So we've found them occasionally simply by mistake - and it would be
great if we found them because we actively went _looking_ for them.
> So what if we drop this patch set and
>
> 1. Find and fix every place in the kernel that leaks addresses.
> 2. Verify that checkpatch.pl warns for all potential future leakage.
> 2. Add a script to check dmesg output for future hardening.
Very ambitious (particularly that "*every* place"), but I certainly
think it would be the better end result, yes.
And I do think we would be really well off if we aimed for simply
getting rid of all the variations of %p that output hex addresses
entirely.
Don't get me wrong: I think the various _fancy_ versions of "%pXYZ"
are great, ie things like "%pS" to show the symbol name etc.
But plain %p has definitely been a problem, and I don't think %pa is
great either. So aiming to get rid of them entirely is probably a good
idea.
So I am not opposed to hobbling %p per se. It's literally just the
'kptr_restrict' model I detest. I'd rather get rid of %p (and %pa)
_entirely_ and make valid users have to work a bit extra for it,
because I think the 6+ years of kptr_restrict has shown that model of
"let people who care just enable it again" to simply not work.
Linus
^ permalink raw reply
* [PATCH net-next v4 2/3] tools: bpf: add bpftool
From: Jakub Kicinski @ 2017-10-05 3:10 UTC (permalink / raw)
To: netdev
Cc: alexei.starovoitov, daniel, dsahern, oss-drivers, brouer,
Jakub Kicinski
In-Reply-To: <20171005031005.15364-1-jakub.kicinski@netronome.com>
Add a simple tool for querying and updating BPF objects on the system.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
tools/bpf/Makefile | 18 +-
tools/bpf/bpftool/Makefile | 80 +++++
tools/bpf/bpftool/common.c | 216 ++++++++++++
tools/bpf/bpftool/jit_disasm.c | 87 +++++
tools/bpf/bpftool/main.c | 212 ++++++++++++
tools/bpf/bpftool/main.h | 99 ++++++
tools/bpf/bpftool/map.c | 744 +++++++++++++++++++++++++++++++++++++++++
tools/bpf/bpftool/prog.c | 456 +++++++++++++++++++++++++
8 files changed, 1909 insertions(+), 3 deletions(-)
create mode 100644 tools/bpf/bpftool/Makefile
create mode 100644 tools/bpf/bpftool/common.c
create mode 100644 tools/bpf/bpftool/jit_disasm.c
create mode 100644 tools/bpf/bpftool/main.c
create mode 100644 tools/bpf/bpftool/main.h
create mode 100644 tools/bpf/bpftool/map.c
create mode 100644 tools/bpf/bpftool/prog.c
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index ddf888010652..325a35e1c28e 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -3,6 +3,7 @@ prefix = /usr
CC = gcc
LEX = flex
YACC = bison
+MAKE = make
CFLAGS += -Wall -O2
CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
@@ -13,7 +14,7 @@ CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
%.lex.c: %.l
$(LEX) -o $@ $<
-all : bpf_jit_disasm bpf_dbg bpf_asm
+all: bpf_jit_disasm bpf_dbg bpf_asm bpftool
bpf_jit_disasm : CFLAGS += -DPACKAGE='bpf_jit_disasm'
bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
@@ -26,10 +27,21 @@ bpf_asm : LDLIBS =
bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o
bpf_exp.lex.o : bpf_exp.yacc.c
-clean :
+clean: bpftool_clean
rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.*
-install :
+install: bpftool_install
install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
install bpf_dbg $(prefix)/bin/bpf_dbg
install bpf_asm $(prefix)/bin/bpf_asm
+
+bpftool:
+ $(MAKE) -C bpftool
+
+bpftool_install:
+ $(MAKE) -C bpftool install
+
+bpftool_clean:
+ $(MAKE) -C bpftool clean
+
+.PHONY: bpftool FORCE
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
new file mode 100644
index 000000000000..a7151f47fb40
--- /dev/null
+++ b/tools/bpf/bpftool/Makefile
@@ -0,0 +1,80 @@
+include ../../scripts/Makefile.include
+
+include ../../scripts/utilities.mak
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+ifeq ($(V),1)
+ Q =
+else
+ Q = @
+endif
+
+BPF_DIR = $(srctree)/tools/lib/bpf/
+
+ifneq ($(OUTPUT),)
+ BPF_PATH=$(OUTPUT)
+else
+ BPF_PATH=$(BPF_DIR)
+endif
+
+LIBBPF = $(BPF_PATH)libbpf.a
+
+$(LIBBPF): FORCE
+ $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(FEATURE_DUMP_EXPORT)
+
+$(LIBBPF)-clean:
+ $(call QUIET_CLEAN, libbpf)
+ $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) clean >/dev/null
+
+prefix = /usr
+
+CC = gcc
+
+CFLAGS += -O2
+CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow
+CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf
+LIBS = -lelf -lbfd -lopcodes $(LIBBPF)
+
+include $(wildcard *.d)
+
+all: $(OUTPUT)bpftool
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OUTPUT)%.o,$(SRCS))
+
+$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
+ $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+
+$(OUTPUT)%.o: %.c
+ $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $<
+
+clean: $(LIBBPF)-clean
+ $(call QUIET_CLEAN, bpftool)
+ $(Q)rm -rf $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d
+
+install:
+ install $(OUTPUT)bpftool $(prefix)/sbin/bpftool
+
+FORCE:
+
+.PHONY: all clean FORCE
+.DEFAULT_GOAL := all
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
new file mode 100644
index 000000000000..df8396a0c400
--- /dev/null
+++ b/tools/bpf/bpftool/common.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 Netronome Systems, Inc.
+ *
+ * This software is dual licensed under the GNU General License Version 2,
+ * June 1991 as shown in the file COPYING in the top-level directory of this
+ * source tree or the BSD 2-Clause License provided below. You have the
+ * option to license this software under the complete terms of either license.
+ *
+ * The BSD 2-Clause License:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Author: Jakub Kicinski <kubakici@wp.pl> */
+
+#include <errno.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/limits.h>
+#include <linux/magic.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
+
+#include <bpf.h>
+
+#include "main.h"
+
+static bool is_bpffs(char *path)
+{
+ struct statfs st_fs;
+
+ if (statfs(path, &st_fs) < 0)
+ return false;
+
+ return (unsigned long)st_fs.f_type == BPF_FS_MAGIC;
+}
+
+int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
+{
+ enum bpf_obj_type type;
+ int fd;
+
+ fd = bpf_obj_get(path);
+ if (fd < 0) {
+ err("bpf obj get (%s): %s\n", path,
+ errno == EACCES && !is_bpffs(dirname(path)) ?
+ "directory not in bpf file system (bpffs)" :
+ strerror(errno));
+ return -1;
+ }
+
+ type = get_fd_type(fd);
+ if (type < 0) {
+ close(fd);
+ return type;
+ }
+ if (type != exp_type) {
+ err("incorrect object type: %s\n", get_fd_type_name(type));
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
+{
+ unsigned int id;
+ char *endptr;
+ int err;
+ int fd;
+
+ if (!is_prefix(*argv, "id")) {
+ err("expected 'id' got %s\n", *argv);
+ return -1;
+ }
+ NEXT_ARG();
+
+ id = strtoul(*argv, &endptr, 0);
+ if (*endptr) {
+ err("can't parse %s as ID\n", *argv);
+ return -1;
+ }
+ NEXT_ARG();
+
+ if (argc != 1)
+ usage();
+
+ fd = get_fd_by_id(id);
+ if (fd < 0) {
+ err("can't get prog by id (%u): %s\n", id, strerror(errno));
+ return -1;
+ }
+
+ err = bpf_obj_pin(fd, *argv);
+ close(fd);
+ if (err) {
+ err("can't pin the object (%s): %s\n", *argv,
+ errno == EACCES && !is_bpffs(dirname(*argv)) ?
+ "directory not in bpf file system (bpffs)" :
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+const char *get_fd_type_name(enum bpf_obj_type type)
+{
+ static const char * const names[] = {
+ [BPF_OBJ_UNKNOWN] = "unknown",
+ [BPF_OBJ_PROG] = "prog",
+ [BPF_OBJ_MAP] = "map",
+ };
+
+ if (type < 0 || type >= ARRAY_SIZE(names) || !names[type])
+ return names[BPF_OBJ_UNKNOWN];
+
+ return names[type];
+}
+
+int get_fd_type(int fd)
+{
+ char path[PATH_MAX];
+ char buf[512];
+ ssize_t n;
+
+ snprintf(path, sizeof(path), "/proc/%d/fd/%d", getpid(), fd);
+
+ n = readlink(path, buf, sizeof(buf));
+ if (n < 0) {
+ err("can't read link type: %s\n", strerror(errno));
+ return -1;
+ }
+ if (n == sizeof(path)) {
+ err("can't read link type: path too long!\n");
+ return -1;
+ }
+
+ if (strstr(buf, "bpf-map"))
+ return BPF_OBJ_MAP;
+ else if (strstr(buf, "bpf-prog"))
+ return BPF_OBJ_PROG;
+
+ return BPF_OBJ_UNKNOWN;
+}
+
+char *get_fdinfo(int fd, const char *key)
+{
+ char path[PATH_MAX];
+ char *line = NULL;
+ size_t line_n = 0;
+ ssize_t n;
+ FILE *fdi;
+
+ snprintf(path, sizeof(path), "/proc/%d/fdinfo/%d", getpid(), fd);
+
+ fdi = fopen(path, "r");
+ if (!fdi) {
+ err("can't open fdinfo: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ while ((n = getline(&line, &line_n, fdi))) {
+ char *value;
+ int len;
+
+ if (!strstr(line, key))
+ continue;
+
+ fclose(fdi);
+
+ value = strchr(line, '\t');
+ if (!value || !value[1]) {
+ err("malformed fdinfo!?\n");
+ free(line);
+ return NULL;
+ }
+ value++;
+
+ len = strlen(value);
+ memmove(line, value, len);
+ line[len - 1] = '\0';
+
+ return line;
+ }
+
+ err("key '%s' not found in fdinfo\n", key);
+ free(line);
+ fclose(fdi);
+ return NULL;
+}
diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c
new file mode 100644
index 000000000000..70e480b59e9d
--- /dev/null
+++ b/tools/bpf/bpftool/jit_disasm.c
@@ -0,0 +1,87 @@
+/*
+ * Based on:
+ *
+ * Minimal BPF JIT image disassembler
+ *
+ * Disassembles BPF JIT compiler emitted opcodes back to asm insn's for
+ * debugging or verification purposes.
+ *
+ * Copyright 2013 Daniel Borkmann <daniel@iogearbox.net>
+ * Licensed under the GNU General Public License, version 2.0 (GPLv2)
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <bfd.h>
+#include <dis-asm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static void get_exec_path(char *tpath, size_t size)
+{
+ ssize_t len;
+ char *path;
+
+ snprintf(tpath, size, "/proc/%d/exe", (int) getpid());
+ tpath[size - 1] = 0;
+
+ path = strdup(tpath);
+ assert(path);
+
+ len = readlink(path, tpath, size - 1);
+ assert(len > 0);
+ tpath[len] = 0;
+
+ free(path);
+}
+
+void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
+{
+ disassembler_ftype disassemble;
+ struct disassemble_info info;
+ int count, i, pc = 0;
+ char tpath[256];
+ bfd *bfdf;
+
+ if (!len)
+ return;
+
+ memset(tpath, 0, sizeof(tpath));
+ get_exec_path(tpath, sizeof(tpath));
+
+ bfdf = bfd_openr(tpath, NULL);
+ assert(bfdf);
+ assert(bfd_check_format(bfdf, bfd_object));
+
+ init_disassemble_info(&info, stdout, (fprintf_ftype) fprintf);
+ info.arch = bfd_get_arch(bfdf);
+ info.mach = bfd_get_mach(bfdf);
+ info.buffer = image;
+ info.buffer_length = len;
+
+ disassemble_init_for_target(&info);
+
+ disassemble = disassembler(bfdf);
+ assert(disassemble);
+
+ do {
+ printf("%4x:\t", pc);
+
+ count = disassemble(pc, &info);
+
+ if (opcodes) {
+ printf("\n\t");
+ for (i = 0; i < count; ++i)
+ printf("%02x ", (uint8_t) image[pc + i]);
+ }
+ printf("\n");
+
+ pc += count;
+ } while (count > 0 && pc < len);
+
+ bfd_close(bfdf);
+}
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
new file mode 100644
index 000000000000..e02d00d6e00b
--- /dev/null
+++ b/tools/bpf/bpftool/main.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2017 Netronome Systems, Inc.
+ *
+ * This software is dual licensed under the GNU General License Version 2,
+ * June 1991 as shown in the file COPYING in the top-level directory of this
+ * source tree or the BSD 2-Clause License provided below. You have the
+ * option to license this software under the complete terms of either license.
+ *
+ * The BSD 2-Clause License:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Author: Jakub Kicinski <kubakici@wp.pl> */
+
+#include <bfd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <linux/bpf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <bpf.h>
+
+#include "main.h"
+
+const char *bin_name;
+static int last_argc;
+static char **last_argv;
+static int (*last_do_help)(int argc, char **argv);
+
+void usage(void)
+{
+ last_do_help(last_argc - 1, last_argv + 1);
+
+ exit(-1);
+}
+
+static int do_help(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Usage: %s OBJECT { COMMAND | help }\n"
+ " %s batch file FILE\n"
+ "\n"
+ " OBJECT := { prog | map }\n",
+ bin_name, bin_name);
+
+ return 0;
+}
+
+int cmd_select(const struct cmd *cmds, int argc, char **argv,
+ int (*help)(int argc, char **argv))
+{
+ unsigned int i;
+
+ last_argc = argc;
+ last_argv = argv;
+ last_do_help = help;
+
+ if (argc < 1 && cmds[0].func)
+ return cmds[0].func(argc, argv);
+
+ for (i = 0; cmds[i].func; i++)
+ if (is_prefix(*argv, cmds[i].cmd))
+ return cmds[i].func(argc - 1, argv + 1);
+
+ help(argc - 1, argv + 1);
+
+ return -1;
+}
+
+bool is_prefix(const char *pfx, const char *str)
+{
+ if (!pfx)
+ return false;
+ if (strlen(str) < strlen(pfx))
+ return false;
+
+ return !memcmp(str, pfx, strlen(pfx));
+}
+
+void print_hex(void *arg, unsigned int n, const char *sep)
+{
+ unsigned char *data = arg;
+ unsigned int i;
+
+ for (i = 0; i < n; i++) {
+ const char *pfx = "";
+
+ if (!i)
+ /* nothing */;
+ else if (!(i % 16))
+ printf("\n");
+ else if (!(i % 8))
+ printf(" ");
+ else
+ pfx = sep;
+
+ printf("%s%02hhx", i ? pfx : "", data[i]);
+ }
+}
+
+static int do_batch(int argc, char **argv);
+
+static const struct cmd cmds[] = {
+ { "help", do_help },
+ { "batch", do_batch },
+ { "prog", do_prog },
+ { "map", do_map },
+ { 0 }
+};
+
+static int do_batch(int argc, char **argv)
+{
+ unsigned int lines = 0;
+ char *n_argv[4096];
+ char buf[65536];
+ int n_argc;
+ FILE *fp;
+ int err;
+
+ if (argc < 2) {
+ err("too few parameters for batch\n");
+ return -1;
+ } else if (!is_prefix(*argv, "file")) {
+ err("expected 'file', got: %s\n", *argv);
+ return -1;
+ } else if (argc > 2) {
+ err("too many parameters for batch\n");
+ return -1;
+ }
+ NEXT_ARG();
+
+ fp = fopen(*argv, "r");
+ if (!fp) {
+ err("Can't open file (%s): %s\n", *argv, strerror(errno));
+ return -1;
+ }
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (strlen(buf) == sizeof(buf) - 1) {
+ errno = E2BIG;
+ break;
+ }
+
+ n_argc = 0;
+ n_argv[n_argc] = strtok(buf, " \t\n");
+
+ while (n_argv[n_argc]) {
+ n_argc++;
+ if (n_argc == ARRAY_SIZE(n_argv)) {
+ err("line %d has too many arguments, skip\n",
+ lines);
+ n_argc = 0;
+ break;
+ }
+ n_argv[n_argc] = strtok(NULL, " \t\n");
+ }
+
+ if (!n_argc)
+ continue;
+
+ err = cmd_select(cmds, n_argc, n_argv, do_help);
+ if (err)
+ goto err_close;
+
+ lines++;
+ }
+
+ if (errno && errno != ENOENT) {
+ perror("reading batch file failed");
+ err = -1;
+ } else {
+ info("processed %d lines\n", lines);
+ err = 0;
+ }
+err_close:
+ fclose(fp);
+
+ return err;
+}
+
+int main(int argc, char **argv)
+{
+ bin_name = argv[0];
+ NEXT_ARG();
+
+ bfd_init();
+
+ return cmd_select(cmds, argc, argv, do_help);
+}
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
new file mode 100644
index 000000000000..85d2d7870a58
--- /dev/null
+++ b/tools/bpf/bpftool/main.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 Netronome Systems, Inc.
+ *
+ * This software is dual licensed under the GNU General License Version 2,
+ * June 1991 as shown in the file COPYING in the top-level directory of this
+ * source tree or the BSD 2-Clause License provided below. You have the
+ * option to license this software under the complete terms of either license.
+ *
+ * The BSD 2-Clause License:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Author: Jakub Kicinski <kubakici@wp.pl> */
+
+#ifndef __BPF_TOOL_H
+#define __BPF_TOOL_H
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <linux/bpf.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#define err(msg...) fprintf(stderr, "Error: " msg)
+#define warn(msg...) fprintf(stderr, "Warning: " msg)
+#define info(msg...) fprintf(stderr, msg)
+
+#define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr))
+
+#define min(a, b) \
+ ({ typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _b : _a; })
+#define max(a, b) \
+ ({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _b : _a; })
+
+#define NEXT_ARG() ({ argc--; argv++; if (argc < 0) usage(); })
+#define NEXT_ARGP() ({ (*argc)--; (*argv)++; if (*argc < 0) usage(); })
+#define BAD_ARG() ({ err("what is '%s'?\n", *argv); -1; })
+
+#define BPF_TAG_FMT "%02hhx:%02hhx:%02hhx:%02hhx:" \
+ "%02hhx:%02hhx:%02hhx:%02hhx"
+
+#define HELP_SPEC_PROGRAM \
+ "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"
+
+enum bpf_obj_type {
+ BPF_OBJ_UNKNOWN,
+ BPF_OBJ_PROG,
+ BPF_OBJ_MAP,
+};
+
+extern const char *bin_name;
+
+bool is_prefix(const char *pfx, const char *str);
+void print_hex(void *arg, unsigned int n, const char *sep);
+void usage(void) __attribute__((noreturn));
+
+struct cmd {
+ const char *cmd;
+ int (*func)(int argc, char **argv);
+};
+
+int cmd_select(const struct cmd *cmds, int argc, char **argv,
+ int (*help)(int argc, char **argv));
+
+int get_fd_type(int fd);
+const char *get_fd_type_name(enum bpf_obj_type type);
+char *get_fdinfo(int fd, const char *key);
+int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
+int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
+
+int do_prog(int argc, char **arg);
+int do_map(int argc, char **arg);
+
+int prog_parse_fd(int *argc, char ***argv);
+
+void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes);
+
+#endif
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
new file mode 100644
index 000000000000..0528a5379e6c
--- /dev/null
+++ b/tools/bpf/bpftool/map.c
@@ -0,0 +1,744 @@
+/*
+ * Copyright (C) 2017 Netronome Systems, Inc.
+ *
+ * This software is dual licensed under the GNU General License Version 2,
+ * June 1991 as shown in the file COPYING in the top-level directory of this
+ * source tree or the BSD 2-Clause License provided below. You have the
+ * option to license this software under the complete terms of either license.
+ *
+ * The BSD 2-Clause License:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Author: Jakub Kicinski <kubakici@wp.pl> */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <bpf.h>
+
+#include "main.h"
+
+static const char * const map_type_name[] = {
+ [BPF_MAP_TYPE_UNSPEC] = "unspec",
+ [BPF_MAP_TYPE_HASH] = "hash",
+ [BPF_MAP_TYPE_ARRAY] = "array",
+ [BPF_MAP_TYPE_PROG_ARRAY] = "prog_array",
+ [BPF_MAP_TYPE_PERF_EVENT_ARRAY] = "perf_event_array",
+ [BPF_MAP_TYPE_PERCPU_HASH] = "percpu_hash",
+ [BPF_MAP_TYPE_PERCPU_ARRAY] = "percpu_array",
+ [BPF_MAP_TYPE_STACK_TRACE] = "stack_trace",
+ [BPF_MAP_TYPE_CGROUP_ARRAY] = "cgroup_array",
+ [BPF_MAP_TYPE_LRU_HASH] = "lru_hash",
+ [BPF_MAP_TYPE_LRU_PERCPU_HASH] = "lru_percpu_hash",
+ [BPF_MAP_TYPE_LPM_TRIE] = "lpm_trie",
+ [BPF_MAP_TYPE_ARRAY_OF_MAPS] = "array_of_maps",
+ [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps",
+ [BPF_MAP_TYPE_DEVMAP] = "devmap",
+ [BPF_MAP_TYPE_SOCKMAP] = "sockmap",
+};
+
+static unsigned int get_possible_cpus(void)
+{
+ static unsigned int result;
+ char buf[128];
+ long int n;
+ char *ptr;
+ int fd;
+
+ if (result)
+ return result;
+
+ fd = open("/sys/devices/system/cpu/possible", O_RDONLY);
+ if (fd < 0) {
+ err("can't open sysfs possible cpus\n");
+ exit(-1);
+ }
+
+ n = read(fd, buf, sizeof(buf));
+ if (n < 2) {
+ err("can't read sysfs possible cpus\n");
+ exit(-1);
+ }
+ close(fd);
+
+ if (n == sizeof(buf)) {
+ err("read sysfs possible cpus overflow\n");
+ exit(-1);
+ }
+
+ ptr = buf;
+ n = 0;
+ while (*ptr && *ptr != '\n') {
+ unsigned int a, b;
+
+ if (sscanf(ptr, "%u-%u", &a, &b) == 2) {
+ n += b - a + 1;
+
+ ptr = strchr(ptr, '-') + 1;
+ } else if (sscanf(ptr, "%u", &a) == 1) {
+ n++;
+ } else {
+ assert(0);
+ }
+
+ while (isdigit(*ptr))
+ ptr++;
+ if (*ptr == ',')
+ ptr++;
+ }
+
+ result = n;
+
+ return result;
+}
+
+static bool map_is_per_cpu(__u32 type)
+{
+ return type == BPF_MAP_TYPE_PERCPU_HASH ||
+ type == BPF_MAP_TYPE_PERCPU_ARRAY ||
+ type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
+}
+
+static bool map_is_map_of_maps(__u32 type)
+{
+ return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
+ type == BPF_MAP_TYPE_HASH_OF_MAPS;
+}
+
+static bool map_is_map_of_progs(__u32 type)
+{
+ return type == BPF_MAP_TYPE_PROG_ARRAY;
+}
+
+static void *alloc_value(struct bpf_map_info *info)
+{
+ if (map_is_per_cpu(info->type))
+ return malloc(info->value_size * get_possible_cpus());
+ else
+ return malloc(info->value_size);
+}
+
+static int map_parse_fd(int *argc, char ***argv)
+{
+ int fd;
+
+ if (is_prefix(**argv, "id")) {
+ unsigned int id;
+ char *endptr;
+
+ NEXT_ARGP();
+
+ id = strtoul(**argv, &endptr, 0);
+ if (*endptr) {
+ err("can't parse %s as ID\n", **argv);
+ return -1;
+ }
+ NEXT_ARGP();
+
+ fd = bpf_map_get_fd_by_id(id);
+ if (fd < 0)
+ err("get map by id (%u): %s\n", id, strerror(errno));
+ return fd;
+ } else if (is_prefix(**argv, "pinned")) {
+ char *path;
+
+ NEXT_ARGP();
+
+ path = **argv;
+ NEXT_ARGP();
+
+ return open_obj_pinned_any(path, BPF_OBJ_MAP);
+ }
+
+ err("expected 'id' or 'pinned', got: '%s'?\n", **argv);
+ return -1;
+}
+
+static int
+map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
+{
+ int err;
+ int fd;
+
+ fd = map_parse_fd(argc, argv);
+ if (fd < 0)
+ return -1;
+
+ err = bpf_obj_get_info_by_fd(fd, info, info_len);
+ if (err) {
+ err("can't get map info: %s\n", strerror(errno));
+ close(fd);
+ return err;
+ }
+
+ return fd;
+}
+
+static void print_entry(struct bpf_map_info *info, unsigned char *key,
+ unsigned char *value)
+{
+ if (!map_is_per_cpu(info->type)) {
+ bool single_line, break_names;
+
+ break_names = info->key_size > 16 || info->value_size > 16;
+ single_line = info->key_size + info->value_size <= 24 &&
+ !break_names;
+
+ printf("key:%c", break_names ? '\n' : ' ');
+ print_hex(key, info->key_size, " ");
+
+ printf(single_line ? " " : "\n");
+
+ printf("value:%c", break_names ? '\n' : ' ');
+ print_hex(value, info->value_size, " ");
+
+ printf("\n");
+ } else {
+ unsigned int i, n;
+
+ n = get_possible_cpus();
+
+ printf("key:\n");
+ print_hex(key, info->key_size, " ");
+ printf("\n");
+ for (i = 0; i < n; i++) {
+ printf("value (CPU %02d):%c",
+ i, info->value_size > 16 ? '\n' : ' ');
+ print_hex(value + i * info->value_size,
+ info->value_size, " ");
+ printf("\n");
+ }
+ }
+}
+
+static char **parse_bytes(char **argv, const char *name, unsigned char *val,
+ unsigned int n)
+{
+ unsigned int i = 0;
+ char *endptr;
+
+ while (i < n && argv[i]) {
+ val[i] = strtoul(argv[i], &endptr, 0);
+ if (*endptr) {
+ err("error parsing byte: %s\n", argv[i]);
+ break;
+ }
+ i++;
+ }
+
+ if (i != n) {
+ err("%s expected %d bytes got %d\n", name, n, i);
+ return NULL;
+ }
+
+ return argv + i;
+}
+
+static int parse_elem(char **argv, struct bpf_map_info *info,
+ void *key, void *value, __u32 key_size, __u32 value_size,
+ __u32 *flags, __u32 **value_fd)
+{
+ if (!*argv) {
+ if (!key && !value)
+ return 0;
+ err("did not find %s\n", key ? "key" : "value");
+ return -1;
+ }
+
+ if (is_prefix(*argv, "key")) {
+ if (!key) {
+ if (key_size)
+ err("duplicate key\n");
+ else
+ err("unnecessary key\n");
+ return -1;
+ }
+
+ argv = parse_bytes(argv + 1, "key", key, key_size);
+ if (!argv)
+ return -1;
+
+ return parse_elem(argv, info, NULL, value, key_size, value_size,
+ flags, value_fd);
+ } else if (is_prefix(*argv, "value")) {
+ int fd;
+
+ if (!value) {
+ if (value_size)
+ err("duplicate value\n");
+ else
+ err("unnecessary value\n");
+ return -1;
+ }
+
+ argv++;
+
+ if (map_is_map_of_maps(info->type)) {
+ int argc = 2;
+
+ if (value_size != 4) {
+ err("value smaller than 4B for map in map?\n");
+ return -1;
+ }
+ if (!argv[0] || !argv[1]) {
+ err("not enough value arguments for map in map\n");
+ return -1;
+ }
+
+ fd = map_parse_fd(&argc, &argv);
+ if (fd < 0)
+ return -1;
+
+ *value_fd = value;
+ **value_fd = fd;
+ } else if (map_is_map_of_progs(info->type)) {
+ int argc = 2;
+
+ if (value_size != 4) {
+ err("value smaller than 4B for map of progs?\n");
+ return -1;
+ }
+ if (!argv[0] || !argv[1]) {
+ err("not enough value arguments for map of progs\n");
+ return -1;
+ }
+
+ fd = prog_parse_fd(&argc, &argv);
+ if (fd < 0)
+ return -1;
+
+ *value_fd = value;
+ **value_fd = fd;
+ } else {
+ argv = parse_bytes(argv, "value", value, value_size);
+ if (!argv)
+ return -1;
+ }
+
+ return parse_elem(argv, info, key, NULL, key_size, value_size,
+ flags, NULL);
+ } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
+ is_prefix(*argv, "exist")) {
+ if (!flags) {
+ err("flags specified multiple times: %s\n", *argv);
+ return -1;
+ }
+
+ if (is_prefix(*argv, "any"))
+ *flags = BPF_ANY;
+ else if (is_prefix(*argv, "noexist"))
+ *flags = BPF_NOEXIST;
+ else if (is_prefix(*argv, "exist"))
+ *flags = BPF_EXIST;
+
+ return parse_elem(argv + 1, info, key, value, key_size,
+ value_size, NULL, value_fd);
+ }
+
+ err("expected key or value, got: %s\n", *argv);
+ return -1;
+}
+
+static int show_map_close(int fd, struct bpf_map_info *info)
+{
+ char *memlock;
+
+ memlock = get_fdinfo(fd, "memlock");
+ close(fd);
+
+ printf("%u: ", info->id);
+ if (info->type < ARRAY_SIZE(map_type_name))
+ printf("%s ", map_type_name[info->type]);
+ else
+ printf("type %u ", info->type);
+
+ if (*info->name)
+ printf("name %s ", info->name);
+
+ printf("flags 0x%x\n", info->map_flags);
+ printf("\tkey %uB value %uB max_entries %u",
+ info->key_size, info->value_size, info->max_entries);
+
+ if (memlock)
+ printf(" memlock %sB", memlock);
+ free(memlock);
+
+ printf("\n");
+
+ return 0;
+}
+
+static int do_show(int argc, char **argv)
+{
+ struct bpf_map_info info = {};
+ __u32 len = sizeof(info);
+ __u32 id = 0;
+ int err;
+ int fd;
+
+ if (argc == 2) {
+ fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
+ if (fd < 0)
+ return -1;
+
+ return show_map_close(fd, &info);
+ }
+
+ if (argc)
+ return BAD_ARG();
+
+ while (true) {
+ err = bpf_map_get_next_id(id, &id);
+ if (err) {
+ if (errno == ENOENT)
+ break;
+ err("can't get next map: %s\n", strerror(errno));
+ if (errno == EINVAL)
+ err("kernel too old?\n");
+ return -1;
+ }
+
+ fd = bpf_map_get_fd_by_id(id);
+ if (fd < 0) {
+ err("can't get map by id (%u): %s\n",
+ id, strerror(errno));
+ return -1;
+ }
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
+ if (err) {
+ err("can't get map info: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ show_map_close(fd, &info);
+ }
+
+ return errno == ENOENT ? 0 : -1;
+}
+
+static int do_dump(int argc, char **argv)
+{
+ void *key, *value, *prev_key;
+ unsigned int num_elems = 0;
+ struct bpf_map_info info = {};
+ __u32 len = sizeof(info);
+ int err;
+ int fd;
+
+ if (argc != 2)
+ usage();
+
+ fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
+ if (fd < 0)
+ return -1;
+
+ if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) {
+ err("Dumping maps of maps and program maps not supported\n");
+ close(fd);
+ return -1;
+ }
+
+ key = malloc(info.key_size);
+ value = alloc_value(&info);
+ if (!key || !value) {
+ err("mem alloc failed\n");
+ err = -1;
+ goto exit_free;
+ }
+
+ prev_key = NULL;
+ while (true) {
+ err = bpf_map_get_next_key(fd, prev_key, key);
+ if (err) {
+ if (errno == ENOENT)
+ err = 0;
+ break;
+ }
+
+ if (!bpf_map_lookup_elem(fd, key, value)) {
+ print_entry(&info, key, value);
+ } else {
+ info("can't lookup element with key: ");
+ print_hex(key, info.key_size, " ");
+ printf("\n");
+ }
+
+ prev_key = key;
+ num_elems++;
+ }
+
+ printf("Found %u element%s\n", num_elems, num_elems != 1 ? "s" : "");
+
+exit_free:
+ free(key);
+ free(value);
+ close(fd);
+
+ return err;
+}
+
+static int do_update(int argc, char **argv)
+{
+ struct bpf_map_info info = {};
+ __u32 len = sizeof(info);
+ __u32 *value_fd = NULL;
+ __u32 flags = BPF_ANY;
+ void *key, *value;
+ int fd, err;
+
+ if (argc < 2)
+ usage();
+
+ fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
+ if (fd < 0)
+ return -1;
+
+ key = malloc(info.key_size);
+ value = alloc_value(&info);
+ if (!key || !value) {
+ err("mem alloc failed");
+ err = -1;
+ goto exit_free;
+ }
+
+ err = parse_elem(argv, &info, key, value, info.key_size,
+ info.value_size, &flags, &value_fd);
+ if (err)
+ goto exit_free;
+
+ err = bpf_map_update_elem(fd, key, value, flags);
+ if (err) {
+ err("update failed: %s\n", strerror(errno));
+ goto exit_free;
+ }
+
+exit_free:
+ if (value_fd)
+ close(*value_fd);
+ free(key);
+ free(value);
+ close(fd);
+
+ return err;
+}
+
+static int do_lookup(int argc, char **argv)
+{
+ struct bpf_map_info info = {};
+ __u32 len = sizeof(info);
+ void *key, *value;
+ int err;
+ int fd;
+
+ if (argc < 2)
+ usage();
+
+ fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
+ if (fd < 0)
+ return -1;
+
+ key = malloc(info.key_size);
+ value = alloc_value(&info);
+ if (!key || !value) {
+ err("mem alloc failed");
+ err = -1;
+ goto exit_free;
+ }
+
+ err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
+ if (err)
+ goto exit_free;
+
+ err = bpf_map_lookup_elem(fd, key, value);
+ if (!err) {
+ print_entry(&info, key, value);
+ } else if (errno == ENOENT) {
+ printf("key:\n");
+ print_hex(key, info.key_size, " ");
+ printf("\n\nNot found\n");
+ } else {
+ err("lookup failed: %s\n", strerror(errno));
+ }
+
+exit_free:
+ free(key);
+ free(value);
+ close(fd);
+
+ return err;
+}
+
+static int do_getnext(int argc, char **argv)
+{
+ struct bpf_map_info info = {};
+ __u32 len = sizeof(info);
+ void *key, *nextkey;
+ int err;
+ int fd;
+
+ if (argc < 2)
+ usage();
+
+ fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
+ if (fd < 0)
+ return -1;
+
+ key = malloc(info.key_size);
+ nextkey = malloc(info.key_size);
+ if (!key || !nextkey) {
+ err("mem alloc failed");
+ err = -1;
+ goto exit_free;
+ }
+
+ if (argc) {
+ err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
+ NULL, NULL);
+ if (err)
+ goto exit_free;
+ } else {
+ free(key);
+ key = NULL;
+ }
+
+ err = bpf_map_get_next_key(fd, key, nextkey);
+ if (err) {
+ err("can't get next key: %s\n", strerror(errno));
+ goto exit_free;
+ }
+
+ if (key) {
+ printf("key:\n");
+ print_hex(key, info.key_size, " ");
+ printf("\n");
+ } else {
+ printf("key: None\n");
+ }
+
+ printf("next key:\n");
+ print_hex(nextkey, info.key_size, " ");
+ printf("\n");
+
+exit_free:
+ free(nextkey);
+ free(key);
+ close(fd);
+
+ return err;
+}
+
+static int do_delete(int argc, char **argv)
+{
+ struct bpf_map_info info = {};
+ __u32 len = sizeof(info);
+ void *key;
+ int err;
+ int fd;
+
+ if (argc < 2)
+ usage();
+
+ fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
+ if (fd < 0)
+ return -1;
+
+ key = malloc(info.key_size);
+ if (!key) {
+ err("mem alloc failed");
+ err = -1;
+ goto exit_free;
+ }
+
+ err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
+ if (err)
+ goto exit_free;
+
+ err = bpf_map_delete_elem(fd, key);
+ if (err)
+ err("delete failed: %s\n", strerror(errno));
+
+exit_free:
+ free(key);
+ close(fd);
+
+ return err;
+}
+
+static int do_pin(int argc, char **argv)
+{
+ return do_pin_any(argc, argv, bpf_map_get_fd_by_id);
+}
+
+static int do_help(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Usage: %s %s show [MAP]\n"
+ " %s %s dump MAP\n"
+ " %s %s update MAP key BYTES value VALUE [UPDATE_FLAGS]\n"
+ " %s %s lookup MAP key BYTES\n"
+ " %s %s getnext MAP [key BYTES]\n"
+ " %s %s delete MAP key BYTES\n"
+ " %s %s pin MAP FILE\n"
+ " %s %s help\n"
+ "\n"
+ " MAP := { id MAP_ID | pinned FILE }\n"
+ " " HELP_SPEC_PROGRAM "\n"
+ " VALUE := { BYTES | MAP | PROG }\n"
+ " UPDATE_FLAGS := { any | exist | noexist }\n"
+ "",
+ bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
+ bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
+ bin_name, argv[-2], bin_name, argv[-2]);
+
+ return 0;
+}
+
+static const struct cmd cmds[] = {
+ { "show", do_show },
+ { "help", do_help },
+ { "dump", do_dump },
+ { "update", do_update },
+ { "lookup", do_lookup },
+ { "getnext", do_getnext },
+ { "delete", do_delete },
+ { "pin", do_pin },
+ { 0 }
+};
+
+int do_map(int argc, char **argv)
+{
+ return cmd_select(cmds, argc, argv, do_help);
+}
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
new file mode 100644
index 000000000000..421ba89ce86a
--- /dev/null
+++ b/tools/bpf/bpftool/prog.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2017 Netronome Systems, Inc.
+ *
+ * This software is dual licensed under the GNU General License Version 2,
+ * June 1991 as shown in the file COPYING in the top-level directory of this
+ * source tree or the BSD 2-Clause License provided below. You have the
+ * option to license this software under the complete terms of either license.
+ *
+ * The BSD 2-Clause License:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Author: Jakub Kicinski <kubakici@wp.pl> */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <bpf.h>
+
+#include "main.h"
+
+static const char * const prog_type_name[] = {
+ [BPF_PROG_TYPE_UNSPEC] = "unspec",
+ [BPF_PROG_TYPE_SOCKET_FILTER] = "socket_filter",
+ [BPF_PROG_TYPE_KPROBE] = "kprobe",
+ [BPF_PROG_TYPE_SCHED_CLS] = "sched_cls",
+ [BPF_PROG_TYPE_SCHED_ACT] = "sched_act",
+ [BPF_PROG_TYPE_TRACEPOINT] = "tracepoint",
+ [BPF_PROG_TYPE_XDP] = "xdp",
+ [BPF_PROG_TYPE_PERF_EVENT] = "perf_event",
+ [BPF_PROG_TYPE_CGROUP_SKB] = "cgroup_skb",
+ [BPF_PROG_TYPE_CGROUP_SOCK] = "cgroup_sock",
+ [BPF_PROG_TYPE_LWT_IN] = "lwt_in",
+ [BPF_PROG_TYPE_LWT_OUT] = "lwt_out",
+ [BPF_PROG_TYPE_LWT_XMIT] = "lwt_xmit",
+ [BPF_PROG_TYPE_SOCK_OPS] = "sock_ops",
+ [BPF_PROG_TYPE_SK_SKB] = "sk_skb",
+};
+
+static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
+{
+ struct timespec real_time_ts, boot_time_ts;
+ time_t wallclock_secs;
+ struct tm load_tm;
+
+ buf[--size] = '\0';
+
+ if (clock_gettime(CLOCK_REALTIME, &real_time_ts) ||
+ clock_gettime(CLOCK_BOOTTIME, &boot_time_ts)) {
+ perror("Can't read clocks");
+ snprintf(buf, size, "%llu", nsecs / 1000000000);
+ return;
+ }
+
+ wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) +
+ nsecs / 1000000000;
+
+ if (!localtime_r(&wallclock_secs, &load_tm)) {
+ snprintf(buf, size, "%llu", nsecs / 1000000000);
+ return;
+ }
+
+ strftime(buf, size, "%b %d/%H:%M", &load_tm);
+}
+
+static int prog_fd_by_tag(unsigned char *tag)
+{
+ struct bpf_prog_info info = {};
+ __u32 len = sizeof(info);
+ unsigned int id = 0;
+ int err;
+ int fd;
+
+ while (true) {
+ err = bpf_prog_get_next_id(id, &id);
+ if (err) {
+ err("%s\n", strerror(errno));
+ return -1;
+ }
+
+ fd = bpf_prog_get_fd_by_id(id);
+ if (fd < 0) {
+ err("can't get prog by id (%u): %s\n",
+ id, strerror(errno));
+ return -1;
+ }
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
+ if (err) {
+ err("can't get prog info (%u): %s\n",
+ id, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ if (!memcmp(tag, info.tag, BPF_TAG_SIZE))
+ return fd;
+
+ close(fd);
+ }
+}
+
+int prog_parse_fd(int *argc, char ***argv)
+{
+ int fd;
+
+ if (is_prefix(**argv, "id")) {
+ unsigned int id;
+ char *endptr;
+
+ NEXT_ARGP();
+
+ id = strtoul(**argv, &endptr, 0);
+ if (*endptr) {
+ err("can't parse %s as ID\n", **argv);
+ return -1;
+ }
+ NEXT_ARGP();
+
+ fd = bpf_prog_get_fd_by_id(id);
+ if (fd < 0)
+ err("get by id (%u): %s\n", id, strerror(errno));
+ return fd;
+ } else if (is_prefix(**argv, "tag")) {
+ unsigned char tag[BPF_TAG_SIZE];
+
+ NEXT_ARGP();
+
+ if (sscanf(**argv, BPF_TAG_FMT, tag, tag + 1, tag + 2,
+ tag + 3, tag + 4, tag + 5, tag + 6, tag + 7)
+ != BPF_TAG_SIZE) {
+ err("can't parse tag\n");
+ return -1;
+ }
+ NEXT_ARGP();
+
+ return prog_fd_by_tag(tag);
+ } else if (is_prefix(**argv, "pinned")) {
+ char *path;
+
+ NEXT_ARGP();
+
+ path = **argv;
+ NEXT_ARGP();
+
+ return open_obj_pinned_any(path, BPF_OBJ_PROG);
+ }
+
+ err("expected 'id', 'tag' or 'pinned', got: '%s'?\n", **argv);
+ return -1;
+}
+
+static void show_prog_maps(int fd, u32 num_maps)
+{
+ struct bpf_prog_info info = {};
+ __u32 len = sizeof(info);
+ __u32 map_ids[num_maps];
+ unsigned int i;
+ int err;
+
+ info.nr_map_ids = num_maps;
+ info.map_ids = ptr_to_u64(map_ids);
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
+ if (err || !info.nr_map_ids)
+ return;
+
+ printf(" map_ids ");
+ for (i = 0; i < info.nr_map_ids; i++)
+ printf("%u%s", map_ids[i],
+ i == info.nr_map_ids - 1 ? "" : ",");
+}
+
+static int show_prog(int fd)
+{
+ struct bpf_prog_info info = {};
+ __u32 len = sizeof(info);
+ char *memlock;
+ int err;
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
+ if (err) {
+ err("can't get prog info: %s\n", strerror(errno));
+ return -1;
+ }
+
+ printf("%u: ", info.id);
+ if (info.type < ARRAY_SIZE(prog_type_name))
+ printf("%s ", prog_type_name[info.type]);
+ else
+ printf("type %u ", info.type);
+
+ if (*info.name)
+ printf("name %s ", info.name);
+
+ printf("tag ");
+ print_hex(info.tag, BPF_TAG_SIZE, ":");
+ printf("\n");
+
+ if (info.load_time) {
+ char buf[32];
+
+ print_boot_time(info.load_time, buf, sizeof(buf));
+
+ /* Piggy back on load_time, since 0 uid is a valid one */
+ printf("\tloaded_at %s uid %u\n", buf, info.created_by_uid);
+ }
+
+ printf("\txlated %uB", info.xlated_prog_len);
+
+ if (info.jited_prog_len)
+ printf(" jited %uB", info.jited_prog_len);
+ else
+ printf(" not jited");
+
+ memlock = get_fdinfo(fd, "memlock");
+ if (memlock)
+ printf(" memlock %sB", memlock);
+ free(memlock);
+
+ if (info.nr_map_ids)
+ show_prog_maps(fd, info.nr_map_ids);
+
+ printf("\n");
+
+ return 0;
+}
+
+static int do_show(int argc, char **argv)
+{ __u32 id = 0;
+ int err;
+ int fd;
+
+ if (argc == 2) {
+ fd = prog_parse_fd(&argc, &argv);
+ if (fd < 0)
+ return -1;
+
+ return show_prog(fd);
+ }
+
+ if (argc)
+ return BAD_ARG();
+
+ while (true) {
+ err = bpf_prog_get_next_id(id, &id);
+ if (err) {
+ if (errno == ENOENT)
+ break;
+ err("can't get next program: %s\n", strerror(errno));
+ if (errno == EINVAL)
+ err("kernel too old?\n");
+ return -1;
+ }
+
+ fd = bpf_prog_get_fd_by_id(id);
+ if (fd < 0) {
+ err("can't get prog by id (%u): %s\n",
+ id, strerror(errno));
+ return -1;
+ }
+
+ err = show_prog(fd);
+ close(fd);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int do_dump(int argc, char **argv)
+{
+ struct bpf_prog_info info = {};
+ __u32 len = sizeof(info);
+ bool can_disasm = false;
+ unsigned int buf_size;
+ char *filepath = NULL;
+ bool opcodes = false;
+ unsigned char *buf;
+ __u32 *member_len;
+ __u64 *member_ptr;
+ ssize_t n;
+ int err;
+ int fd;
+
+ if (is_prefix(*argv, "jited")) {
+ member_len = &info.jited_prog_len;
+ member_ptr = &info.jited_prog_insns;
+ can_disasm = true;
+ } else if (is_prefix(*argv, "xlated")) {
+ member_len = &info.xlated_prog_len;
+ member_ptr = &info.xlated_prog_insns;
+ } else {
+ err("expected 'xlated' or 'jited', got: %s\n", *argv);
+ return -1;
+ }
+ NEXT_ARG();
+
+ if (argc < 2)
+ usage();
+
+ fd = prog_parse_fd(&argc, &argv);
+ if (fd < 0)
+ return -1;
+
+ if (is_prefix(*argv, "file")) {
+ NEXT_ARG();
+ if (!argc) {
+ err("expected file path\n");
+ return -1;
+ }
+
+ filepath = *argv;
+ NEXT_ARG();
+ } else if (is_prefix(*argv, "opcodes")) {
+ opcodes = true;
+ NEXT_ARG();
+ }
+
+ if (!filepath && !can_disasm) {
+ err("expected 'file' got %s\n", *argv);
+ return -1;
+ }
+ if (argc) {
+ usage();
+ return -1;
+ }
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
+ if (err) {
+ err("can't get prog info: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (!*member_len) {
+ info("no instructions returned\n");
+ close(fd);
+ return 0;
+ }
+
+ buf_size = *member_len;
+
+ buf = malloc(buf_size);
+ if (!buf) {
+ err("mem alloc failed\n");
+ close(fd);
+ return -1;
+ }
+
+ memset(&info, 0, sizeof(info));
+
+ *member_ptr = ptr_to_u64(buf);
+ *member_len = buf_size;
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
+ close(fd);
+ if (err) {
+ err("can't get prog info: %s\n", strerror(errno));
+ goto err_free;
+ }
+
+ if (*member_len > buf_size) {
+ info("too many instructions returned\n");
+ goto err_free;
+ }
+
+ if (filepath) {
+ fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd < 0) {
+ err("can't open file %s: %s\n", filepath,
+ strerror(errno));
+ goto err_free;
+ }
+
+ n = write(fd, buf, *member_len);
+ close(fd);
+ if (n != *member_len) {
+ err("error writing output file: %s\n",
+ n < 0 ? strerror(errno) : "short write");
+ goto err_free;
+ }
+ } else {
+ disasm_print_insn(buf, *member_len, opcodes);
+ }
+
+ free(buf);
+
+ return 0;
+
+err_free:
+ free(buf);
+ return -1;
+}
+
+static int do_pin(int argc, char **argv)
+{
+ return do_pin_any(argc, argv, bpf_prog_get_fd_by_id);
+}
+
+static int do_help(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Usage: %s %s show [PROG]\n"
+ " %s %s dump xlated PROG file FILE\n"
+ " %s %s dump jited PROG [file FILE] [opcodes]\n"
+ " %s %s pin PROG FILE\n"
+ " %s %s help\n"
+ "\n"
+ " " HELP_SPEC_PROGRAM "\n"
+ "",
+ bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
+ bin_name, argv[-2], bin_name, argv[-2]);
+
+ return 0;
+}
+
+static const struct cmd cmds[] = {
+ { "show", do_show },
+ { "dump", do_dump },
+ { "pin", do_pin },
+ { 0 }
+};
+
+int do_prog(int argc, char **argv)
+{
+ return cmd_select(cmds, argc, argv, do_help);
+}
--
2.14.1
^ permalink raw reply related
* [PATCH net-next v4 1/3] tools: rename tools/net directory to tools/bpf
From: Jakub Kicinski @ 2017-10-05 3:10 UTC (permalink / raw)
To: netdev
Cc: alexei.starovoitov, daniel, dsahern, oss-drivers, brouer,
Jakub Kicinski
In-Reply-To: <20171005031005.15364-1-jakub.kicinski@netronome.com>
We currently only have BPF tools in the tools/net directory.
We are about to add more BPF tools there, not necessarily
networking related, rename the directory and related Makefile
targets to bpf.
Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
MAINTAINERS | 3 +--
tools/Makefile | 14 +++++++-------
tools/{net => bpf}/Makefile | 0
tools/{net => bpf}/bpf_asm.c | 0
tools/{net => bpf}/bpf_dbg.c | 0
tools/{net => bpf}/bpf_exp.l | 0
tools/{net => bpf}/bpf_exp.y | 0
tools/{net => bpf}/bpf_jit_disasm.c | 0
8 files changed, 8 insertions(+), 9 deletions(-)
rename tools/{net => bpf}/Makefile (100%)
rename tools/{net => bpf}/bpf_asm.c (100%)
rename tools/{net => bpf}/bpf_dbg.c (100%)
rename tools/{net => bpf}/bpf_exp.l (100%)
rename tools/{net => bpf}/bpf_exp.y (100%)
rename tools/{net => bpf}/bpf_jit_disasm.c (100%)
diff --git a/MAINTAINERS b/MAINTAINERS
index 5231392cf4bd..004816a585b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2725,7 +2725,7 @@ F: net/core/filter.c
F: net/sched/act_bpf.c
F: net/sched/cls_bpf.c
F: samples/bpf/
-F: tools/net/bpf*
+F: tools/bpf/
F: tools/testing/selftests/bpf/
BROADCOM B44 10/100 ETHERNET DRIVER
@@ -9416,7 +9416,6 @@ F: include/uapi/linux/in.h
F: include/uapi/linux/net.h
F: include/uapi/linux/netdevice.h
F: include/uapi/linux/net_namespace.h
-F: tools/net/
F: tools/testing/selftests/net/
F: lib/random32.c
diff --git a/tools/Makefile b/tools/Makefile
index 9dfede37c8ff..df6fcb293fbc 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,7 +19,7 @@ include scripts/Makefile.include
@echo ' kvm_stat - top-like utility for displaying kvm statistics'
@echo ' leds - LEDs tools'
@echo ' liblockdep - user-space wrapper for kernel locking-validator'
- @echo ' net - misc networking tools'
+ @echo ' bpf - misc BPF tools'
@echo ' perf - Linux performance measurement and analysis tool'
@echo ' selftests - various kernel selftests'
@echo ' spi - spi tools'
@@ -57,7 +57,7 @@ acpi: FORCE
cpupower: FORCE
$(call descend,power/$@)
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool leds: FORCE
+cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds: FORCE
$(call descend,$@)
liblockdep: FORCE
@@ -91,7 +91,7 @@ kvm_stat: FORCE
all: acpi cgroup cpupower gpio hv firewire liblockdep \
perf selftests spi turbostat usb \
- virtio vm net x86_energy_perf_policy \
+ virtio vm bpf x86_energy_perf_policy \
tmon freefall iio objtool kvm_stat
acpi_install:
@@ -100,7 +100,7 @@ all: acpi cgroup cpupower gpio hv firewire liblockdep \
cpupower_install:
$(call descend,power/$(@:_install=),install)
-cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install:
$(call descend,$(@:_install=),install)
liblockdep_install:
@@ -124,7 +124,7 @@ all: acpi cgroup cpupower gpio hv firewire liblockdep \
install: acpi_install cgroup_install cpupower_install gpio_install \
hv_install firewire_install iio_install liblockdep_install \
perf_install selftests_install turbostat_install usb_install \
- virtio_install vm_install net_install x86_energy_perf_policy_install \
+ virtio_install vm_install bpf_install x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install
acpi_clean:
@@ -133,7 +133,7 @@ install: acpi_install cgroup_install cpupower_install gpio_install \
cpupower_clean:
$(call descend,power/cpupower,clean)
-cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean leds_clean:
+cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean:
$(call descend,$(@:_clean=),clean)
liblockdep_clean:
@@ -169,7 +169,7 @@ install: acpi_install cgroup_install cpupower_install gpio_install \
clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \
perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
- vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
+ vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
gpio_clean objtool_clean leds_clean
diff --git a/tools/net/Makefile b/tools/bpf/Makefile
similarity index 100%
rename from tools/net/Makefile
rename to tools/bpf/Makefile
diff --git a/tools/net/bpf_asm.c b/tools/bpf/bpf_asm.c
similarity index 100%
rename from tools/net/bpf_asm.c
rename to tools/bpf/bpf_asm.c
diff --git a/tools/net/bpf_dbg.c b/tools/bpf/bpf_dbg.c
similarity index 100%
rename from tools/net/bpf_dbg.c
rename to tools/bpf/bpf_dbg.c
diff --git a/tools/net/bpf_exp.l b/tools/bpf/bpf_exp.l
similarity index 100%
rename from tools/net/bpf_exp.l
rename to tools/bpf/bpf_exp.l
diff --git a/tools/net/bpf_exp.y b/tools/bpf/bpf_exp.y
similarity index 100%
rename from tools/net/bpf_exp.y
rename to tools/bpf/bpf_exp.y
diff --git a/tools/net/bpf_jit_disasm.c b/tools/bpf/bpf_jit_disasm.c
similarity index 100%
rename from tools/net/bpf_jit_disasm.c
rename to tools/bpf/bpf_jit_disasm.c
--
2.14.1
^ permalink raw reply related
* [PATCH net-next v4 0/3] tools: add bpftool
From: Jakub Kicinski @ 2017-10-05 3:10 UTC (permalink / raw)
To: netdev
Cc: alexei.starovoitov, daniel, dsahern, oss-drivers, brouer,
Jakub Kicinski
Hi!
This set adds bpftool to the tools/ directory. The first
patch renames tools/net to tools/bpf, the second one adds
the new code, while the third adds simple documentation.
v4:
- rename docs *.txt -> *.rst (Jesper).
v3:
- address Alexei's comments about output and docs.
v2:
- report names, map ids, load time, uid;
- add docs/man pages;
- general cleanups & fixes.
Jakub Kicinski (3):
tools: rename tools/net directory to tools/bpf
tools: bpf: add bpftool
tools: bpftool: add documentation
MAINTAINERS | 3 +-
tools/Makefile | 14 +-
tools/{net => bpf}/Makefile | 18 +-
tools/{net => bpf}/bpf_asm.c | 0
tools/{net => bpf}/bpf_dbg.c | 0
tools/{net => bpf}/bpf_exp.l | 0
tools/{net => bpf}/bpf_exp.y | 0
tools/{net => bpf}/bpf_jit_disasm.c | 0
tools/bpf/bpftool/Documentation/Makefile | 34 ++
tools/bpf/bpftool/Documentation/bpftool-map.rst | 110 ++++
tools/bpf/bpftool/Documentation/bpftool-prog.rst | 79 +++
tools/bpf/bpftool/Documentation/bpftool.rst | 34 ++
tools/bpf/bpftool/Makefile | 86 +++
tools/bpf/bpftool/common.c | 216 +++++++
tools/bpf/bpftool/jit_disasm.c | 87 +++
tools/bpf/bpftool/main.c | 212 +++++++
tools/bpf/bpftool/main.h | 99 +++
tools/bpf/bpftool/map.c | 744 +++++++++++++++++++++++
tools/bpf/bpftool/prog.c | 456 ++++++++++++++
19 files changed, 2180 insertions(+), 12 deletions(-)
rename tools/{net => bpf}/Makefile (74%)
rename tools/{net => bpf}/bpf_asm.c (100%)
rename tools/{net => bpf}/bpf_dbg.c (100%)
rename tools/{net => bpf}/bpf_exp.l (100%)
rename tools/{net => bpf}/bpf_exp.y (100%)
rename tools/{net => bpf}/bpf_jit_disasm.c (100%)
create mode 100644 tools/bpf/bpftool/Documentation/Makefile
create mode 100644 tools/bpf/bpftool/Documentation/bpftool-map.rst
create mode 100644 tools/bpf/bpftool/Documentation/bpftool-prog.rst
create mode 100644 tools/bpf/bpftool/Documentation/bpftool.rst
create mode 100644 tools/bpf/bpftool/Makefile
create mode 100644 tools/bpf/bpftool/common.c
create mode 100644 tools/bpf/bpftool/jit_disasm.c
create mode 100644 tools/bpf/bpftool/main.c
create mode 100644 tools/bpf/bpftool/main.h
create mode 100644 tools/bpf/bpftool/map.c
create mode 100644 tools/bpf/bpftool/prog.c
--
2.14.1
^ permalink raw reply
* [PATCH net-next v4 3/3] tools: bpftool: add documentation
From: Jakub Kicinski @ 2017-10-05 3:10 UTC (permalink / raw)
To: netdev
Cc: alexei.starovoitov, daniel, dsahern, oss-drivers, brouer,
Jakub Kicinski, David Beckett, linux-doc
In-Reply-To: <20171005031005.15364-1-jakub.kicinski@netronome.com>
Add documentation for bpftool. Separate files for each subcommand.
Use rst format. Documentation is compiled into man pages using
rst2man.
Signed-off-by: David Beckett <david.beckett@netronome.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
---
CC: linux-doc@vger.kernel.org
tools/bpf/bpftool/Documentation/Makefile | 34 +++++++
tools/bpf/bpftool/Documentation/bpftool-map.rst | 110 +++++++++++++++++++++++
tools/bpf/bpftool/Documentation/bpftool-prog.rst | 79 ++++++++++++++++
tools/bpf/bpftool/Documentation/bpftool.rst | 34 +++++++
tools/bpf/bpftool/Makefile | 6 ++
5 files changed, 263 insertions(+)
create mode 100644 tools/bpf/bpftool/Documentation/Makefile
create mode 100644 tools/bpf/bpftool/Documentation/bpftool-map.rst
create mode 100644 tools/bpf/bpftool/Documentation/bpftool-prog.rst
create mode 100644 tools/bpf/bpftool/Documentation/bpftool.rst
diff --git a/tools/bpf/bpftool/Documentation/Makefile b/tools/bpf/bpftool/Documentation/Makefile
new file mode 100644
index 000000000000..bde77d7c4390
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/Makefile
@@ -0,0 +1,34 @@
+include ../../../scripts/Makefile.include
+include ../../../scripts/utilities.mak
+
+INSTALL ?= install
+RM ?= rm -f
+
+# Make the path relative to DESTDIR, not prefix
+ifndef DESTDIR
+prefix?=$(HOME)
+endif
+mandir ?= $(prefix)/share/man
+man8dir = $(mandir)/man8
+
+MAN8_RST = $(wildcard *.rst)
+
+_DOC_MAN8 = $(patsubst %.rst,%.8,$(MAN8_RST))
+DOC_MAN8 = $(addprefix $(OUTPUT),$(_DOC_MAN8))
+
+man: man8
+man8: $(DOC_MAN8)
+
+$(OUTPUT)%.8: %.rst
+ rst2man $< > $@
+
+clean:
+ $(call QUIET_CLEAN, Documentation) $(RM) $(DOC_MAN8)
+
+install: man
+ $(call QUIET_INSTALL, Documentation-man) \
+ $(INSTALL) -d -m 755 $(DESTDIR)$(man8dir); \
+ $(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir);
+
+.PHONY: man man8 clean install
+.DEFAULT_GOAL := man
diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
new file mode 100644
index 000000000000..ad78a0a177aa
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
@@ -0,0 +1,110 @@
+================
+bpftool-map
+================
+-------------------------------------------------------------------------------
+tool for inspection and simple manipulation of eBPF maps
+-------------------------------------------------------------------------------
+
+:Manual section: 8
+
+SYNOPSIS
+========
+
+ **bpftool** **map** *COMMAND*
+
+ *COMMANDS* :=
+ { show | dump | update | lookup | getnext | delete | pin | help }
+
+MAP COMMANDS
+=============
+
+| **bpftool** map show [*MAP*]
+| **bpftool** map dump *MAP*
+| **bpftool** map update *MAP* key *BYTES* value *VALUE* [*UPDATE_FLAGS*]
+| **bpftool** map lookup *MAP* key *BYTES*
+| **bpftool** map getnext *MAP* [key *BYTES*]
+| **bpftool** map delete *MAP* key *BYTES*
+| **bpftool** map pin *MAP* *FILE*
+| **bpftool** map help
+|
+| *MAP* := { id MAP_ID | pinned FILE }
+| *VALUE* := { BYTES | MAP | PROGRAM }
+| *UPDATE_FLAGS* := { any | exist | noexist }
+
+DESCRIPTION
+===========
+ **bpftool map show** [*MAP*]
+ Show information about loaded maps. If *MAP* is specified
+ show information only about given map, otherwise list all
+ maps currently loaded on the system.
+
+ Output will start with map ID followed by map type and
+ zero or more named attributes (depending on kernel version).
+
+ **bpftool map dump** *MAP*
+ Dump all entries in a given *MAP*.
+
+ **bpftool map update** *MAP* **key** *BYTES* **value** *VALUE* [*UPDATE_FLAGS*]
+ Update map entry for a given *KEY*.
+
+ *UPDATE_FLAGS* can be one of: **any** update existing entry
+ or add if doesn't exit; **exist** update only if entry already
+ exists; **noexist** update only if entry doesn't exist.
+
+ **bpftool map lookup** *MAP* **key** *BYTES*
+ Lookup **key** in the map.
+
+ **bpftool map getnext** *MAP* [**key** *BYTES*]
+ Get next key. If *key* is not specified, get first key.
+
+ **bpftool map delete** *MAP* **key** *BYTES*
+ Remove entry from the map.
+
+ **bpftool map pin** *MAP* *FILE*
+ Pin map *MAP* as *FILE*.
+
+ Note: *FILE* must be located in *bpffs* mount.
+
+ **bpftool map help**
+ Print short help message.
+
+EXAMPLES
+========
+**# bpftool map show**
+::
+
+ 10: hash name some_map flags 0x0
+ key 4B value 8B max_entries 2048 memlock 167936B
+
+**# bpftool map update id 10 key 13 00 07 00 value 02 00 00 00 01 02 03 04**
+
+**# bpftool map lookup id 10 key 0 1 2 3**
+
+::
+
+ key: 00 01 02 03 value: 00 01 02 03 04 05 06 07
+
+
+**# bpftool map dump id 10**
+::
+
+ key: 00 01 02 03 value: 00 01 02 03 04 05 06 07
+ key: 0d 00 07 00 value: 02 00 00 00 01 02 03 04
+ Found 2 elements
+
+**# bpftool map getnext id 10 key 0 1 2 3**
+::
+
+ key:
+ 00 01 02 03
+ next key:
+ 0d 00 07 00
+
+|
+| **# mount -t bpf none /sys/fs/bpf/**
+| **# bpftool map pin id 10 /sys/fs/bpf/map**
+| **# bpftool map del pinned /sys/fs/bpf/map key 13 00 07 00**
+
+SEE ALSO
+========
+ **bpftool**\ (8), **bpftool-prog**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
new file mode 100644
index 000000000000..79791bf11e4d
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -0,0 +1,79 @@
+================
+bpftool-prog
+================
+-------------------------------------------------------------------------------
+tool for inspection and simple manipulation of eBPF progs
+-------------------------------------------------------------------------------
+
+:Manual section: 8
+
+SYNOPSIS
+========
+
+| **bpftool** prog show [*PROG*]
+| **bpftool** prog dump xlated *PROG* file *FILE*
+| **bpftool** prog dump jited *PROG* [file *FILE*] [opcodes]
+| **bpftool** prog pin *PROG* *FILE*
+| **bpftool** prog help
+|
+| *PROG* := { id *PROG_ID* | pinned *FILE* | tag *PROG_TAG* }
+
+DESCRIPTION
+===========
+ **bpftool prog show** [*PROG*]
+ Show information about loaded programs. If *PROG* is
+ specified show information only about given program, otherwise
+ list all programs currently loaded on the system.
+
+ Output will start with program ID followed by program type and
+ zero or more named attributes (depending on kernel version).
+
+ **bpftool prog dump xlated** *PROG* **file** *FILE*
+ Dump eBPF instructions of the program from the kernel to a
+ file.
+
+ **bpftool prog dump jited** *PROG* [**file** *FILE*] [**opcodes**]
+ Dump jited image (host machine code) of the program.
+ If *FILE* is specified image will be written to a file,
+ otherwise it will be disassembled and printed to stdout.
+
+ **opcodes** controls if raw opcodes will be printed.
+
+ **bpftool prog pin** *PROG* *FILE*
+ Pin program *PROG* as *FILE*.
+
+ Note: *FILE* must be located in *bpffs* mount.
+
+ **bpftool prog help**
+ Print short help message.
+
+EXAMPLES
+========
+**# bpftool prog show**
+::
+
+ 10: xdp name some_prog tag 00:5a:3d:21:23:62:0c:8b
+ loaded_at Sep 29/20:11 uid 0
+ xlated 528B jited 370B memlock 4096B map_ids 10
+
+|
+| **# bpftool prog dump xlated id 10 file /tmp/t**
+| **# ls -l /tmp/t**
+| -rw------- 1 root root 560 Jul 22 01:42 /tmp/t
+
+|
+| **# bpftool prog dum jited pinned /sys/fs/bpf/prog**
+
+::
+
+ push %rbp
+ mov %rsp,%rbp
+ sub $0x228,%rsp
+ sub $0x28,%rbp
+ mov %rbx,0x0(%rbp)
+
+
+
+SEE ALSO
+========
+ **bpftool**\ (8), **bpftool-map**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
new file mode 100644
index 000000000000..f1df1893fb54
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool.rst
@@ -0,0 +1,34 @@
+================
+BPFTOOL
+================
+-------------------------------------------------------------------------------
+tool for inspection and simple manipulation of eBPF programs and maps
+-------------------------------------------------------------------------------
+
+:Manual section: 8
+
+SYNOPSIS
+========
+
+ **bpftool** *OBJECT* { *COMMAND* | help }
+
+ **bpftool** batch file *FILE*
+
+ *OBJECT* := { **map** | **program** }
+
+ *MAP-COMMANDS* :=
+ { show | dump | update | lookup | getnext | delete | pin | help }
+
+ *PROG-COMMANDS* := { show | dump jited | dump xlated | pin | help }
+
+DESCRIPTION
+===========
+ *bpftool* allows for inspection and simple modification of BPF objects
+ on the system.
+
+ Note that format of the output of all tools is not guaranteed to be
+ stable and should not be depended upon.
+
+SEE ALSO
+========
+ **bpftool-map**\ (8), **bpftool-prog**\ (8)
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index a7151f47fb40..8705ee44664d 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -74,6 +74,12 @@ clean: $(LIBBPF)-clean
install:
install $(OUTPUT)bpftool $(prefix)/sbin/bpftool
+doc:
+ $(Q)$(MAKE) -C Documentation/
+
+doc-install:
+ $(Q)$(MAKE) -C Documentation/ install
+
FORCE:
.PHONY: all clean FORCE
--
2.14.1
^ permalink raw reply related
* Re: [PATCH v7 6/8] net/i40e: add FDIR support for GTP-C and GTP-U
From: Wu, Jingjing @ 2017-10-05 3:09 UTC (permalink / raw)
To: Xing, Beilei; +Cc: Chilikin, Andrey, dev@dpdk.org
In-Reply-To: <1506700252-34949-7-git-send-email-beilei.xing@intel.com>
> @@ -975,27 +1003,30 @@ i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input
> *fdir_input,
> raw_pkt += sizeof(uint16_t);
> len += sizeof(uint16_t);
>
> - switch (fdir_input->pctype) {
> - case I40E_FILTER_PCTYPE_L2_PAYLOAD:
> + if (is_customized_pctype) {
> + cus_pctype = i40e_flow_fdir_find_customized_pctype(pf, pctype);
> + if (!cus_pctype)
> + PMD_DRV_LOG(ERR, "unknown pctype %u.",
> + fdir_input->pctype);
Doesn't return here?
If it is impossible cus_pctype is NULL, the check is unnecessary.
Because you used the cus_ptype below.
Thanks
Jingjing
^ permalink raw reply
* [PATCH] kconfig: Sync zconf.y with zconf.tab.c_shipped
From: Ulf Magnusson @ 2017-10-05 3:06 UTC (permalink / raw)
To: yann.morin.1998, linux-kbuild
Cc: mmarek, yamada.masahiro, lacombar, linux-kernel, Ulf Magnusson
Looks like a change to a comment in zconf.y was never committed, because
the updated version only appears it zconf.tab.c_shipped. Update the
comment in zconf.y to match.
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
---
scripts/kconfig/zconf.y | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index c8f396c..4b2cf41 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -101,7 +101,7 @@ static struct menu *current_menu, *current_entry;
} if_entry menu_entry choice_entry
%{
-/* Include zconf_id.c here so it can see the token constants. */
+/* Include kconf_id.c here so it can see the token constants. */
#include "kconf_id.c"
%}
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.