diff options
Diffstat (limited to 'kexec/arch/sh/kexec-sh.c')
-rw-r--r-- | kexec/arch/sh/kexec-sh.c | 45 |
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; } /* |