xref: /openbsd-src/sys/arch/amd64/include/codepatch.h (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*      $OpenBSD: codepatch.h,v 1.13 2020/02/28 05:22:53 deraadt Exp $    */
2 /*
3  * Copyright (c) 2014-2015 Stefan Fritsch <sf@sfritsch.de>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #ifndef _MACHINE_CODEPATCH_H_
19 #define _MACHINE_CODEPATCH_H_
20 
21 #include <machine/param.h>
22 
23 #ifndef _LOCORE
24 
25 /* code in this section will be unmapped after boot */
26 #define __cptext __attribute__((section(".cptext")))
27 
28 __cptext void *codepatch_maprw(vaddr_t *nva, vaddr_t dest);
29 __cptext void codepatch_unmaprw(vaddr_t nva);
30 __cptext void codepatch_fill_nop(void *caddr, uint16_t len);
31 __cptext void codepatch_nop(uint16_t tag);
32 __cptext void codepatch_replace(uint16_t tag, void *code, size_t len);
33 __cptext void codepatch_call(uint16_t _tag, void *_func);
34 __cptext void codepatch_jmp(uint16_t _tag, void *_func);
35 void codepatch_disable(void);
36 
37 #endif /* !_LOCORE */
38 
39 /*
40  * Mark the start of some code snippet to be patched.
41  */
42 #define	CODEPATCH_START	998:
43 /*
44  * Mark the end of some code to be patched, and assign the given tag.
45  */
46 #define	CODEPATCH_END2(startnum,tag)		 \
47 	999:					 \
48 	.section .codepatch, "a"		;\
49 	.quad startnum##b			;\
50 	.short (999b - startnum##b)		;\
51 	.short tag				;\
52 	.int 0					;\
53 	.previous
54 #define	CODEPATCH_END(tag)	CODEPATCH_END2(998,tag)
55 
56 #define CPTAG_STAC		1
57 #define CPTAG_CLAC		2
58 #define CPTAG_EOI		3
59 #define CPTAG_XRSTOR		4
60 #define CPTAG_XSAVE		5
61 #define CPTAG_MELTDOWN_NOP	6
62 #define CPTAG_MELTDOWN_ALLTRAPS	7
63 #define CPTAG_PCID_SET_REUSE	8
64 #define CPTAG_MDS		9
65 #define CPTAG_MDS_VMM		10
66 #define CPTAG_FENCE_SWAPGS_MIS_TAKEN	11
67 #define CPTAG_FENCE_NO_SAFE_SMAP	12
68 
69 /*
70  * As stac/clac SMAP instructions are 3 bytes, we want the fastest
71  * 3 byte nop sequence possible here.  This will be replaced by
72  * stac/clac instructions if SMAP is detected after booting.
73  *
74  * This would be 'nop (%rax)' if binutils could cope.
75  * Intel documents multi-byte NOP sequences as being available
76  * on all family 0x6 and 0xf processors (ie 686+)
77  */
78 #define SMAP_NOP	.byte 0x0f, 0x1f, 0x00
79 #define SMAP_STAC	CODEPATCH_START			;\
80 			SMAP_NOP			;\
81 			CODEPATCH_END(CPTAG_STAC)
82 #define SMAP_CLAC	CODEPATCH_START			;\
83 			SMAP_NOP			;\
84 			CODEPATCH_END(CPTAG_CLAC)
85 
86 /* CVE-2019-1125: block speculation after swapgs */
87 #define	FENCE_SWAPGS_MIS_TAKEN \
88 	CODEPATCH_START				; \
89 	lfence					; \
90 	CODEPATCH_END(CPTAG_FENCE_SWAPGS_MIS_TAKEN)
91 /* block speculation when a correct SMAP impl would have been enough */
92 #define	FENCE_NO_SAFE_SMAP \
93 	CODEPATCH_START				; \
94 	lfence					; \
95 	CODEPATCH_END(CPTAG_FENCE_NO_SAFE_SMAP)
96 
97 #define	PCID_SET_REUSE_SIZE	12
98 #define	PCID_SET_REUSE_NOP					\
99 	997:							;\
100 	.byte	0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00	;\
101 	.byte	0x0f, 0x1f, 0x40, 0x00				;\
102 	CODEPATCH_END2(997, CPTAG_PCID_SET_REUSE)
103 
104 #endif /* _MACHINE_CODEPATCH_H_ */
105