* Re: [RFC PATCH 2/3] topology: support node_numa_mem() for determining the fallback node
From: Joonsoo Kim @ 2014-02-11 7:42 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Han Pingtian, Matt Mackall, Pekka Enberg,
Linux Memory Management List, Paul Mackerras, Anton Blanchard,
David Rientjes, Christoph Lameter, linuxppc-dev, Wanpeng Li
In-Reply-To: <20140210191321.GD1558@linux.vnet.ibm.com>
On Mon, Feb 10, 2014 at 11:13:21AM -0800, Nishanth Aravamudan wrote:
> Hi Christoph,
>
> On 07.02.2014 [12:51:07 -0600], Christoph Lameter wrote:
> > Here is a draft of a patch to make this work with memoryless nodes.
> >
> > The first thing is that we modify node_match to also match if we hit an
> > empty node. In that case we simply take the current slab if its there.
> >
> > If there is no current slab then a regular allocation occurs with the
> > memoryless node. The page allocator will fallback to a possible node and
> > that will become the current slab. Next alloc from a memoryless node
> > will then use that slab.
> >
> > For that we also add some tracking of allocations on nodes that were not
> > satisfied using the empty_node[] array. A successful alloc on a node
> > clears that flag.
> >
> > I would rather avoid the empty_node[] array since its global and there may
> > be thread specific allocation restrictions but it would be expensive to do
> > an allocation attempt via the page allocator to make sure that there is
> > really no page available from the page allocator.
>
> With this patch on our test system (I pulled out the numa_mem_id()
> change, since you Acked Joonsoo's already), on top of 3.13.0 + my
> kthread locality change + CONFIG_HAVE_MEMORYLESS_NODES + Joonsoo's RFC
> patch 1):
>
> MemTotal: 8264704 kB
> MemFree: 5924608 kB
> ...
> Slab: 1402496 kB
> SReclaimable: 102848 kB
> SUnreclaim: 1299648 kB
>
> And Anton's slabusage reports:
>
> slab mem objs slabs
> used active active
> ------------------------------------------------------------
> kmalloc-16384 207 MB 98.60% 100.00%
> task_struct 134 MB 97.82% 100.00%
> kmalloc-8192 117 MB 100.00% 100.00%
> pgtable-2^12 111 MB 100.00% 100.00%
> pgtable-2^10 104 MB 100.00% 100.00%
>
> For comparison, Anton's patch applied at the same point in the series:
>
> meminfo:
>
> MemTotal: 8264704 kB
> MemFree: 4150464 kB
> ...
> Slab: 1590336 kB
> SReclaimable: 208768 kB
> SUnreclaim: 1381568 kB
>
> slabusage:
>
> slab mem objs slabs
> used active active
> ------------------------------------------------------------
> kmalloc-16384 227 MB 98.63% 100.00%
> kmalloc-8192 130 MB 100.00% 100.00%
> task_struct 129 MB 97.73% 100.00%
> pgtable-2^12 112 MB 100.00% 100.00%
> pgtable-2^10 106 MB 100.00% 100.00%
>
>
> Consider this patch:
>
> Acked-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
> Tested-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
Hello,
I still think that there is another problem.
Your report about CONFIG_SLAB said that SLAB uses just 200MB.
Below is your previous report.
Ok, with your patches applied and CONFIG_SLAB enabled:
MemTotal: 8264640 kB
MemFree: 7119680 kB
Slab: 207232 kB
SReclaimable: 32896 kB
SUnreclaim: 174336 kB
The number on CONFIG_SLUB with these patches tell us that SLUB uses 1.4GB.
There is large difference on slab usage.
And, I should note that number of active objects on slabinfo can be wrong
on some situation, since it doesn't consider cpu slab (and cpu partial slab).
I recommend to confirm page_to_nid() and other things as I mentioned earlier.
Thanks.
^ permalink raw reply
* Re: arch/powerpc/math-emu/mtfsf.c - incorrect mask?
From: Gabriel Paubert @ 2014-02-11 7:26 UTC (permalink / raw)
To: James Yang; +Cc: Chris Proctor, Stephen N Chivers, linuxppc-dev
In-Reply-To: <alpine.LRH.2.00.1402101056410.10318@ra8135-ec1.am.freescale.net>
Hi James,
On Mon, Feb 10, 2014 at 11:03:07AM -0600, James Yang wrote:
[snipped]
> > Ok, if you have measured that method1 is faster than method2, let us go for it.
> > I believe method2 would be faster if you had a large out-of-order execution
> > window, because more parallelism can be extracted from it, but this is probably
> > only true for high end cores, which do not need FPU emulation in the first place.
>
> Yeah, 8548 can issue 2 SFX instructions per cycle which is what the
> compiler generated.
>
Then it is method1.
>
> > The other place where we can optimize is the generation of FEX. Here is
> > my current patch:
> >
> >
> > diff --git a/arch/powerpc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c
> > index dbce92e..b57b3fa8 100644
> > --- a/arch/powerpc/math-emu/mtfsf.c
> > +++ b/arch/powerpc/math-emu/mtfsf.c
> > @@ -11,48 +11,35 @@ mtfsf(unsigned int FM, u32 *frB)
> > u32 mask;
> > u32 fpscr;
> >
> > - if (FM == 0)
> > + if (likely(FM == 0xff))
> > + mask = 0xffffffff;
> > + else if (unlikely(FM == 0))
> > return 0;
> > -
> > - if (FM == 0xff)
> > - mask = 0x9fffffff;
> > else {
> > - mask = 0;
> > - if (FM & (1 << 0))
> > - mask |= 0x90000000;
> > - if (FM & (1 << 1))
> > - mask |= 0x0f000000;
> > - if (FM & (1 << 2))
> > - mask |= 0x00f00000;
> > - if (FM & (1 << 3))
> > - mask |= 0x000f0000;
> > - if (FM & (1 << 4))
> > - mask |= 0x0000f000;
> > - if (FM & (1 << 5))
> > - mask |= 0x00000f00;
> > - if (FM & (1 << 6))
> > - mask |= 0x000000f0;
> > - if (FM & (1 << 7))
> > - mask |= 0x0000000f;
> > + mask = (FM & 1);
> > + mask |= (FM << 3) & 0x10;
> > + mask |= (FM << 6) & 0x100;
> > + mask |= (FM << 9) & 0x1000;
> > + mask |= (FM << 12) & 0x10000;
> > + mask |= (FM << 15) & 0x100000;
> > + mask |= (FM << 18) & 0x1000000;
> > + mask |= (FM << 21) & 0x10000000;
> > + mask *= 15;
>
>
> Needs to also mask out bits 1 and 2, they aren't to be set from frB.
>
> mask &= 0x9FFFFFFF;
>
>
Look at the following lines:
>
>
> > }
> >
> > - __FPU_FPSCR &= ~(mask);
> > - __FPU_FPSCR |= (frB[1] & mask);
> > + fpscr = ((__FPU_FPSCR & ~mask) | (frB[1] & mask)) &
> > + ~(FPSCR_VX | FPSCR_FEX);
It's here (masking FPSCR_VX and FPSCR_FEX).
Actually the previous code was redundant, it cleared FEX and VX in the
mask computation and later again when recomputing them. Clearing them
once should be enough.
> >
> > - __FPU_FPSCR &= ~(FPSCR_VX);
> > - if (__FPU_FPSCR & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI |
> > + if (fpscr & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI |
> > FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC |
> > FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI))
> > - __FPU_FPSCR |= FPSCR_VX;
> > -
> > - fpscr = __FPU_FPSCR;
> > - fpscr &= ~(FPSCR_FEX);
> > - if (((fpscr & FPSCR_VX) && (fpscr & FPSCR_VE)) ||
> > - ((fpscr & FPSCR_OX) && (fpscr & FPSCR_OE)) ||
> > - ((fpscr & FPSCR_UX) && (fpscr & FPSCR_UE)) ||
> > - ((fpscr & FPSCR_ZX) && (fpscr & FPSCR_ZE)) ||
> > - ((fpscr & FPSCR_XX) && (fpscr & FPSCR_XE)))
> > - fpscr |= FPSCR_FEX;
> > + fpscr |= FPSCR_VX;
> > +
> > + /* The bit order of exception enables and exception status
> > + * is the same. Simply shift and mask to check for enabled
> > + * exceptions.
> > + */
> > + if (fpscr & (fpscr >> 22) & 0xf8) fpscr |= FPSCR_FEX;
> > __FPU_FPSCR = fpscr;
> >
> > #ifdef DEBUG
> > mtfsf.c | 57 ++++++++++++++++++++++-----------------------------------
> > 1 file changed, 22 insertions(+), 35 deletions(-)
> >
> >
> > Notes:
> >
> > 1) I'm really unsure on whether 0xff is frequent or not. So the likely()
> > statement at the beginning may be wrong. Actually, if it is not very likely,
> > it might be better to remove the special casef for FM==0xff. A look at
> > GCC sources shows that it never generates a mask of 0xff. From glibc
> > sources, there vast majority of cases uses 0x1, only isnan() uses 0xff.
>
> Can't handle all cases here.
That's why I would go for the simplest possible code. Conditionals are
expensive and minimizing cache footprint is often the best measure of
performance for infrequently used code. With this in mind, I would get
rid of all the tests for special FM values and rely on the optimized
generic case.
>
> > 2) it may be better to remove the check for FM==0, after all, the instruction
> > effectively becomes a nop, and generating the instruction in the first place
> > would be too stupid for words.
>
> Hmm a heavy no-op. I wonder if it is heavier than a sync.
In theory not. It contains the equivalent of several isync (taking an exception
and returning from it), but not any synchronization wrt the memory accesses.
Gabriel
^ permalink raw reply
* Re: [PATCH] powerpc/spufs: Remove MAX_USER_PRIO define
From: Kamalesh Babulal @ 2014-02-11 8:15 UTC (permalink / raw)
To: Jeremy Kerr; +Cc: Dongsheng Yang, linuxppc-dev, Ingo Molnar, linux-kernel
In-Reply-To: <1392098717.689604.970589769393.1.gpush@pablo>
* Jeremy Kerr <jk@ozlabs.org> [2014-02-11 14:05:17]:
> Current ppc64_defconfig fails with:
>
> arch/powerpc/platforms/cell/spufs/sched.c:86:0: error: "MAX_USER_PRIO" redefined [-Werror]
> cc1: all warnings being treated as errors
>
> 6b6350f1 introduced a generic MAX_USER_PRIO macro to sched/prio.h, which
> is causing the conflit. Use that one instead of our own.
you can also use DEFAULT_PRIO from sched/prio.h instead of NORMAL_PRIO.
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 49318385d4fa..014979db2018 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -64,11 +64,6 @@ static struct timer_list spusched_timer;
static struct timer_list spuloadavg_timer;
/*
- * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
- */
-#define NORMAL_PRIO 120
-
-/*
* Frequency of the spu scheduler tick. By default we do one SPU scheduler
* tick for every 10 CPU scheduler ticks.
*/
@@ -97,7 +92,7 @@ static struct timer_list spuloadavg_timer;
*/
void spu_set_timeslice(struct spu_context *ctx)
{
- if (ctx->prio < NORMAL_PRIO)
+ if (ctx->prio < DEFAULT_PRIO)
ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio);
else
ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio);
Thanks,
Kamalesh.
^ permalink raw reply related
* Re: [PATCH v1 2/2] powernv, cpufreq: Add per-core locking to serialize frequency transitions
From: Preeti U Murthy @ 2014-02-11 8:15 UTC (permalink / raw)
To: Vaidyanathan Srinivasan; +Cc: linuxppc-dev, Anton Blanchard, Srivatsa S. Bhat
In-Reply-To: <20140211070208.21159.86862.stgit@drishya>
Hi Vaidy,
On 02/11/2014 12:32 PM, Vaidyanathan Srinivasan wrote:
> From: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
>
> On POWER systems, the CPU frequency is controlled at a core-level and
> hence we need to serialize so that only one of the threads in the core
> switches the core's frequency at a time.
>
> Using a global mutex lock would needlessly serialize _all_ frequency
> transitions in the system (across all cores). So introduce per-core
> locking to enable finer-grained synchronization and thereby enhance
> the speed and responsiveness of the cpufreq driver to varying workload
> demands.
>
> The design of per-core locking is very simple and straight-forward: we
> first define a Per-CPU lock and use the ones that belongs to the first
> thread sibling of the core.
>
> cpu_first_thread_sibling() macro is used to find the *common* lock for
> all thread siblings belonging to a core.
>
> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
> Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
> ---
> drivers/cpufreq/powernv-cpufreq.c | 21 ++++++++++++++++-----
> 1 file changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
> index ea3b630..8240e90 100644
> --- a/drivers/cpufreq/powernv-cpufreq.c
> +++ b/drivers/cpufreq/powernv-cpufreq.c
> @@ -24,8 +24,15 @@
> #include <linux/of.h>
> #include <asm/cputhreads.h>
>
> -/* FIXME: Make this per-core */
> -static DEFINE_MUTEX(freq_switch_mutex);
> +/* Per-Core locking for frequency transitions */
> +static DEFINE_PER_CPU(struct mutex, freq_switch_lock);
> +
> +#define lock_core_freq(cpu) \
> + mutex_lock(&per_cpu(freq_switch_lock,\
> + cpu_first_thread_sibling(cpu)));
> +#define unlock_core_freq(cpu) \
> + mutex_unlock(&per_cpu(freq_switch_lock,\
> + cpu_first_thread_sibling(cpu)));
>
> #define POWERNV_MAX_PSTATES 256
>
> @@ -219,7 +226,7 @@ static int powernv_cpufreq_target(struct cpufreq_policy *policy,
> freqs.new = powernv_freqs[new_index].frequency;
> freqs.cpu = policy->cpu;
>
> - mutex_lock(&freq_switch_mutex);
> + lock_core_freq(policy->cpu);
> cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
>
> pr_debug("setting frequency for cpu %d to %d kHz index %d pstate %d",
> @@ -231,7 +238,7 @@ static int powernv_cpufreq_target(struct cpufreq_policy *policy,
> rc = powernv_set_freq(policy->cpus, new_index);
>
> cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
> - mutex_unlock(&freq_switch_mutex);
> + unlock_core_freq(policy->cpu);
>
> return rc;
> }
> @@ -248,7 +255,7 @@ static struct cpufreq_driver powernv_cpufreq_driver = {
>
> static int __init powernv_cpufreq_init(void)
> {
> - int rc = 0;
> + int cpu, rc = 0;
>
> /* Discover pstates from device tree and init */
>
> @@ -258,6 +265,10 @@ static int __init powernv_cpufreq_init(void)
> pr_info("powernv-cpufreq disabled\n");
> return rc;
> }
> + /* Init per-core mutex */
> + for_each_possible_cpu(cpu) {
> + mutex_init(&per_cpu(freq_switch_lock, cpu));
> + }
>
> rc = cpufreq_register_driver(&powernv_cpufreq_driver);
> return rc;
This looks good to me.
Reviewed-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Thanks
Regards
Preeti U Murthy
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH v1 1/2] powernv: cpufreq driver for powernv platform
From: Preeti U Murthy @ 2014-02-11 8:37 UTC (permalink / raw)
To: Vaidyanathan Srinivasan; +Cc: linuxppc-dev, Anton Blanchard, Srivatsa S. Bhat
In-Reply-To: <20140211070201.21159.31101.stgit@drishya>
Hi Vaidy,
On 02/11/2014 12:32 PM, Vaidyanathan Srinivasan wrote:
> Backend driver to dynamically set voltage and frequency on
> IBM POWER non-virtualized platforms. Power management SPRs
> are used to set the required PState.
>
> This driver works in conjunction with cpufreq governors
> like 'ondemand' to provide a demand based frequency and
> voltage setting on IBM POWER non-virtualized platforms.
>
> PState table is obtained from OPAL v3 firmware through device
> tree.
>
> powernv_cpufreq back-end driver would parse the relevant device-tree
> nodes and initialise the cpufreq subsystem on powernv platform.
>
> Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
> Signed-off-by: Anton Blanchard <anton@samba.org>
> ---
<snip>
> +static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
> +{
> + int base, i;
> +
> +#ifdef CONFIG_SMP
> + base = cpu_first_thread_sibling(policy->cpu);
> +
> + for (i = 0; i < threads_per_core; i++)
> + cpumask_set_cpu(base + i, policy->cpus);
> +#endif
> + policy->cpuinfo.transition_latency = 25000;
Is it ok to hard code this field? How about getting this also from the
device tree?
> +
> + /* Print frequency table */
> + for (i = 0; powernv_freqs[i].frequency != CPUFREQ_TABLE_END; i++)
> + pr_debug("%d: %d\n", i, powernv_freqs[i].frequency);
The frequency table as a result will be printed on every cpu when
cpufreq gets initialized. Considering this information will not vary
across CPUs, can we print this during powernv_cpufreq_init() after
parsing the device tree for the pstates?
Thanks
Regards
Preeti U Murthy
^ permalink raw reply
* Re: [PATCH v2] powerpc ticket locks
From: Raghavendra KT @ 2014-02-11 9:39 UTC (permalink / raw)
To: Torsten Duwe
Cc: Tom Musta, Peter Zijlstra, Raghavendra KT,
Linux Kernel Mailing List, Paul Mackerras, Anton Blanchard,
Scott Wood, Paul E. McKenney, linuxppc-dev, Ingo Molnar
In-Reply-To: <20140207165801.GC2107@lst.de>
On Fri, Feb 7, 2014 at 10:28 PM, Torsten Duwe <duwe@lst.de> wrote:
> Ticket locks for ppc, version 2. Changes since v1:
> * The atomically exchanged entity is always 32 bits.
> * asm inline string variations thus removed.
> * Carry the additional holder hint only #if defined(CONFIG_PPC_SPLPAR)
>
> Signed-off-by: Torsten Duwe <duwe@suse.de>
> --
[...]
> +static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
> {
> + register struct __raw_tickets old, tmp,
> + inc = { .tail = TICKET_LOCK_INC };
> +
> CLEAR_IO_SYNC;
> - while (1) {
> - if (likely(__arch_spin_trylock(lock) == 0))
> - break;
> + __asm__ __volatile__(
> +"1: lwarx %0,0,%4 # arch_spin_lock\n"
> +" add %1,%3,%0\n"
> + PPC405_ERR77(0, "%4")
> +" stwcx. %1,0,%4\n"
> +" bne- 1b"
> + : "=&r" (old), "=&r" (tmp), "+m" (lock->tickets)
> + : "r" (inc), "r" (&lock->tickets)
> + : "cc");
> +
> + if (likely(old.head == old.tail))
> + goto out;
> +
> + for (;;) {
> + unsigned count = 100;
I am sure you wanted to tune the total loops to typical lock holding time ...
^ permalink raw reply
* [PATCH] powerpc/spufs: Fix duplicate definition of MAX_USER_PRIO
From: Peter Zijlstra @ 2014-02-11 9:41 UTC (permalink / raw)
To: kbuild test robot
Cc: Dongsheng Yang, Arnd Bergmann, linux-kernel, kbuild-all,
linuxppc-dev, Ingo Molnar
In-Reply-To: <52f92761.nu9w3QblrTnGpeYg%fengguang.wu@intel.com>
On Tue, Feb 11, 2014 at 03:24:17AM +0800, kbuild test robot wrote:
> >> arch/powerpc/platforms/cell/spufs/sched.c:86:0: warning: "MAX_USER_PRIO" redefined [enabled by default]
> #define MAX_USER_PRIO (MAX_PRIO - MAX_RT_PRIO)
> ^
> In file included from include/linux/sched.h:6:0,
> from arch/powerpc/platforms/cell/spufs/sched.c:26:
> include/linux/sched/prio.h:39:0: note: this is the location of the previous definition
> #define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
> ^
Since USER_PRIO(p) is ((p)-MAX_RT_PRIO) the above two definitions are
the same and we can simply remove the spufs one.
Fixes: 6b6350f155af ("sched: Expose some macros related to priority")
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
---
arch/powerpc/platforms/cell/spufs/sched.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 49318385d4fa..4a0a64fe25df 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -83,7 +83,6 @@ static struct timer_list spuloadavg_timer;
#define MIN_SPU_TIMESLICE max(5 * HZ / (1000 * SPUSCHED_TICK), 1)
#define DEF_SPU_TIMESLICE (100 * HZ / (1000 * SPUSCHED_TICK))
-#define MAX_USER_PRIO (MAX_PRIO - MAX_RT_PRIO)
#define SCALE_PRIO(x, prio) \
max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
^ permalink raw reply related
* Re: [PATCH v2] powerpc ticket locks
From: Raghavendra KT @ 2014-02-11 9:53 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Torsten Duwe
Cc: Tom Musta, Peter Zijlstra, Raghavendra KT,
Linux Kernel Mailing List, Paul Mackerras, Anton Blanchard,
Scott Wood, Paul E. McKenney, linuxppc-dev, Ingo Molnar
In-Reply-To: <1392001823.3996.21.camel@pasglop>
On Mon, Feb 10, 2014 at 8:40 AM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Fri, 2014-02-07 at 17:58 +0100, Torsten Duwe wrote:
>> typedef struct {
>> - volatile unsigned int slock;
>> -} arch_spinlock_t;
>> + union {
>> + __ticketpair_t head_tail;
>> + struct __raw_tickets {
>> +#ifdef __BIG_ENDIAN__ /* The "tail" part should be in the MSBs */
>> + __ticket_t tail, head;
>> +#else
>> + __ticket_t head, tail;
>> +#endif
>> + } tickets;
>> + };
>> +#if defined(CONFIG_PPC_SPLPAR)
>> + u32 holder;
>> +#endif
>> +} arch_spinlock_t __aligned(4);
>
> That's still broken with lockref (which we just merged).
>
> We must have the arch_spinlock_t and the ref in the same 64-bit word
> otherwise it will break.
>
> We can make it work in theory since the holder doesn't have to be
> accessed atomically, but the practicals are a complete mess ...
> lockref would essentially have to re-implement the holder handling
> of the spinlocks and use lower level ticket stuff.
>
Probably very basic and stupid question from me.
How much important to have holder information for PPC? From my
previous experiment
on x86, it was lock-waiter preemption which is problematic rather than
lock-holder preemption.
^ permalink raw reply
* Re: [PATCH V4 2/3] tick/cpuidle: Initialize hrtimer mode of broadcast
From: Daniel Lezcano @ 2014-02-11 10:16 UTC (permalink / raw)
To: Preeti U Murthy, linux-pm, peterz, benh, rafael.j.wysocki,
linux-kernel, tglx, linuxppc-dev, mingo
Cc: deepthi, fweisbec, paulus, srivatsa.bhat, paulmck
In-Reply-To: <20140207080632.17187.80532.stgit@preeti.in.ibm.com>
On 02/07/2014 09:06 AM, Preeti U Murthy wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
>
> On some architectures, in certain CPU deep idle states the local timers stop.
> An external clock device is used to wakeup these CPUs. The kernel support for the
> wakeup of these CPUs is provided by the tick broadcast framework by using the
> external clock device as the wakeup source.
>
> However not all implementations of architectures provide such an external
> clock device. This patch includes support in the broadcast framework to handle
> the wakeup of the CPUs in deep idle states on such systems by queuing a hrtimer
> on one of the CPUs, which is meant to handle the wakeup of CPUs in deep idle states.
>
> This patchset introduces a pseudo clock device which can be registered by the
> archs as tick_broadcast_device in the absence of a real external clock
> device. Once registered, the broadcast framework will work as is for these
> architectures as long as the archs take care of the BROADCAST_ENTER
> notification failing for one of the CPUs. This CPU is made the stand by CPU to
> handle wakeup of the CPUs in deep idle and it *must not enter deep idle states*.
>
> The CPU with the earliest wakeup is chosen to be this CPU. Hence this way the
> stand by CPU dynamically moves around and so does the hrtimer which is queued
> to trigger at the next earliest wakeup time. This is consistent with the case where
> an external clock device is present. The smp affinity of this clock device is
> set to the CPU with the earliest wakeup.
Hi Preeti,
jumping a bit late in the thread...
Setting the smp affinity on the earliest timer should be handled
automatically with the CLOCK_EVT_FEAT_DYNIRQ flag. Did you look at using
this flag ?
Another comment is the overall approach. We enter the cpuidle idle
framework with a specific state to go to and it is the tick framework
telling us we mustn't go to this state. IMO the logic is wrong, the
decision to not enter this state should be moved somewhere else.
Why don't you create a cpuidle driver with the shallow idle states
assigned to a cpu (let's say cpu0) and another one with all the deeper
idle states for the rest of the cpus ? Using the multiple cpuidle driver
support makes it possible. The timer won't be moving around and a cpu
will be dedicated to act as the broadcast timer.
Wouldn't make sense and be less intrusive than the patchset you proposed ?
> This patchset handles the hotplug of
> the stand by CPU as well by moving the hrtimer on to the CPU handling the CPU_DEAD
> notification.
>
> Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
> [Added Changelog and code to handle reprogramming of hrtimer]
> ---
>
> include/linux/clockchips.h | 9 +++
> kernel/time/Makefile | 2 -
> kernel/time/tick-broadcast-hrtimer.c | 105 ++++++++++++++++++++++++++++++++++
> kernel/time/tick-broadcast.c | 54 +++++++++++++++++
> 4 files changed, 166 insertions(+), 4 deletions(-)
> create mode 100644 kernel/time/tick-broadcast-hrtimer.c
>
> diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
> index e0c5a6c..dbe9e14 100644
> --- a/include/linux/clockchips.h
> +++ b/include/linux/clockchips.h
> @@ -62,6 +62,11 @@ enum clock_event_mode {
> #define CLOCK_EVT_FEAT_DYNIRQ 0x000020
> #define CLOCK_EVT_FEAT_PERCPU 0x000040
>
> +/*
> + * Clockevent device is based on a hrtimer for broadcast
> + */
> +#define CLOCK_EVT_FEAT_HRTIMER 0x000080
> +
> /**
> * struct clock_event_device - clock event device descriptor
> * @event_handler: Assigned by the framework to be called by the low
> @@ -83,6 +88,7 @@ enum clock_event_mode {
> * @name: ptr to clock event name
> * @rating: variable to rate clock event devices
> * @irq: IRQ number (only for non CPU local devices)
> + * @bound_on: Bound on CPU
> * @cpumask: cpumask to indicate for which CPUs this device works
> * @list: list head for the management code
> * @owner: module reference
> @@ -113,6 +119,7 @@ struct clock_event_device {
> const char *name;
> int rating;
> int irq;
> + int bound_on;
> const struct cpumask *cpumask;
> struct list_head list;
> struct module *owner;
> @@ -180,9 +187,11 @@ extern int tick_receive_broadcast(void);
> #endif
>
> #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
> +extern void tick_setup_hrtimer_broadcast(void);
> extern int tick_check_broadcast_expired(void);
> #else
> static inline int tick_check_broadcast_expired(void) { return 0; }
> +static void tick_setup_hrtimer_broadcast(void) {};
> #endif
>
> #ifdef CONFIG_GENERIC_CLOCKEVENTS
> diff --git a/kernel/time/Makefile b/kernel/time/Makefile
> index 9250130..06151ef 100644
> --- a/kernel/time/Makefile
> +++ b/kernel/time/Makefile
> @@ -3,7 +3,7 @@ obj-y += timeconv.o posix-clock.o alarmtimer.o
>
> obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o
> obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o
> -obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o
> +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o tick-broadcast-hrtimer.o
> obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o
> obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o
> obj-$(CONFIG_TICK_ONESHOT) += tick-sched.o
> diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c
> new file mode 100644
> index 0000000..af1e119
> --- /dev/null
> +++ b/kernel/time/tick-broadcast-hrtimer.c
> @@ -0,0 +1,105 @@
> +/*
> + * linux/kernel/time/tick-broadcast-hrtimer.c
> + * This file emulates a local clock event device
> + * via a pseudo clock device.
> + */
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/hrtimer.h>
> +#include <linux/interrupt.h>
> +#include <linux/percpu.h>
> +#include <linux/profile.h>
> +#include <linux/clockchips.h>
> +#include <linux/sched.h>
> +#include <linux/smp.h>
> +#include <linux/module.h>
> +
> +#include "tick-internal.h"
> +
> +static struct hrtimer bctimer;
> +
> +static void bc_set_mode(enum clock_event_mode mode,
> + struct clock_event_device *bc)
> +{
> + switch (mode) {
> + case CLOCK_EVT_MODE_SHUTDOWN:
> + /*
> + * Note, we cannot cancel the timer here as we might
> + * run into the following live lock scenario:
> + *
> + * cpu 0 cpu1
> + * lock(broadcast_lock);
> + * hrtimer_interrupt()
> + * bc_handler()
> + * tick_handle_oneshot_broadcast();
> + * lock(broadcast_lock);
> + * hrtimer_cancel()
> + * wait_for_callback()
> + */
> + hrtimer_try_to_cancel(&bctimer);
> + break;
> + default:
> + break;
> + }
> +}
> +
> +/*
> + * This is called from the guts of the broadcast code when the cpu
> + * which is about to enter idle has the earliest broadcast timer event.
> + */
> +static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
> +{
> + /*
> + * We try to cancel the timer first. If the callback is on
> + * flight on some other cpu then we let it handle it. If we
> + * were able to cancel the timer nothing can rearm it as we
> + * own broadcast_lock.
> + *
> + * However we can also be called from the event handler of
> + * ce_broadcast_hrtimer itself when it expires. We cannot therefore
> + * restart the timer since it is on flight on the same CPU. But
> + * due to the same reason we can reset it.
> + */
> + if (hrtimer_try_to_cancel(&bctimer) >= 0) {
> + hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED);
> + /* Bind the "device" to the cpu */
> + bc->bound_on = smp_processor_id();
> + } else if (bc->bound_on == smp_processor_id()) {
> + hrtimer_set_expires(&bctimer, expires);
> + }
> + return 0;
> +}
> +
> +static struct clock_event_device ce_broadcast_hrtimer = {
> + .set_mode = bc_set_mode,
> + .set_next_ktime = bc_set_next,
> + .features = CLOCK_EVT_FEAT_ONESHOT |
> + CLOCK_EVT_FEAT_KTIME |
> + CLOCK_EVT_FEAT_HRTIMER,
> + .rating = 0,
> + .bound_on = -1,
> + .min_delta_ns = 1,
> + .max_delta_ns = KTIME_MAX,
> + .min_delta_ticks = 1,
> + .max_delta_ticks = KTIME_MAX,
> + .mult = 1,
> + .shift = 0,
> + .cpumask = cpu_all_mask,
> +};
> +
> +static enum hrtimer_restart bc_handler(struct hrtimer *t)
> +{
> + ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer);
> +
> + if (ce_broadcast_hrtimer.next_event.tv64 == KTIME_MAX)
> + return HRTIMER_NORESTART;
> +
> + return HRTIMER_RESTART;
> +}
> +
> +void tick_setup_hrtimer_broadcast(void)
> +{
> + hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
> + bctimer.function = bc_handler;
> + clockevents_register_device(&ce_broadcast_hrtimer);
> +}
> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
> index ddf2ac2..2f013c3 100644
> --- a/kernel/time/tick-broadcast.c
> +++ b/kernel/time/tick-broadcast.c
> @@ -630,6 +630,42 @@ again:
> raw_spin_unlock(&tick_broadcast_lock);
> }
>
> +static int broadcast_needs_cpu(struct clock_event_device *bc, int cpu)
> +{
> + if (!(bc->features & CLOCK_EVT_FEAT_HRTIMER))
> + return 0;
> + if (bc->next_event.tv64 == KTIME_MAX)
> + return 0;
> + return bc->bound_on == cpu ? -EBUSY : 0;
> +}
> +
> +static void broadcast_shutdown_local(struct clock_event_device *bc,
> + struct clock_event_device *dev)
> +{
> + /*
> + * For hrtimer based broadcasting we cannot shutdown the cpu
> + * local device if our own event is the first one to expire or
> + * if we own the broadcast timer.
> + */
> + if (bc->features & CLOCK_EVT_FEAT_HRTIMER) {
> + if (broadcast_needs_cpu(bc, smp_processor_id()))
> + return;
> + if (dev->next_event.tv64 < bc->next_event.tv64)
> + return;
> + }
> + clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
> +}
> +
> +static void broadcast_move_bc(int deadcpu)
> +{
> + struct clock_event_device *bc = tick_broadcast_device.evtdev;
> +
> + if (!bc || !broadcast_needs_cpu(bc, deadcpu))
> + return;
> + /* This moves the broadcast assignment to this cpu */
> + clockevents_program_event(bc, bc->next_event, 1);
> +}
> +
> /*
> * Powerstate information: The system enters/leaves a state, where
> * affected devices might stop
> @@ -648,7 +684,7 @@ int tick_broadcast_oneshot_control(unsigned long reason)
> * states
> */
> if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
> - return;
> + return 0;
>
> /*
> * We are called with preemtion disabled from the depth of the
> @@ -659,7 +695,7 @@ int tick_broadcast_oneshot_control(unsigned long reason)
> dev = td->evtdev;
>
> if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
> - return;
> + return 0;
>
> bc = tick_broadcast_device.evtdev;
>
> @@ -667,7 +703,7 @@ int tick_broadcast_oneshot_control(unsigned long reason)
> if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
> if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
> WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
> - clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
> + broadcast_shutdown_local(bc, dev);
> /*
> * We only reprogram the broadcast timer if we
> * did not mark ourself in the force mask and
> @@ -680,6 +716,16 @@ int tick_broadcast_oneshot_control(unsigned long reason)
> dev->next_event.tv64 < bc->next_event.tv64)
> tick_broadcast_set_event(bc, cpu, dev->next_event, 1);
> }
> + /*
> + * If the current CPU owns the hrtimer broadcast
> + * mechanism, it cannot go deep idle and we remove the
> + * CPU from the broadcast mask. We don't have to go
> + * through the EXIT path as the local timer is not
> + * shutdown.
> + */
> + ret = broadcast_needs_cpu(bc, cpu);
> + if (ret)
> + cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
> } else {
> if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) {
> clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
> @@ -853,6 +899,8 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
> cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
> cpumask_clear_cpu(cpu, tick_broadcast_force_mask);
>
> + broadcast_move_bc(cpu);
> +
> raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
> }
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 2/3] mm: dirty accountable change only apply to non prot numa case
From: Aneesh Kumar K.V @ 2014-02-11 10:34 UTC (permalink / raw)
To: benh, paulus, riel, mgorman, mpe; +Cc: linux-mm, linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1392114895-14997-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
So move it within the if loop
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
mm/mprotect.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 7332c1785744..33eab902f10e 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -58,6 +58,13 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
if (pte_numa(ptent))
ptent = pte_mknonnuma(ptent);
ptent = pte_modify(ptent, newprot);
+ /*
+ * Avoid taking write faults for pages we
+ * know to be dirty.
+ */
+ if (dirty_accountable && pte_dirty(ptent))
+ ptent = pte_mkwrite(ptent);
+ ptep_modify_prot_commit(mm, addr, pte, ptent);
updated = true;
} else {
struct page *page;
@@ -72,22 +79,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
}
}
}
-
- /*
- * Avoid taking write faults for pages we know to be
- * dirty.
- */
- if (dirty_accountable && pte_dirty(ptent)) {
- ptent = pte_mkwrite(ptent);
- updated = true;
- }
-
if (updated)
pages++;
-
- /* Only !prot_numa always clears the pte */
- if (!prot_numa)
- ptep_modify_prot_commit(mm, addr, pte, ptent);
} else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
swp_entry_t entry = pte_to_swp_entry(oldpte);
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/3] powerpc: mm: Add new set flag argument to pte/pmd update function
From: Aneesh Kumar K.V @ 2014-02-11 10:34 UTC (permalink / raw)
To: benh, paulus, riel, mgorman, mpe; +Cc: linux-mm, linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1392114895-14997-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
We will use this later to set the _PAGE_NUMA bit.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/hugetlb.h | 2 +-
arch/powerpc/include/asm/pgtable-ppc64.h | 26 +++++++++++++++-----------
arch/powerpc/mm/pgtable_64.c | 12 +++++++-----
arch/powerpc/mm/subpage-prot.c | 2 +-
4 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index d750336b171d..623f2971ce0e 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -127,7 +127,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_PPC64
- return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+ return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 1));
#else
return __pte(pte_update(ptep, ~0UL, 0));
#endif
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index bc141c950b1e..eb9261024f51 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -195,6 +195,7 @@ extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
static inline unsigned long pte_update(struct mm_struct *mm,
unsigned long addr,
pte_t *ptep, unsigned long clr,
+ unsigned long set,
int huge)
{
#ifdef PTE_ATOMIC_UPDATES
@@ -205,14 +206,15 @@ static inline unsigned long pte_update(struct mm_struct *mm,
andi. %1,%0,%6\n\
bne- 1b \n\
andc %1,%0,%4 \n\
+ or %1,%1,%7\n\
stdcx. %1,0,%3 \n\
bne- 1b"
: "=&r" (old), "=&r" (tmp), "=m" (*ptep)
- : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
+ : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set)
: "cc" );
#else
unsigned long old = pte_val(*ptep);
- *ptep = __pte(old & ~clr);
+ *ptep = __pte((old & ~clr) | set);
#endif
/* huge pages use the old page table lock */
if (!huge)
@@ -231,9 +233,9 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
{
unsigned long old;
- if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
+ if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
return 0;
- old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0);
+ old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
return (old & _PAGE_ACCESSED) != 0;
}
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -252,7 +254,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
if ((pte_val(*ptep) & _PAGE_RW) == 0)
return;
- pte_update(mm, addr, ptep, _PAGE_RW, 0);
+ pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
}
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
@@ -261,7 +263,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
if ((pte_val(*ptep) & _PAGE_RW) == 0)
return;
- pte_update(mm, addr, ptep, _PAGE_RW, 1);
+ pte_update(mm, addr, ptep, _PAGE_RW, 0, 1);
}
/*
@@ -284,14 +286,14 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
- unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0);
+ unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
return __pte(old);
}
static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
pte_t * ptep)
{
- pte_update(mm, addr, ptep, ~0UL, 0);
+ pte_update(mm, addr, ptep, ~0UL, 0, 0);
}
@@ -506,7 +508,9 @@ extern int pmdp_set_access_flags(struct vm_area_struct *vma,
extern unsigned long pmd_hugepage_update(struct mm_struct *mm,
unsigned long addr,
- pmd_t *pmdp, unsigned long clr);
+ pmd_t *pmdp,
+ unsigned long clr,
+ unsigned long set);
static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
unsigned long addr, pmd_t *pmdp)
@@ -515,7 +519,7 @@ static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
return 0;
- old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED);
+ old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0);
return ((old & _PAGE_ACCESSED) != 0);
}
@@ -542,7 +546,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr,
if ((pmd_val(*pmdp) & _PAGE_RW) == 0)
return;
- pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW);
+ pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW, 0);
}
#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 65b7b65e8708..62bf5e8e78da 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -510,7 +510,8 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
}
unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
- pmd_t *pmdp, unsigned long clr)
+ pmd_t *pmdp, unsigned long clr,
+ unsigned long set)
{
unsigned long old, tmp;
@@ -526,14 +527,15 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
andi. %1,%0,%6\n\
bne- 1b \n\
andc %1,%0,%4 \n\
+ or %1,%1,%7\n\
stdcx. %1,0,%3 \n\
bne- 1b"
: "=&r" (old), "=&r" (tmp), "=m" (*pmdp)
- : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY)
+ : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY), "r" (set)
: "cc" );
#else
old = pmd_val(*pmdp);
- *pmdp = __pmd(old & ~clr);
+ *pmdp = __pmd((old & ~clr) | set);
#endif
if (old & _PAGE_HASHPTE)
hpte_do_hugepage_flush(mm, addr, pmdp);
@@ -708,7 +710,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp)
{
- pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT);
+ pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
}
/*
@@ -835,7 +837,7 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm,
unsigned long old;
pgtable_t *pgtable_slot;
- old = pmd_hugepage_update(mm, addr, pmdp, ~0UL);
+ old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0);
old_pmd = __pmd(old);
/*
* We have pmd == none and we are holding page_table_lock.
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c
index a770df2dae70..6c0b1f5f8d2c 100644
--- a/arch/powerpc/mm/subpage-prot.c
+++ b/arch/powerpc/mm/subpage-prot.c
@@ -78,7 +78,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr,
pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
arch_enter_lazy_mmu_mode();
for (; npages > 0; --npages) {
- pte_update(mm, addr, pte, 0, 0);
+ pte_update(mm, addr, pte, 0, 0, 0);
addr += PAGE_SIZE;
++pte;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 0/3] powerpc: Fix random application crashes with NUMA_BALANCING enabled
From: Aneesh Kumar K.V @ 2014-02-11 10:34 UTC (permalink / raw)
To: benh, paulus, riel, mgorman, mpe; +Cc: linux-mm, linuxppc-dev
Hello,
This patch series fix random application crashes observed on ppc64 with numa
balancing enabled. Without the patch we see crashes like
anacron[14551]: unhandled signal 11 at 0000000000000041 nip 000000003cfd54b4 lr 000000003cfd5464 code 30001
anacron[14599]: unhandled signal 11 at 0000000000000041 nip 000000003efc54b4 lr 000000003efc5464 code 30001
-aneesh
^ permalink raw reply
* [PATCH 3/3] mm: Use ptep/pmdp_set_numa for updating _PAGE_NUMA bit
From: Aneesh Kumar K.V @ 2014-02-11 10:34 UTC (permalink / raw)
To: benh, paulus, riel, mgorman, mpe; +Cc: linux-mm, linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1392114895-14997-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Archs like ppc64 doesn't do tlb flush in set_pte/pmd functions. ppc64 also doesn't implement
flush_tlb_range. ppc64 require the tlb flushing to be batched within ptl locks. The reason
to do that is to ensure that the hash page table is in sync with linux page table.
We track the hpte index in linux pte and if we clear them without flushing hash and drop the
ptl lock, we can have another cpu update the pte and can end up with double hash. We also want
to keep set_pte_at simpler by not requiring them to do hash flush for performance reason.
Hence cannot use them while updating _PAGE_NUMA bit. Add new functions for marking pte/pmd numa
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/pgtable.h | 22 ++++++++++++++++++++++
include/asm-generic/pgtable.h | 24 ++++++++++++++++++++++++
mm/huge_memory.c | 9 ++-------
mm/mprotect.c | 4 +---
4 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index f83b6f3e1b39..3ebb188c3ff5 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -75,12 +75,34 @@ static inline pte_t pte_mknuma(pte_t pte)
return pte;
}
+#define ptep_set_numa ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ if ((pte_val(*ptep) & _PAGE_PRESENT) == 0)
+ VM_BUG_ON(1);
+
+ pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0);
+ return;
+}
+
#define pmd_numa pmd_numa
static inline int pmd_numa(pmd_t pmd)
{
return pte_numa(pmd_pte(pmd));
}
+#define pmdp_set_numa pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp)
+{
+ if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0)
+ VM_BUG_ON(1);
+
+ pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA);
+ return;
+}
+
#define pmd_mknonnuma pmd_mknonnuma
static inline pmd_t pmd_mknonnuma(pmd_t pmd)
{
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 8e4f41d9af4d..93fdb5315a0d 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -669,6 +669,18 @@ static inline int pmd_numa(pmd_t pmd)
}
#endif
+#ifndef pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp)
+{
+ pmd_t pmd = *pmdp;
+
+ pmd = pmd_mknuma(entry);
+ set_pmd_at(mm, addr, pmdp, pmd);
+ return;
+}
+#endif
+
/*
* pte/pmd_mknuma sets the _PAGE_ACCESSED bitflag automatically
* because they're called by the NUMA hinting minor page fault. If we
@@ -701,6 +713,18 @@ static inline pte_t pte_mknuma(pte_t pte)
}
#endif
+#ifndef ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_t ptent = *ptep;
+
+ ptent = pte_mknuma(ptent);
+ set_pte_at(mm, addr, ptep, ptent);
+ return;
+}
+#endif
+
#ifndef pmd_mknuma
static inline pmd_t pmd_mknuma(pmd_t pmd)
{
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 82166bf974e1..da23eb96779f 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1545,6 +1545,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
entry = pmd_mknonnuma(entry);
entry = pmd_modify(entry, newprot);
ret = HPAGE_PMD_NR;
+ set_pmd_at(mm, addr, pmd, entry);
BUG_ON(pmd_write(entry));
} else {
struct page *page = pmd_page(*pmd);
@@ -1557,16 +1558,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
*/
if (!is_huge_zero_page(page) &&
!pmd_numa(*pmd)) {
- entry = *pmd;
- entry = pmd_mknuma(entry);
+ pmdp_set_numa(mm, addr, pmd);
ret = HPAGE_PMD_NR;
}
}
-
- /* Set PMD if cleared earlier */
- if (ret == HPAGE_PMD_NR)
- set_pmd_at(mm, addr, pmd, entry);
-
spin_unlock(ptl);
}
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 33eab902f10e..769a67a15803 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -69,12 +69,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
} else {
struct page *page;
- ptent = *pte;
page = vm_normal_page(vma, addr, oldpte);
if (page && !PageKsm(page)) {
if (!pte_numa(oldpte)) {
- ptent = pte_mknuma(ptent);
- set_pte_at(mm, addr, pte, ptent);
+ ptep_set_numa(mm, addr, pte);
updated = true;
}
}
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH v2] powerpc ticket locks
From: Torsten Duwe @ 2014-02-11 10:40 UTC (permalink / raw)
To: Raghavendra KT
Cc: Tom Musta, Peter Zijlstra, Raghavendra KT,
Linux Kernel Mailing List, Paul Mackerras, Anton Blanchard,
Scott Wood, Paul E. McKenney, linuxppc-dev, Ingo Molnar
In-Reply-To: <CAC4Lta2Pssu5QY_QLmy5C3Fm2G3fwpiuc5BNOLBnQTmmRH+W4Q@mail.gmail.com>
On Tue, Feb 11, 2014 at 03:23:51PM +0530, Raghavendra KT wrote:
> How much important to have holder information for PPC? From my
> previous experiment
> on x86, it was lock-waiter preemption which is problematic rather than
> lock-holder preemption.
It's something very special to IBM pSeries: the hypervisor can assign
fractions of physical CPUs to guests. Sometimes a guest with 4 quarter
CPUs will be faster than 1 monoprocessor. (correct me if I'm wrong).
The directed yield resolves the silly situation when holder and waiter
reside on the same physical CPU, as I understand it.
x86 has nothing comparable.
Torsten
^ permalink raw reply
* [PATCH v2 0/2] Support of the kmcoge4 board
From: Valentin Longchamp @ 2014-02-11 11:50 UTC (permalink / raw)
To: Scott Wood, linuxppc-dev; +Cc: Valentin Longchamp, devicetree
This series adds support for Keymile's COGE4 board, called kmcoge4. This
board is the reference design for further designs at Keymile around the
P2040/P2041 SoCs from Freescale. This reference design is internally
called kmp204x.
Changes in v2:
- add a patch so that the Zarlink vendor prefix is defined
- add some nodes on the localbus CS when possible
- only use the corenet_generic machine and add kmcoge4 to the supported
boards instead of defining a new kmp204x machine
- set better and more precise device nodes for the spi devices
- remove the partion layout for the spi_flash@0
Valentin Longchamp (2):
devicetree: bindings: add Zarlink to the vendor prefixes
powerpc/mpc85xx: add support for Keymile's kmcoge4 board
.../devicetree/bindings/vendor-prefixes.txt | 1 +
arch/powerpc/boot/dts/kmcoge4.dts | 161 +++++++++++++++
arch/powerpc/configs/85xx/kmp204x_defconfig | 227 +++++++++++++++++++++
arch/powerpc/platforms/85xx/Kconfig | 2 +-
arch/powerpc/platforms/85xx/corenet_generic.c | 3 +-
5 files changed, 392 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/boot/dts/kmcoge4.dts
create mode 100644 arch/powerpc/configs/85xx/kmp204x_defconfig
--
1.8.0.1
^ permalink raw reply
* [PATCH v2 1/2] devicetree: bindings: add Zarlink to the vendor prefixes
From: Valentin Longchamp @ 2014-02-11 11:50 UTC (permalink / raw)
To: Scott Wood, linuxppc-dev; +Cc: Valentin Longchamp, devicetree
In-Reply-To: <1392119407-29490-1-git-send-email-valentin.longchamp@keymile.com>
Even though the company belongs to Microsemi, many chips are still
labeled as Zarlink. Among them is the family of network clock generators,
the zl3034x.
Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
---
Changes in v2:
- add a patch so that the Zarlink vendor prefix is defined
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index edbb8d8..35f1c9b 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -81,3 +81,4 @@ winbond Winbond Electronics corp.
wlf Wolfson Microelectronics
wm Wondermedia Technologies, Inc.
xlnx Xilinx
+zarlink Zarlink Semiconductor
--
1.8.0.1
^ permalink raw reply related
* [PATCH v2 2/2] powerpc/mpc85xx: add support for Keymile's kmcoge4 board
From: Valentin Longchamp @ 2014-02-11 11:50 UTC (permalink / raw)
To: Scott Wood, linuxppc-dev; +Cc: Valentin Longchamp
In-Reply-To: <1392119407-29490-1-git-send-email-valentin.longchamp@keymile.com>
This patch introduces the support for Keymile's kmcoge4 board which is
the internal reference design for boards based on Freescale's
P2040/P2041 SoCs. This internal reference design is named kmp204x.
The peripherals used on this board are:
- SPI NOR Flash as bootloader medium
- NAND Flash with a ubi partition
- 2 PCIe busses (hosts 1 and 3)
- 3 FMAN Ethernet devices (FMAN1 DTSEC1/2/5)
- 4 Local Bus windows, with one dedicated to the QRIO reset/power mgmt
CPLD
- 2 I2C busses
- last but not least, the mandatory serial port
The patch also adds a defconfig file for this reference design that is
necessary because of the lowmem option that must be set higher due to
the number of PCIe devices with big ioremapped mem ranges on the boad.
Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
---
Changes in v2:
- add some nodes on the localbus CS when possible
- only use the corenet_generic machine and add kmcoge4 to the supported
boards instead of defining a new kmp204x machine
- set better and more precise device nodes for the spi devices
- remove the partion layout for the spi_flash@0
arch/powerpc/boot/dts/kmcoge4.dts | 161 ++++++++++++++++++
arch/powerpc/configs/85xx/kmp204x_defconfig | 227 ++++++++++++++++++++++++++
arch/powerpc/platforms/85xx/Kconfig | 2 +-
arch/powerpc/platforms/85xx/corenet_generic.c | 3 +-
4 files changed, 391 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/boot/dts/kmcoge4.dts
create mode 100644 arch/powerpc/configs/85xx/kmp204x_defconfig
diff --git a/arch/powerpc/boot/dts/kmcoge4.dts b/arch/powerpc/boot/dts/kmcoge4.dts
new file mode 100644
index 0000000..5eab9df
--- /dev/null
+++ b/arch/powerpc/boot/dts/kmcoge4.dts
@@ -0,0 +1,161 @@
+/*
+ * Keymile kmcoge4 Device Tree Source, based on the P2041RDB DTS
+ *
+ * (C) Copyright 2014
+ * Valentin Longchamp, Keymile AG, valentin.longchamp@keymile.com
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/include/ "fsl/p2041si-pre.dtsi"
+
+/ {
+ model = "keymile,kmcoge4";
+ compatible = "keymile,kmcoge4", "keymile,kmp204x";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ memory {
+ device_type = "memory";
+ };
+
+ dcsr: dcsr@f00000000 {
+ ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+ };
+
+ soc: soc@ffe000000 {
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+ spi@110000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25fl256s1";
+ reg = <0>;
+ spi-max-frequency = <20000000>; /* input clock */
+ };
+
+ network_clock@1 {
+ compatible = "zarlink,zl30343";
+ reg = <1>;
+ spi-max-frequency = <8000000>;
+ };
+
+ flash@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,m25p32";
+ reg = <2>;
+ spi-max-frequency = <15000000>;
+ };
+ };
+
+ i2c@119000 {
+ status = "disabled";
+ };
+
+ i2c@119100 {
+ status = "disabled";
+ };
+
+ usb0: usb@210000 {
+ status = "disabled";
+ };
+
+ usb1: usb@211000 {
+ status = "disabled";
+ };
+
+ sata@220000 {
+ status = "disabled";
+ };
+
+ sata@221000 {
+ status = "disabled";
+ };
+ };
+
+ rio: rapidio@ffe0c0000 {
+ status = "disabled";
+ };
+
+ lbc: localbus@ffe124000 {
+ reg = <0xf 0xfe124000 0 0x1000>;
+ ranges = <0 0 0xf 0xffa00000 0x00040000 /* LB 0 */
+ 1 0 0xf 0xfb000000 0x00010000 /* LB 1 */
+ 2 0 0xf 0xd0000000 0x10000000 /* LB 2 */
+ 3 0 0xf 0xe0000000 0x10000000>; /* LB 3 */
+
+ nand@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,elbc-fcm-nand";
+ reg = <0 0 0x40000>;
+
+ partition@0 {
+ label = "ubi0";
+ reg = <0x0 0x10000000>;
+ };
+ };
+
+ reset_cpld@1,0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <1 0 0x80>;
+ interrupt-parent = <&mpic>;
+ interrupts = <
+ 4 1 0 0
+ 5 1 0 0>;
+ };
+
+ chassis_mgmt@3,0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <3 0 0x100>;
+ interrupt-parent = <&mpic>;
+ interrupts = <6 1 0 0>;
+ };
+ };
+
+ pci0: pcie@ffe200000 {
+ reg = <0xf 0xfe200000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie@ffe201000 {
+ status = "disabled";
+ };
+
+ pci2: pcie@ffe202000 {
+ reg = <0xf 0xfe202000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x20000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8010000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+};
+
+/include/ "fsl/p2041si-post.dtsi"
diff --git a/arch/powerpc/configs/85xx/kmp204x_defconfig b/arch/powerpc/configs/85xx/kmp204x_defconfig
new file mode 100644
index 0000000..afd9a3f
--- /dev/null
+++ b/arch/powerpc/configs/85xx/kmp204x_defconfig
@@ -0,0 +1,227 @@
+CONFIG_PPC_85xx=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_CORENET_GENERIC=y
+CONFIG_MPIC_MSGR=y
+CONFIG_HIGHMEM=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_KEXEC=y
+CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEASPM is not set
+CONFIG_PCI_MSI=y
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_LOWMEM_SIZE_BOOL=y
+CONFIG_LOWMEM_SIZE=0x20000000
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IP_SCTP=m
+CONFIG_TIPC=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_HFSC=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_RED=y
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TEQL=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_GRED=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_CLS_CGROUP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
+CONFIG_DEVTMPFS=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_PHRAM=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC_BCH=y
+CONFIG_MTD_NAND_FSL_ELBC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_GLUEBI=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=2048
+CONFIG_EEPROM_AT24=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_FSL_XGMAC_MDIO=y
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
+CONFIG_MARVELL_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_FIXED_PHY=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PPC_EPAPR_HV_BYTECHAN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_NVRAM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_FSL_SPI=y
+CONFIG_SPI_FSL_ESPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_PTP_1588_CLOCK=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_MPC85XX=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS3232=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+# CONFIG_NET_VENDOR_SILICOM is not set
+CONFIG_CLK_PPC_CORENET=y
+CONFIG_EXT2_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=m
+CONFIG_CRC_ITU_T=m
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_SCHEDSTATS=y
+CONFIG_RCU_TRACE=y
+CONFIG_UPROBE_EVENT=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 4d46349..6ba3be1 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -257,7 +257,7 @@ config CORENET_GENERIC
help
This option enables support for the FSL CoreNet based boards.
For 32bit kernel, the following boards are supported:
- P2041 RDB, P3041 DS and P4080 DS
+ P2041 RDB, P3041 DS, P4080 DS and kmcoge4
For 64bit kernel, the following boards are supported:
T4240 QDS and B4 QDS
The following boards are supported for both 32bit and 64bit kernel:
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index fbd871e..8c065ae 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -56,7 +56,7 @@ void __init corenet_gen_setup_arch(void)
swiotlb_detect_4g();
- pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
+ pr_info("%s board\n", ppc_md.name);
}
static const struct of_device_id of_device_ids[] = {
@@ -106,6 +106,7 @@ static const char * const boards[] __initconst = {
"fsl,B4860QDS",
"fsl,B4420QDS",
"fsl,B4220QDS",
+ "keymile,kmcoge4",
NULL
};
--
1.8.0.1
^ permalink raw reply related
* Re: [PATCH 2/3] mm: dirty accountable change only apply to non prot numa case
From: Rik van Riel @ 2014-02-11 13:20 UTC (permalink / raw)
To: Aneesh Kumar K.V, benh, paulus, mgorman, mpe; +Cc: linux-mm, linuxppc-dev
In-Reply-To: <1392114895-14997-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On 02/11/2014 05:34 AM, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> So move it within the if loop
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: Rik van Riel <riel@redhat.com>
--
All rights reversed
^ permalink raw reply
* Re: [PATCH 3/3] mm: Use ptep/pmdp_set_numa for updating _PAGE_NUMA bit
From: Rik van Riel @ 2014-02-11 13:25 UTC (permalink / raw)
To: Aneesh Kumar K.V, benh, paulus, mgorman, mpe; +Cc: linux-mm, linuxppc-dev
In-Reply-To: <1392114895-14997-4-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On 02/11/2014 05:34 AM, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> Archs like ppc64 doesn't do tlb flush in set_pte/pmd functions. ppc64 also doesn't implement
> flush_tlb_range. ppc64 require the tlb flushing to be batched within ptl locks. The reason
> to do that is to ensure that the hash page table is in sync with linux page table.
> We track the hpte index in linux pte and if we clear them without flushing hash and drop the
> ptl lock, we can have another cpu update the pte and can end up with double hash. We also want
> to keep set_pte_at simpler by not requiring them to do hash flush for performance reason.
> Hence cannot use them while updating _PAGE_NUMA bit. Add new functions for marking pte/pmd numa
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: Rik van Riel <riel@redhat.com>
--
All rights reversed
^ permalink raw reply
* Re: [PATCH 1/3] powerpc: mm: Add new set flag argument to pte/pmd update function
From: Rik van Riel @ 2014-02-11 13:54 UTC (permalink / raw)
To: Aneesh Kumar K.V, benh, paulus, mgorman, mpe; +Cc: linux-mm, linuxppc-dev
In-Reply-To: <1392114895-14997-2-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On 02/11/2014 05:34 AM, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> We will use this later to set the _PAGE_NUMA bit.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
--
All rights reversed
^ permalink raw reply
* Re: [PATCH V4 2/3] tick/cpuidle: Initialize hrtimer mode of broadcast
From: Thomas Gleixner @ 2014-02-11 15:58 UTC (permalink / raw)
To: Daniel Lezcano
Cc: deepthi, linux-pm, peterz, rafael.j.wysocki, linux-kernel, paulus,
srivatsa.bhat, fweisbec, Preeti U Murthy, paulmck, linuxppc-dev,
mingo
In-Reply-To: <52F9F896.4020402@linaro.org>
On Tue, 11 Feb 2014, Daniel Lezcano wrote:
> On 02/07/2014 09:06 AM, Preeti U Murthy wrote:
> Setting the smp affinity on the earliest timer should be handled automatically
> with the CLOCK_EVT_FEAT_DYNIRQ flag. Did you look at using this flag ?
How should this flag help? Not at all, because the hrtimer based
broadcast device cannot assign affinities.
> Another comment is the overall approach. We enter the cpuidle idle framework
> with a specific state to go to and it is the tick framework telling us we
> mustn't go to this state. IMO the logic is wrong, the decision to not enter
> this state should be moved somewhere else.
>
> Why don't you create a cpuidle driver with the shallow idle states assigned to
> a cpu (let's say cpu0) and another one with all the deeper idle states for the
> rest of the cpus ? Using the multiple cpuidle driver support makes it
> possible. The timer won't be moving around and a cpu will be dedicated to act
> as the broadcast timer.
>
> Wouldn't make sense and be less intrusive than the patchset you proposed ?
How do you arm the broadcast timer on CPU0 from CPU1? You can't!
You cannot access the cpu local timer on a different cpu. So you would
have to send an IPI over to CPU0 so that it can reevaluate and
schedule the broadcast. That's even more backwards than telling the
cpuidle code that the CPU is not in a state to go deep.
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH V4 2/3] tick/cpuidle: Initialize hrtimer mode of broadcast
From: Preeti U Murthy @ 2014-02-11 16:09 UTC (permalink / raw)
To: Daniel Lezcano
Cc: deepthi, linux-pm, peterz, rafael.j.wysocki, linux-kernel, paulus,
srivatsa.bhat, fweisbec, tglx, paulmck, linuxppc-dev, mingo
In-Reply-To: <52F9F896.4020402@linaro.org>
Hi Daniel,
Thank you very much for the review.
On 02/11/2014 03:46 PM, Daniel Lezcano wrote:
> On 02/07/2014 09:06 AM, Preeti U Murthy wrote:
>> From: Thomas Gleixner <tglx@linutronix.de>
>>
>> On some architectures, in certain CPU deep idle states the local
>> timers stop.
>> An external clock device is used to wakeup these CPUs. The kernel
>> support for the
>> wakeup of these CPUs is provided by the tick broadcast framework by
>> using the
>> external clock device as the wakeup source.
>>
>> However not all implementations of architectures provide such an external
>> clock device. This patch includes support in the broadcast framework
>> to handle
>> the wakeup of the CPUs in deep idle states on such systems by queuing
>> a hrtimer
>> on one of the CPUs, which is meant to handle the wakeup of CPUs in
>> deep idle states.
>>
>> This patchset introduces a pseudo clock device which can be registered
>> by the
>> archs as tick_broadcast_device in the absence of a real external clock
>> device. Once registered, the broadcast framework will work as is for
>> these
>> architectures as long as the archs take care of the BROADCAST_ENTER
>> notification failing for one of the CPUs. This CPU is made the stand
>> by CPU to
>> handle wakeup of the CPUs in deep idle and it *must not enter deep
>> idle states*.
>>
>> The CPU with the earliest wakeup is chosen to be this CPU. Hence this
>> way the
>> stand by CPU dynamically moves around and so does the hrtimer which is
>> queued
>> to trigger at the next earliest wakeup time. This is consistent with
>> the case where
>> an external clock device is present. The smp affinity of this clock
>> device is
>> set to the CPU with the earliest wakeup.
>
> Hi Preeti,
>
> jumping a bit late in the thread...
>
> Setting the smp affinity on the earliest timer should be handled
> automatically with the CLOCK_EVT_FEAT_DYNIRQ flag. Did you look at using
> this flag ?
This patch is not setting the smp affinity of the pseudo clock device at
all. Its not required to for the reason that it does not exist.
I mentioned this point because we assign a CPU with the earliest wakeup
as standby. I compared this logic to the one used by the tick broadcast
framework for archs which have an external clock device to set the smp
affinity of the device.
If these archs do not have the flag CLOCK_EVT_FEAT_DYNIRQ set for the
external clock device, the tick broadcast framework sets the smp
affinity of this device to the CPU with the earliest wakeup. We are
using the same logic in this patchset as well to assign the stand by CPU.
>
> Another comment is the overall approach. We enter the cpuidle idle
> framework with a specific state to go to and it is the tick framework
> telling us we mustn't go to this state. IMO the logic is wrong, the
> decision to not enter this state should be moved somewhere else.
Its not the tick framework which tells us that we cannot enter deep idle
state, its the *tick broadcast* framework specifically. The tick
broadcast framework was introduced with the primary intention of
handling wakeup of CPUs in deep idle states when the local timers become
non-functional. Therefore there is a co-operation between this tick
broadcast framework and cpuidle. This has always been the case.
That is why just before cpus go into deep idle, they call into the
broadcast framework. Till now it was assumed that the tick broadcast
framework would find no problems with the cpus entering deep idle.
Therefore cpuidle would simply assume that all is well and go ahead and
enter deep idle state.
But today there is a scenario when there could be problems if all cpus
enter deep idle states and the tick broadcast framework now notifies the
cpuidle framework to hold back one cpu. This is just a simple extension
of the current interaction between cpuidle and tick broadcast framework.
>
> Why don't you create a cpuidle driver with the shallow idle states
> assigned to a cpu (let's say cpu0) and another one with all the deeper
> idle states for the rest of the cpus ? Using the multiple cpuidle driver
> support makes it possible. The timer won't be moving around and a cpu
> will be dedicated to act as the broadcast timer.
>
Having a dedicated stand by cpu for broadcasting has some issues which
were pointed to when I posted the initial versions of this patchset.
https://lkml.org/lkml/2013/7/27/14
1. This could create power/thermal imbalance on the chip since only the
standby cpu cannot enter deep idle state at all times.
2. If it is cpu0 it is fine, else with the logic that you suggest,
hot-plugging out the dedicated stand by cpu would mean moving the work
of broadcasting to another cpu and modifying the cpuidle state table for
it. Even with cpu0, if support to hotplug it out is enabled (maybe it is
already), we will face the same issue and this gets very messy.
> Wouldn't make sense and be less intrusive than the patchset you proposed ?
Actually this patchset brings in a solution that is as less intrusive as
possible. It makes the problem nearly invisible except for a failed
return from a call into the broadcast framework. It simply asks the
archs which do not have an external clock device to register a pseudo
device with the broadcast framework and from then on everything just
falls in place to enable deep idle states for such archs.
Thanks
Regards
Preeti U Murthy
>
>
>> This patchset handles the hotplug of
>> the stand by CPU as well by moving the hrtimer on to the CPU handling
>> the CPU_DEAD
>> notification.
>>
>> Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
>> [Added Changelog and code to handle reprogramming of hrtimer]
>> ---
>>
>> include/linux/clockchips.h | 9 +++
>> kernel/time/Makefile | 2 -
>> kernel/time/tick-broadcast-hrtimer.c | 105
>> ++++++++++++++++++++++++++++++++++
>> kernel/time/tick-broadcast.c | 54 +++++++++++++++++
>> 4 files changed, 166 insertions(+), 4 deletions(-)
>> create mode 100644 kernel/time/tick-broadcast-hrtimer.c
>>
>> diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
>> index e0c5a6c..dbe9e14 100644
>> --- a/include/linux/clockchips.h
>> +++ b/include/linux/clockchips.h
>> @@ -62,6 +62,11 @@ enum clock_event_mode {
>> #define CLOCK_EVT_FEAT_DYNIRQ 0x000020
>> #define CLOCK_EVT_FEAT_PERCPU 0x000040
>>
>> +/*
>> + * Clockevent device is based on a hrtimer for broadcast
>> + */
>> +#define CLOCK_EVT_FEAT_HRTIMER 0x000080
>> +
>> /**
>> * struct clock_event_device - clock event device descriptor
>> * @event_handler: Assigned by the framework to be called by the low
>> @@ -83,6 +88,7 @@ enum clock_event_mode {
>> * @name: ptr to clock event name
>> * @rating: variable to rate clock event devices
>> * @irq: IRQ number (only for non CPU local devices)
>> + * @bound_on: Bound on CPU
>> * @cpumask: cpumask to indicate for which CPUs this device
>> works
>> * @list: list head for the management code
>> * @owner: module reference
>> @@ -113,6 +119,7 @@ struct clock_event_device {
>> const char *name;
>> int rating;
>> int irq;
>> + int bound_on;
>> const struct cpumask *cpumask;
>> struct list_head list;
>> struct module *owner;
>> @@ -180,9 +187,11 @@ extern int tick_receive_broadcast(void);
>> #endif
>>
>> #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) &&
>> defined(CONFIG_TICK_ONESHOT)
>> +extern void tick_setup_hrtimer_broadcast(void);
>> extern int tick_check_broadcast_expired(void);
>> #else
>> static inline int tick_check_broadcast_expired(void) { return 0; }
>> +static void tick_setup_hrtimer_broadcast(void) {};
>> #endif
>>
>> #ifdef CONFIG_GENERIC_CLOCKEVENTS
>> diff --git a/kernel/time/Makefile b/kernel/time/Makefile
>> index 9250130..06151ef 100644
>> --- a/kernel/time/Makefile
>> +++ b/kernel/time/Makefile
>> @@ -3,7 +3,7 @@ obj-y += timeconv.o posix-clock.o alarmtimer.o
>>
>> obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o
>> obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o
>> -obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o
>> +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o
>> tick-broadcast-hrtimer.o
>> obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o
>> obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o
>> obj-$(CONFIG_TICK_ONESHOT) += tick-sched.o
>> diff --git a/kernel/time/tick-broadcast-hrtimer.c
>> b/kernel/time/tick-broadcast-hrtimer.c
>> new file mode 100644
>> index 0000000..af1e119
>> --- /dev/null
>> +++ b/kernel/time/tick-broadcast-hrtimer.c
>> @@ -0,0 +1,105 @@
>> +/*
>> + * linux/kernel/time/tick-broadcast-hrtimer.c
>> + * This file emulates a local clock event device
>> + * via a pseudo clock device.
>> + */
>> +#include <linux/cpu.h>
>> +#include <linux/err.h>
>> +#include <linux/hrtimer.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/percpu.h>
>> +#include <linux/profile.h>
>> +#include <linux/clockchips.h>
>> +#include <linux/sched.h>
>> +#include <linux/smp.h>
>> +#include <linux/module.h>
>> +
>> +#include "tick-internal.h"
>> +
>> +static struct hrtimer bctimer;
>> +
>> +static void bc_set_mode(enum clock_event_mode mode,
>> + struct clock_event_device *bc)
>> +{
>> + switch (mode) {
>> + case CLOCK_EVT_MODE_SHUTDOWN:
>> + /*
>> + * Note, we cannot cancel the timer here as we might
>> + * run into the following live lock scenario:
>> + *
>> + * cpu 0 cpu1
>> + * lock(broadcast_lock);
>> + * hrtimer_interrupt()
>> + * bc_handler()
>> + * tick_handle_oneshot_broadcast();
>> + * lock(broadcast_lock);
>> + * hrtimer_cancel()
>> + * wait_for_callback()
>> + */
>> + hrtimer_try_to_cancel(&bctimer);
>> + break;
>> + default:
>> + break;
>> + }
>> +}
>> +
>> +/*
>> + * This is called from the guts of the broadcast code when the cpu
>> + * which is about to enter idle has the earliest broadcast timer event.
>> + */
>> +static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
>> +{
>> + /*
>> + * We try to cancel the timer first. If the callback is on
>> + * flight on some other cpu then we let it handle it. If we
>> + * were able to cancel the timer nothing can rearm it as we
>> + * own broadcast_lock.
>> + *
>> + * However we can also be called from the event handler of
>> + * ce_broadcast_hrtimer itself when it expires. We cannot therefore
>> + * restart the timer since it is on flight on the same CPU. But
>> + * due to the same reason we can reset it.
>> + */
>> + if (hrtimer_try_to_cancel(&bctimer) >= 0) {
>> + hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED);
>> + /* Bind the "device" to the cpu */
>> + bc->bound_on = smp_processor_id();
>> + } else if (bc->bound_on == smp_processor_id()) {
>> + hrtimer_set_expires(&bctimer, expires);
>> + }
>> + return 0;
>> +}
>> +
>> +static struct clock_event_device ce_broadcast_hrtimer = {
>> + .set_mode = bc_set_mode,
>> + .set_next_ktime = bc_set_next,
>> + .features = CLOCK_EVT_FEAT_ONESHOT |
>> + CLOCK_EVT_FEAT_KTIME |
>> + CLOCK_EVT_FEAT_HRTIMER,
>> + .rating = 0,
>> + .bound_on = -1,
>> + .min_delta_ns = 1,
>> + .max_delta_ns = KTIME_MAX,
>> + .min_delta_ticks = 1,
>> + .max_delta_ticks = KTIME_MAX,
>> + .mult = 1,
>> + .shift = 0,
>> + .cpumask = cpu_all_mask,
>> +};
>> +
>> +static enum hrtimer_restart bc_handler(struct hrtimer *t)
>> +{
>> + ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer);
>> +
>> + if (ce_broadcast_hrtimer.next_event.tv64 == KTIME_MAX)
>> + return HRTIMER_NORESTART;
>> +
>> + return HRTIMER_RESTART;
>> +}
>> +
>> +void tick_setup_hrtimer_broadcast(void)
>> +{
>> + hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
>> + bctimer.function = bc_handler;
>> + clockevents_register_device(&ce_broadcast_hrtimer);
>> +}
>> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
>> index ddf2ac2..2f013c3 100644
>> --- a/kernel/time/tick-broadcast.c
>> +++ b/kernel/time/tick-broadcast.c
>> @@ -630,6 +630,42 @@ again:
>> raw_spin_unlock(&tick_broadcast_lock);
>> }
>>
>> +static int broadcast_needs_cpu(struct clock_event_device *bc, int cpu)
>> +{
>> + if (!(bc->features & CLOCK_EVT_FEAT_HRTIMER))
>> + return 0;
>> + if (bc->next_event.tv64 == KTIME_MAX)
>> + return 0;
>> + return bc->bound_on == cpu ? -EBUSY : 0;
>> +}
>> +
>> +static void broadcast_shutdown_local(struct clock_event_device *bc,
>> + struct clock_event_device *dev)
>> +{
>> + /*
>> + * For hrtimer based broadcasting we cannot shutdown the cpu
>> + * local device if our own event is the first one to expire or
>> + * if we own the broadcast timer.
>> + */
>> + if (bc->features & CLOCK_EVT_FEAT_HRTIMER) {
>> + if (broadcast_needs_cpu(bc, smp_processor_id()))
>> + return;
>> + if (dev->next_event.tv64 < bc->next_event.tv64)
>> + return;
>> + }
>> + clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
>> +}
>> +
>> +static void broadcast_move_bc(int deadcpu)
>> +{
>> + struct clock_event_device *bc = tick_broadcast_device.evtdev;
>> +
>> + if (!bc || !broadcast_needs_cpu(bc, deadcpu))
>> + return;
>> + /* This moves the broadcast assignment to this cpu */
>> + clockevents_program_event(bc, bc->next_event, 1);
>> +}
>> +
>> /*
>> * Powerstate information: The system enters/leaves a state, where
>> * affected devices might stop
>> @@ -648,7 +684,7 @@ int tick_broadcast_oneshot_control(unsigned long
>> reason)
>> * states
>> */
>> if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
>> - return;
>> + return 0;
>>
>> /*
>> * We are called with preemtion disabled from the depth of the
>> @@ -659,7 +695,7 @@ int tick_broadcast_oneshot_control(unsigned long
>> reason)
>> dev = td->evtdev;
>>
>> if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
>> - return;
>> + return 0;
>>
>> bc = tick_broadcast_device.evtdev;
>>
>> @@ -667,7 +703,7 @@ int tick_broadcast_oneshot_control(unsigned long
>> reason)
>> if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
>> if (!cpumask_test_and_set_cpu(cpu,
>> tick_broadcast_oneshot_mask)) {
>> WARN_ON_ONCE(cpumask_test_cpu(cpu,
>> tick_broadcast_pending_mask));
>> - clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
>> + broadcast_shutdown_local(bc, dev);
>> /*
>> * We only reprogram the broadcast timer if we
>> * did not mark ourself in the force mask and
>> @@ -680,6 +716,16 @@ int tick_broadcast_oneshot_control(unsigned long
>> reason)
>> dev->next_event.tv64 < bc->next_event.tv64)
>> tick_broadcast_set_event(bc, cpu, dev->next_event, 1);
>> }
>> + /*
>> + * If the current CPU owns the hrtimer broadcast
>> + * mechanism, it cannot go deep idle and we remove the
>> + * CPU from the broadcast mask. We don't have to go
>> + * through the EXIT path as the local timer is not
>> + * shutdown.
>> + */
>> + ret = broadcast_needs_cpu(bc, cpu);
>> + if (ret)
>> + cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
>> } else {
>> if (cpumask_test_and_clear_cpu(cpu,
>> tick_broadcast_oneshot_mask)) {
>> clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
>> @@ -853,6 +899,8 @@ void tick_shutdown_broadcast_oneshot(unsigned int
>> *cpup)
>> cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
>> cpumask_clear_cpu(cpu, tick_broadcast_force_mask);
>>
>> + broadcast_move_bc(cpu);
>> +
>> raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
>> }
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
>
^ permalink raw reply
* Re: [PATCH 1/3] powerpc: mm: Add new set flag argument to pte/pmd update function
From: Mel Gorman @ 2014-02-11 17:00 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: riel, linux-mm, paulus, linuxppc-dev
In-Reply-To: <1392114895-14997-2-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On Tue, Feb 11, 2014 at 04:04:53PM +0530, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> We will use this later to set the _PAGE_NUMA bit.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Acked-by: Mel Gorman <mgorman@suse.de>
--
Mel Gorman
SUSE Labs
^ permalink raw reply
* Re: [PATCH 2/3] mm: dirty accountable change only apply to non prot numa case
From: Mel Gorman @ 2014-02-11 17:03 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: riel, linux-mm, paulus, linuxppc-dev
In-Reply-To: <1392114895-14997-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On Tue, Feb 11, 2014 at 04:04:54PM +0530, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> So move it within the if loop
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Acked-by: Mel Gorman <mgorman@suse.de>
--
Mel Gorman
SUSE Labs
^ permalink raw reply
* Re: [PATCH 3/3] mm: Use ptep/pmdp_set_numa for updating _PAGE_NUMA bit
From: Mel Gorman @ 2014-02-11 17:07 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: riel, linux-mm, paulus, linuxppc-dev
In-Reply-To: <1392114895-14997-4-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On Tue, Feb 11, 2014 at 04:04:55PM +0530, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> Archs like ppc64 doesn't do tlb flush in set_pte/pmd functions. ppc64 also doesn't implement
> flush_tlb_range. ppc64 require the tlb flushing to be batched within ptl locks. The reason
> to do that is to ensure that the hash page table is in sync with linux page table.
> We track the hpte index in linux pte and if we clear them without flushing hash and drop the
> ptl lock, we can have another cpu update the pte and can end up with double hash. We also want
> to keep set_pte_at simpler by not requiring them to do hash flush for performance reason.
> Hence cannot use them while updating _PAGE_NUMA bit. Add new functions for marking pte/pmd numa
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Acked-by: Mel Gorman <mgorman@suse.de>
--
Mel Gorman
SUSE Labs
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox