Annotation of src/sys/arch/x86/x86/patch.c, Revision 1.3.12.1
1.3.12.1! yamt 1: /* $NetBSD: patch.c,v 1.3 2007/05/17 14:51:35 yamt Exp $ */
1.2 ad 2:
3: /*-
4: * Copyright (c) 2007 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Andrew Doran.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: /*
40: * Patch kernel code at boot time, depending on available CPU features.
41: */
42:
43: #include <sys/cdefs.h>
1.3.12.1! yamt 44: __KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.3 2007/05/17 14:51:35 yamt Exp $");
1.2 ad 45:
46: #include "opt_multiprocessor.h"
47: #include "opt_lockdebug.h"
48: #ifdef i386
49: #include "opt_cputype.h"
50: #endif
51:
52: #include <sys/types.h>
53: #include <sys/systm.h>
54:
55: #include <machine/cpu.h>
56: #include <machine/cpufunc.h>
57: #include <machine/specialreg.h>
58:
59: #include <x86/cpuvar.h>
60: #include <x86/cputypes.h>
61:
62: void spllower(int);
63: void spllower_end(void);
64: void i686_spllower(int);
65: void i686_spllower_end(void);
66: void i686_spllower_patch(void);
67: void amd64_spllower(int);
68: void amd64_spllower_end(void);
69: void amd64_spllower_patch(void);
70:
71: void mutex_spin_exit_end(void);
72: void i686_mutex_spin_exit(int);
73: void i686_mutex_spin_exit_end(void);
74: void i686_mutex_spin_exit_patch(void);
75:
76: void mb_read(void);
77: void mb_read_end(void);
78: void mb_write(void);
79: void mb_write_end(void);
80: void mb_memory(void);
81: void mb_memory_end(void);
82: void x86_mb_nop(void);
83: void x86_mb_nop_end(void);
84: void sse2_mb_read(void);
85: void sse2_mb_read_end(void);
86: void sse2_mb_memory(void);
87: void sse2_mb_memory_end(void);
88:
89: #define X86_NOP 0x90
90: #define X86_REP 0xf3
91: #define X86_RET 0xc3
92: #define X86_CS 0x2e
93: #define X86_DS 0x3e
94: #define X86_GROUP_0F 0x0f
95:
96: static void __attribute__ ((__unused__))
97: patchfunc(void *from_s, void *from_e, void *to_s, void *to_e,
98: void *pcrel)
99: {
100: uint8_t *ptr;
101: u_long psl;
102:
103: if ((uintptr_t)from_e - (uintptr_t)from_s !=
104: (uintptr_t)to_e - (uintptr_t)to_s)
105: panic("patchfunc: sizes do not match (from=%p)", from_s);
106:
1.3.12.1! yamt 107: psl = x86_read_psl();
! 108: x86_disable_intr();
1.2 ad 109: memcpy(to_s, from_s, (uintptr_t)to_e - (uintptr_t)to_s);
110: if (pcrel != NULL) {
111: ptr = pcrel;
112: /* Branch hints */
113: if (ptr[0] == X86_CS || ptr[0] == X86_DS)
114: ptr++;
115: /* Conditional jumps */
116: if (ptr[0] == X86_GROUP_0F)
117: ptr++;
118: /* 4-byte relative jump or call */
119: *(uint32_t *)(ptr + 1 - (uintptr_t)from_s + (uintptr_t)to_s) +=
120: ((uint32_t)(uintptr_t)from_s - (uint32_t)(uintptr_t)to_s);
121: }
122: x86_flush();
1.3.12.1! yamt 123: x86_write_psl(psl);
1.2 ad 124: }
125:
126: static inline void __attribute__ ((__unused__))
127: patchbytes(void *addr, const int byte1, const int byte2)
128: {
129: ((uint8_t *)addr)[0] = (uint8_t)byte1;
130: if (byte2 != -1)
131: ((uint8_t *)addr)[1] = (uint8_t)byte2;
132: }
133:
134: void
135: x86_patch(void)
136: {
137: #if !defined(GPROF)
138: static int again;
139: u_long cr0;
140:
141: if (again)
142: return;
143: again = 1;
144:
145: /* Disable write protection in supervisor mode. */
146: cr0 = rcr0();
147: lcr0(cr0 & ~CR0_WP);
148:
149: /*
150: * i686 patches.
151: */
152: #ifdef I686_CPU
153: if (cpu_class == CPUCLASS_686 && (cpu_feature & CPUID_CX8) != 0) {
154: patchfunc(
155: i686_spllower, i686_spllower_end,
156: spllower, spllower_end,
157: i686_spllower_patch
158: );
159: #if !defined(LOCKDEBUG) && !defined(I386_CPU) && !defined(DIAGNOSTIC)
160: patchfunc(
161: i686_mutex_spin_exit, i686_mutex_spin_exit_end,
162: mutex_spin_exit, mutex_spin_exit_end,
163: i686_mutex_spin_exit_patch
164: );
165: #endif /* !defined(LOCKDEBUG) && !defined(I386_CPU) */
166: }
167: if ((cpu_feature & CPUID_SSE2) != 0) {
168: patchfunc(
169: sse2_mb_read, sse2_mb_read_end,
170: mb_read, mb_read_end,
171: NULL
172: );
173: patchfunc(
174: sse2_mb_memory, sse2_mb_memory_end,
175: mb_memory, mb_memory_end,
176: NULL
177: );
178: }
179: #endif /* I686_CPU */
180:
181: /*
182: * AMD64 patches.
183: */
184: #ifdef __x86_64__
185: patchfunc(
186: amd64_spllower, amd64_spllower_end,
187: spllower, spllower_end,
188: amd64_spllower_patch
189: );
190: #endif /* __x86_64__ */
191:
192: /*
193: * Uniprocessor. XXX Should be determined at runtime.
194: */
195: #if !defined(MULTIPROCESSOR)
196: patchfunc(
197: x86_mb_nop, x86_mb_nop_end,
198: mb_read, mb_read_end,
199: NULL
200: );
201: patchfunc(
202: x86_mb_nop, x86_mb_nop_end,
203: mb_write, mb_write_end,
204: NULL
205: );
206: patchfunc(
207: x86_mb_nop, x86_mb_nop_end,
208: mb_memory, mb_memory_end,
209: NULL
210: );
211: #endif /* !MULTIPROCESSOR */
212:
213: /* Re-enable write protection. */
214: lcr0(cr0);
215: #endif /* GPROF */
216: }
CVSweb <webmaster@jp.NetBSD.org>