| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: nvmm.c,v 1.30 2020/05/24 08:08:49 maxv Exp $ */ | | 1 | /* $NetBSD: nvmm.c,v 1.31 2020/06/25 17:01:19 maxv Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2018-2019 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2018-2019 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Maxime Villard. | | 8 | * by Maxime Villard. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -20,41 +20,41 @@ | | | @@ -20,41 +20,41 @@ |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.30 2020/05/24 08:08:49 maxv Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.31 2020/06/25 17:01:19 maxv Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/systm.h> | | 36 | #include <sys/systm.h> |
37 | #include <sys/kernel.h> | | 37 | #include <sys/kernel.h> |
38 | | | 38 | |
39 | #include <sys/cpu.h> | | 39 | #include <sys/cpu.h> |
40 | #include <sys/conf.h> | | 40 | #include <sys/conf.h> |
41 | #include <sys/kmem.h> | | 41 | #include <sys/kmem.h> |
42 | #include <sys/module.h> | | 42 | #include <sys/module.h> |
43 | #include <sys/proc.h> | | 43 | #include <sys/proc.h> |
44 | #include <sys/mman.h> | | 44 | #include <sys/mman.h> |
45 | #include <sys/file.h> | | 45 | #include <sys/file.h> |
46 | #include <sys/filedesc.h> | | 46 | #include <sys/filedesc.h> |
47 | #include <sys/kauth.h> | | 47 | #include <sys/device.h> |
48 | | | 48 | |
49 | #include <uvm/uvm.h> | | 49 | #include <uvm/uvm.h> |
50 | #include <uvm/uvm_page.h> | | 50 | #include <uvm/uvm_page.h> |
51 | | | 51 | |
52 | #include "ioconf.h" | | 52 | #include "ioconf.h" |
53 | | | 53 | |
54 | #include <dev/nvmm/nvmm.h> | | 54 | #include <dev/nvmm/nvmm.h> |
55 | #include <dev/nvmm/nvmm_internal.h> | | 55 | #include <dev/nvmm/nvmm_internal.h> |
56 | #include <dev/nvmm/nvmm_ioctl.h> | | 56 | #include <dev/nvmm/nvmm_ioctl.h> |
57 | | | 57 | |
58 | static struct nvmm_machine machines[NVMM_MAX_MACHINES]; | | 58 | static struct nvmm_machine machines[NVMM_MAX_MACHINES]; |
59 | static volatile unsigned int nmachines __cacheline_aligned; | | 59 | static volatile unsigned int nmachines __cacheline_aligned; |
60 | | | 60 | |
| @@ -950,42 +950,47 @@ nvmm_ctl_mach_info(struct nvmm_owner *ow | | | @@ -950,42 +950,47 @@ nvmm_ctl_mach_info(struct nvmm_owner *ow |
950 | static int | | 950 | static int |
951 | nvmm_ctl(struct nvmm_owner *owner, struct nvmm_ioc_ctl *args) | | 951 | nvmm_ctl(struct nvmm_owner *owner, struct nvmm_ioc_ctl *args) |
952 | { | | 952 | { |
953 | switch (args->op) { | | 953 | switch (args->op) { |
954 | case NVMM_CTL_MACH_INFO: | | 954 | case NVMM_CTL_MACH_INFO: |
955 | return nvmm_ctl_mach_info(owner, args); | | 955 | return nvmm_ctl_mach_info(owner, args); |
956 | default: | | 956 | default: |
957 | return EINVAL; | | 957 | return EINVAL; |
958 | } | | 958 | } |
959 | } | | 959 | } |
960 | | | 960 | |
961 | /* -------------------------------------------------------------------------- */ | | 961 | /* -------------------------------------------------------------------------- */ |
962 | | | 962 | |
| | | 963 | static const struct nvmm_impl * |
| | | 964 | nvmm_ident(void) |
| | | 965 | { |
| | | 966 | size_t i; |
| | | 967 | |
| | | 968 | for (i = 0; i < __arraycount(nvmm_impl_list); i++) { |
| | | 969 | if ((*nvmm_impl_list[i]->ident)()) |
| | | 970 | return nvmm_impl_list[i]; |
| | | 971 | } |
| | | 972 | |
| | | 973 | return NULL; |
| | | 974 | } |
| | | 975 | |
963 | static int | | 976 | static int |
964 | nvmm_init(void) | | 977 | nvmm_init(void) |
965 | { | | 978 | { |
966 | size_t i, n; | | 979 | size_t i, n; |
967 | | | 980 | |
968 | for (i = 0; i < __arraycount(nvmm_impl_list); i++) { | | 981 | nvmm_impl = nvmm_ident(); |
969 | if (!(*nvmm_impl_list[i]->ident)()) { | | 982 | if (nvmm_impl == NULL) |
970 | continue; | | | |
971 | } | | | |
972 | nvmm_impl = nvmm_impl_list[i]; | | | |
973 | break; | | | |
974 | } | | | |
975 | if (nvmm_impl == NULL) { | | | |
976 | printf("NVMM: CPU not supported\n"); | | | |
977 | return ENOTSUP; | | 983 | return ENOTSUP; |
978 | } | | | |
979 | | | 984 | |
980 | for (i = 0; i < NVMM_MAX_MACHINES; i++) { | | 985 | for (i = 0; i < NVMM_MAX_MACHINES; i++) { |
981 | machines[i].machid = i; | | 986 | machines[i].machid = i; |
982 | rw_init(&machines[i].lock); | | 987 | rw_init(&machines[i].lock); |
983 | for (n = 0; n < NVMM_MAX_VCPUS; n++) { | | 988 | for (n = 0; n < NVMM_MAX_VCPUS; n++) { |
984 | machines[i].cpus[n].present = false; | | 989 | machines[i].cpus[n].present = false; |
985 | machines[i].cpus[n].cpuid = n; | | 990 | machines[i].cpus[n].cpuid = n; |
986 | mutex_init(&machines[i].cpus[n].lock, MUTEX_DEFAULT, | | 991 | mutex_init(&machines[i].cpus[n].lock, MUTEX_DEFAULT, |
987 | IPL_NONE); | | 992 | IPL_NONE); |
988 | } | | 993 | } |
989 | } | | 994 | } |
990 | | | 995 | |
991 | (*nvmm_impl->init)(); | | 996 | (*nvmm_impl->init)(); |
| @@ -1159,70 +1164,149 @@ nvmm_ioctl(file_t *fp, u_long cmd, void | | | @@ -1159,70 +1164,149 @@ nvmm_ioctl(file_t *fp, u_long cmd, void |
1159 | case NVMM_IOC_HVA_MAP: | | 1164 | case NVMM_IOC_HVA_MAP: |
1160 | return nvmm_hva_map(owner, data); | | 1165 | return nvmm_hva_map(owner, data); |
1161 | case NVMM_IOC_HVA_UNMAP: | | 1166 | case NVMM_IOC_HVA_UNMAP: |
1162 | return nvmm_hva_unmap(owner, data); | | 1167 | return nvmm_hva_unmap(owner, data); |
1163 | case NVMM_IOC_CTL: | | 1168 | case NVMM_IOC_CTL: |
1164 | return nvmm_ctl(owner, data); | | 1169 | return nvmm_ctl(owner, data); |
1165 | default: | | 1170 | default: |
1166 | return EINVAL; | | 1171 | return EINVAL; |
1167 | } | | 1172 | } |
1168 | } | | 1173 | } |
1169 | | | 1174 | |
1170 | /* -------------------------------------------------------------------------- */ | | 1175 | /* -------------------------------------------------------------------------- */ |
1171 | | | 1176 | |
| | | 1177 | static int nvmm_match(device_t, cfdata_t, void *); |
| | | 1178 | static void nvmm_attach(device_t, device_t, void *); |
| | | 1179 | static int nvmm_detach(device_t, int); |
| | | 1180 | |
| | | 1181 | extern struct cfdriver nvmm_cd; |
| | | 1182 | |
| | | 1183 | CFATTACH_DECL_NEW(nvmm, 0, nvmm_match, nvmm_attach, nvmm_detach, NULL); |
| | | 1184 | |
| | | 1185 | static struct cfdata nvmm_cfdata[] = { |
| | | 1186 | { |
| | | 1187 | .cf_name = "nvmm", |
| | | 1188 | .cf_atname = "nvmm", |
| | | 1189 | .cf_unit = 0, |
| | | 1190 | .cf_fstate = FSTATE_STAR, |
| | | 1191 | .cf_loc = NULL, |
| | | 1192 | .cf_flags = 0, |
| | | 1193 | .cf_pspec = NULL, |
| | | 1194 | }, |
| | | 1195 | { NULL, NULL, 0, FSTATE_NOTFOUND, NULL, 0, NULL } |
| | | 1196 | }; |
| | | 1197 | |
| | | 1198 | static int |
| | | 1199 | nvmm_match(device_t self, cfdata_t cfdata, void *arg) |
| | | 1200 | { |
| | | 1201 | return 1; |
| | | 1202 | } |
| | | 1203 | |
| | | 1204 | static void |
| | | 1205 | nvmm_attach(device_t parent, device_t self, void *aux) |
| | | 1206 | { |
| | | 1207 | int error; |
| | | 1208 | |
| | | 1209 | error = nvmm_init(); |
| | | 1210 | if (error) |
| | | 1211 | panic("%s: impossible", __func__); |
| | | 1212 | aprint_normal_dev(self, "attached\n"); |
| | | 1213 | } |
| | | 1214 | |
| | | 1215 | static int |
| | | 1216 | nvmm_detach(device_t self, int flags) |
| | | 1217 | { |
| | | 1218 | if (nmachines > 0) |
| | | 1219 | return EBUSY; |
| | | 1220 | nvmm_fini(); |
| | | 1221 | return 0; |
| | | 1222 | } |
| | | 1223 | |
1172 | void | | 1224 | void |
1173 | nvmmattach(int nunits) | | 1225 | nvmmattach(int nunits) |
1174 | { | | 1226 | { |
1175 | /* nothing */ | | 1227 | /* nothing */ |
1176 | } | | 1228 | } |
1177 | | | 1229 | |
1178 | MODULE(MODULE_CLASS_MISC, nvmm, NULL); | | 1230 | MODULE(MODULE_CLASS_MISC, nvmm, NULL); |
1179 | | | 1231 | |
| | | 1232 | #if defined(_MODULE) |
| | | 1233 | CFDRIVER_DECL(nvmm, DV_VIRTUAL, NULL); |
| | | 1234 | #endif |
| | | 1235 | |
1180 | static int | | 1236 | static int |
1181 | nvmm_modcmd(modcmd_t cmd, void *arg) | | 1237 | nvmm_modcmd(modcmd_t cmd, void *arg) |
1182 | { | | 1238 | { |
| | | 1239 | #if defined(_MODULE) |
| | | 1240 | devmajor_t bmajor = NODEVMAJOR; |
| | | 1241 | devmajor_t cmajor = 345; |
| | | 1242 | #endif |
1183 | int error; | | 1243 | int error; |
1184 | | | 1244 | |
1185 | switch (cmd) { | | 1245 | switch (cmd) { |
1186 | case MODULE_CMD_INIT: | | 1246 | case MODULE_CMD_INIT: |
1187 | error = nvmm_init(); | | 1247 | if (nvmm_ident() == NULL) { |
| | | 1248 | aprint_error("%s: cpu not supported\n", |
| | | 1249 | nvmm_cd.cd_name); |
| | | 1250 | return ENOTSUP; |
| | | 1251 | } |
| | | 1252 | #if defined(_MODULE) |
| | | 1253 | error = config_cfdriver_attach(&nvmm_cd); |
1188 | if (error) | | 1254 | if (error) |
1189 | return error; | | 1255 | return error; |
| | | 1256 | #endif |
| | | 1257 | error = config_cfattach_attach(nvmm_cd.cd_name, &nvmm_ca); |
| | | 1258 | if (error) { |
| | | 1259 | config_cfdriver_detach(&nvmm_cd); |
| | | 1260 | aprint_error("%s: config_cfattach_attach failed\n", |
| | | 1261 | nvmm_cd.cd_name); |
| | | 1262 | return error; |
| | | 1263 | } |
| | | 1264 | |
| | | 1265 | error = config_cfdata_attach(nvmm_cfdata, 1); |
| | | 1266 | if (error) { |
| | | 1267 | config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca); |
| | | 1268 | config_cfdriver_detach(&nvmm_cd); |
| | | 1269 | aprint_error("%s: unable to register cfdata\n", |
| | | 1270 | nvmm_cd.cd_name); |
| | | 1271 | return error; |
| | | 1272 | } |
| | | 1273 | |
| | | 1274 | if (config_attach_pseudo(nvmm_cfdata) == NULL) { |
| | | 1275 | aprint_error("%s: config_attach_pseudo failed\n", |
| | | 1276 | nvmm_cd.cd_name); |
| | | 1277 | config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca); |
| | | 1278 | config_cfdriver_detach(&nvmm_cd); |
| | | 1279 | return ENXIO; |
| | | 1280 | } |
1190 | | | 1281 | |
1191 | #if defined(_MODULE) | | 1282 | #if defined(_MODULE) |
1192 | { | | 1283 | /* mknod /dev/nvmm c 345 0 */ |
1193 | devmajor_t bmajor = NODEVMAJOR; | | 1284 | error = devsw_attach(nvmm_cd.cd_name, NULL, &bmajor, |
1194 | devmajor_t cmajor = 345; | | 1285 | &nvmm_cdevsw, &cmajor); |
1195 | | | 1286 | if (error) { |
1196 | /* mknod /dev/nvmm c 345 0 */ | | 1287 | aprint_error("%s: unable to register devsw\n", |
1197 | error = devsw_attach("nvmm", NULL, &bmajor, | | 1288 | nvmm_cd.cd_name); |
1198 | &nvmm_cdevsw, &cmajor); | | 1289 | config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca); |
1199 | if (error) { | | 1290 | config_cfdriver_detach(&nvmm_cd); |
1200 | nvmm_fini(); | | 1291 | return error; |
1201 | return error; | | | |
1202 | } | | | |
1203 | } | | 1292 | } |
1204 | #endif | | 1293 | #endif |
1205 | return 0; | | 1294 | return 0; |
1206 | | | | |
1207 | case MODULE_CMD_FINI: | | 1295 | case MODULE_CMD_FINI: |
1208 | if (nmachines > 0) { | | 1296 | error = config_cfdata_detach(nvmm_cfdata); |
1209 | return EBUSY; | | 1297 | if (error) |
1210 | } | | 1298 | return error; |
| | | 1299 | error = config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca); |
| | | 1300 | if (error) |
| | | 1301 | return error; |
1211 | #if defined(_MODULE) | | 1302 | #if defined(_MODULE) |
1212 | { | | 1303 | config_cfdriver_detach(&nvmm_cd); |
1213 | error = devsw_detach(NULL, &nvmm_cdevsw); | | 1304 | devsw_detach(NULL, &nvmm_cdevsw); |
1214 | if (error) { | | | |
1215 | return error; | | | |
1216 | } | | | |
1217 | } | | | |
1218 | #endif | | 1305 | #endif |
1219 | nvmm_fini(); | | | |
1220 | return 0; | | 1306 | return 0; |
1221 | | | | |
1222 | case MODULE_CMD_AUTOUNLOAD: | | 1307 | case MODULE_CMD_AUTOUNLOAD: |
1223 | return EBUSY; | | 1308 | return EBUSY; |
1224 | | | | |
1225 | default: | | 1309 | default: |
1226 | return ENOTTY; | | 1310 | return ENOTTY; |
1227 | } | | 1311 | } |
1228 | } | | 1312 | } |