ia64/xen-unstable

changeset 19562:5599cc1e0a84

[IA64] fix early access to per cpu area.

The following changeset broke booting xen-ia64 on some kinds of ia64 boxes.
http://xenbits.xensource.com/ext/ia64/xen-unstable.hg/rev/3fd8f9b34941

The tasklet_schedule call raise_softirq().
Because raise_softirq() use per_cpu, if we access per_cpu before cpu_init()
the behavior would be unexpected.

There was a similar issue on Linux/ia64.
The following change sets resolved it.
10617bbe84628eb18ab5f723d3ba35005adde143
c459ce8b5a7d933a3bcf6915ab17ac1e036e2ac4

This patch fixes the issue following the linux/ia64 solution.
Allocate per cpu area for cpu0 in .data section and initialize
it early.

reported-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Tue Apr 21 18:27:59 2009 +0900 (2009-04-21)
parents 69ba67bdbf93
children 6ba4e34d21d3
files xen/arch/ia64/linux-xen/head.S xen/arch/ia64/linux-xen/mm_contig.c xen/arch/ia64/linux-xen/smpboot.c xen/arch/ia64/xen/xen.lds.S xen/include/asm-ia64/linux-xen/asm/README.origin xen/include/asm-ia64/linux-xen/asm/sections.h xen/include/asm-ia64/linux/asm/README.origin xen/include/asm-ia64/linux/asm/sections.h
line diff
     1.1 --- a/xen/arch/ia64/linux-xen/head.S	Mon Apr 20 15:38:29 2009 +0100
     1.2 +++ b/xen/arch/ia64/linux-xen/head.S	Tue Apr 21 18:27:59 2009 +0900
     1.3 @@ -382,6 +382,35 @@ 1:	// now we are in virtual mode
     1.4  	mov ar.rsc=0		// place RSE in enforced lazy mode
     1.5  	;;
     1.6  	loadrs			// clear the dirty partition
     1.7 +#ifdef XEN
     1.8 +(isAP)	br.few 2f
     1.9 +	movl r19=__phys_per_cpu_start
    1.10 +	mov r18=PERCPU_PAGE_SIZE
    1.11 +#ifndef CONFIG_SMP
    1.12 +	add r19=r19,r18
    1.13 +	;;
    1.14 +#else
    1.15 +	movl r20=__cpu0_per_cpu
    1.16 +	;;
    1.17 +	shr.u r18=r18,3
    1.18 +1:
    1.19 +	ld8 r21=[r19],8 ;;
    1.20 +	st8[r20]=r21,8
    1.21 +	adds r18=-1,r18
    1.22 +	;;
    1.23 +	cmp4.lt p7,p6=0,r18
    1.24 +(p7)	br.cond.dptk.few 1b
    1.25 +	;;
    1.26 +#endif
    1.27 +	movl r18=__per_cpu_offset
    1.28 +	movl r19=__cpu0_per_cpu
    1.29 +	movl r20=__per_cpu_start
    1.30 +	;;
    1.31 +	sub r20=r19,r20
    1.32 +	;;
    1.33 +	st8 [r18]=r20
    1.34 +2:
    1.35 +#endif
    1.36  	;;
    1.37  	mov ar.bspstore=r2	// establish the new RSE stack
    1.38  	;;
     2.1 --- a/xen/arch/ia64/linux-xen/mm_contig.c	Mon Apr 20 15:38:29 2009 +0100
     2.2 +++ b/xen/arch/ia64/linux-xen/mm_contig.c	Tue Apr 21 18:27:59 2009 +0900
     2.3 @@ -183,7 +183,7 @@ void *percpu_area __initdata = NULL;
     2.4  void* __init
     2.5  per_cpu_allocate(void *xen_heap_start, unsigned long end_in_pa)
     2.6  {
     2.7 -	int order = get_order(NR_CPUS * PERCPU_PAGE_SIZE);
     2.8 +	int order = get_order((NR_CPUS - 1) * PERCPU_PAGE_SIZE);
     2.9  	unsigned long size = 1UL << (order + PAGE_SHIFT);
    2.10  	unsigned long start = ALIGN_UP((unsigned long)xen_heap_start,
    2.11  				       PERCPU_PAGE_SIZE);
    2.12 @@ -226,19 +226,31 @@ per_cpu_init (void)
    2.13  	 */
    2.14  	if (smp_processor_id() == 0) {
    2.15  #ifdef XEN
    2.16 +		void *cpu0_data = __cpu0_per_cpu;
    2.17 +
    2.18 +		__per_cpu_offset[0] = (char *)cpu0_data - __per_cpu_start;
    2.19 +		per_cpu(local_per_cpu_offset, 0) = __per_cpu_offset[0];
    2.20 +
    2.21  		cpu_data = get_per_cpu_area();
    2.22  		if (cpu_data == NULL) 
    2.23  			panic("can't allocate per cpu area.\n");
    2.24 +
    2.25 +		for (cpu = 1; cpu < NR_CPUS; cpu++) {
    2.26 +			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
    2.27 +			__per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
    2.28 +			cpu_data += PERCPU_PAGE_SIZE;
    2.29 +			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
    2.30 +		}
    2.31  #else
    2.32  		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS,
    2.33  					   PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
    2.34 -#endif
    2.35  		for (cpu = 0; cpu < NR_CPUS; cpu++) {
    2.36  			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
    2.37  			__per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
    2.38  			cpu_data += PERCPU_PAGE_SIZE;
    2.39  			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
    2.40  		}
    2.41 +#endif
    2.42  	}
    2.43  	return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
    2.44  }
     3.1 --- a/xen/arch/ia64/linux-xen/smpboot.c	Mon Apr 20 15:38:29 2009 +0100
     3.2 +++ b/xen/arch/ia64/linux-xen/smpboot.c	Tue Apr 21 18:27:59 2009 +0900
     3.3 @@ -449,8 +449,8 @@ start_secondary (void *unused)
     3.4  {
     3.5  	/* Early console may use I/O ports */
     3.6  	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
     3.7 +#ifndef XEN
     3.8  	Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
     3.9 -#ifndef XEN
    3.10  	efi_map_pal_code();
    3.11  #endif
    3.12  	cpu_init();
     4.1 --- a/xen/arch/ia64/xen/xen.lds.S	Mon Apr 20 15:38:29 2009 +0100
     4.2 +++ b/xen/arch/ia64/xen/xen.lds.S	Tue Apr 21 18:27:59 2009 +0900
     4.3 @@ -195,7 +195,17 @@ SECTIONS
     4.4  
     4.5    data : { } :data
     4.6    .data : AT(ADDR(.data) - LOAD_OFFSET)
     4.7 -	{ *(.data) *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS }
     4.8 +	{
     4.9 +#ifdef CONFIG_SMP
    4.10 +  . = ALIGN(PERCPU_PAGE_SIZE);
    4.11 +		__cpu0_per_cpu = .;
    4.12 +  . = . + PERCPU_PAGE_SIZE;    /* cpu0 per-cpu space */
    4.13 +#endif
    4.14 +		*(.data)
    4.15 +		*(.data1)
    4.16 +		*(.gnu.linkonce.d*)
    4.17 +		CONSTRUCTORS
    4.18 +	}
    4.19  
    4.20    . = ALIGN(16);	/* gp must be 16-byte aligned for exc. table */
    4.21    .got : AT(ADDR(.got) - LOAD_OFFSET)
     5.1 --- a/xen/include/asm-ia64/linux-xen/asm/README.origin	Mon Apr 20 15:38:29 2009 +0100
     5.2 +++ b/xen/include/asm-ia64/linux-xen/asm/README.origin	Tue Apr 21 18:27:59 2009 +0900
     5.3 @@ -22,6 +22,7 @@ pgtable.h		-> linux/include/asm-ia64/pgt
     5.4  processor.h		-> linux/include/asm-ia64/processor.h
     5.5  ptrace.h		-> linux/include/asm-ia64/ptrace.h
     5.6  sal.h			-> linux/include/asm-ia64/sal.h
     5.7 +sections.h		-> linux/include/asm-ia64/sections.h
     5.8  smp.h			-> linux/include/asm-ia64/smp.h
     5.9  spinlock.h		-> linux/include/asm-ia64/spinlock.h
    5.10  system.h		-> linux/include/asm-ia64/system.h
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/include/asm-ia64/linux-xen/asm/sections.h	Tue Apr 21 18:27:59 2009 +0900
     6.3 @@ -0,0 +1,28 @@
     6.4 +#ifndef _ASM_IA64_SECTIONS_H
     6.5 +#define _ASM_IA64_SECTIONS_H
     6.6 +
     6.7 +/*
     6.8 + * Copyright (C) 1998-2003 Hewlett-Packard Co
     6.9 + *	David Mosberger-Tang <davidm@hpl.hp.com>
    6.10 + */
    6.11 +
    6.12 +#include <asm-generic/sections.h>
    6.13 +
    6.14 +extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
    6.15 +#ifdef XEN
    6.16 +#ifdef CONFIG_SMP
    6.17 +extern char __cpu0_per_cpu[];
    6.18 +#endif
    6.19 +#endif
    6.20 +extern char __start___vtop_patchlist[], __end___vtop_patchlist[];
    6.21 +extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];
    6.22 +extern char __start_gate_section[];
    6.23 +extern char __start_gate_mckinley_e9_patchlist[], __end_gate_mckinley_e9_patchlist[];
    6.24 +extern char __start_gate_vtop_patchlist[], __end_gate_vtop_patchlist[];
    6.25 +extern char __start_gate_fsyscall_patchlist[], __end_gate_fsyscall_patchlist[];
    6.26 +extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[];
    6.27 +extern char __start_unwind[], __end_unwind[];
    6.28 +extern char __start_ivt_text[], __end_ivt_text[];
    6.29 +
    6.30 +#endif /* _ASM_IA64_SECTIONS_H */
    6.31 +
     7.1 --- a/xen/include/asm-ia64/linux/asm/README.origin	Mon Apr 20 15:38:29 2009 +0100
     7.2 +++ b/xen/include/asm-ia64/linux/asm/README.origin	Tue Apr 21 18:27:59 2009 +0900
     7.3 @@ -29,7 +29,6 @@ param.h			-> linux/include/asm-ia64/para
     7.4  patch.h			-> linux/include/asm-ia64/patch.h
     7.5  pci.h			-> linux/include/asm-ia64/pci.h
     7.6  rse.h			-> linux/include/asm-ia64/rse.h
     7.7 -sections.h		-> linux/include/asm-ia64/sections.h
     7.8  setup.h			-> linux/include/asm-ia64/setup.h
     7.9  string.h		-> linux/include/asm-ia64/string.h
    7.10  thread_info.h		-> linux/include/asm-ia64/thread_info.h
     8.1 --- a/xen/include/asm-ia64/linux/asm/sections.h	Mon Apr 20 15:38:29 2009 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,23 +0,0 @@
     8.4 -#ifndef _ASM_IA64_SECTIONS_H
     8.5 -#define _ASM_IA64_SECTIONS_H
     8.6 -
     8.7 -/*
     8.8 - * Copyright (C) 1998-2003 Hewlett-Packard Co
     8.9 - *	David Mosberger-Tang <davidm@hpl.hp.com>
    8.10 - */
    8.11 -
    8.12 -#include <asm-generic/sections.h>
    8.13 -
    8.14 -extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
    8.15 -extern char __start___vtop_patchlist[], __end___vtop_patchlist[];
    8.16 -extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];
    8.17 -extern char __start_gate_section[];
    8.18 -extern char __start_gate_mckinley_e9_patchlist[], __end_gate_mckinley_e9_patchlist[];
    8.19 -extern char __start_gate_vtop_patchlist[], __end_gate_vtop_patchlist[];
    8.20 -extern char __start_gate_fsyscall_patchlist[], __end_gate_fsyscall_patchlist[];
    8.21 -extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[];
    8.22 -extern char __start_unwind[], __end_unwind[];
    8.23 -extern char __start_ivt_text[], __end_ivt_text[];
    8.24 -
    8.25 -#endif /* _ASM_IA64_SECTIONS_H */
    8.26 -