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

Re: [Xen-devel] [RFC PATCH v1] Replace tasklets with per-cpu implementation.



>>> On 08.09.14 at 21:01, <konrad.wilk@xxxxxxxxxx> wrote:
> On Wed, Sep 03, 2014 at 09:03:45AM +0100, Jan Beulich wrote:
>> >>> On 02.09.14 at 22:28, <konrad.wilk@xxxxxxxxxx> wrote:
>> > I typed this prototype up and asked folks with the right hardware to
>> > test it. It _ought_ to, thought I think that the tasklet code
>> > still could use an overhaul.
>> 
>> Apart from needing general cleaning up, the main question I have
>> is whether the dpci_kill() part couldn't be replaced by obtaining a
>> proper reference on the domain when scheduling a softirq, and
>> dropping that reference after having handled it.
> 
> 
> The one fatal corner is when we call 'hvm_dirq_assist' with
> d->arch.hvm_domain.irq.dpci set to NULL. There is even an ASSERT in 
> 'hvm_dirq_assist' for that.
> 
> The one edge condition I am troubled by is when we receive an
> interrupt and process it - while on anothre CPU we get an hypercall
> for 'domain_kill'.
> 
> That is:
>  a) 'do_IRQ'-> .. schedule_dpci_for(d)' had been called (and so
>     d->arch.hvm_domain.irq.dpci is still valid).
> 
>  b) on another CPU 'domain_kill' calls domain_relinquish_resources
>    >pci_release_devices->pci_clean_dpci_irqs which then makes 
>    d->arch.hvm_domain.irq.dpci NULL.
> 
>  c). the 'schedule_tail' (vmx_do_resume) right after a) is called 
>    which means we call the do_softirq. The 'dpci_softirq' is called
>    which calls 'hvm_dirq_assist' and blows up.
> 
>  d). the 'domain_relinquish_resources' on another CPU continues on trying
>    to tear down the domain.

I have to admit that I don't immediately see why this would be a
problem with the new softirq approach, but not with the previous
tasklet one. In any event, couldn't domain_relinquish_resources()
wait for the list of scheduled entities to become empty, while not
inserting new entries onto the list when ->is_dying?

> +static void schedule_dpci_for(struct domain *d)
> +{
> +    if ( !test_and_set_bit(STATE_SCHED, &d->state) )
> +    {
> +        unsigned long flags;
> +        struct list_head *list;
> +
> +        local_irq_save(flags);
> +        INIT_LIST_HEAD(&d->list);
> +        get_domain(d); /* To be put by 'dpci_softirq' */

get_knownalive_domain()?

> +static void migrate_tasklets_from_cpu(unsigned int cpu, struct list_head 
> *list)

tasklets?

> +{
> +    struct domain *d;
> +
> +    while ( !list_empty(list) )
> +    {
> +        d = list_entry(list->next, struct domain, list);
> +        list_del(&d->list);
> +        schedule_dpci_for(d);
> +    }
> +}
> +
> +static int cpu_callback(
> +    struct notifier_block *nfb, unsigned long action, void *hcpu)
> +{
> +    unsigned int cpu = (unsigned long)hcpu;
> +
> +    switch ( action )
> +    {
> +    case CPU_UP_PREPARE:
> +        INIT_LIST_HEAD(&per_cpu(dpci_list, cpu));
> +        break;
> +    case CPU_UP_CANCELED:
> +    case CPU_DEAD:
> +        migrate_tasklets_from_cpu(cpu, (&per_cpu(dpci_list, cpu)));

Can CPUs go down while softirqs are pending on them?

> +        break;
> +    default:
> +        break;
> +    }
> +
> +    return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block cpu_nfb = {
> +    .notifier_call = cpu_callback,
> +    .priority = 99

If the whole notification is needed, this seemingly arbitrary number
would need a comment.

> --- a/xen/include/xen/softirq.h
> +++ b/xen/include/xen/softirq.h
> @@ -8,6 +8,7 @@ enum {
>      NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ,
>      RCU_SOFTIRQ,
>      TASKLET_SOFTIRQ,
> +    HVM_DPCI_SOFTIRQ,
>      NR_COMMON_SOFTIRQS
>  };

This should of course also be conditional upon HAS_PASSTHROUGH.

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®.