This sets up an array that describes all the TR entries to
be unpinned by relocate_new_kernel. As it stands relocate_new_kernel
makes several false assumptions about constants in xen-linux
being the same as xen, and fails to unpin several entries.
This is desipite heavy additions of #ifdef XEN code.
In order to pass all the required arguments to relocate_new_kernel,
aproximately 15 parameters would be needed. This is untidy.
And furthermore, only the first 8 parameters seem to get passed correctly.
Instead of this, the vaules are packed into an array, and
the base address of the array is passed.
I am still concerned about the TC (TLB cache) entry clearing
code in relocate_new_kernel, as it still makes assumptions
about xen-linux and xen having the same contants - however
these assumptions are currently valid.
I believe that it should be possible to further restructure things
such that the TR and TC unpinning portions of relocate_new_kernel are
replaced by code supplied by xen. This should be possible
because this code is run before the segmentation relocation takes place,
and thus xen memory should be accessable at this time. Such an
approach should be able to make use of ia64_do_tlb_purge,
reducing the both the ammount of code and maintenence overhead
in the future.
The construction of such a change would likely remove all of
the code incoporated in this patch. So I'm not aiming to have
this change merged until I investigate the code-in-xen idea.
There is also a xen-linux portion to this patch.
Cc: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
Index: xen-unstable.hg/xen/arch/ia64/xen/machine_kexec.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/machine_kexec.c 2008-01-23
15:16:11.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/machine_kexec.c 2008-01-23
15:17:33.000000000 +0900
@@ -25,6 +25,7 @@
#include <linux/notifier.h>
#include <asm/dom_fw_dom0.h>
+#if 0
typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
unsigned long indirection_page,
unsigned long start_address,
@@ -32,9 +33,23 @@ typedef asmlinkage NORET_TYPE void (*rel
unsigned long pal_addr,
unsigned long cpu_data_pa,
unsigned long kernel_start,
- unsigned long page_offset,
+ unsigned long percpu_addr,
+ unsigned long shared_info,
+ unsigned long shared_info_shift,
+ unsigned long priv_regs,
+ unsigned long priv_regs_shift,
+ unsigned long stack,
unsigned long vhpt)
ATTRIB_NORET;
+#endif
+
+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 cpu_data_pa,
+ unsigned long *tr_list)
+ ATTRIB_NORET;
#define kexec_flush_icache_page(page) \
do { \
@@ -51,15 +66,19 @@ void machine_kexec_unload(int type, int
{
}
+#define PURGE_DTLB (1LL<<62)
+#define PURGE_ITLB (1LL<<63)
+
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;
+ unsigned long tr[(7*2)+1];
int ii;
/* Interrupts aren't acceptable while we reboot */
@@ -84,12 +103,50 @@ 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);
+
+ ii = 0;
+ /* TR for kernel text and data */
+ tr[ii++] = PURGE_ITLB|PURGE_DTLB|(KERNEL_TR_PAGE_SHIFT<<2);
+ tr[ii++] = KERNEL_START;
+ /* TR for percpu data */
+ tr[ii++] = PURGE_DTLB|(PERCPU_PAGE_SHIFT<<2);
+ tr[ii++] = PERCPU_ADDR;
+ /* TR for shared_info
+ * v->domain->arch.shared_info_va is rubbis if
+ * v->domain->shared_info is zero. If this is
+ * a problem use a saved value.
+ */
+ BUG_ON(!v->domain->shared_info);
+ tr[ii++] = PURGE_DTLB|(XSI_SHIFT<<2);
+ tr[ii++] = v->domain->arch.shared_info_va;
+ /* TR for mapped_regs */
+ tr[ii++] = PURGE_DTLB|(XMAPPEDREGS_SHIFT<<2);
+ tr[ii++] = v->domain->arch.shared_info_va + XMAPPEDREGS_OFS;
+ /* TR for pal code */
+ tr[ii++] = PURGE_ITLB|(IA64_GRANULE_SHIFT<<2);
+ /* XXX: GRANULEROUNDDOWN is probably not neccessary
+ * as ptr should ignore trailing bits
+ */
+ tr[ii++] = GRANULEROUNDDOWN((unsigned long) pal_vaddr);
+ /* TR for stack
+ * Ony clear stack if it doesn't overlap with kernel text and data
+ * - which it seems to often
+ */
+ if (((unsigned long)current & ~(KERNEL_TR_PAGE_SIZE-1)) !=
+ KERNEL_START) {
+ tr[ii++] = PURGE_DTLB|(IA64_GRANULE_SHIFT<<2);
+ tr[ii++] = (unsigned long)current;
+ }
+#if VHPT_ENABLED
+ // TR for VHPT
+ tr[ii++] = PURGE_DTLB|(IA64_GRANULE_SHIFT<<2);
+ tr[ii++] = __va_ul(vcpu_vhpt_maddr(current));
+#endif
+ tr[ii] = 0UL;
+
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);
+ cpu_data_pa, tr);
BUG();
}
--
--
Horms
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|