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>
This commit is contained in:
Родитель
a9e7062d73
Коммит
5b09b2876e
|
@ -39,6 +39,13 @@ static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata;
|
|||
static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly;
|
||||
#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)
|
||||
{
|
||||
pgd_t *pgd = pgd_offset_k(0UL);
|
||||
|
@ -102,9 +109,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
|
|||
|
||||
early_printk("Kernel alive\n");
|
||||
|
||||
_cpu_pda = __cpu_pda;
|
||||
cpu_pda(0) = &_boot_cpu_pda;
|
||||
pda_init(0);
|
||||
x86_64_init_pda();
|
||||
|
||||
early_printk("Kernel really alive\n");
|
||||
|
||||
|
|
|
@ -971,6 +971,7 @@ void xen_setup_vcpu_info_placement(void)
|
|||
|
||||
/* xen_vcpu_setup managed to place the vcpu_info within the
|
||||
percpu area for all cpus, so make use of it */
|
||||
#ifdef CONFIG_X86_32
|
||||
if (have_vcpu_info_placement) {
|
||||
printk(KERN_INFO "Xen: using vcpu_info placement\n");
|
||||
|
||||
|
@ -980,6 +981,7 @@ void xen_setup_vcpu_info_placement(void)
|
|||
pv_irq_ops.irq_enable = xen_irq_enable_direct;
|
||||
pv_mmu_ops.read_cr2 = xen_read_cr2_direct;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
switch (type) {
|
||||
#ifdef CONFIG_X86_32
|
||||
SITE(pv_irq_ops, irq_enable);
|
||||
SITE(pv_irq_ops, irq_disable);
|
||||
SITE(pv_irq_ops, save_fl);
|
||||
SITE(pv_irq_ops, restore_fl);
|
||||
#endif /* CONFIG_X86_32 */
|
||||
#undef SITE
|
||||
|
||||
patch_site:
|
||||
|
@ -1323,6 +1327,7 @@ asmlinkage void __init xen_start_kernel(void)
|
|||
#ifdef CONFIG_X86_64
|
||||
/* Disable until direct per-cpu data access. */
|
||||
have_vcpu_info_placement = 0;
|
||||
x86_64_init_pda();
|
||||
#endif
|
||||
|
||||
xen_smp_init();
|
||||
|
|
|
@ -22,6 +22,32 @@
|
|||
|
||||
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 */
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
|
|
@ -76,6 +76,7 @@ extern unsigned long init_pg_tables_start;
|
|||
extern unsigned long init_pg_tables_end;
|
||||
|
||||
#else
|
||||
void __init x86_64_init_pda(void);
|
||||
void __init x86_64_start_kernel(char *real_mode);
|
||||
void __init x86_64_start_reservations(char *real_mode_data);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче