summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2011-09-15 20:06:34 +0900
committerSimon Horman <horms@verge.net.au>2011-10-05 07:12:47 +0900
commit8f47bcfa2b0150a8b8b995a5f10b9fffb320bc6d (patch)
treebb995cfff7d90a4b9376418c27a918eda16d791b
parent6b8a0f7285fa3eb3f67dfa0d8d5b61ade69e953d (diff)
sh: Take into account the base of System RAM in virt_to_phys()
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@verge.net.au>
-rw-r--r--kexec/arch/sh/kexec-sh.c45
1 files changed, 44 insertions, 1 deletions
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;
}
/*