[PATCH v2] tty: hvc: Fix data abort due to race in hvc_open

2020-05-20 Thread Raghavendra Rao Ananta
Potentially, hvc_open() can be called in parallel when two tasks calls
open() on /dev/hvcX. In such a scenario, if the hp->ops->notifier_add()
callback in the function fails, where it sets the tty->driver_data to
NULL, the parallel hvc_open() can see this NULL and cause a memory abort.
Hence, do a NULL check at the beginning, before proceeding ahead.

The issue can be easily reproduced by launching two tasks simultaneously
that does an open() call on /dev/hvcX.
For example:
$ cat /dev/hvc0 & cat /dev/hvc0 &

Cc: sta...@vger.kernel.org
Signed-off-by: Raghavendra Rao Ananta 
---
 drivers/tty/hvc/hvc_console.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 436cc51c92c3..80709f754cc8 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -350,6 +350,9 @@ static int hvc_open(struct tty_struct *tty, struct file * 
filp)
unsigned long flags;
int rc = 0;

+   if (!hp)
+   return -ENODEV;
+
spin_lock_irqsave(>port.lock, flags);
/* Check and then increment for fast path open. */
if (hp->port.count++ > 0) {
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH] of: Add of_get_memory_prop()

2019-09-18 Thread Raghavendra Rao Ananta
On some embedded systems, the '/memory' dt-property gets updated
by the bootloader (for example, the DDR configuration) and then
gets passed onto the kernel. The device drivers may have to read
the properties at runtime to make decisions. Hence, add
of_get_memory_prop() for the device drivers to query the requested
properties.

Signed-off-by: Raghavendra Rao Ananta 
---
 drivers/of/fdt.c   | 27 +++
 include/linux/of_fdt.h |  1 +
 2 files changed, 28 insertions(+)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 223d617ecfe1..925cf2852433 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -79,6 +79,33 @@ void __init of_fdt_limit_memory(int limit)
}
 }
 
+/**
+ * of_fdt_get_memory_prop - Return the requested property from the /memory node
+ *
+ * On match, returns a non-zero positive value which represents the property
+ * value. Otherwise returns -ENOENT.
+ */
+int of_fdt_get_memory_prop(const char *pname)
+{
+   int memory;
+   int len;
+   fdt32_t *prop = NULL;
+
+   if (!pname)
+   return -EINVAL;
+
+   memory = fdt_path_offset(initial_boot_params, "/memory");
+   if (memory > 0)
+   prop = fdt_getprop_w(initial_boot_params, memory,
+ pname, );
+
+   if (!prop || len != sizeof(u32))
+   return -ENOENT;
+
+   return fdt32_to_cpu(*prop);
+}
+EXPORT_SYMBOL_GPL(of_fdt_get_memory_prop);
+
 static bool of_fdt_device_is_available(const void *blob, unsigned long node)
 {
const char *status = fdt_getprop(blob, node, "status", NULL);
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index acf820e88952..537f29373358 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -38,6 +38,7 @@ extern char __dtb_end[];
 /* Other Prototypes */
 extern u64 of_flat_dt_translate_address(unsigned long node);
 extern void of_fdt_limit_memory(int limit);
+extern int of_fdt_get_memory_prop(const char *pname);
 #endif /* CONFIG_OF_FLATTREE */
 
 #ifdef CONFIG_OF_EARLY_FLATTREE
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH 1/1] perf: Add CPU hotplug support for events

2018-02-16 Thread Raghavendra Rao Ananta



On 02/16/2018 12:39 PM, Peter Zijlstra wrote:

On Fri, Feb 16, 2018 at 10:06:29AM -0800, Raghavendra Rao Ananta wrote:

No this is absolutely disguisting. You can simply keep the events in the
dead CPU's context. It's really not that hard.

Keeping the events in the dead CPU's context was also an idea that we had.
However, detaching that event from the PMU when the CPU is offline would be
a pain. Consider the scenario in which an event is about to be destroyed
when the CPU is offline (yet still attached to the CPU). During it's
destruction, a cross-cpu call is made (from perf_remove_from_context()) to
the offlined CPU to detach the event from the CPU's PMU. As the CPU is
offline, that would not be possible, and again a separate logic has to be
written for cleaning up the events whose CPUs are offlined.


That is actually really simple to deal with. The real problems are with
semantics, is an event enabled when the CPU is dead? Can you
disable/enable an event on a dead CPU.

The below patch (_completely_ untested) should do most of it, but needs
help with the details. I suspect we want to allow enable/disable on
events that are on a dead CPU, and equally I think we want to account
the time an enabled event spends on a dead CPU to go towards the
'enabled' bucket.
I've gone through your diff, and it gave me a hint of similar texture 
what we are trying to do (except for maintaining an offline event list). 
Nevertheless, I tried to test your patch. I created an hw event, and 
tried to offline the CPU in parallel, and I immediately hit a watchdog 
soft lockup bug! Tried the same this by first switching off the CPU 
(without any event created), and I hit into similar issue. I am sure we 
can fix it, but apart from the "why we are doing hotplug?" question, was 
was there specifically any issue with our patch?





Also, you _still_ don't explain why you care about dead CPUs.

I wanted to understand, if we no longer care about hotplugging of CPUs, 
then why do we still have exported symbols such as cpu_up() and 
cpu_down()? Moreover, we also have the hotplug interface exposed to 
users-space as well (through sysfs). As long as these interfaces exist, 
there's always a potential chance of bringing the CPU up/down. Can you 
please clear this thing up for me?


-- Raghavendra

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 1/1] perf: Add CPU hotplug support for events

2018-02-16 Thread Raghavendra Rao Ananta



On 02/16/2018 12:39 PM, Peter Zijlstra wrote:

On Fri, Feb 16, 2018 at 10:06:29AM -0800, Raghavendra Rao Ananta wrote:

No this is absolutely disguisting. You can simply keep the events in the
dead CPU's context. It's really not that hard.

Keeping the events in the dead CPU's context was also an idea that we had.
However, detaching that event from the PMU when the CPU is offline would be
a pain. Consider the scenario in which an event is about to be destroyed
when the CPU is offline (yet still attached to the CPU). During it's
destruction, a cross-cpu call is made (from perf_remove_from_context()) to
the offlined CPU to detach the event from the CPU's PMU. As the CPU is
offline, that would not be possible, and again a separate logic has to be
written for cleaning up the events whose CPUs are offlined.


That is actually really simple to deal with. The real problems are with
semantics, is an event enabled when the CPU is dead? Can you
disable/enable an event on a dead CPU.

The below patch (_completely_ untested) should do most of it, but needs
help with the details. I suspect we want to allow enable/disable on
events that are on a dead CPU, and equally I think we want to account
the time an enabled event spends on a dead CPU to go towards the
'enabled' bucket.
I've gone through your diff, and it gave me a hint of similar texture 
what we are trying to do (except for maintaining an offline event list). 
Nevertheless, I tried to test your patch. I created an hw event, and 
tried to offline the CPU in parallel, and I immediately hit a watchdog 
soft lockup bug! Tried the same this by first switching off the CPU 
(without any event created), and I hit into similar issue. I am sure we 
can fix it, but apart from the "why we are doing hotplug?" question, was 
was there specifically any issue with our patch?





Also, you _still_ don't explain why you care about dead CPUs.

I wanted to understand, if we no longer care about hotplugging of CPUs, 
then why do we still have exported symbols such as cpu_up() and 
cpu_down()? Moreover, we also have the hotplug interface exposed to 
users-space as well (through sysfs). As long as these interfaces exist, 
there's always a potential chance of bringing the CPU up/down. Can you 
please clear this thing up for me?


-- Raghavendra

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 1/1] perf: Add CPU hotplug support for events

2018-02-16 Thread Raghavendra Rao Ananta



On 02/16/2018 12:21 AM, Peter Zijlstra wrote:

On Thu, Feb 15, 2018 at 03:01:41PM -0800, Raghavendra Rao Ananta wrote:

Perf framework doesn't allow prevserving CPU events across
CPU hotplugs. The events are scheduled out as and when the
CPU walks offline. Moreover, the framework also doesn't
allow the clients to create events on an offline CPU. As
a result, the clients have to keep on monitoring the CPU
state until it comes back online.

Therefore, introducing the perf framework to support creation
and preserving of (CPU) events for offline CPUs. Through
this, the CPU's online state would be transparent to the
client and it not have to worry about monitoring the CPU's
state. Success would be returned to the client even while
creating the event on an offline CPU. If during the lifetime
of the event the CPU walks offline, the event would be
preserved and would continue to count as soon as (and if) the
CPU comes back online.

Signed-off-by: Raghavendra Rao Ananta <rana...@codeaurora.org>
---
  include/linux/perf_event.h |   7 +++
  kernel/events/core.c   | 123 +
  2 files changed, 97 insertions(+), 33 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7546822..bc07f16 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -489,6 +489,7 @@ struct perf_addr_filters_head {
   * enum perf_event_state - the states of a event
   */
  enum perf_event_state {
+   PERF_EVENT_STATE_DORMANT= -5,
PERF_EVENT_STATE_DEAD   = -4,
PERF_EVENT_STATE_EXIT   = -3,
PERF_EVENT_STATE_ERROR  = -2,
@@ -687,6 +688,12 @@ struct perf_event {
  #endif
  
  	struct list_head		sb_list;

+
+   /* Entry into the list that holds the events whose CPUs
+* are offline. These events will be removed from the
+* list and installed once the CPU wakes up.
+*/
+   struct list_headdormant_entry;


No this is absolutely disguisting. You can simply keep the events in the
dead CPU's context. It's really not that hard.
Keeping the events in the dead CPU's context was also an idea that we 
had. However, detaching that event from the PMU when the CPU is offline 
would be a pain. Consider the scenario in which an event is about to be 
destroyed when the CPU is offline (yet still attached to the CPU). 
During it's destruction, a cross-cpu call is made (from 
perf_remove_from_context()) to the offlined CPU to detach the event from 
the CPU's PMU. As the CPU is offline, that would not be possible, and 
again a separate logic has to be written for cleaning up the events 
whose CPUs are offlined. Hence, I thought it would be a cleaner way to 
maintain the events.


Also, you _still_ don't explain why you care about dead CPUs.



It's just not only about dead CPUs. It's the fact that the CPUs can come 
and go online. The embedded world, specifically Android mobile SoCs, 
rely on CPU hotplugs to manage power and thermal constraints. These 
hotplugs can happen at a very rapid pace. Adjacently, they also rely on 
many perf event counters for its management. Therefore, there is

a need to preserve these events across hotplugs.
In such a scenario, a perf client (kernel or user-space) can create
events even when the CPU is offline. If the CPU comes online during
the lifetime of the event, the registered event can start counting
spontaneously. As an extension to this, the events' count can also
be preserved across CPU hotplugs. This takes the burden off of the
clients to monitor the state of the CPU.

-- Raghavendra

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 1/1] perf: Add CPU hotplug support for events

2018-02-16 Thread Raghavendra Rao Ananta



On 02/16/2018 12:21 AM, Peter Zijlstra wrote:

On Thu, Feb 15, 2018 at 03:01:41PM -0800, Raghavendra Rao Ananta wrote:

Perf framework doesn't allow prevserving CPU events across
CPU hotplugs. The events are scheduled out as and when the
CPU walks offline. Moreover, the framework also doesn't
allow the clients to create events on an offline CPU. As
a result, the clients have to keep on monitoring the CPU
state until it comes back online.

Therefore, introducing the perf framework to support creation
and preserving of (CPU) events for offline CPUs. Through
this, the CPU's online state would be transparent to the
client and it not have to worry about monitoring the CPU's
state. Success would be returned to the client even while
creating the event on an offline CPU. If during the lifetime
of the event the CPU walks offline, the event would be
preserved and would continue to count as soon as (and if) the
CPU comes back online.

Signed-off-by: Raghavendra Rao Ananta 
---
  include/linux/perf_event.h |   7 +++
  kernel/events/core.c   | 123 +
  2 files changed, 97 insertions(+), 33 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7546822..bc07f16 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -489,6 +489,7 @@ struct perf_addr_filters_head {
   * enum perf_event_state - the states of a event
   */
  enum perf_event_state {
+   PERF_EVENT_STATE_DORMANT= -5,
PERF_EVENT_STATE_DEAD   = -4,
PERF_EVENT_STATE_EXIT   = -3,
PERF_EVENT_STATE_ERROR  = -2,
@@ -687,6 +688,12 @@ struct perf_event {
  #endif
  
  	struct list_head		sb_list;

+
+   /* Entry into the list that holds the events whose CPUs
+* are offline. These events will be removed from the
+* list and installed once the CPU wakes up.
+*/
+   struct list_headdormant_entry;


No this is absolutely disguisting. You can simply keep the events in the
dead CPU's context. It's really not that hard.
Keeping the events in the dead CPU's context was also an idea that we 
had. However, detaching that event from the PMU when the CPU is offline 
would be a pain. Consider the scenario in which an event is about to be 
destroyed when the CPU is offline (yet still attached to the CPU). 
During it's destruction, a cross-cpu call is made (from 
perf_remove_from_context()) to the offlined CPU to detach the event from 
the CPU's PMU. As the CPU is offline, that would not be possible, and 
again a separate logic has to be written for cleaning up the events 
whose CPUs are offlined. Hence, I thought it would be a cleaner way to 
maintain the events.


Also, you _still_ don't explain why you care about dead CPUs.



It's just not only about dead CPUs. It's the fact that the CPUs can come 
and go online. The embedded world, specifically Android mobile SoCs, 
rely on CPU hotplugs to manage power and thermal constraints. These 
hotplugs can happen at a very rapid pace. Adjacently, they also rely on 
many perf event counters for its management. Therefore, there is

a need to preserve these events across hotplugs.
In such a scenario, a perf client (kernel or user-space) can create
events even when the CPU is offline. If the CPU comes online during
the lifetime of the event, the registered event can start counting
spontaneously. As an extension to this, the events' count can also
be preserved across CPU hotplugs. This takes the burden off of the
clients to monitor the state of the CPU.

-- Raghavendra

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH 1/1] perf: Add CPU hotplug support for events

2018-02-15 Thread Raghavendra Rao Ananta
Perf framework doesn't allow prevserving CPU events across
CPU hotplugs. The events are scheduled out as and when the
CPU walks offline. Moreover, the framework also doesn't
allow the clients to create events on an offline CPU. As
a result, the clients have to keep on monitoring the CPU
state until it comes back online.

Therefore, introducing the perf framework to support creation
and preserving of (CPU) events for offline CPUs. Through
this, the CPU's online state would be transparent to the
client and it not have to worry about monitoring the CPU's
state. Success would be returned to the client even while
creating the event on an offline CPU. If during the lifetime
of the event the CPU walks offline, the event would be
preserved and would continue to count as soon as (and if) the
CPU comes back online.

Signed-off-by: Raghavendra Rao Ananta <rana...@codeaurora.org>
---
 include/linux/perf_event.h |   7 +++
 kernel/events/core.c   | 123 +
 2 files changed, 97 insertions(+), 33 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7546822..bc07f16 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -489,6 +489,7 @@ struct perf_addr_filters_head {
  * enum perf_event_state - the states of a event
  */
 enum perf_event_state {
+   PERF_EVENT_STATE_DORMANT= -5,
PERF_EVENT_STATE_DEAD   = -4,
PERF_EVENT_STATE_EXIT   = -3,
PERF_EVENT_STATE_ERROR  = -2,
@@ -687,6 +688,12 @@ struct perf_event {
 #endif
 
struct list_headsb_list;
+
+   /* Entry into the list that holds the events whose CPUs
+* are offline. These events will be removed from the
+* list and installed once the CPU wakes up.
+*/
+   struct list_headdormant_entry;
 #endif /* CONFIG_PERF_EVENTS */
 };
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 96db9ae..5d0a155 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2329,6 +2329,30 @@ static int  __perf_install_in_context(void *info)
return ret;
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static DEFINE_PER_CPU(struct list_head, dormant_event_list);
+static DEFINE_PER_CPU(spinlock_t, dormant_event_list_lock);
+
+static void perf_prepare_install_in_context(struct perf_event *event)
+{
+   int cpu = event->cpu;
+   bool prepare_hp_sched = !READ_ONCE(event->ctx->task);
+
+   if (!prepare_hp_sched)
+   return;
+
+   spin_lock(_cpu(dormant_event_list_lock, cpu));
+   if (event->state == PERF_EVENT_STATE_DORMANT)
+   goto out;
+
+   event->state = PERF_EVENT_STATE_DORMANT;
+   list_add_tail(>dormant_entry,
+   _cpu(dormant_event_list, cpu));
+out:
+   spin_unlock(_cpu(dormant_event_list_lock, cpu));
+}
+#endif
+
 /*
  * Attach a performance event to a context.
  *
@@ -2353,6 +2377,15 @@ static int  __perf_install_in_context(void *info)
smp_store_release(>ctx, ctx);
 
if (!task) {
+   struct perf_cpu_context *cpuctx =
+   container_of(ctx, struct perf_cpu_context, ctx);
+
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+   if (!cpuctx->online) {
+   perf_prepare_install_in_context(event);
+   return;
+   }
+#endif
cpu_function_call(cpu, __perf_install_in_context, event);
return;
}
@@ -2421,6 +2454,43 @@ static int  __perf_install_in_context(void *info)
raw_spin_unlock_irq(>lock);
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static void perf_deferred_install_in_context(int cpu)
+{
+   struct perf_event *event, *tmp;
+   struct perf_event_context *ctx;
+
+   /* This function is called twice while coming online. Once for
+* CPUHP_PERF_PREPARE and the other for CPUHP_AP_PERF_ONLINE.
+* Only during the CPUHP_AP_PERF_ONLINE state, we can confirm
+* that CPU PMU is ready and can be installed to.
+*/
+   if (!cpu_online(cpu))
+   return;
+
+   spin_lock(_cpu(dormant_event_list_lock, cpu));
+   list_for_each_entry_safe(event, tmp,
+   _cpu(dormant_event_list, cpu), dormant_entry) {
+   if (cpu != event->cpu)
+   continue;
+
+   list_del(>dormant_entry);
+   event->state = PERF_EVENT_STATE_INACTIVE;
+   spin_unlock(_cpu(dormant_event_list_lock, cpu));
+
+   ctx = event->ctx;
+   perf_event_set_state(event, PERF_EVENT_STATE_INACTIVE);
+
+   mutex_lock(>mutex);
+   perf_install_in_context(ctx, event, cpu);
+   mutex_unlock(>mutex);
+
+   spin_lock(_cpu(dormant_event_l

[PATCH 1/1] perf: Add CPU hotplug support for events

2018-02-15 Thread Raghavendra Rao Ananta
Perf framework doesn't allow prevserving CPU events across
CPU hotplugs. The events are scheduled out as and when the
CPU walks offline. Moreover, the framework also doesn't
allow the clients to create events on an offline CPU. As
a result, the clients have to keep on monitoring the CPU
state until it comes back online.

Therefore, introducing the perf framework to support creation
and preserving of (CPU) events for offline CPUs. Through
this, the CPU's online state would be transparent to the
client and it not have to worry about monitoring the CPU's
state. Success would be returned to the client even while
creating the event on an offline CPU. If during the lifetime
of the event the CPU walks offline, the event would be
preserved and would continue to count as soon as (and if) the
CPU comes back online.

Signed-off-by: Raghavendra Rao Ananta 
---
 include/linux/perf_event.h |   7 +++
 kernel/events/core.c   | 123 +
 2 files changed, 97 insertions(+), 33 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7546822..bc07f16 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -489,6 +489,7 @@ struct perf_addr_filters_head {
  * enum perf_event_state - the states of a event
  */
 enum perf_event_state {
+   PERF_EVENT_STATE_DORMANT= -5,
PERF_EVENT_STATE_DEAD   = -4,
PERF_EVENT_STATE_EXIT   = -3,
PERF_EVENT_STATE_ERROR  = -2,
@@ -687,6 +688,12 @@ struct perf_event {
 #endif
 
struct list_headsb_list;
+
+   /* Entry into the list that holds the events whose CPUs
+* are offline. These events will be removed from the
+* list and installed once the CPU wakes up.
+*/
+   struct list_headdormant_entry;
 #endif /* CONFIG_PERF_EVENTS */
 };
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 96db9ae..5d0a155 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2329,6 +2329,30 @@ static int  __perf_install_in_context(void *info)
return ret;
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static DEFINE_PER_CPU(struct list_head, dormant_event_list);
+static DEFINE_PER_CPU(spinlock_t, dormant_event_list_lock);
+
+static void perf_prepare_install_in_context(struct perf_event *event)
+{
+   int cpu = event->cpu;
+   bool prepare_hp_sched = !READ_ONCE(event->ctx->task);
+
+   if (!prepare_hp_sched)
+   return;
+
+   spin_lock(_cpu(dormant_event_list_lock, cpu));
+   if (event->state == PERF_EVENT_STATE_DORMANT)
+   goto out;
+
+   event->state = PERF_EVENT_STATE_DORMANT;
+   list_add_tail(>dormant_entry,
+   _cpu(dormant_event_list, cpu));
+out:
+   spin_unlock(_cpu(dormant_event_list_lock, cpu));
+}
+#endif
+
 /*
  * Attach a performance event to a context.
  *
@@ -2353,6 +2377,15 @@ static int  __perf_install_in_context(void *info)
smp_store_release(>ctx, ctx);
 
if (!task) {
+   struct perf_cpu_context *cpuctx =
+   container_of(ctx, struct perf_cpu_context, ctx);
+
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+   if (!cpuctx->online) {
+   perf_prepare_install_in_context(event);
+   return;
+   }
+#endif
cpu_function_call(cpu, __perf_install_in_context, event);
return;
}
@@ -2421,6 +2454,43 @@ static int  __perf_install_in_context(void *info)
raw_spin_unlock_irq(>lock);
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static void perf_deferred_install_in_context(int cpu)
+{
+   struct perf_event *event, *tmp;
+   struct perf_event_context *ctx;
+
+   /* This function is called twice while coming online. Once for
+* CPUHP_PERF_PREPARE and the other for CPUHP_AP_PERF_ONLINE.
+* Only during the CPUHP_AP_PERF_ONLINE state, we can confirm
+* that CPU PMU is ready and can be installed to.
+*/
+   if (!cpu_online(cpu))
+   return;
+
+   spin_lock(_cpu(dormant_event_list_lock, cpu));
+   list_for_each_entry_safe(event, tmp,
+   _cpu(dormant_event_list, cpu), dormant_entry) {
+   if (cpu != event->cpu)
+   continue;
+
+   list_del(>dormant_entry);
+   event->state = PERF_EVENT_STATE_INACTIVE;
+   spin_unlock(_cpu(dormant_event_list_lock, cpu));
+
+   ctx = event->ctx;
+   perf_event_set_state(event, PERF_EVENT_STATE_INACTIVE);
+
+   mutex_lock(>mutex);
+   perf_install_in_context(ctx, event, cpu);
+   mutex_unlock(>mutex);
+
+   spin_lock(_cpu(dormant_event_list_lock, cpu));
+   }
+   spin_unlock(_c

[PATCH 0/1] perf: Add CPU hotplug support for events

2018-02-15 Thread Raghavendra Rao Ananta
The embedded world, specifically Android mobile SoCs, rely on CPU
hotplugs to manage power and thermal constraints. These hotplugs
can happen at a very rapid pace. Adjacently, they also relies on
many perf event counters for its management. Therefore, there is
a need to preserve these events across hotplugs.

In such a scenario, a perf client (kernel or user-space) can create
events even when the CPU is offline. If the CPU comes online during
the lifetime of the event, the registered event can start counting
spontaneously. As an extension to this, the events' count can also
be preserved across CPU hotplugs. This takes the burden off of the
clients to monitor the state of the CPU.

The tests were conducted on x86_64 PC. Sample results:
/* CPU-1 is offline: Event created when CPU is offline */
# ./perf stat -C 1 -e cycles -v -I 1000
Using CPUID GenuineIntel-6-5E
cycles: 0 0 0
#   time counts unit events
 1.000143727cycles
cycles: 0 0 0
 2.000309394cycles
cycles: 0 0 0
 3.000466412cycles
cycles: 0 0 0
 4.000599885cycles
cycles: 0 0 0
 5.000750095cycles
cycles: 0 0 0
 6.000901789cycles
cycles: 0 0 0
 7.001035315cycles
cycles: 0 0 0
 8.001195270cycles

/* CPU-1 made online: Event started counting */

cycles: 21046256 719464572 719464572
 9.001379820 21,046,256  cycles
cycles: 19537953 1000222653 1000222653
10.001634052 19,537,953  cycles
cycles: 27480135 195468 195468
11.001764556 27,480,135  cycles
cycles: 27723233 1000108008 1000108008
12.001909310 27,723,233  cycles
cycles: 19137349 1000133462 1000133462
13.002079041 19,137,349  cycles
cycles: 48913285 1000101268 1000101268
14.002218928 48,913,285  cycles
cycles: 27259199 1000128972 1000128972
15.002388700 27,259,199  cycles
cycles: 19249055 195789 195789
16.002514765 19,249,055  cycles
cycles: 27530051 1000246860 1000246860
17.002801610 27,530,051  cycles
cycles: 34348072 1000272874 1000272874
18.003110100 34,348,072  cycles
cycles: 11526457 107984264 107984264
19.003435811 11,526,457  cycles

/* CPU-1 made offline */

cycles: 0 0 0
20.003582803cycles
cycles: 0 0 0
21.003896484cycles
cycles: 0 0 0
22.004212989cycles
cycles: 0 0 0
23.004346689cycles
cycles: 0 0 0
24.004668259cycles
cycles: 0 0 0
25.004983504cycles
cycles: 0 0 0
#   time counts unit events
26.005315741cycles

/* CPU-1 made online: Event preserved across hotplug */

cycles: 27210082 933493459 933493459
27.005652287 27,210,082  cycles
cycles: 41950431 1000112865 1000112865
28.005805475 41,950,431  cycles
cycles: 35075124 1000141146 1000141146
29.005974101 35,075,124  cycles
cycles: 45240055 1000132743 1000132743
30.006140008 45,240,055  cycles
cycles: 43426180 177828 177828
31.006253035 43,426,180  cycles
cycles: 34593167 1000315835 1000315835
32.006605393 34,593,167  cycles
cycles: 105078270 1000136171 1000136171
33.006773971105,078,270  cycles

Raghavendra Rao Ananta (1):
  perf: Add CPU hotplug support for events

 include/linux/perf_event.h |   7 +++
 kernel/events/core.c   | 123 +
 2 files changed, 97 insertions(+), 33 deletions(-)

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/1] perf: Add CPU hotplug support for events

2018-02-15 Thread Raghavendra Rao Ananta
The embedded world, specifically Android mobile SoCs, rely on CPU
hotplugs to manage power and thermal constraints. These hotplugs
can happen at a very rapid pace. Adjacently, they also relies on
many perf event counters for its management. Therefore, there is
a need to preserve these events across hotplugs.

In such a scenario, a perf client (kernel or user-space) can create
events even when the CPU is offline. If the CPU comes online during
the lifetime of the event, the registered event can start counting
spontaneously. As an extension to this, the events' count can also
be preserved across CPU hotplugs. This takes the burden off of the
clients to monitor the state of the CPU.

The tests were conducted on x86_64 PC. Sample results:
/* CPU-1 is offline: Event created when CPU is offline */
# ./perf stat -C 1 -e cycles -v -I 1000
Using CPUID GenuineIntel-6-5E
cycles: 0 0 0
#   time counts unit events
 1.000143727cycles
cycles: 0 0 0
 2.000309394cycles
cycles: 0 0 0
 3.000466412cycles
cycles: 0 0 0
 4.000599885cycles
cycles: 0 0 0
 5.000750095cycles
cycles: 0 0 0
 6.000901789cycles
cycles: 0 0 0
 7.001035315cycles
cycles: 0 0 0
 8.001195270cycles

/* CPU-1 made online: Event started counting */

cycles: 21046256 719464572 719464572
 9.001379820 21,046,256  cycles
cycles: 19537953 1000222653 1000222653
10.001634052 19,537,953  cycles
cycles: 27480135 195468 195468
11.001764556 27,480,135  cycles
cycles: 27723233 1000108008 1000108008
12.001909310 27,723,233  cycles
cycles: 19137349 1000133462 1000133462
13.002079041 19,137,349  cycles
cycles: 48913285 1000101268 1000101268
14.002218928 48,913,285  cycles
cycles: 27259199 1000128972 1000128972
15.002388700 27,259,199  cycles
cycles: 19249055 195789 195789
16.002514765 19,249,055  cycles
cycles: 27530051 1000246860 1000246860
17.002801610 27,530,051  cycles
cycles: 34348072 1000272874 1000272874
18.003110100 34,348,072  cycles
cycles: 11526457 107984264 107984264
19.003435811 11,526,457  cycles

/* CPU-1 made offline */

cycles: 0 0 0
20.003582803cycles
cycles: 0 0 0
21.003896484cycles
cycles: 0 0 0
22.004212989cycles
cycles: 0 0 0
23.004346689cycles
cycles: 0 0 0
24.004668259cycles
cycles: 0 0 0
25.004983504cycles
cycles: 0 0 0
#   time counts unit events
26.005315741cycles

/* CPU-1 made online: Event preserved across hotplug */

cycles: 27210082 933493459 933493459
27.005652287 27,210,082  cycles
cycles: 41950431 1000112865 1000112865
28.005805475 41,950,431  cycles
cycles: 35075124 1000141146 1000141146
29.005974101 35,075,124  cycles
cycles: 45240055 1000132743 1000132743
30.006140008 45,240,055  cycles
cycles: 43426180 177828 177828
31.006253035 43,426,180  cycles
cycles: 34593167 1000315835 1000315835
32.006605393 34,593,167  cycles
cycles: 105078270 1000136171 1000136171
33.006773971105,078,270  cycles

Raghavendra Rao Ananta (1):
  perf: Add CPU hotplug support for events

 include/linux/perf_event.h |   7 +++
 kernel/events/core.c   | 123 +
 2 files changed, 97 insertions(+), 33 deletions(-)

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH] perf: Add support for creating offline events

2018-02-13 Thread Raghavendra Rao Ananta



On 02/13/2018 08:08 AM, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 02:22:30PM -0800, Raghavendra Rao Ananta wrote:



On 02/12/2018 01:21 PM, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 10:04:42PM +0100, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 09:42:05AM -0800, Raghavendra Rao Ananta wrote:

Hi Jiri,

Thank you for the response.

Does perf tool has its own check to see if the CPU was offline during the
lifetime of an event? If so, it might ignore these type of events.


nope, we don't check on that



Initially, I tested the same using perf tool and found similar results.
Then I debugged further and found that the perf core was actually sending
data to the userspace (copy_to_user()) and the corresponding count for the
data. Hence, I tested this further by writing my own userspace application,
and I was able to read the count through this,
even when the CPU was made offline and back online.

Do you think we also have to modify the perf tool accordingly?


hum, I wonder what's wrong.. will check


I think the user space needs to enable the event once the
cpu gets online.. which we dont do and your app does..?

maybe we could add perf_event_attr::enable_on_online ;-)

I'll check what we can do in user space, I guess we can
monitor the cpu state and enable event accordingly

jirka


Yes, probably that's the reason.

In order for an event to get scheduled-in, it expects the event to be at
least in PERF_EVENT_STATE_INACTIVE state. If you notice, in my patch,
when the cpu wakes up, we are initializing the state of the event
(perf_event__state_init()) and then trying to schedule-in. Since the event
was created with a disabled state, it seems that the same this is followed
and the state gets initialized to PERF_EVENT_STATE_OFF. Unfortunately,
events in this state could not be scheduled.

One way for things to get working is, instead of calling
perf_event__state_init() before the event is scheduled-in (when the cpu
wakes up), we can do something like:
perf_event_set_state(event, PERF_EVENT_STATE_INACTIVE);


could you add check in ioctl call that set the inactive state
on the dormant event.. that would start it once the cpu is
online.. as requested


I am a little confused. When you say "check", do you mean a new ioctl 
command?


So the flow (from the user-space perspective) would go something like this?

1. // CPU offline

2. perf_event_open(); // event started as disabled --> added to dormant 
list in the kernel


3. ioctl(SET_INACTIVE); // change the state of the event to inactive

4. // CPU woken up!

5. // schedule the (inactive) event by traversing the dormant list

Is this what you were trying to mention, or am I missing something?

Raghavendra
--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH] perf: Add support for creating offline events

2018-02-13 Thread Raghavendra Rao Ananta



On 02/13/2018 08:08 AM, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 02:22:30PM -0800, Raghavendra Rao Ananta wrote:



On 02/12/2018 01:21 PM, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 10:04:42PM +0100, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 09:42:05AM -0800, Raghavendra Rao Ananta wrote:

Hi Jiri,

Thank you for the response.

Does perf tool has its own check to see if the CPU was offline during the
lifetime of an event? If so, it might ignore these type of events.


nope, we don't check on that



Initially, I tested the same using perf tool and found similar results.
Then I debugged further and found that the perf core was actually sending
data to the userspace (copy_to_user()) and the corresponding count for the
data. Hence, I tested this further by writing my own userspace application,
and I was able to read the count through this,
even when the CPU was made offline and back online.

Do you think we also have to modify the perf tool accordingly?


hum, I wonder what's wrong.. will check


I think the user space needs to enable the event once the
cpu gets online.. which we dont do and your app does..?

maybe we could add perf_event_attr::enable_on_online ;-)

I'll check what we can do in user space, I guess we can
monitor the cpu state and enable event accordingly

jirka


Yes, probably that's the reason.

In order for an event to get scheduled-in, it expects the event to be at
least in PERF_EVENT_STATE_INACTIVE state. If you notice, in my patch,
when the cpu wakes up, we are initializing the state of the event
(perf_event__state_init()) and then trying to schedule-in. Since the event
was created with a disabled state, it seems that the same this is followed
and the state gets initialized to PERF_EVENT_STATE_OFF. Unfortunately,
events in this state could not be scheduled.

One way for things to get working is, instead of calling
perf_event__state_init() before the event is scheduled-in (when the cpu
wakes up), we can do something like:
perf_event_set_state(event, PERF_EVENT_STATE_INACTIVE);


could you add check in ioctl call that set the inactive state
on the dormant event.. that would start it once the cpu is
online.. as requested


I am a little confused. When you say "check", do you mean a new ioctl 
command?


So the flow (from the user-space perspective) would go something like this?

1. // CPU offline

2. perf_event_open(); // event started as disabled --> added to dormant 
list in the kernel


3. ioctl(SET_INACTIVE); // change the state of the event to inactive

4. // CPU woken up!

5. // schedule the (inactive) event by traversing the dormant list

Is this what you were trying to mention, or am I missing something?

Raghavendra
--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH] perf: Add support for creating offline events

2018-02-12 Thread Raghavendra Rao Ananta



On 02/12/2018 01:21 PM, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 10:04:42PM +0100, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 09:42:05AM -0800, Raghavendra Rao Ananta wrote:

Hi Jiri,

Thank you for the response.

Does perf tool has its own check to see if the CPU was offline during the
lifetime of an event? If so, it might ignore these type of events.


nope, we don't check on that



Initially, I tested the same using perf tool and found similar results.
Then I debugged further and found that the perf core was actually sending
data to the userspace (copy_to_user()) and the corresponding count for the
data. Hence, I tested this further by writing my own userspace application,
and I was able to read the count through this,
even when the CPU was made offline and back online.

Do you think we also have to modify the perf tool accordingly?


hum, I wonder what's wrong.. will check


I think the user space needs to enable the event once the
cpu gets online.. which we dont do and your app does..?

maybe we could add perf_event_attr::enable_on_online ;-)

I'll check what we can do in user space, I guess we can
monitor the cpu state and enable event accordingly

jirka


Yes, probably that's the reason.

In order for an event to get scheduled-in, it expects the event to be at 
least in PERF_EVENT_STATE_INACTIVE state. If you notice, in my patch,
when the cpu wakes up, we are initializing the state of the event 
(perf_event__state_init()) and then trying to schedule-in. Since the 
event was created with a disabled state, it seems that the same this is 
followed and the state gets initialized to PERF_EVENT_STATE_OFF. 
Unfortunately, events in this state could not be scheduled.


One way for things to get working is, instead of calling 
perf_event__state_init() before the event is scheduled-in (when the cpu 
wakes up), we can do something like:

perf_event_set_state(event, PERF_EVENT_STATE_INACTIVE);

I made this change and ran the same test as yours, and I see things 
working out for us:


# ./perf stat -C 1 -e sched:sched_switch -v -I 1000
failed to read counter sched:sched_switch
#   time counts unit events
 1.000115547sched:sched_switch 


failed to read counter sched:sched_switch
 2.000265492sched:sched_switch 


failed to read counter sched:sched_switch
 3.000379462sched:sched_switch 


failed to read counter sched:sched_switch
 4.000523872sched:sched_switch 


failed to read counter sched:sched_switch
 5.000614808sched:sched_switch

/* CPU bought ONLINE here */

sched:sched_switch: 541 284808940 284808940
 6.000767761541  sched:sched_switch 


sched:sched_switch: 180 1000119686 1000119686
 7.000907234180  sched:sched_switch 


sched:sched_switch: 248 1000129929 1000129929
 8.001026518248  sched:sched_switch 


sched:sched_switch: 253 1000173050 1000173050
 9.001203689253  sched:sched_switch 


sched:sched_switch: 620 1000113378 1000113378
10.001323334620  sched:sched_switch 


sched:sched_switch: 366 1000121839 1000121839
11.001448354366  sched:sched_switch 


sched:sched_switch: 327 1000147664 1000147664
12.001591432327  sched:sched_switch 


^Csched:sched_switch: 272 488810681 488810681
12.490414290272  sched:sched_switch 


sched:sched_switch: 6 75893 75893

Yes, so as you mentioned adding something like 
perf_event_attr::enable_on_online gives us a control as to put the event 
in INACTIVE state.

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH] perf: Add support for creating offline events

2018-02-12 Thread Raghavendra Rao Ananta



On 02/12/2018 01:21 PM, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 10:04:42PM +0100, Jiri Olsa wrote:

On Mon, Feb 12, 2018 at 09:42:05AM -0800, Raghavendra Rao Ananta wrote:

Hi Jiri,

Thank you for the response.

Does perf tool has its own check to see if the CPU was offline during the
lifetime of an event? If so, it might ignore these type of events.


nope, we don't check on that



Initially, I tested the same using perf tool and found similar results.
Then I debugged further and found that the perf core was actually sending
data to the userspace (copy_to_user()) and the corresponding count for the
data. Hence, I tested this further by writing my own userspace application,
and I was able to read the count through this,
even when the CPU was made offline and back online.

Do you think we also have to modify the perf tool accordingly?


hum, I wonder what's wrong.. will check


I think the user space needs to enable the event once the
cpu gets online.. which we dont do and your app does..?

maybe we could add perf_event_attr::enable_on_online ;-)

I'll check what we can do in user space, I guess we can
monitor the cpu state and enable event accordingly

jirka


Yes, probably that's the reason.

In order for an event to get scheduled-in, it expects the event to be at 
least in PERF_EVENT_STATE_INACTIVE state. If you notice, in my patch,
when the cpu wakes up, we are initializing the state of the event 
(perf_event__state_init()) and then trying to schedule-in. Since the 
event was created with a disabled state, it seems that the same this is 
followed and the state gets initialized to PERF_EVENT_STATE_OFF. 
Unfortunately, events in this state could not be scheduled.


One way for things to get working is, instead of calling 
perf_event__state_init() before the event is scheduled-in (when the cpu 
wakes up), we can do something like:

perf_event_set_state(event, PERF_EVENT_STATE_INACTIVE);

I made this change and ran the same test as yours, and I see things 
working out for us:


# ./perf stat -C 1 -e sched:sched_switch -v -I 1000
failed to read counter sched:sched_switch
#   time counts unit events
 1.000115547sched:sched_switch 


failed to read counter sched:sched_switch
 2.000265492sched:sched_switch 


failed to read counter sched:sched_switch
 3.000379462sched:sched_switch 


failed to read counter sched:sched_switch
 4.000523872sched:sched_switch 


failed to read counter sched:sched_switch
 5.000614808sched:sched_switch

/* CPU bought ONLINE here */

sched:sched_switch: 541 284808940 284808940
 6.000767761541  sched:sched_switch 


sched:sched_switch: 180 1000119686 1000119686
 7.000907234180  sched:sched_switch 


sched:sched_switch: 248 1000129929 1000129929
 8.001026518248  sched:sched_switch 


sched:sched_switch: 253 1000173050 1000173050
 9.001203689253  sched:sched_switch 


sched:sched_switch: 620 1000113378 1000113378
10.001323334620  sched:sched_switch 


sched:sched_switch: 366 1000121839 1000121839
11.001448354366  sched:sched_switch 


sched:sched_switch: 327 1000147664 1000147664
12.001591432327  sched:sched_switch 


^Csched:sched_switch: 272 488810681 488810681
12.490414290272  sched:sched_switch 


sched:sched_switch: 6 75893 75893

Yes, so as you mentioned adding something like 
perf_event_attr::enable_on_online gives us a control as to put the event 
in INACTIVE state.

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH] perf: Add support for creating offline events

