summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMasatake YAMATO <yamato@redhat.com>2017-12-04 22:08:16 +0900
committerDmitry V. Levin <ldv@altlinux.org>2017-12-04 18:29:38 +0000
commit647709d8e5d123414276346412c51c673a478049 (patch)
tree5955d1765190f7306946e2381ee70c0e049edbc4
parent1d3b9b2c94aece61b7f4686627d7fb9417dc1510 (diff)
downloadstrace-647709d8e5d123414276346412c51c673a478049.tar.gz
kvm: decode the argument of KVM_{SET, GET}_SREGS ioctl command
* configure.ac (AC_CHECK_TYPES): Add struct kvm_sregs. * kvm.c [HAVE_STRUCT_KVM_SREGS] (kvm_ioctl_decode_sregs): New function. (kvm_ioctl) [HAVE_STRUCT_KVM_SREGS] <KVM_SET_SREGS, KVM_GET_SREGS>: Use it. * linux/arch_kvm.c (arch_print_kvm_sregs): New function. * linux/x86_64/arch_kvm.c (PRINT_FIELD_KVM_SREGS_STRUCT): New macro. (kvm_ioctl_decode_regs_dtable, kvm_ioctl_decode_regs_segment, arch_print_kvm_sregs): New functions. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
-rw-r--r--configure.ac1
-rw-r--r--kvm.c24
-rw-r--r--linux/arch_kvm.c10
-rw-r--r--linux/x86_64/arch_kvm.c72
4 files changed, 107 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 9a3646aca..729ef3f7d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -543,6 +543,7 @@ AC_CHECK_TYPES([struct blk_user_trace_setup],,, [#include <linux/blktrace_api.h>
AC_CHECK_TYPES(m4_normalize([
struct kvm_regs,
+ struct kvm_sregs,
struct kvm_userspace_memory_region
]),,, [#include <linux/kvm.h>])
diff --git a/kvm.c b/kvm.c
index 2d5962c29..86fd9e509 100644
--- a/kvm.c
+++ b/kvm.c
@@ -85,6 +85,24 @@ kvm_ioctl_decode_regs(struct tcb *const tcp, const unsigned int code,
}
# endif /* HAVE_STRUCT_KVM_REGS */
+# ifdef HAVE_STRUCT_KVM_SREGS
+static int
+kvm_ioctl_decode_sregs(struct tcb *const tcp, const unsigned int code,
+ const kernel_ulong_t arg)
+{
+ struct kvm_sregs sregs;
+
+ if (code == KVM_GET_SREGS && entering(tcp))
+ return 0;
+
+ tprints(", ");
+ if (!umove_or_printaddr(tcp, arg, &sregs))
+ arch_print_kvm_sregs(tcp, arg, &sregs);
+
+ return RVAL_IOCTL_DECODED;
+}
+# endif /* HAVE_STRUCT_KVM_SREGS */
+
int
kvm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg)
{
@@ -103,6 +121,12 @@ kvm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t a
return kvm_ioctl_decode_regs(tcp, code, arg);
# endif
+# ifdef HAVE_STRUCT_KVM_SREGS
+ case KVM_SET_SREGS:
+ case KVM_GET_SREGS:
+ return kvm_ioctl_decode_sregs(tcp, code, arg);
+# endif
+
case KVM_CREATE_VM:
return RVAL_DECODED | RVAL_FD;
case KVM_RUN:
diff --git a/linux/arch_kvm.c b/linux/arch_kvm.c
index d1292a5b1..f12f32ab4 100644
--- a/linux/arch_kvm.c
+++ b/linux/arch_kvm.c
@@ -7,3 +7,13 @@ arch_print_kvm_regs(struct tcb *const tcp,
printaddr(addr);
}
#endif /* HAVE_STRUCT_KVM_REGS */
+
+#ifdef HAVE_STRUCT_KVM_SREGS
+static void
+arch_print_kvm_sregs(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const struct kvm_sregs *const sregs)
+{
+ printaddr(addr);
+}
+#endif /* HAVE_STRUCT_KVM_SREGS */
diff --git a/linux/x86_64/arch_kvm.c b/linux/x86_64/arch_kvm.c
index f5ade5d89..f0075cae5 100644
--- a/linux/x86_64/arch_kvm.c
+++ b/linux/x86_64/arch_kvm.c
@@ -36,3 +36,75 @@ arch_print_kvm_regs(struct tcb *const tcp,
tprints("}");
}
#endif /* HAVE_STRUCT_KVM_REGS */
+
+#ifdef HAVE_STRUCT_KVM_SREGS
+static void
+kvm_ioctl_decode_regs_segment(const char *prefix,
+ const struct kvm_segment *const segment)
+{
+ tprints(prefix);
+ PRINT_FIELD_X("={", *segment, base);
+ PRINT_FIELD_U(", ", *segment, limit);
+ PRINT_FIELD_U(", ", *segment, selector);
+ PRINT_FIELD_U(", ", *segment, type);
+ PRINT_FIELD_U(", ", *segment, present);
+ PRINT_FIELD_U(", ", *segment, dpl);
+ PRINT_FIELD_U(", ", *segment, db);
+ PRINT_FIELD_U(", ", *segment, s);
+ PRINT_FIELD_U(", ", *segment, l);
+ PRINT_FIELD_U(", ", *segment, g);
+ PRINT_FIELD_U(", ", *segment, avl);
+ tprints("}");
+}
+
+static void
+kvm_ioctl_decode_regs_dtable(const char *prefix,
+ const struct kvm_dtable *const dtable)
+{
+ tprints(prefix);
+ PRINT_FIELD_X("={", *dtable, base);
+ PRINT_FIELD_U(", ", *dtable, limit);
+ tprints("}");
+}
+
+# define PRINT_FIELD_KVM_SREGS_STRUCT(prefix_, where_, type_, field_) \
+ kvm_ioctl_decode_regs_ ## type_(prefix_ #field_, &(where_)->field_)
+
+static void
+arch_print_kvm_sregs(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const struct kvm_sregs *const sregs)
+{
+ PRINT_FIELD_KVM_SREGS_STRUCT("{", sregs, segment, cs);
+ if (abbrev(tcp)) {
+ tprints(", ...}");
+ return;
+ }
+
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, segment, ds);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, segment, es);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, segment, fs);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, segment, gs);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, segment, ss);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, segment, tr);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, segment, ldt);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, dtable, gdt);
+ PRINT_FIELD_KVM_SREGS_STRUCT(", ", sregs, dtable, idt);
+ PRINT_FIELD_U(", ", *sregs, cr0);
+ PRINT_FIELD_U(", ", *sregs, cr2);
+ PRINT_FIELD_U(", ", *sregs, cr3);
+ PRINT_FIELD_U(", ", *sregs, cr4);
+ PRINT_FIELD_U(", ", *sregs, cr8);
+ PRINT_FIELD_U(", ", *sregs, efer);
+ PRINT_FIELD_X(", ", *sregs, apic_base);
+ tprints(", interrupt_bitmap=[");
+
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(sregs->interrupt_bitmap); i++) {
+ if (i != 0)
+ tprints(", ");
+ tprintf("%#" PRI__x64, sregs->interrupt_bitmap[i]);
+ }
+ tprints("]}");
+}
+#endif /* HAVE_STRUCT_KVM_SREGS */