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

Re: [Xen-devel] [PATCH v6 17/19] x86/VPMU: NMI-based VPMU support



>>> On 13.05.14 at 17:53, <boris.ostrovsky@xxxxxxxxxx> wrote:
> With send_guest_vcpu_virq() and hvm_get_segment_register() for PV(H) and 
> vlapic
> accesses for HVM moved to sofint, the only routines/macros that 
> vpmu_do_interrupt()
> calls in NMI mode are:
> * memcpy()
> * querying domain type (is_XX_domain())
> * guest_cpu_user_regs()
> * XLAT_cpu_user_regs()
> * raise_softirq()
> * vcpu_vpmu()
> * vpmu_ops->arch_vpmu_save()

With this ...

> --- a/xen/arch/x86/hvm/svm/vpmu.c
> +++ b/xen/arch/x86/hvm/svm/vpmu.c
> @@ -185,6 +185,7 @@ static inline void context_load(struct vcpu *v)
>      }
>  }
>  
> +/* Must be NMI-safe */
>  static void amd_vpmu_load(struct vcpu *v)

... is the comment perhaps misplaced?

> +static void vpmu_send_nmi(struct vcpu *v)
> +{
> +    struct vlapic *vlapic;
> +    u32 vlapic_lvtpc;
> +    unsigned char int_vec;
> +
> +    ASSERT( is_hvm_vcpu(v) );
> +
> +    vlapic = vcpu_vlapic(v);
> +    if ( !is_vlapic_lvtpc_enabled(vlapic) )
> +        return;
> +
> +    vlapic_lvtpc = vlapic_get_reg(vlapic, APIC_LVTPC);
> +    int_vec = vlapic_lvtpc & APIC_VECTOR_MASK;
> +
> +    if ( GET_APIC_DELIVERY_MODE(vlapic_lvtpc) == APIC_MODE_FIXED )
> +        vlapic_set_irq(vcpu_vlapic(v), int_vec, 0);
> +    else
> +        v->nmi_pending = 1;

I realize this is only the result of code movement, but what is this
if/else pair doing?

> +static void pmu_softnmi(void)
> +{
> +    struct cpu_user_regs *regs;
> +    struct vcpu *v, *sampled = per_cpu(sampled_vcpu, smp_processor_id());

this_cpu().

> +
> +    if ( sampled == NULL )
> +        return;
> +    per_cpu(sampled_vcpu, smp_processor_id()) = NULL;

Again.

> +
> +    if ( (vpmu_mode & XENPMU_MODE_PRIV) ||
> +         (sampled->domain->domain_id >= DOMID_FIRST_RESERVED) )
> +        v = hardware_domain->vcpu[smp_processor_id() %
> +                                  hardware_domain->max_vcpus];
> +    else
> +    {
> +        if ( is_hvm_domain(sampled->domain) )
> +        {
> +            vpmu_send_nmi(sampled);
> +            return;
> +        }
> +        v = sampled;
> +    }
> +
> +    regs = &v->arch.vpmu.xenpmu_data->pmu.r.regs;
> +    if ( !is_pv_domain(sampled->domain) )

Even if it means the same, has_hvm_container_vcpu(sampled)
please: You're guarding an operation here that requires a HVM
container.

> +    {
> +        struct segment_register cs;
> +
> +        hvm_get_segment_register(sampled, x86_seg_cs, &cs);

I hope you understand that what you read here is only implicitly (due
to the softirq getting serviced before the guest gets re-entered) the
current value. Or wait - is it at all? What if a scheduler softirq first
causes the guest to be de-scheduled and another CPU manages to
pick it up before you get here?

> @@ -472,6 +574,21 @@ static int pvpmu_init(struct domain *d, xen_pmu_params_t 
> *params)
>          return -EINVAL;
>      }
>  
> +    if ( !pvpmu_initted )
> +    {
> +        if (reserve_lapic_nmi() == 0)

Coding style.

> +            set_nmi_callback(pmu_nmi_interrupt);
> +        else
> +        {
> +            printk("Failed to reserve PMU NMI\n");
> +            put_page(page);
> +            return -EBUSY;
> +        }
> +        open_softirq(PMU_SOFTIRQ, pmu_softnmi);
> +
> +        pvpmu_initted = 1;

Is it excluded that you get two racing pvpmu_init() calls (i.e. are
these exclusively coming from e.g. a domctl)? If not, better
serialization would be needed here.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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