Commit 5b09b287 authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Ingo Molnar

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: default avatarJeremy 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: default avatarIngo Molnar <mingo@elte.hu>
parent a9e7062d
...@@ -39,6 +39,13 @@ static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata; ...@@ -39,6 +39,13 @@ static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata;
static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly; static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly;
#endif #endif
void __init x86_64_init_pda(void)
{
_cpu_pda = __cpu_pda;
cpu_pda(0) = &_boot_cpu_pda;
pda_init(0);
}
static void __init zap_identity_mappings(void) static void __init zap_identity_mappings(void)
{ {
pgd_t *pgd = pgd_offset_k(0UL); pgd_t *pgd = pgd_offset_k(0UL);
...@@ -102,9 +109,7 @@ void __init x86_64_start_kernel(char * real_mode_data) ...@@ -102,9 +109,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
early_printk("Kernel alive\n"); early_printk("Kernel alive\n");
_cpu_pda = __cpu_pda; x86_64_init_pda();
cpu_pda(0) = &_boot_cpu_pda;
pda_init(0);
early_printk("Kernel really alive\n"); early_printk("Kernel really alive\n");
......
...@@ -971,6 +971,7 @@ void xen_setup_vcpu_info_placement(void) ...@@ -971,6 +971,7 @@ void xen_setup_vcpu_info_placement(void)
/* xen_vcpu_setup managed to place the vcpu_info within the /* xen_vcpu_setup managed to place the vcpu_info within the
percpu area for all cpus, so make use of it */ percpu area for all cpus, so make use of it */
#ifdef CONFIG_X86_32
if (have_vcpu_info_placement) { if (have_vcpu_info_placement) {
printk(KERN_INFO "Xen: using vcpu_info placement\n"); printk(KERN_INFO "Xen: using vcpu_info placement\n");
...@@ -980,6 +981,7 @@ void xen_setup_vcpu_info_placement(void) ...@@ -980,6 +981,7 @@ void xen_setup_vcpu_info_placement(void)
pv_irq_ops.irq_enable = xen_irq_enable_direct; pv_irq_ops.irq_enable = xen_irq_enable_direct;
pv_mmu_ops.read_cr2 = xen_read_cr2_direct; pv_mmu_ops.read_cr2 = xen_read_cr2_direct;
} }
#endif
} }
static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, 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,10 +1002,12 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
goto patch_site goto patch_site
switch (type) { switch (type) {
#ifdef CONFIG_X86_32
SITE(pv_irq_ops, irq_enable); SITE(pv_irq_ops, irq_enable);
SITE(pv_irq_ops, irq_disable); SITE(pv_irq_ops, irq_disable);
SITE(pv_irq_ops, save_fl); SITE(pv_irq_ops, save_fl);
SITE(pv_irq_ops, restore_fl); SITE(pv_irq_ops, restore_fl);
#endif /* CONFIG_X86_32 */
#undef SITE #undef SITE
patch_site: patch_site:
...@@ -1323,6 +1327,7 @@ asmlinkage void __init xen_start_kernel(void) ...@@ -1323,6 +1327,7 @@ asmlinkage void __init xen_start_kernel(void)
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
/* Disable until direct per-cpu data access. */ /* Disable until direct per-cpu data access. */
have_vcpu_info_placement = 0; have_vcpu_info_placement = 0;
x86_64_init_pda();
#endif #endif
xen_smp_init(); xen_smp_init();
......
...@@ -22,6 +22,32 @@ ...@@ -22,6 +22,32 @@
DECLARE_PER_CPU(struct x8664_pda, pda); DECLARE_PER_CPU(struct x8664_pda, pda);
/*
* These are supposed to be implemented as a single instruction which
* operates on the per-cpu data base segment. x86-64 doesn't have
* that yet, so this is a fairly inefficient workaround for the
* meantime. The single instruction is atomic with respect to
* preemption and interrupts, so we need to explicitly disable
* interrupts here to achieve the same effect. However, because it
* can be used from within interrupt-disable/enable, we can't actually
* disable interrupts; disabling preemption is enough.
*/
#define x86_read_percpu(var) \
({ \
typeof(per_cpu_var(var)) __tmp; \
preempt_disable(); \
__tmp = __get_cpu_var(var); \
preempt_enable(); \
__tmp; \
})
#define x86_write_percpu(var, val) \
do { \
preempt_disable(); \
__get_cpu_var(var) = (val); \
preempt_enable(); \
} while(0)
#else /* CONFIG_X86_64 */ #else /* CONFIG_X86_64 */
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
......
...@@ -76,6 +76,7 @@ extern unsigned long init_pg_tables_start; ...@@ -76,6 +76,7 @@ extern unsigned long init_pg_tables_start;
extern unsigned long init_pg_tables_end; extern unsigned long init_pg_tables_end;
#else #else
void __init x86_64_init_pda(void);
void __init x86_64_start_kernel(char *real_mode); void __init x86_64_start_kernel(char *real_mode);
void __init x86_64_start_reservations(char *real_mode_data); void __init x86_64_start_reservations(char *real_mode_data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment