|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] x86/mm: Improve ring management for memory events. Do not lose guest events
Hi,
This looks fine to me; this time I'd like Olaf to review and test it
before I commit it. :)
A few comments inline below -- mostly nits about style.
At 13:28 -0500 on 11 Jan (1326288504), Andres Lagar-Cavilla wrote:
> Signed-off-by: Adin Scannell <adin@xxxxxxxxxxx>
> Signed-off-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>
Housekeeping: please keep Olaf's Signed-off-by: line to cover the parts
of this patch that he's certifying.
> diff -r d3342b370b6f -r a85e7d46401b xen/arch/x86/hvm/hvm.c
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -4188,25 +4188,31 @@ static int hvm_memory_event_traps(long p
> unsigned long value, unsigned long old,
> bool_t gla_valid, unsigned long gla)
> {
> + int rc;
> struct vcpu* v = current;
> struct domain *d = v->domain;
> mem_event_request_t req;
> - int rc;
>
Please try to avoid this kind of unrelated shuffling (and I saw some
whitespace changes later on as well). It's not a big deal, but it makes
reviewing a bit easier and avoids unnecessarily clashing with other
patches.
> diff -r d3342b370b6f -r a85e7d46401b xen/arch/x86/mm/mem_event.c
> --- a/xen/arch/x86/mm/mem_event.c
> +++ b/xen/arch/x86/mm/mem_event.c
> +
> +/*
> + * mem_event_wake_requesters() will wakeup vcpus waiting for room in the
DYM mem_event_wake_blocked() ?
> + * ring. These vCPUs were paused on their way out after placing an event,
> + * but need to be resumed where the ring is capable of processing at least
> + * one event from them.
> + */
> +static void mem_event_wake_blocked(struct domain *d, struct mem_event_domain
> *med)
> +{
> + struct vcpu *v;
> + int online = d->max_vcpus;
> + int avail_req = mem_event_ring_available(med);
> +
> + if( avail_req <= 0 || med->blocked == 0 )
s/if(/if (/
> + return;
> +
> + /*
> + * We ensure that we only have vCPUs online if there are enough free
> slots
> + * for their memory events to be processed. This will ensure that no
> + * memory events are lost (due to the fact that certain types of events
> + * cannot be replayed, we need to ensure that there is space in the ring
> + * for when they are hit).
> + * See comment below in mem_event_put_request().
> + */
> + for_each_vcpu ( d, v )
> + if ( test_bit(med->pause_flag, &v->pause_flags) )
> + online--;
> +
> + ASSERT(online == (d->max_vcpus - med->blocked));
Maybe better to do the cheap calculation as the default and the more
expensive one for the ASSERT?
> + /* We remember which vcpu last woke up to avoid scanning always linearly
> + * from zero and starving higher-numbered vcpus under high load */
> + if ( d->vcpu )
> + {
> + int i, j, k;
> +
> + for (i = med->last_vcpu_wake_up + 1, j = 0; j < d->max_vcpus; i++,
> j++)
> + {
> + k = i % d->max_vcpus;
> + v = d->vcpu[k];
> + if ( !v )
> + continue;
> +
> + if ( !(med->blocked) || online >= avail_req )
> + break;
> +
> + if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) )
> + {
> + vcpu_unpause(v);
> + online++;
> + med->blocked--;
> + med->last_vcpu_wake_up = k;
> + }
> + }
> + }
> +}
> +
> +/*
> + * In the event that a vCPU attempted to place an event in the ring and
> + * was unable to do so, it is queued on a wait queue. These are woken as
> + * needed, and take precedence over the blocked vCPUs.
> + */
> +static void mem_event_wake_queued(struct domain *d, struct mem_event_domain
> *med)
> +{
> + int avail_req = mem_event_ring_available(med);
> +
> + if ( avail_req > 0 )
> + wake_up_nr(&med->wq, avail_req);
> +}
> +
> +/*
> + * mem_event_wake_waiters() will wakeup all vcpus waiting for the ring to
DYM mem_event_wake() ?
> + * become available. If we have queued vCPUs, they get top priority. We
> + * are guaranteed that they will go through code paths that will eventually
> + * call mem_event_wake() again, ensuring that any blocked vCPUs will get
> + * unpaused once all the queued vCPUs have made it through.
> + */
> +void mem_event_wake(struct domain *d, struct mem_event_domain *med)
> +{
> + if (!list_empty(&med->wq.list))
> + mem_event_wake_queued(d, med);
> + else
> + mem_event_wake_blocked(d, med);
> +}
> +
> +static int mem_event_disable(struct domain *d, struct mem_event_domain *med)
> +{
> + if( med->ring_page )
s/if(/if (/g :)
> + {
> + struct vcpu *v;
> +
> + mem_event_ring_lock(med);
> +
> + if (!list_empty(&med->wq.list))
if ( ... )
> + {
> + mem_event_ring_unlock(med);
> + return -EBUSY;
> + }
> +
> + unmap_domain_page(med->ring_page);
> + med->ring_page = NULL;
> +
> + unmap_domain_page(med->shared_page);
> + med->shared_page = NULL;
> +
> + /* Wake up everybody */
> + wake_up_all(&med->wq);
> +
> + /* Unblock all vCPUs */
> + for_each_vcpu ( d, v )
> + {
> + if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) )
> + {
> + vcpu_unpause(v);
> + med->blocked--;
> + }
> + }
> +
> + mem_event_ring_unlock(med);
> + }
>
> return 0;
> }
>
> -void mem_event_put_request(struct domain *d, struct mem_event_domain *med,
> mem_event_request_t *req)
> +static inline void mem_event_release_slot(struct domain *d,
> + struct mem_event_domain *med)
> +{
> + /* Update the accounting */
> + if ( current->domain == d )
> + med->target_producers--;
> + else
> + med->foreign_producers--;
> +
> + /* Kick any waiters */
> + mem_event_wake(d, med);
> +}
> +
> +/*
> + * mem_event_mark_and_pause() tags vcpu and put it to sleep.
> + * The vcpu will resume execution in mem_event_wake_waiters().
> + */
> +void mem_event_mark_and_pause(struct vcpu *v, struct mem_event_domain *med)
> +{
> + if ( !test_and_set_bit(med->pause_flag, &v->pause_flags) )
> + {
> + vcpu_pause_nosync(v);
> + med->blocked++;
> + }
> +}
> +
> +/*
> + * This must be preceeded by a call to claim_slot(), and is guaranteed to
preceded
Cheers,
Tim.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |