ia64/xen-unstable

changeset 17134:0b20ac6ec64a

[IA64] kexec: Unpin TLB in the hypervisor

The dom0 relocate_new_kernel code makes a large number of assumptions about
various compile time constants, and thus assumes that these constants are
the same for the hypervisor and dom0. Despite extensive #ifdef work this
has proved to be both fragile and incomplete.

This patch changes things around so that the unpinning work is done
by code provided by the hypervisor, reusing existing code there.
Apart from being a solution that works, its also likely
a much more maintainable solution, as as TLB changes in the hypervisor
code are made, the code paths in the hypervisor are much more likely
to be checked than this one which lies in a completely different tree.

There is also a dom0 Linux kernel portion to this patch.
Its commit message has comments detailing various implementation
issues. See linux-2.6.18-xen.hg ee7015727bd15e80e17e725f70c0a5336e45607a

Signed-off-by: Simon Horman <horms@verge.net.au>
author Alex Williamson <alex.williamson@hp.com>
date Fri Feb 29 09:18:01 2008 -0700 (2008-02-29)
parents daf39fc8038a
children 71a8366fb212
files xen/arch/ia64/xen/machine_kexec.c xen/arch/ia64/xen/relocate_kernel.S xen/include/asm-ia64/kexec.h
line diff
     1.1 --- a/xen/arch/ia64/xen/machine_kexec.c	Wed Feb 27 13:08:59 2008 -0700
     1.2 +++ b/xen/arch/ia64/xen/machine_kexec.c	Fri Feb 29 09:18:01 2008 -0700
     1.3 @@ -25,17 +25,6 @@
     1.4  #include <linux/notifier.h>
     1.5  #include <asm/dom_fw_dom0.h>
     1.6  
     1.7 -typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
     1.8 -					unsigned long indirection_page,
     1.9 -					unsigned long start_address,
    1.10 -					struct ia64_boot_param *boot_param,
    1.11 -					unsigned long pal_addr,
    1.12 -					unsigned long cpu_data_pa,
    1.13 -					unsigned long kernel_start,
    1.14 -					unsigned long page_offset,
    1.15 -					unsigned long vhpt)
    1.16 -					ATTRIB_NORET;
    1.17 -
    1.18  #define kexec_flush_icache_page(page)					\
    1.19  do {									\
    1.20  	unsigned long page_addr = (unsigned long)page_address(page);	\
    1.21 @@ -54,12 +43,6 @@ void machine_kexec_unload(int type, int 
    1.22  static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
    1.23  {
    1.24  	xen_kexec_image_t *image = arg;
    1.25 -	relocate_new_kernel_t rnk;
    1.26 -	unsigned long code_addr = (unsigned long)
    1.27 -				  __va(image->reboot_code_buffer);
    1.28 -	unsigned long cpu_data_pa = (unsigned long)
    1.29 -				  __pa(cpu_data(smp_processor_id()));
    1.30 -	unsigned long vhpt;
    1.31  	int ii;
    1.32  
    1.33  	/* Interrupts aren't acceptable while we reboot */
    1.34 @@ -84,12 +67,8 @@ static void ia64_machine_kexec(struct un
    1.35  	while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
    1.36  		ia64_eoi();
    1.37  	platform_kernel_launch_event();
    1.38 -	vhpt = __va_ul(vcpu_vhpt_maddr(current));
    1.39 -	BUG_ON(!vhpt);
    1.40 -	rnk = (relocate_new_kernel_t)&code_addr;
    1.41 -	(*rnk)(image->indirection_page, image->start_address, ia64_boot_param,
    1.42 -	       GRANULEROUNDDOWN((unsigned long) pal_vaddr), cpu_data_pa,
    1.43 -	       KERNEL_START, PAGE_OFFSET, vhpt);
    1.44 +	relocate_new_kernel(image->indirection_page, image->start_address,
    1.45 +			    __pa(ia64_boot_param), image->reboot_code_buffer);
    1.46  	BUG();
    1.47  }
    1.48  
     2.1 --- a/xen/arch/ia64/xen/relocate_kernel.S	Wed Feb 27 13:08:59 2008 -0700
     2.2 +++ b/xen/arch/ia64/xen/relocate_kernel.S	Fri Feb 29 09:18:01 2008 -0700
     2.3 @@ -16,6 +16,57 @@
     2.4  #include <asm/pgtable.h>
     2.5  #include <asm/mca_asm.h>
     2.6  
     2.7 +/* relocate_new_kernel
     2.8 + *
     2.9 + * Do all the unpinning here, as the hypervisor has all the relevant
    2.10 + * variables and constants. Then go into the reboot_code_buffer to
    2.11 + * relocaate the new kernel and then branch into purgatory.
    2.12 + *
    2.13 + * Based on ia64_jump_to_sal
    2.14 + *
    2.15 + * in0: indirection_page
    2.16 + * in1: start_address
    2.17 + * in2: boot_param
    2.18 + * in2: dom0_relocate_new_kernel
    2.19 + */
    2.20 +GLOBAL_ENTRY(relocate_new_kernel)
    2.21 +	.prologue
    2.22 +	alloc r31=ar.pfs,4,0,4,0
    2.23 +	.body
    2.24 +	rsm psr.i  | psr.ic
    2.25 +{
    2.26 +	flushrs
    2.27 +	srlz.i
    2.28 +}
    2.29 +	movl r18=tlb_purge_done;;
    2.30 +	DATA_VA_TO_PA(r18);;
    2.31 +	mov b1=r18	// Return location
    2.32 +	movl r18=ia64_do_tlb_purge;;
    2.33 +	DATA_VA_TO_PA(r18);;
    2.34 +	mov b2=r18	// doing tlb_flush work
    2.35 +	mov ar.rsc=0	// Put RSE  in enforced lazy, LE mode
    2.36 +	movl r17=1f;;
    2.37 +	DATA_VA_TO_PA(r17);;
    2.38 +	mov cr.iip=r17
    2.39 +	movl r16=IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC;;
    2.40 +	mov cr.ipsr=r16
    2.41 +	mov cr.ifs=r0;;
    2.42 +	rfi;;
    2.43 +1:
    2.44 +        /* Invalidate all TLB data/inst */
    2.45 +	br.sptk.many b2;; // jump to tlb purge code
    2.46 +
    2.47 +tlb_purge_done:
    2.48 +	mov out0=in0	// out3 is ignored and thus can be garbage
    2.49 +	mov out1=in1
    2.50 +	mov out2=in2
    2.51 +	mov b1=in3
    2.52 +	;;
    2.53 +	br.sptk.many b1;; // jump to dom0-supplied relocate_new_kernel
    2.54 +
    2.55 +	/* We should never get here */
    2.56 +END(relocate_new_kernel)
    2.57 +
    2.58  GLOBAL_ENTRY(ia64_dump_cpu_regs)
    2.59          .prologue
    2.60          alloc loc0=ar.pfs,1,2,0,0
     3.1 --- a/xen/include/asm-ia64/kexec.h	Wed Feb 27 13:08:59 2008 -0700
     3.2 +++ b/xen/include/asm-ia64/kexec.h	Fri Feb 29 09:18:01 2008 -0700
     3.3 @@ -5,8 +5,10 @@
     3.4  #include <xen/kexec.h>
     3.5  
     3.6  extern const unsigned int relocate_new_kernel_size;
     3.7 -extern void relocate_new_kernel(unsigned long, unsigned long,
     3.8 -                                struct ia64_boot_param *, unsigned long);
     3.9 +extern void relocate_new_kernel(unsigned long indirection_page,
    3.10 +                                unsigned long start_address,
    3.11 +                                unsigned long boot_param,
    3.12 +                                unsigned long dom0_relocate_new_kernel);
    3.13  void crash_save_xen_notes(void);
    3.14  void machine_kexec(xen_kexec_image_t *image);
    3.15  unsigned long kdump_find_rsvd_region(unsigned long size,