diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2008-07-08 18:06:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-16 04:58:13 -0400 |
commit | 5b09b2876ed1a8e34a0da8f069575fc6174e2077 (patch) | |
tree | 370750e5c1d4073ed4a7525ccd0348e4154ba0d4 | |
parent | a9e7062d7339f1a1df2b6d7e5d595c7d55b56bfb (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.c | 11 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 5 | ||||
-rw-r--r-- | include/asm-x86/percpu.h | 26 | ||||
-rw-r--r-- | include/asm-x86/setup.h | 1 |
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; | |||
39 | static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly; | 39 | static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly; |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | void __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 | |||
42 | static void __init zap_identity_mappings(void) | 49 | static 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 | ||
985 | static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, | 987 | static 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 | ||
23 | DECLARE_PER_CPU(struct x8664_pda, pda); | 23 | DECLARE_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; | |||
76 | extern unsigned long init_pg_tables_end; | 76 | extern unsigned long init_pg_tables_end; |
77 | 77 | ||
78 | #else | 78 | #else |
79 | void __init x86_64_init_pda(void); | ||
79 | void __init x86_64_start_kernel(char *real_mode); | 80 | void __init x86_64_start_kernel(char *real_mode); |
80 | void __init x86_64_start_reservations(char *real_mode_data); | 81 | void __init x86_64_start_reservations(char *real_mode_data); |
81 | 82 | ||