diff mbox

[Xen-devel,3/4] xen/arm: Implement a dummy debug monitor for ARM32

Message ID 1398379556-1132-4-git-send-email-julien.grall@linaro.org
State Accepted, archived
Headers show

Commit Message

Julien Grall April 24, 2014, 10:45 p.m. UTC
XSA-93 (commit 0b18220 "xen/arm: Don't let guess access to Debug and Performance
Monitors registers") disable Debug Registers access.

When CONFIG_PERF_EVENTS is enabled in the Linux Kernel, it will try to
initialize the debug monitors. If an error occured Linux won't use this
feature.

The implementation made Xen expose a minimal set of registers which let think
the guest (i.e.) thinks HW debug won't work.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    This commit is candidate for backporting on Xen 4.4. Distribution may
    enable HW DEBUG (e.g. Linaro Ubuntu image), therefore Linux will try
    to initialize it.
---
 xen/arch/arm/traps.c         |   77 ++++++++++++++++++++++++++++++++++++++++--
 xen/include/asm-arm/cpregs.h |   14 ++++++++
 2 files changed, 89 insertions(+), 2 deletions(-)

Comments

Ian Campbell May 2, 2014, 11:09 a.m. UTC | #1
On Thu, 2014-04-24 at 23:45 +0100, Julien Grall wrote:
> XSA-93 (commit 0b18220 "xen/arm: Don't let guess access to Debug and Performance
> Monitors registers") disable Debug Registers access.
> 
> When CONFIG_PERF_EVENTS is enabled in the Linux Kernel, it will try to
> initialize the debug monitors. If an error occured Linux won't use this
> feature.
> 
> The implementation made Xen expose a minimal set of registers which let think
> the guest (i.e.) thinks HW debug won't work.

Why only for arm32?

I think arm64 makes more use than arm32 (unconditionally touches
MDSCR_EL1 on the ctx switch path).

I think we should be considering allow the guest to access these and
context switching them instead.

> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> ---
>     This commit is candidate for backporting on Xen 4.4. Distribution may
>     enable HW DEBUG (e.g. Linaro Ubuntu image), therefore Linux will try
>     to initialize it.
> ---
>  xen/arch/arm/traps.c         |   77 ++++++++++++++++++++++++++++++++++++++++--
>  xen/include/asm-arm/cpregs.h |   14 ++++++++
>  2 files changed, 89 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 319bbe9..1f61e6e 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -1468,7 +1468,76 @@ static void do_cp15_64(struct cpu_user_regs *regs,
>      advance_pc(regs, hsr);
>  }
>  
> -static void do_cp14(struct cpu_user_regs *regs, union hsr hsr)
> +static void do_cp14_32(struct cpu_user_regs *regs, union hsr hsr)
> +{
> +    struct hsr_cp32 cp32 = hsr.cp32;
> +    uint32_t *r = (uint32_t *)select_user_reg(regs, cp32.reg);
> +    struct domain *d = current->domain;
> +
> +    if ( !check_conditional_instr(regs, hsr) )
> +    {
> +        advance_pc(regs, hsr);
> +        return;
> +    }
> +
> +    switch ( hsr.bits & HSR_CP32_REGS_MASK )
> +    {
> +    case HSR_CPREG32(DBGDIDR):
> +
> +        /* Read-only register */
> +        if ( !cp32.read )
> +            goto bad_cp;
> +
> +        /* Implement the minimum requirements:
> +         *  - Number of watchpoints: 1
> +         *  - Number of breakpoints: 2
> +         *  - Version: ARMv7 v7.1
> +         *  - Variant and Revision bits match MDIR
> +         */
> +        *r = (1 << 24) | (5 << 16);
> +        *r |= ((d->arch.vpidr >> 20) & 0xf) | (d->arch.vpidr & 0xf);
> +        break;
> +
> +    case HSR_CPREG32(DBGDSCRINT):
> +    case HSR_CPREG32(DBGDSCREXT):
> +        /* Implement debug status and control register as RAZ/WI.
> +         * The OS won't use Hardware debug if MDBGen not set
> +         */
> +        if ( cp32.read )
> +           *r = 0;
> +        break;
> +    case HSR_CPREG32(DBGVCR):
> +    case HSR_CPREG32(DBGOSLAR):
> +    case HSR_CPREG32(DBGBVR0):
> +    case HSR_CPREG32(DBGCR0):
> +    case HSR_CPREG32(DBGWVR0):
> +    case HSR_CPREG32(DBGWCR0):
> +    case HSR_CPREG32(DBGBVR1):
> +    case HSR_CPREG32(DBGCR1):
> +    case HSR_CPREG32(DBGOSDLR):
> +        /* RAZ/WI */
> +        if ( cp32.read )
> +            *r = 0;
> +        break;
> +
> +    default:
> +bad_cp:
> +#ifndef NDEBUG
> +        gdprintk(XENLOG_ERR,
> +                 "%s p14, %d, r%d, cr%d, cr%d, %d @ 0x%"PRIregister"\n",
> +                  cp32.read ? "mrc" : "mcr",
> +                  cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
> +        gdprintk(XENLOG_ERR, "unhandled 32-bit cp14 access %#x\n",
> +                 hsr.bits & HSR_CP32_REGS_MASK);
> +#endif
> +        inject_undef32_exception(regs);
> +        return;
> +    }
> +
> +    advance_pc(regs, hsr);
> +}
> +
> +static void do_cp14_dbg(struct cpu_user_regs *regs, union hsr hsr)
>  {
>      if ( !check_conditional_instr(regs, hsr) )
>      {
> @@ -1720,10 +1789,14 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
>          do_cp15_64(regs, hsr);
>          break;
>      case HSR_EC_CP14_32:
> +        if ( !is_32bit_domain(current->domain) )
> +            goto bad_trap;
> +        do_cp14_32(regs, hsr);
> +        break;
>      case HSR_EC_CP14_DBG:
>          if ( !is_32bit_domain(current->domain) )
>              goto bad_trap;
> -        do_cp14(regs, hsr);
> +        do_cp14_dbg(regs, hsr);
>          break;
>      case HSR_EC_CP:
>          if ( !is_32bit_domain(current->domain) )
> diff --git a/xen/include/asm-arm/cpregs.h b/xen/include/asm-arm/cpregs.h
> index f44e3b5..306e506 100644
> --- a/xen/include/asm-arm/cpregs.h
> +++ b/xen/include/asm-arm/cpregs.h
> @@ -71,6 +71,20 @@
>  
>  /* Coprocessor 14 */
>  
> +/* CP14 0: Debug Register interface */
> +#define DBGDIDR         p14,0,c0,c0,0   /* Debug ID Register */
> +#define DBGDSCRINT      p14,0,c0,c1,0   /* Debug Status and Control Internal */
> +#define DBGDSCREXT      p14,0,c0,c2,2   /* Debug Status and Control External */
> +#define DBGVCR          p14,0,c0,c7,0   /* Vector Catch */
> +#define DBGBVR0         p14,0,c0,c0,4   /* Breakpoint Value 0 */
> +#define DBGCR0          p14,0,c0,c0,5   /* Breakpoint Control 0 */
> +#define DBGWVR0         p14,0,c0,c0,6   /* Watchpoint Value 0 */
> +#define DBGWCR0         p14,0,c0,c0,7   /* Watchpoint Control 0 */
> +#define DBGBVR1         p14,0,c0,c1,4   /* Breakpoint Value 1 */
> +#define DBGCR1          p14,0,c0,c1,5   /* Breakpoint Control 1 */
> +#define DBGOSLAR        p14,0,c1,c0,4   /* OS Lock Access */
> +#define DBGOSDLR        p14,0,c1,c3,4   /* OS Double Lock */
> +
>  /* CP14 CR0: */
>  #define TEECR           p14,6,c0,c0,0   /* ThumbEE Configuration Register */
>
Julien Grall May 2, 2014, 12:53 p.m. UTC | #2
On 05/02/2014 12:09 PM, Ian Campbell wrote:
> On Thu, 2014-04-24 at 23:45 +0100, Julien Grall wrote:
>> XSA-93 (commit 0b18220 "xen/arm: Don't let guess access to Debug and Performance
>> Monitors registers") disable Debug Registers access.
>>
>> When CONFIG_PERF_EVENTS is enabled in the Linux Kernel, it will try to
>> initialize the debug monitors. If an error occured Linux won't use this
>> feature.
>>
>> The implementation made Xen expose a minimal set of registers which let think
>> the guest (i.e.) thinks HW debug won't work.
> 
> Why only for arm32?

Because, if I'm not mistaken, you've already implemented a dummy HW
debug for arm64 in commit 0b182202 "xen/arm: Don't let guess access to
Debug and Performance Monitor registers".

> I think arm64 makes more use than arm32 (unconditionally touches
> MDSCR_EL1 on the ctx switch path).
> 
> I think we should be considering allow the guest to access these and
> context switching them instead.

Disabling HW breakpoint don't disable debug. Linux will only use
software breakpoing (which is of course a bit slower).

I wrote this series to allow Distribution kernel (such as Linaro Ubuntu
kernel) boots correctly on Xen 4.4 and onwards.

I don't plan to more spend time to write a correct emulation (i.e
context switching) to support HW debug.

Regards,
Ian Campbell May 2, 2014, 1:14 p.m. UTC | #3
On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
> On 05/02/2014 12:09 PM, Ian Campbell wrote:
> > On Thu, 2014-04-24 at 23:45 +0100, Julien Grall wrote:
> >> XSA-93 (commit 0b18220 "xen/arm: Don't let guess access to Debug and Performance
> >> Monitors registers") disable Debug Registers access.
> >>
> >> When CONFIG_PERF_EVENTS is enabled in the Linux Kernel, it will try to
> >> initialize the debug monitors. If an error occured Linux won't use this
> >> feature.
> >>
> >> The implementation made Xen expose a minimal set of registers which let think
> >> the guest (i.e.) thinks HW debug won't work.
> > 
> > Why only for arm32?
> 
> Because, if I'm not mistaken, you've already implemented a dummy HW
> debug for arm64 in commit 0b182202 "xen/arm: Don't let guess access to
> Debug and Performance Monitor registers".

That's a RAZ/WI thing, I thought this was something cleverer (returing
values to make the guest think nothing was there).

> 
> > I think arm64 makes more use than arm32 (unconditionally touches
> > MDSCR_EL1 on the ctx switch path).
> > 
> > I think we should be considering allow the guest to access these and
> > context switching them instead.
> 
> Disabling HW breakpoint don't disable debug. Linux will only use
> software breakpoing (which is of course a bit slower).
> 
> I wrote this series to allow Distribution kernel (such as Linaro Ubuntu
> kernel) boots correctly on Xen 4.4 and onwards.
> 
> I don't plan to more spend time to write a correct emulation (i.e
> context switching) to support HW debug.
> 
> Regards,
>
Ian Campbell May 2, 2014, 1:26 p.m. UTC | #4
On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
> I don't plan to more spend time to write a correct emulation (i.e
> context switching) to support HW debug.

I'm not going to ack a patch which causes arm32 to diverge from arm64 in
this area, especially not when the correct solution (more critical on
arm64 than arm32) is to properly context switch these registers.

Ian.
Julien Grall May 2, 2014, 1:29 p.m. UTC | #5
On 05/02/2014 02:14 PM, Ian Campbell wrote:
> On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
>> On 05/02/2014 12:09 PM, Ian Campbell wrote:
>>> On Thu, 2014-04-24 at 23:45 +0100, Julien Grall wrote:
>>>> XSA-93 (commit 0b18220 "xen/arm: Don't let guess access to Debug and Performance
>>>> Monitors registers") disable Debug Registers access.
>>>>
>>>> When CONFIG_PERF_EVENTS is enabled in the Linux Kernel, it will try to
>>>> initialize the debug monitors. If an error occured Linux won't use this
>>>> feature.
>>>>
>>>> The implementation made Xen expose a minimal set of registers which let think
>>>> the guest (i.e.) thinks HW debug won't work.
>>>
>>> Why only for arm32?
>>
>> Because, if I'm not mistaken, you've already implemented a dummy HW
>> debug for arm64 in commit 0b182202 "xen/arm: Don't let guess access to
>> Debug and Performance Monitor registers".
> 
> That's a RAZ/WI thing, I thought this was something cleverer (returing
> values to make the guest think nothing was there).

Most of the time RAZ/WI is enough.  The arm32 implementation makes the
life harder.

I didn't check the arm64 implementation as I don't use it every day... I
need to set up the Foundation Model on my computer.
Julien Grall May 2, 2014, 1:39 p.m. UTC | #6
On 05/02/2014 02:26 PM, Ian Campbell wrote:
> On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
>> I don't plan to more spend time to write a correct emulation (i.e
>> context switching) to support HW debug.
> 
> I'm not going to ack a patch which causes arm32 to diverge from arm64 in
> this area, especially not when the correct solution (more critical on
> arm64 than arm32) is to properly context switch these registers.

We don't diverge... The Linux HW debug arm32 implementation doesn't
permit to use RAZ/WI on some registers.

Currently arm64 HW debug may or may not work but it won't crash the
guest. It's not the case on arm32. So the current Xen already diverge.

As said earlier, the HW debug is not essential. Writing a proper
emulation will take some time and I don't have time for writing and
testing it correctly.

IHMO, this solution is perfect for Xen 4.4, otherwise Xen 4.4.1 will
breaks support with lots of distribution.

For Xen 4.5, it's intermediate solution to allow guest working correctly
and people playing their shiny distribution on top of Xen. When someone
will care about HW debug, then we will have to support it correctly.

Regards,
Ian Campbell May 2, 2014, 2:18 p.m. UTC | #7
On Fri, 2014-05-02 at 14:39 +0100, Julien Grall wrote:
> On 05/02/2014 02:26 PM, Ian Campbell wrote:
> > On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
> >> I don't plan to more spend time to write a correct emulation (i.e
> >> context switching) to support HW debug.
> > 
> > I'm not going to ack a patch which causes arm32 to diverge from arm64 in
> > this area, especially not when the correct solution (more critical on
> > arm64 than arm32) is to properly context switch these registers.
> 
> We don't diverge... The Linux HW debug arm32 implementation doesn't
> permit to use RAZ/WI on some registers.
> 
> Currently arm64 HW debug may or may not work but it won't crash the
> guest. It's not the case on arm32. So the current Xen already diverge.

I think that was a mistake (albeit made under the pressure of a security
embargo), we shouldn't diverge further.

> As said earlier, the HW debug is not essential. Writing a proper
> emulation will take some time and I don't have time for writing and
> testing it correctly.

This is not about writing any sort of emulation AFAICT. It is about
context switching a couple of dozen new registers, of which 80% are
multiple instances of the same type of register.

The proper solution won't involve any trapping at all. (Maybe we will do
lazy context switching at some point, but that's another thing).

Ian.

> 
> IHMO, this solution is perfect for Xen 4.4, otherwise Xen 4.4.1 will
> breaks support with lots of distribution.
> 
> For Xen 4.5, it's intermediate solution to allow guest working correctly
> and people playing their shiny distribution on top of Xen. When someone
> will care about HW debug, then we will have to support it correctly.
> 
> Regards,
>
Julien Grall May 2, 2014, 2:22 p.m. UTC | #8
On 05/02/2014 03:18 PM, Ian Campbell wrote:
> On Fri, 2014-05-02 at 14:39 +0100, Julien Grall wrote:
>> On 05/02/2014 02:26 PM, Ian Campbell wrote:
>>> On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
>>>> I don't plan to more spend time to write a correct emulation (i.e
>>>> context switching) to support HW debug.
>>>
>>> I'm not going to ack a patch which causes arm32 to diverge from arm64 in
>>> this area, especially not when the correct solution (more critical on
>>> arm64 than arm32) is to properly context switch these registers.
>>
>> We don't diverge... The Linux HW debug arm32 implementation doesn't
>> permit to use RAZ/WI on some registers.
>>
>> Currently arm64 HW debug may or may not work but it won't crash the
>> guest. It's not the case on arm32. So the current Xen already diverge.
> 
> I think that was a mistake (albeit made under the pressure of a security
> embargo), we shouldn't diverge further.
> 
>> As said earlier, the HW debug is not essential. Writing a proper
>> emulation will take some time and I don't have time for writing and
>> testing it correctly.
> 
> This is not about writing any sort of emulation AFAICT. It is about
> context switching a couple of dozen new registers, of which 80% are
> multiple instances of the same type of register.
> 
> The proper solution won't involve any trapping at all. (Maybe we will do
> lazy context switching at some point, but that's another thing).

Are we sure that context switching won't lead to another security issue?
It's not clear to me how debugging behave with virtualization.
Ian Campbell May 2, 2014, 3:17 p.m. UTC | #9
On Fri, 2014-05-02 at 15:22 +0100, Julien Grall wrote:
> On 05/02/2014 03:18 PM, Ian Campbell wrote:
> > On Fri, 2014-05-02 at 14:39 +0100, Julien Grall wrote:
> >> On 05/02/2014 02:26 PM, Ian Campbell wrote:
> >>> On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
> >>>> I don't plan to more spend time to write a correct emulation (i.e
> >>>> context switching) to support HW debug.
> >>>
> >>> I'm not going to ack a patch which causes arm32 to diverge from arm64 in
> >>> this area, especially not when the correct solution (more critical on
> >>> arm64 than arm32) is to properly context switch these registers.
> >>
> >> We don't diverge... The Linux HW debug arm32 implementation doesn't
> >> permit to use RAZ/WI on some registers.
> >>
> >> Currently arm64 HW debug may or may not work but it won't crash the
> >> guest. It's not the case on arm32. So the current Xen already diverge.
> > 
> > I think that was a mistake (albeit made under the pressure of a security
> > embargo), we shouldn't diverge further.
> > 
> >> As said earlier, the HW debug is not essential. Writing a proper
> >> emulation will take some time and I don't have time for writing and
> >> testing it correctly.
> > 
> > This is not about writing any sort of emulation AFAICT. It is about
> > context switching a couple of dozen new registers, of which 80% are
> > multiple instances of the same type of register.
> > 
> > The proper solution won't involve any trapping at all. (Maybe we will do
> > lazy context switching at some point, but that's another thing).
> 
> Are we sure that context switching won't lead to another security issue?

Not if we do it right ;-)

> It's not clear to me how debugging behave with virtualization.

Me neither, yet.

Ian.
Ian Campbell June 13, 2014, 12:02 p.m. UTC | #10
On Fri, 2014-05-02 at 14:29 +0100, Julien Grall wrote:
> On 05/02/2014 02:14 PM, Ian Campbell wrote:
> > On Fri, 2014-05-02 at 13:53 +0100, Julien Grall wrote:
> >> On 05/02/2014 12:09 PM, Ian Campbell wrote:
> >>> On Thu, 2014-04-24 at 23:45 +0100, Julien Grall wrote:
> >>>> XSA-93 (commit 0b18220 "xen/arm: Don't let guess access to Debug and Performance
> >>>> Monitors registers") disable Debug Registers access.
> >>>>
> >>>> When CONFIG_PERF_EVENTS is enabled in the Linux Kernel, it will try to
> >>>> initialize the debug monitors. If an error occured Linux won't use this
> >>>> feature.
> >>>>
> >>>> The implementation made Xen expose a minimal set of registers which let think
> >>>> the guest (i.e.) thinks HW debug won't work.
> >>>
> >>> Why only for arm32?
> >>
> >> Because, if I'm not mistaken, you've already implemented a dummy HW
> >> debug for arm64 in commit 0b182202 "xen/arm: Don't let guess access to
> >> Debug and Performance Monitor registers".
> > 
> > That's a RAZ/WI thing, I thought this was something cleverer (returing
> > values to make the guest think nothing was there).

I think we've got a bit sidetracked here (especially in the other
subthread), sorry about that.

> Most of the time RAZ/WI is enough.  The arm32 implementation makes the
> life harder.

Looking at it with fresh eyes this morning I see what you mean now, the
essential difference is that with arm32 DBGDIDR is trapped by
MDCR_EL2.TDA, whereas the the arm64 equivalent (IDAA64DFR*) are not
(it's trapped as part of the ID register group, which we don't bother
trapping). The rest of the registers are RAZ/WI which is consistent with
arm64.

So in the end you've convinced me that this is the right thing to do for
now and to backport to 4.4.

Acked-by: Ian Campbell <ian.campbell@citrix.com>

I've committed this and the previous (perfc) one but not the next one
(useful debug for coproc traps) which had comments.

I did s/DBGCR/DBGBCR/ to match the name used in both the v7 and v8 ARM
ARMs, I think it was just a typo? Hope that's ok.

Also DBGOSLAR is supposed to be WO but you've implemented it as RAZ/WI,
I didn't think that mattered enough to bother with though.

Sorry that it took so long to get my head around this.

> I didn't check the arm64 implementation as I don't use it every day... I
> need to set up the Foundation Model on my computer.

You made me notice that arm64 doesn't handle OSDLR_EL1 traps. I think
that's harmless (unless a guest kernel tries to use it) but I'll send
out a patch shortly.

Ian.
Julien Grall June 14, 2014, 5:16 p.m. UTC | #11
Hi Ian,

On 13/06/14 13:02, Ian Campbell wrote:
> Looking at it with fresh eyes this morning I see what you mean now, the
> essential difference is that with arm32 DBGDIDR is trapped by
> MDCR_EL2.TDA, whereas the the arm64 equivalent (IDAA64DFR*) are not
> (it's trapped as part of the ID register group, which we don't bother
> trapping). The rest of the registers are RAZ/WI which is consistent with
> arm64.

Right, this patch is mostly here to let Linux think there is not debug 
hardware registers.

As you said on another mail, the long term goal is to context switch 
correctly those register to allow perf and debug working in the guest.

> So in the end you've convinced me that this is the right thing to do for
> now and to backport to 4.4.
>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
>
> I've committed this and the previous (perfc) one but not the next one
> (useful debug for coproc traps) which had comments.
>
> I did s/DBGCR/DBGBCR/ to match the name used in both the v7 and v8 ARM
> ARMs, I think it was just a typo? Hope that's ok.

Yes, I forgot the B by mistake.

>
> Also DBGOSLAR is supposed to be WO but you've implemented it as RAZ/WI,
> I didn't think that mattered enough to bother with though.

I was lazy to add 2 more lines to handle this register WO.

I'm not sure what is behavior when a guest is trying to read a WO 
register. I guess an undefined instruction.

I can send a follow-up to use this behavior for Xen 4.5.

Regards,
diff mbox

Patch

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 319bbe9..1f61e6e 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1468,7 +1468,76 @@  static void do_cp15_64(struct cpu_user_regs *regs,
     advance_pc(regs, hsr);
 }
 
-static void do_cp14(struct cpu_user_regs *regs, union hsr hsr)
+static void do_cp14_32(struct cpu_user_regs *regs, union hsr hsr)
+{
+    struct hsr_cp32 cp32 = hsr.cp32;
+    uint32_t *r = (uint32_t *)select_user_reg(regs, cp32.reg);
+    struct domain *d = current->domain;
+
+    if ( !check_conditional_instr(regs, hsr) )
+    {
+        advance_pc(regs, hsr);
+        return;
+    }
+
+    switch ( hsr.bits & HSR_CP32_REGS_MASK )
+    {
+    case HSR_CPREG32(DBGDIDR):
+
+        /* Read-only register */
+        if ( !cp32.read )
+            goto bad_cp;
+
+        /* Implement the minimum requirements:
+         *  - Number of watchpoints: 1
+         *  - Number of breakpoints: 2
+         *  - Version: ARMv7 v7.1
+         *  - Variant and Revision bits match MDIR
+         */
+        *r = (1 << 24) | (5 << 16);
+        *r |= ((d->arch.vpidr >> 20) & 0xf) | (d->arch.vpidr & 0xf);
+        break;
+
+    case HSR_CPREG32(DBGDSCRINT):
+    case HSR_CPREG32(DBGDSCREXT):
+        /* Implement debug status and control register as RAZ/WI.
+         * The OS won't use Hardware debug if MDBGen not set
+         */
+        if ( cp32.read )
+           *r = 0;
+        break;
+    case HSR_CPREG32(DBGVCR):
+    case HSR_CPREG32(DBGOSLAR):
+    case HSR_CPREG32(DBGBVR0):
+    case HSR_CPREG32(DBGCR0):
+    case HSR_CPREG32(DBGWVR0):
+    case HSR_CPREG32(DBGWCR0):
+    case HSR_CPREG32(DBGBVR1):
+    case HSR_CPREG32(DBGCR1):
+    case HSR_CPREG32(DBGOSDLR):
+        /* RAZ/WI */
+        if ( cp32.read )
+            *r = 0;
+        break;
+
+    default:
+bad_cp:
+#ifndef NDEBUG
+        gdprintk(XENLOG_ERR,
+                 "%s p14, %d, r%d, cr%d, cr%d, %d @ 0x%"PRIregister"\n",
+                  cp32.read ? "mrc" : "mcr",
+                  cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
+        gdprintk(XENLOG_ERR, "unhandled 32-bit cp14 access %#x\n",
+                 hsr.bits & HSR_CP32_REGS_MASK);
+#endif
+        inject_undef32_exception(regs);
+        return;
+    }
+
+    advance_pc(regs, hsr);
+}
+
+static void do_cp14_dbg(struct cpu_user_regs *regs, union hsr hsr)
 {
     if ( !check_conditional_instr(regs, hsr) )
     {
@@ -1720,10 +1789,14 @@  asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
         do_cp15_64(regs, hsr);
         break;
     case HSR_EC_CP14_32:
+        if ( !is_32bit_domain(current->domain) )
+            goto bad_trap;
+        do_cp14_32(regs, hsr);
+        break;
     case HSR_EC_CP14_DBG:
         if ( !is_32bit_domain(current->domain) )
             goto bad_trap;
-        do_cp14(regs, hsr);
+        do_cp14_dbg(regs, hsr);
         break;
     case HSR_EC_CP:
         if ( !is_32bit_domain(current->domain) )
diff --git a/xen/include/asm-arm/cpregs.h b/xen/include/asm-arm/cpregs.h
index f44e3b5..306e506 100644
--- a/xen/include/asm-arm/cpregs.h
+++ b/xen/include/asm-arm/cpregs.h
@@ -71,6 +71,20 @@ 
 
 /* Coprocessor 14 */
 
+/* CP14 0: Debug Register interface */
+#define DBGDIDR         p14,0,c0,c0,0   /* Debug ID Register */
+#define DBGDSCRINT      p14,0,c0,c1,0   /* Debug Status and Control Internal */
+#define DBGDSCREXT      p14,0,c0,c2,2   /* Debug Status and Control External */
+#define DBGVCR          p14,0,c0,c7,0   /* Vector Catch */
+#define DBGBVR0         p14,0,c0,c0,4   /* Breakpoint Value 0 */
+#define DBGCR0          p14,0,c0,c0,5   /* Breakpoint Control 0 */
+#define DBGWVR0         p14,0,c0,c0,6   /* Watchpoint Value 0 */
+#define DBGWCR0         p14,0,c0,c0,7   /* Watchpoint Control 0 */
+#define DBGBVR1         p14,0,c0,c1,4   /* Breakpoint Value 1 */
+#define DBGCR1          p14,0,c0,c1,5   /* Breakpoint Control 1 */
+#define DBGOSLAR        p14,0,c1,c0,4   /* OS Lock Access */
+#define DBGOSDLR        p14,0,c1,c3,4   /* OS Double Lock */
+
 /* CP14 CR0: */
 #define TEECR           p14,6,c0,c0,0   /* ThumbEE Configuration Register */