Sun Jan 7 11:24:45 2018 UTC ()
Give patchbytes an array.


(maxv)
diff -r1.24 -r1.25 src/sys/arch/x86/x86/patch.c

cvs diff -r1.24 -r1.25 src/sys/arch/x86/x86/patch.c (expand / switch to unified diff)

--- src/sys/arch/x86/x86/patch.c 2017/10/27 23:22:01 1.24
+++ src/sys/arch/x86/x86/patch.c 2018/01/07 11:24:45 1.25
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: patch.c,v 1.24 2017/10/27 23:22:01 riastradh Exp $ */ 1/* $NetBSD: patch.c,v 1.25 2018/01/07 11:24:45 maxv Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -24,27 +24,27 @@ @@ -24,27 +24,27 @@
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Patch kernel code at boot time, depending on available CPU features. 33 * Patch kernel code at boot time, depending on available CPU features.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.24 2017/10/27 23:22:01 riastradh Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.25 2018/01/07 11:24:45 maxv Exp $");
38 38
39#include "opt_lockdebug.h" 39#include "opt_lockdebug.h"
40#ifdef i386 40#ifdef i386
41#include "opt_spldebug.h" 41#include "opt_spldebug.h"
42#endif 42#endif
43 43
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/systm.h> 45#include <sys/systm.h>
46 46
47#include <machine/cpu.h> 47#include <machine/cpu.h>
48#include <machine/cpufunc.h> 48#include <machine/cpufunc.h>
49#include <machine/specialreg.h> 49#include <machine/specialreg.h>
50 50
@@ -120,34 +120,34 @@ patchfunc(void *from_s, void *from_e, vo @@ -120,34 +120,34 @@ patchfunc(void *from_s, void *from_e, vo
120#ifdef GPROF 120#ifdef GPROF
121#ifdef i386 121#ifdef i386
122#define MCOUNT_CALL_OFFSET 3 122#define MCOUNT_CALL_OFFSET 3
123#endif 123#endif
124#ifdef __x86_64__ 124#ifdef __x86_64__
125#define MCOUNT_CALL_OFFSET 5 125#define MCOUNT_CALL_OFFSET 5
126#endif 126#endif
127 /* Patch mcount call offset */ 127 /* Patch mcount call offset */
128 adjust_jumpoff((uint8_t *)from_s + MCOUNT_CALL_OFFSET, from_s, to_s); 128 adjust_jumpoff((uint8_t *)from_s + MCOUNT_CALL_OFFSET, from_s, to_s);
129#endif 129#endif
130} 130}
131 131
132static inline void __unused 132static inline void __unused
133patchbytes(void *addr, const int byte1, const int byte2, const int byte3) 133patchbytes(void *addr, const uint8_t *bytes, size_t size)
134{ 134{
 135 uint8_t *ptr = (uint8_t *)addr;
 136 size_t i;
135 137
136 ((uint8_t *)addr)[0] = (uint8_t)byte1; 138 for (i = 0; i < size; i++) {
137 if (byte2 != -1) 139 ptr[i] = bytes[i];
138 ((uint8_t *)addr)[1] = (uint8_t)byte2; 140 }
139 if (byte3 != -1) 
140 ((uint8_t *)addr)[2] = (uint8_t)byte3; 
141} 141}
142 142
143void 143void
144x86_patch(bool early) 144x86_patch(bool early)
145{ 145{
146 static bool first, second; 146 static bool first, second;
147 u_long psl; 147 u_long psl;
148 u_long cr0; 148 u_long cr0;
149 int i; 149 int i;
150 150
151 if (early) { 151 if (early) {
152 if (first) 152 if (first)
153 return; 153 return;
@@ -159,31 +159,35 @@ x86_patch(bool early) @@ -159,31 +159,35 @@ x86_patch(bool early)
159 } 159 }
160 160
161 /* Disable interrupts. */ 161 /* Disable interrupts. */
162 psl = x86_read_psl(); 162 psl = x86_read_psl();
163 x86_disable_intr(); 163 x86_disable_intr();
164 164
165 /* Disable write protection in supervisor mode. */ 165 /* Disable write protection in supervisor mode. */
166 cr0 = rcr0(); 166 cr0 = rcr0();
167 lcr0(cr0 & ~CR0_WP); 167 lcr0(cr0 & ~CR0_WP);
168 168
169#if !defined(GPROF) 169#if !defined(GPROF)
170 if (!early && ncpu == 1) { 170 if (!early && ncpu == 1) {
171#ifndef LOCKDEBUG 171#ifndef LOCKDEBUG
 172 const uint8_t bytes[] = {
 173 X86_NOP
 174 };
 175
172 /* Uniprocessor: kill LOCK prefixes. */ 176 /* Uniprocessor: kill LOCK prefixes. */
173 for (i = 0; x86_lockpatch[i] != 0; i++) 177 for (i = 0; x86_lockpatch[i] != 0; i++)
174 patchbytes(x86_lockpatch[i], X86_NOP, -1, -1); 178 patchbytes(x86_lockpatch[i], bytes, sizeof(bytes));
175 for (i = 0; atomic_lockpatch[i] != 0; i++) 179 for (i = 0; atomic_lockpatch[i] != 0; i++)
176 patchbytes(atomic_lockpatch[i], X86_NOP, -1, -1); 180 patchbytes(atomic_lockpatch[i], bytes, sizeof(bytes));
177#endif /* !LOCKDEBUG */ 181#endif /* !LOCKDEBUG */
178 } 182 }
179 if (!early && (cpu_feature[0] & CPUID_SSE2) != 0) { 183 if (!early && (cpu_feature[0] & CPUID_SSE2) != 0) {
180 /* 184 /*
181 * Faster memory barriers. We do not need to patch 185 * Faster memory barriers. We do not need to patch
182 * membar_producer to use SFENCE because on x86 186 * membar_producer to use SFENCE because on x86
183 * ordinary non-temporal stores are always issued in 187 * ordinary non-temporal stores are always issued in
184 * program order to main memory and to other CPUs. 188 * program order to main memory and to other CPUs.
185 */ 189 */
186 patchfunc( 190 patchfunc(
187 sse2_lfence, sse2_lfence_end, 191 sse2_lfence, sse2_lfence_end,
188 membar_consumer, membar_consumer_end, 192 membar_consumer, membar_consumer_end,
189 NULL 193 NULL
@@ -227,50 +231,61 @@ x86_patch(bool early) @@ -227,50 +231,61 @@ x86_patch(bool early)
227#endif /* i386 && !LOCKDEBUG */ 231#endif /* i386 && !LOCKDEBUG */
228 } 232 }
229#endif /* !SPLDEBUG */ 233#endif /* !SPLDEBUG */
230 234
231 /* 235 /*
232 * On some Opteron revisions, locked operations erroneously 236 * On some Opteron revisions, locked operations erroneously
233 * allow memory references to be `bled' outside of critical 237 * allow memory references to be `bled' outside of critical
234 * sections. Apply workaround. 238 * sections. Apply workaround.
235 */ 239 */
236 if (cpu_vendor == CPUVENDOR_AMD && 240 if (cpu_vendor == CPUVENDOR_AMD &&
237 (CPUID_TO_FAMILY(cpu_info_primary.ci_signature) == 0xe || 241 (CPUID_TO_FAMILY(cpu_info_primary.ci_signature) == 0xe ||
238 (CPUID_TO_FAMILY(cpu_info_primary.ci_signature) == 0xf && 242 (CPUID_TO_FAMILY(cpu_info_primary.ci_signature) == 0xf &&
239 CPUID_TO_EXTMODEL(cpu_info_primary.ci_signature) < 0x4))) { 243 CPUID_TO_EXTMODEL(cpu_info_primary.ci_signature) < 0x4))) {
 244 const uint8_t bytes[] = {
 245 0x0F, 0xAE, 0xE8 /* lfence */
 246 };
 247
240 for (i = 0; x86_retpatch[i] != 0; i++) { 248 for (i = 0; x86_retpatch[i] != 0; i++) {
241 /* ret,nop,nop,ret -> lfence,ret */ 249 /* ret,nop,nop,ret -> lfence,ret */
242 patchbytes(x86_retpatch[i], 0x0f, 0xae, 0xe8); 250 patchbytes(x86_retpatch[i], bytes, sizeof(bytes));
243 } 251 }
244 } 252 }
245 253
246#ifdef amd64 254#ifdef amd64
247 /* 255 /*
248 * If SMAP is present then patch the prepared holes with clac/stac 256 * If SMAP is present then patch the prepared holes with clac/stac
249 * instructions. 257 * instructions.
250 * 258 *
251 * clac = 0x0f, 0x01, 0xca 259 * clac = 0x0f, 0x01, 0xca
252 * stac = 0x0f, 0x01, 0xcb 260 * stac = 0x0f, 0x01, 0xcb
253 */ 261 */
254 if (!early && cpu_feature[5] & CPUID_SEF_SMAP) { 262 if (!early && cpu_feature[5] & CPUID_SEF_SMAP) {
255 KASSERT(rcr4() & CR4_SMAP); 263 KASSERT(rcr4() & CR4_SMAP);
 264 const uint8_t clac_bytes[] = {
 265 0x0F, 0x01, 0xCA /* clac */
 266 };
 267 const uint8_t stac_bytes[] = {
 268 0x0F, 0x01, 0xCB /* stac */
 269 };
 270
256 for (i = 0; x86_clacpatch[i] != NULL; i++) { 271 for (i = 0; x86_clacpatch[i] != NULL; i++) {
257 /* ret,int3,int3 -> clac */ 272 /* ret,int3,int3 -> clac */
258 patchbytes(x86_clacpatch[i], 273 patchbytes(x86_clacpatch[i], clac_bytes,
259 0x0f, 0x01, 0xca); 274 sizeof(clac_bytes));
260 } 275 }
261 for (i = 0; x86_stacpatch[i] != NULL; i++) { 276 for (i = 0; x86_stacpatch[i] != NULL; i++) {
262 /* ret,int3,int3 -> stac */ 277 /* ret,int3,int3 -> stac */
263 patchbytes(x86_stacpatch[i], 278 patchbytes(x86_stacpatch[i], stac_bytes,
264 0x0f, 0x01, 0xcb); 279 sizeof(stac_bytes));
265 } 280 }
266 } 281 }
267#endif 282#endif
268 283
269 /* Write back and invalidate cache, flush pipelines. */ 284 /* Write back and invalidate cache, flush pipelines. */
270 wbinvd(); 285 wbinvd();
271 x86_flush(); 286 x86_flush();
272 x86_write_psl(psl); 287 x86_write_psl(psl);
273 288
274 /* Re-enable write protection. */ 289 /* Re-enable write protection. */
275 lcr0(cr0); 290 lcr0(cr0);
276} 291}