summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2016-06-06 17:58:47 +0100
committerSimon Horman <horms@verge.net.au>2016-06-08 09:15:03 +0900
commitbab7cb1ce778bb37cd9791133458adb5f00ddf0b (patch)
tree49b86b195036db4d4a57759b0ba2e9d9d19baa14
parent2a36d76bbbc30bd55789136bd5e596c445c19caf (diff)
kdump: mmap() and munmap() only work on page-aligned quantites
The man page for mmap() and munmap() says that mmap() and munmap() only works for page-aligned addresses, sizes and offsets. Arrange to give these interfaces what they want. Reviewed-by: Pratyush Anand <panand@redhat.com> Signed-off-by: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kdump/kdump.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/kdump/kdump.c b/kdump/kdump.c
index 821ee7c..3247a54 100644
--- a/kdump/kdump.c
+++ b/kdump/kdump.c
@@ -25,22 +25,35 @@
#define MAP_WINDOW_SIZE (64*1024*1024)
#define DEV_MEM "/dev/mem"
+#define ALIGN_MASK(x,y) (((x) + (y)) & ~(y))
+#define ALIGN(x,y) ALIGN_MASK(x, (y) - 1)
+
static void *map_addr(int fd, unsigned long size, off_t offset)
{
+ unsigned long page_size = getpagesize();
+ unsigned long map_offset = offset & (page_size - 1);
+ size_t len = ALIGN(size + map_offset, page_size);
void *result;
- result = mmap(0, size, PROT_READ, MAP_SHARED, fd, offset);
+
+ result = mmap(0, len, PROT_READ, MAP_SHARED, fd, offset - map_offset);
if (result == MAP_FAILED) {
fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %llu size: %lu: %s\n",
(unsigned long long)offset, size, strerror(errno));
exit(5);
}
- return result;
+ return result + map_offset;
}
static void unmap_addr(void *addr, unsigned long size)
{
+ unsigned long page_size = getpagesize();
+ unsigned long map_offset = (uintptr_t)addr & (page_size - 1);
+ size_t len = ALIGN(size + map_offset, page_size);
int ret;
- ret = munmap(addr, size);
+
+ addr -= map_offset;
+
+ ret = munmap(addr, len);
if (ret < 0) {
fprintf(stderr, "munmap failed: %s\n",
strerror(errno));