diff mbox series

[v6,09/51] i386/xen: handle guest hypercalls

Message ID 20230110122042.1562155-10-dwmw2@infradead.org
State New
Headers show
Series Xen support under KVM | expand

Commit Message

David Woodhouse Jan. 10, 2023, 12:20 p.m. UTC
From: Joao Martins <joao.m.martins@oracle.com>

This means handling the new exit reason for Xen but still
crashing on purpose. As we implement each of the hypercalls
we will then return the right return code.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
[dwmw2: Add CPL to hypercall tracing, disallow hypercalls from CPL > 0]
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 target/i386/kvm/kvm.c        |  5 ++++
 target/i386/kvm/trace-events |  3 +++
 target/i386/kvm/xen-emu.c    | 44 ++++++++++++++++++++++++++++++++++++
 target/i386/kvm/xen-emu.h    |  1 +
 4 files changed, 53 insertions(+)

Comments

Paul Durrant Jan. 16, 2023, 4:24 p.m. UTC | #1
On 10/01/2023 12:20, David Woodhouse wrote:
> From: Joao Martins <joao.m.martins@oracle.com>
> 
> This means handling the new exit reason for Xen but still
> crashing on purpose. As we implement each of the hypercalls
> we will then return the right return code.
> 
> Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
> [dwmw2: Add CPL to hypercall tracing, disallow hypercalls from CPL > 0]
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
>   target/i386/kvm/kvm.c        |  5 ++++
>   target/i386/kvm/trace-events |  3 +++
>   target/i386/kvm/xen-emu.c    | 44 ++++++++++++++++++++++++++++++++++++
>   target/i386/kvm/xen-emu.h    |  1 +
>   4 files changed, 53 insertions(+)
> 
> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index 4ab2c08af6..7cbfbed492 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -5477,6 +5477,11 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
>           assert(run->msr.reason == KVM_MSR_EXIT_REASON_FILTER);
>           ret = kvm_handle_wrmsr(cpu, run);
>           break;
> +#ifdef CONFIG_XEN_EMU
> +    case KVM_EXIT_XEN:
> +        ret = kvm_xen_handle_exit(cpu, &run->xen);
> +        break;
> +#endif
>       default:
>           fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
>           ret = -1;
> diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
> index 7c369db1e1..cd6f842b1f 100644
> --- a/target/i386/kvm/trace-events
> +++ b/target/i386/kvm/trace-events
> @@ -5,3 +5,6 @@ kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %"
>   kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
>   kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
>   kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
> +
> +# xen-emu.c
> +kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64
> diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
> index 4883b95d9d..476f464ee2 100644
> --- a/target/i386/kvm/xen-emu.c
> +++ b/target/i386/kvm/xen-emu.c
> @@ -10,10 +10,12 @@
>    */
>   
>   #include "qemu/osdep.h"
> +#include "qemu/log.h"
>   #include "sysemu/kvm_int.h"
>   #include "sysemu/kvm_xen.h"
>   #include "kvm/kvm_i386.h"
>   #include "xen-emu.h"
> +#include "trace.h"
>   
>   int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>   {
> @@ -84,3 +86,45 @@ uint32_t kvm_xen_get_caps(void)
>   {
>       return kvm_state->xen_caps;
>   }
> +
> +static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
> +{
> +    uint16_t code = exit->u.hcall.input;
> +
> +    if (exit->u.hcall.cpl > 0) {
> +        exit->u.hcall.result = -EPERM;
> +        return true;
> +    }
> +
> +    switch (code) {
> +    default:
> +        return false;
> +    }
> +}
> +
> +int kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
> +{
> +    if (exit->type != KVM_EXIT_XEN_HCALL) {
> +        return -1;
> +    }
> +
> +    if (!do_kvm_xen_handle_exit(cpu, exit)) {
> +        /*
> +         * Some hypercalls will be deliberately "implemented" by returning
> +         * -ENOSYS. This case is for hypercalls which are unexpected.
> +         */
> +        exit->u.hcall.result = -ENOSYS;
> +        qemu_log_mask(LOG_UNIMP, "Unimplemented Xen hypercall %"
> +                      PRId64 " (0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 ")\n",
> +                      (uint64_t)exit->u.hcall.input,
> +                      (uint64_t)exit->u.hcall.params[0],
> +                      (uint64_t)exit->u.hcall.params[1],
> +                      (uint64_t)exit->u.hcall.params[2]);
> +    }
> +
> +    trace_kvm_xen_hypercall(CPU(cpu)->cpu_index, exit->u.hcall.cpl,
> +                            exit->u.hcall.input, exit->u.hcall.params[0],
> +                            exit->u.hcall.params[1], exit->u.hcall.params[2],
> +                            exit->u.hcall.result);

It seems odd to have the trace message after the hypercall is handled. 
Any additional tracing in the handler if going to come out before we're 
told what hypercall it is.

   Paul

> +    return 0;
> +}
> diff --git a/target/i386/kvm/xen-emu.h b/target/i386/kvm/xen-emu.h
> index d62f1d8ed8..21faf6bf38 100644
> --- a/target/i386/kvm/xen-emu.h
> +++ b/target/i386/kvm/xen-emu.h
> @@ -25,5 +25,6 @@
>   
>   int kvm_xen_init(KVMState *s, uint32_t hypercall_msr);
>   int kvm_xen_init_vcpu(CPUState *cs);
> +int kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit);
>   
>   #endif /* QEMU_I386_KVM_XEN_EMU_H */
David Woodhouse Jan. 16, 2023, 5:57 p.m. UTC | #2
On Mon, 2023-01-16 at 16:24 +0000, Paul Durrant wrote:
> > +    trace_kvm_xen_hypercall(CPU(cpu)->cpu_index, exit->u.hcall.cpl,
> > +                            exit->u.hcall.input, exit->u.hcall.params[0],
> > +                            exit->u.hcall.params[1], exit->u.hcall.params[2],
> > +                            exit->u.hcall.result);
> 
> It seems odd to have the trace message after the hypercall is handled. 
> Any additional tracing in the handler if going to come out before we're 
> told what hypercall it is.

