direct-io.hg

changeset 11939:a947ca5d4731

[IA64] initial xen relocation support

Add support for relocating movl instructions which are run in physical
mode and rely on physical addressing.

This is needed to support platforms which do not provide physical
memory at address 0x4000000.

More relocation points are likely to be needed, please add them as
appropriate in xenpatch.c

Signed-off-by: Jes Sorensen <jes@sgi.com>
author awilliam@xenbuild.aw
date Sun Oct 01 11:14:00 2006 -0600 (2006-10-01)
parents 92bd25c46f27
children 53ec7e3d3a8a
files xen/arch/ia64/xen/Makefile xen/arch/ia64/xen/xenpatch.c xen/arch/ia64/xen/xensetup.c
line diff
     1.1 --- a/xen/arch/ia64/xen/Makefile	Sun Oct 01 11:09:54 2006 -0600
     1.2 +++ b/xen/arch/ia64/xen/Makefile	Sun Oct 01 11:14:00 2006 -0600
     1.3 @@ -25,5 +25,6 @@ obj-y += xensetup.o
     1.4  obj-y += xentime.o
     1.5  obj-y += flushd.o
     1.6  obj-y += privop_stat.o
     1.7 +obj-y += xenpatch.o
     1.8  
     1.9  obj-$(crash_debug) += gdbstub.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xen/arch/ia64/xen/xenpatch.c	Sun Oct 01 11:14:00 2006 -0600
     2.3 @@ -0,0 +1,122 @@
     2.4 +/******************************************************************************
     2.5 + * xenpatch.c
     2.6 + * Copyright (c) 2006 Silicon Graphics Inc.
     2.7 + *         Jes Sorensen <jes@sgi.com>
     2.8 + *
     2.9 + * This program is free software; you can redistribute it and/or modify it
    2.10 + * under the terms and conditions of the GNU General Public License,
    2.11 + * version 2, as published by the Free Software Foundation.
    2.12 + *
    2.13 + * This program is distributed in the hope it will be useful, but WITHOUT
    2.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    2.16 + * more details.
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License along with
    2.19 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    2.20 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    2.21 + *
    2.22 + * Parts of this based on code from arch/ia64/kernel/patch.c
    2.23 + */
    2.24 +
    2.25 +#include <xen/config.h>
    2.26 +#include <xen/lib.h>
    2.27 +#include <asm/xensystem.h>
    2.28 +#include <asm/intrinsics.h>
    2.29 +
    2.30 +/*
    2.31 + * This was adapted from code written by Tony Luck:
    2.32 + *
    2.33 + * The 64-bit value in a "movl reg=value" is scattered between the two words of the bundle
    2.34 + * like this:
    2.35 + *
    2.36 + * 6  6         5         4         3         2         1
    2.37 + * 3210987654321098765432109876543210987654321098765432109876543210
    2.38 + * ABBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCDEEEEEFFFFFFFFFGGGGGGG
    2.39 + *
    2.40 + * CCCCCCCCCCCCCCCCCCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    2.41 + * xxxxAFFFFFFFFFEEEEEDxGGGGGGGxxxxxxxxxxxxxBBBBBBBBBBBBBBBBBBBBBBB
    2.42 + */
    2.43 +static u64
    2.44 +get_imm64 (u64 insn_addr)
    2.45 +{
    2.46 +	u64 *p = (u64 *) (insn_addr & -16);	/* mask out slot number */
    2.47 +
    2.48 +	return ( (p[1] & 0x0800000000000000UL) << 4)  | /*A*/
    2.49 +		((p[1] & 0x00000000007fffffUL) << 40) | /*B*/
    2.50 +		((p[0] & 0xffffc00000000000UL) >> 24) | /*C*/
    2.51 +		((p[1] & 0x0000100000000000UL) >> 23) | /*D*/
    2.52 +		((p[1] & 0x0003e00000000000UL) >> 29) | /*E*/
    2.53 +		((p[1] & 0x07fc000000000000UL) >> 43) | /*F*/
    2.54 +		((p[1] & 0x000007f000000000UL) >> 36);  /*G*/
    2.55 +}
    2.56 +
    2.57 +/* Patch instruction with "val" where "mask" has 1 bits. */
    2.58 +void
    2.59 +ia64_patch (u64 insn_addr, u64 mask, u64 val)
    2.60 +{
    2.61 +	u64 m0, m1, v0, v1, b0, b1, *b = (u64 *) (insn_addr & -16);
    2.62 +#define insn_mask ((1UL << 41) - 1)
    2.63 +	unsigned long shift;
    2.64 +
    2.65 +	b0 = b[0]; b1 = b[1];
    2.66 +	/* 5 bits of template, then 3 x 41-bit instructions */
    2.67 +	shift = 5 + 41 * (insn_addr % 16);
    2.68 +	if (shift >= 64) {
    2.69 +		m1 = mask << (shift - 64);
    2.70 +		v1 = val << (shift - 64);
    2.71 +	} else {
    2.72 +		m0 = mask << shift; m1 = mask >> (64 - shift);
    2.73 +		v0 = val  << shift; v1 = val >> (64 - shift);
    2.74 +		b[0] = (b0 & ~m0) | (v0 & m0);
    2.75 +	}
    2.76 +	b[1] = (b1 & ~m1) | (v1 & m1);
    2.77 +}
    2.78 +
    2.79 +void
    2.80 +ia64_patch_imm64 (u64 insn_addr, u64 val)
    2.81 +{
    2.82 +	/* The assembler may generate offset pointing to either slot 1
    2.83 +	   or slot 2 for a long (2-slot) instruction, occupying slots 1
    2.84 +	   and 2.  */
    2.85 +  	insn_addr &= -16UL;
    2.86 +	ia64_patch(insn_addr + 2, 0x01fffefe000UL,
    2.87 +		   (((val & 0x8000000000000000UL) >> 27) | /* bit 63 -> 36 */
    2.88 +		    ((val & 0x0000000000200000UL) <<  0) | /* bit 21 -> 21 */
    2.89 +		    ((val & 0x00000000001f0000UL) <<  6) | /* bit 16 -> 22 */
    2.90 +		    ((val & 0x000000000000ff80UL) << 20) | /* bit  7 -> 27 */
    2.91 +		    ((val & 0x000000000000007fUL) << 13)  /* bit  0 -> 13 */));
    2.92 +	ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
    2.93 +}
    2.94 +
    2.95 +extern char frametable_miss;
    2.96 +extern unsigned long xen_pstart;
    2.97 +
    2.98 +/*
    2.99 + * Add more patch points in seperate functions as appropriate
   2.100 + */
   2.101 +
   2.102 +static void xen_patch_frametable_miss(u64 offset)
   2.103 +{
   2.104 +	u64 addr, val;
   2.105 +
   2.106 +	addr = (u64)&frametable_miss;
   2.107 +	val = get_imm64(addr) + offset;
   2.108 +	ia64_patch_imm64(addr, val);
   2.109 +}
   2.110 +
   2.111 +
   2.112 +void xen_patch_kernel(void)
   2.113 +{
   2.114 +	unsigned long patch_offset, orig_val, new_val;
   2.115 +
   2.116 +	patch_offset = xen_pstart - (KERNEL_START - PAGE_OFFSET);
   2.117 +
   2.118 +	printk("Xen patching physical address access by offset: "
   2.119 +	       "0x%lx\n", patch_offset);
   2.120 +
   2.121 +	xen_patch_frametable_miss(patch_offset);
   2.122 +
   2.123 +	ia64_sync_i();
   2.124 +	ia64_srlz_i();
   2.125 +}
     3.1 --- a/xen/arch/ia64/xen/xensetup.c	Sun Oct 01 11:09:54 2006 -0600
     3.2 +++ b/xen/arch/ia64/xen/xensetup.c	Sun Oct 01 11:14:00 2006 -0600
     3.3 @@ -48,6 +48,7 @@ extern void setup_per_cpu_areas(void);
     3.4  extern void mem_init(void);
     3.5  extern void init_IRQ(void);
     3.6  extern void trap_init(void);
     3.7 +extern void xen_patch_kernel(void);
     3.8  
     3.9  /* opt_nosmp: If true, secondary processors are ignored. */
    3.10  static int opt_nosmp = 0;
    3.11 @@ -293,6 +294,8 @@ void start_kernel(void)
    3.12      printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
    3.13             xen_pstart, xenheap_phys_end);
    3.14  
    3.15 +    xen_patch_kernel();
    3.16 +
    3.17      kern_md = md = efi_get_md(xen_pstart);
    3.18      md_end = __pa(ia64_imva(&_end));
    3.19      relo_start = xenheap_phys_end;