1 // SPDX-License-Identifier: GPL-2.0
3 * A sample program to run a User VM on the ACRN hypervisor
5 * This sample runs in a Service VM, which is a privileged VM of ACRN.
6 * CONFIG_ACRN_HSM needs to be enabled in the Service VM.
8 * Guest VM code in guest16.s will be executed after the VM launched.
10 * Copyright (C) 2020 Intel Corporation. All rights reserved.
19 #include <sys/ioctl.h>
20 #include <linux/acrn.h>
22 #define GUEST_MEMORY_SIZE (1024*1024)
25 extern const unsigned char guest16
[], guest16_end
[];
26 static char io_request_page
[4096] __attribute__((aligned(4096)));
27 static struct acrn_io_request
*io_req_buf
= (struct acrn_io_request
*)io_request_page
;
40 ioctl(hsm_fd
, ACRN_IOCTL_PAUSE_VM
, vmid
);
41 ioctl(hsm_fd
, ACRN_IOCTL_DESTROY_IOREQ_CLIENT
, 0);
44 int main(int argc
, char **argv
)
47 struct acrn_vm_creation create_vm
= {0};
48 struct acrn_vm_memmap ram_map
= {0};
49 struct acrn_vcpu_regs regs
;
50 struct acrn_io_request
*io_req
;
51 struct acrn_ioreq_notify
__attribute__((aligned(8))) notify
;
56 ret
= posix_memalign(&guest_memory
, 4096, GUEST_MEMORY_SIZE
);
58 printf("Not enough memory!\n");
61 hsm_fd
= open("/dev/acrn_hsm", O_RDWR
|O_CLOEXEC
);
63 create_vm
.ioreq_buf
= (__u64
)io_req_buf
;
64 ret
= ioctl(hsm_fd
, ACRN_IOCTL_CREATE_VM
, &create_vm
);
65 printf("Created VM! [%d]\n", ret
);
66 vcpu_num
= create_vm
.vcpu_num
;
67 vmid
= create_vm
.vmid
;
69 /* setup guest memory */
70 ram_map
.type
= ACRN_MEMMAP_RAM
;
71 ram_map
.vma_base
= (__u64
)guest_memory
;
72 ram_map
.len
= GUEST_MEMORY_SIZE
;
73 ram_map
.user_vm_pa
= 0;
74 ram_map
.attr
= ACRN_MEM_ACCESS_RWX
;
75 ret
= ioctl(hsm_fd
, ACRN_IOCTL_SET_MEMSEG
, &ram_map
);
76 printf("Set up VM memory! [%d]\n", ret
);
78 memcpy(guest_memory
, guest16
, guest16_end
-guest16
);
80 /* setup vcpu registers */
81 memset(®s
, 0, sizeof(regs
));
83 regs
.vcpu_regs
.rip
= 0;
86 regs
.vcpu_regs
.cr0
= 0x30U
;
87 regs
.vcpu_regs
.cs_ar
= 0x009FU
;
88 regs
.vcpu_regs
.cs_sel
= 0xF000U
;
89 regs
.vcpu_regs
.cs_limit
= 0xFFFFU
;
90 regs
.vcpu_regs
.cs_base
= 0 & 0xFFFF0000UL
;
91 regs
.vcpu_regs
.rip
= 0 & 0xFFFFUL
;
93 ret
= ioctl(hsm_fd
, ACRN_IOCTL_SET_VCPU_REGS
, ®s
);
94 printf("Set up VM BSP registers! [%d]\n", ret
);
96 /* create an ioreq client for this VM */
97 ret
= ioctl(hsm_fd
, ACRN_IOCTL_CREATE_IOREQ_CLIENT
, 0);
98 printf("Created IO request client! [%d]\n", ret
);
101 ret
= ioctl(hsm_fd
, ACRN_IOCTL_START_VM
, vmid
);
102 printf("Start VM! [%d]\n", ret
);
104 signal(SIGINT
, vm_exit
);
106 ret
= ioctl(hsm_fd
, ACRN_IOCTL_ATTACH_IOREQ_CLIENT
, 0);
108 for (vcpu_id
= 0; vcpu_id
< vcpu_num
; vcpu_id
++) {
109 io_req
= &io_req_buf
[vcpu_id
];
110 if ((__sync_add_and_fetch(&io_req
->processed
, 0) == ACRN_IOREQ_STATE_PROCESSING
)
111 && (!io_req
->kernel_handled
))
112 if (io_req
->type
== ACRN_IOREQ_TYPE_PORTIO
) {
115 port
= io_req
->reqs
.pio_request
.address
;
116 bytes
= io_req
->reqs
.pio_request
.size
;
117 in
= (io_req
->reqs
.pio_request
.direction
== ACRN_IOREQ_DIR_READ
);
118 printf("Guest VM %s PIO[%x] with size[%x]\n", in
? "read" : "write", port
, bytes
);
121 notify
.vcpu
= vcpu_id
;
122 ioctl(hsm_fd
, ACRN_IOCTL_NOTIFY_REQUEST_FINISH
, ¬ify
);
127 ret
= ioctl(hsm_fd
, ACRN_IOCTL_DESTROY_VM
, NULL
);
128 printf("Destroy VM! [%d]\n", ret
);