xref: /openbsd-src/sys/arch/amd64/include/codepatch.h (revision 6cbac32f9ea2203a6cfb69c3648aeb36e7aff937)
1*6cbac32fSguenther /*      $OpenBSD: codepatch.h,v 1.19 2024/02/12 01:18:17 guenther Exp $    */
261d6df42Ssf /*
361d6df42Ssf  * Copyright (c) 2014-2015 Stefan Fritsch <sf@sfritsch.de>
461d6df42Ssf  *
561d6df42Ssf  * Permission to use, copy, modify, and distribute this software for any
661d6df42Ssf  * purpose with or without fee is hereby granted, provided that the above
761d6df42Ssf  * copyright notice and this permission notice appear in all copies.
861d6df42Ssf  *
961d6df42Ssf  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1061d6df42Ssf  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1161d6df42Ssf  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1261d6df42Ssf  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1361d6df42Ssf  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1461d6df42Ssf  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1561d6df42Ssf  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1661d6df42Ssf  */
1761d6df42Ssf 
1861d6df42Ssf #ifndef _MACHINE_CODEPATCH_H_
1961d6df42Ssf #define _MACHINE_CODEPATCH_H_
2061d6df42Ssf 
2161d6df42Ssf #include <machine/param.h>
2261d6df42Ssf 
2361d6df42Ssf #ifndef _LOCORE
2461d6df42Ssf 
255f6ecb19Ssf /* code in this section will be unmapped after boot */
265f6ecb19Ssf #define __cptext __attribute__((section(".cptext")))
275f6ecb19Ssf 
285f6ecb19Ssf __cptext void *codepatch_maprw(vaddr_t *nva, vaddr_t dest);
295f6ecb19Ssf __cptext void codepatch_unmaprw(vaddr_t nva);
305f6ecb19Ssf __cptext void codepatch_fill_nop(void *caddr, uint16_t len);
315f6ecb19Ssf __cptext void codepatch_nop(uint16_t tag);
32183b7dd1Sguenther __cptext void codepatch_replace(uint16_t tag, const void *code, size_t len);
33b8d87cb1Sguenther __cptext void codepatch_call(uint16_t _tag, void *_func);
34b8d87cb1Sguenther __cptext void codepatch_jmp(uint16_t _tag, void *_func);
355f6ecb19Ssf void codepatch_disable(void);
3661d6df42Ssf 
3761d6df42Ssf #endif /* !_LOCORE */
3861d6df42Ssf 
3961d6df42Ssf /*
4061d6df42Ssf  * Mark the start of some code snippet to be patched.
4161d6df42Ssf  */
4261d6df42Ssf #define	CODEPATCH_START	998:
4361d6df42Ssf /*
4461d6df42Ssf  * Mark the end of some code to be patched, and assign the given tag.
4561d6df42Ssf  */
46f95e373fSguenther #define	CODEPATCH_END2(startnum,tag)		 \
4761d6df42Ssf 	999:					 \
4861d6df42Ssf 	.section .codepatch, "a"		;\
49f95e373fSguenther 	.quad startnum##b			;\
50f95e373fSguenther 	.short (999b - startnum##b)		;\
5161d6df42Ssf 	.short tag				;\
522daa5239Ssf 	.int 0					;\
5361d6df42Ssf 	.previous
54f95e373fSguenther #define	CODEPATCH_END(tag)	CODEPATCH_END2(998,tag)
5561d6df42Ssf 
5661d6df42Ssf #define CPTAG_STAC		1
5761d6df42Ssf #define CPTAG_CLAC		2
58984d4744Ssf #define CPTAG_EOI		3
59c9de630fSguenther #define CPTAG_XRSTOR		4
60c9de630fSguenther #define CPTAG_XSAVE		5
611fc8fad1Sguenther #define CPTAG_MELTDOWN_NOP	6
625c3fa5a3Sguenther #define CPTAG_MELTDOWN_ALLTRAPS	7
635c3fa5a3Sguenther #define CPTAG_PCID_SET_REUSE	8
645c3fa5a3Sguenther #define CPTAG_MDS		9
655c3fa5a3Sguenther #define CPTAG_MDS_VMM		10
665c3fa5a3Sguenther #define CPTAG_FENCE_SWAPGS_MIS_TAKEN	11
675c3fa5a3Sguenther #define CPTAG_FENCE_NO_SAFE_SMAP	12
6855fdb5faSguenther #define CPTAG_XRSTORS			13
691538f8cbSguenther #define CPTAG_RETPOLINE_RAX		14
701538f8cbSguenther #define CPTAG_RETPOLINE_R11		15
711538f8cbSguenther #define CPTAG_RETPOLINE_R13		16
72*6cbac32fSguenther #define CPTAG_IBPB_NOP			17
7361d6df42Ssf 
74019cf0fbSguenther /*
7567ca69ecSguenther  * stac/clac SMAP instructions have lfence like semantics.  Let's
7667ca69ecSguenther  * guarantee those semantics on older cpus.
77019cf0fbSguenther  */
7867ca69ecSguenther #define SMAP_NOP	lfence
79019cf0fbSguenther #define SMAP_STAC	CODEPATCH_START			;\
80019cf0fbSguenther 			SMAP_NOP			;\
81019cf0fbSguenther 			CODEPATCH_END(CPTAG_STAC)
82019cf0fbSguenther #define SMAP_CLAC	CODEPATCH_START			;\
83019cf0fbSguenther 			SMAP_NOP			;\
84019cf0fbSguenther 			CODEPATCH_END(CPTAG_CLAC)
85019cf0fbSguenther 
865c3fa5a3Sguenther /* CVE-2019-1125: block speculation after swapgs */
875c3fa5a3Sguenther #define	FENCE_SWAPGS_MIS_TAKEN \
885c3fa5a3Sguenther 	CODEPATCH_START				; \
895c3fa5a3Sguenther 	lfence					; \
905c3fa5a3Sguenther 	CODEPATCH_END(CPTAG_FENCE_SWAPGS_MIS_TAKEN)
915c3fa5a3Sguenther /* block speculation when a correct SMAP impl would have been enough */
925c3fa5a3Sguenther #define	FENCE_NO_SAFE_SMAP \
935c3fa5a3Sguenther 	CODEPATCH_START				; \
945c3fa5a3Sguenther 	lfence					; \
955c3fa5a3Sguenther 	CODEPATCH_END(CPTAG_FENCE_NO_SAFE_SMAP)
965c3fa5a3Sguenther 
97f95e373fSguenther #define	PCID_SET_REUSE_SIZE	12
98f95e373fSguenther #define	PCID_SET_REUSE_NOP					\
99f95e373fSguenther 	997:							;\
100f95e373fSguenther 	.byte	0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00	;\
101f95e373fSguenther 	.byte	0x0f, 0x1f, 0x40, 0x00				;\
102f95e373fSguenther 	CODEPATCH_END2(997, CPTAG_PCID_SET_REUSE)
103f95e373fSguenther 
10440ce500bSguenther /* Would be neat if these could be in something like .cptext */
10540ce500bSguenther #define CODEPATCH_CODE(symbol, instructions...)		\
10640ce500bSguenther 	.section .rodata;				\
10740ce500bSguenther 	.globl	symbol;					\
10840ce500bSguenther symbol:	instructions;					\
10940ce500bSguenther 	.size	symbol, . - symbol
11040ce500bSguenther 
11140ce500bSguenther /* provide a (short) variable with the length of the patch */
11240ce500bSguenther #define CODEPATCH_CODE_LEN(symbol, instructions...)	\
11340ce500bSguenther 	CODEPATCH_CODE(symbol, instructions);		\
11440ce500bSguenther 996:	.globl	symbol##_len;				\
11540ce500bSguenther 	.align	2;					\
11640ce500bSguenther symbol##_len:						\
11740ce500bSguenther 	.short	996b - symbol;				\
11840ce500bSguenther 	.size	symbol##_len, 2
11940ce500bSguenther 
12061d6df42Ssf #endif /* _MACHINE_CODEPATCH_H_ */
121