Linux userland API discussions
 help / color / mirror / Atom feed
* Re: [PATCH] pci_regs: reintroduce PCI_MSIX_FLAGS_BIRMASK
From: Michael S. Tsirkin @ 2015-07-13 16:32 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rajat Jain,
	Chen, Gong, Guenter Roeck, Rafał Miłecki,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CAErSpo4cbj58VheRbQOJ3XnyBn_SvmUi9ZyFhRnPWhf8ciJ7jg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Mon, Jul 13, 2015 at 10:49:02AM -0500, Bjorn Helgaas wrote:
> On Mon, Jul 13, 2015 at 10:11 AM, Michael S. Tsirkin <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > On Wed, Jul 01, 2015 at 12:14:10PM +0200, Michael S. Tsirkin wrote:
> >> This partially reverts commit 09a2c73ddfc7f173237fc7209a65b34dd5bcb5ed.
> >>     PCI: Remove unused PCI_MSIX_FLAGS_BIRMASK definition
> >>
> >> That commit dropped a symbol from an exported header claiming "no one
> >> uses it". This isn't how Linux normally approaches userspace API though,
> >> and in fact QEMU build fails if trying to use updated headers from linux
> >> 3.12 and up.
> >>
> >> Sure, userspace can be fixed to use the new symbol, but the cost
> >> of keeping the old one around is fairly low, too.
> >>
> >> Signed-off-by: Michael S. Tsirkin <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> >
> > Ping. Can this be included upstream please?
> 
> Yes, I plan to merge it, and I'll mark it for stable.  This looks like
> a complete revert of 09a2c73ddfc7, not a partial revert.  Am I missing
> something?

Only that I redefine PCI_MSIX_FLAGS_BIRMASK in terms of PCI_MSIX_PBA_BIR
so that there's no duplication.

> 09a2c73ddfc7 appeared in v3.13 (not v3.12), so it wouldn't ordinarily
> be post-merge window material.  But it seems pretty safe, so I might
> put it in for v4.2 instead of waiting for v4.3.
> 
> >> ---
> >>  include/uapi/linux/pci_regs.h | 1 +
> >>  1 file changed, 1 insertion(+)
> >>
> >> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> >> index efe3443..66644ac 100644
> >> --- a/include/uapi/linux/pci_regs.h
> >> +++ b/include/uapi/linux/pci_regs.h
> >> @@ -319,6 +319,7 @@
> >>  #define PCI_MSIX_PBA         8       /* Pending Bit Array offset */
> >>  #define  PCI_MSIX_PBA_BIR    0x00000007 /* BAR index */
> >>  #define  PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */
> >> +#define  PCI_MSIX_FLAGS_BIRMASK      PCI_MSIX_PBA_BIR /* deprecated */
> >>  #define PCI_CAP_MSIX_SIZEOF  12      /* size of MSIX registers */
> >>
> >>  /* MSI-X Table entry format */
> >> --
> >> MST

^ permalink raw reply

* Re: [PATCH v7 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
From: Philipp Zabel @ 2015-07-13 16:50 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Greg Kroah-Hartman, stefan.wahren-eS4NqCHxEME,
	devicetree-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	linux-api-u79uwXL29TY76Z2rM5mHXA, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w, Mark Brown,
	Kumar Gala, mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, wxt-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <1436521486-10682-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hi Srinivas,

Am Freitag, den 10.07.2015, 10:44 +0100 schrieb Srinivas Kandagatla:
> This patch adds just providers part of the framework just to enable easy
> review.
[...]
> +/**
> + * nvmem_register() - Register a nvmem device for given nvmem_config.
> + * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
> + *
> + * @config: nvmem device configuration with which nvmem device is created.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to nvmem_device.
> + */
> +
> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
> +{
[...]
> +	nvmem->read_only = nvmem->dev.of_node ?
> +				of_property_read_bool(nvmem->dev.of_node,
> +				"read-only") :
> +				config->read_only;

I think read_only should be set if any of the device node property or
nvmem_config->read_only request it. That way, even if the nvmem is
theoretically writeable (no read-only property in DT), the driver still
can make it read-only if writing isn't implemented:

+	nvmem->read_only = nvmem->dev.of_node ?
+				of_property_read_bool(nvmem->dev.of_node,
+				"read-only") : 0;
+	nvmem->read_only |= config->read_only;

[...]
> new file mode 100644
> index 0000000..f589d3b
> --- /dev/null
> +++ b/include/linux/nvmem-provider.h
[...]
> +struct nvmem_config {
> +	struct device		*dev;
> +	const char		*name;
> +	int			id;
> +	struct module		*owner;
> +	struct nvmem_cell_info	*cells;

Should that be const?

> +	int			ncells;
> +	bool			read_only;
> +};
> +
> +#if IS_ENABLED(CONFIG_NVMEM)
> +
> +struct nvmem_device *nvmem_register(struct nvmem_config *cfg);

Then that could be made const, too.

best regards
Philipp

^ permalink raw reply

* Re: [PATCH 0/5] coresight: Support context-ID tracing when PID namespace is enabled
From: Mathieu Poirier @ 2015-07-13 17:26 UTC (permalink / raw)
  To: Chunyan Zhang
  Cc: Greg KH, Mark Brown, Serge Broslavsky, Lyra Zhang,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1436258518-9339-1-git-send-email-zhang.chunyan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On 7 July 2015 at 02:41, Chunyan Zhang <zhang.chunyan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> The Coresight ETM drivers already support context-ID tracing, but it won't
> work when PID namespace is enabled. This is because when using PID
> namespace a process id (ie. VPID) seen from the current namespace differs
> from the id (ie. PID) seen by kernel.
>
> This patch-set does add a translation between VPID and PID.
>
> Chunyan Zhang (5):
>   coresight-etm3x: Change the name of the ctxid_val to ctxid_pid
>   coresight-etm4x: Change the name of the ctxid_val to ctxid_pid
>   Coresight: Add an interface for supporting ETM3/4 Context ID tracing
>   coresight-etm3x: Support context-ID tracing when PID namespace is
>     enabled
>   coresight-etm4x: Support context-ID tracing when PID namespace is
>     enabled
>
>  .../ABI/testing/sysfs-bus-coresight-devices-etm3x  |  2 +-
>  .../ABI/testing/sysfs-bus-coresight-devices-etm4x  |  2 +-
>  drivers/hwtracing/coresight/coresight-etm.h        |  7 ++--
>  drivers/hwtracing/coresight/coresight-etm3x.c      | 28 +++++++++-------
>  drivers/hwtracing/coresight/coresight-etm4x.c      | 37 ++++++++++++++--------
>  drivers/hwtracing/coresight/coresight-etm4x.h      |  7 ++--
>  include/linux/coresight.h                          | 20 ++++++++++++
>  7 files changed, 72 insertions(+), 31 deletions(-)
>
> --
> 1.9.1
>

Applied - thanks.

^ permalink raw reply

* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Mathieu Desnoyers @ 2015-07-13 17:36 UTC (permalink / raw)
  To: Ben Maurer
  Cc: Paul Turner, Andrew Hunter, Peter Zijlstra, Ingo Molnar, rostedt,
	Paul E. McKenney, Josh Triplett, Lai Jiangshan, Linus Torvalds,
	Andrew Morton, linux-api, libc-alpha-9JcytcrH/bA+uJoB2kUjGw
In-Reply-To: <5CDDBDF2D36D9F43B9F5E99003F6A0D48D5F39C6-f8hGUhss0nh9TZdEUguypQ2O0Ztt9esIQQ4Iyu8u01E@public.gmane.org>

----- On Jul 13, 2015, at 7:17 AM, Ben Maurer bmaurer-b10kYP2dOMg@public.gmane.org wrote:

> At Facebook we already use getcpu in folly, our base C++ library, to provide
> high performance concurrency algorithms. Folly includes an abstraction called
> AccessSpreader which helps engineers write abstractions which shard themselves
> across different cores to prevent cache contention
> (https://github.com/facebook/folly/blob/master/folly/detail/CacheLocality.cpp).
> We have used this primative to create faster reader writer locks
> (https://github.com/facebook/folly/blob/master/folly/SharedMutex.h), as well as
> in an abstraction that powers workqueues
> (https://github.com/facebook/folly/blob/master/folly/IndexedMemPool.h). This
> would be a great perf improvement for these types of abstractions and probably
> encourage us to use the idea more widely.
> 
> One quick comment on the approach -- it'd be really great if we had a method
> that didn't require users to register each thread. This can often lead to
> requiring an additional branch in critical code to check if the appropriate
> caches have been initialized. Also, one of the most interesting potential
> applications of the restartable sequences concept is in malloc. having a brief
> period at the beginning of the life of a thread where malloc didn't work would
> be pretty tricky to program around.

If we invoke this per-thread registration directly in the glibc NPTL implementation,
in start_thread, do you think it would fit your requirements ?

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply

* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Andy Lutomirski @ 2015-07-13 18:36 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Ben Maurer, Paul E. McKenney, Ingo Molnar, linux-api,
	Andrew Morton, Josh Triplett, Lai Jiangshan, rostedt, Paul Turner,
	Andrew Hunter, Peter Zijlstra, Linus Torvalds
In-Reply-To: <1050138282.1065.1436801252018.JavaMail.zimbra-vg+e7yoeK/dWk0Htik3J/w@public.gmane.org>

On Jul 13, 2015 9:27 AM, "Mathieu Desnoyers"
<mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w@public.gmane.org> wrote:
>
> ----- On Jul 12, 2015, at 11:38 PM, Andy Lutomirski luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org wrote:
>
> > On Jul 12, 2015 12:06 PM, "Mathieu Desnoyers"
> > <mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w@public.gmane.org> wrote:
> >>
> >> Expose a new system call allowing threads to register a userspace memory
> >> area where to store the current CPU number. Scheduler migration sets the
> >> TIF_NOTIFY_RESUME flag on the current thread. Upon return to user-space,
> >> a notify-resume handler updates the current CPU value within that
> >> user-space memory area.
> >>
> >> This getcpu cache is an alternative to the sched_getcpu() vdso which has
> >> a few benefits:
> >> - It is faster to do a memory read that to call a vDSO,
> >> - This cache value can be read from within an inline assembly, which
> >>   makes it a useful building block for restartable sequences.
> >>
> >
> > Let's wait and see what the final percpu atomic solution is.  If it
> > involves percpu segments, then this is unnecessary.
>
> percpu segments will likely not solve everything. I have a use-case
> with dynamically allocated per-cpu ring buffer in user-space (lttng-ust)
> which can be a challenge for percpu segments. Having a fast getcpu()
> is a win in those cases.
>

Even so, percpu segments will give you fast getcpu without introducing
a new scheduler hook.

> >
> > Also, this will need to be rebased onto -tip, and that should wait
> > until the big exit rewrite is farther along.
>
> I don't really care which thread flag it ends up using, and this is
> more or less an internal implementation detail. The important part is
> the ABI exposed to user-space, and it's good to start the discussion
> on this aspect early.
>

Agreed.

> >
> >> This approach is inspired by Paul Turner and Andrew Hunter's work
> >> on percpu atomics, which lets the kernel handle restart of critical
> >> sections:
> >> Ref.:
> >> * https://lkml.org/lkml/2015/6/24/665
> >> * https://lwn.net/Articles/650333/
> >> *
> >> http://www.linuxplumbersconf.org/2013/ocw/system/presentations/1695/original/LPC%20-%20PerCpu%20Atomics.pdf
> >>
> >> Benchmarking sched_getcpu() vs tls cache approach. Getting the
> >> current CPU number:
> >>
> >> - With Linux vdso:            12.7 ns
> >
> > This is a bit unfair, because the glibc wrapper sucks and the
> > __vdso_getcpu interface is overcomplicated.  We can fix it with a
> > better API.  It won't make it *that* much faster, though.
>
> Even if we improve the vDSO function, we are at a point where just
> the function call is not that cheap.
>

True, and the LSL isn't likely to go away.  The branches can go, though.

--Andy

^ permalink raw reply

* Re: [PATCH v7 0/9] Add simple NVMEM Framework via regmap.
From: Stefan Wahren @ 2015-07-13 18:54 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w, Mark Brown,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ
In-Reply-To: <1436521427-10568-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hi Srinivas,

[add Ezequiel Garcia to CC]

> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 10. Juli 2015 um
> 11:43 geschrieben:
>
>
> Hi Greg,
>
> This patchset adds a new simple NVMEM framework to kernel, and it is tested
> with various drivers like "QCOM thermal sensors", "QCOM cpr driver",
> "begal bone cape manager" and few more on the way.
>
> Thankyou all for providing inputs and comments on previous versions of this
> patchset. Here is the v7 of the patchset addressing all the issues raised as
> part of previous versions review.
>
> Up until now, NVMEM drivers like eeprom were stored in drivers/misc, where
> they
> all had to duplicate pretty much the same code to register a sysfs file, allow
> in-kernel users to access the content of the devices they were driving, etc.
> This was also a problem as far as other in-kernel users were involved, since
> the solutions used were pretty much different from on driver to another, there
> was a rather big abstraction leak.

i only want to mention that there are more places of NVMEM drivers like:

drivers/mfd/ab3100-otp.c
drivers/soc/tegra/fuse/*.c

>
> Introduction of this framework aims at solving this. It also introduces DT
> representation for consumer devices to go get the data they require (MAC
> Addresses, SoC/Revision ID, part numbers, and so on) from the NVMEMs.
>
> After learning few things about QCOM qfprom and other eeprom/efuses, which
> has packed fields at bit level. Which makes it important to add support to
> such memories. This version adds support to this type of non volatile
> memories by adding support to bit level nvmem-cells.
>
> Having regmap interface to this framework would give much better
> abstraction for nvmems on different buses.
>
> patch 1-4 Introduces the NVMEM framework.
> Patch 5-6 Adds Qualcomm specific qfprom driver.
> Patch 7 migrates an existing driver to nvmem framework.
> Patch 8 adds entry in MAINTAINERS.
>
> Its also possible to migrate other nvmem drivers to this framework, and I
> think
> some of them already posted patches based on this framework.
>
> Providers APIs:
> nvmem_register/unregister();

How do i get the cell info from the devicetree into the nvmem_config?

I expected a function something like of_nvmem_cell_info_get() in the Providers
API.

>
> Consumers APIs:
> Cell based apis for both DT/Non-DT:
> nvmem_cell_get()/nvmem_cell_put();
> devm_nvmem_cell_get()/devm_nvmem_cell_put();
> of_nvmem_cell_get()
> nvmem_cell_read()/nvmem_cell_write();
>
> Raw byte access apis for both DT/non-DT.
> nvmem_device_get()/nvmem_device_put()
> devm_nvmem_device_get()/nvmem_device_put()
> of_nvmem_device_get()
>
> nvmem_device_read()/nvmem_device_write();
> nvmem_device_cell_read()/nvmem_device_cell_write();
>
> Device Tree:
>
> /* Provider */
> qfprom: qfprom@00700000 {
> ...
>
> /* Data cells */
> tsens_calibration: calib@404 {
> reg = <0x404 0x10>;
> };
>
> tsens_calibration_bckp: calib_bckp@504 {
> reg = <0x504 0x11>;
> bit-offset = 6;
> nbits = 128;
> };
>
> pvs_version: pvs-version@6 {
> reg = <0x6 0x2>
> bit-offset = 7;
> nbits = 2;
> };
>
> speed_bin: speed-bin@c{
> reg = <0xc 0x1>;
> bit-offset = 2;
> nbits = 3;
>
> };
> ...
> };
> /* Consumer */
> tsens {
> ...
> nvmem-cells = <&tsens_calibration>;
> nvmem-cell-names = "calibration";
> };
>
> userspace interface: binary file in /sys/bus/nvmem/devices/*/nvmem
>
> ex:
> hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
>
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> ...
> *
> 0001000

Since we're entering userspace the behavior should be clear.

How do we treat register gaps? Fill them with zero?

Best regards
Stefan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH -mm v7 5/6] proc: add kpageidle file
From: Andres Lagar-Cavilla @ 2015-07-13 19:02 UTC (permalink / raw)
  To: Vladimir Davydov
  Cc: Andrew Morton, Minchan Kim, Raghavendra K T, Johannes Weiner,
	Michal Hocko, Greg Thelen, Michel Lespinasse, David Rientjes,
	Pavel Emelyanov, Cyrill Gorcunov, Jonathan Corbet, linux-api,
	linux-doc, linux-mm, cgroups, linux-kernel
In-Reply-To: <25f235220bef9d799f48a060d7638a5de31fc994.1436623799.git.vdavydov@parallels.com>

On Sat, Jul 11, 2015 at 7:48 AM, Vladimir Davydov
<vdavydov@parallels.com> wrote:
> Knowing the portion of memory that is not used by a certain application
> or memory cgroup (idle memory) can be useful for partitioning the system
> efficiently, e.g. by setting memory cgroup limits appropriately.
> Currently, the only means to estimate the amount of idle memory provided
> by the kernel is /proc/PID/{clear_refs,smaps}: the user can clear the
> access bit for all pages mapped to a particular process by writing 1 to
> clear_refs, wait for some time, and then count smaps:Referenced.
> However, this method has two serious shortcomings:
>
>  - it does not count unmapped file pages
>  - it affects the reclaimer logic
>
> To overcome these drawbacks, this patch introduces two new page flags,
> Idle and Young, and a new proc file, /proc/kpageidle. A page's Idle flag
> can only be set from userspace by setting bit in /proc/kpageidle at the
> offset corresponding to the page, and it is cleared whenever the page is
> accessed either through page tables (it is cleared in page_referenced()
> in this case) or using the read(2) system call (mark_page_accessed()).
> Thus by setting the Idle flag for pages of a particular workload, which
> can be found e.g. by reading /proc/PID/pagemap, waiting for some time to
> let the workload access its working set, and then reading the kpageidle
> file, one can estimate the amount of pages that are not used by the
> workload.
>
> The Young page flag is used to avoid interference with the memory
> reclaimer. A page's Young flag is set whenever the Access bit of a page
> table entry pointing to the page is cleared by writing to kpageidle. If
> page_referenced() is called on a Young page, it will add 1 to its return
> value, therefore concealing the fact that the Access bit was cleared.
>
> Note, since there is no room for extra page flags on 32 bit, this
> feature uses extended page flags when compiled on 32 bit.
>
> Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>

Thanks for the updates, addressing THP and TLB flushing, very
elegantly. Some quick early reaction. I may come back for more :)

> ---
>  Documentation/vm/pagemap.txt |  12 ++-
>  fs/proc/page.c               | 222 +++++++++++++++++++++++++++++++++++++++++++
>  fs/proc/task_mmu.c           |   4 +-
>  include/linux/mm.h           |  98 +++++++++++++++++++
>  include/linux/page-flags.h   |  11 +++
>  include/linux/page_ext.h     |   4 +
>  mm/Kconfig                   |  12 +++
>  mm/debug.c                   |   4 +
>  mm/huge_memory.c             |   5 +
>  mm/page_ext.c                |   3 +
>  mm/rmap.c                    |   5 +
>  mm/swap.c                    |   2 +
>  12 files changed, 380 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/vm/pagemap.txt b/Documentation/vm/pagemap.txt
> index a9b7afc8fbc6..c9266340852c 100644
> --- a/Documentation/vm/pagemap.txt
> +++ b/Documentation/vm/pagemap.txt
> @@ -5,7 +5,7 @@ pagemap is a new (as of 2.6.25) set of interfaces in the kernel that allow
>  userspace programs to examine the page tables and related information by
>  reading files in /proc.
>
> -There are four components to pagemap:
> +There are five components to pagemap:
>
>   * /proc/pid/pagemap.  This file lets a userspace process find out which
>     physical frame each virtual page is mapped to.  It contains one 64-bit
> @@ -69,6 +69,16 @@ There are four components to pagemap:
>     memory cgroup each page is charged to, indexed by PFN. Only available when
>     CONFIG_MEMCG is set.
>
> + * /proc/kpageidle.  This file implements a bitmap where each bit corresponds
> +   to a page, indexed by PFN. When the bit is set, the corresponding page is
> +   idle. A page is considered idle if it has not been accessed since it was
> +   marked idle. To mark a page idle one should set the bit corresponding to the
> +   page by writing to the file. A value written to the file is OR-ed with the
> +   current bitmap value. Only user memory pages can be marked idle, for other
> +   page types input is silently ignored. Writing to this file beyond max PFN
> +   results in the ENXIO error. Only available when CONFIG_IDLE_PAGE_TRACKING is
> +   set.
> +
>  Short descriptions to the page flags:
>
>   0. LOCKED
> diff --git a/fs/proc/page.c b/fs/proc/page.c
> index 70d23245dd43..e51690c5f173 100644
> --- a/fs/proc/page.c
> +++ b/fs/proc/page.c
> @@ -5,6 +5,7 @@
>  #include <linux/ksm.h>
>  #include <linux/mm.h>
>  #include <linux/mmzone.h>
> +#include <linux/rmap.h>
>  #include <linux/huge_mm.h>
>  #include <linux/proc_fs.h>
>  #include <linux/seq_file.h>
> @@ -16,6 +17,7 @@
>
>  #define KPMSIZE sizeof(u64)
>  #define KPMMASK (KPMSIZE - 1)
> +#define KPMBITS (KPMSIZE * BITS_PER_BYTE)
>
>  /* /proc/kpagecount - an array exposing page counts
>   *
> @@ -275,6 +277,222 @@ static const struct file_operations proc_kpagecgroup_operations = {
>  };
>  #endif /* CONFIG_MEMCG */
>
> +#ifdef CONFIG_IDLE_PAGE_TRACKING
> +/*
> + * Idle page tracking only considers user memory pages, for other types of
> + * pages the idle flag is always unset and an attempt to set it is silently
> + * ignored.
> + *
> + * We treat a page as a user memory page if it is on an LRU list, because it is
> + * always safe to pass such a page to rmap_walk(), which is essential for idle
> + * page tracking. With such an indicator of user pages we can skip isolated
> + * pages, but since there are not usually many of them, it will hardly affect
> + * the overall result.
> + *
> + * This function tries to get a user memory page by pfn as described above.
> + */
> +static struct page *kpageidle_get_page(unsigned long pfn)
> +{
> +       struct page *page;
> +       struct zone *zone;
> +
> +       if (!pfn_valid(pfn))
> +               return NULL;
> +
> +       page = pfn_to_page(pfn);
> +       if (!page || PageTail(page) || !PageLRU(page) ||
> +           !get_page_unless_zero(page))

get_page_unless_zero does not succeed for Tail pages.

> +               return NULL;
> +
> +       if (unlikely(PageTail(page))) {
> +               put_page(page);
> +               return NULL;
> +       }
> +
> +       zone = page_zone(page);
> +       spin_lock_irq(&zone->lru_lock);
> +       if (unlikely(!PageLRU(page))) {
> +               put_page(page);
> +               page = NULL;
> +       }
> +       spin_unlock_irq(&zone->lru_lock);
> +       return page;
> +}
> +
> +static int kpageidle_clear_pte_refs_one(struct page *page,
> +                                       struct vm_area_struct *vma,
> +                                       unsigned long addr, void *arg)
> +{
> +       struct mm_struct *mm = vma->vm_mm;
> +       spinlock_t *ptl;
> +       pmd_t *pmd;
> +       pte_t *pte;
> +       bool referenced = false;
> +
> +       if (unlikely(PageTransHuge(page))) {

VM_BUG_ON(!PageHead)?

> +               pmd = page_check_address_pmd(page, mm, addr,
> +                                            PAGE_CHECK_ADDRESS_PMD_FLAG, &ptl);
> +               if (pmd) {
> +                       referenced = pmdp_test_and_clear_young(vma, addr, pmd);

For any workload using MMU notifiers, this will lose significant
information by not querying the secondary PTE. The most
straightforward case is KVM. Once mappings are setup, all access
activity is recorded through shadow PTEs. This interface will say
"idle" even though the VM is blasting memory.

Andres


> +                       spin_unlock(ptl);
> +               }
> +       } else {
> +               pte = page_check_address(page, mm, addr, &ptl, 0);
> +               if (pte) {
> +                       referenced = ptep_test_and_clear_young(vma, addr, pte);
> +                       pte_unmap_unlock(pte, ptl);
> +               }
> +       }
> +       if (referenced) {
> +               clear_page_idle(page);
> +               /*
> +                * We cleared the referenced bit in a mapping to this page. To
> +                * avoid interference with page reclaim, mark it young so that
> +                * page_referenced() will return > 0.
> +                */
> +               set_page_young(page);
> +       }
> +       return SWAP_AGAIN;
> +}
> +
> +static void kpageidle_clear_pte_refs(struct page *page)
> +{
> +       struct rmap_walk_control rwc = {
> +               .rmap_one = kpageidle_clear_pte_refs_one,
> +               .anon_lock = page_lock_anon_vma_read,
> +       };
> +       bool need_lock;
> +
> +       if (!page_mapped(page) ||
> +           !page_rmapping(page))
> +               return;
> +
> +       need_lock = !PageAnon(page) || PageKsm(page);
> +       if (need_lock && !trylock_page(page))
> +               return;
> +
> +       rmap_walk(page, &rwc);
> +
> +       if (need_lock)
> +               unlock_page(page);
> +}
> +
> +static ssize_t kpageidle_read(struct file *file, char __user *buf,
> +                             size_t count, loff_t *ppos)
> +{
> +       u64 __user *out = (u64 __user *)buf;
> +       struct page *page;
> +       unsigned long pfn, end_pfn;
> +       ssize_t ret = 0;
> +       u64 idle_bitmap = 0;
> +       int bit;
> +
> +       if (*ppos & KPMMASK || count & KPMMASK)
> +               return -EINVAL;
> +
> +       pfn = *ppos * BITS_PER_BYTE;
> +       if (pfn >= max_pfn)
> +               return 0;
> +
> +       end_pfn = pfn + count * BITS_PER_BYTE;
> +       if (end_pfn > max_pfn)
> +               end_pfn = ALIGN(max_pfn, KPMBITS);
> +
> +       for (; pfn < end_pfn; pfn++) {
> +               bit = pfn % KPMBITS;
> +               page = kpageidle_get_page(pfn);
> +               if (page) {
> +                       if (page_is_idle(page)) {
> +                               /*
> +                                * The page might have been referenced via a
> +                                * pte, in which case it is not idle. Clear
> +                                * refs and recheck.
> +                                */
> +                               kpageidle_clear_pte_refs(page);
> +                               if (page_is_idle(page))
> +                                       idle_bitmap |= 1ULL << bit;
> +                       }
> +                       put_page(page);
> +               }
> +               if (bit == KPMBITS - 1) {
> +                       if (put_user(idle_bitmap, out)) {
> +                               ret = -EFAULT;
> +                               break;
> +                       }
> +                       idle_bitmap = 0;
> +                       out++;
> +               }
> +       }
> +
> +       *ppos += (char __user *)out - buf;
> +       if (!ret)
> +               ret = (char __user *)out - buf;
> +       return ret;
> +}
> +
> +static ssize_t kpageidle_write(struct file *file, const char __user *buf,
> +                              size_t count, loff_t *ppos)
> +{
> +       const u64 __user *in = (const u64 __user *)buf;
> +       struct page *page;
> +       unsigned long pfn, end_pfn;
> +       ssize_t ret = 0;
> +       u64 idle_bitmap = 0;
> +       int bit;
> +
> +       if (*ppos & KPMMASK || count & KPMMASK)
> +               return -EINVAL;
> +
> +       pfn = *ppos * BITS_PER_BYTE;
> +       if (pfn >= max_pfn)
> +               return -ENXIO;
> +
> +       end_pfn = pfn + count * BITS_PER_BYTE;
> +       if (end_pfn > max_pfn)
> +               end_pfn = ALIGN(max_pfn, KPMBITS);
> +
> +       for (; pfn < end_pfn; pfn++) {
> +               bit = pfn % KPMBITS;
> +               if (bit == 0) {
> +                       if (get_user(idle_bitmap, in)) {
> +                               ret = -EFAULT;
> +                               break;
> +                       }
> +                       in++;
> +               }
> +               if (idle_bitmap >> bit & 1) {
> +                       page = kpageidle_get_page(pfn);
> +                       if (page) {
> +                               kpageidle_clear_pte_refs(page);
> +                               set_page_idle(page);
> +                               put_page(page);
> +                       }
> +               }
> +       }
> +
> +       *ppos += (const char __user *)in - buf;
> +       if (!ret)
> +               ret = (const char __user *)in - buf;
> +       return ret;
> +}
> +
> +static const struct file_operations proc_kpageidle_operations = {
> +       .llseek = mem_lseek,
> +       .read = kpageidle_read,
> +       .write = kpageidle_write,
> +};
> +
> +#ifndef CONFIG_64BIT
> +static bool need_page_idle(void)
> +{
> +       return true;
> +}
> +struct page_ext_operations page_idle_ops = {
> +       .need = need_page_idle,
> +};
> +#endif
> +#endif /* CONFIG_IDLE_PAGE_TRACKING */
> +
>  static int __init proc_page_init(void)
>  {
>         proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
> @@ -282,6 +500,10 @@ static int __init proc_page_init(void)
>  #ifdef CONFIG_MEMCG
>         proc_create("kpagecgroup", S_IRUSR, NULL, &proc_kpagecgroup_operations);
>  #endif
> +#ifdef CONFIG_IDLE_PAGE_TRACKING
> +       proc_create("kpageidle", S_IRUSR | S_IWUSR, NULL,
> +                   &proc_kpageidle_operations);
> +#endif
>         return 0;
>  }
>  fs_initcall(proc_page_init);
> diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> index 3b4d8255e806..3efd7f641f92 100644
> --- a/fs/proc/task_mmu.c
> +++ b/fs/proc/task_mmu.c
> @@ -458,7 +458,7 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
>
>         mss->resident += size;
>         /* Accumulate the size in pages that have been accessed. */
> -       if (young || PageReferenced(page))
> +       if (young || page_is_young(page) || PageReferenced(page))
>                 mss->referenced += size;
>         mapcount = page_mapcount(page);
>         if (mapcount >= 2) {
> @@ -810,6 +810,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
>
>                 /* Clear accessed and referenced bits. */
>                 pmdp_test_and_clear_young(vma, addr, pmd);
> +               test_and_clear_page_young(page);
>                 ClearPageReferenced(page);
>  out:
>                 spin_unlock(ptl);
> @@ -837,6 +838,7 @@ out:
>
>                 /* Clear accessed and referenced bits. */
>                 ptep_test_and_clear_young(vma, addr, pte);
> +               test_and_clear_page_young(page);
>                 ClearPageReferenced(page);
>         }
>         pte_unmap_unlock(pte - 1, ptl);
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 7f471789781a..de450c1191b9 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2205,5 +2205,103 @@ void __init setup_nr_node_ids(void);
>  static inline void setup_nr_node_ids(void) {}
>  #endif
>
> +#ifdef CONFIG_IDLE_PAGE_TRACKING
> +#ifdef CONFIG_64BIT
> +static inline bool page_is_young(struct page *page)
> +{
> +       return PageYoung(page);
> +}
> +
> +static inline void set_page_young(struct page *page)
> +{
> +       SetPageYoung(page);
> +}
> +
> +static inline bool test_and_clear_page_young(struct page *page)
> +{
> +       return TestClearPageYoung(page);
> +}
> +
> +static inline bool page_is_idle(struct page *page)
> +{
> +       return PageIdle(page);
> +}
> +
> +static inline void set_page_idle(struct page *page)
> +{
> +       SetPageIdle(page);
> +}
> +
> +static inline void clear_page_idle(struct page *page)
> +{
> +       ClearPageIdle(page);
> +}
> +#else /* !CONFIG_64BIT */
> +/*
> + * If there is not enough space to store Idle and Young bits in page flags, use
> + * page ext flags instead.
> + */
> +extern struct page_ext_operations page_idle_ops;
> +
> +static inline bool page_is_young(struct page *page)
> +{
> +       return test_bit(PAGE_EXT_YOUNG, &lookup_page_ext(page)->flags);
> +}
> +
> +static inline void set_page_young(struct page *page)
> +{
> +       set_bit(PAGE_EXT_YOUNG, &lookup_page_ext(page)->flags);
> +}
> +
> +static inline bool test_and_clear_page_young(struct page *page)
> +{
> +       return test_and_clear_bit(PAGE_EXT_YOUNG,
> +                                 &lookup_page_ext(page)->flags);
> +}
> +
> +static inline bool page_is_idle(struct page *page)
> +{
> +       return test_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags);
> +}
> +
> +static inline void set_page_idle(struct page *page)
> +{
> +       set_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags);
> +}
> +
> +static inline void clear_page_idle(struct page *page)
> +{
> +       clear_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags);
> +}
> +#endif /* CONFIG_64BIT */
> +#else /* !CONFIG_IDLE_PAGE_TRACKING */
> +static inline bool page_is_young(struct page *page)
> +{
> +       return false;
> +}
> +
> +static inline void set_page_young(struct page *page)
> +{
> +}
> +
> +static inline bool test_and_clear_page_young(struct page *page)
> +{
> +       return false;
> +}
> +
> +static inline bool page_is_idle(struct page *page)
> +{
> +       return false;
> +}
> +
> +static inline void set_page_idle(struct page *page)
> +{
> +}
> +
> +static inline void clear_page_idle(struct page *page)
> +{
> +}
> +#endif /* CONFIG_IDLE_PAGE_TRACKING */
> +
>  #endif /* __KERNEL__ */
>  #endif /* _LINUX_MM_H */
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 91b7f9b2b774..478f2241f284 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -109,6 +109,10 @@ enum pageflags {
>  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>         PG_compound_lock,
>  #endif
> +#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
> +       PG_young,
> +       PG_idle,
> +#endif
>         __NR_PAGEFLAGS,
>
>         /* Filesystems */
> @@ -363,6 +367,13 @@ PAGEFLAG_FALSE(HWPoison)
>  #define __PG_HWPOISON 0
>  #endif
>
> +#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
> +TESTPAGEFLAG(Young, young, PF_ANY)
> +SETPAGEFLAG(Young, young, PF_ANY)
> +TESTCLEARFLAG(Young, young, PF_ANY)
> +PAGEFLAG(Idle, idle, PF_ANY)
> +#endif
> +
>  /*
>   * On an anonymous page mapped into a user virtual memory area,
>   * page->mapping points to its anon_vma, not to a struct address_space;
> diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h
> index c42981cd99aa..17f118a82854 100644
> --- a/include/linux/page_ext.h
> +++ b/include/linux/page_ext.h
> @@ -26,6 +26,10 @@ enum page_ext_flags {
>         PAGE_EXT_DEBUG_POISON,          /* Page is poisoned */
>         PAGE_EXT_DEBUG_GUARD,
>         PAGE_EXT_OWNER,
> +#if defined(CONFIG_IDLE_PAGE_TRACKING) && !defined(CONFIG_64BIT)
> +       PAGE_EXT_YOUNG,
> +       PAGE_EXT_IDLE,
> +#endif
>  };
>
>  /*
> diff --git a/mm/Kconfig b/mm/Kconfig
> index e79de2bd12cd..db817e2c2ec8 100644
> --- a/mm/Kconfig
> +++ b/mm/Kconfig
> @@ -654,3 +654,15 @@ config DEFERRED_STRUCT_PAGE_INIT
>           when kswapd starts. This has a potential performance impact on
>           processes running early in the lifetime of the systemm until kswapd
>           finishes the initialisation.
> +
> +config IDLE_PAGE_TRACKING
> +       bool "Enable idle page tracking"
> +       select PROC_PAGE_MONITOR
> +       select PAGE_EXTENSION if !64BIT
> +       help
> +         This feature allows to estimate the amount of user pages that have
> +         not been touched during a given period of time. This information can
> +         be useful to tune memory cgroup limits and/or for job placement
> +         within a compute cluster.
> +
> +         See Documentation/vm/pagemap.txt for more details.
> diff --git a/mm/debug.c b/mm/debug.c
> index 76089ddf99ea..6c1b3ea61bfd 100644
> --- a/mm/debug.c
> +++ b/mm/debug.c
> @@ -48,6 +48,10 @@ static const struct trace_print_flags pageflag_names[] = {
>  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>         {1UL << PG_compound_lock,       "compound_lock" },
>  #endif
> +#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
> +       {1UL << PG_young,               "young"         },
> +       {1UL << PG_idle,                "idle"          },
> +#endif
>  };
>
>  static void dump_flags(unsigned long flags,
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 9671f51e954d..db404966faf4 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1754,6 +1754,11 @@ static void __split_huge_page_refcount(struct page *page,
>                 /* clear PageTail before overwriting first_page */
>                 smp_wmb();
>
> +               if (page_is_young(page))
> +                       set_page_young(page_tail);
> +               if (page_is_idle(page))
> +                       set_page_idle(page_tail);
> +
>                 /*
>                  * __split_huge_page_splitting() already set the
>                  * splitting bit in all pmd that could map this
> diff --git a/mm/page_ext.c b/mm/page_ext.c
> index d86fd2f5353f..e4b3af054bf2 100644
> --- a/mm/page_ext.c
> +++ b/mm/page_ext.c
> @@ -59,6 +59,9 @@ static struct page_ext_operations *page_ext_ops[] = {
>  #ifdef CONFIG_PAGE_OWNER
>         &page_owner_ops,
>  #endif
> +#if defined(CONFIG_IDLE_PAGE_TRACKING) && !defined(CONFIG_64BIT)
> +       &page_idle_ops,
> +#endif
>  };
>
>  static unsigned long total_usage;
> diff --git a/mm/rmap.c b/mm/rmap.c
> index 49b244b1f18c..c96677ade3d1 100644
> --- a/mm/rmap.c
> +++ b/mm/rmap.c
> @@ -798,6 +798,11 @@ static int page_referenced_one(struct page *page, struct vm_area_struct *vma,
>                 pte_unmap_unlock(pte, ptl);
>         }
>
> +       if (referenced)
> +               clear_page_idle(page);
> +       if (test_and_clear_page_young(page))
> +               referenced++;
> +
>         if (referenced) {
>                 pra->referenced++;
>                 pra->vm_flags |= vma->vm_flags;
> diff --git a/mm/swap.c b/mm/swap.c
> index ab7c338eda87..db43c9b4891d 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -623,6 +623,8 @@ void mark_page_accessed(struct page *page)
>         } else if (!PageReferenced(page)) {
>                 SetPageReferenced(page);
>         }
> +       if (page_is_idle(page))
> +               clear_page_idle(page);
>  }
>  EXPORT_SYMBOL(mark_page_accessed);
>
> --
> 2.1.4
>



-- 
Andres Lagar-Cavilla | Google Kernel Team | andreslc@google.com

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH v7 2/9] nvmem: Add a simple NVMEM framework for consumers
From: Stefan Wahren @ 2015-07-13 19:06 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w, Mark Brown,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1436521495-10728-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 10. Juli 2015 um
> 11:44 geschrieben:
>
>
> [...]
> ---
> drivers/nvmem/core.c | 424 ++++++++++++++++++++++++++++++++++++++++-
> include/linux/nvmem-consumer.h | 76 ++++++++
> 2 files changed, 498 insertions(+), 2 deletions(-)
> create mode 100644 include/linux/nvmem-consumer.h
>
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index a779ad1..f429ad4 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -15,14 +15,15 @@
> */
>
> #include <linux/device.h>
> -#include <linux/nvmem-provider.h>
> #include <linux/export.h>
> #include <linux/fs.h>
> #include <linux/idr.h>
> #include <linux/init.h>
> -#include <linux/regmap.h>

please avoid such changes in your patch series. This should be fixed in the
first patch.

Thanks
Stefan

^ permalink raw reply

* Re: [PATCH v7 2/9] nvmem: Add a simple NVMEM framework for consumers
From: Srinivas Kandagatla @ 2015-07-13 19:24 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, mporter, linux-arm-msm, Maxime Ripard,
	pantelis.antoniou, Mark Brown, devicetree
In-Reply-To: <1510509759.163664.1436814382477.JavaMail.open-xchange@oxbsltgw06.schlund.de>



On 13/07/15 20:06, Stefan Wahren wrote:
>> -#include <linux/nvmem-provider.h>
>> >#include <linux/export.h>
>> >#include <linux/fs.h>
>> >#include <linux/idr.h>
>> >#include <linux/init.h>
>> >-#include <linux/regmap.h>
> please avoid such changes in your patch series. This should be fixed in the
> first patch.
Sure, I know why this happened, the headers were re-ordered in this 
patch.. I will take care of it.

--srini

^ permalink raw reply

* Re: [PATCH v7 0/9] Add simple NVMEM Framework via regmap.
From: Srinivas Kandagatla @ 2015-07-13 19:35 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: devicetree, arnd, ezequiel, linux-api, s.hauer, sboyd,
	linux-kernel, pantelis.antoniou, Rob Herring, Mark Brown,
	Kumar Gala, mporter, linux-arm-msm, wxt
In-Reply-To: <1984575203.163267.1436813665815.JavaMail.open-xchange@oxbsltgw06.schlund.de>



On 13/07/15 19:54, Stefan Wahren wrote:
> Hi Srinivas,
>
> [add Ezequiel Garcia to CC]
>
>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 10. Juli 2015 um
>> 11:43 geschrieben:
>>
>>
>> Hi Greg,
>>
>> This patchset adds a new simple NVMEM framework to kernel, and it is tested
>> with various drivers like "QCOM thermal sensors", "QCOM cpr driver",
>> "begal bone cape manager" and few more on the way.
>>
>> Thankyou all for providing inputs and comments on previous versions of this
>> patchset. Here is the v7 of the patchset addressing all the issues raised as
>> part of previous versions review.
>>
>> Up until now, NVMEM drivers like eeprom were stored in drivers/misc, where
>> they
>> all had to duplicate pretty much the same code to register a sysfs file, allow
>> in-kernel users to access the content of the devices they were driving, etc.
>> This was also a problem as far as other in-kernel users were involved, since
>> the solutions used were pretty much different from on driver to another, there
>> was a rather big abstraction leak.
>
> i only want to mention that there are more places of NVMEM drivers like:
>
> drivers/mfd/ab3100-otp.c
> drivers/soc/tegra/fuse/*.c

Thanks for mentioning.

>
>>
>> Introduction of this framework aims at solving this. It also introduces DT
>> representation for consumer devices to go get the data they require (MAC
>> Addresses, SoC/Revision ID, part numbers, and so on) from the NVMEMs.
>>
>> After learning few things about QCOM qfprom and other eeprom/efuses, which
>> has packed fields at bit level. Which makes it important to add support to
>> such memories. This version adds support to this type of non volatile
>> memories by adding support to bit level nvmem-cells.
>>
>> Having regmap interface to this framework would give much better
>> abstraction for nvmems on different buses.
>>
>> patch 1-4 Introduces the NVMEM framework.
>> Patch 5-6 Adds Qualcomm specific qfprom driver.
>> Patch 7 migrates an existing driver to nvmem framework.
>> Patch 8 adds entry in MAINTAINERS.
>>
>> Its also possible to migrate other nvmem drivers to this framework, and I
>> think
>> some of them already posted patches based on this framework.
>>
>> Providers APIs:
>> nvmem_register/unregister();
>
> How do i get the cell info from the devicetree into the nvmem_config?
>
Not sure what is the real use-case here, But this is how it is supposed 
to work.

cellinfo in nvmem_config is used to pass cell information in non-dt 
style to the core. The core would parse it and convert into nvmem-cells. 
Am not sure why would you want to do other way round. Could you explain 
the real use case here?


> I expected a function something like of_nvmem_cell_info_get() in the Providers
> API.


>
...

>> userspace interface: binary file in /sys/bus/nvmem/devices/*/nvmem
>>
>> ex:
>> hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
>>
>> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
>> *
>> 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
>> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
>> ...
>> *
>> 0001000
>
> Since we're entering userspace the behavior should be clear.
>
> How do we treat register gaps? Fill them with zero?
nvmem file would read full nvmem size which is passed to it as regmap. 
So It would dump whatever the provider returns.


--srini
>
> Best regards
> Stefan
>

^ permalink raw reply

* [PATCH v4 0/5] support "cpu_isolated" mode for nohz_full
From: Chris Metcalf @ 2015-07-13 19:57 UTC (permalink / raw)
  To: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, Catalin Marinas, Will Deacon, linux-doc, linux-api,
	linux-kernel
  Cc: Chris Metcalf
In-Reply-To: <1433345365-29506-1-git-send-email-cmetcalf@ezchip.com>

This posting of the series is basically a "ping" since there were
no comments to the v3 version.  I have rebased it to 4.2-rc1, added
support for arm64 syscall tracking for "strict" mode, and retested it;
are there any remaining concerns?  Thomas, I haven't heard from you
whether my removal of the cpu_idle calls sufficiently addresses your
concerns about that aspect.  Are there other concerns with this patch
series at this point?

Original patch series cover letter follows:

The existing nohz_full mode does a nice job of suppressing extraneous
kernel interrupts for cores that desire it.  However, there is a need
for a more deterministic mode that rigorously disallows kernel
interrupts, even at a higher cost in user/kernel transition time:
for example, high-speed networking applications running userspace
drivers that will drop packets if they are ever interrupted.

These changes attempt to provide an initial draft of such a framework;
the changes do not add any overhead to the usual non-nohz_full mode,
and only very small overhead to the typical nohz_full mode.  A prctl()
option (PR_SET_CPU_ISOLATED) is added to control whether processes have
requested this stricter semantics, and within that prctl() option we
provide a number of different bits for more precise control.
Additionally, we add a new command-line boot argument to facilitate
debugging where unexpected interrupts are being delivered from.

Code that is conceptually similar has been in use in Tilera's
Multicore Development Environment since 2008, known as Zero-Overhead
Linux, and has seen wide adoption by a range of customers.  This patch
series represents the first serious attempt to upstream that
functionality.  Although the current state of the kernel isn't quite
ready to run with absolutely no kernel interrupts (for example,
workqueues on cpu_isolated cores still remain to be dealt with), this
patch series provides a way to make dynamic tradeoffs between avoiding
kernel interrupts on the one hand, and making voluntary calls in and
out of the kernel more expensive, for tasks that want it.

The series (based currently on v4.2-rc1) is available at:

  git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git dataplane

v4:
  rebased on kernel v4.2-rc1
  added support for detecting CPU_ISOLATED_STRICT syscalls on arm64

v3:
  remove dependency on cpu_idle subsystem (Thomas Gleixner)
  use READ_ONCE instead of ACCESS_ONCE in tick_nohz_cpu_isolated_enter
  use seconds for console messages instead of jiffies (Thomas Gleixner)
  updated commit description for patch 5/5

v2:
  rename "dataplane" to "cpu_isolated"
  drop ksoftirqd suppression changes (believed no longer needed)
  merge previous "QUIESCE" functionality into baseline functionality
  explicitly track syscalls and exceptions for "STRICT" functionality
  allow configuring a signal to be delivered for STRICT mode failures
  move debug tracking to irq_enter(), not irq_exit()

Note: I have not removed the commit to disable the 1Hz timer tick
fallback that was nack'ed by PeterZ, pending a decision on that thread
as to what to do (https://lkml.org/lkml/2015/5/8/555); also since if
we remove the 1Hz tick, cpu_isolated threads will never re-enter
userspace since a tick will always be pending.

Chris Metcalf (5):
  nohz_full: add support for "cpu_isolated" mode
  nohz: support PR_CPU_ISOLATED_STRICT mode
  nohz: cpu_isolated strict mode configurable signal
  nohz: add cpu_isolated_debug boot flag
  nohz: cpu_isolated: allow tick to be fully disabled

 Documentation/kernel-parameters.txt |   6 +++
 arch/tile/kernel/process.c          |   9 ++++
 arch/tile/kernel/ptrace.c           |   6 ++-
 arch/tile/mm/homecache.c            |   5 +-
 arch/x86/kernel/ptrace.c            |   2 +
 include/linux/context_tracking.h    |  11 ++--
 include/linux/sched.h               |   3 ++
 include/linux/tick.h                |  28 ++++++++++
 include/uapi/linux/prctl.h          |   8 +++
 kernel/context_tracking.c           |  12 +++--
 kernel/irq_work.c                   |   4 +-
 kernel/sched/core.c                 |  18 +++++++
 kernel/signal.c                     |   5 ++
 kernel/smp.c                        |   4 ++
 kernel/softirq.c                    |   6 +++
 kernel/sys.c                        |   8 +++
 kernel/time/tick-sched.c            | 104 +++++++++++++++++++++++++++++++++++-
 17 files changed, 229 insertions(+), 10 deletions(-)

-- 
2.1.2

^ permalink raw reply

* [PATCH v4 1/5] nohz_full: add support for "cpu_isolated" mode
From: Chris Metcalf @ 2015-07-13 19:57 UTC (permalink / raw)
  To: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, linux-doc, linux-api, linux-kernel
  Cc: Chris Metcalf
In-Reply-To: <1436817481-8732-1-git-send-email-cmetcalf@ezchip.com>

The existing nohz_full mode makes tradeoffs to minimize userspace
interruptions while still attempting to avoid overheads in the
kernel entry/exit path, to provide 100% kernel semantics, etc.

However, some applications require a stronger commitment from the
kernel to avoid interruptions, in particular userspace device
driver style applications, such as high-speed networking code.

This change introduces a framework to allow applications to elect
to have the stronger semantics as needed, specifying
prctl(PR_SET_CPU_ISOLATED, PR_CPU_ISOLATED_ENABLE) to do so.
Subsequent commits will add additional flags and additional
semantics.

The "cpu_isolated" state is indicated by setting a new task struct
field, cpu_isolated_flags, to the value passed by prctl().  When the
_ENABLE bit is set for a task, and it is returning to userspace
on a nohz_full core, it calls the new tick_nohz_cpu_isolated_enter()
routine to take additional actions to help the task avoid being
interrupted in the future.

Initially, there are only two actions taken.  First, the task
calls lru_add_drain() to prevent being interrupted by a subsequent
lru_add_drain_all() call on another core.  Then, the code checks for
pending timer interrupts and quiesces until they are no longer pending.
As a result, sys calls (and page faults, etc.) can be inordinately slow.
However, this quiescing guarantees that no unexpected interrupts will
occur, even if the application intentionally calls into the kernel.

Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
---
 arch/tile/kernel/process.c |  9 ++++++++
 include/linux/sched.h      |  3 +++
 include/linux/tick.h       | 10 ++++++++
 include/uapi/linux/prctl.h |  5 ++++
 kernel/context_tracking.c  |  3 +++
 kernel/sys.c               |  8 +++++++
 kernel/time/tick-sched.c   | 57 ++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 95 insertions(+)

diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index e036c0aa9792..3625e839ad62 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -70,6 +70,15 @@ void arch_cpu_idle(void)
 	_cpu_idle();
 }
 
+#ifdef CONFIG_NO_HZ_FULL
+void tick_nohz_cpu_isolated_wait(void)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+	_cpu_idle();
+	set_current_state(TASK_RUNNING);
+}
+#endif
+
 /*
  * Release a thread_info structure
  */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ae21f1591615..f350b0c20bbc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1778,6 +1778,9 @@ struct task_struct {
 	unsigned long	task_state_change;
 #endif
 	int pagefault_disabled;
+#ifdef CONFIG_NO_HZ_FULL
+	unsigned int	cpu_isolated_flags;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 3741ba1a652c..cb5569181359 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -10,6 +10,7 @@
 #include <linux/context_tracking_state.h>
 #include <linux/cpumask.h>
 #include <linux/sched.h>
+#include <linux/prctl.h>
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void __init tick_init(void);
@@ -144,11 +145,18 @@ static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask)
 		cpumask_or(mask, mask, tick_nohz_full_mask);
 }
 
+static inline bool tick_nohz_is_cpu_isolated(void)
+{
+	return tick_nohz_full_cpu(smp_processor_id()) &&
+		(current->cpu_isolated_flags & PR_CPU_ISOLATED_ENABLE);
+}
+
 extern void __tick_nohz_full_check(void);
 extern void tick_nohz_full_kick(void);
 extern void tick_nohz_full_kick_cpu(int cpu);
 extern void tick_nohz_full_kick_all(void);
 extern void __tick_nohz_task_switch(struct task_struct *tsk);
+extern void tick_nohz_cpu_isolated_enter(void);
 #else
 static inline bool tick_nohz_full_enabled(void) { return false; }
 static inline bool tick_nohz_full_cpu(int cpu) { return false; }
@@ -158,6 +166,8 @@ static inline void tick_nohz_full_kick_cpu(int cpu) { }
 static inline void tick_nohz_full_kick(void) { }
 static inline void tick_nohz_full_kick_all(void) { }
 static inline void __tick_nohz_task_switch(struct task_struct *tsk) { }
+static inline bool tick_nohz_is_cpu_isolated(void) { return false; }
+static inline void tick_nohz_cpu_isolated_enter(void) { }
 #endif
 
 static inline bool is_housekeeping_cpu(int cpu)
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 31891d9535e2..edb40b6b84db 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -190,4 +190,9 @@ struct prctl_mm_map {
 # define PR_FP_MODE_FR		(1 << 0)	/* 64b FP registers */
 # define PR_FP_MODE_FRE		(1 << 1)	/* 32b compatibility */
 
+/* Enable/disable or query cpu_isolated mode for NO_HZ_FULL kernels. */
+#define PR_SET_CPU_ISOLATED	47
+#define PR_GET_CPU_ISOLATED	48
+# define PR_CPU_ISOLATED_ENABLE	(1 << 0)
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
index 0a495ab35bc7..f9de3ee12723 100644
--- a/kernel/context_tracking.c
+++ b/kernel/context_tracking.c
@@ -20,6 +20,7 @@
 #include <linux/hardirq.h>
 #include <linux/export.h>
 #include <linux/kprobes.h>
+#include <linux/tick.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/context_tracking.h>
@@ -99,6 +100,8 @@ void context_tracking_enter(enum ctx_state state)
 			 * on the tick.
 			 */
 			if (state == CONTEXT_USER) {
+				if (tick_nohz_is_cpu_isolated())
+					tick_nohz_cpu_isolated_enter();
 				trace_user_enter(0);
 				vtime_user_enter(current);
 			}
diff --git a/kernel/sys.c b/kernel/sys.c
index 259fda25eb6b..36eb9a839f1f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2267,6 +2267,14 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 	case PR_GET_FP_MODE:
 		error = GET_FP_MODE(me);
 		break;
+#ifdef CONFIG_NO_HZ_FULL
+	case PR_SET_CPU_ISOLATED:
+		me->cpu_isolated_flags = arg2;
+		break;
+	case PR_GET_CPU_ISOLATED:
+		error = me->cpu_isolated_flags;
+		break;
+#endif
 	default:
 		error = -EINVAL;
 		break;
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index c792429e98c6..4cf093c012d1 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -24,6 +24,7 @@
 #include <linux/posix-timers.h>
 #include <linux/perf_event.h>
 #include <linux/context_tracking.h>
+#include <linux/swap.h>
 
 #include <asm/irq_regs.h>
 
@@ -389,6 +390,62 @@ void __init tick_nohz_init(void)
 	pr_info("NO_HZ: Full dynticks CPUs: %*pbl.\n",
 		cpumask_pr_args(tick_nohz_full_mask));
 }
+
+/*
+ * Rather than continuously polling for the next_event in the
+ * tick_cpu_device, architectures can provide a method to save power
+ * by sleeping until an interrupt arrives.
+ */
+void __weak tick_nohz_cpu_isolated_wait(void)
+{
+	cpu_relax();
+}
+
+/*
+ * We normally return immediately to userspace.
+ *
+ * In "cpu_isolated" mode we wait until no more interrupts are
+ * pending.  Otherwise we nap with interrupts enabled and wait for the
+ * next interrupt to fire, then loop back and retry.
+ *
+ * Note that if you schedule two "cpu_isolated" processes on the same
+ * core, neither will ever leave the kernel, and one will have to be
+ * killed manually.  Otherwise in situations where another process is
+ * in the runqueue on this cpu, this task will just wait for that
+ * other task to go idle before returning to user space.
+ */
+void tick_nohz_cpu_isolated_enter(void)
+{
+	struct clock_event_device *dev =
+		__this_cpu_read(tick_cpu_device.evtdev);
+	struct task_struct *task = current;
+	unsigned long start = jiffies;
+	bool warned = false;
+
+	/* Drain the pagevecs to avoid unnecessary IPI flushes later. */
+	lru_add_drain();
+
+	while (READ_ONCE(dev->next_event.tv64) != KTIME_MAX) {
+		if (!warned && (jiffies - start) >= (5 * HZ)) {
+			pr_warn("%s/%d: cpu %d: cpu_isolated task blocked for %ld seconds\n",
+				task->comm, task->pid, smp_processor_id(),
+				(jiffies - start) / HZ);
+			warned = true;
+		}
+		if (should_resched())
+			schedule();
+		if (test_thread_flag(TIF_SIGPENDING))
+			break;
+		tick_nohz_cpu_isolated_wait();
+	}
+	if (warned) {
+		pr_warn("%s/%d: cpu %d: cpu_isolated task unblocked after %ld seconds\n",
+			task->comm, task->pid, smp_processor_id(),
+			(jiffies - start) / HZ);
+		dump_stack();
+	}
+}
+
 #endif
 
 /*
-- 
2.1.2

^ permalink raw reply related

* [PATCH v4 2/5] nohz: support PR_CPU_ISOLATED_STRICT mode
From: Chris Metcalf @ 2015-07-13 19:57 UTC (permalink / raw)
  To: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, Catalin Marinas, Will Deacon, linux-doc, linux-api,
	linux-kernel
  Cc: Chris Metcalf
In-Reply-To: <1436817481-8732-1-git-send-email-cmetcalf@ezchip.com>

With cpu_isolated mode, the task is in principle guaranteed not to be
interrupted by the kernel, but only if it behaves.  In particular, if it
enters the kernel via system call, page fault, or any of a number of other
synchronous traps, it may be unexpectedly exposed to long latencies.
Add a simple flag that puts the process into a state where any such
kernel entry is fatal.

To allow the state to be entered and exited, we add an internal bit to
current->cpu_isolated_flags that is set when prctl() sets the flags.
We check the bit on syscall entry as well as on any exception_enter().
The prctl() syscall is ignored to allow clearing the bit again later,
and exit/exit_group are ignored to allow exiting the task without
a pointless signal killing you as you try to do so.

This change adds the syscall-detection hooks only for x86, arm64,
and tile.

The signature of context_tracking_exit() changes to report whether
we, in fact, are exiting back to user space, so that we can track
user exceptions properly separately from other kernel entries.

Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
---
 arch/arm64/kernel/ptrace.c       |  4 ++++
 arch/tile/kernel/ptrace.c        |  6 +++++-
 arch/x86/kernel/ptrace.c         |  2 ++
 include/linux/context_tracking.h | 11 ++++++++---
 include/linux/tick.h             | 16 ++++++++++++++++
 include/uapi/linux/prctl.h       |  1 +
 kernel/context_tracking.c        |  9 ++++++---
 kernel/time/tick-sched.c         | 38 ++++++++++++++++++++++++++++++++++++++
 8 files changed, 80 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index d882b833dbdb..7315b1579cbd 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -1150,6 +1150,10 @@ static void tracehook_report_syscall(struct pt_regs *regs,
 
 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 {
+	/* Ensure we report cpu_isolated violations in all circumstances. */
+	if (test_thread_flag(TIF_NOHZ) && tick_nohz_cpu_isolated_strict())
+		tick_nohz_cpu_isolated_syscall(regs->syscallno);
+
 	/* Do the secure computing check first; failures should be fast. */
 	if (secure_computing() == -1)
 		return -1;
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index f84eed8243da..d4e43a13bab1 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -259,8 +259,12 @@ int do_syscall_trace_enter(struct pt_regs *regs)
 	 * If TIF_NOHZ is set, we are required to call user_exit() before
 	 * doing anything that could touch RCU.
 	 */
-	if (work & _TIF_NOHZ)
+	if (work & _TIF_NOHZ) {
 		user_exit();
+		if (tick_nohz_cpu_isolated_strict())
+			tick_nohz_cpu_isolated_syscall(
+				regs->regs[TREG_SYSCALL_NR]);
+	}
 
 	if (work & _TIF_SYSCALL_TRACE) {
 		if (tracehook_report_syscall_entry(regs))
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 9be72bc3613f..860f346977e2 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1479,6 +1479,8 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
 	if (work & _TIF_NOHZ) {
 		user_exit();
 		work &= ~_TIF_NOHZ;
+		if (tick_nohz_cpu_isolated_strict())
+			tick_nohz_cpu_isolated_syscall(regs->orig_ax);
 	}
 
 #ifdef CONFIG_SECCOMP
diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h
index b96bd299966f..8b994e2a0330 100644
--- a/include/linux/context_tracking.h
+++ b/include/linux/context_tracking.h
@@ -3,6 +3,7 @@
 
 #include <linux/sched.h>
 #include <linux/vtime.h>
+#include <linux/tick.h>
 #include <linux/context_tracking_state.h>
 #include <asm/ptrace.h>
 
@@ -11,7 +12,7 @@
 extern void context_tracking_cpu_set(int cpu);
 
 extern void context_tracking_enter(enum ctx_state state);
-extern void context_tracking_exit(enum ctx_state state);
+extern bool context_tracking_exit(enum ctx_state state);
 extern void context_tracking_user_enter(void);
 extern void context_tracking_user_exit(void);
 
@@ -35,8 +36,12 @@ static inline enum ctx_state exception_enter(void)
 		return 0;
 
 	prev_ctx = this_cpu_read(context_tracking.state);
-	if (prev_ctx != CONTEXT_KERNEL)
-		context_tracking_exit(prev_ctx);
+	if (prev_ctx != CONTEXT_KERNEL) {
+		if (context_tracking_exit(prev_ctx)) {
+			if (tick_nohz_cpu_isolated_strict())
+				tick_nohz_cpu_isolated_exception();
+		}
+	}
 
 	return prev_ctx;
 }
diff --git a/include/linux/tick.h b/include/linux/tick.h
index cb5569181359..f79f6945f762 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -157,6 +157,8 @@ extern void tick_nohz_full_kick_cpu(int cpu);
 extern void tick_nohz_full_kick_all(void);
 extern void __tick_nohz_task_switch(struct task_struct *tsk);
 extern void tick_nohz_cpu_isolated_enter(void);
+extern void tick_nohz_cpu_isolated_syscall(int nr);
+extern void tick_nohz_cpu_isolated_exception(void);
 #else
 static inline bool tick_nohz_full_enabled(void) { return false; }
 static inline bool tick_nohz_full_cpu(int cpu) { return false; }
@@ -168,6 +170,8 @@ static inline void tick_nohz_full_kick_all(void) { }
 static inline void __tick_nohz_task_switch(struct task_struct *tsk) { }
 static inline bool tick_nohz_is_cpu_isolated(void) { return false; }
 static inline void tick_nohz_cpu_isolated_enter(void) { }
+static inline void tick_nohz_cpu_isolated_syscall(int nr) { }
+static inline void tick_nohz_cpu_isolated_exception(void) { }
 #endif
 
 static inline bool is_housekeeping_cpu(int cpu)
@@ -200,4 +204,16 @@ static inline void tick_nohz_task_switch(struct task_struct *tsk)
 		__tick_nohz_task_switch(tsk);
 }
 
+static inline bool tick_nohz_cpu_isolated_strict(void)
+{
+#ifdef CONFIG_NO_HZ_FULL
+	if (tick_nohz_full_cpu(smp_processor_id()) &&
+	    (current->cpu_isolated_flags &
+	     (PR_CPU_ISOLATED_ENABLE | PR_CPU_ISOLATED_STRICT)) ==
+	    (PR_CPU_ISOLATED_ENABLE | PR_CPU_ISOLATED_STRICT))
+		return true;
+#endif
+	return false;
+}
+
 #endif
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index edb40b6b84db..0c11238a84fb 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -194,5 +194,6 @@ struct prctl_mm_map {
 #define PR_SET_CPU_ISOLATED	47
 #define PR_GET_CPU_ISOLATED	48
 # define PR_CPU_ISOLATED_ENABLE	(1 << 0)
+# define PR_CPU_ISOLATED_STRICT	(1 << 1)
 
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
index f9de3ee12723..fd051ea290ee 100644
--- a/kernel/context_tracking.c
+++ b/kernel/context_tracking.c
@@ -147,15 +147,16 @@ NOKPROBE_SYMBOL(context_tracking_user_enter);
  * This call supports re-entrancy. This way it can be called from any exception
  * handler without needing to know if we came from userspace or not.
  */
-void context_tracking_exit(enum ctx_state state)
+bool context_tracking_exit(enum ctx_state state)
 {
 	unsigned long flags;
+	bool from_user = false;
 
 	if (!context_tracking_is_enabled())
-		return;
+		return false;
 
 	if (in_interrupt())
-		return;
+		return false;
 
 	local_irq_save(flags);
 	if (!context_tracking_recursion_enter())
@@ -169,6 +170,7 @@ void context_tracking_exit(enum ctx_state state)
 			 */
 			rcu_user_exit();
 			if (state == CONTEXT_USER) {
+				from_user = true;
 				vtime_user_exit(current);
 				trace_user_exit(0);
 			}
@@ -178,6 +180,7 @@ void context_tracking_exit(enum ctx_state state)
 	context_tracking_recursion_exit();
 out_irq_restore:
 	local_irq_restore(flags);
+	return from_user;
 }
 NOKPROBE_SYMBOL(context_tracking_exit);
 EXPORT_SYMBOL_GPL(context_tracking_exit);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 4cf093c012d1..9f495c7c7dc2 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -27,6 +27,7 @@
 #include <linux/swap.h>
 
 #include <asm/irq_regs.h>
+#include <asm/unistd.h>
 
 #include "tick-internal.h"
 
@@ -446,6 +447,43 @@ void tick_nohz_cpu_isolated_enter(void)
 	}
 }
 
+static void kill_cpu_isolated_strict_task(void)
+{
+	dump_stack();
+	current->cpu_isolated_flags &= ~PR_CPU_ISOLATED_ENABLE;
+	send_sig(SIGKILL, current, 1);
+}
+
+/*
+ * This routine is called from syscall entry (with the syscall number
+ * passed in) if the _STRICT flag is set.
+ */
+void tick_nohz_cpu_isolated_syscall(int syscall)
+{
+	/* Ignore prctl() syscalls or any task exit. */
+	switch (syscall) {
+	case __NR_prctl:
+	case __NR_exit:
+	case __NR_exit_group:
+		return;
+	}
+
+	pr_warn("%s/%d: cpu_isolated strict mode violated by syscall %d\n",
+		current->comm, current->pid, syscall);
+	kill_cpu_isolated_strict_task();
+}
+
+/*
+ * This routine is called from any userspace exception if the _STRICT
+ * flag is set.
+ */
+void tick_nohz_cpu_isolated_exception(void)
+{
+	pr_warn("%s/%d: cpu_isolated strict mode violated by exception\n",
+		current->comm, current->pid);
+	kill_cpu_isolated_strict_task();
+}
+
 #endif
 
 /*
-- 
2.1.2

^ permalink raw reply related

* [PATCH v4 3/5] nohz: cpu_isolated strict mode configurable signal
From: Chris Metcalf @ 2015-07-13 19:57 UTC (permalink / raw)
  To: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, linux-doc, linux-api, linux-kernel
  Cc: Chris Metcalf
In-Reply-To: <1436817481-8732-1-git-send-email-cmetcalf@ezchip.com>

Allow userspace to override the default SIGKILL delivered
when a cpu_isolated process in STRICT mode does a syscall
or otherwise synchronously enters the kernel.

In addition to being able to set the signal, we now also
pass whether or not the interruption was from a syscall in
the si_code field of the siginfo.

Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
---
 include/uapi/linux/prctl.h |  2 ++
 kernel/time/tick-sched.c   | 15 +++++++++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 0c11238a84fb..ab45bd3d5799 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -195,5 +195,7 @@ struct prctl_mm_map {
 #define PR_GET_CPU_ISOLATED	48
 # define PR_CPU_ISOLATED_ENABLE	(1 << 0)
 # define PR_CPU_ISOLATED_STRICT	(1 << 1)
+# define PR_CPU_ISOLATED_SET_SIG(sig)  (((sig) & 0x7f) << 8)
+# define PR_CPU_ISOLATED_GET_SIG(bits) (((bits) >> 8) & 0x7f)
 
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 9f495c7c7dc2..c5eca9c99fad 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -447,11 +447,18 @@ void tick_nohz_cpu_isolated_enter(void)
 	}
 }
 
-static void kill_cpu_isolated_strict_task(void)
+static void kill_cpu_isolated_strict_task(int is_syscall)
 {
+	siginfo_t info = {};
+	int sig;
+
 	dump_stack();
 	current->cpu_isolated_flags &= ~PR_CPU_ISOLATED_ENABLE;
-	send_sig(SIGKILL, current, 1);
+
+	sig = PR_CPU_ISOLATED_GET_SIG(current->cpu_isolated_flags) ?: SIGKILL;
+	info.si_signo = sig;
+	info.si_code = is_syscall;
+	send_sig_info(sig, &info, current);
 }
 
 /*
@@ -470,7 +477,7 @@ void tick_nohz_cpu_isolated_syscall(int syscall)
 
 	pr_warn("%s/%d: cpu_isolated strict mode violated by syscall %d\n",
 		current->comm, current->pid, syscall);
-	kill_cpu_isolated_strict_task();
+	kill_cpu_isolated_strict_task(1);
 }
 
 /*
@@ -481,7 +488,7 @@ void tick_nohz_cpu_isolated_exception(void)
 {
 	pr_warn("%s/%d: cpu_isolated strict mode violated by exception\n",
 		current->comm, current->pid);
-	kill_cpu_isolated_strict_task();
+	kill_cpu_isolated_strict_task(0);
 }
 
 #endif
-- 
2.1.2

^ permalink raw reply related

* Re: [PATCH v7 0/9] Add simple NVMEM Framework via regmap.
From: Stefan Wahren @ 2015-07-13 20:11 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Rob Herring, Kumar Gala, arnd, sboyd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, pantelis.antoniou, ezequiel,
	Mark Brown, devicetree
In-Reply-To: <55A4131C.7040700@linaro.org>

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 13. Juli 2015 um
> 21:35 geschrieben:
>
> On 13/07/15 19:54, Stefan Wahren wrote:
> > Hi Srinivas,
> >
> >> [...]
> >>
> >> Providers APIs:
> >> nvmem_register/unregister();
> >
> > How do i get the cell info from the devicetree into the nvmem_config?
> >
> Not sure what is the real use-case here, But this is how it is supposed
> to work.
>
> cellinfo in nvmem_config is used to pass cell information in non-dt
> style to the core. The core would parse it and convert into nvmem-cells.
> Am not sure why would you want to do other way round. Could you explain
> the real use case here?
>

my question comes from porting mxs_ocotp to NVMEM framework.

Here is the devicetree part:

ocotp: ocotp@8002c000 {
	compatible = "fsl,imx28-ocotp", "fsl,ocotp";
	#address-cells = <1>;
	#size-cells = <1>;
	reg = <0x8002c000 0x2000>;
	clocks = <&clks 25>;
	read-only;
				
	/* Data cells */
	ocotp_customer: costumer@20 {
		reg = <0x20 0x10>;
	};

	ocotp_rom0: rom0@1a0 {
		reg = <0x1a0 0x4>;
	};
};

After calling nvmem_register() in the provider driver [1] no data cell is
registered. So
i looked at the core code and i thought that retrieving the cell info and put it
into the nvmem_config
is job of the provider driver.

Did i missed something?

[1] -
https://github.com/lategoodbye/fsl_ocotp/commit/7c98e19755b69f761885b0e1ceb2c258a7c47ade

