* Re: [iproute2 1/1] ss: Add support for TIPC socket diag in ss tool
From: Stephen Hemminger @ 2018-03-27 18:39 UTC (permalink / raw)
To: GhantaKrishnamurthy MohanKrishna
Cc: tipc-discussion, jon.maloy, maloy, ying.xue, netdev,
Parthasarathy Bhuvaragan
In-Reply-To: <1521813662-9954-2-git-send-email-mohan.krishna.ghanta.krishnamurthy@ericsson.com>
On Fri, 23 Mar 2018 15:01:02 +0100
GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com> wrote:
> For iproute 4.x
> Allow TIPC socket statistics to be dumped with --tipc
> and tipc specific info with --tipcinfo.
>
> Acked-by: Jon Maloy <jon.maloy@ericsson.com>
> Signed-off-by: GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com>
> Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@gmail.com>
> ---
> misc/ss.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 164 insertions(+), 2 deletions(-)
>
> diff --git a/misc/ss.c b/misc/ss.c
> index e047f9c04582..812f45717af9 100644
> --- a/misc/ss.c
> +++ b/misc/ss.c
> @@ -45,6 +45,10 @@
> #include <linux/netlink_diag.h>
> #include <linux/sctp.h>
> #include <linux/vm_sockets_diag.h>
> +#include <linux/net.h>
> +#include <linux/tipc.h>
> +#include <linux/tipc_netlink.h>
> +#include <linux/tipc_sockets_diag.h>
This needs to be against iproute2-next, not master since there is no tipc_sockets_diag.h
in Linus's tree.
All the header files for iproute2 include/uapi/linux come from upstream kernel
via 'make headers_install'. Therefore you need to have tipc_sockets_diag.h in
kernel already.
^ permalink raw reply
* Re: [iproute PATCH] ssfilter: Eliminate shift/reduce conflicts
From: Stephen Hemminger @ 2018-03-27 18:42 UTC (permalink / raw)
To: Phil Sutter; +Cc: netdev
In-Reply-To: <20180324174514.17840-1-phil@nwl.cc>
On Sat, 24 Mar 2018 18:45:14 +0100
Phil Sutter <phil@nwl.cc> wrote:
> The problematic bit was the 'expr: expr expr' rule. Fix this by making
> 'expr' token represent a single filter only and introduce a new token
> 'exprlist' to represent a combination of filters.
>
> Signed-off-by: Phil Sutter <phil@nwl.cc>
Thanks for fixing this. It was always a nuisance.
^ permalink raw reply
* Re: [iproute PATCH 2/3] ss: Put filter DB parsing into a separate function
From: Stephen Hemminger @ 2018-03-27 18:46 UTC (permalink / raw)
To: Phil Sutter; +Cc: netdev
In-Reply-To: <20180324181811.22615-3-phil@nwl.cc>
On Sat, 24 Mar 2018 19:18:10 +0100
Phil Sutter <phil@nwl.cc> wrote:
> +#define ENTRY(name, ...) { #name, { __VA_ARGS__, MAX_DB }}
> + ENTRY(all, UDP_DB, DCCP_DB, TCP_DB, RAW_DB, \
> + UNIX_ST_DB, UNIX_DG_DB, UNIX_SQ_DB, \
> + PACKET_R_DB, PACKET_DG_DB, NETLINK_DB, \
> + SCTP_DB, VSOCK_ST_DB, VSOCK_DG_DB),
Checkpatch complains that line continuations are not necessary here;
and it is right. Macro usage can cross lines.
^ permalink raw reply
* Re: [PATCH v6 bpf-next 08/11] bpf: introduce BPF_RAW_TRACEPOINT
From: Alexei Starovoitov @ 2018-03-27 18:45 UTC (permalink / raw)
To: Steven Rostedt
Cc: davem, daniel, torvalds, peterz, netdev, kernel-team, linux-api,
Mathieu Desnoyers, Kees Cook
In-Reply-To: <20180327130211.284c8924@gandalf.local.home>
On 3/27/18 10:02 AM, Steven Rostedt wrote:
> On Mon, 26 Mar 2018 19:47:03 -0700
> Alexei Starovoitov <ast@fb.com> wrote:
>
>
>> Ctrl-C of tracing daemon or cmdline tool that uses this feature
>> will automatically detach bpf program, unload it and
>> unregister tracepoint probe.
>>
>> On the kernel side for_each_kernel_tracepoint() is used
>
> You need to update the change log to state
> kernel_tracepoint_find_by_name().
ahh. right. will do.
>> +#undef DECLARE_EVENT_CLASS
>> +#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
>> +/* no 'static' here. The bpf probe functions are global */ \
>> +notrace void \
>
> I'm curious to why you have notrace here? Since it is separate from
> perf and ftrace, for debugging purposes, it could be useful to allow
> function tracing to this function.
To avoid unnecessary overhead. And I don't think it's useful to trace
them. They're tiny jump functions of one or two instructions.
Really no point wasting mentry on them.
>> +static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
>> +{
>> + struct bpf_raw_tracepoint *raw_tp;
>> + struct tracepoint *tp;
>> + struct bpf_prog *prog;
>> + char tp_name[128];
>> + int tp_fd, err;
>> +
>> + if (strncpy_from_user(tp_name, u64_to_user_ptr(attr->raw_tracepoint.name),
>> + sizeof(tp_name) - 1) < 0)
>> + return -EFAULT;
>> + tp_name[sizeof(tp_name) - 1] = 0;
>> +
>> + tp = kernel_tracepoint_find_by_name(tp_name);
>> + if (!tp)
>> + return -ENOENT;
>> +
>> + raw_tp = kmalloc(sizeof(*raw_tp), GFP_USER | __GFP_ZERO);
>
> Please use kzalloc(), instead of open coding the "__GPF_ZERO"
right. will do
>
> Could you add some comments here to explain what the below is doing.
To write a proper comment I need to understand it and I don't.
That's the reason why I didn't put in in common header,
because it would require proper comment on what it is and
how one can use it.
I'm expecting Daniel to follow up on this.
>> +#define UNPACK(...) __VA_ARGS__
>> +#define REPEAT_1(FN, DL, X, ...) FN(X)
>> +#define REPEAT_2(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_1(FN, DL, __VA_ARGS__)
>> +#define REPEAT_3(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_2(FN, DL, __VA_ARGS__)
>> +#define REPEAT_4(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_3(FN, DL, __VA_ARGS__)
>> +#define REPEAT_5(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_4(FN, DL, __VA_ARGS__)
>> +#define REPEAT_6(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_5(FN, DL, __VA_ARGS__)
>> +#define REPEAT_7(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_6(FN, DL, __VA_ARGS__)
>> +#define REPEAT_8(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_7(FN, DL, __VA_ARGS__)
>> +#define REPEAT_9(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_8(FN, DL, __VA_ARGS__)
>> +#define REPEAT_10(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_9(FN, DL, __VA_ARGS__)
>> +#define REPEAT_11(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_10(FN, DL, __VA_ARGS__)
>> +#define REPEAT_12(FN, DL, X, ...) FN(X) UNPACK DL REPEAT_11(FN, DL, __VA_ARGS__)
>> +#define REPEAT(X, FN, DL, ...) REPEAT_##X(FN, DL, __VA_ARGS__)
>> +
>> +
>> + snprintf(buf, sizeof(buf), "__bpf_trace_%s", tp->name);
>> + addr = kallsyms_lookup_name(buf);
>> + if (!addr)
>> + return -ENOENT;
>> +
>> + return tracepoint_probe_register(tp, (void *)addr, prog);
>
> You are putting in a hell of a lot of trust with kallsyms returning
> properly. I can see this being very fragile. This is calling a function
> based on the result of kallsyms. I'm sure the security folks would love
> this.
>
> There's a few things to make this a bit more robust. One is to add a
> table that points to all __bpf_trace_* functions, and verify that the
> result from kallsyms is in that table.
>
> Honestly, I think this is too much of a short cut and a hack. I know
> you want to keep it "simple" and save space, but you really should do
> it the same way ftrace and perf do it. That is, create a section and
> have all tracepoints create a structure that holds a pointer to the
> tracepoint and to the bpf probe function. Then you don't even need the
> kernel_tracepoint_find_by_name(), you just iterate over your table and
> you get the tracepoint and the bpf function associated to it.
>
> Relying on kallsyms to return an address to execute is just way too
> extreme and fragile for my liking.
Wasting extra 8bytes * number_of_tracepoints just for lack of trust
in kallsyms doesn't sound like good trade off to me.
If kallsyms are inaccurate all sorts of things will break:
kprobes, livepatch, etc.
I'd rather suggest for ftrace to use kallsyms approach as well
and reduce memory footprint.
^ permalink raw reply
* [resend PATCH] rxrpc: Neaten logging macros and add KERN_DEBUG logging level
From: Joe Perches @ 2018-03-27 18:52 UTC (permalink / raw)
To: David Howells; +Cc: David S. Miller, linux-afs, netdev, linux-kernel
When enabled, the current debug logging does not have a KERN_<LEVEL>.
Add KERN_DEBUG to the logging macros.
Miscellanea:
o Remove #define redundancy and neaten the macros a bit
Signed-off-by: Joe Perches <joe@perches.com>
---
Resend of patch: https://lkml.org/lkml/2017/11/30/573
No change in patch.
David Howells is now a listed maintainer for net/rxrpc/ so he should receive
this patch via get_maintainer
net/rxrpc/ar-internal.h | 75 ++++++++++++++++++-------------------------------
1 file changed, 28 insertions(+), 47 deletions(-)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 416688381eb7..d4b53b2339b3 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1147,66 +1147,47 @@ static inline bool after_eq(u32 seq1, u32 seq2)
*/
extern unsigned int rxrpc_debug;
-#define dbgprintk(FMT,...) \
- printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__)
+#if defined(__KDEBUG) || defined(CONFIG_AF_RXRPC_DEBUG)
+#define dbgprintk(fmt, ...) \
+ printk(KERN_DEBUG "[%-6.6s] " fmt "\n", current->comm, ##__VA_ARGS__)
+#else
+#define dbgprintk(fmt, ...) \
+ no_printk(KERN_DEBUG "[%-6.6s] " fmt "\n", current->comm, ##__VA_ARGS__)
+#endif
-#define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
-#define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
-#define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__)
-#define kproto(FMT,...) dbgprintk("### "FMT ,##__VA_ARGS__)
-#define knet(FMT,...) dbgprintk("@@@ "FMT ,##__VA_ARGS__)
+#define kenter(fmt, ...) dbgprintk("==> %s(" fmt ")", __func__, ##__VA_ARGS__)
+#define kleave(fmt, ...) dbgprintk("<== %s()" fmt "", __func__, ##__VA_ARGS__)
+#define kdebug(fmt, ...) dbgprintk(" " fmt, ##__VA_ARGS__)
+#define kproto(fmt, ...) dbgprintk("### " fmt, ##__VA_ARGS__)
+#define knet(fmt, ...) dbgprintk("@@@ " fmt, ##__VA_ARGS__)
+#if defined(__KDEBUG) || !defined(CONFIG_AF_RXRPC_DEBUG)
+#define _enter(fmt, ...) kenter(fmt, ##__VA_ARGS__)
+#define _leave(fmt, ...) kleave(fmt, ##__VA_ARGS__)
+#define _debug(fmt, ...) kdebug(fmt, ##__VA_ARGS__)
+#define _proto(fmt, ...) kproto(fmt, ##__VA_ARGS__)
+#define _net(fmt, ...) knet(fmt, ##__VA_ARGS__)
-#if defined(__KDEBUG)
-#define _enter(FMT,...) kenter(FMT,##__VA_ARGS__)
-#define _leave(FMT,...) kleave(FMT,##__VA_ARGS__)
-#define _debug(FMT,...) kdebug(FMT,##__VA_ARGS__)
-#define _proto(FMT,...) kproto(FMT,##__VA_ARGS__)
-#define _net(FMT,...) knet(FMT,##__VA_ARGS__)
+#else
-#elif defined(CONFIG_AF_RXRPC_DEBUG)
#define RXRPC_DEBUG_KENTER 0x01
#define RXRPC_DEBUG_KLEAVE 0x02
#define RXRPC_DEBUG_KDEBUG 0x04
#define RXRPC_DEBUG_KPROTO 0x08
#define RXRPC_DEBUG_KNET 0x10
-#define _enter(FMT,...) \
-do { \
- if (unlikely(rxrpc_debug & RXRPC_DEBUG_KENTER)) \
- kenter(FMT,##__VA_ARGS__); \
-} while (0)
-
-#define _leave(FMT,...) \
-do { \
- if (unlikely(rxrpc_debug & RXRPC_DEBUG_KLEAVE)) \
- kleave(FMT,##__VA_ARGS__); \
-} while (0)
-
-#define _debug(FMT,...) \
-do { \
- if (unlikely(rxrpc_debug & RXRPC_DEBUG_KDEBUG)) \
- kdebug(FMT,##__VA_ARGS__); \
-} while (0)
-
-#define _proto(FMT,...) \
-do { \
- if (unlikely(rxrpc_debug & RXRPC_DEBUG_KPROTO)) \
- kproto(FMT,##__VA_ARGS__); \
+#define RXRPC_DEBUG(TYPE, type, fmt, ...) \
+do { \
+ if (unlikely(rxrpc_debug & RXRPC_DEBUG_##TYPE)) \
+ type(fmt, ##__VA_ARGS__); \
} while (0)
-#define _net(FMT,...) \
-do { \
- if (unlikely(rxrpc_debug & RXRPC_DEBUG_KNET)) \
- knet(FMT,##__VA_ARGS__); \
-} while (0)
+#define _enter(fmt, ...) RXRPC_DEBUG(KENTER, kenter, fmt, ##__VA_ARGS__)
+#define _leave(fmt, ...) RXRPC_DEBUG(KLEAVE, kleave, fmt, ##__VA_ARGS__)
+#define _debug(fmt, ...) RXRPC_DEBUG(KDEBUG, kdebug, fmt, ##__VA_ARGS__)
+#define _proto(fmt, ...) RXRPC_DEBUG(KPROTO, kproto, fmt, ##__VA_ARGS__)
+#define _net(fmt, ...) RXRPC_DEBUG(KNET, knet, fmt, ##__VA_ARGS__)
-#else
-#define _enter(FMT,...) no_printk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
-#define _leave(FMT,...) no_printk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
-#define _debug(FMT,...) no_printk(" "FMT ,##__VA_ARGS__)
-#define _proto(FMT,...) no_printk("### "FMT ,##__VA_ARGS__)
-#define _net(FMT,...) no_printk("@@@ "FMT ,##__VA_ARGS__)
#endif
/*
--
2.15.0
^ permalink raw reply related
* Re: [PATCH iproute2 v1] Drop capabilities if not running ip exec vrf with libcap
From: Stephen Hemminger @ 2018-03-27 18:52 UTC (permalink / raw)
To: Luca Boccassi; +Cc: netdev, dsahern, luto
In-Reply-To: <20180327174855.30497-1-bluca@debian.org>
On Tue, 27 Mar 2018 18:48:55 +0100
Luca Boccassi <bluca@debian.org> wrote:
> ip vrf exec requires root or CAP_NET_ADMIN, CAP_SYS_ADMIN and
> CAP_DAC_OVERRIDE. It is not possible to run unprivileged commands like
> ping as non-root or non-cap-enabled due to this requirement.
> To allow users and administrators to safely add the required
> capabilities to the binary, drop all capabilities on start if not
> invoked with "vrf exec".
> Update the manpage with the requirements.
>
> Signed-off-by: Luca Boccassi <bluca@debian.org>
Applied
^ permalink raw reply
* Re: RFC on writel and writel_relaxed
From: Alexander Duyck @ 2018-03-27 18:54 UTC (permalink / raw)
To: Will Deacon
Cc: Sinan Kaya, Benjamin Herrenschmidt, Arnd Bergmann,
Jason Gunthorpe, David Laight, Oliver,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
linux-rdma@vger.kernel.org, Alexander Duyck, Paul E. McKenney,
netdev@vger.kernel.org, Linus Torvalds
In-Reply-To: <20180327151029.GB17494@arm.com>
On Tue, Mar 27, 2018 at 8:10 AM, Will Deacon <will.deacon@arm.com> wrote:
> Hi Alex,
>
> On Tue, Mar 27, 2018 at 10:46:58AM -0400, Sinan Kaya wrote:
>> +netdev, +Alex
>>
>> On 3/26/2018 6:00 PM, Benjamin Herrenschmidt wrote:
>> > On Mon, 2018-03-26 at 23:30 +0200, Arnd Bergmann wrote:
>> >> Most of the drivers have a unwound loop with writeq() or something to
>> >>> do it.
>> >>
>> >> But isn't the writeq() barrier much more expensive than anything you'd
>> >> do in function calls?
>> >
>> > It is for us, and will break any write combining.
>> >
>> >>>>> The same document says that _relaxed() does not give that guarentee.
>> >>>>>
>> >>>>> The lwn articule on this went into some depth on the interaction with
>> >>>>> spinlocks.
>> >>>>>
>> >>>>> As far as I can see, containment in a spinlock seems to be the only
>> >>>>> different between writel and writel_relaxed..
>> >>>>
>> >>>> I was always puzzled by this: The intention of _relaxed() on ARM
>> >>>> (where it originates) was to skip the barrier that serializes DMA
>> >>>> with MMIO, not to skip the serialization between MMIO and locks.
>> >>>
>> >>> But that was never a requirement of writel(),
>> >>> Documentation/memory-barriers.txt gives an explicit example demanding
>> >>> the wmb() before writel() for ordering system memory against writel.
>> >
>> > This is a bug in the documentation.
>> >
>> >> Indeed, but it's in an example for when to use dma_wmb(), not wmb().
>> >> Adding Alexander Duyck to Cc, he added that section as part of
>> >> 1077fa36f23e ("arch: Add lightweight memory barriers dma_rmb() and
>> >> dma_wmb()"). Also adding the other people that were involved with that.
>> >
>> > Linus himself made it very clear years ago. readl and writel have to
>> > order vs memory accesses.
>> >
>> >>> I actually have no idea why ARM had that barrier, I always assumed it
>> >>> was to give program ordering to the accesses and that _relaxed allowed
>> >>> re-ordering (the usual meaning of relaxed)..
>> >>>
>> >>> But the barrier document makes it pretty clear that the only
>> >>> difference between the two is spinlock containment, and WillD wrote
>> >>> this text, so I belive it is accurate for ARM.
>> >>>
>> >>> Very confusing.
>> >>
>> >> It does mention serialization with both DMA and locks in the
>> >> section about readX_relaxed()/writeX_relaxed(). The part
>> >> about DMA is very clear here, and I must have just forgotten
>> >> the exact semantics with regards to spinlocks. I'm still not
>> >> sure what prevents a writel() from leaking out the end of a
>> >> spinlock section that doesn't happen with writel_relaxed(), since
>> >> the barrier in writel() comes before the access, and the
>> >> spin_unlock() shouldn't affect the external buses.
>> >
>> > So...
>> >
>> > Historically, what happened is that we (we means whoever participated
>> > in the discussion on the list with Linus calling the shots really)
>> > decided that there was no sane way for drivers to understand a world
>> > where readl/writel didn't fully order things vs. memory accesses (ie,
>> > DMA).
>> >
>> > So it should always be correct to do:
>> >
>> > - Write to some in-memory buffer
>> > - writel() to kick the DMA read of that buffer
>> >
>> > without any extra barrier.
>> >
>> > The spinlock situation however got murky. Mostly that came up because
>> > on architecture (I forgot who, might have been ia64) has a hard time
>> > providing that consistency without making writel insanely expensive.
>> >
>> > Thus they created mmiowb whose main purpose was precisely to order
>> > writel with a following spin_unlock.
>> >
>> > I decided not to go down that path on power because getting all drivers
>> > "fixed" to do the right thing was going to be a losing battle, and
>> > instead added per-cpu tracking of writel in order to "escalate" to a
>> > heavier barrier in spin_unlock itself when necessary.
>> >
>> > Now, all this happened more than a decade ago and it's possible that
>> > the understanding or expectations "shifted" over time...
>>
>> Alex is raising concerns on the netdev list.
>>
>> Sinan
>> "We are being told that if you use writel(), then you don't need a wmb() on
>> all architectures."
>>
>> Alex:
>> "I'm not sure who told you that but that is incorrect, at least for
>> x86. If you attempt to use writel() without the wmb() we will have to
>> NAK the patches. We will accept the wmb() with writel_releaxed() since
>> that solves things for ARM."
>>
>> > Jason is seeking behavior clarification for write combined buffers.
>>
>> Alex:
>> "Don't bother. I can tell you right now that for x86 you have to have a
>> wmb() before the writel().
>
> To clarify: are you saying that on x86 you need a wmb() prior to a writel
> if you want that writel to be ordered after prior writes to memory? Is this
> specific to WC memory or some other non-standard attribute?
Note, I am not a CPU guy so this is just my interpretation. It is my
understanding that the wmb(), aka sfence, is needed on x86 to sort out
writes between Write-back(WB) system memory and Strong Uncacheable
(UC) MMIO accesses.
I was hoping to be able to cite something in the software developers
manual (https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf),
but that tends to be pretty vague. I have re-read section 22.34
(volume 3B) several times and I am still not clear on if it says we
need the sfence or not. It is a matter of figuring out what the impact
of store buffers and caching are for WB versus UC memory.
> The only reason we have wmb() inside writel() on arm, arm64 and power is for
> parity with x86 because Linus (CC'd) wanted architectures to order I/O vs
> memory by default so that it was easier to write portable drivers. The
> performance impact of that implicit barrier is non-trivial, but we want the
> driver portability and I went as far as adding generic _relaxed versions for
> the cases where ordering isn't required. You seem to be suggesting that none
> of this is necessary and drivers would already run into problems on x86 if
> they didn't use wmb() explicitly in conjunction with writel, which I find
> hard to believe and is in direct contradiction with the current Linux I/O
> memory model (modulo the broken example in the dma_*mb section of
> memory-barriers.txt).
Is the issue specifically related to memory versus I/O or are there
potential ordering issues for MMIO versus MMIO? I recall when working
on the dma_*mb section that the ARM barriers were much more complex
versus some of the other architectures. One big difference that I can
see for the x86 versus what you define for the "_relaxed" version of
things is the ordering of MMIO operations with respect to locked
transactions. I know x86 forces all MMIO operations to be completed
before you can process any locked operation.
> Has something changed?
>
> Will
As far as I know the code has been this way for a while, something
like 2002, when the barrier was already present in e1000. However
there it was calling out weakly ordered models "such as IA-64". Since
then pretty much all the hardware based network drivers at this point
have similar code floating around with wmb() in place to prevent
issues on weak ordered memory systems.
So in any case we still need to be careful as there are architectures
that are depending on this even if they might not be x86. :-/
- Alex
^ permalink raw reply
* [PATCH] bpf: follow idr code convention
From: Shaohua Li @ 2018-03-27 18:53 UTC (permalink / raw)
To: netdev @ vger . kernel . org
Cc: Kernel Team, Shaohua Li, Daniel Borkmann, Alexei Starovoitov
From: Shaohua Li <shli@fb.com>
Generally we do a preload before doing idr allocation. This also help
improve the allocation success rate in memory pressure.
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Shaohua Li <shli@fb.com>
---
kernel/bpf/syscall.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 43f95d1..beab5de 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -203,11 +203,13 @@ static int bpf_map_alloc_id(struct bpf_map *map)
{
int id;
+ idr_preload(GFP_KERNEL);
spin_lock_bh(&map_idr_lock);
id = idr_alloc_cyclic(&map_idr, map, 1, INT_MAX, GFP_ATOMIC);
if (id > 0)
map->id = id;
spin_unlock_bh(&map_idr_lock);
+ idr_preload_end();
if (WARN_ON_ONCE(!id))
return -ENOSPC;
@@ -940,11 +942,13 @@ static int bpf_prog_alloc_id(struct bpf_prog *prog)
{
int id;
+ idr_preload(GFP_KERNEL);
spin_lock_bh(&prog_idr_lock);
id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
if (id > 0)
prog->aux->id = id;
spin_unlock_bh(&prog_idr_lock);
+ idr_preload_end();
/* id is in [1, INT_MAX) */
if (WARN_ON_ONCE(!id))
--
2.9.5
^ permalink raw reply related
* Re: [PATCH v6 bpf-next 08/11] bpf: introduce BPF_RAW_TRACEPOINT
From: Steven Rostedt @ 2018-03-27 18:58 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: davem, daniel, torvalds, peterz, netdev, kernel-team, linux-api,
Mathieu Desnoyers, Kees Cook
In-Reply-To: <20180327131143.4b83534c@gandalf.local.home>
On Tue, 27 Mar 2018 13:11:43 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> On Tue, 27 Mar 2018 13:02:11 -0400
> Steven Rostedt <rostedt@goodmis.org> wrote:
>
> > Honestly, I think this is too much of a short cut and a hack. I know
> > you want to keep it "simple" and save space, but you really should do
> > it the same way ftrace and perf do it. That is, create a section and
> > have all tracepoints create a structure that holds a pointer to the
> > tracepoint and to the bpf probe function. Then you don't even need the
> > kernel_tracepoint_find_by_name(), you just iterate over your table and
> > you get the tracepoint and the bpf function associated to it.
>
> Also, if you do it the perf/ftrace way, you get support for module
> tracepoints pretty much for free. Which would include tracepoints in
> networking code that is loaded by a module.
This doesn't include module code (but that wouldn't be too hard to set
up), but I compiled and booted this. I didn't test if it works (I
didn't have the way to test bpf here). But this patch applies on top of
this patch (patch 8). You can remove patch 7 and fold this into this
patch. And then you can also make the __bpf_trace_* function static.
This would be much more robust and less error prone.
-- Steve
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..4fab7392e237 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -178,6 +178,15 @@
#define TRACE_SYSCALLS()
#endif
+#ifdef CONFIG_BPF_EVENTS
+#define BPF_RAW_TP() . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start__bpf_raw_tp) = .; \
+ KEEP(*(__bpf_raw_tp_map)) \
+ VMLINUX_SYMBOL(__stop__bpf_raw_tp) = .;
+#else
+#define BPF_RAW_TP()
+#endif
+
#ifdef CONFIG_SERIAL_EARLYCON
#define EARLYCON_TABLE() STRUCT_ALIGN(); \
VMLINUX_SYMBOL(__earlycon_table) = .; \
@@ -576,6 +585,7 @@
*(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS() \
+ BPF_RAW_TP() \
KPROBE_BLACKLIST() \
ERROR_INJECT_WHITELIST() \
MEM_DISCARD(init.rodata) \
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 399ebe6f90cf..fb4778c0a248 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -470,8 +470,9 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx);
int perf_event_attach_bpf_prog(struct perf_event *event, struct bpf_prog *prog);
void perf_event_detach_bpf_prog(struct perf_event *event);
int perf_event_query_prog_array(struct perf_event *event, void __user *info);
-int bpf_probe_register(struct tracepoint *tp, struct bpf_prog *prog);
-int bpf_probe_unregister(struct tracepoint *tp, struct bpf_prog *prog);
+int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog);
+int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog);
+struct bpf_raw_event_map *bpf_find_raw_tracepoint(const char *name);
#else
static inline unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
{
@@ -491,14 +492,18 @@ perf_event_query_prog_array(struct perf_event *event, void __user *info)
{
return -EOPNOTSUPP;
}
-static inline int bpf_probe_register(struct tracepoint *tp, struct bpf_prog *p)
+static inline int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *p)
{
return -EOPNOTSUPP;
}
-static inline int bpf_probe_unregister(struct tracepoint *tp, struct bpf_prog *p)
+static inline int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *p)
{
return -EOPNOTSUPP;
}
+static inline struct bpf_raw_event_map *bpf_find_raw_tracepoint(const char *name)
+{
+ return NULL;
+}
#endif
enum {
diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
index 39a283c61c51..35db8dd48c4c 100644
--- a/include/linux/tracepoint-defs.h
+++ b/include/linux/tracepoint-defs.h
@@ -36,4 +36,9 @@ struct tracepoint {
u32 num_args;
};
+struct bpf_raw_event_map {
+ struct tracepoint *tp;
+ void *bpf_func;
+};
+
#endif
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index f100c63ff19e..6037a2f0108a 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1312,7 +1312,7 @@ static int bpf_obj_get(const union bpf_attr *attr)
}
struct bpf_raw_tracepoint {
- struct tracepoint *tp;
+ struct bpf_raw_event_map *btp;
struct bpf_prog *prog;
};
@@ -1321,7 +1321,7 @@ static int bpf_raw_tracepoint_release(struct inode *inode, struct file *filp)
struct bpf_raw_tracepoint *raw_tp = filp->private_data;
if (raw_tp->prog) {
- bpf_probe_unregister(raw_tp->tp, raw_tp->prog);
+ bpf_probe_unregister(raw_tp->btp, raw_tp->prog);
bpf_prog_put(raw_tp->prog);
}
kfree(raw_tp);
@@ -1339,7 +1339,7 @@ static const struct file_operations bpf_raw_tp_fops = {
static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
{
struct bpf_raw_tracepoint *raw_tp;
- struct tracepoint *tp;
+ struct bpf_raw_event_map *btp;
struct bpf_prog *prog;
char tp_name[128];
int tp_fd, err;
@@ -1349,14 +1349,14 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
return -EFAULT;
tp_name[sizeof(tp_name) - 1] = 0;
- tp = kernel_tracepoint_find_by_name(tp_name);
- if (!tp)
+ btp = bpf_find_raw_tracepoint(tp_name);
+ if (!btp)
return -ENOENT;
raw_tp = kmalloc(sizeof(*raw_tp), GFP_USER | __GFP_ZERO);
if (!raw_tp)
return -ENOMEM;
- raw_tp->tp = tp;
+ raw_tp->btp = btp;
prog = bpf_prog_get_type(attr->raw_tracepoint.prog_fd,
BPF_PROG_TYPE_RAW_TRACEPOINT);
@@ -1365,7 +1365,7 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
goto out_free_tp;
}
- err = bpf_probe_register(raw_tp->tp, prog);
+ err = bpf_probe_register(raw_tp->btp, prog);
if (err)
goto out_put_prog;
@@ -1373,7 +1373,7 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
tp_fd = anon_inode_getfd("bpf-raw-tracepoint", &bpf_raw_tp_fops, raw_tp,
O_CLOEXEC);
if (tp_fd < 0) {
- bpf_probe_unregister(raw_tp->tp, prog);
+ bpf_probe_unregister(raw_tp->btp, prog);
err = tp_fd;
goto out_put_prog;
}
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index eb58ef156d36..e578b173fe1d 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -965,6 +965,19 @@ int perf_event_query_prog_array(struct perf_event *event, void __user *info)
return ret;
}
+extern struct bpf_raw_event_map *__start__bpf_raw_tp[];
+extern struct bpf_raw_event_map *__stop__bpf_raw_tp[];
+
+struct bpf_raw_event_map *bpf_find_raw_tracepoint(const char *name)
+{
+ struct bpf_raw_event_map* const *btp = __start__bpf_raw_tp;
+
+ for (; btp < __stop__bpf_raw_tp; btp++)
+ if (!strcmp((*btp)->tp->name, name))
+ return *btp;
+ return NULL;
+}
+
static __always_inline
void __bpf_trace_run(struct bpf_prog *prog, u64 *args)
{
@@ -1020,10 +1033,9 @@ BPF_TRACE_DEFN_x(10);
BPF_TRACE_DEFN_x(11);
BPF_TRACE_DEFN_x(12);
-static int __bpf_probe_register(struct tracepoint *tp, struct bpf_prog *prog)
+static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
{
- unsigned long addr;
- char buf[128];
+ struct tracepoint *tp = btp->tp;
/*
* check that program doesn't access arguments beyond what's
@@ -1032,43 +1044,25 @@ static int __bpf_probe_register(struct tracepoint *tp, struct bpf_prog *prog)
if (prog->aux->max_ctx_offset > tp->num_args * sizeof(u64))
return -EINVAL;
- snprintf(buf, sizeof(buf), "__bpf_trace_%s", tp->name);
- addr = kallsyms_lookup_name(buf);
- if (!addr)
- return -ENOENT;
-
- return tracepoint_probe_register(tp, (void *)addr, prog);
+ return tracepoint_probe_register(tp, (void *)btp->bpf_func, prog);
}
-int bpf_probe_register(struct tracepoint *tp, struct bpf_prog *prog)
+int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
{
int err;
mutex_lock(&bpf_event_mutex);
- err = __bpf_probe_register(tp, prog);
+ err = __bpf_probe_register(btp, prog);
mutex_unlock(&bpf_event_mutex);
return err;
}
-static int __bpf_probe_unregister(struct tracepoint *tp, struct bpf_prog *prog)
-{
- unsigned long addr;
- char buf[128];
-
- snprintf(buf, sizeof(buf), "__bpf_trace_%s", tp->name);
- addr = kallsyms_lookup_name(buf);
- if (!addr)
- return -ENOENT;
-
- return tracepoint_probe_unregister(tp, (void *)addr, prog);
-}
-
-int bpf_probe_unregister(struct tracepoint *tp, struct bpf_prog *prog)
+int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
{
int err;
mutex_lock(&bpf_event_mutex);
- err = __bpf_probe_unregister(tp, prog);
+ err = tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
mutex_unlock(&bpf_event_mutex);
return err;
}
^ permalink raw reply related
* Re: [PATCH net v2] udp6: set dst cache for a connected sk before udp_v6_send_skb
From: Martin KaFai Lau @ 2018-03-27 19:00 UTC (permalink / raw)
To: Alexey Kodanev; +Cc: netdev, Eric Dumazet, David Miller
In-Reply-To: <7d9ede59-3c29-4b09-eb2e-2650400a7d5c@oracle.com>
On Tue, Mar 27, 2018 at 04:27:30PM +0300, Alexey Kodanev wrote:
> On 26.03.2018 20:02, Martin KaFai Lau wrote:
> > On Mon, Mar 26, 2018 at 05:48:47PM +0300, Alexey Kodanev wrote:
> >> After commit 33c162a980fe ("ipv6: datagram: Update dst cache of a
> >> connected datagram sk during pmtu update"), when the error occurs on
> >> sending datagram in udpv6_sendmsg() due to ICMPV6_PKT_TOOBIG type,
> >> error handler can trigger the following path and call ip6_dst_store():
> >>
> >> udpv6_err()
> >> ip6_sk_update_pmtu()
> >> ip6_datagram_dst_update()
> >> ip6_dst_lookup_flow(), can create a RTF_CACHE clone
> > Instead of ip6_dst_lookup_flow(),
> > you meant the RTF_CACHE route created in ip6_update_pmtu()
> >
>
> Right, or even earlier... I was using vti tunnel and it invokes
> skb_dst_update_pmtu() on this error, then sends ICMPv6_PKT_TOOBIG.
>
> >> ...
> >> ip6_dst_store()
> >>
> >> It can happen before a connected UDP socket invokes ip6_dst_store()
> >> in the end of udpv6_sendmsg(), on destination release, as a result,
> >> the last one changes dst to the old one, preventing getting updated
> >> dst cache on the next udpv6_sendmsg() call.
> >>
> >> This patch moves ip6_dst_store() in udpv6_sendmsg(), so that it is
> >> invoked after ip6_sk_dst_lookup_flow() and before udp_v6_send_skb().
> > After this patch, the above udpv6_err() path could not happen after
> > ip6_sk_dst_lookup_flow() and before the ip6_dst_store() in udpv6_sendmsg()?
> >
>
> May be we could minimize this if save it in ip6_sk_dst_lookup_flow()
> for a connected UDP sockets only if we're not getting it from a cache
> for some reason?
I am just not clear how moving it earlier can completely stop the
described issue. Beside, the next ICMPV6_PKT_TOOBIG will be
received again and eventually rectify sk->sk_dst_cache?
>
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index a8a9195..0204f52 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -1115,13 +1115,30 @@ struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6,
> * error code.
> */
> struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
> - const struct in6_addr *final_dst)
> + const struct in6_addr *final_dst,
> + bool connected)
> {
> struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
>
> dst = ip6_sk_dst_check(sk, dst, fl6);
> - if (!dst)
> - dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
> + if (dst)
> + return dst;
> +
> + dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
> +
> + if (connected && !IS_ERR(dst))
> + ip6_dst_store(sk, dst_clone(dst), ...);
Right, I think doing dst_store() only if ip6_sk_dst_check()/
sk_dst_check() returns NULL is a more sensible thing to
do here.
>
> Thanks,
> Alexey
>
> >>
> >> Also, increase refcnt for dst, when passing it to ip6_dst_store()
> >> because after that the dst cache can be released by other calls
> >> to ip6_dst_store() with the same socket.
> >>
> >> Fixes: 33c162a980fe ("ipv6: datagram: Update dst cache of a connected datagram sk during pmtu update")
> >> Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
> >> ---
> >>
> >> v2: * remove 'release_dst:' label
> >>
> >> * move ip6_dst_store() below MSG_CONFIRM check as
> >> suggested by Eric and add dst_clone()
> >>
> >> * add 'Fixes' commit.
> >>
> >>
> >> net/ipv6/udp.c | 29 +++++++++++------------------
> >> 1 file changed, 11 insertions(+), 18 deletions(-)
> >>
> >> diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
> >> index 52e3ea0..4508e5a 100644
> >> --- a/net/ipv6/udp.c
> >> +++ b/net/ipv6/udp.c
> >> @@ -1303,6 +1303,16 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
> >> goto do_confirm;
> >> back_from_confirm:
> >>
> >> + if (connected)>> + ip6_dst_store(sk, dst_clone(dst),
> >> + ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ?
> >> + &sk->sk_v6_daddr : NULL,
> >> +#ifdef CONFIG_IPV6_SUBTREES
> >> + ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
> >> + &np->saddr :
> >> +#endif
> >> + NULL);
> >> +
> >> /* Lockless fast path for the non-corking case */
> >> if (!corkreq) {
> >> struct sk_buff *skb;
> >> @@ -1314,7 +1324,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
> >> err = PTR_ERR(skb);
> >> if (!IS_ERR_OR_NULL(skb))
> >> err = udp_v6_send_skb(skb, &fl6);
> >> - goto release_dst;
> >> + goto out;
> >> }
> >>
> >> lock_sock(sk);
> >> @@ -1348,23 +1358,6 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
> >> err = np->recverr ? net_xmit_errno(err) : 0;
> >> release_sock(sk);
> >>
> >> -release_dst:
> >> - if (dst) {
> >> - if (connected) {
> >> - ip6_dst_store(sk, dst,
> >> - ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ?
> >> - &sk->sk_v6_daddr : NULL,
> >> -#ifdef CONFIG_IPV6_SUBTREES
> >> - ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
> >> - &np->saddr :
> >> -#endif
> >> - NULL);
> >> - } else {
> >> - dst_release(dst);
> >> - }
> >> - dst = NULL;
> >> - }
> >> -
> >> out:
> >> dst_release(dst);
> >> fl6_sock_release(flowlabel);
> >> --
> >> 1.8.3.1
> >>
>
^ permalink raw reply
* Re: [PATCH v6 bpf-next 08/11] bpf: introduce BPF_RAW_TRACEPOINT
From: Steven Rostedt @ 2018-03-27 19:00 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: davem, daniel, torvalds, peterz, netdev, kernel-team, linux-api,
Mathieu Desnoyers, Kees Cook, Thomas Gleixner, Ingo Molnar
In-Reply-To: <f071b59d-5d67-0eb6-c5b1-68094b0a5118@fb.com>
On Tue, 27 Mar 2018 11:45:34 -0700
Alexei Starovoitov <ast@fb.com> wrote:
> >> +
> >> + snprintf(buf, sizeof(buf), "__bpf_trace_%s", tp->name);
> >> + addr = kallsyms_lookup_name(buf);
> >> + if (!addr)
> >> + return -ENOENT;
> >> +
> >> + return tracepoint_probe_register(tp, (void *)addr, prog);
> >
> > You are putting in a hell of a lot of trust with kallsyms returning
> > properly. I can see this being very fragile. This is calling a function
> > based on the result of kallsyms. I'm sure the security folks would love
> > this.
> >
> > There's a few things to make this a bit more robust. One is to add a
> > table that points to all __bpf_trace_* functions, and verify that the
> > result from kallsyms is in that table.
> >
> > Honestly, I think this is too much of a short cut and a hack. I know
> > you want to keep it "simple" and save space, but you really should do
> > it the same way ftrace and perf do it. That is, create a section and
> > have all tracepoints create a structure that holds a pointer to the
> > tracepoint and to the bpf probe function. Then you don't even need the
> > kernel_tracepoint_find_by_name(), you just iterate over your table and
> > you get the tracepoint and the bpf function associated to it.
> >
> > Relying on kallsyms to return an address to execute is just way too
> > extreme and fragile for my liking.
>
> Wasting extra 8bytes * number_of_tracepoints just for lack of trust
> in kallsyms doesn't sound like good trade off to me.
> If kallsyms are inaccurate all sorts of things will break:
> kprobes, livepatch, etc.
> I'd rather suggest for ftrace to use kallsyms approach as well
> and reduce memory footprint.
If Linus, Thomas, Peter, Ingo, and the security folks trust kallsyms to
return a valid function pointer from a name, then sure, we can try
going that way.
-- Steve
^ permalink raw reply
* Re: [PATCH v6 bpf-next 08/11] bpf: introduce BPF_RAW_TRACEPOINT
From: Steven Rostedt @ 2018-03-27 19:07 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: davem, daniel, torvalds, peterz, netdev, kernel-team, linux-api,
Mathieu Desnoyers, Kees Cook, Thomas Gleixner, Ingo Molnar
In-Reply-To: <20180327150041.3d86e16e@gandalf.local.home>
On Tue, 27 Mar 2018 15:00:41 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> > Wasting extra 8bytes * number_of_tracepoints just for lack of trust
> > in kallsyms doesn't sound like good trade off to me.
> > If kallsyms are inaccurate all sorts of things will break:
> > kprobes, livepatch, etc.
And if kallsyms breaks, these will break by failing to attach, or some
other benign error. Ftrace uses kallsyms to find functions too, but it
only enables functions based on the result, it doesn't use the result
for anything but to compare it to what it already knows.
This is a first that I know of to trust that kallsyms returns something
that you expect to execute with no other validation. It may be valid,
but it also makes me very nervous too. If others are fine with such an
approach, then OK, we can enter a new chapter of development where we
can use kallsyms to find the functions we want to call and use it.
-- Steve
^ permalink raw reply
* Re: [PATCH v6 bpf-next 08/11] bpf: introduce BPF_RAW_TRACEPOINT
From: Steven Rostedt @ 2018-03-27 19:10 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: davem, daniel, torvalds, peterz, netdev, kernel-team, linux-api,
Mathieu Desnoyers, Kees Cook, Thomas Gleixner, Ingo Molnar,
Andrew Morton
In-Reply-To: <20180327150041.3d86e16e@gandalf.local.home>
[ Added Andrew Morton too ]
On Tue, 27 Mar 2018 15:00:41 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> On Tue, 27 Mar 2018 11:45:34 -0700
> Alexei Starovoitov <ast@fb.com> wrote:
>
> > >> +
> > >> + snprintf(buf, sizeof(buf), "__bpf_trace_%s", tp->name);
> > >> + addr = kallsyms_lookup_name(buf);
> > >> + if (!addr)
> > >> + return -ENOENT;
> > >> +
> > >> + return tracepoint_probe_register(tp, (void *)addr, prog);
> > >
> > > You are putting in a hell of a lot of trust with kallsyms returning
> > > properly. I can see this being very fragile. This is calling a function
> > > based on the result of kallsyms. I'm sure the security folks would love
> > > this.
> > >
> > > There's a few things to make this a bit more robust. One is to add a
> > > table that points to all __bpf_trace_* functions, and verify that the
> > > result from kallsyms is in that table.
> > >
> > > Honestly, I think this is too much of a short cut and a hack. I know
> > > you want to keep it "simple" and save space, but you really should do
> > > it the same way ftrace and perf do it. That is, create a section and
> > > have all tracepoints create a structure that holds a pointer to the
> > > tracepoint and to the bpf probe function. Then you don't even need the
> > > kernel_tracepoint_find_by_name(), you just iterate over your table and
> > > you get the tracepoint and the bpf function associated to it.
> > >
> > > Relying on kallsyms to return an address to execute is just way too
> > > extreme and fragile for my liking.
> >
> > Wasting extra 8bytes * number_of_tracepoints just for lack of trust
> > in kallsyms doesn't sound like good trade off to me.
> > If kallsyms are inaccurate all sorts of things will break:
> > kprobes, livepatch, etc.
> > I'd rather suggest for ftrace to use kallsyms approach as well
> > and reduce memory footprint.
>
> If Linus, Thomas, Peter, Ingo, and the security folks trust kallsyms to
> return a valid function pointer from a name, then sure, we can try
> going that way.
I would like an ack from Linus and/or Andrew before we go further down
this road.
-- Steve
^ permalink raw reply
* Industrial routers with high?performance-price ratio and multiple functions
From: Linda @ 2018-03-27 1:41 UTC (permalink / raw)
To: netdev
Dear Sir or Madam,
If you're on the market for industrial routers, It will be glad to tell you that we can meet all of your requirements .
Our company name is Xiamen Ursalink Technology Co,We are the manufacturer specializing on designing and producing M2M/IoT hardware and solutions.
The features of our products£º
1. High-availability LTE/WCDMA/GSM connection
2. Automated fail-over between Ethernet and cellular (dual SIMs).
3. IPsec, OpenVPN, DMVPN, L2TP, GRE, PPTP for safety communication.
4. Ultra-reliable and secure data transmission via Gigabit Ethernet ports.
5. Fully integrated into Microsoft Auzure IoT eco-system, easily to be build an IoT solution.
6. Python & Ursalink SDK (Python 2.7/C) for secondary development.
7. Free 3-year warranty
8. No additional license fee (All-in-one system)
9. It can work as Modbus Master to send alerts by SMS.
10. It support TCP2COM protocol to integrate with SCADA system.
... ...
Such a high performance-price ratio, with multiple functions, and high security router is your best choice,isn¡¯t it?
To get more information£¬you can click here or visit www.ursalink.com .
More details will be available on receipt of your reply.
^ permalink raw reply
* Re: [PATCH v6 bpf-next 08/11] bpf: introduce BPF_RAW_TRACEPOINT
From: Mathieu Desnoyers @ 2018-03-27 19:10 UTC (permalink / raw)
To: rostedt
Cc: Alexei Starovoitov, David S. Miller, Daniel Borkmann,
Linus Torvalds, Peter Zijlstra, netdev, kernel-team, linux-api,
Kees Cook, Thomas Gleixner, Ingo Molnar
In-Reply-To: <20180327150041.3d86e16e@gandalf.local.home>
----- On Mar 27, 2018, at 3:00 PM, rostedt rostedt@goodmis.org wrote:
> On Tue, 27 Mar 2018 11:45:34 -0700
> Alexei Starovoitov <ast@fb.com> wrote:
>
>> >> +
>> >> + snprintf(buf, sizeof(buf), "__bpf_trace_%s", tp->name);
>> >> + addr = kallsyms_lookup_name(buf);
>> >> + if (!addr)
>> >> + return -ENOENT;
>> >> +
>> >> + return tracepoint_probe_register(tp, (void *)addr, prog);
>> >
>> > You are putting in a hell of a lot of trust with kallsyms returning
>> > properly. I can see this being very fragile. This is calling a function
>> > based on the result of kallsyms. I'm sure the security folks would love
>> > this.
>> >
>> > There's a few things to make this a bit more robust. One is to add a
>> > table that points to all __bpf_trace_* functions, and verify that the
>> > result from kallsyms is in that table.
>> >
>> > Honestly, I think this is too much of a short cut and a hack. I know
>> > you want to keep it "simple" and save space, but you really should do
>> > it the same way ftrace and perf do it. That is, create a section and
>> > have all tracepoints create a structure that holds a pointer to the
>> > tracepoint and to the bpf probe function. Then you don't even need the
>> > kernel_tracepoint_find_by_name(), you just iterate over your table and
>> > you get the tracepoint and the bpf function associated to it.
>> >
>> > Relying on kallsyms to return an address to execute is just way too
>> > extreme and fragile for my liking.
>>
>> Wasting extra 8bytes * number_of_tracepoints just for lack of trust
>> in kallsyms doesn't sound like good trade off to me.
>> If kallsyms are inaccurate all sorts of things will break:
>> kprobes, livepatch, etc.
>> I'd rather suggest for ftrace to use kallsyms approach as well
>> and reduce memory footprint.
>
> If Linus, Thomas, Peter, Ingo, and the security folks trust kallsyms to
> return a valid function pointer from a name, then sure, we can try
> going that way.
This will crash on ARM Thumb2 kernels. Also, how is this expected to
work on PowerPC ABIv1 without KALLSYMS_ALL ?
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
^ permalink raw reply
* Re: [net-next PATCH v2 03/10] net: netcp: ethss: make call to gbe_sgmii_config() conditional
From: Murali Karicheri @ 2018-03-27 19:20 UTC (permalink / raw)
To: Andrew Lunn
Cc: robh+dt, mark.rutland, ssantosh, malat, w-kwok2, devicetree,
linux-kernel, linux-arm-kernel, davem, netdev
In-Reply-To: <20180327171343.GN5862@lunn.ch>
On 03/27/2018 01:13 PM, Andrew Lunn wrote:
> On Tue, Mar 27, 2018 at 12:31:42PM -0400, Murali Karicheri wrote:
>> As a preparatory patch to add support for 2u cpsw hardware found on
>> K2G SoC, make call to gbe_sgmii_config() conditional. This is required
>> since 2u uses RGMII interface instead of SGMII and to allow for driver
>> re-use.
>>
>> Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
>> ---
>> drivers/net/ethernet/ti/netcp_ethss.c | 7 +++++--
>> 1 file changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
>> index 56dbc0b..1dea891 100644
>> --- a/drivers/net/ethernet/ti/netcp_ethss.c
>> +++ b/drivers/net/ethernet/ti/netcp_ethss.c
>> @@ -2271,7 +2271,8 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf)
>>
>> void (*hndlr)(struct net_device *) = gbe_adjust_link;
>>
>> - gbe_sgmii_config(priv, slave);
>> + if ((priv->ss_version == GBE_SS_VERSION_14) || IS_SS_ID_NU(priv))
>> + gbe_sgmii_config(priv, slave);
>
> Hi Murali
>
> So you have:
>
> #define IS_SS_ID_NU(d) \
> (GBE_IDENT((d)->ss_version) == GBE_SS_ID_NU)
>
>
> Does version 14 have a name? Could you add another IS_SS_ID_XX(d)
> macro for it? That would make these statements more consistent.
>
unfortunately not being the first version :)
Probably we can add
#define IS_SS_ID_VER_14(d) \
(GBE_IDENT((d)->ss_version) == GBE_SS_VERSION_14)
and replace all instances of (priv->ss_version == GBE_SS_VERSION_14) with
if (IS_SS_ID_VER_14(priv)) or equivalent.
> Andrew
>
--
Murali Karicheri
Linux Kernel, Keystone
^ permalink raw reply
* Re: [PATCH v2 bpf-next] bpf, tracing: unbreak lttng
From: Steven Rostedt @ 2018-03-27 19:35 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Alexei Starovoitov, davem, torvalds, peterz, mathieu.desnoyers,
netdev, kernel-team, linux-api
In-Reply-To: <1260578f-4a29-2c72-d81c-3f6e0588bbee@iogearbox.net>
On Tue, 27 Mar 2018 11:39:19 +0200
Daniel Borkmann <daniel@iogearbox.net> wrote:
> On 03/27/2018 02:07 AM, Steven Rostedt wrote:
> > On Mon, 26 Mar 2018 16:02:20 -0700
> > Alexei Starovoitov <ast@kernel.org> wrote:
> >
> >> for_each_kernel_tracepoint() is used by out-of-tree lttng module
> >> and therefore cannot be changed.
> >
> > This is false and misleading. NACK.
>
> Steven, while I really don't care about this particular function, you wrote
> a few emails ago, quote:
>
> Look, the tracepoint code was written by Mathieu for LTTng, and perf
> and ftrace were able to benefit because of it, as well as your bpf
> code. For this, we agreed to keep this function around for his use,
> as its the only thing he requires. Everyone has been fine with that.
> [...] Having that function for LTTng does not hurt us. And I will NACK
> removing it.
>
> So later saying that "this is false and misleading" is kind of misleading
> by itself. ;-) Anyway, it would probably make sense to add a comment to
> for_each_kernel_tracepoint() that this is used by LTTng so that people
> don't accidentally remove it due to missing in-tree user. I would think
> some sort of clarification/background in a comment or such would have
> avoided the whole confusion and resulting discussion around this in the
> first place.
I agree, a comment should be added. But the function can still be
modified, which is what I meant here by being misleading.
>
> Btw, in networking land, as soon as there is no in-tree user for a particular
> kernel function, it will get ripped out, no matter what. Given this is also
> the typical convention in the kernel, it may have caused some confusion with
> above preference.
This is usually the case with me too. This came from Mathieu doing a
lot of work to help perf and ftrace, but keep this for him to maintain
LTTng. This was the solution to a long drawn out flame war. Yes,
there's a lot of history behind that function, and I agree that we
should comment the history behind it.
>
> Anyway, given v6 is out now, I've tossed the old series from bpf-next tree.
> So I hope we can all move on with some more constructive discussion. :-)
Yes, which we are doing around the kallsyms part. ;-)
-- Steve
^ permalink raw reply
* Re: [net-next PATCH v2 03/10] net: netcp: ethss: make call to gbe_sgmii_config() conditional
From: Murali Karicheri @ 2018-03-27 19:39 UTC (permalink / raw)
To: Andrew Lunn
Cc: mark.rutland, devicetree, malat, netdev, linux-kernel, w-kwok2,
robh+dt, ssantosh, davem, linux-arm-kernel
In-Reply-To: <20180327171817.GO5862@lunn.ch>
On 03/27/2018 01:18 PM, Andrew Lunn wrote:
> On Tue, Mar 27, 2018 at 12:31:42PM -0400, Murali Karicheri wrote:
>> As a preparatory patch to add support for 2u cpsw hardware found on
>> K2G SoC, make call to gbe_sgmii_config() conditional. This is required
>> since 2u uses RGMII interface instead of SGMII and to allow for driver
>> re-use.
>>
>> Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
>> ---
>> drivers/net/ethernet/ti/netcp_ethss.c | 7 +++++--
>> 1 file changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
>> index 56dbc0b..1dea891 100644
>> --- a/drivers/net/ethernet/ti/netcp_ethss.c
>> +++ b/drivers/net/ethernet/ti/netcp_ethss.c
>> @@ -2271,7 +2271,8 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf)
>>
>> void (*hndlr)(struct net_device *) = gbe_adjust_link;
>>
>> - gbe_sgmii_config(priv, slave);
>> + if ((priv->ss_version == GBE_SS_VERSION_14) || IS_SS_ID_NU(priv))
>> + gbe_sgmii_config(priv, slave);
>
> Or maybe:
>
> if (slave->phy_node == PHY_INTERFACE_MODE_SGMII)
> gbe_sgmii_config(priv, slave);
Yeah. Based on my response to your other comment, this would become
if ((slave->link_interface == SGMII_LINK_MAC_PHY) &&
(IS_SS_ID_VER_14(priv) || IS_SS_ID_NU(priv)))
gbe_sgmii_config(priv, slave);
We can't solely depends on phy_mode here. Phy interface is one of several
interface possible. There is MAC_TO_MAC_FORCED, NO_MDIO etc. So we check the
link_interface above.
If we can agree, here is what will appear in v3
1) Add another patch to do conversion of priv->ss_version == GBE_SS_VERSION_14 check
with a macro, IS_SS_ID_VER_14
2) modify this patch as above.
Murali
>
> Andrew
>
--
Murali Karicheri
Linux Kernel, Keystone
^ permalink raw reply
* [PATCH net-next 0/3] net: Broadcom drivers coalescing fixes
From: Florian Fainelli @ 2018-03-27 19:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, davem, jaedon.shin, pgynther, opendmb,
Michael Chan, gospo, talgi, saeedm
Hi all,
Following Tal's review of the adaptive RX/TX coalescing feature added to the
SYSTEMPORT and GENET driver a number of things showed up:
- adaptive TX coalescing is not actually a good idea with the current way
the estimator will program the ring, this results in a higher CPU load, NAPI
on TX already does a reasonably good job at maintaining the interrupt count low
- both SYSTEMPORT and GENET would suffer from the same issues while configuring
coalescing parameters where the values would just not be applied correctly
based on user settings, so we fix that too
Tal, thanks again for your feedback, I would appreciate if you could review that
the new behavior appears to be implemented correctly.
Thanks!
Florian Fainelli (3):
net: systemport: Remove adaptive TX coalescing
net: systemport: Fix coalescing settings handling
net: bcmgenet: Fix coalescing settings handling
drivers/net/ethernet/broadcom/bcmsysport.c | 118 ++++++++++---------------
drivers/net/ethernet/broadcom/bcmsysport.h | 5 +-
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 78 +++++++++++-----
drivers/net/ethernet/broadcom/genet/bcmgenet.h | 4 +-
4 files changed, 106 insertions(+), 99 deletions(-)
--
2.14.1
^ permalink raw reply
* [PATCH net-next 1/3] net: systemport: Remove adaptive TX coalescing
From: Florian Fainelli @ 2018-03-27 19:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, davem, jaedon.shin, pgynther, opendmb,
Michael Chan, gospo, talgi, saeedm
In-Reply-To: <20180327194707.31857-1-f.fainelli@gmail.com>
Adaptive TX coalescing is not currently giving us any advantages and
ends up making the CPU spin more frequently until TX completion. Deny
and disable adaptive TX coalescing for now and rely on static
configuration, we can always add it back later.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/bcmsysport.c | 61 ++++--------------------------
drivers/net/ethernet/broadcom/bcmsysport.h | 1 -
2 files changed, 8 insertions(+), 54 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 4e26f606a7f2..1e52bb7d822e 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
-#include <linux/net_dim.h>
#include <linux/etherdevice.h>
#include <linux/platform_device.h>
#include <linux/of.h>
@@ -588,7 +587,8 @@ static void bcm_sysport_set_rx_coalesce(struct bcm_sysport_priv *priv)
rdma_writel(priv, reg, RDMA_MBDONE_INTR);
}
-static void bcm_sysport_set_tx_coalesce(struct bcm_sysport_tx_ring *ring)
+static void bcm_sysport_set_tx_coalesce(struct bcm_sysport_tx_ring *ring,
+ struct ethtool_coalesce *ec)
{
struct bcm_sysport_priv *priv = ring->priv;
u32 reg;
@@ -596,8 +596,8 @@ static void bcm_sysport_set_tx_coalesce(struct bcm_sysport_tx_ring *ring)
reg = tdma_readl(priv, TDMA_DESC_RING_INTR_CONTROL(ring->index));
reg &= ~(RING_INTR_THRESH_MASK |
RING_TIMEOUT_MASK << RING_TIMEOUT_SHIFT);
- reg |= ring->dim.coal_pkts;
- reg |= DIV_ROUND_UP(ring->dim.coal_usecs * 1000, 8192) <<
+ reg |= ec->tx_max_coalesced_frames;
+ reg |= DIV_ROUND_UP(ec->tx_coalesce_usecs * 1000, 8192) <<
RING_TIMEOUT_SHIFT;
tdma_writel(priv, reg, TDMA_DESC_RING_INTR_CONTROL(ring->index));
}
@@ -606,18 +606,12 @@ static int bcm_sysport_get_coalesce(struct net_device *dev,
struct ethtool_coalesce *ec)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
- struct bcm_sysport_tx_ring *ring;
- unsigned int i;
u32 reg;
reg = tdma_readl(priv, TDMA_DESC_RING_INTR_CONTROL(0));
ec->tx_coalesce_usecs = (reg >> RING_TIMEOUT_SHIFT) * 8192 / 1000;
ec->tx_max_coalesced_frames = reg & RING_INTR_THRESH_MASK;
- for (i = 0; i < dev->num_tx_queues; i++) {
- ring = &priv->tx_rings[i];
- ec->use_adaptive_tx_coalesce |= ring->dim.use_dim;
- }
reg = rdma_readl(priv, RDMA_MBDONE_INTR);
@@ -632,7 +626,6 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
struct ethtool_coalesce *ec)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
- struct bcm_sysport_tx_ring *ring;
unsigned int i;
/* Base system clock is 125Mhz, DMA timeout is this reference clock
@@ -646,20 +639,12 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
return -EINVAL;
if ((ec->tx_coalesce_usecs == 0 && ec->tx_max_coalesced_frames == 0) ||
- (ec->rx_coalesce_usecs == 0 && ec->rx_max_coalesced_frames == 0))
+ (ec->rx_coalesce_usecs == 0 && ec->rx_max_coalesced_frames == 0) ||
+ ec->use_adaptive_tx_coalesce)
return -EINVAL;
- for (i = 0; i < dev->num_tx_queues; i++) {
- ring = &priv->tx_rings[i];
- ring->dim.coal_pkts = ec->tx_max_coalesced_frames;
- ring->dim.coal_usecs = ec->tx_coalesce_usecs;
- if (!ec->use_adaptive_tx_coalesce && ring->dim.use_dim) {
- ring->dim.coal_pkts = 1;
- ring->dim.coal_usecs = 0;
- }
- ring->dim.use_dim = ec->use_adaptive_tx_coalesce;
- bcm_sysport_set_tx_coalesce(ring);
- }
+ for (i = 0; i < dev->num_tx_queues; i++)
+ bcm_sysport_set_tx_coalesce(&priv->tx_rings[i], ec);
priv->dim.coal_usecs = ec->rx_coalesce_usecs;
priv->dim.coal_pkts = ec->rx_max_coalesced_frames;
@@ -940,8 +925,6 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
ring->packets += pkts_compl;
ring->bytes += bytes_compl;
u64_stats_update_end(&priv->syncp);
- ring->dim.packets = pkts_compl;
- ring->dim.bytes = bytes_compl;
ring->c_index = c_index;
@@ -987,7 +970,6 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
{
struct bcm_sysport_tx_ring *ring =
container_of(napi, struct bcm_sysport_tx_ring, napi);
- struct net_dim_sample dim_sample;
unsigned int work_done = 0;
work_done = bcm_sysport_tx_reclaim(ring->priv, ring);
@@ -1004,12 +986,6 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
return 0;
}
- if (ring->dim.use_dim) {
- net_dim_sample(ring->dim.event_ctr, ring->dim.packets,
- ring->dim.bytes, &dim_sample);
- net_dim(&ring->dim.dim, dim_sample);
- }
-
return budget;
}
@@ -1089,23 +1065,6 @@ static void bcm_sysport_dim_work(struct work_struct *work)
dim->state = NET_DIM_START_MEASURE;
}
-static void bcm_sysport_dim_tx_work(struct work_struct *work)
-{
- struct net_dim *dim = container_of(work, struct net_dim, work);
- struct bcm_sysport_net_dim *ndim =
- container_of(dim, struct bcm_sysport_net_dim, dim);
- struct bcm_sysport_tx_ring *ring =
- container_of(ndim, struct bcm_sysport_tx_ring, dim);
- struct net_dim_cq_moder cur_profile =
- net_dim_get_profile(dim->mode, dim->profile_ix);
-
- ring->dim.coal_usecs = cur_profile.usec;
- ring->dim.coal_pkts = cur_profile.pkts;
-
- bcm_sysport_set_tx_coalesce(ring);
- dim->state = NET_DIM_START_MEASURE;
-}
-
/* RX and misc interrupt routine */
static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
{
@@ -1152,7 +1111,6 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
continue;
txr = &priv->tx_rings[ring];
- txr->dim.event_ctr++;
if (likely(napi_schedule_prep(&txr->napi))) {
intrl2_0_mask_set(priv, ring_bit);
@@ -1185,7 +1143,6 @@ static irqreturn_t bcm_sysport_tx_isr(int irq, void *dev_id)
continue;
txr = &priv->tx_rings[ring];
- txr->dim.event_ctr++;
if (likely(napi_schedule_prep(&txr->napi))) {
intrl2_1_mask_set(priv, BIT(ring));
@@ -1551,7 +1508,6 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
reg |= (1 << index);
tdma_writel(priv, reg, TDMA_TIER1_ARB_0_QUEUE_EN);
- bcm_sysport_init_dim(&ring->dim, bcm_sysport_dim_tx_work);
napi_enable(&ring->napi);
netif_dbg(priv, hw, priv->netdev,
@@ -1582,7 +1538,6 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
return;
napi_disable(&ring->napi);
- cancel_work_sync(&ring->dim.dim.work);
netif_napi_del(&ring->napi);
bcm_sysport_tx_clean(priv, ring);
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index e1c97d4a82b4..57e18ef8f206 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -723,7 +723,6 @@ struct bcm_sysport_tx_ring {
struct bcm_sysport_priv *priv; /* private context backpointer */
unsigned long packets; /* packets statistics */
unsigned long bytes; /* bytes statistics */
- struct bcm_sysport_net_dim dim; /* Net DIM context */
unsigned int switch_queue; /* switch port queue number */
unsigned int switch_port; /* switch port queue number */
bool inspect; /* inspect switch port and queue */
--
2.14.1
^ permalink raw reply related
* [PATCH net-next 2/3] net: systemport: Fix coalescing settings handling
From: Florian Fainelli @ 2018-03-27 19:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, davem, jaedon.shin, pgynther, opendmb,
Michael Chan, gospo, talgi, saeedm
In-Reply-To: <20180327194707.31857-1-f.fainelli@gmail.com>
There were a number of issues with setting the RX coalescing parameters:
- we would not be preserving values that would have been configured
across close/open calls, instead we would always reset to no timeout
and 1 interrupt per packet, this would also prevent DIM from setting its
default usec/pkts values
- when adaptive RX would be turned on, we woud not be fetching the
default parameters, we would stay with no timeout/1 packet per
interrupt until the estimator kicks in and changes that
- finally disabling adaptive RX coalescing while providing parameters
would not be honored, and we would stay with whatever DIM had
previously determined instead of the user requested parameters
Fixes: b6e0e875421e ("net: systemport: Implement adaptive interrupt coalescing")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/bcmsysport.c | 57 ++++++++++++++++++++----------
drivers/net/ethernet/broadcom/bcmsysport.h | 4 +--
2 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 1e52bb7d822e..43ad6300c351 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -574,16 +574,16 @@ static int bcm_sysport_set_wol(struct net_device *dev,
return 0;
}
-static void bcm_sysport_set_rx_coalesce(struct bcm_sysport_priv *priv)
+static void bcm_sysport_set_rx_coalesce(struct bcm_sysport_priv *priv,
+ u32 usecs, u32 pkts)
{
u32 reg;
reg = rdma_readl(priv, RDMA_MBDONE_INTR);
reg &= ~(RDMA_INTR_THRESH_MASK |
RDMA_TIMEOUT_MASK << RDMA_TIMEOUT_SHIFT);
- reg |= priv->dim.coal_pkts;
- reg |= DIV_ROUND_UP(priv->dim.coal_usecs * 1000, 8192) <<
- RDMA_TIMEOUT_SHIFT;
+ reg |= pkts;
+ reg |= DIV_ROUND_UP(usecs * 1000, 8192) << RDMA_TIMEOUT_SHIFT;
rdma_writel(priv, reg, RDMA_MBDONE_INTR);
}
@@ -626,6 +626,8 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
struct ethtool_coalesce *ec)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
+ struct net_dim_cq_moder moder;
+ u32 usecs, pkts;
unsigned int i;
/* Base system clock is 125Mhz, DMA timeout is this reference clock
@@ -646,15 +648,22 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
for (i = 0; i < dev->num_tx_queues; i++)
bcm_sysport_set_tx_coalesce(&priv->tx_rings[i], ec);
- priv->dim.coal_usecs = ec->rx_coalesce_usecs;
- priv->dim.coal_pkts = ec->rx_max_coalesced_frames;
+ priv->rx_coalesce_usecs = ec->rx_coalesce_usecs;
+ priv->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
+ usecs = priv->rx_coalesce_usecs;
+ pkts = priv->rx_max_coalesced_frames;
- if (!ec->use_adaptive_rx_coalesce && priv->dim.use_dim) {
- priv->dim.coal_pkts = 1;
- priv->dim.coal_usecs = 0;
+ /* If DIM is enabled, immediately obtain default parameters */
+ if (ec->use_adaptive_rx_coalesce) {
+ moder = net_dim_get_def_profile(priv->dim.dim.mode);
+ usecs = moder.usec;
+ pkts = moder.pkts;
}
+
priv->dim.use_dim = ec->use_adaptive_rx_coalesce;
- bcm_sysport_set_rx_coalesce(priv);
+
+ /* Apply desired coalescing parameters */
+ bcm_sysport_set_rx_coalesce(priv, usecs, pkts);
return 0;
}
@@ -1058,10 +1067,7 @@ static void bcm_sysport_dim_work(struct work_struct *work)
struct net_dim_cq_moder cur_profile =
net_dim_get_profile(dim->mode, dim->profile_ix);
- priv->dim.coal_usecs = cur_profile.usec;
- priv->dim.coal_pkts = cur_profile.pkts;
-
- bcm_sysport_set_rx_coalesce(priv);
+ bcm_sysport_set_rx_coalesce(priv, cur_profile.usec, cur_profile.pkts);
dim->state = NET_DIM_START_MEASURE;
}
@@ -1408,14 +1414,30 @@ static void bcm_sysport_adj_link(struct net_device *dev)
phy_print_status(phydev);
}
-static void bcm_sysport_init_dim(struct bcm_sysport_net_dim *dim,
+static void bcm_sysport_init_dim(struct bcm_sysport_priv *priv,
void (*cb)(struct work_struct *work))
{
+ struct bcm_sysport_net_dim *dim = &priv->dim;
+ struct net_dim_cq_moder moder;
+ u32 usecs, pkts;
+
INIT_WORK(&dim->dim.work, cb);
dim->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
dim->event_ctr = 0;
dim->packets = 0;
dim->bytes = 0;
+
+ usecs = priv->rx_coalesce_usecs;
+ pkts = priv->rx_max_coalesced_frames;
+
+ /* If DIM was enabled, re-apply default parameters */
+ if (dim->use_dim) {
+ moder = net_dim_get_def_profile(dim->dim.mode);
+ usecs = moder.usec;
+ pkts = moder.pkts;
+ }
+
+ bcm_sysport_set_rx_coalesce(priv, usecs, pkts);
}
static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
@@ -1658,8 +1680,6 @@ static int bcm_sysport_init_rx_ring(struct bcm_sysport_priv *priv)
rdma_writel(priv, 0, RDMA_END_ADDR_HI);
rdma_writel(priv, priv->num_rx_desc_words - 1, RDMA_END_ADDR_LO);
- rdma_writel(priv, 1, RDMA_MBDONE_INTR);
-
netif_dbg(priv, hw, priv->netdev,
"RDMA cfg, num_rx_bds=%d, rx_bds=%p\n",
priv->num_rx_bds, priv->rx_bds);
@@ -1827,7 +1847,7 @@ static void bcm_sysport_netif_start(struct net_device *dev)
struct bcm_sysport_priv *priv = netdev_priv(dev);
/* Enable NAPI */
- bcm_sysport_init_dim(&priv->dim, bcm_sysport_dim_work);
+ bcm_sysport_init_dim(priv, bcm_sysport_dim_work);
napi_enable(&priv->napi);
/* Enable RX interrupt and TX ring full interrupt */
@@ -2333,6 +2353,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
/* libphy will adjust the link state accordingly */
netif_carrier_off(dev);
+ priv->rx_max_coalesced_frames = 1;
u64_stats_init(&priv->syncp);
priv->dsa_notifier.notifier_call = bcm_sysport_dsa_notifier;
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index 57e18ef8f206..d6e5d0cbf3a3 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -701,8 +701,6 @@ struct bcm_sysport_net_dim {
u16 event_ctr;
unsigned long packets;
unsigned long bytes;
- u32 coal_usecs;
- u32 coal_pkts;
struct net_dim dim;
};
@@ -755,6 +753,8 @@ struct bcm_sysport_priv {
unsigned int rx_c_index;
struct bcm_sysport_net_dim dim;
+ u32 rx_max_coalesced_frames;
+ u32 rx_coalesce_usecs;
/* PHY device */
struct device_node *phy_dn;
--
2.14.1
^ permalink raw reply related
* [PATCH net-next 3/3] net: bcmgenet: Fix coalescing settings handling
From: Florian Fainelli @ 2018-03-27 19:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, davem, jaedon.shin, pgynther, opendmb,
Michael Chan, gospo, talgi, saeedm
In-Reply-To: <20180327194707.31857-1-f.fainelli@gmail.com>
There were a number of issues with setting the RX coalescing parameters:
- we would not be preserving values that would have been configured
across close/open calls, instead we would always reset to no timeout
and 1 interrupt per packet, this would also prevent DIM from setting its
default usec/pkts values
- when adaptive RX would be turned on, we woud not be fetching the
default parameters, we would stay with no timeout/1 packet per interrupt
until the estimator kicks in and changes that
- finally disabling adaptive RX coalescing while providing parameters
would not be honored, and we would stay with whatever DIM had previously
determined instead of the user requested parameters
Fixes: 9f4ca05827a2 ("net: bcmgenet: Add support for adaptive RX coalescing")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 78 ++++++++++++++++++--------
drivers/net/ethernet/broadcom/genet/bcmgenet.h | 4 +-
2 files changed, 57 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 7db8edc643ec..76409debb796 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -625,18 +625,18 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
return 0;
}
-static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring)
+static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring,
+ u32 usecs, u32 pkts)
{
struct bcmgenet_priv *priv = ring->priv;
unsigned int i = ring->index;
u32 reg;
- bcmgenet_rdma_ring_writel(priv, i, ring->dim.coal_pkts,
- DMA_MBUF_DONE_THRESH);
+ bcmgenet_rdma_ring_writel(priv, i, pkts, DMA_MBUF_DONE_THRESH);
reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
reg &= ~DMA_TIMEOUT_MASK;
- reg |= DIV_ROUND_UP(ring->dim.coal_usecs * 1000, 8192);
+ reg |= DIV_ROUND_UP(usecs * 1000, 8192);
bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
}
@@ -645,6 +645,8 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
{
struct bcmgenet_priv *priv = netdev_priv(dev);
struct bcmgenet_rx_ring *ring;
+ struct net_dim_cq_moder moder;
+ u32 usecs, pkts;
unsigned int i;
/* Base system clock is 125Mhz, DMA timeout is this reference clock
@@ -682,25 +684,37 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
for (i = 0; i < priv->hw_params->rx_queues; i++) {
ring = &priv->rx_rings[i];
- ring->dim.coal_usecs = ec->rx_coalesce_usecs;
- ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
- if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
- ring->dim.coal_pkts = 1;
- ring->dim.coal_usecs = 0;
+
+ ring->rx_coalesce_usecs = ec->rx_coalesce_usecs;
+ ring->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
+ usecs = ring->rx_coalesce_usecs;
+ pkts = ring->rx_max_coalesced_frames;
+
+ if (ec->use_adaptive_rx_coalesce) {
+ moder = net_dim_get_def_profile(ring->dim.dim.mode);
+ usecs = moder.usec;
+ pkts = moder.pkts;
}
+
ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
- bcmgenet_set_rx_coalesce(ring);
+ bcmgenet_set_rx_coalesce(ring, usecs, pkts);
}
ring = &priv->rx_rings[DESC_INDEX];
- ring->dim.coal_usecs = ec->rx_coalesce_usecs;
- ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
- if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
- ring->dim.coal_pkts = 1;
- ring->dim.coal_usecs = 0;
+
+ ring->rx_coalesce_usecs = ec->rx_coalesce_usecs;
+ ring->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
+ usecs = ring->rx_coalesce_usecs;
+ pkts = ring->rx_max_coalesced_frames;
+
+ if (ec->use_adaptive_rx_coalesce) {
+ moder = net_dim_get_def_profile(ring->dim.dim.mode);
+ usecs = moder.usec;
+ pkts = moder.pkts;
}
+
ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
- bcmgenet_set_rx_coalesce(ring);
+ bcmgenet_set_rx_coalesce(ring, usecs, pkts);
return 0;
}
@@ -1924,10 +1938,7 @@ static void bcmgenet_dim_work(struct work_struct *work)
struct net_dim_cq_moder cur_profile =
net_dim_get_profile(dim->mode, dim->profile_ix);
- ring->dim.coal_usecs = cur_profile.usec;
- ring->dim.coal_pkts = cur_profile.pkts;
-
- bcmgenet_set_rx_coalesce(ring);
+ bcmgenet_set_rx_coalesce(ring, cur_profile.usec, cur_profile.pkts);
dim->state = NET_DIM_START_MEASURE;
}
@@ -2079,14 +2090,30 @@ static void init_umac(struct bcmgenet_priv *priv)
dev_dbg(kdev, "done init umac\n");
}
-static void bcmgenet_init_dim(struct bcmgenet_net_dim *dim,
+static void bcmgenet_init_dim(struct bcmgenet_rx_ring *ring,
void (*cb)(struct work_struct *work))
{
+ struct bcmgenet_net_dim *dim = &ring->dim;
+ struct net_dim_cq_moder moder;
+ u32 usecs, pkts;
+
INIT_WORK(&dim->dim.work, cb);
dim->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
dim->event_ctr = 0;
dim->packets = 0;
dim->bytes = 0;
+
+ usecs = ring->rx_coalesce_usecs;
+ pkts = ring->rx_max_coalesced_frames;
+
+ /* If DIM was enabled, re-apply default parameters */
+ if (dim->use_dim) {
+ moder = net_dim_get_def_profile(dim->dim.mode);
+ usecs = moder.usec;
+ pkts = moder.pkts;
+ }
+
+ bcmgenet_set_rx_coalesce(ring, usecs, pkts);
}
/* Initialize a Tx ring along with corresponding hardware registers */
@@ -2178,7 +2205,7 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
if (ret)
return ret;
- bcmgenet_init_dim(&ring->dim, bcmgenet_dim_work);
+ bcmgenet_init_dim(ring, bcmgenet_dim_work);
/* Initialize Rx NAPI */
netif_napi_add(priv->dev, &ring->napi, bcmgenet_rx_poll,
@@ -2186,7 +2213,6 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_PROD_INDEX);
bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);
- bcmgenet_rdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
bcmgenet_rdma_ring_writel(priv, index,
((size << DMA_RING_SIZE_SHIFT) |
RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
@@ -3424,6 +3450,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
struct net_device *dev;
const void *macaddr;
struct resource *r;
+ unsigned int i;
int err = -EIO;
const char *phy_mode_str;
@@ -3552,6 +3579,11 @@ static int bcmgenet_probe(struct platform_device *pdev)
netif_set_real_num_tx_queues(priv->dev, priv->hw_params->tx_queues + 1);
netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
+ /* Set default coalescing parameters */
+ for (i = 0; i < priv->hw_params->rx_queues; i++)
+ priv->rx_rings[i].rx_max_coalesced_frames = 1;
+ priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
+
/* libphy will determine the link state */
netif_carrier_off(dev);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 22c41e0430fb..b773bc07edf7 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -578,8 +578,6 @@ struct bcmgenet_net_dim {
u16 event_ctr;
unsigned long packets;
unsigned long bytes;
- u32 coal_usecs;
- u32 coal_pkts;
struct net_dim dim;
};
@@ -598,6 +596,8 @@ struct bcmgenet_rx_ring {
unsigned int end_ptr; /* Rx ring end CB ptr */
unsigned int old_discards;
struct bcmgenet_net_dim dim;
+ u32 rx_max_coalesced_frames;
+ u32 rx_coalesce_usecs;
void (*int_enable)(struct bcmgenet_rx_ring *);
void (*int_disable)(struct bcmgenet_rx_ring *);
struct bcmgenet_priv *priv;
--
2.14.1
^ permalink raw reply related
* Re: possible deadlock in rtnl_lock (5)
From: Julian Anastasov @ 2018-03-27 19:52 UTC (permalink / raw)
To: Florian Westphal; +Cc: syzbot, netdev, lvs-devel, syzkaller-bugs
In-Reply-To: <20180327115001.GC26275@breakpoint.cc>
Hello,
On Tue, 27 Mar 2018, Florian Westphal wrote:
> syzbot <syzbot+a46d6abf9d56b1365a72@syzkaller.appspotmail.com> wrote:
> [ cc Julian and trimming cc list ]
>
> > syzkaller688027/4497 is trying to acquire lock:
> > (rtnl_mutex){+.+.}, at: [<00000000bb14d7fb>] rtnl_lock+0x17/0x20
> > net/core/rtnetlink.c:74
>
> > but task is already holding lock:
> > IPVS: stopping backup sync thread 4495 ...
> > (rtnl_mutex){+.+.}, at: [<00000000bb14d7fb>] rtnl_lock+0x17/0x20
> > net/core/rtnetlink.c:74
> >
> > other info that might help us debug this:
> > Possible unsafe locking scenario:
> >
> > CPU0
> > ----
> > lock(rtnl_mutex);
> > lock(rtnl_mutex);
> >
> > *** DEADLOCK ***
> >
> > May be due to missing lock nesting notation
>
> Looks like this is real, commit e0b26cc997d57305b4097711e12e13992580ae34
> ("ipvs: call rtnl_lock early") added rtnl_lock when starting sync thread
> but socket close invokes rtnl_lock too:
I see, thanks! I'll have to move the locks into
start_sync_thread and to split make_{send,receive}_sock
to {make,setup}_{send,receive}_sock ...
> > stack backtrace:
> > rtnl_lock+0x17/0x20 net/core/rtnetlink.c:74
> > ip_mc_drop_socket+0x88/0x230 net/ipv4/igmp.c:2643
> > inet_release+0x4e/0x1c0 net/ipv4/af_inet.c:413
> > sock_release+0x8d/0x1e0 net/socket.c:595
> > start_sync_thread+0x2213/0x2b70 net/netfilter/ipvs/ip_vs_sync.c:1924
> > do_ip_vs_set_ctl+0x1139/0x1cc0 net/netfilter/ipvs/ip_vs_ctl.c:2389
Regards
^ permalink raw reply
* Re: RFC on writel and writel_relaxed
From: Arnd Bergmann @ 2018-03-27 19:54 UTC (permalink / raw)
To: Alexander Duyck
Cc: Will Deacon, Sinan Kaya, Benjamin Herrenschmidt, Jason Gunthorpe,
David Laight, Oliver,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
linux-rdma@vger.kernel.org, Alexander Duyck, Paul E. McKenney,
netdev@vger.kernel.org, Linus Torvalds
In-Reply-To: <CAKgT0Uem6HT-Z=HBnSVcC4rnDL0yFyXEbr+FN3YYkJ=ExZpUPQ@mail.gmail.com>
On Tue, Mar 27, 2018 at 8:54 PM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Tue, Mar 27, 2018 at 8:10 AM, Will Deacon <will.deacon@arm.com> wrote:
>>>
>>> Sinan
>>> "We are being told that if you use writel(), then you don't need a wmb() on
>>> all architectures."
>>>
>>> Alex:
>>> "I'm not sure who told you that but that is incorrect, at least for
>>> x86. If you attempt to use writel() without the wmb() we will have to
>>> NAK the patches. We will accept the wmb() with writel_releaxed() since
>>> that solves things for ARM."
>>>
>>> > Jason is seeking behavior clarification for write combined buffers.
>>>
>>> Alex:
>>> "Don't bother. I can tell you right now that for x86 you have to have a
>>> wmb() before the writel().
>>
>> To clarify: are you saying that on x86 you need a wmb() prior to a writel
>> if you want that writel to be ordered after prior writes to memory? Is this
>> specific to WC memory or some other non-standard attribute?
>
> Note, I am not a CPU guy so this is just my interpretation. It is my
> understanding that the wmb(), aka sfence, is needed on x86 to sort out
> writes between Write-back(WB) system memory and Strong Uncacheable
> (UC) MMIO accesses.
>
> I was hoping to be able to cite something in the software developers
> manual (https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf),
> but that tends to be pretty vague. I have re-read section 22.34
> (volume 3B) several times and I am still not clear on if it says we
> need the sfence or not. It is a matter of figuring out what the impact
> of store buffers and caching are for WB versus UC memory.
Here is what I found regarding the store buffer in that document:
11.10 STORE BUFFER
Intel 64 and IA-32 processors temporarily store each write (store) to
memory in a store buffer. The store buffer
improves processor performance by allowing the processor to continue
executing instructions without having to
wait until a write to memory and/or to a cache is complete. It also
allows writes to be delayed for more efficient use
of memory-access bus cycles.
In general, the existence of the store buffer is transparent to
software, even in systems that use multiple processors.
The processor ensures that write operations are always carried out in
program order. It also insures that the
contents of the store buffer are always drained to memory in the
following situations:
• When an exception or interrupt is generated.
• (P6 and more recent processor families only) When a serializing
instruction is executed.
• When an I/O instruction is executed.
• When a LOCK operation is performed.
• (P6 and more recent processor families only) When a BINIT operation
is performed.
• (Pentium III, and more recent processor families only) When using an
SFENCE instruction to order stores.
• (Pentium 4 and more recent processor families only) When using an
MFENCE instruction to order stores.
The discussion of write ordering in Section 8.2, “Memory Ordering,”
gives a detailed description of the operation of
the store buffer.
Arnd
^ permalink raw reply
* HI
From: Lucy Boston @ 2018-03-27 20:39 UTC (permalink / raw)
--
Greeting, once again is me Lucy Boston this is twice am contacting you
please is very urgent respond to me for more details through my.
Email:
dr.lucyboston@gmail.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox