source: trunk/packages/xen-3.1/xen-3.1/xen/arch/ia64/xen/xenpatch.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 3.7 KB
Line 
1/******************************************************************************
2 * xenpatch.c
3 * Copyright (c) 2006 Silicon Graphics Inc.
4 *         Jes Sorensen <jes@sgi.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 * Parts of this based on code from arch/ia64/kernel/patch.c
20 */
21
22#include <xen/config.h>
23#include <xen/lib.h>
24#include <asm/xensystem.h>
25#include <asm/intrinsics.h>
26
27/*
28 * This was adapted from code written by Tony Luck:
29 *
30 * The 64-bit value in a "movl reg=value" is scattered between the two words of the bundle
31 * like this:
32 *
33 * 6  6         5         4         3         2         1
34 * 3210987654321098765432109876543210987654321098765432109876543210
35 * ABBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCDEEEEEFFFFFFFFFGGGGGGG
36 *
37 * CCCCCCCCCCCCCCCCCCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
38 * xxxxAFFFFFFFFFEEEEEDxGGGGGGGxxxxxxxxxxxxxBBBBBBBBBBBBBBBBBBBBBBB
39 */
40static u64
41get_imm64 (u64 insn_addr)
42{
43        u64 *p = (u64 *) (insn_addr & -16);     /* mask out slot number */
44
45        return ( (p[1] & 0x0800000000000000UL) << 4)  | /*A*/
46                ((p[1] & 0x00000000007fffffUL) << 40) | /*B*/
47                ((p[0] & 0xffffc00000000000UL) >> 24) | /*C*/
48                ((p[1] & 0x0000100000000000UL) >> 23) | /*D*/
49                ((p[1] & 0x0003e00000000000UL) >> 29) | /*E*/
50                ((p[1] & 0x07fc000000000000UL) >> 43) | /*F*/
51                ((p[1] & 0x000007f000000000UL) >> 36);  /*G*/
52}
53
54/* Patch instruction with "val" where "mask" has 1 bits. */
55void
56ia64_patch (u64 insn_addr, u64 mask, u64 val)
57{
58        u64 m0, m1, v0, v1, b0, b1, *b = (u64 *) (insn_addr & -16);
59#define insn_mask ((1UL << 41) - 1)
60        unsigned long shift;
61
62        b0 = b[0]; b1 = b[1];
63        /* 5 bits of template, then 3 x 41-bit instructions */
64        shift = 5 + 41 * (insn_addr % 16);
65        if (shift >= 64) {
66                m1 = mask << (shift - 64);
67                v1 = val << (shift - 64);
68        } else {
69                m0 = mask << shift; m1 = mask >> (64 - shift);
70                v0 = val  << shift; v1 = val >> (64 - shift);
71                b[0] = (b0 & ~m0) | (v0 & m0);
72        }
73        b[1] = (b1 & ~m1) | (v1 & m1);
74}
75
76void
77ia64_patch_imm64 (u64 insn_addr, u64 val)
78{
79        /* The assembler may generate offset pointing to either slot 1
80           or slot 2 for a long (2-slot) instruction, occupying slots 1
81           and 2.  */
82        insn_addr &= -16UL;
83        ia64_patch(insn_addr + 2, 0x01fffefe000UL,
84                   (((val & 0x8000000000000000UL) >> 27) | /* bit 63 -> 36 */
85                    ((val & 0x0000000000200000UL) <<  0) | /* bit 21 -> 21 */
86                    ((val & 0x00000000001f0000UL) <<  6) | /* bit 16 -> 22 */
87                    ((val & 0x000000000000ff80UL) << 20) | /* bit  7 -> 27 */
88                    ((val & 0x000000000000007fUL) << 13)  /* bit  0 -> 13 */));
89        ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
90}
91
92extern char frametable_miss;
93extern unsigned long xen_pstart;
94
95/*
96 * Add more patch points in seperate functions as appropriate
97 */
98
99static void xen_patch_frametable_miss(u64 offset)
100{
101        u64 addr, val;
102
103        addr = (u64)&frametable_miss;
104        val = get_imm64(addr) + offset;
105        ia64_patch_imm64(addr, val);
106}
107
108
109void xen_patch_kernel(void)
110{
111        unsigned long patch_offset;
112
113        patch_offset = xen_pstart - (KERNEL_START - PAGE_OFFSET);
114
115        printk("Xen patching physical address access by offset: "
116               "0x%lx\n", patch_offset);
117
118        xen_patch_frametable_miss(patch_offset);
119
120        ia64_sync_i();
121        ia64_srlz_i();
122}
Note: See TracBrowser for help on using the repository browser.