xref: /aosp_15_r20/external/strace/kvm.c (revision cf84ac9a129d8ea9952db616b4e9b904c4bdde56)
1*cf84ac9aSAndroid Build Coastguard Worker /*
2*cf84ac9aSAndroid Build Coastguard Worker  * Support for decoding of KVM_* ioctl commands.
3*cf84ac9aSAndroid Build Coastguard Worker  *
4*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 2017 Masatake YAMATO <[email protected]>
5*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 2017 Red Hat, Inc.
6*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 2017-2018 The strace developers.
7*cf84ac9aSAndroid Build Coastguard Worker  * All rights reserved.
8*cf84ac9aSAndroid Build Coastguard Worker  *
9*cf84ac9aSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
10*cf84ac9aSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
11*cf84ac9aSAndroid Build Coastguard Worker  * are met:
12*cf84ac9aSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
13*cf84ac9aSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
14*cf84ac9aSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
15*cf84ac9aSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
16*cf84ac9aSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
17*cf84ac9aSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
18*cf84ac9aSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
19*cf84ac9aSAndroid Build Coastguard Worker  *
20*cf84ac9aSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21*cf84ac9aSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22*cf84ac9aSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23*cf84ac9aSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24*cf84ac9aSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25*cf84ac9aSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*cf84ac9aSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*cf84ac9aSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*cf84ac9aSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29*cf84ac9aSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*cf84ac9aSAndroid Build Coastguard Worker  */
31*cf84ac9aSAndroid Build Coastguard Worker 
32*cf84ac9aSAndroid Build Coastguard Worker #include "defs.h"
33*cf84ac9aSAndroid Build Coastguard Worker 
34*cf84ac9aSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_KVM_H
35*cf84ac9aSAndroid Build Coastguard Worker # include <linux/kvm.h>
36*cf84ac9aSAndroid Build Coastguard Worker # include "print_fields.h"
37*cf84ac9aSAndroid Build Coastguard Worker # include "arch_kvm.c"
38*cf84ac9aSAndroid Build Coastguard Worker # include "xmalloc.h"
39*cf84ac9aSAndroid Build Coastguard Worker # include "mmap_cache.h"
40*cf84ac9aSAndroid Build Coastguard Worker 
41*cf84ac9aSAndroid Build Coastguard Worker struct vcpu_info {
42*cf84ac9aSAndroid Build Coastguard Worker 	struct vcpu_info *next;
43*cf84ac9aSAndroid Build Coastguard Worker 	int fd;
44*cf84ac9aSAndroid Build Coastguard Worker 	int cpuid;
45*cf84ac9aSAndroid Build Coastguard Worker 	long mmap_addr;
46*cf84ac9aSAndroid Build Coastguard Worker 	unsigned long mmap_len;
47*cf84ac9aSAndroid Build Coastguard Worker 	bool resolved;
48*cf84ac9aSAndroid Build Coastguard Worker };
49*cf84ac9aSAndroid Build Coastguard Worker 
50*cf84ac9aSAndroid Build Coastguard Worker static bool dump_kvm_run_structure;
51*cf84ac9aSAndroid Build Coastguard Worker 
52*cf84ac9aSAndroid Build Coastguard Worker static struct vcpu_info *
vcpu_find(struct tcb * const tcp,int fd)53*cf84ac9aSAndroid Build Coastguard Worker vcpu_find(struct tcb *const tcp, int fd)
54*cf84ac9aSAndroid Build Coastguard Worker {
55*cf84ac9aSAndroid Build Coastguard Worker 	for (struct vcpu_info *vcpu_info = tcp->vcpu_info_list;
56*cf84ac9aSAndroid Build Coastguard Worker 	     vcpu_info;
57*cf84ac9aSAndroid Build Coastguard Worker 	     vcpu_info = vcpu_info->next)
58*cf84ac9aSAndroid Build Coastguard Worker 		if (vcpu_info->fd == fd)
59*cf84ac9aSAndroid Build Coastguard Worker 			return vcpu_info;
60*cf84ac9aSAndroid Build Coastguard Worker 
61*cf84ac9aSAndroid Build Coastguard Worker 	return NULL;
62*cf84ac9aSAndroid Build Coastguard Worker }
63*cf84ac9aSAndroid Build Coastguard Worker 
64*cf84ac9aSAndroid Build Coastguard Worker static struct vcpu_info *
vcpu_alloc(struct tcb * const tcp,int fd,int cpuid)65*cf84ac9aSAndroid Build Coastguard Worker vcpu_alloc(struct tcb *const tcp, int fd, int cpuid)
66*cf84ac9aSAndroid Build Coastguard Worker {
67*cf84ac9aSAndroid Build Coastguard Worker 	struct vcpu_info *vcpu_info = xcalloc(1, sizeof(*vcpu_info));
68*cf84ac9aSAndroid Build Coastguard Worker 
69*cf84ac9aSAndroid Build Coastguard Worker 	vcpu_info->fd = fd;
70*cf84ac9aSAndroid Build Coastguard Worker 	vcpu_info->cpuid = cpuid;
71*cf84ac9aSAndroid Build Coastguard Worker 
72*cf84ac9aSAndroid Build Coastguard Worker 	vcpu_info->next = tcp->vcpu_info_list;
73*cf84ac9aSAndroid Build Coastguard Worker 	tcp->vcpu_info_list = vcpu_info;
74*cf84ac9aSAndroid Build Coastguard Worker 
75*cf84ac9aSAndroid Build Coastguard Worker 	return vcpu_info;
76*cf84ac9aSAndroid Build Coastguard Worker }
77*cf84ac9aSAndroid Build Coastguard Worker 
78*cf84ac9aSAndroid Build Coastguard Worker void
kvm_vcpu_info_free(struct tcb * tcp)79*cf84ac9aSAndroid Build Coastguard Worker kvm_vcpu_info_free(struct tcb *tcp)
80*cf84ac9aSAndroid Build Coastguard Worker {
81*cf84ac9aSAndroid Build Coastguard Worker 	struct vcpu_info *head, *next;
82*cf84ac9aSAndroid Build Coastguard Worker 
83*cf84ac9aSAndroid Build Coastguard Worker 	for (head = tcp->vcpu_info_list; head; head = next) {
84*cf84ac9aSAndroid Build Coastguard Worker 		next = head->next;
85*cf84ac9aSAndroid Build Coastguard Worker 		free(head);
86*cf84ac9aSAndroid Build Coastguard Worker 	}
87*cf84ac9aSAndroid Build Coastguard Worker 
88*cf84ac9aSAndroid Build Coastguard Worker 	tcp->vcpu_info_list = NULL;
89*cf84ac9aSAndroid Build Coastguard Worker }
90*cf84ac9aSAndroid Build Coastguard Worker 
91*cf84ac9aSAndroid Build Coastguard Worker static void
vcpu_register(struct tcb * const tcp,int fd,int cpuid)92*cf84ac9aSAndroid Build Coastguard Worker vcpu_register(struct tcb *const tcp, int fd, int cpuid)
93*cf84ac9aSAndroid Build Coastguard Worker {
94*cf84ac9aSAndroid Build Coastguard Worker 	if (fd < 0)
95*cf84ac9aSAndroid Build Coastguard Worker 		return;
96*cf84ac9aSAndroid Build Coastguard Worker 
97*cf84ac9aSAndroid Build Coastguard Worker 	struct vcpu_info *vcpu_info = vcpu_find(tcp, fd);
98*cf84ac9aSAndroid Build Coastguard Worker 
99*cf84ac9aSAndroid Build Coastguard Worker 	if (!vcpu_info)
100*cf84ac9aSAndroid Build Coastguard Worker 		vcpu_info = vcpu_alloc(tcp, fd, cpuid);
101*cf84ac9aSAndroid Build Coastguard Worker 	else if (vcpu_info->cpuid != cpuid)
102*cf84ac9aSAndroid Build Coastguard Worker 	{
103*cf84ac9aSAndroid Build Coastguard Worker 		vcpu_info->cpuid = cpuid;
104*cf84ac9aSAndroid Build Coastguard Worker 		vcpu_info->resolved = false;
105*cf84ac9aSAndroid Build Coastguard Worker 	}
106*cf84ac9aSAndroid Build Coastguard Worker }
107*cf84ac9aSAndroid Build Coastguard Worker 
108*cf84ac9aSAndroid Build Coastguard Worker static bool
is_map_for_file(struct mmap_cache_entry_t * map_info,void * data)109*cf84ac9aSAndroid Build Coastguard Worker is_map_for_file(struct mmap_cache_entry_t *map_info, void *data)
110*cf84ac9aSAndroid Build Coastguard Worker {
111*cf84ac9aSAndroid Build Coastguard Worker 	/* major version for anon inode may be given in get_anon_bdev()
112*cf84ac9aSAndroid Build Coastguard Worker 	 * in linux kernel.
113*cf84ac9aSAndroid Build Coastguard Worker 	 *
114*cf84ac9aSAndroid Build Coastguard Worker 	 * 	*p = MKDEV(0, dev & MINORMASK);
115*cf84ac9aSAndroid Build Coastguard Worker 	 *-----------------^
116*cf84ac9aSAndroid Build Coastguard Worker 	 */
117*cf84ac9aSAndroid Build Coastguard Worker 	return map_info->binary_filename &&
118*cf84ac9aSAndroid Build Coastguard Worker 		map_info->major == 0 &&
119*cf84ac9aSAndroid Build Coastguard Worker 		strcmp(map_info->binary_filename, data) == 0;
120*cf84ac9aSAndroid Build Coastguard Worker }
121*cf84ac9aSAndroid Build Coastguard Worker 
122*cf84ac9aSAndroid Build Coastguard Worker static unsigned long
map_len(struct mmap_cache_entry_t * map_info)123*cf84ac9aSAndroid Build Coastguard Worker map_len(struct mmap_cache_entry_t *map_info)
124*cf84ac9aSAndroid Build Coastguard Worker {
125*cf84ac9aSAndroid Build Coastguard Worker 	return map_info->start_addr < map_info->end_addr
126*cf84ac9aSAndroid Build Coastguard Worker 		? map_info->end_addr - map_info->start_addr
127*cf84ac9aSAndroid Build Coastguard Worker 		: 0;
128*cf84ac9aSAndroid Build Coastguard Worker }
129*cf84ac9aSAndroid Build Coastguard Worker 
130*cf84ac9aSAndroid Build Coastguard Worker #define VCPU_DENTRY_PREFIX "anon_inode:kvm-vcpu:"
131*cf84ac9aSAndroid Build Coastguard Worker 
132*cf84ac9aSAndroid Build Coastguard Worker static struct vcpu_info*
vcpu_get_info(struct tcb * const tcp,int fd)133*cf84ac9aSAndroid Build Coastguard Worker vcpu_get_info(struct tcb *const tcp, int fd)
134*cf84ac9aSAndroid Build Coastguard Worker {
135*cf84ac9aSAndroid Build Coastguard Worker 	struct vcpu_info *vcpu_info = vcpu_find(tcp, fd);
136*cf84ac9aSAndroid Build Coastguard Worker 	struct mmap_cache_entry_t *map_info;
137*cf84ac9aSAndroid Build Coastguard Worker 	const char *cpuid_str;
138*cf84ac9aSAndroid Build Coastguard Worker 
139*cf84ac9aSAndroid Build Coastguard Worker 	enum mmap_cache_rebuild_result mc_stat =
140*cf84ac9aSAndroid Build Coastguard Worker 		mmap_cache_rebuild_if_invalid(tcp, __func__);
141*cf84ac9aSAndroid Build Coastguard Worker 	if (mc_stat == MMAP_CACHE_REBUILD_NOCACHE)
142*cf84ac9aSAndroid Build Coastguard Worker 		return NULL;
143*cf84ac9aSAndroid Build Coastguard Worker 
144*cf84ac9aSAndroid Build Coastguard Worker 	if (vcpu_info && vcpu_info->resolved) {
145*cf84ac9aSAndroid Build Coastguard Worker 		if (mc_stat == MMAP_CACHE_REBUILD_READY)
146*cf84ac9aSAndroid Build Coastguard Worker 			return vcpu_info;
147*cf84ac9aSAndroid Build Coastguard Worker 		else {
148*cf84ac9aSAndroid Build Coastguard Worker 			map_info = mmap_cache_search(tcp, vcpu_info->mmap_addr);
149*cf84ac9aSAndroid Build Coastguard Worker 			if (map_info) {
150*cf84ac9aSAndroid Build Coastguard Worker 				cpuid_str =
151*cf84ac9aSAndroid Build Coastguard Worker 					STR_STRIP_PREFIX(map_info->binary_filename,
152*cf84ac9aSAndroid Build Coastguard Worker 							 VCPU_DENTRY_PREFIX);
153*cf84ac9aSAndroid Build Coastguard Worker 				if (cpuid_str != map_info->binary_filename) {
154*cf84ac9aSAndroid Build Coastguard Worker 					int cpuid = string_to_uint(cpuid_str);
155*cf84ac9aSAndroid Build Coastguard Worker 					if (cpuid < 0)
156*cf84ac9aSAndroid Build Coastguard Worker 						return NULL;
157*cf84ac9aSAndroid Build Coastguard Worker 					if (vcpu_info->cpuid == cpuid)
158*cf84ac9aSAndroid Build Coastguard Worker 						return vcpu_info;
159*cf84ac9aSAndroid Build Coastguard Worker 				}
160*cf84ac9aSAndroid Build Coastguard Worker 			}
161*cf84ac9aSAndroid Build Coastguard Worker 
162*cf84ac9aSAndroid Build Coastguard Worker 			/* The vcpu vma may be mremap'ed. */
163*cf84ac9aSAndroid Build Coastguard Worker 			vcpu_info->resolved = false;
164*cf84ac9aSAndroid Build Coastguard Worker 		}
165*cf84ac9aSAndroid Build Coastguard Worker 	}
166*cf84ac9aSAndroid Build Coastguard Worker 
167*cf84ac9aSAndroid Build Coastguard Worker 	/* Slow path: !vcpu_info || !vcpu_info->resolved */
168*cf84ac9aSAndroid Build Coastguard Worker 	char path[PATH_MAX + 1];
169*cf84ac9aSAndroid Build Coastguard Worker 	cpuid_str = path;
170*cf84ac9aSAndroid Build Coastguard Worker 	if (getfdpath(tcp, fd, path, sizeof(path)) >= 0)
171*cf84ac9aSAndroid Build Coastguard Worker 		cpuid_str = STR_STRIP_PREFIX(path, VCPU_DENTRY_PREFIX);
172*cf84ac9aSAndroid Build Coastguard Worker 	if (cpuid_str == path)
173*cf84ac9aSAndroid Build Coastguard Worker 		map_info = NULL;
174*cf84ac9aSAndroid Build Coastguard Worker 	else
175*cf84ac9aSAndroid Build Coastguard Worker 		map_info = mmap_cache_search_custom(tcp, is_map_for_file, path);
176*cf84ac9aSAndroid Build Coastguard Worker 
177*cf84ac9aSAndroid Build Coastguard Worker 	if (map_info) {
178*cf84ac9aSAndroid Build Coastguard Worker 		int cpuid = string_to_uint(cpuid_str);
179*cf84ac9aSAndroid Build Coastguard Worker 		if (cpuid < 0)
180*cf84ac9aSAndroid Build Coastguard Worker 			return NULL;
181*cf84ac9aSAndroid Build Coastguard Worker 		if (!vcpu_info)
182*cf84ac9aSAndroid Build Coastguard Worker 			vcpu_info = vcpu_alloc(tcp, fd, cpuid);
183*cf84ac9aSAndroid Build Coastguard Worker 		else if (vcpu_info->cpuid != cpuid)
184*cf84ac9aSAndroid Build Coastguard Worker 			vcpu_info->cpuid = cpuid;
185*cf84ac9aSAndroid Build Coastguard Worker 		vcpu_info->mmap_addr = map_info->start_addr;
186*cf84ac9aSAndroid Build Coastguard Worker 		vcpu_info->mmap_len  = map_len(map_info);
187*cf84ac9aSAndroid Build Coastguard Worker 		vcpu_info->resolved  = true;
188*cf84ac9aSAndroid Build Coastguard Worker 		return vcpu_info;
189*cf84ac9aSAndroid Build Coastguard Worker 	}
190*cf84ac9aSAndroid Build Coastguard Worker 
191*cf84ac9aSAndroid Build Coastguard Worker 	return NULL;
192*cf84ac9aSAndroid Build Coastguard Worker }
193*cf84ac9aSAndroid Build Coastguard Worker 
194*cf84ac9aSAndroid Build Coastguard Worker static int
kvm_ioctl_create_vcpu(struct tcb * const tcp,const kernel_ulong_t arg)195*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_create_vcpu(struct tcb *const tcp, const kernel_ulong_t arg)
196*cf84ac9aSAndroid Build Coastguard Worker {
197*cf84ac9aSAndroid Build Coastguard Worker 	uint32_t cpuid = arg;
198*cf84ac9aSAndroid Build Coastguard Worker 
199*cf84ac9aSAndroid Build Coastguard Worker 	if (entering(tcp)) {
200*cf84ac9aSAndroid Build Coastguard Worker 		tprintf(", %u", cpuid);
201*cf84ac9aSAndroid Build Coastguard Worker 		if (dump_kvm_run_structure)
202*cf84ac9aSAndroid Build Coastguard Worker 			return 0;
203*cf84ac9aSAndroid Build Coastguard Worker 	} else if (!syserror(tcp)) {
204*cf84ac9aSAndroid Build Coastguard Worker 		vcpu_register(tcp, tcp->u_rval, cpuid);
205*cf84ac9aSAndroid Build Coastguard Worker 	}
206*cf84ac9aSAndroid Build Coastguard Worker 
207*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_IOCTL_DECODED | RVAL_FD;
208*cf84ac9aSAndroid Build Coastguard Worker }
209*cf84ac9aSAndroid Build Coastguard Worker 
210*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION
211*cf84ac9aSAndroid Build Coastguard Worker #  include "xlat/kvm_mem_flags.h"
212*cf84ac9aSAndroid Build Coastguard Worker static int
kvm_ioctl_set_user_memory_region(struct tcb * const tcp,const kernel_ulong_t arg)213*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_set_user_memory_region(struct tcb *const tcp, const kernel_ulong_t arg)
214*cf84ac9aSAndroid Build Coastguard Worker {
215*cf84ac9aSAndroid Build Coastguard Worker 	struct kvm_userspace_memory_region u_memory_region;
216*cf84ac9aSAndroid Build Coastguard Worker 
217*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
218*cf84ac9aSAndroid Build Coastguard Worker 	if (umove_or_printaddr(tcp, arg, &u_memory_region))
219*cf84ac9aSAndroid Build Coastguard Worker 		return RVAL_IOCTL_DECODED;
220*cf84ac9aSAndroid Build Coastguard Worker 
221*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U("{", u_memory_region, slot);
222*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_FLAGS(", ", u_memory_region, flags, kvm_mem_flags,
223*cf84ac9aSAndroid Build Coastguard Worker 			  "KVM_MEM_???");
224*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X(", ", u_memory_region, guest_phys_addr);
225*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", u_memory_region, memory_size);
226*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X(", ", u_memory_region, userspace_addr);
227*cf84ac9aSAndroid Build Coastguard Worker 	tprints("}");
228*cf84ac9aSAndroid Build Coastguard Worker 
229*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_IOCTL_DECODED;
230*cf84ac9aSAndroid Build Coastguard Worker }
231*cf84ac9aSAndroid Build Coastguard Worker # endif /* HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION */
232*cf84ac9aSAndroid Build Coastguard Worker 
233*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_REGS
234*cf84ac9aSAndroid Build Coastguard Worker static int
kvm_ioctl_decode_regs(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)235*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_decode_regs(struct tcb *const tcp, const unsigned int code,
236*cf84ac9aSAndroid Build Coastguard Worker 		      const kernel_ulong_t arg)
237*cf84ac9aSAndroid Build Coastguard Worker {
238*cf84ac9aSAndroid Build Coastguard Worker 	struct kvm_regs regs;
239*cf84ac9aSAndroid Build Coastguard Worker 
240*cf84ac9aSAndroid Build Coastguard Worker 	if (code == KVM_GET_REGS && entering(tcp))
241*cf84ac9aSAndroid Build Coastguard Worker 		return 0;
242*cf84ac9aSAndroid Build Coastguard Worker 
243*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
244*cf84ac9aSAndroid Build Coastguard Worker 	if (!umove_or_printaddr(tcp, arg, &regs))
245*cf84ac9aSAndroid Build Coastguard Worker 		arch_print_kvm_regs(tcp, arg, &regs);
246*cf84ac9aSAndroid Build Coastguard Worker 
247*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_IOCTL_DECODED;
248*cf84ac9aSAndroid Build Coastguard Worker }
249*cf84ac9aSAndroid Build Coastguard Worker # endif /* HAVE_STRUCT_KVM_REGS */
250*cf84ac9aSAndroid Build Coastguard Worker 
251*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_CPUID2
252*cf84ac9aSAndroid Build Coastguard Worker #  include "xlat/kvm_cpuid_flags.h"
253*cf84ac9aSAndroid Build Coastguard Worker static bool
print_kvm_cpuid_entry(struct tcb * const tcp,void * elem_buf,size_t elem_size,void * data)254*cf84ac9aSAndroid Build Coastguard Worker print_kvm_cpuid_entry(struct tcb *const tcp,
255*cf84ac9aSAndroid Build Coastguard Worker 		      void* elem_buf, size_t elem_size, void* data)
256*cf84ac9aSAndroid Build Coastguard Worker {
257*cf84ac9aSAndroid Build Coastguard Worker 	const struct kvm_cpuid_entry2 *entry = elem_buf;
258*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X("{", *entry, function);
259*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X(", ", *entry, index);
260*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_FLAGS(", ", *entry, flags, kvm_cpuid_flags,
261*cf84ac9aSAndroid Build Coastguard Worker 			  "KVM_CPUID_FLAG_???");
262*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X(", ", *entry, eax);
263*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X(", ", *entry, ebx);
264*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X(", ", *entry, ecx);
265*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_X(", ", *entry, edx);
266*cf84ac9aSAndroid Build Coastguard Worker 	tprints("}");
267*cf84ac9aSAndroid Build Coastguard Worker 
268*cf84ac9aSAndroid Build Coastguard Worker 	return true;
269*cf84ac9aSAndroid Build Coastguard Worker }
270*cf84ac9aSAndroid Build Coastguard Worker 
271*cf84ac9aSAndroid Build Coastguard Worker static int
kvm_ioctl_decode_cpuid2(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)272*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_decode_cpuid2(struct tcb *const tcp, const unsigned int code,
273*cf84ac9aSAndroid Build Coastguard Worker 			const kernel_ulong_t arg)
274*cf84ac9aSAndroid Build Coastguard Worker {
275*cf84ac9aSAndroid Build Coastguard Worker 	struct kvm_cpuid2 cpuid;
276*cf84ac9aSAndroid Build Coastguard Worker 
277*cf84ac9aSAndroid Build Coastguard Worker 	if (entering(tcp) && (code == KVM_GET_SUPPORTED_CPUID
278*cf84ac9aSAndroid Build Coastguard Worker #  ifdef KVM_GET_EMULATED_CPUID
279*cf84ac9aSAndroid Build Coastguard Worker 			      || code == KVM_GET_EMULATED_CPUID
280*cf84ac9aSAndroid Build Coastguard Worker #  endif
281*cf84ac9aSAndroid Build Coastguard Worker 			     ))
282*cf84ac9aSAndroid Build Coastguard Worker 		return 0;
283*cf84ac9aSAndroid Build Coastguard Worker 
284*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
285*cf84ac9aSAndroid Build Coastguard Worker 	if (!umove_or_printaddr(tcp, arg, &cpuid)) {
286*cf84ac9aSAndroid Build Coastguard Worker 		PRINT_FIELD_U("{", cpuid, nent);
287*cf84ac9aSAndroid Build Coastguard Worker 
288*cf84ac9aSAndroid Build Coastguard Worker 		tprints(", entries=");
289*cf84ac9aSAndroid Build Coastguard Worker 		if (abbrev(tcp)) {
290*cf84ac9aSAndroid Build Coastguard Worker 			tprints("[");
291*cf84ac9aSAndroid Build Coastguard Worker 			if (cpuid.nent)
292*cf84ac9aSAndroid Build Coastguard Worker 				tprints("...");
293*cf84ac9aSAndroid Build Coastguard Worker 			tprints("]");
294*cf84ac9aSAndroid Build Coastguard Worker 
295*cf84ac9aSAndroid Build Coastguard Worker 		} else {
296*cf84ac9aSAndroid Build Coastguard Worker 			struct kvm_cpuid_entry2 entry;
297*cf84ac9aSAndroid Build Coastguard Worker 			print_array(tcp, arg + sizeof(cpuid), cpuid.nent,
298*cf84ac9aSAndroid Build Coastguard Worker 				    &entry, sizeof(entry), tfetch_mem,
299*cf84ac9aSAndroid Build Coastguard Worker 				    print_kvm_cpuid_entry, NULL);
300*cf84ac9aSAndroid Build Coastguard Worker 		}
301*cf84ac9aSAndroid Build Coastguard Worker 		tprints("}");
302*cf84ac9aSAndroid Build Coastguard Worker 	}
303*cf84ac9aSAndroid Build Coastguard Worker 
304*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_IOCTL_DECODED;
305*cf84ac9aSAndroid Build Coastguard Worker }
306*cf84ac9aSAndroid Build Coastguard Worker # endif /* HAVE_STRUCT_KVM_CPUID2 */
307*cf84ac9aSAndroid Build Coastguard Worker 
308*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_SREGS
309*cf84ac9aSAndroid Build Coastguard Worker static int
kvm_ioctl_decode_sregs(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)310*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_decode_sregs(struct tcb *const tcp, const unsigned int code,
311*cf84ac9aSAndroid Build Coastguard Worker 		       const kernel_ulong_t arg)
312*cf84ac9aSAndroid Build Coastguard Worker {
313*cf84ac9aSAndroid Build Coastguard Worker 	struct kvm_sregs sregs;
314*cf84ac9aSAndroid Build Coastguard Worker 
315*cf84ac9aSAndroid Build Coastguard Worker 	if (code == KVM_GET_SREGS && entering(tcp))
316*cf84ac9aSAndroid Build Coastguard Worker 		return 0;
317*cf84ac9aSAndroid Build Coastguard Worker 
318*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
319*cf84ac9aSAndroid Build Coastguard Worker 	if (!umove_or_printaddr(tcp, arg, &sregs))
320*cf84ac9aSAndroid Build Coastguard Worker 		arch_print_kvm_sregs(tcp, arg, &sregs);
321*cf84ac9aSAndroid Build Coastguard Worker 
322*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_IOCTL_DECODED;
323*cf84ac9aSAndroid Build Coastguard Worker }
324*cf84ac9aSAndroid Build Coastguard Worker # endif /* HAVE_STRUCT_KVM_SREGS */
325*cf84ac9aSAndroid Build Coastguard Worker 
326*cf84ac9aSAndroid Build Coastguard Worker # include "xlat/kvm_cap.h"
327*cf84ac9aSAndroid Build Coastguard Worker static int
kvm_ioctl_decode_check_extension(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)328*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_decode_check_extension(struct tcb *const tcp, const unsigned int code,
329*cf84ac9aSAndroid Build Coastguard Worker 				 const kernel_ulong_t arg)
330*cf84ac9aSAndroid Build Coastguard Worker {
331*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
332*cf84ac9aSAndroid Build Coastguard Worker 	printxval_index(kvm_cap, arg, "KVM_CAP_???");
333*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_IOCTL_DECODED;
334*cf84ac9aSAndroid Build Coastguard Worker }
335*cf84ac9aSAndroid Build Coastguard Worker 
336*cf84ac9aSAndroid Build Coastguard Worker # include "xlat/kvm_exit_reason.h"
337*cf84ac9aSAndroid Build Coastguard Worker static void
kvm_ioctl_run_attach_auxstr(struct tcb * const tcp,struct vcpu_info * info)338*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_run_attach_auxstr(struct tcb *const tcp,
339*cf84ac9aSAndroid Build Coastguard Worker 			    struct vcpu_info *info)
340*cf84ac9aSAndroid Build Coastguard Worker 
341*cf84ac9aSAndroid Build Coastguard Worker {
342*cf84ac9aSAndroid Build Coastguard Worker 	static struct kvm_run vcpu_run_struct;
343*cf84ac9aSAndroid Build Coastguard Worker 
344*cf84ac9aSAndroid Build Coastguard Worker 	if (info->mmap_len < sizeof(vcpu_run_struct))
345*cf84ac9aSAndroid Build Coastguard Worker 		return;
346*cf84ac9aSAndroid Build Coastguard Worker 
347*cf84ac9aSAndroid Build Coastguard Worker 	if (umove(tcp, info->mmap_addr, &vcpu_run_struct) < 0)
348*cf84ac9aSAndroid Build Coastguard Worker 		return;
349*cf84ac9aSAndroid Build Coastguard Worker 
350*cf84ac9aSAndroid Build Coastguard Worker 	tcp->auxstr = xlat_idx(kvm_exit_reason, ARRAY_SIZE(kvm_exit_reason) - 1,
351*cf84ac9aSAndroid Build Coastguard Worker 			       vcpu_run_struct.exit_reason);
352*cf84ac9aSAndroid Build Coastguard Worker 	if (!tcp->auxstr)
353*cf84ac9aSAndroid Build Coastguard Worker 		tcp->auxstr = "KVM_EXIT_???";
354*cf84ac9aSAndroid Build Coastguard Worker }
355*cf84ac9aSAndroid Build Coastguard Worker 
356*cf84ac9aSAndroid Build Coastguard Worker static int
kvm_ioctl_decode_run(struct tcb * const tcp)357*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl_decode_run(struct tcb *const tcp)
358*cf84ac9aSAndroid Build Coastguard Worker {
359*cf84ac9aSAndroid Build Coastguard Worker 
360*cf84ac9aSAndroid Build Coastguard Worker 	if (entering(tcp))
361*cf84ac9aSAndroid Build Coastguard Worker 		return 0;
362*cf84ac9aSAndroid Build Coastguard Worker 
363*cf84ac9aSAndroid Build Coastguard Worker 	int r = RVAL_DECODED;
364*cf84ac9aSAndroid Build Coastguard Worker 
365*cf84ac9aSAndroid Build Coastguard Worker 	if (syserror(tcp))
366*cf84ac9aSAndroid Build Coastguard Worker 		return r;
367*cf84ac9aSAndroid Build Coastguard Worker 
368*cf84ac9aSAndroid Build Coastguard Worker 	if (dump_kvm_run_structure) {
369*cf84ac9aSAndroid Build Coastguard Worker 		tcp->auxstr = NULL;
370*cf84ac9aSAndroid Build Coastguard Worker 		int fd = tcp->u_arg[0];
371*cf84ac9aSAndroid Build Coastguard Worker 		struct vcpu_info *info = vcpu_get_info(tcp, fd);
372*cf84ac9aSAndroid Build Coastguard Worker 
373*cf84ac9aSAndroid Build Coastguard Worker 		if (info) {
374*cf84ac9aSAndroid Build Coastguard Worker 			kvm_ioctl_run_attach_auxstr(tcp, info);
375*cf84ac9aSAndroid Build Coastguard Worker 			if (tcp->auxstr)
376*cf84ac9aSAndroid Build Coastguard Worker 				r |= RVAL_STR;
377*cf84ac9aSAndroid Build Coastguard Worker 		}
378*cf84ac9aSAndroid Build Coastguard Worker 	}
379*cf84ac9aSAndroid Build Coastguard Worker 
380*cf84ac9aSAndroid Build Coastguard Worker 	return r;
381*cf84ac9aSAndroid Build Coastguard Worker }
382*cf84ac9aSAndroid Build Coastguard Worker 
383*cf84ac9aSAndroid Build Coastguard Worker int
kvm_ioctl(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)384*cf84ac9aSAndroid Build Coastguard Worker kvm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg)
385*cf84ac9aSAndroid Build Coastguard Worker {
386*cf84ac9aSAndroid Build Coastguard Worker 	switch (code) {
387*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_CREATE_VCPU:
388*cf84ac9aSAndroid Build Coastguard Worker 		return kvm_ioctl_create_vcpu(tcp, arg);
389*cf84ac9aSAndroid Build Coastguard Worker 
390*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION
391*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_SET_USER_MEMORY_REGION:
392*cf84ac9aSAndroid Build Coastguard Worker 		return kvm_ioctl_set_user_memory_region(tcp, arg);
393*cf84ac9aSAndroid Build Coastguard Worker # endif
394*cf84ac9aSAndroid Build Coastguard Worker 
395*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_REGS
396*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_SET_REGS:
397*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_GET_REGS:
398*cf84ac9aSAndroid Build Coastguard Worker 		return kvm_ioctl_decode_regs(tcp, code, arg);
399*cf84ac9aSAndroid Build Coastguard Worker # endif
400*cf84ac9aSAndroid Build Coastguard Worker 
401*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_SREGS
402*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_SET_SREGS:
403*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_GET_SREGS:
404*cf84ac9aSAndroid Build Coastguard Worker 		return kvm_ioctl_decode_sregs(tcp, code, arg);
405*cf84ac9aSAndroid Build Coastguard Worker # endif
406*cf84ac9aSAndroid Build Coastguard Worker 
407*cf84ac9aSAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_KVM_CPUID2
408*cf84ac9aSAndroid Build Coastguard Worker        case KVM_SET_CPUID2:
409*cf84ac9aSAndroid Build Coastguard Worker        case KVM_GET_SUPPORTED_CPUID:
410*cf84ac9aSAndroid Build Coastguard Worker #  ifdef KVM_GET_EMULATED_CPUID
411*cf84ac9aSAndroid Build Coastguard Worker        case KVM_GET_EMULATED_CPUID:
412*cf84ac9aSAndroid Build Coastguard Worker #  endif
413*cf84ac9aSAndroid Build Coastguard Worker                return kvm_ioctl_decode_cpuid2(tcp, code, arg);
414*cf84ac9aSAndroid Build Coastguard Worker # endif
415*cf84ac9aSAndroid Build Coastguard Worker 
416*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_CHECK_EXTENSION:
417*cf84ac9aSAndroid Build Coastguard Worker 		return kvm_ioctl_decode_check_extension(tcp, code, arg);
418*cf84ac9aSAndroid Build Coastguard Worker 
419*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_CREATE_VM:
420*cf84ac9aSAndroid Build Coastguard Worker 		return RVAL_DECODED | RVAL_FD;
421*cf84ac9aSAndroid Build Coastguard Worker 
422*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_RUN:
423*cf84ac9aSAndroid Build Coastguard Worker 		return kvm_ioctl_decode_run(tcp);
424*cf84ac9aSAndroid Build Coastguard Worker 
425*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_GET_VCPU_MMAP_SIZE:
426*cf84ac9aSAndroid Build Coastguard Worker 	case KVM_GET_API_VERSION:
427*cf84ac9aSAndroid Build Coastguard Worker 	default:
428*cf84ac9aSAndroid Build Coastguard Worker 		return RVAL_DECODED;
429*cf84ac9aSAndroid Build Coastguard Worker 	}
430*cf84ac9aSAndroid Build Coastguard Worker }
431*cf84ac9aSAndroid Build Coastguard Worker 
432*cf84ac9aSAndroid Build Coastguard Worker void
kvm_run_structure_decoder_init(void)433*cf84ac9aSAndroid Build Coastguard Worker kvm_run_structure_decoder_init(void)
434*cf84ac9aSAndroid Build Coastguard Worker {
435*cf84ac9aSAndroid Build Coastguard Worker 	dump_kvm_run_structure = true;
436*cf84ac9aSAndroid Build Coastguard Worker 	mmap_cache_enable();
437*cf84ac9aSAndroid Build Coastguard Worker }
438*cf84ac9aSAndroid Build Coastguard Worker 
439*cf84ac9aSAndroid Build Coastguard Worker #endif /* HAVE_LINUX_KVM_H */
440