1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2022 Oxide Computer Company 14 */ 15 16 17 #include <stdio.h> 18 #include <unistd.h> 19 #include <stropts.h> 20 #include <strings.h> 21 #include <signal.h> 22 #include <setjmp.h> 23 #include <libgen.h> 24 25 #include <sys/vmm.h> 26 #include <sys/vmm_dev.h> 27 #include <sys/mman.h> 28 #include <vmmapi.h> 29 30 #include "common.h" 31 32 enum test_segs { 33 SEG_LOWMEM = 0, 34 SEG_BOOTROM = 1, 35 }; 36 #define PAGE_CNT 2 37 #define PAGE_SZ 4096 38 #define SEG_SZ (PAGE_CNT * PAGE_SZ) 39 #define WHOLE_SZ (SEG_SZ * 2) 40 41 #define TESTVAL_LOWMEM 0x1000ffff 42 #define TESTVAL_BOOTROM 0x2000eeee 43 44 int 45 main(int argc, char *argv[]) 46 { 47 struct vmctx *ctx; 48 int res, fd; 49 const char *suite_name = basename(argv[0]); 50 51 ctx = create_test_vm(suite_name); 52 if (ctx == NULL) { 53 perror("could open test VM"); 54 return (1); 55 } 56 fd = vm_get_device_fd(ctx); 57 58 res = alloc_memseg(ctx, SEG_LOWMEM, SEG_SZ, ""); 59 if (res != 0) { 60 perror("could not alloc lowmem seg"); 61 goto bail; 62 } 63 res = alloc_memseg(ctx, SEG_BOOTROM, SEG_SZ, "bootrom"); 64 if (res != 0) { 65 perror("could not alloc bootrom seg"); 66 goto bail; 67 } 68 69 res = vm_mmap_memseg(ctx, 0, SEG_LOWMEM, 0, SEG_SZ, PROT_ALL); 70 if (res != 0) { 71 perror("could not map lowmem into vmspace"); 72 goto bail; 73 } 74 res = vm_mmap_memseg(ctx, SEG_SZ, SEG_BOOTROM, 0, SEG_SZ, PROT_READ); 75 if (res != 0) { 76 perror("could not map bootrom into vmspace"); 77 goto bail; 78 } 79 80 void *guest_mem; 81 guest_mem = mmap(NULL, WHOLE_SZ, PROT_READ, MAP_SHARED, fd, 0); 82 if (guest_mem == MAP_FAILED) { 83 perror("could not mmap guest-physical memory"); 84 goto bail; 85 } 86 87 void *direct_lowmem, *direct_bootrom; 88 off_t seg_obj_off; 89 90 res = vm_get_devmem_offset(ctx, SEG_LOWMEM, &seg_obj_off); 91 if (res != 0) { 92 perror("could not find mapping offset for lowmem seg"); 93 goto bail; 94 } 95 direct_lowmem = mmap(NULL, SEG_SZ, PROT_READ | PROT_WRITE, MAP_SHARED, 96 fd, seg_obj_off); 97 if (direct_lowmem == MAP_FAILED) { 98 perror("could not mmap lowmem directly"); 99 goto bail; 100 } 101 102 res = vm_get_devmem_offset(ctx, SEG_BOOTROM, &seg_obj_off); 103 if (res != 0) { 104 perror("could not find mapping offset for lowmem seg"); 105 goto bail; 106 } 107 direct_bootrom = mmap(NULL, SEG_SZ, PROT_READ | PROT_WRITE, MAP_SHARED, 108 fd, seg_obj_off); 109 if (direct_bootrom == MAP_FAILED) { 110 perror("could not mmap bootrom directly"); 111 goto bail; 112 } 113 114 uint32_t *datap; 115 116 datap = direct_lowmem; 117 *datap = TESTVAL_LOWMEM; 118 datap = direct_bootrom; 119 *datap = TESTVAL_BOOTROM; 120 121 /* check that data written though direct access is as expected */ 122 datap = guest_mem; 123 if (*datap != TESTVAL_LOWMEM) { 124 (void) fprintf(stderr, "unexpected data in lowmem %x != %x\n", 125 *datap, TESTVAL_LOWMEM); 126 goto bail; 127 } 128 datap = (guest_mem + SEG_SZ); 129 if (*datap != TESTVAL_BOOTROM) { 130 (void) fprintf(stderr, "unexpected data in bootrom %x != %x\n", 131 *datap, TESTVAL_BOOTROM); 132 goto bail; 133 } 134 135 /* unmap access mappings */ 136 res = munmap(guest_mem, WHOLE_SZ); 137 if (res != 0) { 138 perror("could not munmap vmspace"); 139 goto bail; 140 } 141 res = munmap(direct_lowmem, SEG_SZ); 142 if (res != 0) { 143 perror("could not munmap lowmem object"); 144 goto bail; 145 } 146 res = munmap(direct_bootrom, SEG_SZ); 147 if (res != 0) { 148 perror("could not munmap bootrom object"); 149 goto bail; 150 } 151 152 /* mission accomplished */ 153 vm_destroy(ctx); 154 (void) printf("%s\tPASS\n", suite_name); 155 return (0); 156 157 bail: 158 vm_destroy(ctx); 159 return (1); 160 } 161