diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-14 13:37:25 -0700 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-14 13:37:25 -0700 |
commit | 351ef7188a1a2e2f154bbda6f703c2d3f4af6d79 (patch) | |
tree | 027081078f4a31f86673d26d85c05afead417df1 | |
parent | 375a8ef5ea38ea10134c125c75a12bbf9d5ba7bd (diff) | |
download | busybox-w32-351ef7188a1a2e2f154bbda6f703c2d3f4af6d79.tar.gz busybox-w32-351ef7188a1a2e2f154bbda6f703c2d3f4af6d79.tar.bz2 busybox-w32-351ef7188a1a2e2f154bbda6f703c2d3f4af6d79.zip |
devmem: map two pages only if it is necessary
function old new delta
devmem_main 463 469 +6
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/devmem.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/miscutils/devmem.c b/miscutils/devmem.c index e13dedc0a..39b580840 100644 --- a/miscutils/devmem.c +++ b/miscutils/devmem.c | |||
@@ -13,9 +13,9 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
13 | uint64_t read_result; | 13 | uint64_t read_result; |
14 | uint64_t writeval = writeval; /* for compiler */ | 14 | uint64_t writeval = writeval; /* for compiler */ |
15 | off_t target; | 15 | off_t target; |
16 | unsigned page_size = getpagesize(); | 16 | unsigned page_size, mapped_size, offset_in_page; |
17 | int fd; | 17 | int fd; |
18 | int width = 8 * sizeof(int); | 18 | unsigned width = 8 * sizeof(int); |
19 | 19 | ||
20 | /* devmem ADDRESS [WIDTH [VALUE]] */ | 20 | /* devmem ADDRESS [WIDTH [VALUE]] */ |
21 | // TODO: options? | 21 | // TODO: options? |
@@ -50,15 +50,22 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
50 | if (argv[3]) | 50 | if (argv[3]) |
51 | writeval = bb_strtoull(argv[3], NULL, 0); | 51 | writeval = bb_strtoull(argv[3], NULL, 0); |
52 | } else { /* argv[2] == NULL */ | 52 | } else { /* argv[2] == NULL */ |
53 | /* make argv[3] to be a valid thing to use */ | 53 | /* make argv[3] to be a valid thing to fetch */ |
54 | argv--; | 54 | argv--; |
55 | } | 55 | } |
56 | if (errno) | 56 | if (errno) |
57 | bb_show_usage(); /* bb_strtouXX failed */ | 57 | bb_show_usage(); /* one of bb_strtouXX failed */ |
58 | 58 | ||
59 | fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); | 59 | fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); |
60 | mapped_size = page_size = getpagesize(); | ||
61 | offset_in_page = (unsigned)target & (page_size - 1); | ||
62 | if (offset_in_page + width > page_size) { | ||
63 | /* This access spans pages. | ||
64 | * Must map two pages to make it possible: */ | ||
65 | mapped_size *= 2; | ||
66 | } | ||
60 | map_base = mmap(NULL, | 67 | map_base = mmap(NULL, |
61 | page_size * 2 /* in case value spans page */, | 68 | mapped_size, |
62 | argv[3] ? (PROT_READ | PROT_WRITE) : PROT_READ, | 69 | argv[3] ? (PROT_READ | PROT_WRITE) : PROT_READ, |
63 | MAP_SHARED, | 70 | MAP_SHARED, |
64 | fd, | 71 | fd, |
@@ -68,7 +75,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
68 | 75 | ||
69 | // printf("Memory mapped at address %p.\n", map_base); | 76 | // printf("Memory mapped at address %p.\n", map_base); |
70 | 77 | ||
71 | virt_addr = (char*)map_base + (target & (page_size - 1)); | 78 | virt_addr = (char*)map_base + offset_in_page; |
72 | 79 | ||
73 | if (!argv[3]) { | 80 | if (!argv[3]) { |
74 | switch (width) { | 81 | switch (width) { |
@@ -119,7 +126,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
119 | } | 126 | } |
120 | 127 | ||
121 | if (ENABLE_FEATURE_CLEAN_UP) { | 128 | if (ENABLE_FEATURE_CLEAN_UP) { |
122 | if (munmap(map_base, page_size * 2) == -1) | 129 | if (munmap(map_base, mapped_size) == -1) |
123 | bb_perror_msg_and_die("munmap"); | 130 | bb_perror_msg_and_die("munmap"); |
124 | close(fd); | 131 | close(fd); |
125 | } | 132 | } |