[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 4 of 4] Add tracing to mem_event and p2m_mem_paging functions
# HG changeset patch # User Olaf Hering <olaf@xxxxxxxxx> # Date 1322737677 -3600 # Node ID 0bf827a48a3c9efd43fe04c291b553d2bec46f8b # Parent c09ac3717a025a8ead44bbc795fedda715d134c7 Add tracing to mem_event and p2m_mem_paging functions Maintaining these trace_var calls out-of-tree became a burden and made debugging paging related issues harder. So putting it into the tree will ease debugging with xenalyze. Signed-off-by: Olaf Hering <olaf@xxxxxxxxx> diff -r c09ac3717a02 -r 0bf827a48a3c xen/arch/x86/mm/mem_event.c --- a/xen/arch/x86/mm/mem_event.c +++ b/xen/arch/x86/mm/mem_event.c @@ -24,6 +24,7 @@ #include <asm/domain.h> #include <xen/event.h> #include <xen/wait.h> +#include <xen/trace.h> #include <asm/p2m.h> #include <asm/mem_event.h> #include <asm/mem_paging.h> @@ -149,6 +150,13 @@ static int _mem_event_put_request(struct mem_event_front_ring_t *front_ring; int free_requests; RING_IDX req_prod; + struct trc_mem_event_put_request T = { .td = d->domain_id }; + int ret = 0; + + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.ring_bit = med->bit; + T.gfn = req->gfn; mem_event_ring_lock(med); @@ -156,7 +164,7 @@ static int _mem_event_put_request(struct /* Requests from foreign domain were claimed in mem_event_check_ring() */ if ((current->domain == d && free_requests < med->foreign_producers) || !free_requests) { mem_event_ring_unlock(med); - return 0; + goto out; } front_ring = &med->front_ring; @@ -176,7 +184,15 @@ static int _mem_event_put_request(struct notify_via_xen_event_channel(d, med->xen_port); - return 1; + ret = 1; + +out: + T.ret = ret; + T.room = free_requests; + T.foreign_producers = med->foreign_producers + ret; + trace_var(TRC_MEM_EVENT_PUT_REQUEST, 1, sizeof(T), &T); + + return ret; } void mem_event_put_request(struct domain *d, struct mem_event_domain *med, diff -r c09ac3717a02 -r 0bf827a48a3c xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -31,6 +31,7 @@ #include <asm/hvm/vmx/vmx.h> /* ept_p2m_init() */ #include <xen/iommu.h> #include <xen/wait.h> +#include <xen/trace.h> #include <asm/mem_event.h> #include <public/mem_event.h> #include <asm/mem_sharing.h> @@ -215,7 +216,12 @@ static struct p2m_mem_paging_queue *p2m_ { struct p2m_mem_paging_queue_head *h; struct p2m_mem_paging_queue *q, *q_match, *q_free; + struct trc_mem_p2m_paging_queue T = { .td = d->domain_id }; + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = gfn; + h = d->arch.hvm_domain.gfn_queue; q_match = q_free = NULL; @@ -238,19 +244,37 @@ static struct p2m_mem_paging_queue *p2m_ printk("wq woken for gfn %u:%u %lx %u %u %u\n", current->domain->domain_id, current->vcpu_id, gfn, q_match->index, q_match->woken, q_match->waiters); q_match->waiters++; q_match->gfn = gfn; + + T.waiters = q_match->waiters; + T.woken = q_match->woken; + T.index = q_match->index; } + trace_var(TRC_MEM_P2M_PAGING_GET_QUEUE, 1, sizeof(T), &T); + if (!q_match) printk("No wq_get for gfn %u:%u %lx\n", current->domain->domain_id, current->vcpu_id, gfn); + spin_unlock(&d->arch.hvm_domain.gfn_lock); return q_match; } static void p2m_mem_paging_put_queue(struct domain *d, struct p2m_mem_paging_queue *q_match) { + struct trc_mem_p2m_paging_queue T = { .td = d->domain_id }; + + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = q_match->gfn; + T.waiters = q_match->waiters; + T.woken = q_match->woken; + T.index = q_match->index; + spin_lock(&d->arch.hvm_domain.gfn_lock); + trace_var(TRC_MEM_P2M_PAGING_PUT_QUEUE, 1, sizeof(T), &T); + if (q_match->waiters == 0) printk("wq_put no waiters, gfn %u:%u %lx %u\n", current->domain->domain_id, current->vcpu_id, q_match->gfn, q_match->woken); else if (--q_match->waiters == 0) @@ -263,6 +287,11 @@ static void p2m_mem_paging_wake_queue(st { struct p2m_mem_paging_queue_head *h; struct p2m_mem_paging_queue *q, *q_match = NULL; + struct trc_mem_p2m_paging_queue T = { .td = d->domain_id }; + + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = gfn; spin_lock(&d->arch.hvm_domain.gfn_lock); @@ -277,8 +306,15 @@ static void p2m_mem_paging_wake_queue(st if (q_match->woken || q_match->waiters == 0) printk("Wrong wake for gfn %u:%u %p %lx %u %u\n", current->domain->domain_id, current->vcpu_id, q_match, gfn, q_match->woken, q_match->waiters); q_match->woken++; + + T.waiters = q_match->waiters; + T.woken = q_match->woken; + T.index = q_match->index; + wake_up_all(&q_match->wq); } + trace_var(TRC_MEM_P2M_PAGING_WAKE_QUEUE, 1, sizeof(T), &T); + spin_unlock(&d->arch.hvm_domain.gfn_lock); } @@ -937,34 +973,45 @@ int p2m_mem_paging_nominate(struct domai p2m_access_t a; mfn_t mfn; int ret; + struct trc_mem_p2m_paging T = { .td = d->domain_id }; + + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = gfn; p2m_lock(p2m); mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, p2m_query, NULL); + T.reason++; /* Check if mfn is valid */ ret = -EINVAL; if ( !mfn_valid(mfn) ) goto out; + T.reason++; /* Check p2m type */ ret = -EAGAIN; if ( !p2m_is_pageable(p2mt) ) goto out; + T.reason++; /* Check for io memory page */ if ( is_iomem_page(mfn_x(mfn)) ) goto out; + T.reason++; /* Check page count and type */ page = mfn_to_page(mfn); if ( (page->count_info & (PGC_count_mask | PGC_allocated)) != (1 | PGC_allocated) ) goto out; + T.reason++; if ( (page->u.inuse.type_info & PGT_type_mask) != PGT_none ) goto out; + T.reason++; /* Fix p2m entry */ set_p2m_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2m_ram_paging_out, a); audit_p2m(p2m, 1); @@ -972,6 +1019,10 @@ int p2m_mem_paging_nominate(struct domai out: p2m_unlock(p2m); + + T.mfn = mfn_x(mfn); + T.p2mt = p2mt; + trace_var(TRC_MEM_P2M_PAGING_NOMINATE, 1, sizeof(T), &T); return ret; } @@ -1002,6 +1053,11 @@ int p2m_mem_paging_evict(struct domain * mfn_t mfn; struct p2m_domain *p2m = p2m_get_hostp2m(d); int ret = -EINVAL; + struct trc_mem_p2m_paging T = { .td = d->domain_id }; + + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = gfn; p2m_lock(p2m); @@ -1010,24 +1066,29 @@ int p2m_mem_paging_evict(struct domain * if ( unlikely(!mfn_valid(mfn)) ) goto out; + T.reason++; /* Allow only nominated pages */ if ( p2mt != p2m_ram_paging_out ) goto out; + T.reason++; ret = -EBUSY; /* Get the page so it doesn't get modified under Xen's feet */ page = mfn_to_page(mfn); if ( unlikely(!get_page(page, d)) ) goto out; + T.reason++; /* Check page count and type once more */ if ( (page->count_info & (PGC_count_mask | PGC_allocated)) != (2 | PGC_allocated) ) goto out_put; + T.reason++; if ( (page->u.inuse.type_info & PGT_type_mask) != PGT_none ) goto out_put; + T.reason++; /* Decrement guest domain's ref count of the page */ if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) put_page(page); @@ -1050,6 +1111,12 @@ int p2m_mem_paging_evict(struct domain * out: p2m_unlock(p2m); + + T.flag_evict_fail = !!ret; + T.mfn = mfn_x(mfn); + T.p2mt = p2mt; + trace_var(TRC_MEM_P2M_PAGING_EVICT, 1, sizeof(T), &T); + return ret; } @@ -1065,10 +1132,16 @@ int p2m_mem_paging_evict(struct domain * void p2m_mem_paging_drop_page(struct domain *d, unsigned long gfn) { mem_event_request_t req = { .type = MEM_EVENT_TYPE_PAGING, .gfn = gfn }; + struct trc_mem_p2m_paging T = { .td = d->domain_id }; /* Send release notification to pager */ req.flags = MEM_EVENT_FLAG_DROP_PAGE; + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = gfn; + trace_var(TRC_MEM_P2M_PAGING_DROP, 1, sizeof(T), &T); + mem_event_put_request(d, &d->mem_event->paging, &req); } @@ -1101,11 +1174,13 @@ void p2m_mem_paging_populate(struct doma p2m_access_t a; mfn_t mfn; struct p2m_domain *p2m = p2m_get_hostp2m(d); - int put_request = 0; + int put_request = 0, ring_full; + struct trc_mem_p2m_paging T = { .td = d->domain_id }; /* Check that there's space on the ring for this request */ - if ( mem_event_check_ring(d, &d->mem_event->paging) ) - return; + ring_full = mem_event_check_ring(d, &d->mem_event->paging); + if ( ring_full ) + goto trace; /* Fix p2m mapping */ p2m_lock(p2m); @@ -1127,11 +1202,24 @@ void p2m_mem_paging_populate(struct doma } p2m_unlock(p2m); - /* One request per gfn, guest vcpus go to sleep, foreigners try again */ - if ( put_request ) - mem_event_put_request(d, &d->mem_event->paging, &req); - else - mem_event_put_req_producers(d, &d->mem_event->paging); + T.mfn = mfn_x(mfn); + T.p2mt = p2mt; + +trace: + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = gfn; + T.reason = ring_full; + T.flag_drop_page = put_request; + trace_var(TRC_MEM_P2M_PAGING_POPULATE, 1, sizeof(T), &T); + + if ( !ring_full ) { + /* One request per gfn, guest vcpus go to sleep, foreigners try again */ + if ( put_request ) + mem_event_put_request(d, &d->mem_event->paging, &req); + else + mem_event_put_req_producers(d, &d->mem_event->paging); + } } /** @@ -1153,6 +1241,7 @@ int p2m_mem_paging_prep(struct domain *d mfn_t mfn; struct p2m_domain *p2m = p2m_get_hostp2m(d); int ret; + struct trc_mem_p2m_paging T = { .td = d->domain_id }; p2m_lock(p2m); @@ -1184,6 +1273,15 @@ int p2m_mem_paging_prep(struct domain *d out: p2m_unlock(p2m); + + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = gfn; + T.mfn = mfn_x(mfn); + T.p2mt = p2mt; + T.reason = ret; + trace_var(TRC_MEM_P2M_PAGING_PREP, 1, sizeof(T), &T); + return ret; } @@ -1209,6 +1307,7 @@ void p2m_mem_paging_resume(struct domain p2m_type_t p2mt; p2m_access_t a; mfn_t mfn; + struct trc_mem_p2m_paging T = { .td = d->domain_id }; /* Pull the response off the ring */ mem_event_get_response(&d->mem_event->paging, &rsp); @@ -1230,8 +1329,16 @@ void p2m_mem_paging_resume(struct domain audit_p2m(p2m, 1); } p2m_unlock(p2m); + T.mfn = mfn_x(mfn); + T.p2mt = p2mt; } + T.d = current->domain->domain_id; + T.v = current->vcpu_id; + T.gfn = rsp.gfn; + T.flag_drop_page = !!(rsp.flags & MEM_EVENT_FLAG_DROP_PAGE); + trace_var(TRC_MEM_P2M_PAGING_RESUME, 1, sizeof(T), &T); + /* Wake vcpus waiting for room in the ring */ mem_event_wake_requesters(&d->mem_event->paging); diff -r c09ac3717a02 -r 0bf827a48a3c xen/include/public/trace.h --- a/xen/include/public/trace.h +++ b/xen/include/public/trace.h @@ -94,6 +94,37 @@ #define TRC_MEM_POD_ZERO_RECLAIM (TRC_MEM + 17) #define TRC_MEM_POD_SUPERPAGE_SPLINTER (TRC_MEM + 18) +#define TRC_MEM_EVENT_PUT_REQUEST (TRC_MEM + 19) +struct trc_mem_event_put_request { + unsigned int d:16, v:16; + unsigned int td:16, room:16; + unsigned int gfn; + unsigned int foreign_producers:16, ret:1, ring_bit:5; +} __attribute__((packed)); + +#define TRC_MEM_P2M_PAGING_NOMINATE (TRC_MEM + 20) +#define TRC_MEM_P2M_PAGING_EVICT (TRC_MEM + 21) +#define TRC_MEM_P2M_PAGING_DROP (TRC_MEM + 22) +#define TRC_MEM_P2M_PAGING_POPULATE (TRC_MEM + 23) +#define TRC_MEM_P2M_PAGING_PREP (TRC_MEM + 24) +#define TRC_MEM_P2M_PAGING_RESUME (TRC_MEM + 25) +struct trc_mem_p2m_paging { + unsigned int d:16, v:16; + unsigned int td:16, p2mt:5, reason:5, flag_evict_fail:1, flag_drop_page:1; + unsigned int gfn; + unsigned int mfn; +} __attribute__((packed)); + +#define TRC_MEM_P2M_PAGING_GET_QUEUE (TRC_MEM + 26) +#define TRC_MEM_P2M_PAGING_PUT_QUEUE (TRC_MEM + 27) +#define TRC_MEM_P2M_PAGING_WAKE_QUEUE (TRC_MEM + 28) +struct trc_mem_p2m_paging_queue { + unsigned int d:16, v:16; + unsigned int td:16, woken:8; + unsigned int gfn; + unsigned int index:16, waiters:16; +} __attribute__((packed)); + #define TRC_PV_HYPERCALL (TRC_PV + 1) #define TRC_PV_TRAP (TRC_PV + 3) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |