aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/amd64/copyout.c
blob: 36e817635694819a09fd5fdb792def574f2b06b4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*-
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
 *
 * Copyright (c) 2018 The FreeBSD Foundation
 * All rights reserved.
 *
 * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
 * under sponsorship from the FreeBSD Foundation.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#ifdef SAN_NEEDS_INTERCEPTORS
#define	SAN_RUNTIME
#endif

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/md_var.h>
#include <machine/specialreg.h>
#include <x86/ifunc.h>

int fubyte_nosmap(volatile const void *base);
int fubyte_smap(volatile const void *base);
DEFINE_IFUNC(, int, fubyte, (volatile const void *))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    fubyte_smap : fubyte_nosmap);
}

int fuword16_nosmap(volatile const void *base);
int fuword16_smap(volatile const void *base);
DEFINE_IFUNC(, int, fuword16, (volatile const void *))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    fuword16_smap : fuword16_nosmap);
}

int fueword_nosmap(volatile const void *base, long *val);
int fueword_smap(volatile const void *base, long *val);
DEFINE_IFUNC(, int, fueword, (volatile const void *, long *))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    fueword_smap : fueword_nosmap);
}
DEFINE_IFUNC(, int, fueword64, (volatile const void *, int64_t *))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    fueword_smap : fueword_nosmap);
}

int	fueword32_nosmap(volatile const void *base, int32_t *val);
int	fueword32_smap(volatile const void *base, int32_t *val);
DEFINE_IFUNC(, int, fueword32, (volatile const void *, int32_t *))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    fueword32_smap : fueword32_nosmap);
}

int	subyte_nosmap(volatile void *base, int byte);
int	subyte_smap(volatile void *base, int byte);
DEFINE_IFUNC(, int, subyte, (volatile void *, int))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    subyte_smap : subyte_nosmap);
}

int	suword16_nosmap(volatile void *base, int word);
int	suword16_smap(volatile void *base, int word);
DEFINE_IFUNC(, int, suword16, (volatile void *, int))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    suword16_smap : suword16_nosmap);
}

int	suword32_nosmap(volatile void *base, int32_t word);
int	suword32_smap(volatile void *base, int32_t word);
DEFINE_IFUNC(, int, suword32, (volatile void *, int32_t))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    suword32_smap : suword32_nosmap);
}

int	suword_nosmap(volatile void *base, long word);
int	suword_smap(volatile void *base, long word);
DEFINE_IFUNC(, int, suword, (volatile void *, long))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    suword_smap : suword_nosmap);
}
DEFINE_IFUNC(, int, suword64, (volatile void *, int64_t))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    suword_smap : suword_nosmap);
}

int	casueword32_nosmap(volatile uint32_t *base, uint32_t oldval,
	    uint32_t *oldvalp, uint32_t newval);
int	casueword32_smap(volatile uint32_t *base, uint32_t oldval,
	    uint32_t *oldvalp, uint32_t newval);
DEFINE_IFUNC(, int, casueword32, (volatile uint32_t *, uint32_t, uint32_t *,
    uint32_t))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    casueword32_smap : casueword32_nosmap);
}

int	casueword_nosmap(volatile u_long *p, u_long oldval, u_long *oldvalp,
	    u_long newval);
int	casueword_smap(volatile u_long *p, u_long oldval, u_long *oldvalp,
	    u_long newval);
DEFINE_IFUNC(, int, casueword, (volatile u_long *, u_long, u_long *, u_long))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    casueword_smap : casueword_nosmap);
}

int	copyinstr_nosmap(const void *udaddr, void *kaddr, size_t len,
	    size_t *lencopied);
int	copyinstr_smap(const void *udaddr, void *kaddr, size_t len,
	    size_t *lencopied);
DEFINE_IFUNC(, int, copyinstr, (const void *, void *, size_t, size_t *))
{

	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
	    copyinstr_smap : copyinstr_nosmap);
}

int	copyin_nosmap_std(const void *udaddr, void *kaddr, size_t len);
int	copyin_smap_std(const void *udaddr, void *kaddr, size_t len);
int	copyin_nosmap_erms(const void *udaddr, void *kaddr, size_t len);
int	copyin_smap_erms(const void *udaddr, void *kaddr, size_t len);
DEFINE_IFUNC(, int, copyin, (const void *, void *, size_t))
{

	switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) {
	case CPUID_STDEXT_SMAP:
		return (copyin_smap_std);
	case CPUID_STDEXT_ERMS:
		return (copyin_nosmap_erms);
	case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS:
		return (copyin_smap_erms);
	default:
		return (copyin_nosmap_std);
	}
}

int	copyout_nosmap_std(const void *kaddr, void *udaddr, size_t len);
int	copyout_smap_std(const void *kaddr, void *udaddr, size_t len);
int	copyout_nosmap_erms(const void *kaddr, void *udaddr, size_t len);
int	copyout_smap_erms(const void *kaddr, void *udaddr, size_t len);
DEFINE_IFUNC(, int, copyout, (const void *, void *, size_t))
{

	switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) {
	case CPUID_STDEXT_SMAP:
		return (copyout_smap_std);
	case CPUID_STDEXT_ERMS:
		return (copyout_nosmap_erms);
	case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS:
		return (copyout_smap_erms);
	default:
		return (copyout_nosmap_std);
	}
}