aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/paravirt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/paravirt.c')
-rw-r--r--arch/i386/kernel/paravirt.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c
index 53f07a8275e3..79c167fcaee9 100644
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -124,20 +124,28 @@ unsigned paravirt_patch_ignore(unsigned len)
124 return len; 124 return len;
125} 125}
126 126
127struct branch {
128 unsigned char opcode;
129 u32 delta;
130} __attribute__((packed));
131
127unsigned paravirt_patch_call(void *target, u16 tgt_clobbers, 132unsigned paravirt_patch_call(void *target, u16 tgt_clobbers,
128 void *site, u16 site_clobbers, 133 void *site, u16 site_clobbers,
129 unsigned len) 134 unsigned len)
130{ 135{
131 unsigned char *call = site; 136 unsigned char *call = site;
132 unsigned long delta = (unsigned long)target - (unsigned long)(call+5); 137 unsigned long delta = (unsigned long)target - (unsigned long)(call+5);
138 struct branch b;
133 139
134 if (tgt_clobbers & ~site_clobbers) 140 if (tgt_clobbers & ~site_clobbers)
135 return len; /* target would clobber too much for this site */ 141 return len; /* target would clobber too much for this site */
136 if (len < 5) 142 if (len < 5)
137 return len; /* call too long for patch site */ 143 return len; /* call too long for patch site */
138 144
139 *call++ = 0xe8; /* call */ 145 b.opcode = 0xe8; /* call */
140 *(unsigned long *)call = delta; 146 b.delta = delta;
147 BUILD_BUG_ON(sizeof(b) != 5);
148 text_poke(call, (unsigned char *)&b, 5);
141 149
142 return 5; 150 return 5;
143} 151}
@@ -150,8 +158,9 @@ unsigned paravirt_patch_jmp(void *target, void *site, unsigned len)
150 if (len < 5) 158 if (len < 5)
151 return len; /* call too long for patch site */ 159 return len; /* call too long for patch site */
152 160
153 *jmp++ = 0xe9; /* jmp */ 161 b.opcode = 0xe9; /* jmp */
154 *(unsigned long *)jmp = delta; 162 b.delta = delta;
163 text_poke(call, (unsigned char *)&b, 5);
155 164
156 return 5; 165 return 5;
157} 166}