Skip to contentSkip to conversation

Add support for filtering out user pages under Xen4

PATCH In review Petr Tesarik 2 participants 2 messages Aug 24, 2012 – Nov 5, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v3 8/9 Add support for filtering out user pages under Xen4

In Xen-4.0+, usage of a page must be determined from its PGC_xxx flags, which are stored in the highest bits of the _count field of struct page_info.

Let's keep the original function for Xen3 only and add a new function for walking the pages under Xen4. This avoids adding many new conditionals to the inner loop and also makes the logic easier to follow for all Xen versions.

---
 makedumpfile.c |  102 
+++++++++++++++++++++++++++++++++++++++++++++++++++++----
 makedumpfile.h |   25 +++++++++++++
 2 files changed, 121 insertions(+), 6 deletions(-)
makedumpfile.h +25 -0
@@ -78,6 +78,31 @@ int get_mem_type(void);
 #define LSEEKED_PDATA	(3)
 
 /*
+ * Xen page flags
+ */
+#define BITS_PER_BYTE (8)
+#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
+#define PG_shift(idx)	(BITS_PER_LONG - (idx))
+#define PG_mask(x, idx)	(x ## UL << PG_shift(idx))
+ /* Cleared when the owning guest 'frees' this page. */
+#define PGC_allocated       PG_mask(1, 1)
+ /* Page is Xen heap? */
+#define PGC_xen_heap        PG_mask(1, 2)
+ /* Page is broken? */
+#define PGC_broken          PG_mask(1, 7)
+ /* Mutually-exclusive page states: { inuse, offlining, offlined, free }. */
+#define PGC_state           PG_mask(3, 9)
+#define PGC_state_inuse     PG_mask(0, 9)
+#define PGC_state_offlining PG_mask(1, 9)
+#define PGC_state_offlined  PG_mask(2, 9)
+#define PGC_state_free      PG_mask(3, 9)
+#define page_state_is(ci, st) (((ci)&PGC_state) == PGC_state_##st)
+
+ /* Count of references to this frame. */
+#define PGC_count_width   PG_shift(9)
+#define PGC_count_mask    ((1UL<<PGC_count_width)-1)
+
+/*
  * Memory flags
  */
 #define MEMORY_PAGETABLE_4L	(1 << 0)
makedumpfile.c +32 -4
@@ -5719,7 +5719,7 @@ is_select_domain(unsigned int id)
 }
 
 int
