diff mbox

[v3,3/9] monitor: ARM SMC events

Message ID 1462373480-20206-3-git-send-email-tamas@tklengyel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tamas K Lengyel May 4, 2016, 2:51 p.m. UTC
Add support for monitoring ARM SMC events. This patch only adds the required
bits to enable/disable monitoring and forwarding the event through vm_event.

Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>

v3: Split parts off as separate patches
    Union for arm32/64 register structs in vm_event
    Cosmetic fixes
---
 xen/arch/arm/monitor.c        | 49 +++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/traps.c          | 16 ++++++++++++--
 xen/include/asm-arm/domain.h  |  5 +++++
 xen/include/asm-arm/monitor.h | 24 ++++++---------------
 xen/include/public/domctl.h   |  1 +
 xen/include/public/vm_event.h |  2 ++
 6 files changed, 77 insertions(+), 20 deletions(-)

Comments

Razvan Cojocaru May 5, 2016, 9:36 a.m. UTC | #1
On 05/04/2016 05:51 PM, Tamas K Lengyel wrote:
> Add support for monitoring ARM SMC events. This patch only adds the required
> bits to enable/disable monitoring and forwarding the event through vm_event.
> 
> Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> 
> v3: Split parts off as separate patches
>     Union for arm32/64 register structs in vm_event
>     Cosmetic fixes
> ---
>  xen/arch/arm/monitor.c        | 49 +++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/traps.c          | 16 ++++++++++++--
>  xen/include/asm-arm/domain.h  |  5 +++++
>  xen/include/asm-arm/monitor.h | 24 ++++++---------------
>  xen/include/public/domctl.h   |  1 +
>  xen/include/public/vm_event.h |  2 ++
>  6 files changed, 77 insertions(+), 20 deletions(-)

The interface part looks alright, but I can't comment on the
ARM-specific bits. With that:

Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
Julien Grall May 16, 2016, 9:56 a.m. UTC | #2
Hi Tamas,

On 04/05/16 15:51, Tamas K Lengyel wrote:
> Add support for monitoring ARM SMC events. This patch only adds the required
> bits to enable/disable monitoring and forwarding the event through vm_event.
>
> Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
>
> v3: Split parts off as separate patches
>      Union for arm32/64 register structs in vm_event
>      Cosmetic fixes
> ---
>   xen/arch/arm/monitor.c        | 49 +++++++++++++++++++++++++++++++++++++++++++
>   xen/arch/arm/traps.c          | 16 ++++++++++++--
>   xen/include/asm-arm/domain.h  |  5 +++++
>   xen/include/asm-arm/monitor.h | 24 ++++++---------------
>   xen/include/public/domctl.h   |  1 +
>   xen/include/public/vm_event.h |  2 ++
>   6 files changed, 77 insertions(+), 20 deletions(-)
>
> diff --git a/xen/arch/arm/monitor.c b/xen/arch/arm/monitor.c
> index f957257..9c481ac 100644
> --- a/xen/arch/arm/monitor.c
> +++ b/xen/arch/arm/monitor.c
> @@ -22,6 +22,55 @@
>   #include <asm/vm_event.h>
>   #include <public/vm_event.h>
>
> +int arch_monitor_domctl_event(struct domain *d,
> +                              struct xen_domctl_monitor_op *mop)
> +{
> +    struct arch_domain *ad = &d->arch;
> +    bool_t requested_status = (XEN_DOMCTL_MONITOR_OP_ENABLE == mop->op);
> +
> +    switch ( mop->event )
> +    {
> +    case XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL:
> +    {
> +        bool_t old_status = ad->monitor.privileged_call_enabled;
> +
> +        if ( unlikely(old_status == requested_status) )
> +            return -EEXIST;
> +
> +        domain_pause(d);
> +        ad->monitor.privileged_call_enabled = requested_status;
> +        domain_unpause(d);
> +        break;
> +    }
> +
> +    default:
> +        /*
> +         * Should not be reached unless arch_monitor_get_capabilities() is
> +         * not properly implemented.
> +         */
> +        ASSERT_UNREACHABLE();
> +        return -EOPNOTSUPP;
> +    }
> +
> +    return 0;
> +}
> +
> +bool_t monitor_smc(const struct cpu_user_regs *regs) {

Coding style, the brace should be on a separate line.

> +    struct vcpu *curr = current;
> +    vm_event_request_t req = { 0 };
> +
> +    if ( !curr->domain->arch.monitor.privileged_call_enabled )
> +        return 0;
> +
> +    req.reason = VM_EVENT_REASON_PRIVILEGED_CALL;
> +    req.vcpu_id = curr->vcpu_id;
> +
> +    if ( vm_event_monitor_traps(curr, 1, &req) <= 0 )
> +        return 0;
> +    else
> +        return 1;
> +}
> +
>   void monitor_guest_request(void)
>   {
>       struct vcpu *curr = current;
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 9abfc3c..f26e12e 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -41,6 +41,7 @@
>   #include <asm/mmio.h>
>   #include <asm/cpufeature.h>
>   #include <asm/flushtlb.h>
> +#include <asm/monitor.h>
>
>   #include "decode.h"
>   #include "vtimer.h"
> @@ -2491,6 +2492,17 @@ bad_data_abort:
>       inject_dabt_exception(regs, info.gva, hsr.len);
>   }
>
> +static void do_trap_smc(struct cpu_user_regs *regs, const union hsr hsr)
> +{
> +    bool_t handled = 0;
> +
> +    if ( current->domain->arch.monitor.privileged_call_enabled )
> +        handled = monitor_smc(regs);
> +
> +    if ( handled != 1 )

handled is a boolean. So if ( !handled )

Regards,
diff mbox

Patch

diff --git a/xen/arch/arm/monitor.c b/xen/arch/arm/monitor.c
index f957257..9c481ac 100644
--- a/xen/arch/arm/monitor.c
+++ b/xen/arch/arm/monitor.c
@@ -22,6 +22,55 @@ 
 #include <asm/vm_event.h>
 #include <public/vm_event.h>
 
+int arch_monitor_domctl_event(struct domain *d,
+                              struct xen_domctl_monitor_op *mop)
+{
+    struct arch_domain *ad = &d->arch;
+    bool_t requested_status = (XEN_DOMCTL_MONITOR_OP_ENABLE == mop->op);
+
+    switch ( mop->event )
+    {
+    case XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL:
+    {
+        bool_t old_status = ad->monitor.privileged_call_enabled;
+
+        if ( unlikely(old_status == requested_status) )
+            return -EEXIST;
+
+        domain_pause(d);
+        ad->monitor.privileged_call_enabled = requested_status;
+        domain_unpause(d);
+        break;
+    }
+
+    default:
+        /*
+         * Should not be reached unless arch_monitor_get_capabilities() is
+         * not properly implemented.
+         */
+        ASSERT_UNREACHABLE();
+        return -EOPNOTSUPP;
+    }
+
+    return 0;
+}
+
+bool_t monitor_smc(const struct cpu_user_regs *regs) {
+    struct vcpu *curr = current;
+    vm_event_request_t req = { 0 };
+
+    if ( !curr->domain->arch.monitor.privileged_call_enabled )
+        return 0;
+
+    req.reason = VM_EVENT_REASON_PRIVILEGED_CALL;
+    req.vcpu_id = curr->vcpu_id;
+
+    if ( vm_event_monitor_traps(curr, 1, &req) <= 0 )
+        return 0;
+    else
+        return 1;
+}
+
 void monitor_guest_request(void)
 {
     struct vcpu *curr = current;
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 9abfc3c..f26e12e 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -41,6 +41,7 @@ 
 #include <asm/mmio.h>
 #include <asm/cpufeature.h>
 #include <asm/flushtlb.h>
+#include <asm/monitor.h>
 
 #include "decode.h"
 #include "vtimer.h"
@@ -2491,6 +2492,17 @@  bad_data_abort:
     inject_dabt_exception(regs, info.gva, hsr.len);
 }
 
+static void do_trap_smc(struct cpu_user_regs *regs, const union hsr hsr)
+{
+    bool_t handled = 0;
+
+    if ( current->domain->arch.monitor.privileged_call_enabled )
+        handled = monitor_smc(regs);
+
+    if ( handled != 1 )
+        inject_undef_exception(regs, hsr);
+}
+
 static void enter_hypervisor_head(struct cpu_user_regs *regs)
 {
     if ( guest_mode(regs) )
@@ -2566,7 +2578,7 @@  asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
          */
         GUEST_BUG_ON(!psr_mode_is_32bit(regs->cpsr));
         perfc_incr(trap_smc32);
-        inject_undef32_exception(regs);
+        do_trap_smc(regs, hsr);
         break;
     case HSR_EC_HVC32:
         GUEST_BUG_ON(!psr_mode_is_32bit(regs->cpsr));
@@ -2599,7 +2611,7 @@  asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
          */
         GUEST_BUG_ON(psr_mode_is_32bit(regs->cpsr));
         perfc_incr(trap_smc64);
-        inject_undef64_exception(regs, hsr.len);
+        do_trap_smc(regs, hsr);
         break;
     case HSR_EC_SYSREG:
         GUEST_BUG_ON(psr_mode_is_32bit(regs->cpsr));
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index c35ed40..87c7d7d 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -129,6 +129,11 @@  struct arch_domain
     paddr_t efi_acpi_gpa;
     paddr_t efi_acpi_len;
 #endif
+
+    /* Monitor options */
+    struct {
+        uint8_t privileged_call_enabled : 1;
+    } monitor;
 }  __cacheline_aligned;
 
 struct arch_vcpu
diff --git a/xen/include/asm-arm/monitor.h b/xen/include/asm-arm/monitor.h
index 3fd3c9d..9a10d1f 100644
--- a/xen/include/asm-arm/monitor.h
+++ b/xen/include/asm-arm/monitor.h
@@ -3,7 +3,7 @@ 
  *
  * Arch-specific monitor_op domctl handler.
  *
- * Copyright (c) 2015 Tamas K Lengyel (tamas@tklengyel.com)
+ * Copyright (c) 2015-2016 Tamas K Lengyel (tamas@tklengyel.com)
  * Copyright (c) 2016, Bitdefender S.R.L.
  *
  * This program is free software; you can redistribute it and/or
@@ -32,27 +32,15 @@  int arch_monitor_domctl_op(struct domain *d, struct xen_domctl_monitor_op *mop)
     return -EOPNOTSUPP;
 }
 
-static inline
 int arch_monitor_domctl_event(struct domain *d,
-                              struct xen_domctl_monitor_op *mop)
-{
-    /*
-     * No arch-specific monitor vm-events on ARM.
-     *
-     * Should not be reached unless arch_monitor_get_capabilities() is not
-     * properly implemented.
-     */
-    ASSERT_UNREACHABLE();
-    return -EOPNOTSUPP;
-}
+                              struct xen_domctl_monitor_op *mop);
 
 static inline uint32_t arch_monitor_get_capabilities(struct domain *d)
 {
-    uint32_t capabilities = 0;
-
-    capabilities = (1U << XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST);
-
-    return capabilities;
+    return (1U << XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST) |
+           (1U << XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL);
 }
 
+bool_t monitor_smc(const struct cpu_user_regs *regs);
+
 #endif /* __ASM_ARM_MONITOR_H__ */
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 2457698..35adce2 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -1080,6 +1080,7 @@  DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t);
 #define XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP            2
 #define XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT   3
 #define XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST         4
+#define XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL       5
 
 struct xen_domctl_monitor_op {
     uint32_t op; /* XEN_DOMCTL_MONITOR_OP_* */
diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h
index 9270d52..3acf217 100644
--- a/xen/include/public/vm_event.h
+++ b/xen/include/public/vm_event.h
@@ -119,6 +119,8 @@ 
 #define VM_EVENT_REASON_SINGLESTEP              7
 /* An event has been requested via HVMOP_guest_request_vm_event. */
 #define VM_EVENT_REASON_GUEST_REQUEST           8
+/* Privileged call executed (e.g. SMC) */
+#define VM_EVENT_REASON_PRIVILEGED_CALL         9
 
 /* Supported values for the vm_event_write_ctrlreg index. */
 #define VM_EVENT_X86_CR0    0