>From 483e55bc13c6ab246251fcd62c59adc7bf169c52 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 13 Jun 2017 10:56:52 -0400 Subject: [PATCH 3/7] xen-mceinj: Loop around xc_get_pfn_list Now that the xc_get_pfn_list can return max != num_pfns we need to take that into account and loop around. While at it fix the code: - Move the memset in the loop. - Change the loop conditions to exit if the mfn has been found. - Explain why 262144 is used. - Add munmap if we failed to allocate the buffer. Signed-off-by: Konrad Rzeszutek Wilk --- tools/tests/mce-test/tools/xen-mceinj.c | 67 ++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/tools/tests/mce-test/tools/xen-mceinj.c b/tools/tests/mce-test/tools/xen-mceinj.c index 22b4401..9c90235 100644 --- a/tools/tests/mce-test/tools/xen-mceinj.c +++ b/tools/tests/mce-test/tools/xen-mceinj.c @@ -264,7 +264,7 @@ static uint64_t guest_mfn(xc_interface *xc_handle, unsigned long m2p_mfn0; unsigned int guest_width; unsigned long version; - long max_gpfn,i; + unsigned long max_gpfn, i, start_pfn, max, old_v; uint64_t mfn = MCE_INVALID_MFN; if ( domain > DOMID_FIRST_RESERVED ) @@ -284,40 +284,63 @@ static uint64_t guest_mfn(xc_interface *xc_handle, &pt_levels, &guest_width) ) err(xc_handle, "Failed to get platform information\n"); - /* Get guest's pfn list */ - pfn_buf = malloc(sizeof(uint64_t) * max_gpfn); - if ( !pfn_buf ) - err(xc_handle, "Failed to alloc pfn buf\n"); - memset(pfn_buf, 0, sizeof(uint64_t) * max_gpfn); - - ret = xc_get_pfn_list(xc_handle, domain, pfn_buf, 0, max_gpfn, &version); - if ( ret < 0 ) { - free(pfn_buf); - err(xc_handle, "Failed to get pfn list %x\n", ret); - } + max = 262144 /* 1GB of MFNs. */; /* Now get the m2p table */ live_m2p = xc_map_m2p(xc_handle, max_mfn, PROT_READ, &m2p_mfn0); if ( !live_m2p ) err(xc_handle, "Failed to map live M2P table\n"); - /* match the mapping */ - for ( i = 0; i < max_gpfn; i++ ) + + /* Get guest's pfn list */ + pfn_buf = alloc(sizeof(uint64_t) * max); + if ( !pfn_buf ) { - uint64_t tmp; - tmp = pfn_buf[i]; + munmap(live_m2p, M2P_SIZE(max_mfn)); + err(xc_handle, "Failed to alloc pfn buf\n"); + } - if (mfn_valid(tmp) && (mfn_to_pfn(tmp) == gpfn)) - { - mfn = tmp; - Lprintf("We get the mfn 0x%lx for this injection\n", mfn); + start_pfn = 0; + old_v = version = 0; + do { + memset(pfn_buf, 0, sizeof(uint64_t) * max); + ret = xc_get_pfn_list(xc_handle, domain, pfn_buf, start_pfn, max, &version); + if ( old_v != version ) { + Lprintf("P2M changed, refetching.\n"); + start_pfn = 0; + old_v = version; + continue; + } + + if ( ret < 0 ) break; + + Lprintf("%ld/%ld .. \n", start_pfn, max_gpfn); + + if ( max != ret ) + max = ret; /* Update it for the next iteration. */ + + start_pfn += ret; + + for ( i = 0; i < ret; i++ ) + { + uint64_t tmp; + tmp = pfn_buf[i]; + + if (mfn_valid(tmp) && (mfn_to_pfn(tmp) == gpfn)) + { + mfn = tmp; + Lprintf("We get the mfn 0x%lx for this injection\n", mfn); + break; + } } - } + } while ( start_pfn < max_gpfn && (mce == MCE_INVALID_MFN) ); munmap(live_m2p, M2P_SIZE(max_mfn)); - free(pfn_buf); + if ( ret < 0 ) + err(xc_handle, "Failed to get pfn list %x\n", ret); + return mfn; } -- 2.9.4