1/* $OpenBSD: codepatch.h,v 1.19 2024/02/12 01:18:17 guenther 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, const 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);
35void 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#define CPTAG_XRSTORS 13
69#define CPTAG_RETPOLINE_RAX 14
70#define CPTAG_RETPOLINE_R11 15
71#define CPTAG_RETPOLINE_R13 16
72#define CPTAG_IBPB_NOP 17
73
74/*
75 * stac/clac SMAP instructions have lfence like semantics. Let's
76 * guarantee those semantics on older cpus.
77 */
78#define SMAP_NOP lfence
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/* Would be neat if these could be in something like .cptext */
105#define CODEPATCH_CODE(symbol, instructions...) \
106 .section .rodata; \
107 .globl symbol; \
108symbol: instructions; \
109 .size symbol, . - symbol
110
111/* provide a (short) variable with the length of the patch */
112#define CODEPATCH_CODE_LEN(symbol, instructions...) \
113 CODEPATCH_CODE(symbol, instructions); \
114996: .globl symbol##_len; \
115 .align 2; \
116symbol##_len: \
117 .short 996b - symbol; \
118 .size symbol##_len, 2
119
120#endif /* _MACHINE_CODEPATCH_H_ */