All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] hvm/svm: Implement Debug events
@ 2018-03-21 14:47 Alexandru Isaila
  2018-03-21 14:56 ` Andrew Cooper
  2018-03-21 14:57 ` Jan Beulich
  0 siblings, 2 replies; 6+ messages in thread
From: Alexandru Isaila @ 2018-03-21 14:47 UTC (permalink / raw)
  To: xen-devel
  Cc: tamas, suravee.suthikulpanit, rcojocaru, andrew.cooper3,
	jbeulich, Alexandru Isaila, boris.ostrovsky

At this moment the Debug events for the AMD architecture are not
forwarded to the monitor layer.

This patch adds the Debug event to the common capabilities, adds
the VMEXIT_ICEBP then forwards the event to the monitor layer.

Chapter 2: SVM Processor and Platform Extensions: "Note: A vector 1
exception generated by the single byte INT1
instruction (also known as ICEBP) does not trigger the #DB
intercept. Software should use the dedicated ICEBP
intercept to intercept ICEBP"

---
Changes since V2:
	- Moved INSTR_ICEBP entry in opc_tab
	- Added mechanism to enable/disable icebp interception
	- Changed trap_type to unsigned int
	- Replaced svm_propagate_intr with hvm_inject_exception

Signed-off-by: Alexandru Isaila <aisaila@bitdefender.com>
---
 xen/arch/x86/hvm/svm/emulate.c        |  1 +
 xen/arch/x86/hvm/svm/svm.c            | 71 +++++++++++++++++++++++++++--------
 xen/arch/x86/monitor.c                |  6 +++
 xen/include/asm-x86/hvm/hvm.h         | 36 ++++++++++++++++++
 xen/include/asm-x86/hvm/svm/emulate.h |  1 +
 xen/include/asm-x86/monitor.h         |  4 +-
 6 files changed, 101 insertions(+), 18 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/emulate.c b/xen/arch/x86/hvm/svm/emulate.c
index e1a1581..535674e 100644
--- a/xen/arch/x86/hvm/svm/emulate.c
+++ b/xen/arch/x86/hvm/svm/emulate.c
@@ -65,6 +65,7 @@ static const struct {
 } opc_tab[INSTR_MAX_COUNT] = {
     [INSTR_PAUSE]   = { X86EMUL_OPC_F3(0, 0x90) },
     [INSTR_INT3]    = { X86EMUL_OPC(   0, 0xcc) },
+    [INSTR_ICEBP]   = { X86EMUL_OPC(   0, 0xf1) },
     [INSTR_HLT]     = { X86EMUL_OPC(   0, 0xf4) },
     [INSTR_XSETBV]  = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 2, 1) },
     [INSTR_VMRUN]   = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 0) },
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index c34f5b5..5717efd 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -172,6 +172,34 @@ static void svm_enable_msr_interception(struct domain *d, uint32_t msr)
         svm_intercept_msr(v, msr, MSR_INTERCEPT_WRITE);
 }
 
+static void svm_enable_icebp_interception(struct domain *d)
+{
+    struct vcpu *v;
+
+    for_each_vcpu ( d, v )
+    {
+        struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+        uint32_t intercepts = vmcb_get_general2_intercepts(vmcb);
+
+        intercepts |= GENERAL2_INTERCEPT_ICEBP;
+        vmcb_set_general2_intercepts(vmcb, intercepts);
+    }
+}
+
+static void svm_disable_icebp_interception(struct domain *d)
+{
+    struct vcpu *v;
+
+    for_each_vcpu ( d, v )
+    {
+        struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+        uint32_t intercepts = vmcb_get_general2_intercepts(vmcb);
+
+        intercepts &= ~GENERAL2_INTERCEPT_ICEBP;
+        vmcb_set_general2_intercepts(vmcb, intercepts);
+    }
+}
+
 static void svm_save_dr(struct vcpu *v)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -1109,7 +1137,8 @@ static void noreturn svm_do_resume(struct vcpu *v)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     bool debug_state = (v->domain->debugger_attached ||
-                        v->domain->arch.monitor.software_breakpoint_enabled);
+                        v->domain->arch.monitor.software_breakpoint_enabled ||
+                        v->domain->arch.monitor.debug_exception_enabled);
     bool_t vcpu_guestmode = 0;
     struct vlapic *vlapic = vcpu_vlapic(v);
 
@@ -2438,19 +2467,6 @@ static bool svm_get_pending_event(struct vcpu *v, struct x86_event *info)
     return true;
 }
 
-static void svm_propagate_intr(struct vcpu *v, unsigned long insn_len)
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    struct x86_event event = {
-        .vector = vmcb->eventinj.fields.type,
-        .type = vmcb->eventinj.fields.type,
-        .error_code = vmcb->exitinfo1,
-    };
-
-    event.insn_len = insn_len;
-    hvm_inject_event(&event);
-}
-
 static struct hvm_function_table __initdata svm_function_table = {
     .name                 = "SVM",
     .cpu_up_prepare       = svm_cpu_up_prepare,
@@ -2490,6 +2506,8 @@ static struct hvm_function_table __initdata svm_function_table = {
     .msr_read_intercept   = svm_msr_read_intercept,
     .msr_write_intercept  = svm_msr_write_intercept,
     .enable_msr_interception = svm_enable_msr_interception,
+    .enable_icebp_interception = svm_enable_icebp_interception,
+    .disable_icebp_interception = svm_disable_icebp_interception,
     .set_rdtsc_exiting    = svm_set_rdtsc_exiting,
     .set_descriptor_access_exiting = svm_set_descriptor_access_exiting,
     .get_insn_bytes       = svm_get_insn_bytes,
@@ -2656,9 +2674,28 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
         HVMTRACE_0D(SMI);
         break;
 
+    case VMEXIT_ICEBP:
     case VMEXIT_EXCEPTION_DB:
         if ( !v->domain->debugger_attached )
-            hvm_inject_hw_exception(TRAP_debug, X86_EVENT_NO_EC);
+        {
+            int rc;
+            unsigned int trap_type = exit_reason == VMEXIT_ICEBP ?
+                X86_EVENTTYPE_PRI_SW_EXCEPTION : X86_EVENTTYPE_HW_EXCEPTION;
+
+            inst_len = 0;
+
+            if ( trap_type >= X86_EVENTTYPE_SW_INTERRUPT )
+                inst_len = __get_instruction_length(v, INSTR_ICEBP);
+
+            rc = hvm_monitor_debug(regs->rip,
+                                   HVM_MONITOR_DEBUG_EXCEPTION,
+                                   trap_type, inst_len);
+            if ( rc < 0 )
+                goto unexpected_exit_type;
+            if ( !rc )
+                hvm_inject_exception(TRAP_debug,
+                                     trap_type, inst_len, X86_EVENT_NO_EC);
+        }
         else
             domain_pause_for_debugger();
         break;
@@ -2687,7 +2724,9 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
            if ( rc < 0 )
                goto unexpected_exit_type;
            if ( !rc )
-               svm_propagate_intr(v, inst_len);
+               hvm_inject_exception(TRAP_int3,
+                                    X86_EVENTTYPE_SW_EXCEPTION,
+                                    inst_len, X86_EVENT_NO_EC);
         }
         break;
 
diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
index 4317658..3b3af4b 100644
--- a/xen/arch/x86/monitor.c
+++ b/xen/arch/x86/monitor.c
@@ -288,6 +288,12 @@ int arch_monitor_domctl_event(struct domain *d,
         ad->monitor.debug_exception_sync = requested_status ?
                                             mop->u.debug_exception.sync :
                                             0;
+
+        if ( requested_status )
+            hvm_enable_icebp_interception(d);
+        else
+            hvm_disable_icebp_interception(d);
+
         domain_unpause(d);
         break;
     }
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 2376ed6..8d8c325 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -209,6 +209,8 @@ struct hvm_function_table {
                                 bool_t access_w, bool_t access_x);
 
     void (*enable_msr_interception)(struct domain *d, uint32_t msr);
+    void (*enable_icebp_interception)(struct domain *d);
+    void (*disable_icebp_interception)(struct domain *d);
     bool_t (*is_singlestep_supported)(void);
 
     /* Alternate p2m */
@@ -407,6 +409,20 @@ void hvm_migrate_pirqs(struct vcpu *v);
 
 void hvm_inject_event(const struct x86_event *event);
 
+static inline void hvm_inject_exception(
+    unsigned int vector, unsigned int type,
+    unsigned int insn_len,int error_code)
+{
+    struct x86_event event = {
+        .vector = vector,
+        .type = type,
+        .insn_len = insn_len,
+        .error_code = error_code,
+    };
+
+    hvm_inject_event(&event);
+}
+
 static inline void hvm_inject_hw_exception(unsigned int vector, int errcode)
 {
     struct x86_event event = {
@@ -581,6 +597,26 @@ static inline bool_t hvm_enable_msr_interception(struct domain *d, uint32_t msr)
     return 0;
 }
 
+static inline bool_t hvm_enable_icebp_interception(struct domain *d)
+{
+    if( hvm_funcs.enable_icebp_interception )
+    {
+        hvm_funcs.enable_icebp_interception(d);
+        return 1;
+    }
+    return 0;
+}
+
+static inline bool_t hvm_disable_icebp_interception(struct domain *d)
+{
+    if( hvm_funcs.disable_icebp_interception )
+    {
+        hvm_funcs.disable_icebp_interception(d);
+        return 1;
+    }
+    return 0;
+}
+
 static inline bool_t hvm_is_singlestep_supported(void)
 {
     return (hvm_funcs.is_singlestep_supported &&
diff --git a/xen/include/asm-x86/hvm/svm/emulate.h b/xen/include/asm-x86/hvm/svm/emulate.h
index 7c1dcd1..3de8236 100644
--- a/xen/include/asm-x86/hvm/svm/emulate.h
+++ b/xen/include/asm-x86/hvm/svm/emulate.h
@@ -38,6 +38,7 @@ enum instruction_index {
     INSTR_STGI,
     INSTR_CLGI,
     INSTR_INVLPGA,
+    INSTR_ICEBP,
     INSTR_MAX_COUNT /* Must be last - Number of instructions supported */
 };
 
diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h
index 99ed4b87..c5a86d1 100644
--- a/xen/include/asm-x86/monitor.h
+++ b/xen/include/asm-x86/monitor.h
@@ -82,12 +82,12 @@ static inline uint32_t arch_monitor_get_capabilities(struct domain *d)
                     (1U << XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR) |
                     (1U << XEN_DOMCTL_MONITOR_EVENT_INTERRUPT) |
                     (1U << XEN_DOMCTL_MONITOR_EVENT_CPUID) |
+                    (1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) |
                     (1U << XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG));
 
     if ( cpu_has_vmx )
     {
-        capabilities |= ((1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) |
-                         (1U << XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED));
+        capabilities |= (1U << XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED);
 
         /* Since we know this is on VMX, we can just call the hvm func */
         if ( hvm_is_singlestep_supported() )
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v3] hvm/svm: Implement Debug events
  2018-03-21 14:47 [PATCH v3] hvm/svm: Implement Debug events Alexandru Isaila
@ 2018-03-21 14:56 ` Andrew Cooper
  2018-03-21 14:57 ` Jan Beulich
  1 sibling, 0 replies; 6+ messages in thread
From: Andrew Cooper @ 2018-03-21 14:56 UTC (permalink / raw)
  To: Alexandru Isaila, xen-devel
  Cc: boris.ostrovsky, tamas, jbeulich, suravee.suthikulpanit, rcojocaru

On 21/03/18 14:47, Alexandru Isaila wrote:
> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
> index 2376ed6..8d8c325 100644
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -209,6 +209,8 @@ struct hvm_function_table {
>                                  bool_t access_w, bool_t access_x);
>  
>      void (*enable_msr_interception)(struct domain *d, uint32_t msr);
> +    void (*enable_icebp_interception)(struct domain *d);
> +    void (*disable_icebp_interception)(struct domain *d);
>      bool_t (*is_singlestep_supported)(void);
>  
>      /* Alternate p2m */
> @@ -407,6 +409,20 @@ void hvm_migrate_pirqs(struct vcpu *v);
>  
>  void hvm_inject_event(const struct x86_event *event);
>  
> +static inline void hvm_inject_exception(
> +    unsigned int vector, unsigned int type,
> +    unsigned int insn_len,int error_code)

Space after comma.

> +{
> +    struct x86_event event = {
> +        .vector = vector,
> +        .type = type,
> +        .insn_len = insn_len,
> +        .error_code = error_code,
> +    };
> +
> +    hvm_inject_event(&event);
> +}
> +
>  static inline void hvm_inject_hw_exception(unsigned int vector, int errcode)
>  {
>      struct x86_event event = {
> @@ -581,6 +597,26 @@ static inline bool_t hvm_enable_msr_interception(struct domain *d, uint32_t msr)
>      return 0;
>  }
>  
> +static inline bool_t hvm_enable_icebp_interception(struct domain *d)

bool.

Both can be fixed on commit, and everything else looks ok, so
Revewed-by: Andrew Cooper <andrew.cooper3@citrix.com>

I've got a plan which will remove these enable/disable hooks, but we
need a bit more infrastructure from my CPUID series before they can go.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3] hvm/svm: Implement Debug events
  2018-03-21 14:47 [PATCH v3] hvm/svm: Implement Debug events Alexandru Isaila
  2018-03-21 14:56 ` Andrew Cooper
@ 2018-03-21 14:57 ` Jan Beulich
  2018-03-21 15:57   ` Alexandru Stefan ISAILA
  2018-03-21 16:00   ` Alexandru Stefan ISAILA
  1 sibling, 2 replies; 6+ messages in thread
From: Jan Beulich @ 2018-03-21 14:57 UTC (permalink / raw)
  To: Alexandru Isaila
  Cc: tamas, rcojocaru, andrew.cooper3, xen-devel,
	suravee.suthikulpanit, boris.ostrovsky

>>> On 21.03.18 at 15:47, <aisaila@bitdefender.com> wrote:
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -209,6 +209,8 @@ struct hvm_function_table {
>                                  bool_t access_w, bool_t access_x);
>  
>      void (*enable_msr_interception)(struct domain *d, uint32_t msr);
> +    void (*enable_icebp_interception)(struct domain *d);
> +    void (*disable_icebp_interception)(struct domain *d);

Why two new hooks when one (with a boolean parameter)
would do?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3] hvm/svm: Implement Debug events
  2018-03-21 14:57 ` Jan Beulich
@ 2018-03-21 15:57   ` Alexandru Stefan ISAILA
  2018-03-21 16:00   ` Alexandru Stefan ISAILA
  1 sibling, 0 replies; 6+ messages in thread
From: Alexandru Stefan ISAILA @ 2018-03-21 15:57 UTC (permalink / raw)
  To: JBeulich
  Cc: tamas, rcojocaru, andrew.cooper3, xen-devel,
	suravee.suthikulpanit, boris.ostrovsky

On Mi, 2018-03-21 at 08:57 -0600, Jan Beulich wrote:
> >
> > >
> > > >
> > > > On 21.03.18 at 15:47, <aisaila@bitdefender.com> wrote:
> > --- a/xen/include/asm-x86/hvm/hvm.h
> > +++ b/xen/include/asm-x86/hvm/hvm.h
> > @@ -209,6 +209,8 @@ struct hvm_function_table {
> >                                  bool_t access_w, bool_t access_x);
> >
> >      void (*enable_msr_interception)(struct domain *d, uint32_t
> > msr);
> > +    void (*enable_icebp_interception)(struct domain *d);
> > +    void (*disable_icebp_interception)(struct domain *d);
> Why two new hooks when one (with a boolean parameter)
> would do?
>
> Jan
>
I'll merge them in one with a bool parameter

Alex

________________________
This email was scanned by Bitdefender
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3] hvm/svm: Implement Debug events
  2018-03-21 14:57 ` Jan Beulich
  2018-03-21 15:57   ` Alexandru Stefan ISAILA
@ 2018-03-21 16:00   ` Alexandru Stefan ISAILA
  2018-03-21 16:56     ` Jan Beulich
  1 sibling, 1 reply; 6+ messages in thread
From: Alexandru Stefan ISAILA @ 2018-03-21 16:00 UTC (permalink / raw)
  To: JBeulich
  Cc: tamas, rcojocaru, andrew.cooper3, xen-devel,
	suravee.suthikulpanit, boris.ostrovsky

On Mi, 2018-03-21 at 08:57 -0600, Jan Beulich wrote:
> >
> > >
> > > >
> > > > On 21.03.18 at 15:47, <aisaila@bitdefender.com> wrote:
> > --- a/xen/include/asm-x86/hvm/hvm.h
> > +++ b/xen/include/asm-x86/hvm/hvm.h
> > @@ -209,6 +209,8 @@ struct hvm_function_table {
> >                                  bool_t access_w, bool_t access_x);
> >
> >      void (*enable_msr_interception)(struct domain *d, uint32_t
> > msr);
> > +    void (*enable_icebp_interception)(struct domain *d);
> > +    void (*disable_icebp_interception)(struct domain *d);
> Why two new hooks when one (with a boolean parameter)
> would do?
>
> Jan
>
>
Would update_icebp_interception() be a suitable name for the hook?

Thanks,
Alex

________________________
This email was scanned by Bitdefender
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3] hvm/svm: Implement Debug events
  2018-03-21 16:00   ` Alexandru Stefan ISAILA
@ 2018-03-21 16:56     ` Jan Beulich
  0 siblings, 0 replies; 6+ messages in thread
From: Jan Beulich @ 2018-03-21 16:56 UTC (permalink / raw)
  To: Alexandru Stefan ISAILA
  Cc: tamas, rcojocaru, andrew.cooper3, xen-devel,
	suravee.suthikulpanit, boris.ostrovsky

>>> On 21.03.18 at 17:00, <aisaila@bitdefender.com> wrote:
> On Mi, 2018-03-21 at 08:57 -0600, Jan Beulich wrote:
>> >
>> > >
>> > > >
>> > > > On 21.03.18 at 15:47, <aisaila@bitdefender.com> wrote:
>> > --- a/xen/include/asm-x86/hvm/hvm.h
>> > +++ b/xen/include/asm-x86/hvm/hvm.h
>> > @@ -209,6 +209,8 @@ struct hvm_function_table {
>> >                                  bool_t access_w, bool_t access_x);
>> >
>> >      void (*enable_msr_interception)(struct domain *d, uint32_t
>> > msr);
>> > +    void (*enable_icebp_interception)(struct domain *d);
>> > +    void (*disable_icebp_interception)(struct domain *d);
>> Why two new hooks when one (with a boolean parameter)
>> would do?
>>
> Would update_icebp_interception() be a suitable name for the hook?

"update" or "set" would both seem fine to me.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-03-21 16:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-21 14:47 [PATCH v3] hvm/svm: Implement Debug events Alexandru Isaila
2018-03-21 14:56 ` Andrew Cooper
2018-03-21 14:57 ` Jan Beulich
2018-03-21 15:57   ` Alexandru Stefan ISAILA
2018-03-21 16:00   ` Alexandru Stefan ISAILA
2018-03-21 16:56     ` Jan Beulich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.