-exclude_xen_user_domain(void)
+exclude_xen3_user_domain(void)
 {
 	int i;
 	unsigned int count_info, _domain;
@@ -5728,9 +5728,6 @@ exclude_xen_user_domain(void)
 	unsigned long long phys_start, phys_end;
 	unsigned long long pfn, pfn_end;
 	unsigned long long j, size;
-	struct timeval tv_start;
-
-	gettimeofday(&tv_start, NULL);
 
 	/*
 	 * NOTE: the first half of bitmap is not used for Xen extraction
@@ -5781,13 +5778,106 @@ exclude_xen_user_domain(void)
 		}
 	}
 
+	return TRUE;
+}
+
+int
+exclude_xen4_user_domain(void)
+{
+	int i;
+	unsigned long count_info;
+	unsigned int  _domain;
+	unsigned int num_pt_loads = get_num_pt_loads();
+	unsigned long page_info_addr;
+	unsigned long long phys_start, phys_end;
+	unsigned long long pfn, pfn_end;
+	unsigned long long j, size;
+
+	/*
+	 * NOTE: the first half of bitmap is not used for Xen extraction
+	 */
+	for (i = 0; get_pt_load(i, &phys_start, &phys_end, NULL, NULL); i++) {
+
+		print_progress(PROGRESS_XEN_DOMAIN, i, num_pt_loads);
+
+		pfn     = paddr_to_pfn(phys_start);
+		pfn_end = paddr_to_pfn(phys_end);
+		size    = pfn_end - pfn;
+
+		for (j = 0; pfn < pfn_end; pfn++, j++) {
+			print_progress(PROGRESS_XEN_DOMAIN, j + (size * i),
+					size * num_pt_loads);
+
+			page_info_addr = info->frame_table_vaddr + pfn * 

SIZE(page_info);
+ if (!readmem(VADDR_XEN,
+ page_info_addr + OFFSET(page_info.count_info),
+ &count_info, sizeof(count_info))) {
+ clear_bit_on_2nd_bitmap(pfn);
+ continue; /* page_info may not exist */
+ }
+
+ /* always keep Xen heap pages */
+ if (count_info & PGC_xen_heap)
+ continue;
+
+ /* delete free, offlined and broken pages */
+ if (page_state_is(count_info, free) ||
+ page_state_is(count_info, offlined) ||
+ count_info & PGC_broken) {
+ clear_bit_on_2nd_bitmap(pfn);
+ continue;
+ }
+
+ /* keep inuse pages not allocated to any domain
+ * this covers e.g. Xen static data
+ */
+ if (! (count_info & PGC_allocated))
+ continue;
+
+ /* Need to check the domain
+ * keep:
+ * - anonymous (_domain == 0), or
+ * - selected domain page
+ */
+ if (!readmem(VADDR_XEN,
+ page_info_addr + OFFSET(page_info._domain),
+ &_domain, sizeof(_domain))) {
+ ERRMSG("Can't get page_info._domain.\n");
+ return FALSE;
+ }
+
+ if (_domain == 0)
+ continue;
+ if (is_select_domain(_domain))
+ continue;
+ clear_bit_on_2nd_bitmap(pfn);
+ }
+ }
+
+ return TRUE;
+}
+
+int
+exclude_xen_user_domain(void)
+{
+ struct timeval tv_start;
+ int ret;
+
+ gettimeofday(&tv_start, NULL);
+
+ if (info->xen_crash_info.com &&
+ info->xen_crash_info.com->xen_major_version >= 4)
+ ret = exclude_xen4_user_domain();
+ else
+ ret = exclude_xen3_user_domain();
+
/*
* print [100 %]
*/
- print_progress(PROGRESS_XEN_DOMAIN, num_pt_loads, num_pt_loads);
+ print_progress(PROGRESS_XEN_DOMAIN, 1, 1);
print_execution_time(PROGRESS_XEN_DOMAIN, &tv_start);

- return TRUE;
+ return ret;
}

int

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#1 lore raw

Hello Petr,

I'm sorry for having kept you waiting.
I have a small comment for this patch.

Quoted 21 lines · On Fri, 24 Aug 2012 17:43:23 +0200 Petr Tesarik <[email protected]> wrote:

In Xen-4.0+, usage of a page must be determined from its PGC_xxx flags, which are stored in the highest bits of the _count field of struct page_info.

Let's keep the original function for Xen3 only and add a new function for walking the pages under Xen4. This avoids adding many new conditionals to the inner loop and also makes the logic easier to follow for all Xen versions.

---
 makedumpfile.c |  102 
+++++++++++++++++++++++++++++++++++++++++++++++++++++----
 makedumpfile.h |   25 +++++++++++++
 2 files changed, 121 insertions(+), 6 deletions(-)

makedumpfile.h int get_mem_type(void); · line 84

Quoted 7 lines
makedumpfile.h +4 -0
@@ -78,6 +78,31 @@ int get_mem_type(void);
 #define LSEEKED_PDATA	(3)
 
 /*
+ * Xen page flags
+ */
+#define BITS_PER_BYTE (8)
+#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))

BITPERBYTE is already defined as meaning the same as BITS_PER_BYTE, so I will change this patch to use BITPERBYTE instead of BITS_PER_BYTE when merging.

makedumpfile.h:
164
165 #define BITPERBYTE (8)
166 #define PGMM_CACHED (512)

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec