1 /*
2 * Support for decoding of KVM_* ioctl commands.
3 *
4 * Copyright (c) 2017 Masatake YAMATO <yamato@redhat.com>
5 * Copyright (c) 2017 Red Hat, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "defs.h"
32
33 #ifdef HAVE_LINUX_KVM_H
34 # include <linux/kvm.h>
35 # include "print_fields.h"
36 # include "arch_kvm.c"
37
38 static int
kvm_ioctl_create_vcpu(struct tcb * const tcp,const kernel_ulong_t arg)39 kvm_ioctl_create_vcpu(struct tcb *const tcp, const kernel_ulong_t arg)
40 {
41 uint32_t cpuid = arg;
42
43 tprintf(", %u", cpuid);
44 return RVAL_IOCTL_DECODED | RVAL_FD;
45 }
46
47 # ifdef HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION
48 # include "xlat/kvm_mem_flags.h"
49 static int
kvm_ioctl_set_user_memory_region(struct tcb * const tcp,const kernel_ulong_t arg)50 kvm_ioctl_set_user_memory_region(struct tcb *const tcp, const kernel_ulong_t arg)
51 {
52 struct kvm_userspace_memory_region u_memory_region;
53
54 tprints(", ");
55 if (umove_or_printaddr(tcp, arg, &u_memory_region))
56 return RVAL_IOCTL_DECODED;
57
58 PRINT_FIELD_U("{", u_memory_region, slot);
59 PRINT_FIELD_FLAGS(", ", u_memory_region, flags, kvm_mem_flags,
60 "KVM_MEM_???");
61 PRINT_FIELD_X(", ", u_memory_region, guest_phys_addr);
62 PRINT_FIELD_U(", ", u_memory_region, memory_size);
63 PRINT_FIELD_X(", ", u_memory_region, userspace_addr);
64 tprints("}");
65
66 return RVAL_IOCTL_DECODED;
67 }
68 # endif /* HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION */
69
70 # ifdef HAVE_STRUCT_KVM_REGS
71 static int
kvm_ioctl_decode_regs(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)72 kvm_ioctl_decode_regs(struct tcb *const tcp, const unsigned int code,
73 const kernel_ulong_t arg)
74 {
75 struct kvm_regs regs;
76
77 if (code == KVM_GET_REGS && entering(tcp))
78 return 0;
79
80 tprints(", ");
81 if (!umove_or_printaddr(tcp, arg, ®s))
82 arch_print_kvm_regs(tcp, arg, ®s);
83
84 return RVAL_IOCTL_DECODED;
85 }
86 # endif /* HAVE_STRUCT_KVM_REGS */
87
88 # ifdef HAVE_STRUCT_KVM_SREGS
89 static int
kvm_ioctl_decode_sregs(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)90 kvm_ioctl_decode_sregs(struct tcb *const tcp, const unsigned int code,
91 const kernel_ulong_t arg)
92 {
93 struct kvm_sregs sregs;
94
95 if (code == KVM_GET_SREGS && entering(tcp))
96 return 0;
97
98 tprints(", ");
99 if (!umove_or_printaddr(tcp, arg, &sregs))
100 arch_print_kvm_sregs(tcp, arg, &sregs);
101
102 return RVAL_IOCTL_DECODED;
103 }
104 # endif /* HAVE_STRUCT_KVM_SREGS */
105
106 int
kvm_ioctl(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)107 kvm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg)
108 {
109 switch (code) {
110 case KVM_CREATE_VCPU:
111 return kvm_ioctl_create_vcpu(tcp, arg);
112
113 # ifdef HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION
114 case KVM_SET_USER_MEMORY_REGION:
115 return kvm_ioctl_set_user_memory_region(tcp, arg);
116 # endif
117
118 # ifdef HAVE_STRUCT_KVM_REGS
119 case KVM_SET_REGS:
120 case KVM_GET_REGS:
121 return kvm_ioctl_decode_regs(tcp, code, arg);
122 # endif
123
124 # ifdef HAVE_STRUCT_KVM_SREGS
125 case KVM_SET_SREGS:
126 case KVM_GET_SREGS:
127 return kvm_ioctl_decode_sregs(tcp, code, arg);
128 # endif
129
130 case KVM_CREATE_VM:
131 return RVAL_DECODED | RVAL_FD;
132 case KVM_RUN:
133 case KVM_GET_VCPU_MMAP_SIZE:
134 case KVM_GET_API_VERSION:
135 default:
136 return RVAL_DECODED;
137 }
138 }
139
140 #endif /* HAVE_LINUX_KVM_H */
141