this patch also changes the display width of all addresses in physmap.c to 16 hex characters.
FIXME: what about unmappings? munmap is safe. djgpp's __dpmi_free_physical_address_mapping: unknown. DirectHW's unmap_physical: unknown.
FIXME: jakllsch suggested using PRIx64 instead of x, because it's more portable
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- physmap.c | 46 +++++++++++++++++++++++++++++++--------------- 1 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/physmap.c b/physmap.c index cb035a5..3dbe387 100644 --- a/physmap.c +++ b/physmap.c @@ -99,7 +99,8 @@ void physunmap(void *virt_addr, size_t len) /* There is no known way to unmap the first 1 MB. The DPMI server will * do this for us on exit. */ - if ((virt_addr >= realmem_map) && ((virt_addr + len) <= (realmem_map + (1024 * 1024)))) { + if ((virt_addr >= realmem_map) && + ((virt_addr + len) <= (realmem_map + (1024 * 1024)))) { return; }
@@ -195,7 +196,8 @@ static void *sys_physmap_ro_cached(unsigned long phys_addr, size_t len) if (-1 == fd_mem_cached) { /* Open the memory device CACHED. */ if (-1 == (fd_mem_cached = open(MEM_DEV, O_RDWR))) { - msg_perr("Critical error: open(" MEM_DEV "): %s", strerror(errno)); + msg_perr("Critical error: open(" MEM_DEV "): %s", + strerror(errno)); exit(2); } } @@ -221,26 +223,39 @@ void physunmap(void *virt_addr, size_t len) #define PHYSMAP_RW 0 #define PHYSMAP_RO 1
+/* Round start to nearest page boundary below and set len so that the resulting + * address range ends at the lowest possible page boundary where the original + * address range is still entirely contained. It returns the difference between + * the rounded start address and the original start address. */ +static unsigned long round_to_page_boundaries(unsigned long *start, size_t *len) +{ + unsigned long page_size = getpagesize(); + unsigned long page_mask = ~(page_size-1); + unsigned long end = *start + *len; + unsigned long old_start = *start; + msg_gspew("page_size=%lu\n", page_size); + msg_gspew("start=0x%016lx, len=0x%08lx, end=0x%016lx\n", + *start, *len, end); + *start = *start & page_mask; + end = (end & page_mask) + (((end & page_mask) != end) ? page_size : 0); + *len = end - *start; + msg_gspew("start=0x%016lx, len=0x%08lx, end=0x%016lx\n", + *start, *len, *start + *len); + return old_start - *start; +} + static void *physmap_common(const char *descr, unsigned long phys_addr, size_t len, int mayfail, int readonly) { void *virt_addr; + unsigned long diff;
if (len == 0) { - msg_pspew("Not mapping %s, zero size at 0x%08lx.\n", + msg_pspew("Not mapping %s, zero size at 0x%016lx.\n", descr, phys_addr); return ERROR_PTR; } - - if ((getpagesize() - 1) & len) { - msg_perr("Mapping %s at 0x%08lx, unaligned size 0x%lx.\n", - descr, phys_addr, (unsigned long)len); - } - - if ((getpagesize() - 1) & phys_addr) { - msg_perr("Mapping %s, 0x%lx bytes at unaligned 0x%08lx.\n", - descr, (unsigned long)len, phys_addr); - }
+ diff = round_to_page_boundaries(&phys_addr, &len); if (readonly) { virt_addr = sys_physmap_ro_cached(phys_addr, len); } else { @@ -250,7 +265,8 @@ static void *physmap_common(const char *descr, unsigned long phys_addr, size_t l if (ERROR_PTR == virt_addr) { if (NULL == descr) descr = "memory"; - msg_perr("Error accessing %s, 0x%lx bytes at 0x%08lx\n", descr, (unsigned long)len, phys_addr); + msg_perr("Error accessing %s, 0x%lx bytes at 0x%016lx\n", descr, + (unsigned long)len, phys_addr); perror(MEM_DEV " mmap failed"); #ifdef __linux__ if (EINVAL == errno) { @@ -269,7 +285,7 @@ static void *physmap_common(const char *descr, unsigned long phys_addr, size_t l exit(3); }
- return virt_addr; + return virt_addr + diff; }
void *physmap(const char *descr, unsigned long phys_addr, size_t len)