[PATCH v2] sh: Take into account the base of System RAM in virt_to_phys()

Simon Horman horms at verge.net.au
Sun Oct 2 21:05:18 EDT 2011


Previously virt_to_phys() assumed that physical memory always started
at address 0. This is not always the case.

Tested on an sh7757lcr (32bit system) whose only System RAM region is
40000000-4effffff and an ecovec24 (29bit system).

Signed-off-by: Simon Horman <horms at verge.net.au>

---
 kexec/arch/sh/kexec-sh.c |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 44 insertions(+), 1 deletions(-)

v2
* Only use the base of System RAM as an offset into physical memory
  if 32bit addressing is in use.

diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
index 4b21ee8..94ebbc7 100644
--- a/kexec/arch/sh/kexec-sh.c
+++ b/kexec/arch/sh/kexec-sh.c
@@ -185,13 +185,56 @@ void kexec_sh_setup_zero_page(char *zero_page_buf, size_t zero_page_size,
 	}
 }
 
+static int is_32bit(void)
+{
+	const char *cpuinfo = "/proc/cpuinfo";
+	char line[MAX_LINE], key[MAX_LINE], value[MAX_LINE];
+	FILE *fp;
+	int count;
+	int status = 0;
+
+	fp = fopen(cpuinfo, "r");
+	if (!fp)
+		die("Cannot open %s\n", cpuinfo);
+
+	while(fgets(line, sizeof(line), fp) != 0) {
+		count = sscanf(line, "%s : %s", key, value);
+		if (count != 2)
+			continue;
+		if (!strcmp(key, "address sizes")) {
+			if (!strcmp(value, "32 bits physical"))
+				status = 1;
+			break;
+		}
+	}
+
+	fclose(fp);
+
+	return status;
+}
+
 unsigned long virt_to_phys(unsigned long addr)
 {
 	unsigned long seg = addr & 0xe0000000;
+	unsigned long long start = 0;
+
 	if (seg != 0x80000000 && seg != 0xc0000000)
 		die("Virtual address %p is not in P1 or P2\n", (void *)addr);
 
-	return addr - seg;
+	/* If 32bit addressing is used then the base of system RAM
+	 * is an offset into physical memory. */
+	if (is_32bit()) {
+		unsigned long long end;
+		int ret;
+
+		/* Assume there is only one "System RAM" region */
+		ret = parse_iomem_single("System RAM\n", &start, &end);
+		if (ret)
+			die("Could not parse System RAM region "
+			    "in /proc/iomem\n");
+	}
+
+	return addr - seg + start;
 }
 
 /*
-- 
1.7.5.4




More information about the kexec mailing list