]> granicus.if.org Git - strace/commitdiff
kvm: decode the argument of KVM_{SET, GET}_SREGS ioctl command
authorMasatake YAMATO <yamato@redhat.com>
Mon, 4 Dec 2017 13:08:16 +0000 (22:08 +0900)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 4 Dec 2017 18:29:38 +0000 (18:29 +0000)
* 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>
configure.ac
kvm.c
linux/arch_kvm.c
linux/x86_64/arch_kvm.c

index 9a3646acaf724ff70230097e16bc6d4d3a0c66cb..729ef3f7d397795e18232e23a80aef4a4acc4dc3 100644 (file)
@@ -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 2d5962c29c0d442f30a5824ae6ab7a499d0ed077..86fd9e50918668d90e97244d63250e6658c73cbe 100644 (file)
--- 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:
index d1292a5b15ffea2491f168d904c8c90631bc78d2..f12f32ab4f30dcc7fc4996876fced9d2803550c6 100644 (file)
@@ -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 */
index f5ade5d8939d58dcb2e00ca52df7426d50a1cc94..f0075cae5a7f045ed2504ff395c38f40101d7703 100644 (file)
@@ -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 */