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.
Appart 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 codepaths 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 coments detailing various implementation
issues.
Cc: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
xen/arch/ia64/xen/machine_kexec.c | 26 ++---------------
xen/arch/ia64/xen/relocate_kernel.S | 51 +++++++++++++++++++++++++++++++++++
xen/include/asm-ia64/kexec.h | 6 ++--
3 files changed, 58 insertions(+), 25 deletions(-)
Index: xen-unstable.hg/xen/arch/ia64/xen/machine_kexec.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/machine_kexec.c 2008-02-06
14:24:08.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/machine_kexec.c 2008-02-06
15:06:35.000000000 +0900
@@ -25,17 +25,6 @@
#include <linux/notifier.h>
#include <asm/dom_fw_dom0.h>
-typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
- unsigned long indirection_page,
- unsigned long start_address,
- struct ia64_boot_param *boot_param,
- unsigned long pal_addr,
- unsigned long cpu_data_pa,
- unsigned long kernel_start,
- unsigned long page_offset,
- unsigned long vhpt)
- ATTRIB_NORET;
-
#define kexec_flush_icache_page(page) \
do { \
unsigned long page_addr = (unsigned long)page_address(page); \
@@ -53,13 +42,8 @@ void machine_kexec_unload(int type, int
static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
{
+ struct vcpu *v = current;
xen_kexec_image_t *image = arg;
- relocate_new_kernel_t rnk;
- unsigned long code_addr = (unsigned long)
- __va(image->reboot_code_buffer);
- unsigned long cpu_data_pa = (unsigned long)
- __pa(cpu_data(smp_processor_id()));
- unsigned long vhpt;
int ii;
/* Interrupts aren't acceptable while we reboot */
@@ -84,12 +68,8 @@ static void ia64_machine_kexec(struct un
while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
ia64_eoi();
platform_kernel_launch_event();
- vhpt = __va_ul(vcpu_vhpt_maddr(current));
- BUG_ON(!vhpt);
- rnk = (relocate_new_kernel_t)&code_addr;
- (*rnk)(image->indirection_page, image->start_address, ia64_boot_param,
- GRANULEROUNDDOWN((unsigned long) pal_vaddr), cpu_data_pa,
- KERNEL_START, PAGE_OFFSET, vhpt);
+ relocate_new_kernel(image->indirection_page, image->start_address,
+ __pa(ia64_boot_param), image->reboot_code_buffer);
BUG();
}
Index: xen-unstable.hg/xen/arch/ia64/xen/relocate_kernel.S
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/relocate_kernel.S 2008-02-06
14:24:06.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/relocate_kernel.S 2008-02-06
14:25:42.000000000 +0900
@@ -16,6 +16,57 @@
#include <asm/pgtable.h>
#include <asm/mca_asm.h>
+/* relocate_new_kernel
+ *
+ * Do all the unpinning here, as the hypervisor has all the relevant
+ * variables and constants. Then go into the reboot_code_buffer to
+ * relocaate the new kernel and then branch into purgatory.
+ *
+ * Based on ia64_jump_to_sal
+ *
+ * in0: indirection_page
+ * in1: start_address
+ * in2: boot_param
+ * in2: dom0_relocate_new_kernel
+ */
+GLOBAL_ENTRY(relocate_new_kernel)
+ .prologue
+ alloc r31=ar.pfs,4,0,4,0
+ .body
+ rsm psr.i | psr.ic
+{
+ flushrs
+ srlz.i
+}
+ movl r18=tlb_purge_done;;
+ DATA_VA_TO_PA(r18);;
+ mov b1=r18 // Return location
+ movl r18=ia64_do_tlb_purge;;
+ DATA_VA_TO_PA(r18);;
+ mov b2=r18 // doing tlb_flush work
+ mov ar.rsc=0 // Put RSE in enforced lazy, LE mode
+ movl r17=1f;;
+ DATA_VA_TO_PA(r17);;
+ mov cr.iip=r17
+ movl r16=IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC;;
+ mov cr.ipsr=r16
+ mov cr.ifs=r0;;
+ rfi;;
+1:
+ /* Invalidate all TLB data/inst */
+ br.sptk.many b2;; // jump to tlb purge code
+
+tlb_purge_done:
+ mov out0=in0 // out3 is ignored and thus can be garbage
+ mov out1=in1
+ mov out2=in2
+ mov b1=in3
+ ;;
+ br.sptk.many b1;; // jump to dom0-supplied relocate_new_kernel
+
+ /* We should never get here */
+END(relocate_new_kernel)
+
GLOBAL_ENTRY(ia64_dump_cpu_regs)
.prologue
alloc loc0=ar.pfs,1,2,0,0
Index: xen-unstable.hg/xen/include/asm-ia64/kexec.h
===================================================================
--- xen-unstable.hg.orig/xen/include/asm-ia64/kexec.h 2008-02-06
14:24:06.000000000 +0900
+++ xen-unstable.hg/xen/include/asm-ia64/kexec.h 2008-02-06
14:25:42.000000000 +0900
@@ -5,8 +5,10 @@
#include <xen/kexec.h>
extern const unsigned int relocate_new_kernel_size;
-extern void relocate_new_kernel(unsigned long, unsigned long,
- struct ia64_boot_param *, unsigned long);
+extern void relocate_new_kernel(unsigned long indirection_page,
+ unsigned long start_address,
+ unsigned long boot_param,
+ unsigned long dom0_relocate_new_kernel);
void crash_save_xen_notes(void);
void machine_kexec(xen_kexec_image_t *image);
unsigned long kdump_find_rsvd_region(unsigned long size,
--
--
Horms
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|