* [Crash-utility] [PATCH] xen: Add support for domU with Linux kernel 3.19 and newer
@ 2017-05-24 7:13 Honglei Wang
2017-05-24 15:56 ` Dave Anderson
0 siblings, 1 reply; 4+ messages in thread
From: Honglei Wang @ 2017-05-24 7:13 UTC (permalink / raw)
To: crash-utility, kexec, xen-devel
Cc: jgross, honglei.wang, konrad.wilk, daniel.kiper, ptesarik,
anderson, eric.devolder
crash patch c3413456599161cabc4e910a0ae91dfe5eec3c21 (xen: Add support for
dom0 with Linux kernel 3.19 and newer) from Daniel made crash utility
support xen dom0 vmcores after linux kernel commit
054954eb051f35e74b75a566a96fe756015352c8 (xen: switch to linear virtual
mapped sparse p2m list).
This patch can be deemed as a subsequent and make this utility support Xen
PV domU dumpfiles again.
Basically speaking, readmem() can't be used to read xen_p2m_addr associate
memory directly during m2p translation. It introduces infinite recursion.
Following call sequence shows the scenario, it comes from a section of
backtrace with only kvaddr, machine addr and mfn left as parameter:
module_init()
/* The first readmem() from module_init(). */
readmem(addr=0xffffffffa02fe4a0)
/* readmem() needs physical address, so calls kvtop(). */
kvtop(kvaddr=0xffffffffa02fe4a0)
x86_64_kvtop(kvaddr=ffffffffa02fe4a0)
/* Calculate physical address by traversing page tables. */
x86_64_kvtop_xen_wpt(kvaddr=0xffffffffa02fe4a0)
/*
* x86_64_kvtop_xen_wpt() is going to traverse the page table to
* get the physical address for 0xffffffffa02fe4a0. So, at first it
* is needed to translate the pgd from machine address to physical
* address. So invoke xen_m2p() here to do the translation. 0x58687f000
* is the pgd machine address in x86_64_kvtop_xen_wpt() and is needed
* to be translated to its physical address.
*/
xen_m2p(machine=0x58687f000)
__xen_m2p(machine=0x58687f000, mfn=0x58687f)
/*
* __xen_m2p() is going to search mfn 0x58687f in p2m VMA which starts
* at VMA 0xffffc900001cf000. It compares every mfn stored in it with
* 0x58687f. Once it's proved 0x58687f is one mfn in the p2m, its offset
* will be used to calculate the pfn.
*
* readmem() is invoked by __xen_m2p() to read the page from VMA
* 0xffffc900001cf000 here.
*/
readmem(addr=0xffffc900001cf000)
/*
* readmem() needs physical address of 0xffffc900001cf000 to make the
* reading done. So it invokes kvtop() to get the physical address.
*/
kvtop(kvaddr=0xffffc900001cf000)
x86_64_kvtop(kvaddr=0xffffc900001cf000)
/* It needs to calculate physical address by traversing page tables. */
x86_64_kvtop_xen_wpt(kvaddr=0xffffc900001cf000)
/*
* 0x581b7e000 is the machine address of pgd need to be translated here.
* The mfn is calculated in this way at x86_64_kvtop_xen_wpt():
*
* pml4 = ((ulong *)machdep->machspec->pml4) + pml4_index(kvaddr);
* pgd_paddr = (*pml4) & PHYSICAL_PAGE_MASK;
*
* The kvaddr 0xffffc900001cf000 here is quite different from the one
* above, so the machine address of pgd is not the same one. And this
* pgd is the one we use to access the VMA of p2m table.
*/
xen_m2p(machine=0x581b7e000)
__xen_m2p(machine=0x581b7e000, mfn=0x581b7e)
/*
* Looking for mfn 0x581b7e in the range of p2m page which starts at
* VMA 0xffffc900001f5000.
*/
readmem(addr=0xffffc900001f5000)
/* Need physical address of VMA 0xffffc900001f5000 as same reason above. */
kvtop(kvaddr=0xffffc900001f5000)
x86_64_kvtop(kvaddr=0xffffc900001f5000)
/* Need to traverse page tables to calculate physical address for it. */
x86_64_kvtop_xen_wpt(kvaddr=0xffffc900001f5000)
/*
* Unfortunately, machine address 0x581b7e000 have to be translated again.
* Endless loop starts from here.
*/
xen_m2p(machine=0x581b7e000)
__xen_m2p(machine=0x581b7e000, mfn=0x581b7e)
readmem(addr=0xffffc900001f5000)
Fortunately, PV domU p2m mapping is also stored at xd->xfd + xch_index_offset
and organized as struct xen_dumpcore_p2m. We have a chance to read the p2m
stuff directly from there, and then we avoid the loop above.
So, this patch implements a special reading function read_xc_p2m() to extract
the mfns from xd->xfd + xch_index_offset. This function does not need to read
mfns from p2m VMA like readmem() does, so, we avoid the endless loop introduced
by the address translation.
Signed-off-by: Honglei Wang <honglei.wang@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
kernel.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
xendump.c | 2 +-
xendump.h | 2 +
3 files changed, 140 insertions(+), 15 deletions(-)
diff --git a/kernel.c b/kernel.c
index 395736c..7a5ce64 100644
--- a/kernel.c
+++ b/kernel.c
@@ -22,6 +22,7 @@
#include <libgen.h>
#include <ctype.h>
#include <stdbool.h>
+#include "xendump.h"
static void do_module_cmd(ulong, char *, ulong, char *, char *);
static void show_module_taint(void);
@@ -67,6 +68,9 @@ static ulong __xen_m2p(ulonglong, ulong);
static ulong __xen_pvops_m2p_l2(ulonglong, ulong);
static ulong __xen_pvops_m2p_l3(ulonglong, ulong);
static ulong __xen_pvops_m2p_hyper(ulonglong, ulong);
+static ulong __xen_pvops_m2p_domU(ulonglong, ulong);
+static int read_xc_p2m(ulonglong addr, void *buffer, long size);
+static void read_p2m(ulong cache_index, int memtype, void *buffer);
static int search_mapping_page(ulong, ulong *, ulong *, ulong *);
static void read_in_kernel_config_err(int, char *);
static void BUG_bytes_init(void);
@@ -181,10 +185,7 @@ kernel_init()
&kt->pvops_xen.p2m_mid_missing);
get_symbol_data("p2m_missing", sizeof(ulong),
&kt->pvops_xen.p2m_missing);
- } else if (symbol_exists("xen_p2m_addr")) {
- if (!XEN_CORE_DUMPFILE())
- error(FATAL, "p2m array in new format is unreadable.");
- } else {
+ } else if (!symbol_exists("xen_p2m_addr")) {
kt->pvops_xen.p2m_top_entries = get_array_length("p2m_top", NULL, 0);
kt->pvops_xen.p2m_top = symbol_value("p2m_top");
kt->pvops_xen.p2m_missing = symbol_value("p2m_missing");
@@ -9305,13 +9306,7 @@ __xen_m2p(ulonglong machine, ulong mfn)
if (memtype == PHYSADDR)
pc->curcmd_flags |= XEN_MACHINE_ADDR;
- if (!readmem(kt->p2m_mapping_cache[c].mapping, memtype,
- mp, PAGESIZE(), "phys_to_machine_mapping page (cached)",
- RETURN_ON_ERROR))
- error(FATAL, "cannot access "
- "phys_to_machine_mapping page\n");
- else
- kt->last_mapping_read = kt->p2m_mapping_cache[c].mapping;
+ read_p2m(c, memtype, mp);
if (memtype == PHYSADDR)
pc->curcmd_flags &= ~XEN_MACHINE_ADDR;
@@ -9349,9 +9344,12 @@ __xen_m2p(ulonglong machine, ulong mfn)
*/
if (symbol_exists("p2m_mid_missing"))
pfn = __xen_pvops_m2p_l3(machine, mfn);
- else if (symbol_exists("xen_p2m_addr"))
- pfn = __xen_pvops_m2p_hyper(machine, mfn);
- else
+ else if (symbol_exists("xen_p2m_addr")) {
+ if (XEN_CORE_DUMPFILE())
+ pfn = __xen_pvops_m2p_hyper(machine, mfn);
+ else
+ pfn = __xen_pvops_m2p_domU(machine, mfn);
+ } else
pfn = __xen_pvops_m2p_l2(machine, mfn);
if (pfn != XEN_MFN_NOT_FOUND)
@@ -9559,6 +9557,131 @@ __xen_pvops_m2p_hyper(ulonglong machine, ulong mfn)
return XEN_MFN_NOT_FOUND;
}
+static void read_p2m(ulong cache_index, int memtype, void *buffer)
+{
+ /*
+ * Use special read function for PV domain p2m reading.
+ * See the comments of read_xc_p2m().
+ */
+ if (symbol_exists("xen_p2m_addr") && !XEN_CORE_DUMPFILE()) {
+ if (!read_xc_p2m(kt->p2m_mapping_cache[cache_index].mapping,
+ buffer, PAGESIZE()))
+ error(FATAL, "cannot access phys_to_machine_mapping page\n");
+ } else if (!readmem(kt->p2m_mapping_cache[cache_index].mapping, memtype,
+ buffer, PAGESIZE(), "phys_to_machine_mapping page (cached)",
+ RETURN_ON_ERROR))
+ error(FATAL, "cannot access phys_to_machine_mapping page\n");
+
+ kt->last_mapping_read = kt->p2m_mapping_cache[cache_index].mapping;
+}
+
+/*
+ * PV domain p2m mapping info is stored in xd->xfd at xch_index_offset. It
+ * is organized as struct xen_dumpcore_p2m and the pfns are progressively
+ * increased by 1 from 0.
+ *
+ * This is a special p2m reading function for xen PV domain vmcores after
+ * kernel commit 054954eb051f35e74b75a566a96fe756015352c8 (xen: switch
+ * to linear virtual mapped sparse p2m list). It is invoked for reading
+ * p2m associate stuff by read_p2m().
+ */
+static int read_xc_p2m(ulonglong addr, void *buffer, long size)
+{
+ ulong i, new_p2m_buf_size;
+ off_t offset;
+ struct xen_dumpcore_p2m *new_p2m_buf;
+ static struct xen_dumpcore_p2m *p2m_buf;
+ static ulong p2m_buf_size = 0;
+
+ if (size <= 0) {
+ if ((CRASHDEBUG(1) && !STREQ(pc->curcmd, "search")) ||
+ CRASHDEBUG(2))
+ error(INFO, "invalid size request: %ld\n", size);
+ return FALSE;
+ }
+
+ /*
+ * We extract xen_dumpcore_p2m.gmfn and copy them into the
+ * buffer. So, we need temporary p2m_buf whose size is
+ * (size * (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong)))
+ * to put xen_dumpcore_p2m structures read from xd->xfd.
+ */
+ new_p2m_buf_size = size * (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong));
+
+ if (p2m_buf_size != new_p2m_buf_size) {
+ p2m_buf_size = new_p2m_buf_size;
+
+ new_p2m_buf = realloc(p2m_buf, p2m_buf_size);
+ if (new_p2m_buf == NULL) {
+ free(p2m_buf);
+ error(FATAL, "cannot realloc p2m buffer\n");
+ }
+ p2m_buf = new_p2m_buf;
+ }
+
+ offset = addr * (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong));
+ offset += xd->xc_core.header.xch_index_offset;
+
+ if (lseek(xd->xfd, offset, SEEK_SET) == -1)
+ error(FATAL,
+ "cannot lseek to xch_index_offset offset 0x%lx\n", offset);
+ if (read(xd->xfd, (void*)p2m_buf, p2m_buf_size) != p2m_buf_size)
+ error(FATAL,
+ "cannot read from xch_index_offset offset 0x%lx\n", offset);
+
+ for (i = 0; i < size / sizeof(ulong); i++)
+ *((ulong *)buffer + i) = p2m_buf[i].gmfn;
+
+ return TRUE;
+}
+
+static ulong
+__xen_pvops_m2p_domU(ulonglong machine, ulong mfn)
+{
+ ulong c, end, i, mapping, p, pfn, start;
+
+ /*
+ * xch_nr_pages is the number of pages of p2m mapping. It is composed
+ * of struct xen_dumpcore_p2m. The stuff we want to copy into the mapping
+ * page is mfn whose type is unsigned long.
+ * So actual number of p2m pages should be:
+ *
+ * xch_nr_pages / (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong))
+ */
+ for (p = 0;
+ p < xd->xc_core.header.xch_nr_pages /
+ (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong));
+ ++p) {
+
+ mapping = p * PAGESIZE();
+
+ if (mapping != kt->last_mapping_read) {
+ if (!read_xc_p2m(mapping, (void *)kt->m2p_page, PAGESIZE()))
+ error(FATAL, "cannot read the last mapping page\n");
+ kt->last_mapping_read = mapping;
+ }
+ kt->p2m_pages_searched++;
+
+ if (search_mapping_page(mfn, &i, &start, &end)) {
+ pfn = p * XEN_PFNS_PER_PAGE + i;
+ c = kt->p2m_cache_index;
+ if (CRASHDEBUG (1))
+ console("mfn: %lx (%llx) i: %ld pfn: %lx (%llx)\n",
+ mfn, machine, i, pfn, XEN_PFN_TO_PSEUDO(pfn));
+
+ kt->p2m_mapping_cache[c].start = start;
+ kt->p2m_mapping_cache[c].end = end;
+ kt->p2m_mapping_cache[c].mapping = mapping;
+ kt->p2m_mapping_cache[c].pfn = p * XEN_PFNS_PER_PAGE;
+ kt->p2m_cache_index = (c+1) % P2M_MAPPING_CACHE;
+
+ return pfn;
+ }
+ }
+
+ return XEN_MFN_NOT_FOUND;
+}
+
/*
* Search for an mfn in the current mapping page, and if found,
* determine the range of contiguous mfns that it's contained
diff --git a/xendump.c b/xendump.c
index 8170b22..4bd59b5 100644
--- a/xendump.c
+++ b/xendump.c
@@ -19,7 +19,7 @@
#include "xendump.h"
static struct xendump_data xendump_data = { 0 };
-static struct xendump_data *xd = &xendump_data;
+struct xendump_data *xd = &xendump_data;
static int xc_save_verify(char *);
static int xc_core_verify(char *, char *);
diff --git a/xendump.h b/xendump.h
index 08d41b4..b7bae65 100644
--- a/xendump.h
+++ b/xendump.h
@@ -192,3 +192,5 @@ struct xen_dumpcore_p2m {
uint64_t pfn;
uint64_t gmfn;
};
+
+extern struct xendump_data *xd;
--
1.7.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Crash-utility] [PATCH] xen: Add support for domU with Linux kernel 3.19 and newer
2017-05-24 7:13 [Crash-utility] [PATCH] xen: Add support for domU with Linux kernel 3.19 and newer Honglei Wang
@ 2017-05-24 15:56 ` Dave Anderson
2017-05-25 1:32 ` Honglei Wang
2017-05-29 11:38 ` Daniel Kiper
0 siblings, 2 replies; 4+ messages in thread
From: Dave Anderson @ 2017-05-24 15:56 UTC (permalink / raw)
To: Honglei Wang
Cc: jgross, konrad wilk, ptesarik, daniel kiper, kexec, xen-devel,
eric devolder, crash-utility
----- Original Message -----
> crash patch c3413456599161cabc4e910a0ae91dfe5eec3c21 (xen: Add support for
> dom0 with Linux kernel 3.19 and newer) from Daniel made crash utility
> support xen dom0 vmcores after linux kernel commit
> 054954eb051f35e74b75a566a96fe756015352c8 (xen: switch to linear virtual
> mapped sparse p2m list).
>
> This patch can be deemed as a subsequent and make this utility support Xen
> PV domU dumpfiles again.
>
> Basically speaking, readmem() can't be used to read xen_p2m_addr associate
> memory directly during m2p translation. It introduces infinite recursion.
> Following call sequence shows the scenario, it comes from a section of
> backtrace with only kvaddr, machine addr and mfn left as parameter:
>
> module_init()
>
> /* The first readmem() from module_init(). */
> readmem(addr=0xffffffffa02fe4a0)
>
> /* readmem() needs physical address, so calls kvtop(). */
> kvtop(kvaddr=0xffffffffa02fe4a0)
> x86_64_kvtop(kvaddr=ffffffffa02fe4a0)
>
> /* Calculate physical address by traversing page tables. */
> x86_64_kvtop_xen_wpt(kvaddr=0xffffffffa02fe4a0)
>
> /*
> * x86_64_kvtop_xen_wpt() is going to traverse the page table to
> * get the physical address for 0xffffffffa02fe4a0. So, at first it
> * is needed to translate the pgd from machine address to physical
> * address. So invoke xen_m2p() here to do the translation. 0x58687f000
> * is the pgd machine address in x86_64_kvtop_xen_wpt() and is needed
> * to be translated to its physical address.
> */
> xen_m2p(machine=0x58687f000)
> __xen_m2p(machine=0x58687f000, mfn=0x58687f)
>
> /*
> * __xen_m2p() is going to search mfn 0x58687f in p2m VMA which starts
> * at VMA 0xffffc900001cf000. It compares every mfn stored in it with
> * 0x58687f. Once it's proved 0x58687f is one mfn in the p2m, its offset
> * will be used to calculate the pfn.
> *
> * readmem() is invoked by __xen_m2p() to read the page from VMA
> * 0xffffc900001cf000 here.
> */
> readmem(addr=0xffffc900001cf000)
>
> /*
> * readmem() needs physical address of 0xffffc900001cf000 to make the
> * reading done. So it invokes kvtop() to get the physical address.
> */
> kvtop(kvaddr=0xffffc900001cf000)
> x86_64_kvtop(kvaddr=0xffffc900001cf000)
>
> /* It needs to calculate physical address by traversing page tables. */
> x86_64_kvtop_xen_wpt(kvaddr=0xffffc900001cf000)
>
> /*
> * 0x581b7e000 is the machine address of pgd need to be translated here.
> * The mfn is calculated in this way at x86_64_kvtop_xen_wpt():
> *
> * pml4 = ((ulong *)machdep->machspec->pml4) + pml4_index(kvaddr);
> * pgd_paddr = (*pml4) & PHYSICAL_PAGE_MASK;
> *
> * The kvaddr 0xffffc900001cf000 here is quite different from the one
> * above, so the machine address of pgd is not the same one. And this
> * pgd is the one we use to access the VMA of p2m table.
> */
> xen_m2p(machine=0x581b7e000)
> __xen_m2p(machine=0x581b7e000, mfn=0x581b7e)
>
> /*
> * Looking for mfn 0x581b7e in the range of p2m page which starts at
> * VMA 0xffffc900001f5000.
> */
> readmem(addr=0xffffc900001f5000)
>
> /* Need physical address of VMA 0xffffc900001f5000 as same reason above. */
> kvtop(kvaddr=0xffffc900001f5000)
> x86_64_kvtop(kvaddr=0xffffc900001f5000)
>
> /* Need to traverse page tables to calculate physical address for it. */
> x86_64_kvtop_xen_wpt(kvaddr=0xffffc900001f5000)
>
> /*
> * Unfortunately, machine address 0x581b7e000 have to be translated again.
> * Endless loop starts from here.
> */
> xen_m2p(machine=0x581b7e000)
> __xen_m2p(machine=0x581b7e000, mfn=0x581b7e)
> readmem(addr=0xffffc900001f5000)
>
> Fortunately, PV domU p2m mapping is also stored at xd->xfd + xch_index_offset
> and organized as struct xen_dumpcore_p2m. We have a chance to read the p2m
> stuff directly from there, and then we avoid the loop above.
>
> So, this patch implements a special reading function read_xc_p2m() to extract
> the mfns from xd->xfd + xch_index_offset. This function does not need to read
> mfns from p2m VMA like readmem() does, so, we avoid the endless loop introduced
> by the address translation.
>
> Signed-off-by: Honglei Wang <honglei.wang@oracle.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Queued for crash-7.2.0:
https://github.com/crash-utility/crash/commit/5c52842a58a2602dba81de71831af98b2b53c6e0
Thanks,
Dave
> ---
> kernel.c | 151
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
> xendump.c | 2 +-
> xendump.h | 2 +
> 3 files changed, 140 insertions(+), 15 deletions(-)
>
> diff --git a/kernel.c b/kernel.c
> index 395736c..7a5ce64 100644
> --- a/kernel.c
> +++ b/kernel.c
> @@ -22,6 +22,7 @@
> #include <libgen.h>
> #include <ctype.h>
> #include <stdbool.h>
> +#include "xendump.h"
>
> static void do_module_cmd(ulong, char *, ulong, char *, char *);
> static void show_module_taint(void);
> @@ -67,6 +68,9 @@ static ulong __xen_m2p(ulonglong, ulong);
> static ulong __xen_pvops_m2p_l2(ulonglong, ulong);
> static ulong __xen_pvops_m2p_l3(ulonglong, ulong);
> static ulong __xen_pvops_m2p_hyper(ulonglong, ulong);
> +static ulong __xen_pvops_m2p_domU(ulonglong, ulong);
> +static int read_xc_p2m(ulonglong addr, void *buffer, long size);
> +static void read_p2m(ulong cache_index, int memtype, void *buffer);
> static int search_mapping_page(ulong, ulong *, ulong *, ulong *);
> static void read_in_kernel_config_err(int, char *);
> static void BUG_bytes_init(void);
> @@ -181,10 +185,7 @@ kernel_init()
> &kt->pvops_xen.p2m_mid_missing);
> get_symbol_data("p2m_missing", sizeof(ulong),
> &kt->pvops_xen.p2m_missing);
> - } else if (symbol_exists("xen_p2m_addr")) {
> - if (!XEN_CORE_DUMPFILE())
> - error(FATAL, "p2m array in new format is unreadable.");
> - } else {
> + } else if (!symbol_exists("xen_p2m_addr")) {
> kt->pvops_xen.p2m_top_entries = get_array_length("p2m_top", NULL, 0);
> kt->pvops_xen.p2m_top = symbol_value("p2m_top");
> kt->pvops_xen.p2m_missing = symbol_value("p2m_missing");
> @@ -9305,13 +9306,7 @@ __xen_m2p(ulonglong machine, ulong mfn)
> if (memtype == PHYSADDR)
> pc->curcmd_flags |= XEN_MACHINE_ADDR;
>
> - if (!readmem(kt->p2m_mapping_cache[c].mapping, memtype,
> - mp, PAGESIZE(), "phys_to_machine_mapping page (cached)",
> - RETURN_ON_ERROR))
> - error(FATAL, "cannot access "
> - "phys_to_machine_mapping page\n");
> - else
> - kt->last_mapping_read = kt->p2m_mapping_cache[c].mapping;
> + read_p2m(c, memtype, mp);
>
> if (memtype == PHYSADDR)
> pc->curcmd_flags &= ~XEN_MACHINE_ADDR;
> @@ -9349,9 +9344,12 @@ __xen_m2p(ulonglong machine, ulong mfn)
> */
> if (symbol_exists("p2m_mid_missing"))
> pfn = __xen_pvops_m2p_l3(machine, mfn);
> - else if (symbol_exists("xen_p2m_addr"))
> - pfn = __xen_pvops_m2p_hyper(machine, mfn);
> - else
> + else if (symbol_exists("xen_p2m_addr")) {
> + if (XEN_CORE_DUMPFILE())
> + pfn = __xen_pvops_m2p_hyper(machine, mfn);
> + else
> + pfn = __xen_pvops_m2p_domU(machine, mfn);
> + } else
> pfn = __xen_pvops_m2p_l2(machine, mfn);
>
> if (pfn != XEN_MFN_NOT_FOUND)
> @@ -9559,6 +9557,131 @@ __xen_pvops_m2p_hyper(ulonglong machine, ulong mfn)
> return XEN_MFN_NOT_FOUND;
> }
>
> +static void read_p2m(ulong cache_index, int memtype, void *buffer)
> +{
> + /*
> + * Use special read function for PV domain p2m reading.
> + * See the comments of read_xc_p2m().
> + */
> + if (symbol_exists("xen_p2m_addr") && !XEN_CORE_DUMPFILE()) {
> + if (!read_xc_p2m(kt->p2m_mapping_cache[cache_index].mapping,
> + buffer, PAGESIZE()))
> + error(FATAL, "cannot access phys_to_machine_mapping page\n");
> + } else if (!readmem(kt->p2m_mapping_cache[cache_index].mapping, memtype,
> + buffer, PAGESIZE(), "phys_to_machine_mapping page (cached)",
> + RETURN_ON_ERROR))
> + error(FATAL, "cannot access phys_to_machine_mapping page\n");
> +
> + kt->last_mapping_read = kt->p2m_mapping_cache[cache_index].mapping;
> +}
> +
> +/*
> + * PV domain p2m mapping info is stored in xd->xfd at xch_index_offset. It
> + * is organized as struct xen_dumpcore_p2m and the pfns are progressively
> + * increased by 1 from 0.
> + *
> + * This is a special p2m reading function for xen PV domain vmcores after
> + * kernel commit 054954eb051f35e74b75a566a96fe756015352c8 (xen: switch
> + * to linear virtual mapped sparse p2m list). It is invoked for reading
> + * p2m associate stuff by read_p2m().
> + */
> +static int read_xc_p2m(ulonglong addr, void *buffer, long size)
> +{
> + ulong i, new_p2m_buf_size;
> + off_t offset;
> + struct xen_dumpcore_p2m *new_p2m_buf;
> + static struct xen_dumpcore_p2m *p2m_buf;
> + static ulong p2m_buf_size = 0;
> +
> + if (size <= 0) {
> + if ((CRASHDEBUG(1) && !STREQ(pc->curcmd, "search")) ||
> + CRASHDEBUG(2))
> + error(INFO, "invalid size request: %ld\n", size);
> + return FALSE;
> + }
> +
> + /*
> + * We extract xen_dumpcore_p2m.gmfn and copy them into the
> + * buffer. So, we need temporary p2m_buf whose size is
> + * (size * (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong)))
> + * to put xen_dumpcore_p2m structures read from xd->xfd.
> + */
> + new_p2m_buf_size = size * (sizeof(struct xen_dumpcore_p2m) /
> sizeof(ulong));
> +
> + if (p2m_buf_size != new_p2m_buf_size) {
> + p2m_buf_size = new_p2m_buf_size;
> +
> + new_p2m_buf = realloc(p2m_buf, p2m_buf_size);
> + if (new_p2m_buf == NULL) {
> + free(p2m_buf);
> + error(FATAL, "cannot realloc p2m buffer\n");
> + }
> + p2m_buf = new_p2m_buf;
> + }
> +
> + offset = addr * (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong));
> + offset += xd->xc_core.header.xch_index_offset;
> +
> + if (lseek(xd->xfd, offset, SEEK_SET) == -1)
> + error(FATAL,
> + "cannot lseek to xch_index_offset offset 0x%lx\n", offset);
> + if (read(xd->xfd, (void*)p2m_buf, p2m_buf_size) != p2m_buf_size)
> + error(FATAL,
> + "cannot read from xch_index_offset offset 0x%lx\n", offset);
> +
> + for (i = 0; i < size / sizeof(ulong); i++)
> + *((ulong *)buffer + i) = p2m_buf[i].gmfn;
> +
> + return TRUE;
> +}
> +
> +static ulong
> +__xen_pvops_m2p_domU(ulonglong machine, ulong mfn)
> +{
> + ulong c, end, i, mapping, p, pfn, start;
> +
> + /*
> + * xch_nr_pages is the number of pages of p2m mapping. It is composed
> + * of struct xen_dumpcore_p2m. The stuff we want to copy into the mapping
> + * page is mfn whose type is unsigned long.
> + * So actual number of p2m pages should be:
> + *
> + * xch_nr_pages / (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong))
> + */
> + for (p = 0;
> + p < xd->xc_core.header.xch_nr_pages /
> + (sizeof(struct xen_dumpcore_p2m) / sizeof(ulong));
> + ++p) {
> +
> + mapping = p * PAGESIZE();
> +
> + if (mapping != kt->last_mapping_read) {
> + if (!read_xc_p2m(mapping, (void *)kt->m2p_page, PAGESIZE()))
> + error(FATAL, "cannot read the last mapping page\n");
> + kt->last_mapping_read = mapping;
> + }
> + kt->p2m_pages_searched++;
> +
> + if (search_mapping_page(mfn, &i, &start, &end)) {
> + pfn = p * XEN_PFNS_PER_PAGE + i;
> + c = kt->p2m_cache_index;
> + if (CRASHDEBUG (1))
> + console("mfn: %lx (%llx) i: %ld pfn: %lx (%llx)\n",
> + mfn, machine, i, pfn, XEN_PFN_TO_PSEUDO(pfn));
> +
> + kt->p2m_mapping_cache[c].start = start;
> + kt->p2m_mapping_cache[c].end = end;
> + kt->p2m_mapping_cache[c].mapping = mapping;
> + kt->p2m_mapping_cache[c].pfn = p * XEN_PFNS_PER_PAGE;
> + kt->p2m_cache_index = (c+1) % P2M_MAPPING_CACHE;
> +
> + return pfn;
> + }
> + }
> +
> + return XEN_MFN_NOT_FOUND;
> +}
> +
> /*
> * Search for an mfn in the current mapping page, and if found,
> * determine the range of contiguous mfns that it's contained
> diff --git a/xendump.c b/xendump.c
> index 8170b22..4bd59b5 100644
> --- a/xendump.c
> +++ b/xendump.c
> @@ -19,7 +19,7 @@
> #include "xendump.h"
>
> static struct xendump_data xendump_data = { 0 };
> -static struct xendump_data *xd = &xendump_data;
> +struct xendump_data *xd = &xendump_data;
>
> static int xc_save_verify(char *);
> static int xc_core_verify(char *, char *);
> diff --git a/xendump.h b/xendump.h
> index 08d41b4..b7bae65 100644
> --- a/xendump.h
> +++ b/xendump.h
> @@ -192,3 +192,5 @@ struct xen_dumpcore_p2m {
> uint64_t pfn;
> uint64_t gmfn;
> };
> +
> +extern struct xendump_data *xd;
> --
> 1.7.1
>
>
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Crash-utility] [PATCH] xen: Add support for domU with Linux kernel 3.19 and newer
2017-05-24 15:56 ` Dave Anderson
@ 2017-05-25 1:32 ` Honglei Wang
2017-05-29 11:38 ` Daniel Kiper
1 sibling, 0 replies; 4+ messages in thread
From: Honglei Wang @ 2017-05-25 1:32 UTC (permalink / raw)
To: Dave Anderson
Cc: jgross, konrad wilk, ptesarik, daniel kiper, kexec, xen-devel,
eric devolder, crash-utility
Hi Dave,
On 05/24/2017 11:56 PM, Dave Anderson wrote:
> Queued for crash-7.2.0:
> https://github.com/crash-utility/crash/commit/5c52842a58a2602dba81de71831af98b2b53c6e0
>
> Thanks,
> Dave
>
It's great! Thanks a lot.
Honglei
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Crash-utility] [PATCH] xen: Add support for domU with Linux kernel 3.19 and newer
2017-05-24 15:56 ` Dave Anderson
2017-05-25 1:32 ` Honglei Wang
@ 2017-05-29 11:38 ` Daniel Kiper
1 sibling, 0 replies; 4+ messages in thread
From: Daniel Kiper @ 2017-05-29 11:38 UTC (permalink / raw)
To: Dave Anderson
Cc: jgross, Honglei Wang, konrad wilk, ptesarik, kexec, xen-devel,
eric devolder, crash-utility
On Wed, May 24, 2017 at 11:56:28AM -0400, Dave Anderson wrote:
> ----- Original Message -----
> > crash patch c3413456599161cabc4e910a0ae91dfe5eec3c21 (xen: Add support for
> > dom0 with Linux kernel 3.19 and newer) from Daniel made crash utility
> > support xen dom0 vmcores after linux kernel commit
> > 054954eb051f35e74b75a566a96fe756015352c8 (xen: switch to linear virtual
> > mapped sparse p2m list).
> >
> > This patch can be deemed as a subsequent and make this utility support Xen
> > PV domU dumpfiles again.
> >
> > Basically speaking, readmem() can't be used to read xen_p2m_addr associate
> > memory directly during m2p translation. It introduces infinite recursion.
> > Following call sequence shows the scenario, it comes from a section of
> > backtrace with only kvaddr, machine addr and mfn left as parameter:
> >
> > module_init()
> >
> > /* The first readmem() from module_init(). */
> > readmem(addr=0xffffffffa02fe4a0)
> >
> > /* readmem() needs physical address, so calls kvtop(). */
> > kvtop(kvaddr=0xffffffffa02fe4a0)
> > x86_64_kvtop(kvaddr=ffffffffa02fe4a0)
> >
> > /* Calculate physical address by traversing page tables. */
> > x86_64_kvtop_xen_wpt(kvaddr=0xffffffffa02fe4a0)
> >
> > /*
> > * x86_64_kvtop_xen_wpt() is going to traverse the page table to
> > * get the physical address for 0xffffffffa02fe4a0. So, at first it
> > * is needed to translate the pgd from machine address to physical
> > * address. So invoke xen_m2p() here to do the translation. 0x58687f000
> > * is the pgd machine address in x86_64_kvtop_xen_wpt() and is needed
> > * to be translated to its physical address.
> > */
> > xen_m2p(machine=0x58687f000)
> > __xen_m2p(machine=0x58687f000, mfn=0x58687f)
> >
> > /*
> > * __xen_m2p() is going to search mfn 0x58687f in p2m VMA which starts
> > * at VMA 0xffffc900001cf000. It compares every mfn stored in it with
> > * 0x58687f. Once it's proved 0x58687f is one mfn in the p2m, its offset
> > * will be used to calculate the pfn.
> > *
> > * readmem() is invoked by __xen_m2p() to read the page from VMA
> > * 0xffffc900001cf000 here.
> > */
> > readmem(addr=0xffffc900001cf000)
> >
> > /*
> > * readmem() needs physical address of 0xffffc900001cf000 to make the
> > * reading done. So it invokes kvtop() to get the physical address.
> > */
> > kvtop(kvaddr=0xffffc900001cf000)
> > x86_64_kvtop(kvaddr=0xffffc900001cf000)
> >
> > /* It needs to calculate physical address by traversing page tables. */
> > x86_64_kvtop_xen_wpt(kvaddr=0xffffc900001cf000)
> >
> > /*
> > * 0x581b7e000 is the machine address of pgd need to be translated here.
> > * The mfn is calculated in this way at x86_64_kvtop_xen_wpt():
> > *
> > * pml4 = ((ulong *)machdep->machspec->pml4) + pml4_index(kvaddr);
> > * pgd_paddr = (*pml4) & PHYSICAL_PAGE_MASK;
> > *
> > * The kvaddr 0xffffc900001cf000 here is quite different from the one
> > * above, so the machine address of pgd is not the same one. And this
> > * pgd is the one we use to access the VMA of p2m table.
> > */
> > xen_m2p(machine=0x581b7e000)
> > __xen_m2p(machine=0x581b7e000, mfn=0x581b7e)
> >
> > /*
> > * Looking for mfn 0x581b7e in the range of p2m page which starts at
> > * VMA 0xffffc900001f5000.
> > */
> > readmem(addr=0xffffc900001f5000)
> >
> > /* Need physical address of VMA 0xffffc900001f5000 as same reason above. */
> > kvtop(kvaddr=0xffffc900001f5000)
> > x86_64_kvtop(kvaddr=0xffffc900001f5000)
> >
> > /* Need to traverse page tables to calculate physical address for it. */
> > x86_64_kvtop_xen_wpt(kvaddr=0xffffc900001f5000)
> >
> > /*
> > * Unfortunately, machine address 0x581b7e000 have to be translated again.
> > * Endless loop starts from here.
> > */
> > xen_m2p(machine=0x581b7e000)
> > __xen_m2p(machine=0x581b7e000, mfn=0x581b7e)
> > readmem(addr=0xffffc900001f5000)
> >
> > Fortunately, PV domU p2m mapping is also stored at xd->xfd + xch_index_offset
> > and organized as struct xen_dumpcore_p2m. We have a chance to read the p2m
> > stuff directly from there, and then we avoid the loop above.
> >
> > So, this patch implements a special reading function read_xc_p2m() to extract
> > the mfns from xd->xfd + xch_index_offset. This function does not need to read
> > mfns from p2m VMA like readmem() does, so, we avoid the endless loop introduced
> > by the address translation.
> >
> > Signed-off-by: Honglei Wang <honglei.wang@oracle.com>
> > Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>
> Queued for crash-7.2.0:
>
> https://github.com/crash-utility/crash/commit/5c52842a58a2602dba81de71831af98b2b53c6e0
Wow, Dave, you are fast! Thanks a lot!
Honglei, congrats! Thanks for doing the work!
Daniel
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2017-05-29 11:38 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-24 7:13 [Crash-utility] [PATCH] xen: Add support for domU with Linux kernel 3.19 and newer Honglei Wang
2017-05-24 15:56 ` Dave Anderson
2017-05-25 1:32 ` Honglei Wang
2017-05-29 11:38 ` Daniel Kiper
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox