Re: x86 remap allocator in kernel 3.0

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dne St 11. ledna 2012 00:37:50 Petr Tesarik napsal(a):
> [...]
> I can see now that this is unnecessarily complicated, because the
> node_remap_* variables are static arrays of MAX_NUMNODES elements, so I
> can get their size from the debuginfo at POST_GDB init and initialize a
> machine-specific data type with it. I'll post another patch tomorrow.

And here we go. Tested on my system and seems to work just fine.

Petr Tesarik
SUSE Linux
From: Petr Tesarik <ptesarik@xxxxxxx>
Subject: [x86] Add correct handling of regions allocated with the remap allocator
References: bnc#738742
Patch-mainline: no

For NUMA x86, the pgdat is remapped into the node's physical memory. Since
that physical memory may not be reachable through the identity mapping, a
small part of the identity mapping is used.

This special case has never been handled properly by crash.

Signed-off-by: Petr Tesarik <ptesarik@xxxxxxx>

---
 defs.h |    4 ++
 x86.c  |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 115 insertions(+), 8 deletions(-)

--- a/defs.h
+++ b/defs.h
@@ -4253,6 +4253,10 @@ struct machine_specific {
 	ulonglong last_pmd_read_PAE;
 	ulonglong last_ptbl_read_PAE;
 	ulong page_protnone;
+	int max_numnodes;
+	ulong *remap_start_vaddr;
+	ulong *remap_end_vaddr;
+	ulong *remap_start_pfn;
 };
 
 struct syment *x86_is_entry_tramp_address(ulong, ulong *); 
--- a/x86.c
+++ b/x86.c
@@ -996,6 +996,7 @@ static int x86_uvtop_xen_wpt(struct task
 static int x86_kvtop_xen_wpt(struct task_context *, ulong, physaddr_t *, int);
 static int x86_uvtop_xen_wpt_PAE(struct task_context *, ulong, physaddr_t *, int);
 static int x86_kvtop_xen_wpt_PAE(struct task_context *, ulong, physaddr_t *, int);
+static int x86_kvtop_remap(ulong, physaddr_t *);
 static ulong x86_get_task_pgd(ulong);
 static ulong x86_processor_speed(void);
 static ulong x86_get_pc(struct bt_info *);
@@ -1006,6 +1007,7 @@ static uint64_t x86_memory_size(void);
 static ulong x86_vmalloc_start(void);
 static ulong *read_idt_table(int);
 static void eframe_init(void);
+static int remap_init(void);
 #define READ_IDT_INIT     1
 #define READ_IDT_RUNTIME  2
 static char *extract_idt_function(ulong *, char *, ulong *);
@@ -2014,6 +2016,8 @@ x86_init(int when)
 				   "pr_reg");
 		STRUCT_SIZE_INIT(percpu_data, "percpu_data");
 
+		remap_init();
+
 		break;
 
 	case POST_INIT:
@@ -2084,6 +2088,72 @@ eframe_init(void)
 }
 
 /*
+ *  Locate regions remapped by the remap allocator
+ */
+static int
+remap_init(void)
+{
+	ulong start_vaddr, end_vaddr, start_pfn;
+	struct machine_specific *ms;
+	struct syment *sp;
+
+	if (! (sp = symbol_search("node_remap_start_vaddr")) )
+		return FALSE;
+	start_vaddr = sp->value;
+
+	if (! (sp = symbol_search("node_remap_end_vaddr")) )
+		return FALSE;
+	end_vaddr = sp->value;
+
+	if (! (sp = symbol_search("node_remap_start_pfn")) )
+		return FALSE;
+	start_pfn = sp->value;
+
+	ms = machdep->machspec;
+	ms->max_numnodes = get_array_length("node_remap_start_pfn", NULL,
+					    sizeof(ulong));
+	if (ms->max_numnodes < 1)
+		ms->max_numnodes = 1;
+
+	ms->remap_start_vaddr = calloc(3*ms->max_numnodes, sizeof(ulong));
+	if (!ms->remap_start_vaddr)
+		error(FATAL, "cannot malloc remap array");
+	ms->remap_end_vaddr = ms->remap_start_vaddr + ms->max_numnodes;
+	ms->remap_start_pfn = ms->remap_end_vaddr + ms->max_numnodes;
+
+	readmem(start_vaddr, KVADDR, ms->remap_start_vaddr,
+		ms->max_numnodes * sizeof(ulong), "node_remap_start_vaddr",
+		FAULT_ON_ERROR);
+	readmem(end_vaddr, KVADDR, ms->remap_end_vaddr,
+		ms->max_numnodes * sizeof(ulong), "node_remap_end_vaddr",
+		FAULT_ON_ERROR);
+	readmem(start_pfn, KVADDR, ms->remap_start_pfn,
+		ms->max_numnodes * sizeof(ulong), "node_remap_end_vaddr",
+		FAULT_ON_ERROR);
+
+	return TRUE;
+}
+
+static int
+x86_kvtop_remap(ulong kvaddr, physaddr_t *paddr)
+{
+	struct machine_specific *ms;
+	int i;
+
+	ms = machdep->machspec;
+
+	for (i = 0; i < ms->max_numnodes; ++i) {
+		if (kvaddr >= ms->remap_start_vaddr[i] &&
+		    kvaddr < ms->remap_end_vaddr[i]) {
+			*paddr = PTOB(ms->remap_start_pfn[i]) +
+				kvaddr - ms->remap_start_vaddr[i];
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/*
  *  Needs to be done this way because of potential 4G/4G split.
  */
 static int 
@@ -2768,12 +2838,13 @@ x86_kvtop(struct task_context *tc, ulong
 		}
 		pgd = (ulong *)symbol_value("idle_pg_table_l2");
 	} else {
-		if (!vt->vmalloc_start) {
+		if (x86_kvtop_remap(kvaddr, paddr)) {
+			if (!verbose)
+				return TRUE;
+		} else if (!vt->vmalloc_start) {
 			*paddr = VTOP(kvaddr);
 			return TRUE;
-		}
-
-		if (!IS_VMALLOC_ADDR(kvaddr)) { 
+		} else if (!IS_VMALLOC_ADDR(kvaddr)) { 
 			*paddr = VTOP(kvaddr);
 			if (!verbose)
 				return TRUE;
@@ -3023,12 +3094,13 @@ x86_kvtop_PAE(struct task_context *tc, u
 		else
 			pgd = (ulonglong *)symbol_value("idle_pg_table");
 	} else {
-		if (!vt->vmalloc_start) {
+		if (x86_kvtop_remap(kvaddr, paddr)) {
+			if (!verbose)
+				return TRUE;
+		} else if (!vt->vmalloc_start) {
 			*paddr = VTOP(kvaddr);
 			return TRUE;
-		}
-
-		if (!IS_VMALLOC_ADDR(kvaddr)) { 
+		} else if (!IS_VMALLOC_ADDR(kvaddr)) { 
 			*paddr = VTOP(kvaddr);
 			if (!verbose)
 				return TRUE;
@@ -3354,6 +3426,8 @@ x86_dump_machdep_table(ulong arg)
         int others;
 	ulong xen_wpt;
 	char buf[BUFSIZE];
+	struct machine_specific *ms;
+	int i, j, max_numnodes;
 
 	switch (arg) {
 	default:
@@ -3489,6 +3563,35 @@ x86_dump_machdep_table(ulong arg)
 		machdep->machspec->last_ptbl_read_PAE);
 	fprintf(fp, "                 page_protnone: %lx\n",
 		machdep->machspec->page_protnone);
+	fprintf(fp, "                  MAX_NUMNODES: %ld\n",
+		machdep->machspec->max_numnodes);
+
+	ms = machdep->machspec;
+	max_numnodes = ms->max_numnodes;
+
+	fprintf(fp, "             remap_start_vaddr:");
+	for (i = 0; i < max_numnodes; ++i) {
+                if ((i % 8) == 0)
+                        fprintf(fp, "\n        ");
+                fprintf(fp, "%08lx ", ms->remap_start_vaddr[i]);
+	}
+        fprintf(fp, "\n");
+
+	fprintf(fp, "               remap_end_vaddr:");
+	for (i = 0; i < max_numnodes; ++i) {
+                if ((i % 8) == 0)
+                        fprintf(fp, "\n        ");
+                fprintf(fp, "%08lx ", ms->remap_end_vaddr[i]);
+	}
+        fprintf(fp, "\n");
+
+	fprintf(fp, "               remap_start_pfn:");
+	for (i = 0; i < max_numnodes; ++i) {
+                if ((i % 8) == 0)
+                        fprintf(fp, "\n        ");
+                fprintf(fp, "%08lx ", ms->remap_start_pfn[i]);
+	}
+        fprintf(fp, "\n");
 }
 
 /*
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux