aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-07-08 18:06:42 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-16 04:58:13 -0400
commit5b09b2876ed1a8e34a0da8f069575fc6174e2077 (patch)
tree370750e5c1d4073ed4a7525ccd0348e4154ba0d4
parenta9e7062d7339f1a1df2b6d7e5d595c7d55b56bfb (diff)
x86_64: add workaround for no %gs-based percpu
As a stopgap until Mike Travis's x86-64 gs-based percpu patches are ready, provide workaround functions for x86_read/write_percpu for Xen's use. Specifically, this means that we can't really make use of vcpu placement, because we can't use a single gs-based memory access to get to vcpu fields. So disable all that for now. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Cc: Stephen Tweedie <sct@redhat.com> Cc: Eduardo Habkost <ehabkost@redhat.com> Cc: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/head64.c11
-rw-r--r--arch/x86/xen/enlighten.c5
-rw-r--r--include/asm-x86/percpu.h26
-rw-r--r--include/asm-x86/setup.h1
4 files changed, 40 insertions, 3 deletions
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index c97819829146..1b318e903bf6 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -39,6 +39,13 @@ static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata;
39static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly; 39static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly;
40#endif 40#endif
41 41
42void __init x86_64_init_pda(void)
43{
44 _cpu_pda = __cpu_pda;
45 cpu_pda(0) = &_boot_cpu_pda;
46 pda_init(0);
47}
48
42static void __init zap_identity_mappings(void) 49static void __init zap_identity_mappings(void)
43{ 50{
44 pgd_t *pgd = pgd_offset_k(0UL); 51 pgd_t *pgd = pgd_offset_k(0UL);
@@ -102,9 +109,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
102 109
103 early_printk("Kernel alive\n"); 110 early_printk("Kernel alive\n");
104 111
105 _cpu_pda = __cpu_pda; 112 x86_64_init_pda();
106 cpu_pda(0) = &_boot_cpu_pda;
107 pda_init(0);
108 113
109 early_printk("Kernel really alive\n"); 114 early_printk("Kernel really alive\n");
110 115
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index a85f447b8d00..f3f11acf7856 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -971,6 +971,7 @@ void xen_setup_vcpu_info_placement(void)
971 971
972 /* xen_vcpu_setup managed to place the vcpu_info within the 972 /* xen_vcpu_setup managed to place the vcpu_info within the
973 percpu area for all cpus, so make use of it */ 973 percpu area for all cpus, so make use of it */
974#ifdef CONFIG_X86_32
974 if (have_vcpu_info_placement) { 975 if (have_vcpu_info_placement) {
975 printk(KERN_INFO "Xen: using vcpu_info placement\n"); 976 printk(KERN_INFO "Xen: using vcpu_info placement\n");
976 977
@@ -980,6 +981,7 @@ void xen_setup_vcpu_info_placement(void)
980 pv_irq_ops.irq_enable = xen_irq_enable_direct; 981 pv_irq_ops.irq_enable = xen_irq_enable_direct;
981 pv_mmu_ops.read_cr2 = xen_read_cr2_direct; 982 pv_mmu_ops.read_cr2 = xen_read_cr2_direct;
982 } 983 }
984#endif
983} 985}
984 986
985static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, 987static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
@@ -1000,10 +1002,12 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
1000 goto patch_site 1002 goto patch_site
1001 1003
1002 switch (type) { 1004 switch (type) {
1005#ifdef CONFIG_X86_32
1003 SITE(pv_irq_ops, irq_enable); 1006 SITE(pv_irq_ops, irq_enable);
1004 SITE(pv_irq_ops, irq_disable); 1007 SITE(pv_irq_ops, irq_disable);
1005 SITE(pv_irq_ops, save_fl); 1008 SITE(pv_irq_ops, save_fl);
1006 SITE(pv_irq_ops, restore_fl); 1009 SITE(pv_irq_ops, restore_fl);
1010#endif /* CONFIG_X86_32 */
1007#undef SITE 1011#undef SITE
1008 1012
1009 patch_site: 1013 patch_site:
@@ -1323,6 +1327,7 @@ asmlinkage void __init xen_start_kernel(void)
1323#ifdef CONFIG_X86_64 1327#ifdef CONFIG_X86_64
1324 /* Disable until direct per-cpu data access. */ 1328 /* Disable until direct per-cpu data access. */
1325 have_vcpu_info_placement = 0; 1329 have_vcpu_info_placement = 0;
1330 x86_64_init_pda();
1326#endif 1331#endif
1327 1332
1328 xen_smp_init(); 1333 xen_smp_init();
diff --git a/include/asm-x86/percpu.h b/include/asm-x86/percpu.h
index 912a3a17b9db..4e91ee1e37aa 100644
--- a/include/asm-x86/percpu.h
+++ b/include/asm-x86/percpu.h
@@ -22,6 +22,32 @@
22 22
23DECLARE_PER_CPU(struct x8664_pda, pda); 23DECLARE_PER_CPU(struct x8664_pda, pda);
24 24
25/*
26 * These are supposed to be implemented as a single instruction which
27 * operates on the per-cpu data base segment. x86-64 doesn't have
28 * that yet, so this is a fairly inefficient workaround for the
29 * meantime. The single instruction is atomic with respect to
30 * preemption and interrupts, so we need to explicitly disable
31 * interrupts here to achieve the same effect. However, because it
32 * can be used from within interrupt-disable/enable, we can't actually
33 * disable interrupts; disabling preemption is enough.
34 */
35#define x86_read_percpu(var) \
36 ({ \
37 typeof(per_cpu_var(var)) __tmp; \
38 preempt_disable(); \
39 __tmp = __get_cpu_var(var); \
40 preempt_enable(); \
41 __tmp; \
42 })
43
44#define x86_write_percpu(var, val) \
45 do { \
46 preempt_disable(); \
47 __get_cpu_var(var) = (val); \
48 preempt_enable(); \
49 } while(0)
50
25#else /* CONFIG_X86_64 */ 51#else /* CONFIG_X86_64 */
26 52
27#ifdef __ASSEMBLY__ 53#ifdef __ASSEMBLY__
diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h
index 90ab2225e71b..659492624e74 100644
--- a/include/asm-x86/setup.h
+++ b/include/asm-x86/setup.h
@@ -76,6 +76,7 @@ extern unsigned long init_pg_tables_start;
76extern unsigned long init_pg_tables_end; 76extern unsigned long init_pg_tables_end;
77 77
78#else 78#else
79void __init x86_64_init_pda(void);
79void __init x86_64_start_kernel(char *real_mode); 80void __init x86_64_start_kernel(char *real_mode);
80void __init x86_64_start_reservations(char *real_mode_data); 81void __init x86_64_start_reservations(char *real_mode_data);
81 82