1 1.20 reinoud /* $NetBSD: h_mem_assist.c,v 1.20 2020/12/27 20:56:14 reinoud Exp $ */ 2 1.7 maxv 3 1.1 maxv /* 4 1.19 maxv * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net 5 1.1 maxv * All rights reserved. 6 1.1 maxv * 7 1.19 maxv * This code is part of the NVMM hypervisor. 8 1.1 maxv * 9 1.1 maxv * Redistribution and use in source and binary forms, with or without 10 1.1 maxv * modification, are permitted provided that the following conditions 11 1.1 maxv * are met: 12 1.1 maxv * 1. Redistributions of source code must retain the above copyright 13 1.1 maxv * notice, this list of conditions and the following disclaimer. 14 1.1 maxv * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 maxv * notice, this list of conditions and the following disclaimer in the 16 1.1 maxv * documentation and/or other materials provided with the distribution. 17 1.1 maxv * 18 1.19 maxv * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.19 maxv * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.19 maxv * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.19 maxv * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.19 maxv * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 1.19 maxv * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 1.19 maxv * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 1.19 maxv * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 1.19 maxv * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 1.19 maxv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 1.19 maxv * SUCH DAMAGE. 29 1.1 maxv */ 30 1.1 maxv 31 1.1 maxv #include <stdio.h> 32 1.1 maxv #include <stdlib.h> 33 1.1 maxv #include <stdint.h> 34 1.1 maxv #include <stdbool.h> 35 1.1 maxv #include <unistd.h> 36 1.1 maxv #include <string.h> 37 1.1 maxv #include <err.h> 38 1.1 maxv #include <errno.h> 39 1.1 maxv #include <sys/types.h> 40 1.1 maxv #include <sys/mman.h> 41 1.1 maxv #include <machine/segments.h> 42 1.1 maxv #include <machine/psl.h> 43 1.1 maxv #include <machine/pte.h> 44 1.1 maxv #include <x86/specialreg.h> 45 1.1 maxv 46 1.1 maxv #include <nvmm.h> 47 1.1 maxv 48 1.1 maxv #define PAGE_SIZE 4096 49 1.1 maxv 50 1.1 maxv static uint8_t mmiobuf[PAGE_SIZE]; 51 1.1 maxv static uint8_t *instbuf; 52 1.1 maxv 53 1.12 maxv /* -------------------------------------------------------------------------- */ 54 1.12 maxv 55 1.12 maxv static void 56 1.12 maxv mem_callback(struct nvmm_mem *mem) 57 1.12 maxv { 58 1.12 maxv size_t off; 59 1.12 maxv 60 1.12 maxv if (mem->gpa < 0x1000 || mem->gpa + mem->size > 0x1000 + PAGE_SIZE) { 61 1.12 maxv printf("Out of page\n"); 62 1.12 maxv exit(-1); 63 1.12 maxv } 64 1.12 maxv 65 1.12 maxv off = mem->gpa - 0x1000; 66 1.12 maxv 67 1.12 maxv printf("-> gpa = %p\n", (void *)mem->gpa); 68 1.12 maxv 69 1.12 maxv if (mem->write) { 70 1.12 maxv memcpy(mmiobuf + off, mem->data, mem->size); 71 1.12 maxv } else { 72 1.12 maxv memcpy(mem->data, mmiobuf + off, mem->size); 73 1.12 maxv } 74 1.12 maxv } 75 1.12 maxv 76 1.12 maxv static int 77 1.12 maxv handle_memory(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) 78 1.12 maxv { 79 1.12 maxv int ret; 80 1.12 maxv 81 1.12 maxv ret = nvmm_assist_mem(mach, vcpu); 82 1.12 maxv if (ret == -1) { 83 1.12 maxv err(errno, "nvmm_assist_mem"); 84 1.12 maxv } 85 1.12 maxv 86 1.12 maxv return 0; 87 1.12 maxv } 88 1.12 maxv 89 1.12 maxv static void 90 1.12 maxv run_machine(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) 91 1.12 maxv { 92 1.15 maxv struct nvmm_vcpu_exit *exit = vcpu->exit; 93 1.12 maxv 94 1.12 maxv while (1) { 95 1.12 maxv if (nvmm_vcpu_run(mach, vcpu) == -1) 96 1.12 maxv err(errno, "nvmm_vcpu_run"); 97 1.12 maxv 98 1.12 maxv switch (exit->reason) { 99 1.15 maxv case NVMM_VCPU_EXIT_NONE: 100 1.12 maxv break; 101 1.12 maxv 102 1.15 maxv case NVMM_VCPU_EXIT_RDMSR: 103 1.12 maxv /* Stop here. */ 104 1.12 maxv return; 105 1.12 maxv 106 1.15 maxv case NVMM_VCPU_EXIT_MEMORY: 107 1.12 maxv handle_memory(mach, vcpu); 108 1.12 maxv break; 109 1.12 maxv 110 1.15 maxv case NVMM_VCPU_EXIT_SHUTDOWN: 111 1.12 maxv printf("Shutting down!\n"); 112 1.12 maxv return; 113 1.12 maxv 114 1.12 maxv default: 115 1.18 maxv printf("Invalid VMEXIT: 0x%lx\n", exit->reason); 116 1.12 maxv return; 117 1.12 maxv } 118 1.12 maxv } 119 1.12 maxv } 120 1.12 maxv 121 1.16 maxv static struct nvmm_assist_callbacks callbacks = { 122 1.12 maxv .io = NULL, 123 1.12 maxv .mem = mem_callback 124 1.12 maxv }; 125 1.12 maxv 126 1.12 maxv /* -------------------------------------------------------------------------- */ 127 1.12 maxv 128 1.12 maxv struct test { 129 1.12 maxv const char *name; 130 1.12 maxv uint8_t *code_begin; 131 1.12 maxv uint8_t *code_end; 132 1.12 maxv uint64_t wanted; 133 1.12 maxv uint64_t off; 134 1.12 maxv }; 135 1.12 maxv 136 1.12 maxv static void 137 1.12 maxv run_test(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu, 138 1.12 maxv const struct test *test) 139 1.12 maxv { 140 1.12 maxv uint64_t *res; 141 1.12 maxv size_t size; 142 1.12 maxv 143 1.12 maxv size = (size_t)test->code_end - (size_t)test->code_begin; 144 1.12 maxv 145 1.12 maxv memset(mmiobuf, 0, PAGE_SIZE); 146 1.12 maxv memcpy(instbuf, test->code_begin, size); 147 1.12 maxv 148 1.12 maxv run_machine(mach, vcpu); 149 1.12 maxv 150 1.12 maxv res = (uint64_t *)(mmiobuf + test->off); 151 1.12 maxv if (*res == test->wanted) { 152 1.12 maxv printf("Test '%s' passed\n", test->name); 153 1.12 maxv } else { 154 1.12 maxv printf("Test '%s' failed, wanted 0x%lx, got 0x%lx\n", test->name, 155 1.12 maxv test->wanted, *res); 156 1.12 maxv } 157 1.12 maxv } 158 1.12 maxv 159 1.12 maxv /* -------------------------------------------------------------------------- */ 160 1.12 maxv 161 1.12 maxv extern uint8_t test1_begin, test1_end; 162 1.12 maxv extern uint8_t test2_begin, test2_end; 163 1.12 maxv extern uint8_t test3_begin, test3_end; 164 1.12 maxv extern uint8_t test4_begin, test4_end; 165 1.12 maxv extern uint8_t test5_begin, test5_end; 166 1.12 maxv extern uint8_t test6_begin, test6_end; 167 1.12 maxv extern uint8_t test7_begin, test7_end; 168 1.12 maxv extern uint8_t test8_begin, test8_end; 169 1.12 maxv extern uint8_t test9_begin, test9_end; 170 1.12 maxv extern uint8_t test10_begin, test10_end; 171 1.12 maxv extern uint8_t test11_begin, test11_end; 172 1.12 maxv extern uint8_t test12_begin, test12_end; 173 1.12 maxv extern uint8_t test13_begin, test13_end; 174 1.12 maxv extern uint8_t test14_begin, test14_end; 175 1.14 maxv extern uint8_t test_64bit_15_begin, test_64bit_15_end; 176 1.14 maxv extern uint8_t test_64bit_16_begin, test_64bit_16_end; 177 1.20 reinoud extern uint8_t test17_begin, test17_end; 178 1.12 maxv 179 1.12 maxv static const struct test tests64[] = { 180 1.18 maxv { "64bit test1 - MOV", &test1_begin, &test1_end, 0x3004, 0 }, 181 1.18 maxv { "64bit test2 - OR", &test2_begin, &test2_end, 0x16FF, 0 }, 182 1.18 maxv { "64bit test3 - AND", &test3_begin, &test3_end, 0x1FC0, 0 }, 183 1.18 maxv { "64bit test4 - XOR", &test4_begin, &test4_end, 0x10CF, 0 }, 184 1.18 maxv { "64bit test5 - Address Sizes", &test5_begin, &test5_end, 0x1F00, 0 }, 185 1.18 maxv { "64bit test6 - DMO", &test6_begin, &test6_end, 0xFFAB, 0 }, 186 1.18 maxv { "64bit test7 - STOS", &test7_begin, &test7_end, 0x00123456, 0 }, 187 1.18 maxv { "64bit test8 - LODS", &test8_begin, &test8_end, 0x12345678, 0 }, 188 1.18 maxv { "64bit test9 - MOVS", &test9_begin, &test9_end, 0x12345678, 0 }, 189 1.18 maxv { "64bit test10 - MOVZXB", &test10_begin, &test10_end, 0x00000078, 0 }, 190 1.18 maxv { "64bit test11 - MOVZXW", &test11_begin, &test11_end, 0x00005678, 0 }, 191 1.18 maxv { "64bit test12 - CMP", &test12_begin, &test12_end, 0x00000001, 0 }, 192 1.18 maxv { "64bit test13 - SUB", &test13_begin, &test13_end, 0x0000000F0000A0FF, 0 }, 193 1.18 maxv { "64bit test14 - TEST", &test14_begin, &test14_end, 0x00000001, 0 }, 194 1.18 maxv { "64bit test15 - XCHG", &test_64bit_15_begin, &test_64bit_15_end, 0x123456, 0 }, 195 1.18 maxv { "64bit test16 - XCHG", &test_64bit_16_begin, &test_64bit_16_end, 196 1.14 maxv 0x123456, 0 }, 197 1.20 reinoud { "64bit test17 - CMPS", &test17_begin, &test17_end, 0x00001, 0 }, 198 1.13 christos { NULL, NULL, NULL, -1, 0 } 199 1.12 maxv }; 200 1.12 maxv 201 1.1 maxv static void 202 1.1 maxv init_seg(struct nvmm_x64_state_seg *seg, int type, int sel) 203 1.1 maxv { 204 1.1 maxv seg->selector = sel; 205 1.1 maxv seg->attrib.type = type; 206 1.6 maxv seg->attrib.s = (type & 0b10000) != 0; 207 1.1 maxv seg->attrib.dpl = 0; 208 1.1 maxv seg->attrib.p = 1; 209 1.1 maxv seg->attrib.avl = 1; 210 1.6 maxv seg->attrib.l = 1; 211 1.6 maxv seg->attrib.def = 0; 212 1.6 maxv seg->attrib.g = 1; 213 1.3 maxv seg->limit = 0x0000FFFF; 214 1.1 maxv seg->base = 0x00000000; 215 1.1 maxv } 216 1.1 maxv 217 1.1 maxv static void 218 1.12 maxv reset_machine64(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) 219 1.1 maxv { 220 1.11 maxv struct nvmm_x64_state *state = vcpu->state; 221 1.1 maxv 222 1.18 maxv if (nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1) 223 1.18 maxv err(errno, "nvmm_vcpu_getstate"); 224 1.18 maxv 225 1.11 maxv memset(state, 0, sizeof(*state)); 226 1.1 maxv 227 1.1 maxv /* Default. */ 228 1.11 maxv state->gprs[NVMM_X64_GPR_RFLAGS] = PSL_MBO; 229 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_CS], SDT_MEMERA, GSEL(GCODE_SEL, SEL_KPL)); 230 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_SS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); 231 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_DS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); 232 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_ES], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); 233 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_FS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); 234 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_GS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); 235 1.1 maxv 236 1.1 maxv /* Blank. */ 237 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_GDT], 0, 0); 238 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_IDT], 0, 0); 239 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_LDT], SDT_SYSLDT, 0); 240 1.11 maxv init_seg(&state->segs[NVMM_X64_SEG_TR], SDT_SYS386BSY, 0); 241 1.1 maxv 242 1.1 maxv /* Protected mode enabled. */ 243 1.11 maxv state->crs[NVMM_X64_CR_CR0] = CR0_PG|CR0_PE|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM; 244 1.1 maxv 245 1.1 maxv /* 64bit mode enabled. */ 246 1.11 maxv state->crs[NVMM_X64_CR_CR4] = CR4_PAE; 247 1.11 maxv state->msrs[NVMM_X64_MSR_EFER] = EFER_LME | EFER_SCE | EFER_LMA; 248 1.1 maxv 249 1.1 maxv /* Stolen from x86/pmap.c */ 250 1.1 maxv #define PATENTRY(n, type) (type << ((n) * 8)) 251 1.1 maxv #define PAT_UC 0x0ULL 252 1.1 maxv #define PAT_WC 0x1ULL 253 1.1 maxv #define PAT_WT 0x4ULL 254 1.1 maxv #define PAT_WP 0x5ULL 255 1.1 maxv #define PAT_WB 0x6ULL 256 1.1 maxv #define PAT_UCMINUS 0x7ULL 257 1.11 maxv state->msrs[NVMM_X64_MSR_PAT] = 258 1.1 maxv PATENTRY(0, PAT_WB) | PATENTRY(1, PAT_WT) | 259 1.1 maxv PATENTRY(2, PAT_UCMINUS) | PATENTRY(3, PAT_UC) | 260 1.1 maxv PATENTRY(4, PAT_WB) | PATENTRY(5, PAT_WT) | 261 1.1 maxv PATENTRY(6, PAT_UCMINUS) | PATENTRY(7, PAT_UC); 262 1.1 maxv 263 1.1 maxv /* Page tables. */ 264 1.11 maxv state->crs[NVMM_X64_CR_CR3] = 0x3000; 265 1.1 maxv 266 1.11 maxv state->gprs[NVMM_X64_GPR_RIP] = 0x2000; 267 1.1 maxv 268 1.11 maxv if (nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1) 269 1.1 maxv err(errno, "nvmm_vcpu_setstate"); 270 1.1 maxv } 271 1.1 maxv 272 1.1 maxv static void 273 1.12 maxv map_pages64(struct nvmm_machine *mach) 274 1.1 maxv { 275 1.1 maxv pt_entry_t *L4, *L3, *L2, *L1; 276 1.9 htodd int ret; 277 1.1 maxv 278 1.1 maxv instbuf = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 279 1.1 maxv -1, 0); 280 1.1 maxv if (instbuf == MAP_FAILED) 281 1.1 maxv err(errno, "mmap"); 282 1.1 maxv 283 1.1 maxv if (nvmm_hva_map(mach, (uintptr_t)instbuf, PAGE_SIZE) == -1) 284 1.1 maxv err(errno, "nvmm_hva_map"); 285 1.8 maxv ret = nvmm_gpa_map(mach, (uintptr_t)instbuf, 0x2000, PAGE_SIZE, 286 1.8 maxv PROT_READ|PROT_EXEC); 287 1.8 maxv if (ret == -1) 288 1.1 maxv err(errno, "nvmm_gpa_map"); 289 1.1 maxv 290 1.1 maxv L4 = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 291 1.1 maxv -1, 0); 292 1.1 maxv if (L4 == MAP_FAILED) 293 1.1 maxv err(errno, "mmap"); 294 1.1 maxv L3 = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 295 1.1 maxv -1, 0); 296 1.1 maxv if (L3 == MAP_FAILED) 297 1.1 maxv err(errno, "mmap"); 298 1.1 maxv L2 = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 299 1.1 maxv -1, 0); 300 1.1 maxv if (L2 == MAP_FAILED) 301 1.1 maxv err(errno, "mmap"); 302 1.1 maxv L1 = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 303 1.1 maxv -1, 0); 304 1.1 maxv if (L1 == MAP_FAILED) 305 1.1 maxv err(errno, "mmap"); 306 1.1 maxv 307 1.1 maxv if (nvmm_hva_map(mach, (uintptr_t)L4, PAGE_SIZE) == -1) 308 1.1 maxv err(errno, "nvmm_hva_map"); 309 1.1 maxv if (nvmm_hva_map(mach, (uintptr_t)L3, PAGE_SIZE) == -1) 310 1.1 maxv err(errno, "nvmm_hva_map"); 311 1.1 maxv if (nvmm_hva_map(mach, (uintptr_t)L2, PAGE_SIZE) == -1) 312 1.1 maxv err(errno, "nvmm_hva_map"); 313 1.1 maxv if (nvmm_hva_map(mach, (uintptr_t)L1, PAGE_SIZE) == -1) 314 1.1 maxv err(errno, "nvmm_hva_map"); 315 1.1 maxv 316 1.8 maxv ret = nvmm_gpa_map(mach, (uintptr_t)L4, 0x3000, PAGE_SIZE, 317 1.8 maxv PROT_READ|PROT_WRITE); 318 1.8 maxv if (ret == -1) 319 1.1 maxv err(errno, "nvmm_gpa_map"); 320 1.8 maxv ret = nvmm_gpa_map(mach, (uintptr_t)L3, 0x4000, PAGE_SIZE, 321 1.8 maxv PROT_READ|PROT_WRITE); 322 1.8 maxv if (ret == -1) 323 1.1 maxv err(errno, "nvmm_gpa_map"); 324 1.8 maxv ret = nvmm_gpa_map(mach, (uintptr_t)L2, 0x5000, PAGE_SIZE, 325 1.8 maxv PROT_READ|PROT_WRITE); 326 1.8 maxv if (ret == -1) 327 1.1 maxv err(errno, "nvmm_gpa_map"); 328 1.8 maxv ret = nvmm_gpa_map(mach, (uintptr_t)L1, 0x6000, PAGE_SIZE, 329 1.8 maxv PROT_READ|PROT_WRITE); 330 1.8 maxv if (ret == -1) 331 1.1 maxv err(errno, "nvmm_gpa_map"); 332 1.1 maxv 333 1.1 maxv memset(L4, 0, PAGE_SIZE); 334 1.1 maxv memset(L3, 0, PAGE_SIZE); 335 1.1 maxv memset(L2, 0, PAGE_SIZE); 336 1.1 maxv memset(L1, 0, PAGE_SIZE); 337 1.1 maxv 338 1.7 maxv L4[0] = PTE_P | PTE_W | 0x4000; 339 1.7 maxv L3[0] = PTE_P | PTE_W | 0x5000; 340 1.7 maxv L2[0] = PTE_P | PTE_W | 0x6000; 341 1.7 maxv L1[0x2000 / PAGE_SIZE] = PTE_P | PTE_W | 0x2000; 342 1.7 maxv L1[0x1000 / PAGE_SIZE] = PTE_P | PTE_W | 0x1000; 343 1.1 maxv } 344 1.1 maxv 345 1.12 maxv /* 346 1.12 maxv * 0x1000: MMIO address, unmapped 347 1.12 maxv * 0x2000: Instructions, mapped 348 1.12 maxv * 0x3000: L4 349 1.12 maxv * 0x4000: L3 350 1.12 maxv * 0x5000: L2 351 1.12 maxv * 0x6000: L1 352 1.12 maxv */ 353 1.1 maxv static void 354 1.12 maxv test_vm64(void) 355 1.1 maxv { 356 1.12 maxv struct nvmm_machine mach; 357 1.12 maxv struct nvmm_vcpu vcpu; 358 1.12 maxv size_t i; 359 1.12 maxv 360 1.12 maxv if (nvmm_machine_create(&mach) == -1) 361 1.12 maxv err(errno, "nvmm_machine_create"); 362 1.12 maxv if (nvmm_vcpu_create(&mach, 0, &vcpu) == -1) 363 1.12 maxv err(errno, "nvmm_vcpu_create"); 364 1.16 maxv nvmm_vcpu_configure(&mach, &vcpu, NVMM_VCPU_CONF_CALLBACKS, &callbacks); 365 1.12 maxv map_pages64(&mach); 366 1.1 maxv 367 1.12 maxv for (i = 0; tests64[i].name != NULL; i++) { 368 1.12 maxv reset_machine64(&mach, &vcpu); 369 1.12 maxv run_test(&mach, &vcpu, &tests64[i]); 370 1.1 maxv } 371 1.1 maxv 372 1.18 maxv if (nvmm_vcpu_destroy(&mach, &vcpu) == -1) 373 1.18 maxv err(errno, "nvmm_vcpu_destroy"); 374 1.12 maxv if (nvmm_machine_destroy(&mach) == -1) 375 1.12 maxv err(errno, "nvmm_machine_destroy"); 376 1.1 maxv } 377 1.2 maxv 378 1.12 maxv /* -------------------------------------------------------------------------- */ 379 1.1 maxv 380 1.12 maxv extern uint8_t test_16bit_1_begin, test_16bit_1_end; 381 1.12 maxv extern uint8_t test_16bit_2_begin, test_16bit_2_end; 382 1.12 maxv extern uint8_t test_16bit_3_begin, test_16bit_3_end; 383 1.12 maxv extern uint8_t test_16bit_4_begin, test_16bit_4_end; 384 1.12 maxv extern uint8_t test_16bit_5_begin, test_16bit_5_end; 385 1.14 maxv extern uint8_t test_16bit_6_begin, test_16bit_6_end; 386 1.12 maxv 387 1.12 maxv static const struct test tests16[] = { 388 1.12 maxv { "16bit test1 - MOV single", &test_16bit_1_begin, &test_16bit_1_end, 389 1.12 maxv 0x023, 0x10f1 - 0x1000 }, 390 1.12 maxv { "16bit test2 - MOV dual", &test_16bit_2_begin, &test_16bit_2_end, 391 1.12 maxv 0x123, 0x10f3 - 0x1000 }, 392 1.12 maxv { "16bit test3 - MOV dual+disp", &test_16bit_3_begin, &test_16bit_3_end, 393 1.12 maxv 0x678, 0x10f1 - 0x1000 }, 394 1.12 maxv { "16bit test4 - Mixed", &test_16bit_4_begin, &test_16bit_4_end, 395 1.12 maxv 0x1011, 0x10f6 - 0x1000 }, 396 1.12 maxv { "16bit test5 - disp16-only", &test_16bit_5_begin, &test_16bit_5_end, 397 1.12 maxv 0x12, 0x1234 - 0x1000 }, 398 1.14 maxv { "16bit test6 - XCHG", &test_16bit_6_begin, &test_16bit_6_end, 399 1.14 maxv 0x1234, 0x1234 - 0x1000 }, 400 1.12 maxv { NULL, NULL, NULL, -1, -1 } 401 1.12 maxv }; 402 1.1 maxv 403 1.1 maxv static void 404 1.12 maxv reset_machine16(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) 405 1.1 maxv { 406 1.12 maxv struct nvmm_x64_state *state = vcpu->state; 407 1.1 maxv 408 1.12 maxv if (nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1) 409 1.18 maxv err(errno, "nvmm_vcpu_getstate"); 410 1.1 maxv 411 1.12 maxv state->segs[NVMM_X64_SEG_CS].base = 0; 412 1.18 maxv state->segs[NVMM_X64_SEG_CS].limit = 0x2FFF; 413 1.12 maxv state->gprs[NVMM_X64_GPR_RIP] = 0x2000; 414 1.1 maxv 415 1.12 maxv if (nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1) 416 1.12 maxv err(errno, "nvmm_vcpu_setstate"); 417 1.1 maxv } 418 1.1 maxv 419 1.1 maxv static void 420 1.12 maxv map_pages16(struct nvmm_machine *mach) 421 1.1 maxv { 422 1.12 maxv int ret; 423 1.1 maxv 424 1.12 maxv instbuf = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 425 1.12 maxv -1, 0); 426 1.12 maxv if (instbuf == MAP_FAILED) 427 1.12 maxv err(errno, "mmap"); 428 1.1 maxv 429 1.12 maxv if (nvmm_hva_map(mach, (uintptr_t)instbuf, PAGE_SIZE) == -1) 430 1.12 maxv err(errno, "nvmm_hva_map"); 431 1.12 maxv ret = nvmm_gpa_map(mach, (uintptr_t)instbuf, 0x2000, PAGE_SIZE, 432 1.12 maxv PROT_READ|PROT_EXEC); 433 1.12 maxv if (ret == -1) 434 1.12 maxv err(errno, "nvmm_gpa_map"); 435 1.1 maxv } 436 1.1 maxv 437 1.1 maxv /* 438 1.1 maxv * 0x1000: MMIO address, unmapped 439 1.1 maxv * 0x2000: Instructions, mapped 440 1.1 maxv */ 441 1.12 maxv static void 442 1.12 maxv test_vm16(void) 443 1.1 maxv { 444 1.1 maxv struct nvmm_machine mach; 445 1.11 maxv struct nvmm_vcpu vcpu; 446 1.1 maxv size_t i; 447 1.1 maxv 448 1.1 maxv if (nvmm_machine_create(&mach) == -1) 449 1.1 maxv err(errno, "nvmm_machine_create"); 450 1.11 maxv if (nvmm_vcpu_create(&mach, 0, &vcpu) == -1) 451 1.1 maxv err(errno, "nvmm_vcpu_create"); 452 1.16 maxv nvmm_vcpu_configure(&mach, &vcpu, NVMM_VCPU_CONF_CALLBACKS, &callbacks); 453 1.12 maxv map_pages16(&mach); 454 1.1 maxv 455 1.12 maxv for (i = 0; tests16[i].name != NULL; i++) { 456 1.12 maxv reset_machine16(&mach, &vcpu); 457 1.12 maxv run_test(&mach, &vcpu, &tests16[i]); 458 1.1 maxv } 459 1.1 maxv 460 1.18 maxv if (nvmm_vcpu_destroy(&mach, &vcpu) == -1) 461 1.18 maxv err(errno, "nvmm_vcpu_destroy"); 462 1.12 maxv if (nvmm_machine_destroy(&mach) == -1) 463 1.12 maxv err(errno, "nvmm_machine_destroy"); 464 1.12 maxv } 465 1.12 maxv 466 1.12 maxv /* -------------------------------------------------------------------------- */ 467 1.12 maxv 468 1.12 maxv int main(int argc, char *argv[]) 469 1.12 maxv { 470 1.17 maxv if (nvmm_init() == -1) 471 1.17 maxv err(errno, "nvmm_init"); 472 1.12 maxv test_vm64(); 473 1.12 maxv test_vm16(); 474 1.1 maxv return 0; 475 1.1 maxv } 476