Well yeah, but if we do it sooner then we don't have the result, and
end up with two separate trace lines to print the result too.
diff mbox series

Patch

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 4ab2c08af6..7cbfbed492 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -5477,6 +5477,11 @@  int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
         assert(run->msr.reason == KVM_MSR_EXIT_REASON_FILTER);
         ret = kvm_handle_wrmsr(cpu, run);
         break;
+#ifdef CONFIG_XEN_EMU
+    case KVM_EXIT_XEN:
+        ret = kvm_xen_handle_exit(cpu, &run->xen);
+        break;
+#endif
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
index 7c369db1e1..cd6f842b1f 100644
--- a/target/i386/kvm/trace-events
+++ b/target/i386/kvm/trace-events
@@ -5,3 +5,6 @@  kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %"
 kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
 kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
 kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
+
+# xen-emu.c
+kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 4883b95d9d..476f464ee2 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -10,10 +10,12 @@ 
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "sysemu/kvm_int.h"
 #include "sysemu/kvm_xen.h"
 #include "kvm/kvm_i386.h"
 #include "xen-emu.h"
+#include "trace.h"
 
 int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
 {
@@ -84,3 +86,45 @@  uint32_t kvm_xen_get_caps(void)
 {
     return kvm_state->xen_caps;
 }
+
+static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
+{
+    uint16_t code = exit->u.hcall.input;
+
+    if (exit->u.hcall.cpl > 0) {
+        exit->u.hcall.result = -EPERM;
+        return true;
+    }
+
+    switch (code) {
+    default:
+        return false;
+    }
+}
+
+int kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
+{
+    if (exit->type != KVM_EXIT_XEN_HCALL) {
+        return -1;
+    }
+
+    if (!do_kvm_xen_handle_exit(cpu, exit)) {
+        /*
+         * Some hypercalls will be deliberately "implemented" by returning
+         * -ENOSYS. This case is for hypercalls which are unexpected.
+         */
+        exit->u.hcall.result = -ENOSYS;
+        qemu_log_mask(LOG_UNIMP, "Unimplemented Xen hypercall %"
+                      PRId64 " (0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 ")\n",
+                      (uint64_t)exit->u.hcall.input,
+                      (uint64_t)exit->u.hcall.params[0],
+                      (uint64_t)exit->u.hcall.params[1],
+                      (uint64_t)exit->u.hcall.params[2]);
+    }
+
+    trace_kvm_xen_hypercall(CPU(cpu)->cpu_index, exit->u.hcall.cpl,
+                            exit->u.hcall.input, exit->u.hcall.params[0],
+                            exit->u.hcall.params[1], exit->u.hcall.params[2],
+                            exit->u.hcall.result);
+    return 0;
+}
diff --git a/target/i386/kvm/xen-emu.h b/target/i386/kvm/xen-emu.h
index d62f1d8ed8..21faf6bf38 100644
--- a/target/i386/kvm/xen-emu.h
+++ b/target/i386/kvm/xen-emu.h
@@ -25,5 +25,6 @@ 
 
 int kvm_xen_init(KVMState *s, uint32_t hypercall_msr);
 int kvm_xen_init_vcpu(CPUState *cs);
+int kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit);
 
 #endif /* QEMU_I386_KVM_XEN_EMU_H */