2018-02-12 Thread Raghavendra Rao Ananta

Hi Jiri,

Thank you for the response.

Does perf tool has its own check to see if the CPU was offline during 
the lifetime of an event? If so, it might ignore these type of events.


Initially, I tested the same using perf tool and found similar results.
Then I debugged further and found that the perf core was actually 
sending data to the userspace (copy_to_user()) and the corresponding 
count for the data. Hence, I tested this further by writing my own 
userspace application, and I was able to read the count through this,

even when the CPU was made offline and back online.

Do you think we also have to modify the perf tool accordingly?

Find an inline comment.

On 02/12/2018 01:43 AM, Jiri Olsa wrote:

On Fri, Feb 09, 2018 at 03:07:00PM -0800, Raghavendra Rao Ananta wrote:

Perf framework doesn't allow creation of hardware events if
the requested CPU is offline. However, creation of an event
is achievable if the event is attached to the PMU as soon
as the CPU is online again.

So, introducing a feature that could allow to create events
even when the CPU is offline and return a success to the caller.
If, during the time of event creation, the CPU is found offline,
the event is moved to a new state (PERF_EVENT_STATE_DORMANT). As
and when the CPU is know to be woken up (through hotplug notifiers),
all the dormant events would be attached to the PMU (by
perf_install_in_context()). If during the life time of the event,
the CPU hasn't come online, the dormant event would just be freed.

Signed-off-by: Raghavendra Rao Ananta <rana...@codeaurora.org>


hum, I tried and for some reason I'm getting zero counts/times
when the cpu 1 is set back online (in 9.second)

[root@ibm-x3650m4-02 perf]# ./perf stat -C 1 -e sched:sched_switch -v -I 1000
failed to read counter sched:sched_switch
#   time counts unit events
  1.000921624sched:sched_switch
failed to read counter sched:sched_switch
  2.001725364sched:sched_switch
failed to read counter sched:sched_switch
  3.002685350sched:sched_switch
failed to read counter sched:sched_switch
  4.003463851sched:sched_switch
failed to read counter sched:sched_switch
  5.004651601sched:sched_switch
failed to read counter sched:sched_switch
  6.005338294sched:sched_switch
failed to read counter sched:sched_switch
  7.006351155sched:sched_switch
failed to read counter sched:sched_switch
  8.007239698sched:sched_switch
sched:sched_switch: 0 0 0
  9.008665621sched:sched_switch
sched:sched_switch: 0 0 0
 10.009570492sched:sched_switch
sched:sched_switch: 0 0 0
 11.010811591sched:sched_switch
sched:sched_switch: 0 0 0
 12.011614182sched:sched_switch
sched:sched_switch: 0 0 0
 13.012299851sched:sched_switch

looks like the dormant event wasn't scheduled in properly

also while at it, could we also handle cpu going offline case,
so the event would survive until it's back online

Sure, I have a plan for that one as well, but wondering how this goes first.


jirka



Thank you.

Raghavendra

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH] perf: Add support for creating offline events

2018-02-12 Thread Raghavendra Rao Ananta

Hi Jiri,

Thank you for the response.

Does perf tool has its own check to see if the CPU was offline during 
the lifetime of an event? If so, it might ignore these type of events.


Initially, I tested the same using perf tool and found similar results.
Then I debugged further and found that the perf core was actually 
sending data to the userspace (copy_to_user()) and the corresponding 
count for the data. Hence, I tested this further by writing my own 
userspace application, and I was able to read the count through this,

even when the CPU was made offline and back online.

Do you think we also have to modify the perf tool accordingly?

Find an inline comment.

On 02/12/2018 01:43 AM, Jiri Olsa wrote:

On Fri, Feb 09, 2018 at 03:07:00PM -0800, Raghavendra Rao Ananta wrote:

Perf framework doesn't allow creation of hardware events if
the requested CPU is offline. However, creation of an event
is achievable if the event is attached to the PMU as soon
as the CPU is online again.

So, introducing a feature that could allow to create events
even when the CPU is offline and return a success to the caller.
If, during the time of event creation, the CPU is found offline,
the event is moved to a new state (PERF_EVENT_STATE_DORMANT). As
and when the CPU is know to be woken up (through hotplug notifiers),
all the dormant events would be attached to the PMU (by
perf_install_in_context()). If during the life time of the event,
the CPU hasn't come online, the dormant event would just be freed.

Signed-off-by: Raghavendra Rao Ananta 


hum, I tried and for some reason I'm getting zero counts/times
when the cpu 1 is set back online (in 9.second)

[root@ibm-x3650m4-02 perf]# ./perf stat -C 1 -e sched:sched_switch -v -I 1000
failed to read counter sched:sched_switch
#   time counts unit events
  1.000921624sched:sched_switch
failed to read counter sched:sched_switch
  2.001725364sched:sched_switch
failed to read counter sched:sched_switch
  3.002685350sched:sched_switch
failed to read counter sched:sched_switch
  4.003463851sched:sched_switch
failed to read counter sched:sched_switch
  5.004651601sched:sched_switch
failed to read counter sched:sched_switch
  6.005338294sched:sched_switch
failed to read counter sched:sched_switch
  7.006351155sched:sched_switch
failed to read counter sched:sched_switch
  8.007239698sched:sched_switch
sched:sched_switch: 0 0 0
  9.008665621sched:sched_switch
sched:sched_switch: 0 0 0
 10.009570492sched:sched_switch
sched:sched_switch: 0 0 0
 11.010811591sched:sched_switch
sched:sched_switch: 0 0 0
 12.011614182sched:sched_switch
sched:sched_switch: 0 0 0
 13.012299851sched:sched_switch

looks like the dormant event wasn't scheduled in properly

also while at it, could we also handle cpu going offline case,
so the event would survive until it's back online

Sure, I have a plan for that one as well, but wondering how this goes first.


jirka



Thank you.

Raghavendra

--
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH] perf: Add support for creating offline events

2018-02-09 Thread Raghavendra Rao Ananta
Perf framework doesn't allow creation of hardware events if
the requested CPU is offline. However, creation of an event
is achievable if the event is attached to the PMU as soon
as the CPU is online again.

So, introducing a feature that could allow to create events
even when the CPU is offline and return a success to the caller.
If, during the time of event creation, the CPU is found offline,
the event is moved to a new state (PERF_EVENT_STATE_DORMANT). As
and when the CPU is know to be woken up (through hotplug notifiers),
all the dormant events would be attached to the PMU (by
perf_install_in_context()). If during the life time of the event,
the CPU hasn't come online, the dormant event would just be freed.

Signed-off-by: Raghavendra Rao Ananta <rana...@codeaurora.org>
---
 include/linux/perf_event.h |   7 +++
 kernel/events/core.c   | 109 -
 2 files changed, 84 insertions(+), 32 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7546822..bc07f16 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -489,6 +489,7 @@ struct perf_addr_filters_head {
  * enum perf_event_state - the states of a event
  */
 enum perf_event_state {
+   PERF_EVENT_STATE_DORMANT= -5,
PERF_EVENT_STATE_DEAD   = -4,
PERF_EVENT_STATE_EXIT   = -3,
PERF_EVENT_STATE_ERROR  = -2,
@@ -687,6 +688,12 @@ struct perf_event {
 #endif
 
struct list_headsb_list;
+
+   /* Entry into the list that holds the events whose CPUs
+* are offline. These events will be removed from the
+* list and installed once the CPU wakes up.
+*/
+   struct list_headdormant_entry;
 #endif /* CONFIG_PERF_EVENTS */
 };
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f0549e7..66dbccb 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2329,6 +2329,19 @@ static int  __perf_install_in_context(void *info)
return ret;
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static LIST_HEAD(dormant_event_list);
+static DEFINE_SPINLOCK(dormant_event_list_lock);
+
+static void perf_prepare_install_in_context(struct perf_event *event)
+{
+   spin_lock(_event_list_lock);
+   event->state = PERF_EVENT_STATE_DORMANT;
+   list_add_tail(>dormant_entry, _event_list);
+   spin_unlock(_event_list_lock);
+}
+#endif
+
 /*
  * Attach a performance event to a context.
  *
@@ -2353,6 +2366,15 @@ static int  __perf_install_in_context(void *info)
smp_store_release(>ctx, ctx);
 
if (!task) {
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+   struct perf_cpu_context *cpuctx =
+   container_of(ctx, struct perf_cpu_context, ctx);
+
+   if (!cpuctx->online) {
+   perf_prepare_install_in_context(event);
+   return;
+   }
+#endif
cpu_function_call(cpu, __perf_install_in_context, event);
return;
}
@@ -2421,6 +2443,43 @@ static int  __perf_install_in_context(void *info)
raw_spin_unlock_irq(>lock);
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static void perf_deferred_install_in_context(int cpu)
+{
+   struct perf_event *event, *tmp;
+   struct perf_event_context *ctx;
+
+   /* This function is called twice while coming online. Once for
+* CPUHP_PERF_PREPARE and the other for CPUHP_AP_PERF_ONLINE.
+* Only during the CPUHP_AP_PERF_ONLINE state, we can confirm
+* that CPU PMU is ready and can be installed to.
+*/
+   if (!cpu_online(cpu))
+   return;
+
+   spin_lock(_event_list_lock);
+   list_for_each_entry_safe(event, tmp, _event_list,
+   dormant_entry) {
+   if (cpu != event->cpu)
+   continue;
+
+   list_del(>dormant_entry);
+   event->state = PERF_EVENT_STATE_INACTIVE;
+   spin_unlock(_event_list_lock);
+
+   ctx = event->ctx;
+   perf_event__state_init(event);
+
+   mutex_lock(>mutex);
+   perf_install_in_context(ctx, event, cpu);
+   mutex_unlock(>mutex);
+
+   spin_lock(_event_list_lock);
+   }
+   spin_unlock(_event_list_lock);
+}
+#endif
+
 /*
  * Cross CPU call to enable a performance event
  */
@@ -4202,6 +4261,13 @@ int perf_event_release_kernel(struct perf_event *event)
struct perf_event *child, *tmp;
LIST_HEAD(free_list);
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+   spin_lock(_event_list_lock);
+   if (event->state == PERF_EVENT_STATE_DORMANT)
+   list_del(>dormant_entry);
+   spin_unlock(_event_list_lock);
+#endif
+
/*
   

[PATCH] perf: Add support for creating offline events

2018-02-09 Thread Raghavendra Rao Ananta
Perf framework doesn't allow creation of hardware events if
the requested CPU is offline. However, creation of an event
is achievable if the event is attached to the PMU as soon
as the CPU is online again.

So, introducing a feature that could allow to create events
even when the CPU is offline and return a success to the caller.
If, during the time of event creation, the CPU is found offline,
the event is moved to a new state (PERF_EVENT_STATE_DORMANT). As
and when the CPU is know to be woken up (through hotplug notifiers),
all the dormant events would be attached to the PMU (by
perf_install_in_context()). If during the life time of the event,
the CPU hasn't come online, the dormant event would just be freed.

Signed-off-by: Raghavendra Rao Ananta 
---
 include/linux/perf_event.h |   7 +++
 kernel/events/core.c   | 109 -
 2 files changed, 84 insertions(+), 32 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7546822..bc07f16 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -489,6 +489,7 @@ struct perf_addr_filters_head {
  * enum perf_event_state - the states of a event
  */
 enum perf_event_state {
+   PERF_EVENT_STATE_DORMANT= -5,
PERF_EVENT_STATE_DEAD   = -4,
PERF_EVENT_STATE_EXIT   = -3,
PERF_EVENT_STATE_ERROR  = -2,
@@ -687,6 +688,12 @@ struct perf_event {
 #endif
 
struct list_headsb_list;
+
+   /* Entry into the list that holds the events whose CPUs
+* are offline. These events will be removed from the
+* list and installed once the CPU wakes up.
+*/
+   struct list_headdormant_entry;
 #endif /* CONFIG_PERF_EVENTS */
 };
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f0549e7..66dbccb 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2329,6 +2329,19 @@ static int  __perf_install_in_context(void *info)
return ret;
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static LIST_HEAD(dormant_event_list);
+static DEFINE_SPINLOCK(dormant_event_list_lock);
+
+static void perf_prepare_install_in_context(struct perf_event *event)
+{
+   spin_lock(_event_list_lock);
+   event->state = PERF_EVENT_STATE_DORMANT;
+   list_add_tail(>dormant_entry, _event_list);
+   spin_unlock(_event_list_lock);
+}
+#endif
+
 /*
  * Attach a performance event to a context.
  *
@@ -2353,6 +2366,15 @@ static int  __perf_install_in_context(void *info)
smp_store_release(>ctx, ctx);
 
if (!task) {
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+   struct perf_cpu_context *cpuctx =
+   container_of(ctx, struct perf_cpu_context, ctx);
+
+   if (!cpuctx->online) {
+   perf_prepare_install_in_context(event);
+   return;
+   }
+#endif
cpu_function_call(cpu, __perf_install_in_context, event);
return;
}
@@ -2421,6 +2443,43 @@ static int  __perf_install_in_context(void *info)
raw_spin_unlock_irq(>lock);
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static void perf_deferred_install_in_context(int cpu)
+{
+   struct perf_event *event, *tmp;
+   struct perf_event_context *ctx;
+
+   /* This function is called twice while coming online. Once for
+* CPUHP_PERF_PREPARE and the other for CPUHP_AP_PERF_ONLINE.
+* Only during the CPUHP_AP_PERF_ONLINE state, we can confirm
+* that CPU PMU is ready and can be installed to.
+*/
+   if (!cpu_online(cpu))
+   return;
+
+   spin_lock(_event_list_lock);
+   list_for_each_entry_safe(event, tmp, _event_list,
+   dormant_entry) {
+   if (cpu != event->cpu)
+   continue;
+
+   list_del(>dormant_entry);
+   event->state = PERF_EVENT_STATE_INACTIVE;
+   spin_unlock(_event_list_lock);
+
+   ctx = event->ctx;
+   perf_event__state_init(event);
+
+   mutex_lock(>mutex);
+   perf_install_in_context(ctx, event, cpu);
+   mutex_unlock(>mutex);
+
+   spin_lock(_event_list_lock);
+   }
+   spin_unlock(_event_list_lock);
+}
+#endif
+
 /*
  * Cross CPU call to enable a performance event
  */
@@ -4202,6 +4261,13 @@ int perf_event_release_kernel(struct perf_event *event)
struct perf_event *child, *tmp;
LIST_HEAD(free_list);
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+   spin_lock(_event_list_lock);
+   if (event->state == PERF_EVENT_STATE_DORMANT)
+   list_del(>dormant_entry);
+   spin_unlock(_event_list_lock);
+#endif
+
/*
 * If we got here