>
>
> >
> ...
>
> >> userspace interface: binary file in /sys/bus/nvmem/devices/*/nvmem
> >>
> >> ex:
> >> hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
> >>
> >> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> >> *
> >> 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> >> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> >> ...
> >> *
> >> 0001000
> >
> > Since we're entering userspace the behavior should be clear.
> >
> > How do we treat register gaps? Fill them with zero?
> nvmem file would read full nvmem size which is passed to it as regmap.
> So It would dump whatever the provider returns.

Sure, but wouldn't it be nice if different provider behave the same?

>
>
> --srini
> >
> > Best regards
> > Stefan
> >

^ permalink raw reply

* Re: [PATCH v4 1/5] nohz_full: add support for "cpu_isolated" mode
From: Andy Lutomirski @ 2015-07-13 20:40 UTC (permalink / raw)
  To: Chris Metcalf
  Cc: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, linux-doc@vger.kernel.org, Linux API,
	linux-kernel@vger.kernel.org
In-Reply-To: <1436817481-8732-2-git-send-email-cmetcalf@ezchip.com>

On Mon, Jul 13, 2015 at 12:57 PM, Chris Metcalf <cmetcalf@ezchip.com> wrote:
> The existing nohz_full mode makes tradeoffs to minimize userspace
> interruptions while still attempting to avoid overheads in the
> kernel entry/exit path, to provide 100% kernel semantics, etc.
>
> However, some applications require a stronger commitment from the
> kernel to avoid interruptions, in particular userspace device
> driver style applications, such as high-speed networking code.
>
> This change introduces a framework to allow applications to elect
> to have the stronger semantics as needed, specifying
> prctl(PR_SET_CPU_ISOLATED, PR_CPU_ISOLATED_ENABLE) to do so.
> Subsequent commits will add additional flags and additional
> semantics.

I thought the general consensus was that this should be the default
behavior and that any associated bugs should be fixed.

--Andy

^ permalink raw reply

* Re: [PATCH v4 1/5] nohz_full: add support for "cpu_isolated" mode
From: Chris Metcalf @ 2015-07-13 21:01 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, linux-doc@vger.kernel.org, Linux API,
	linux-kernel@vger.kernel.org
In-Reply-To: <CALCETrWaBe10u1X+AqYM7TsbguL=aF-TyuN3xjqgR5Cg2=FiAA@mail.gmail.com>

On 07/13/2015 04:40 PM, Andy Lutomirski wrote:
> On Mon, Jul 13, 2015 at 12:57 PM, Chris Metcalf <cmetcalf@ezchip.com> wrote:
>> The existing nohz_full mode makes tradeoffs to minimize userspace
>> interruptions while still attempting to avoid overheads in the
>> kernel entry/exit path, to provide 100% kernel semantics, etc.
>>
>> However, some applications require a stronger commitment from the
>> kernel to avoid interruptions, in particular userspace device
>> driver style applications, such as high-speed networking code.
>>
>> This change introduces a framework to allow applications to elect
>> to have the stronger semantics as needed, specifying
>> prctl(PR_SET_CPU_ISOLATED, PR_CPU_ISOLATED_ENABLE) to do so.
>> Subsequent commits will add additional flags and additional
>> semantics.
> I thought the general consensus was that this should be the default
> behavior and that any associated bugs should be fixed.

I think it comes down to dividing the set of use cases in two:

- "Regular" nohz_full, as used to improve performance and limit
   interruptions, possibly for power benefits, etc.  But, stray
   interrupts are not particularly bad, and you don't want to take
   extreme measures to avoid them.

- What I'm calling "cpu_isolated" mode where when you return to
   userspace, you expect that by God, the kernel doesn't interrupt you
   again, and if it does, it's a flat-out bug.

There are a few things that cpu_isolated mode currently does to
accomplish its goals that are pretty heavy-weight:

Processes are held in kernel space until ticks are quiesced; this is
not necessarily what every nohz_full task wants.  If a task makes a
kernel call, there may well be arbitrary timer fallout, and having a
way to select whether or not you are willing to take a timer tick after
return to userspace is pretty important.

Likewise, there are things that you may want to do on return to
userspace that are designed to prevent further interruptions in
cpu_isolated mode, even at a possible future performance cost if and
when you return to the kernel, such as flushing the per-cpu free page
list so that you won't be interrupted by an IPI to flush it later.

If you're arguing that the cpu_isolated semantic is really the only
one that makes sense for nohz_full, my sense is that it might be
surprising to many of the folks who do nohz_full work.  But, I'm happy
to be wrong on this point, and maybe all the nohz_full community is
interested in making the same tradeoffs for nohz_full generally that
I've proposed in this patch series just for cpu_isolated?

-- 
Chris Metcalf, EZChip Semiconductor
http://www.ezchip.com


^ permalink raw reply

* Re: [PATCH v7 0/9] Add simple NVMEM Framework via regmap.
From: Srinivas Kandagatla @ 2015-07-13 21:39 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Kumar Gala, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Mark Brown,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <139301016.164015.1436818270753.JavaMail.open-xchange-0SF9iQWekqKZU4JK52HgGMgmgJlYmuWJ@public.gmane.org>



On 13/07/15 21:11, Stefan Wahren wrote:
> Hi Srinivas,
>
>> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 13. Juli 2015 um
>> 21:35 geschrieben:
>>
>> On 13/07/15 19:54, Stefan Wahren wrote:
>>> Hi Srinivas,
>>>
>>>> [...]
>>>>
>>>> Providers APIs:
>>>> nvmem_register/unregister();
>>>
>>> How do i get the cell info from the devicetree into the nvmem_config?
>>>
>> Not sure what is the real use-case here, But this is how it is supposed
>> to work.
>>
>> cellinfo in nvmem_config is used to pass cell information in non-dt
>> style to the core. The core would parse it and convert into nvmem-cells.
>> Am not sure why would you want to do other way round. Could you explain
>> the real use case here?
>>
>
> my question comes from porting mxs_ocotp to NVMEM framework.
>
> Here is the devicetree part:
>
> ocotp: ocotp@8002c000 {
> 	compatible = "fsl,imx28-ocotp", "fsl,ocotp";
> 	#address-cells = <1>;
> 	#size-cells = <1>;
> 	reg = <0x8002c000 0x2000>;
> 	clocks = <&clks 25>;
> 	read-only;
> 				
> 	/* Data cells */
> 	ocotp_customer: costumer@20 {
> 		reg = <0x20 0x10>;
> 	};
>
> 	ocotp_rom0: rom0@1a0 {
> 		reg = <0x1a0 0x4>;
> 	};
> };
>
> After calling nvmem_register() in the provider driver [1] no data cell is
> registered. So
> i looked at the core code and i thought that retrieving the cell info and put it
> into the nvmem_config
> is job of the provider driver.
>
> Did i missed something?
Ok,
There are 2 possible ways to specify nvmem cells
1> via the DT cell entries.
2> via provider driver directly using cell_info struct.

In the ocotp case its done via dt, so you dont need pass the cell info 
in nvmem_config.

You should also note that cell structure in DT is only created when an 
attempt to access is made as the provider lookup is straight forward in 
this case. In non-DT case the cell structure is created immediately and 
added to the global cell list.


--srini
>
> [1] -
> https://github.com/lategoodbye/fsl_ocotp/commit/7c98e19755b69f761885b0e1ceb2c258a7c47ade
>
>>
>>
>>>
>> ...
>>
>>>> userspace interface: binary file in /sys/bus/nvmem/devices/*/nvmem
>>>>
>>>> ex:
>>>> hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
>>>>
>>>> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
>>>> *
>>>> 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
>>>> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
>>>> ...
>>>> *
>>>> 0001000
>>>
>>> Since we're entering userspace the behavior should be clear.
>>>
>>> How do we treat register gaps? Fill them with zero?
>> nvmem file would read full nvmem size which is passed to it as regmap.
>> So It would dump whatever the provider returns.
>
> Sure, but wouldn't it be nice if different provider behave the same?
>
>>
>>
>> --srini
>>>
>>> Best regards
>>> Stefan
>>>

^ permalink raw reply

* Re: [PATCH v4 1/5] nohz_full: add support for "cpu_isolated" mode
From: Andy Lutomirski @ 2015-07-13 21:45 UTC (permalink / raw)
  To: Chris Metcalf
  Cc: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, linux-doc@vger.kernel.org, Linux API,
	linux-kernel@vger.kernel.org
In-Reply-To: <55A4271B.9040506@ezchip.com>

On Mon, Jul 13, 2015 at 2:01 PM, Chris Metcalf <cmetcalf@ezchip.com> wrote:
> On 07/13/2015 04:40 PM, Andy Lutomirski wrote:
>>
>> On Mon, Jul 13, 2015 at 12:57 PM, Chris Metcalf <cmetcalf@ezchip.com>
>> wrote:
>>>
>>> The existing nohz_full mode makes tradeoffs to minimize userspace
>>> interruptions while still attempting to avoid overheads in the
>>> kernel entry/exit path, to provide 100% kernel semantics, etc.
>>>
>>> However, some applications require a stronger commitment from the
>>> kernel to avoid interruptions, in particular userspace device
>>> driver style applications, such as high-speed networking code.
>>>
>>> This change introduces a framework to allow applications to elect
>>> to have the stronger semantics as needed, specifying
>>> prctl(PR_SET_CPU_ISOLATED, PR_CPU_ISOLATED_ENABLE) to do so.
>>> Subsequent commits will add additional flags and additional
>>> semantics.
>>
>> I thought the general consensus was that this should be the default
>> behavior and that any associated bugs should be fixed.
>
>
> I think it comes down to dividing the set of use cases in two:
>
> - "Regular" nohz_full, as used to improve performance and limit
>   interruptions, possibly for power benefits, etc.  But, stray
>   interrupts are not particularly bad, and you don't want to take
>   extreme measures to avoid them.
>
> - What I'm calling "cpu_isolated" mode where when you return to
>   userspace, you expect that by God, the kernel doesn't interrupt you
>   again, and if it does, it's a flat-out bug.
>
> There are a few things that cpu_isolated mode currently does to
> accomplish its goals that are pretty heavy-weight:
>
> Processes are held in kernel space until ticks are quiesced; this is
> not necessarily what every nohz_full task wants.  If a task makes a
> kernel call, there may well be arbitrary timer fallout, and having a
> way to select whether or not you are willing to take a timer tick after
> return to userspace is pretty important.

Then shouldn't deferred work be done immediately in nohz_full mode
regardless?  What is this delayed work that's being done?

>
> Likewise, there are things that you may want to do on return to
> userspace that are designed to prevent further interruptions in
> cpu_isolated mode, even at a possible future performance cost if and
> when you return to the kernel, such as flushing the per-cpu free page
> list so that you won't be interrupted by an IPI to flush it later.
>

Why not just kick the per-cpu free page over to whatever cpu is
monitoring your RCU state, etc?  That should be very quick.

> If you're arguing that the cpu_isolated semantic is really the only
> one that makes sense for nohz_full, my sense is that it might be
> surprising to many of the folks who do nohz_full work.  But, I'm happy
> to be wrong on this point, and maybe all the nohz_full community is
> interested in making the same tradeoffs for nohz_full generally that
> I've proposed in this patch series just for cpu_isolated?

nohz_full is currently dog slow for no particularly good reasons.  I
suspect that the interrupts you're seeing are also there for no
particularly good reasons as well.

Let's fix them instead of adding new ABIs to work around them.

--Andy

^ permalink raw reply

* Re: [PATCH v4 2/5] nohz: support PR_CPU_ISOLATED_STRICT mode
From: Andy Lutomirski @ 2015-07-13 21:47 UTC (permalink / raw)
  To: Chris Metcalf
  Cc: Gilad Ben Yossef, Steven Rostedt, Ingo Molnar, Peter Zijlstra,
	Andrew Morton, Rik van Riel, Tejun Heo, Frederic Weisbecker,
	Thomas Gleixner, Paul E. McKenney, Christoph Lameter,
	Viresh Kumar, Catalin Marinas, Will Deacon,
	linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux API,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1436817481-8732-3-git-send-email-cmetcalf-d5a29ZRxExrQT0dZR+AlfA@public.gmane.org>

On Mon, Jul 13, 2015 at 12:57 PM, Chris Metcalf <cmetcalf-d5a29ZRxExrQT0dZR+AlfA@public.gmane.org> wrote:
> With cpu_isolated mode, the task is in principle guaranteed not to be
> interrupted by the kernel, but only if it behaves.  In particular, if it
> enters the kernel via system call, page fault, or any of a number of other
> synchronous traps, it may be unexpectedly exposed to long latencies.
> Add a simple flag that puts the process into a state where any such
> kernel entry is fatal.
>

To me, this seems like the wrong design.  If nothing else, it seems
too much like an abusable anti-debugging mechanism.  I can imagine
some per-task flag "I think I shouldn't be interrupted now" and a
tracepoint that fires if the task is interrupted with that flag set.
But the strong cpu isolation stuff requires systemwide configuration,
and I think that monitoring that it works should work similarly.

More comments below.

> Signed-off-by: Chris Metcalf <cmetcalf-d5a29ZRxExrQT0dZR+AlfA@public.gmane.org>
> ---
>  arch/arm64/kernel/ptrace.c       |  4 ++++
>  arch/tile/kernel/ptrace.c        |  6 +++++-
>  arch/x86/kernel/ptrace.c         |  2 ++
>  include/linux/context_tracking.h | 11 ++++++++---
>  include/linux/tick.h             | 16 ++++++++++++++++
>  include/uapi/linux/prctl.h       |  1 +
>  kernel/context_tracking.c        |  9 ++++++---
>  kernel/time/tick-sched.c         | 38 ++++++++++++++++++++++++++++++++++++++
>  8 files changed, 80 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index d882b833dbdb..7315b1579cbd 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -1150,6 +1150,10 @@ static void tracehook_report_syscall(struct pt_regs *regs,
>
>  asmlinkage int syscall_trace_enter(struct pt_regs *regs)
>  {
> +       /* Ensure we report cpu_isolated violations in all circumstances. */
> +       if (test_thread_flag(TIF_NOHZ) && tick_nohz_cpu_isolated_strict())
> +               tick_nohz_cpu_isolated_syscall(regs->syscallno);

IMO this is pointless.  If a user wants a syscall to kill them, use
seccomp.  The kernel isn't at fault if the user does a syscall when it
didn't want to enter the kernel.


> @@ -35,8 +36,12 @@ static inline enum ctx_state exception_enter(void)
>                 return 0;
>
>         prev_ctx = this_cpu_read(context_tracking.state);
> -       if (prev_ctx != CONTEXT_KERNEL)
> -               context_tracking_exit(prev_ctx);
> +       if (prev_ctx != CONTEXT_KERNEL) {
> +               if (context_tracking_exit(prev_ctx)) {
> +                       if (tick_nohz_cpu_isolated_strict())
> +                               tick_nohz_cpu_isolated_exception();
> +               }
> +       }

NACK.  I'm cautiously optimistic that an x86 kernel 4.3 or newer will
simply never call exception_enter.  It certainly won't call it
frequently unless something goes wrong with the patches that are
already in -tip.

> --- a/kernel/context_tracking.c
> +++ b/kernel/context_tracking.c
> @@ -147,15 +147,16 @@ NOKPROBE_SYMBOL(context_tracking_user_enter);
>   * This call supports re-entrancy. This way it can be called from any exception
>   * handler without needing to know if we came from userspace or not.
>   */
> -void context_tracking_exit(enum ctx_state state)
> +bool context_tracking_exit(enum ctx_state state)
>  {
>         unsigned long flags;
> +       bool from_user = false;
>

IMO the internal context tracking API (e.g. context_tracking_exit) are
mostly of the form "hey context tracking: I don't really know what
you're doing or what I'm doing, but let me call you and make both of
us feel better."  You're making it somewhat worse: now it's all of the
above plus "I don't even know whether I just entered the kernel --
maybe you have a better idea".

Starting with 4.3, x86 kernels will know *exactly* when they enter the
kernel.  All of this context tracking what-was-my-previous-state stuff
will remain until someone kills it, but when it goes away we'll get a
nice performance boost.

So, no, let's implement this for real if we're going to implement it.

--Andy

^ permalink raw reply

* Re: KDBUS breaks 'make installmandocs'
From: Greg KH @ 2015-07-14  0:39 UTC (permalink / raw)
  To: Ulf Magnusson, linux-api-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	daniel-cYrQPVfZoowdnm+yROfE0A, dh.herrmann-gM/Ye1E23mwN+BqQ9rBEUg,
	tixxdz-Umm1ozX2/EEdnm+yROfE0A
In-Reply-To: <20150712180846.GA32176@huvuddator>

On Sun, Jul 12, 2015 at 08:08:46PM +0200, Ulf Magnusson wrote:
> Hello,
> 
> Tested with next-20150709.
> 
> Documentation/kdbus/Makefile lacks an 'installmandocs' target, causing
> problems for
> 
> %docs: scripts_basic FORCE
> 	$(Q)$(MAKE) $(build)=scripts build_docproc
> 	$(Q)$(MAKE) $(build)=Documentation/DocBook $@
> 	$(Q)$(MAKE) $(build)=Documentation/kdbus $@
> 
> from the top-level Makefile. It still works, but no KDBUS-related man
> pages are installed, and the final error isn't reassuring.

What's the final error?

> Documentation/DocBook/Makefile installs man pages into section 9, while
> KDBUS uses 7. I'm not familiar enough with KDBUS to know what the right
> thing to do here is.

I don't know either, perhaps someone on linux-api knows?

thanks,

greg k-h

^ permalink raw reply

* Re: KDBUS breaks 'make installmandocs'
From: Ulf Magnusson @ 2015-07-14  2:00 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-api, linux-kernel, daniel, dh.herrmann, tixxdz
In-Reply-To: <20150714003925.GA23746@kroah.com>

On Mon, Jul 13, 2015 at 05:39:25PM -0700, Greg KH wrote:
> On Sun, Jul 12, 2015 at 08:08:46PM +0200, Ulf Magnusson wrote:
> > Hello,
> > 
> > Tested with next-20150709.
> > 
> > Documentation/kdbus/Makefile lacks an 'installmandocs' target, causing
> > problems for
> > 
> > %docs: scripts_basic FORCE
> > 	$(Q)$(MAKE) $(build)=scripts build_docproc
> > 	$(Q)$(MAKE) $(build)=Documentation/DocBook $@
> > 	$(Q)$(MAKE) $(build)=Documentation/kdbus $@
> > 
> > from the top-level Makefile. It still works, but no KDBUS-related man
> > pages are installed, and the final error isn't reassuring.
> 
> What's the final error?
> 

$ sudo make installmandocs
  GEN     Documentation/DocBook//v4l2.xml
find Documentation/DocBook/man -name '*.9' | xargs gzip -f
mkdir -p /usr/local/man/man9/
install Documentation/DocBook/man/*.9.gz /usr/local/man/man9/
make[1]: *** No rule to make target 'installmandocs'.  Stop.
Makefile:1359: recipe for target 'installmandocs' failed
make: *** [installmandocs] Error 2


The "*** No rule to make target 'installmandocs'. Stop." error is
generated for Documentation/kdbus/Makefile. The other man pages still
install fine.

(That "GEN     Documentation/DocBook//v4l2.xml" line might be an
unrelated issue. It's from the 'mandocs' prerequisite and shows up even
when the pages are already built.)

> > Documentation/DocBook/Makefile installs man pages into section 9, while
> > KDBUS uses 7. I'm not familiar enough with KDBUS to know what the right
> > thing to do here is.
> 
> I don't know either, perhaps someone on linux-api knows?
> 
> thanks,
> 
> greg k-h

Cheers,
Ulf

^ permalink raw reply

* RE: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Ben Maurer @ 2015-07-14  9:34 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Paul Turner, Andrew Hunter, Peter Zijlstra, Ingo Molnar, rostedt,
	Paul E. McKenney, Josh Triplett, Lai Jiangshan, Linus Torvalds,
	Andrew Morton, linux-api, libc-alpha@sourceware.org
In-Reply-To: <587954201.31.1436808992876.JavaMail.zimbra@efficios.com>

Mathieu Desnoyers wrote:
> If we invoke this per-thread registration directly in the glibc NPTL implementation,
> in start_thread, do you think it would fit your requirements ?

I guess this would basically be transparent to the user -- we'd just need to make sure that the registration happens very early, before any chance of calling malloc.

That said, having the ability for the kernel to understand that TLS implementation are laid out using the same offset on each thread seems like something that could be valuable long term. Doing so makes it possible to build other TLS-based features without forcing each thread to be registered. 

^ permalink raw reply

* Re: [PATCH -mm v7 5/6] proc: add kpageidle file
From: Vladimir Davydov @ 2015-07-14 11:05 UTC (permalink / raw)
  To: Andres Lagar-Cavilla
  Cc: Andrew Morton, Minchan Kim, Raghavendra K T, Johannes Weiner,
	Michal Hocko, Greg Thelen, Michel Lespinasse, David Rientjes,
	Pavel Emelyanov, Cyrill Gorcunov, Jonathan Corbet, linux-api,
	linux-doc, linux-mm, cgroups, linux-kernel
In-Reply-To: <CAJu=L59+7d_16zXZAFfJkr5HSwHsfYXi9EBu_9Sx1tAcJv2LOA@mail.gmail.com>

On Mon, Jul 13, 2015 at 12:02:57PM -0700, Andres Lagar-Cavilla wrote:
> On Sat, Jul 11, 2015 at 7:48 AM, Vladimir Davydov
> <vdavydov@parallels.com> wrote:
[...]
> > +static struct page *kpageidle_get_page(unsigned long pfn)
> > +{
> > +       struct page *page;
> > +       struct zone *zone;
> > +
> > +       if (!pfn_valid(pfn))
> > +               return NULL;
> > +
> > +       page = pfn_to_page(pfn);
> > +       if (!page || PageTail(page) || !PageLRU(page) ||
> > +           !get_page_unless_zero(page))
> 
> get_page_unless_zero does not succeed for Tail pages.

True. So we don't seem to need the PageTail checks here at all, because
if kpageidle_get_page succeeds, the page must be a head, so that we
won't dive into expensive rmap_walk for tail pages. Will remove it then.

> 
> > +               return NULL;
> > +
> > +       if (unlikely(PageTail(page))) {
> > +               put_page(page);
> > +               return NULL;
> > +       }
> > +
> > +       zone = page_zone(page);
> > +       spin_lock_irq(&zone->lru_lock);
> > +       if (unlikely(!PageLRU(page))) {
> > +               put_page(page);
> > +               page = NULL;
> > +       }
> > +       spin_unlock_irq(&zone->lru_lock);
> > +       return page;
> > +}
> > +
> > +static int kpageidle_clear_pte_refs_one(struct page *page,
> > +                                       struct vm_area_struct *vma,
> > +                                       unsigned long addr, void *arg)
> > +{
> > +       struct mm_struct *mm = vma->vm_mm;
> > +       spinlock_t *ptl;
> > +       pmd_t *pmd;
> > +       pte_t *pte;
> > +       bool referenced = false;
> > +
> > +       if (unlikely(PageTransHuge(page))) {
> 
> VM_BUG_ON(!PageHead)?

Don't think it's necessary, because PageTransHuge already does this sort
of check:

: static inline int PageTransHuge(struct page *page)
: {
: 	VM_BUG_ON_PAGE(PageTail(page), page);
: 	return PageHead(page);
: }

> 
> > +               pmd = page_check_address_pmd(page, mm, addr,
> > +                                            PAGE_CHECK_ADDRESS_PMD_FLAG, &ptl);
> > +               if (pmd) {
> > +                       referenced = pmdp_test_and_clear_young(vma, addr, pmd);
> 
> For any workload using MMU notifiers, this will lose significant
> information by not querying the secondary PTE. The most
> straightforward case is KVM. Once mappings are setup, all access
> activity is recorded through shadow PTEs. This interface will say
> "idle" even though the VM is blasting memory.

Hmm, interesting. It seems we have to introduce
mmu_notifier_ops.clear_young then, which, in contrast to
clear_flush_young, won't flush TLB. Looking back at your comment to v6,
now I see that you already mentioned it, but I missed your point :-(
OK, will do it in the next iteration.

Thanks a lot for the review!

Vladimir

^ permalink raw reply

* Re: [PATCH RFC] vfs: add a O_NOMTIME flag
From: Pavel Machek @ 2015-07-14 11:44 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Richard Weinberger, Zach Brown, Dave Chinner, Alexander Viro,
	Sage Weil, linux-fsdevel, LKML, open list:ABI/API
In-Reply-To: <CALCETrWNDMq0nK3ac-uZweV5BKK_yWTQHH5D0YkyEu7bcONo9g@mail.gmail.com>

On Thu 2015-05-07 12:53:46, Andy Lutomirski wrote:
> On Thu, May 7, 2015 at 12:09 PM, Richard Weinberger
> <richard.weinberger@gmail.com> wrote:
> > On Thu, May 7, 2015 at 7:20 PM, Zach Brown <zab@redhat.com> wrote:
> >> On Thu, May 07, 2015 at 10:26:17AM +1000, Dave Chinner wrote:
> >>> On Wed, May 06, 2015 at 03:00:12PM -0700, Zach Brown wrote:
> >>> > Add the O_NOMTIME flag which prevents mtime from being updated which can
> >>> > greatly reduce the IO overhead of writes to allocated and initialized
> >>> > regions of files.
> >>>
> >>> Hmmm. How do backup programs now work out if the file has changed
> >>> and hence needs copying again? ie. applications using this will
> >>> break other critical infrastructure in subtle ways.
> >>
> >> By using backup infrastructure that doesn't use cmtime.  Like btrfs
> >> send/recv.  Or application level backups that know how to do
> >> incrementals from metadata in giant database files, say, without
> >> walking, comparing, and copying the entire thing.
> >
> > But how can Joey random user know that some of his
> > applications are using O_NOMTIME and his KISS backup
> > program does no longer function as expected?
> >
> 
> Joey random user can't have a working KISS backup anyway, though,
> because we screw up mtime updates on mmap writes.  I have patches
> gathering dust that fix that, though.

I'm using unison, and yes, I believe I already seen failures from
mmap(). I'd like to see that fixed, and I can test the patches.

Thanks,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox