[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v5 10/11] viridian: add implementation of synthetic timers



> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@xxxxxxxx]
> Sent: 13 March 2019 15:37
> To: Paul Durrant <Paul.Durrant@xxxxxxxxxx>
> Cc: Julien Grall <julien.grall@xxxxxxx>; Andrew Cooper 
> <Andrew.Cooper3@xxxxxxxxxx>; George Dunlap
> <George.Dunlap@xxxxxxxxxx>; Ian Jackson <Ian.Jackson@xxxxxxxxxx>; Roger Pau 
> Monne
> <roger.pau@xxxxxxxxxx>; Wei Liu <wei.liu2@xxxxxxxxxx>; Stefano Stabellini 
> <sstabellini@xxxxxxxxxx>;
> xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxxx>; Konrad Rzeszutek Wilk 
> <konrad.wilk@xxxxxxxxxx>; Tim
> (Xen.org) <tim@xxxxxxx>
> Subject: RE: [PATCH v5 10/11] viridian: add implementation of synthetic timers
> 
> >>> On 13.03.19 at 15:37, <Paul.Durrant@xxxxxxxxxx> wrote:
> >> From: Jan Beulich [mailto:JBeulich@xxxxxxxx]
> >> Sent: 13 March 2019 14:06
> >>
> >> >>> On 11.03.19 at 14:41, <paul.durrant@xxxxxxxxxx> wrote:
> >> > +bool viridian_synic_deliver_timer_msg(struct vcpu *v, unsigned int 
> >> > sintx,
> >> > +                                      unsigned int index,
> >> > +                                      uint64_t expiration,
> >> > +                                      uint64_t delivery)
> >> > +{
> >> > +    struct viridian_vcpu *vv = v->arch.hvm.viridian;
> >> > +    const union viridian_sint_msr *vs = &vv->sint[sintx];
> >> > +    HV_MESSAGE *msg = vv->simp.ptr;
> >> > +    struct {
> >> > +        uint32_t TimerIndex;
> >> > +        uint32_t Reserved;
> >> > +        uint64_t ExpirationTime;
> >> > +        uint64_t DeliveryTime;
> >> > +    } payload = {
> >> > +        .TimerIndex = index,
> >> > +        .ExpirationTime = expiration,
> >> > +        .DeliveryTime = delivery,
> >> > +    };
> >> > +
> >> > +    if ( test_bit(sintx, &vv->msg_pending) )
> >> > +        return false;
> >> > +
> >> > +    BUILD_BUG_ON(sizeof(*msg) != HV_MESSAGE_SIZE);
> >> > +    msg += sintx;
> >> > +
> >> > +    /*
> >> > +     * To avoid using an atomic test-and-set, and barrier before calling
> >> > +     * vlapic_set_irq(), this function must be called in context of the
> >> > +     * vcpu receiving the message.
> >> > +     */
> >> > +    ASSERT(v == current);
> >> > +    if ( msg->Header.MessageType != HvMessageTypeNone )
> >> > +    {
> >> > +        msg->Header.MessageFlags.MessagePending = 1;
> >> > +        __set_bit(sintx, &vv->msg_pending);
> >> > +        return false;
> >> > +    }
> >> > +
> >> > +    msg->Header.MessageType = HvMessageTimerExpired;
> >> > +    msg->Header.MessageFlags.MessagePending = 0;
> >> > +    msg->Header.PayloadSize = sizeof(payload);
> >> > +    memcpy(msg->Payload, &payload, sizeof(payload));
> >>
> >> Since you can't use plain assignment here, how about a
> >> BUILD_BUG_ON(sizeof(payload) <= sizeof(msg->payload))?
> >
> > Surely '>' rather than '<='?
> 
> Oops, yes - I was apparently thinking the ASSERT() way.
> 
> >> As to safety of this, I have two concerns:
> >>
> >> 1) TscSequence gets updated as a result of a guest action (an MSR
> >> write). This makes it non-obvious that the loop above will get
> >> exited in due course.
> >>
> >
> > True. The domain could try to DoS this call. This could be avoided by doing
> > a domain_pause() if we test continuously fails for a number of iterations, 
> > or
> > maybe just one iteration.
> 
> As per what you say further down, one iteration ought to be enough
> indeed. Otherwise I would have suggested a handful.
> 
> >> > +static void poll_stimer(struct vcpu *v, unsigned int stimerx)
> >> > +{
> >> > +    struct viridian_vcpu *vv = v->arch.hvm.viridian;
> >> > +    struct viridian_stimer *vs = &vv->stimer[stimerx];
> >> > +
> >> > +    if ( !test_bit(stimerx, &vv->stimer_pending) )
> >> > +        return;
> >> > +
> >> > +    if ( !viridian_synic_deliver_timer_msg(v, vs->config.fields.sintx,
> >> > +                                           stimerx, vs->expiration,
> >> > +                                           time_now(v->domain)) )
> >> > +        return;
> >> > +
> >> > +    clear_bit(stimerx, &vv->stimer_pending);
> >>
> >> While perhaps benign, wouldn't it be better to clear the pending bit
> >> before delivering the message?
> >
> > No, because I only want to clear it if the delivery is successful.
> 
> Ah, I see.
> 
> >> > @@ -149,6 +398,63 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t 
> >> > idx, uint64_t val)
> >> >          }
> >> >          break;
> >> >
> >> > +    case HV_X64_MSR_TIME_REF_COUNT:
> >> > +        return X86EMUL_EXCEPTION;
> >> > +
> >> > +    case HV_X64_MSR_STIMER0_CONFIG:
> >> > +    case HV_X64_MSR_STIMER1_CONFIG:
> >> > +    case HV_X64_MSR_STIMER2_CONFIG:
> >> > +    case HV_X64_MSR_STIMER3_CONFIG:
> >> > +    {
> >> > +        unsigned int stimerx =
> >> > +            array_index_nospec((idx - HV_X64_MSR_STIMER0_CONFIG) / 2,
> >> > +                               ARRAY_SIZE(vv->stimer));
> >> > +        struct viridian_stimer *vs = &vv->stimer[stimerx];
> >>
> >> I again think you'd better use array_access_nospec() here (also
> >> for the rdmsr counterparts).
> >
> > I don't follow. I *am* using array_index_nospec().
> 
> But "index" != "access".

Ah, I was blinkered by the 'nospec'... yes, I'll use that rather than rolling 
my own.

> 
> >> > @@ -160,6 +466,7 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t 
> >> > idx, uint64_t val)
> >> >
> >> >  int viridian_time_rdmsr(const struct vcpu *v, uint32_t idx, uint64_t 
> >> > *val)
> >> >  {
> >> > +    struct viridian_vcpu *vv = v->arch.hvm.viridian;
> >>
> >> const?
> >>
> >
> > I don't think so. A read of the reference TSC MSR updates a flag.
> 
> But you don't make any existing code use vv in this patch. And
> the new code you add doesn't look to require it to be non-const.
> I can see why vd (introduced by an earlier patch in the series)
> can't be constified for the reason you name.

Ah, true, I was thinking of vd. Although I'm sure when I tried to const vv I 
got a compiler error. I'll try again... something else might have changed.

> 
> >> > @@ -322,6 +324,15 @@ int guest_wrmsr_viridian(struct vcpu *v, uint32_t 
> >> > idx, uint64_t val)
> >> >      case HV_X64_MSR_TSC_FREQUENCY:
> >> >      case HV_X64_MSR_APIC_FREQUENCY:
> >> >      case HV_X64_MSR_REFERENCE_TSC:
> >> > +    case HV_X64_MSR_TIME_REF_COUNT:
> >> > +    case HV_X64_MSR_STIMER0_CONFIG:
> >> > +    case HV_X64_MSR_STIMER0_COUNT:
> >> > +    case HV_X64_MSR_STIMER1_CONFIG:
> >> > +    case HV_X64_MSR_STIMER1_COUNT:
> >> > +    case HV_X64_MSR_STIMER2_CONFIG:
> >> > +    case HV_X64_MSR_STIMER2_COUNT:
> >> > +    case HV_X64_MSR_STIMER3_CONFIG:
> >> > +    case HV_X64_MSR_STIMER3_COUNT:
> >>
> >> For readability / brevity
> >>
> >>     case HV_X64_MSR_STIMER0_CONFIG ... HV_X64_MSR_STIMER3_COUNT:
> >>
> >> ?
> >
> > Certainly brevity, but I'm not sure about readability. I'll make the change.
> 
> Well, you're the maintainer, so I don't want to talk you into
> something you're really opposed to.
> 

I'm not that bothered so I'll make the change.

  Paul

> Jan


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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.