Mailing List Archive

[PATCH 06 of 10] arm: per-cpu areas
# HG changeset patch
# User Tim Deegan <tim@xen.org>
# Date 1330018799 0
# Node ID 3b1d7a91a2596baca178e8b5610b3cbc299fa5ea
# Parent 1e9c6bd7cc99d1af0107aa927ee2ba03721449b7
arm: per-cpu areas

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/Makefile
--- a/xen/arch/arm/Makefile Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/Makefile Thu Feb 23 17:39:59 2012 +0000
@@ -13,6 +13,7 @@ obj-y += irq.o
obj-y += kernel.o
obj-y += mm.o
obj-y += p2m.o
+obj-y += percpu.o
obj-y += guestcopy.o
obj-y += setup.o
obj-y += time.o
diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/dummy.S
--- a/xen/arch/arm/dummy.S Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/dummy.S Thu Feb 23 17:39:59 2012 +0000
@@ -14,7 +14,6 @@ DUMMY(per_cpu__cpu_core_mask);
DUMMY(per_cpu__cpu_sibling_mask);
DUMMY(node_online_map);
DUMMY(smp_send_state_dump);
-DUMMY(__per_cpu_offset);

/* PIRQ support */
DUMMY(alloc_pirq_struct);
diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/percpu.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/arm/percpu.c Thu Feb 23 17:39:59 2012 +0000
@@ -0,0 +1,85 @@
+#include <xen/config.h>
+#include <xen/percpu.h>
+#include <xen/cpu.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/rcupdate.h>
+
+unsigned long __per_cpu_offset[NR_CPUS];
+#define INVALID_PERCPU_AREA (-(long)__per_cpu_start)
+#define PERCPU_ORDER (get_order_from_bytes(__per_cpu_data_end-__per_cpu_start))
+
+void __init percpu_init_areas(void)
+{
+ unsigned int cpu;
+ for ( cpu = 1; cpu < NR_CPUS; cpu++ )
+ __per_cpu_offset[cpu] = INVALID_PERCPU_AREA;
+}
+
+static int init_percpu_area(unsigned int cpu)
+{
+ char *p;
+ if ( __per_cpu_offset[cpu] != INVALID_PERCPU_AREA )
+ return -EBUSY;
+ if ( (p = alloc_xenheap_pages(PERCPU_ORDER, 0)) == NULL )
+ return -ENOMEM;
+ memset(p, 0, __per_cpu_data_end - __per_cpu_start);
+ __per_cpu_offset[cpu] = p - __per_cpu_start;
+ return 0;
+}
+
+struct free_info {
+ unsigned int cpu;
+ struct rcu_head rcu;
+};
+static DEFINE_PER_CPU(struct free_info, free_info);
+
+static void _free_percpu_area(struct rcu_head *head)
+{
+ struct free_info *info = container_of(head, struct free_info, rcu);
+ unsigned int cpu = info->cpu;
+ char *p = __per_cpu_start + __per_cpu_offset[cpu];
+ free_xenheap_pages(p, PERCPU_ORDER);
+ __per_cpu_offset[cpu] = INVALID_PERCPU_AREA;
+}
+
+static void free_percpu_area(unsigned int cpu)
+{
+ struct free_info *info = &per_cpu(free_info, cpu);
+ info->cpu = cpu;
+ call_rcu(&info->rcu, _free_percpu_area);
+}
+
+static int cpu_percpu_callback(
+ struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+ int rc = 0;
+
+ switch ( action )
+ {
+ case CPU_UP_PREPARE:
+ rc = init_percpu_area(cpu);
+ break;
+ case CPU_UP_CANCELED:
+ case CPU_DEAD:
+ free_percpu_area(cpu);
+ break;
+ default:
+ break;
+ }
+
+ return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
+}
+
+static struct notifier_block cpu_percpu_nfb = {
+ .notifier_call = cpu_percpu_callback,
+ .priority = 100 /* highest priority */
+};
+
+static int __init percpu_presmp_init(void)
+{
+ register_cpu_notifier(&cpu_percpu_nfb);
+ return 0;
+}
+presmp_initcall(percpu_presmp_init);
diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/include/asm-arm/percpu.h
--- a/xen/include/asm-arm/percpu.h Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/include/asm-arm/percpu.h Thu Feb 23 17:39:59 2012 +0000
@@ -12,8 +12,11 @@ void percpu_init_areas(void);
__attribute__((__section__(".bss.percpu" #suffix))) \
__typeof__(type) per_cpu_##name

-#define per_cpu(var, cpu) ((&per_cpu__##var)[cpu?0:0])
-#define __get_cpu_var(var) per_cpu__##var
+
+#define per_cpu(var, cpu) \
+ (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
+#define __get_cpu_var(var) \
+ (*RELOC_HIDE(&per_cpu__##var, get_cpu_info()->per_cpu_offset))

#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Re: [PATCH 06 of 10] arm: per-cpu areas [ In reply to ]
On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> # HG changeset patch
> # User Tim Deegan <tim@xen.org>
> # Date 1330018799 0
> # Node ID 3b1d7a91a2596baca178e8b5610b3cbc299fa5ea
> # Parent 1e9c6bd7cc99d1af0107aa927ee2ba03721449b7
> arm: per-cpu areas
>
> Signed-off-by: Tim Deegan <tim@xen.org>

I tried to apply this along with #1 and #4 but the result hung at just
after freeing initial memory. I expect that's due to missing #2,#3 or #5
rather than a bug here.

With that in mind:
Acked-by: Ian Campbell <ian.campbell@citrix.com>

>
> diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/Makefile
> --- a/xen/arch/arm/Makefile Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/Makefile Thu Feb 23 17:39:59 2012 +0000
> @@ -13,6 +13,7 @@ obj-y += irq.o
> obj-y += kernel.o
> obj-y += mm.o
> obj-y += p2m.o
> +obj-y += percpu.o
> obj-y += guestcopy.o
> obj-y += setup.o
> obj-y += time.o
> diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/dummy.S
> --- a/xen/arch/arm/dummy.S Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/dummy.S Thu Feb 23 17:39:59 2012 +0000
> @@ -14,7 +14,6 @@ DUMMY(per_cpu__cpu_core_mask);
> DUMMY(per_cpu__cpu_sibling_mask);
> DUMMY(node_online_map);
> DUMMY(smp_send_state_dump);
> -DUMMY(__per_cpu_offset);
>
> /* PIRQ support */
> DUMMY(alloc_pirq_struct);
> diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/percpu.c
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/xen/arch/arm/percpu.c Thu Feb 23 17:39:59 2012 +0000
> @@ -0,0 +1,85 @@
> +#include <xen/config.h>
> +#include <xen/percpu.h>
> +#include <xen/cpu.h>
> +#include <xen/init.h>
> +#include <xen/mm.h>
> +#include <xen/rcupdate.h>
> +
> +unsigned long __per_cpu_offset[NR_CPUS];
> +#define INVALID_PERCPU_AREA (-(long)__per_cpu_start)
> +#define PERCPU_ORDER (get_order_from_bytes(__per_cpu_data_end-__per_cpu_start))
> +
> +void __init percpu_init_areas(void)
> +{
> + unsigned int cpu;
> + for ( cpu = 1; cpu < NR_CPUS; cpu++ )
> + __per_cpu_offset[cpu] = INVALID_PERCPU_AREA;
> +}
> +
> +static int init_percpu_area(unsigned int cpu)
> +{
> + char *p;
> + if ( __per_cpu_offset[cpu] != INVALID_PERCPU_AREA )
> + return -EBUSY;
> + if ( (p = alloc_xenheap_pages(PERCPU_ORDER, 0)) == NULL )
> + return -ENOMEM;
> + memset(p, 0, __per_cpu_data_end - __per_cpu_start);
> + __per_cpu_offset[cpu] = p - __per_cpu_start;
> + return 0;
> +}
> +
> +struct free_info {
> + unsigned int cpu;
> + struct rcu_head rcu;
> +};
> +static DEFINE_PER_CPU(struct free_info, free_info);
> +
> +static void _free_percpu_area(struct rcu_head *head)
> +{
> + struct free_info *info = container_of(head, struct free_info, rcu);
> + unsigned int cpu = info->cpu;
> + char *p = __per_cpu_start + __per_cpu_offset[cpu];
> + free_xenheap_pages(p, PERCPU_ORDER);
> + __per_cpu_offset[cpu] = INVALID_PERCPU_AREA;
> +}
> +
> +static void free_percpu_area(unsigned int cpu)
> +{
> + struct free_info *info = &per_cpu(free_info, cpu);
> + info->cpu = cpu;
> + call_rcu(&info->rcu, _free_percpu_area);
> +}
> +
> +static int cpu_percpu_callback(
> + struct notifier_block *nfb, unsigned long action, void *hcpu)
> +{
> + unsigned int cpu = (unsigned long)hcpu;
> + int rc = 0;
> +
> + switch ( action )
> + {
> + case CPU_UP_PREPARE:
> + rc = init_percpu_area(cpu);
> + break;
> + case CPU_UP_CANCELED:
> + case CPU_DEAD:
> + free_percpu_area(cpu);
> + break;
> + default:
> + break;
> + }
> +
> + return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
> +}
> +
> +static struct notifier_block cpu_percpu_nfb = {
> + .notifier_call = cpu_percpu_callback,
> + .priority = 100 /* highest priority */
> +};
> +
> +static int __init percpu_presmp_init(void)
> +{
> + register_cpu_notifier(&cpu_percpu_nfb);
> + return 0;
> +}
> +presmp_initcall(percpu_presmp_init);
> diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/include/asm-arm/percpu.h
> --- a/xen/include/asm-arm/percpu.h Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/include/asm-arm/percpu.h Thu Feb 23 17:39:59 2012 +0000
> @@ -12,8 +12,11 @@ void percpu_init_areas(void);
> __attribute__((__section__(".bss.percpu" #suffix))) \
> __typeof__(type) per_cpu_##name
>
> -#define per_cpu(var, cpu) ((&per_cpu__##var)[cpu?0:0])
> -#define __get_cpu_var(var) per_cpu__##var
> +
> +#define per_cpu(var, cpu) \
> + (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
> +#define __get_cpu_var(var) \
> + (*RELOC_HIDE(&per_cpu__##var, get_cpu_info()->per_cpu_offset))
>
> #define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel