diff mbox

[Xen-devel,4/9] xen: arm: turn vtimer traps for cp32/64 and sysreg into #undef

Message ID 1410279788-27167-4-git-send-email-ian.campbell@citrix.com
State New
Headers show

Commit Message

Ian Campbell Sept. 9, 2014, 4:23 p.m. UTC
We have allowed EL1 to access these registers directly for some time
(at least since 4.3.0). They were only ever trapped to support very
early models which had a buggy hypervisor timer, requiring us to use
the phys timer for Xen itself.

In the interests of minimising the patch for the security update just
remove the call to vtimer_emulate and inject an #undef exception. In
practice we will never see any of these traps.

Handle CNTPCT_EL0 explicitly for consistency with CNTPCT on 32-bit.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/traps.c |   37 ++++++++++++-------------------------
 1 file changed, 12 insertions(+), 25 deletions(-)

Comments

Julien Grall Sept. 9, 2014, 11:31 p.m. UTC | #1
Hi Ian,

On 09/09/14 09:23, Ian Campbell wrote:
> We have allowed EL1 to access these registers directly for some time
> (at least since 4.3.0). They were only ever trapped to support very
> early models which had a buggy hypervisor timer, requiring us to use
> the phys timer for Xen itself.
> In the interests of minimising the patch for the security update just
> remove the call to vtimer_emulate and inject an #undef exception. In
> practice we will never see any of these traps.

I disagree with the commit message, a guest may use the physical timer 
rather than the virtual timer. It's the case when a guest doesn't have 
the necessary code to use the virtual timer.

Hence, the guest could decide to let the userspace access to CNTPCT_EL0 
(see CNTKCTL.PL0CTEN). In a such case, the application will be broken on 
Xen guest.

> Handle CNTPCT_EL0 explicitly for consistency with CNTPCT on 32-bit.
>
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> ---
>   xen/arch/arm/traps.c |   37 ++++++++++++-------------------------
>   1 file changed, 12 insertions(+), 25 deletions(-)
>
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 353e38e..46ed21d 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -1478,13 +1478,8 @@ static void do_cp15_32(struct cpu_user_regs *regs,
>           break;
>       case HSR_CPREG32(CNTP_CTL):
>       case HSR_CPREG32(CNTP_TVAL):
> -        if ( !vtimer_emulate(regs, hsr) )

You dropped every call to vtimer_emulate. It may be interesting to 
remove the related code in vtimer.c

Regards,
Ian Campbell Sept. 10, 2014, 9:46 a.m. UTC | #2
On Tue, 2014-09-09 at 16:31 -0700, Julien Grall wrote:
> Hi Ian,
> 
> On 09/09/14 09:23, Ian Campbell wrote:
> > We have allowed EL1 to access these registers directly for some time
> > (at least since 4.3.0). They were only ever trapped to support very
> > early models which had a buggy hypervisor timer, requiring us to use
> > the phys timer for Xen itself.
> > In the interests of minimising the patch for the security update just
> > remove the call to vtimer_emulate and inject an #undef exception. In
> > practice we will never see any of these traps.
> 
> I disagree with the commit message, a guest may use the physical timer 
> rather than the virtual timer. It's the case when a guest doesn't have 
> the necessary code to use the virtual timer.

I think you've misunderstood. The guest is allowed direct access to the
physical timer ever since we removed the workaround for the buggy
hypervisor timer on the models. Hence we are never trapping these
registers anyway. Probably I should go further here and actually remove
all the phys timer emulation support from vtimer.c.

> Hence, the guest could decide to let the userspace access to CNTPCT_EL0 
> (see CNTKCTL.PL0CTEN). In a such case, the application will be broken on 
> Xen guest.
> 
> > Handle CNTPCT_EL0 explicitly for consistency with CNTPCT on 32-bit.
> >
> > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> > ---
> >   xen/arch/arm/traps.c |   37 ++++++++++++-------------------------
> >   1 file changed, 12 insertions(+), 25 deletions(-)
> >
> > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> > index 353e38e..46ed21d 100644
> > --- a/xen/arch/arm/traps.c
> > +++ b/xen/arch/arm/traps.c
> > @@ -1478,13 +1478,8 @@ static void do_cp15_32(struct cpu_user_regs *regs,
> >           break;
> >       case HSR_CPREG32(CNTP_CTL):
> >       case HSR_CPREG32(CNTP_TVAL):
> > -        if ( !vtimer_emulate(regs, hsr) )
> 
> You dropped every call to vtimer_emulate. It may be interesting to 
> remove the related code in vtimer.c

Yes, I didn't do that when this was going to be a security update to
keep the size of the patch down, but I should do so now though.

Ian.
Julien Grall Sept. 10, 2014, 6:54 p.m. UTC | #3
Hi Ian,

On 10/09/14 02:46, Ian Campbell wrote:
> On Tue, 2014-09-09 at 16:31 -0700, Julien Grall wrote:
>> Hi Ian,
>>
>> On 09/09/14 09:23, Ian Campbell wrote:
>>> We have allowed EL1 to access these registers directly for some time
>>> (at least since 4.3.0). They were only ever trapped to support very
>>> early models which had a buggy hypervisor timer, requiring us to use
>>> the phys timer for Xen itself.
>>> In the interests of minimising the patch for the security update just
>>> remove the call to vtimer_emulate and inject an #undef exception. In
>>> practice we will never see any of these traps.
>>
>> I disagree with the commit message, a guest may use the physical timer
>> rather than the virtual timer. It's the case when a guest doesn't have
>> the necessary code to use the virtual timer.
>
> I think you've misunderstood. The guest is allowed direct access to the
> physical timer ever since we removed the workaround for the buggy
> hypervisor timer on the models. Hence we are never trapping these
> registers anyway. Probably I should go further here and actually remove
> all the phys timer emulation support from vtimer.c.

Are you sure? In init_interrupt_timer (xen/arch/arm/timer.c) we disable 
the access to the physical timer to the guest. See 
WRITE_SYSREG32(CNTHCTL_PA, CNTHCTL_EL2).

Hence, I don't see any save/restore for the physical timer in 
xen/arch/arm/vtimer.c. I only see them for the virtual timer.

Regards,
Ian Campbell Sept. 11, 2014, 8:43 a.m. UTC | #4
On Wed, 2014-09-10 at 11:54 -0700, Julien Grall wrote:
> Hi Ian,
> 
> On 10/09/14 02:46, Ian Campbell wrote:
> > On Tue, 2014-09-09 at 16:31 -0700, Julien Grall wrote:
> >> Hi Ian,
> >>
> >> On 09/09/14 09:23, Ian Campbell wrote:
> >>> We have allowed EL1 to access these registers directly for some time
> >>> (at least since 4.3.0). They were only ever trapped to support very
> >>> early models which had a buggy hypervisor timer, requiring us to use
> >>> the phys timer for Xen itself.
> >>> In the interests of minimising the patch for the security update just
> >>> remove the call to vtimer_emulate and inject an #undef exception. In
> >>> practice we will never see any of these traps.
> >>
> >> I disagree with the commit message, a guest may use the physical timer
> >> rather than the virtual timer. It's the case when a guest doesn't have
> >> the necessary code to use the virtual timer.
> >
> > I think you've misunderstood. The guest is allowed direct access to the
> > physical timer ever since we removed the workaround for the buggy
> > hypervisor timer on the models. Hence we are never trapping these
> > registers anyway. Probably I should go further here and actually remove
> > all the phys timer emulation support from vtimer.c.
> 
> Are you sure? In init_interrupt_timer (xen/arch/arm/timer.c) we disable 
> the access to the physical timer to the guest. See 
> WRITE_SYSREG32(CNTHCTL_PA, CNTHCTL_EL2).

Hrm, I mistakenly thought that was enabling them, but we do indeed need
to set a second bit there, this only allows access to the counter, not
the control registers. I'll take another look.

> Hence, I don't see any save/restore for the physical timer in 
> xen/arch/arm/vtimer.c. I only see them for the virtual timer.
> 
> Regards,
>
Julien Grall Jan. 14, 2015, 4:57 p.m. UTC | #5
Hi Ian,

On 14/01/15 16:33, Ian Campbell wrote:
> On Thu, 2014-09-11 at 09:43 +0100, Ian Campbell wrote:
>> On Wed, 2014-09-10 at 11:54 -0700, Julien Grall wrote:
>>> Hi Ian,
>>>
>>> On 10/09/14 02:46, Ian Campbell wrote:
>>>> On Tue, 2014-09-09 at 16:31 -0700, Julien Grall wrote:
>>>>> Hi Ian,
>>>>>
>>>>> On 09/09/14 09:23, Ian Campbell wrote:
>>>>>> We have allowed EL1 to access these registers directly for some time
>>>>>> (at least since 4.3.0). They were only ever trapped to support very
>>>>>> early models which had a buggy hypervisor timer, requiring us to use
>>>>>> the phys timer for Xen itself.
>>>>>> In the interests of minimising the patch for the security update just
>>>>>> remove the call to vtimer_emulate and inject an #undef exception. In
>>>>>> practice we will never see any of these traps.
>>>>>
>>>>> I disagree with the commit message, a guest may use the physical timer
>>>>> rather than the virtual timer. It's the case when a guest doesn't have
>>>>> the necessary code to use the virtual timer.
> 
> I was just about to dive back into this and was thinking: Is a guest
> which uses the phys timer something we actually wish to support? We
> already require the guest to paravirtualise other aspects of its life,
> and requiring vtimer doesn't seem to step outside that boundary.

Currently if a developer wants to support his OS on Xen, he only has to
add PV drivers (assuming DT support is there). It doesn't have to modify
the core of the OS.

This will be the case with requiring the vtimer. Futhermore, it can be
tricky to implement it on some OS. For instance, the OS may decide to
expose the timer to the user space. Any change would mean recompiler all
the user space for running on Xen.

> Supporting the ptimer is going to take some effort as well as the
> existing code+overhead in Xen.

We already support the physical timer. May I ask, what kind of effort
are necessary?

> Do we know of any existing supported OSes which use the phys timer?

AFAIK no. Even though FreeBSD, while it's not supported, the physical
timer is used by default.

Regards,
Julien Grall Jan. 15, 2015, 12:27 p.m. UTC | #6
Hi Ian,

On 15/01/15 10:26, Ian Campbell wrote:
> I'm looking into the vtimer masking and ctxt switching the irq state
> now, once I've got that going exposing the ptimer directly to guests
> ought to be pretty simple.

I don't think we can expose directly the physical timer to the guest.

If the guest tries to read CNTPCT_EL0, it will read the number of ticks
since the host is up.

Regards,
diff mbox

Patch

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 353e38e..46ed21d 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1478,13 +1478,8 @@  static void do_cp15_32(struct cpu_user_regs *regs,
         break;
     case HSR_CPREG32(CNTP_CTL):
     case HSR_CPREG32(CNTP_TVAL):
-        if ( !vtimer_emulate(regs, hsr) )
-        {
-            dprintk(XENLOG_ERR,
-                    "failed emulation of 32-bit vtimer CP register access\n");
-            domain_crash_synchronous();
-        }
-        break;
+        goto undef_cp15_32;
+
     case HSR_CPREG32(ACTLR):
         if ( cp32.read )
            *r = v->arch.actlr;
@@ -1526,6 +1521,7 @@  static void do_cp15_32(struct cpu_user_regs *regs,
         gdprintk(XENLOG_ERR, "unhandled 32-bit CP15 access %#x\n",
                  hsr.bits & HSR_CP32_REGS_MASK);
 #endif
+ undef_cp15_32:
         inject_undef_exception(regs, hsr.len);
         return;
     }
@@ -1544,13 +1540,8 @@  static void do_cp15_64(struct cpu_user_regs *regs,
     switch ( hsr.bits & HSR_CP64_REGS_MASK )
     {
     case HSR_CPREG64(CNTPCT):
-        if ( !vtimer_emulate(regs, hsr) )
-        {
-            dprintk(XENLOG_ERR,
-                    "failed emulation of 64-bit vtimer CP register access\n");
-            domain_crash_synchronous();
-        }
-        break;
+        goto undef_cp15_64;
+
     default:
         {
 #ifndef NDEBUG
@@ -1563,6 +1554,7 @@  static void do_cp15_64(struct cpu_user_regs *regs,
             gdprintk(XENLOG_ERR, "unhandled 64-bit CP15 access %#x\n",
                      hsr.bits & HSR_CP64_REGS_MASK);
 #endif
+ undef_cp15_64:
             inject_undef_exception(regs, hsr.len);
             return;
         }
@@ -1729,18 +1721,13 @@  static void do_sysreg(struct cpu_user_regs *regs,
         break;
     case HSR_SYSREG_CNTP_CTL_EL0:
     case HSR_SYSREG_CNTP_TVAL_EL0:
-        if ( !vtimer_emulate(regs, hsr) )
-        {
-            dprintk(XENLOG_ERR,
-                    "failed emulation of 64-bit vtimer sysreg access\n");
-            domain_crash_synchronous();
-        }
-        break;
+    case HSR_SYSREG_CNTPCT_EL0:
+        goto undef_sysreg;
     default:
  bad_sysreg:
         {
-            struct hsr_sysreg sysreg = hsr.sysreg;
 #ifndef NDEBUG
+            struct hsr_sysreg sysreg = hsr.sysreg;
 
             gdprintk(XENLOG_ERR,
                      "%s %d, %d, c%d, c%d, %d %s x%d @ 0x%"PRIregister"\n",
@@ -1753,7 +1740,8 @@  static void do_sysreg(struct cpu_user_regs *regs,
             gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x\n",
                      hsr.bits & HSR_SYSREG_REGS_MASK);
 #endif
-            inject_undef_exception(regs, sysreg.len);
+ undef_sysreg:
+            inject_undef_exception(regs, hsr.len);
             return;
         }
     }
@@ -1925,8 +1913,7 @@  asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
         do_cp15_32(regs, hsr);
         break;
     case HSR_EC_CP15_64:
-        if ( !is_32bit_domain(current->domain) )
-            goto bad_trap;
+        BUG_ON(!psr_mode_is_32bit(regs->cpsr));
         do_cp15_64(regs, hsr);
         break;
     case HSR_EC_CP14_32: