map_physical_memory() and its backend vm_map_physical_memory() did not map in the

pages, ie. they considered the areas to be B_LAZY_LOCK. But that doesn't really make
sense and potentially cause page faults where you wouldn't expect them (and where
it's not a good idea to trigger them).
Reworked display_mem() (used by the dw/db/ds commands in the kernel debugger) to
be a bit more sane, improved formatting, and allows it to work on non-existing
memory without a panic.
The "area" debugger command now also accepts an address (contained by the area)
as argument - and it will now always print out an error message if no matching
area could be found.
Replaced all dprintf() calls to kprintf() calls for the kernel debugger functions.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14042 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-08-21 23:17:09 +00:00
parent 464f9febc4
commit 099ceb8f9d

View File

@ -940,7 +940,7 @@ vm_map_physical_memory(aspace_id aid, const char *name, void **_address,
vm_cache_ref *cache_ref;
vm_store *store;
addr_t map_offset;
int err;
status_t status;
vm_address_space *aspace = vm_get_aspace_by_id(aid);
TRACE(("vm_map_physical_memory(aspace = %ld, \"%s\", virtual = %p, spec = %ld,"
@ -975,11 +975,20 @@ vm_map_physical_memory(aspace_id aid, const char *name, void **_address,
cache->scan_skip = 1;
vm_cache_acquire_ref(cache_ref, true);
err = map_backing_store(aspace, store, _address, 0, size, addressSpec, 0, protection, REGION_NO_PRIVATE_MAP, &area, name);
status = map_backing_store(aspace, store, _address, 0, size, addressSpec, 0, protection, REGION_NO_PRIVATE_MAP, &area, name);
vm_cache_release_ref(cache_ref);
if (status >= B_OK) {
// make sure our area is mapped in completely
// (even if that makes the fault routine pretty much useless)
for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
store->ops->fault(store, aspace, offset);
}
}
vm_put_aspace(aspace);
if (err < 0)
return err;
if (status < B_OK)
return status;
// modify the pointer returned to be offset back into the new area
// the same way the physical address in was offset
@ -1619,15 +1628,14 @@ vm_get_page_mapping(aspace_id aid, addr_t vaddr, addr_t *paddr)
static int
display_mem(int argc, char **argv)
{
int item_size;
int display_width;
int num = 1;
int32 displayWidth;
int32 itemSize;
int32 num = 1;
addr_t address;
int i;
int j;
int i, j;
if (argc < 2) {
dprintf("usage: dw/ds/db <address> [num]\n"
kprintf("usage: dw/ds/db <address> [num]\n"
"\tdw - 4 bytes\n"
"\tds - 2 bytes\n"
"\tdb - 1 byte\n");
@ -1643,56 +1651,67 @@ display_mem(int argc, char **argv)
// build the format string
if (strcmp(argv[0], "db") == 0) {
item_size = 1;
display_width = 16;
itemSize = 1;
displayWidth = 16;
} else if (strcmp(argv[0], "ds") == 0) {
item_size = 2;
display_width = 8;
itemSize = 2;
displayWidth = 8;
} else if (strcmp(argv[0], "dw") == 0) {
item_size = 4;
display_width = 4;
itemSize = 4;
displayWidth = 4;
} else {
dprintf("display_mem called in an invalid way!\n");
kprintf("display_mem called in an invalid way!\n");
return 0;
}
dprintf("[0x%lx] '", address);
for (j = 0; j < min_c(display_width, num) * item_size; j++) {
char c = *((char *)address + j);
if (!isalnum(c)) {
c = '.';
}
dprintf("%c", c);
}
dprintf("'");
for (i = 0; i < num; i++) {
if ((i % display_width) == 0 && i != 0) {
dprintf("\n[0x%lx] '", address + i * item_size);
for (j = 0; j < min_c(display_width, (num-i)) * item_size; j++) {
char c = *((char *)address + i * item_size + j);
if (!isalnum(c)) {
uint32 value;
if ((i % displayWidth) == 0) {
int32 displayed = min_c(displayWidth, (num-i)) * itemSize;
if (i != 0)
kprintf("\n");
kprintf("[0x%lx] ", address + i * itemSize);
for (j = 0; j < displayed; j++) {
char c;
if (user_memcpy(&c, (char *)address + i * itemSize + j, 1) != B_OK) {
displayed = j;
break;
}
if (!isalnum(c))
c = '.';
kprintf("%c", c);
}
dprintf("%c", c);
if (num > displayWidth) {
// make sure the spacing in the last line is correct
for (j = displayed; j < displayWidth * itemSize; j++)
kprintf(" ");
}
dprintf("'");
kprintf(" ");
}
switch (item_size) {
if (user_memcpy(&value, (uint8 *)address + i * itemSize, itemSize) != B_OK) {
kprintf("read fault");
break;
}
switch (itemSize) {
case 1:
dprintf(" 0x%02x", *((uint8 *)address + i));
kprintf(" 0x%02x", *(uint8 *)&value);
break;
case 2:
dprintf(" 0x%04x", *((uint16 *)address + i));
kprintf(" 0x%04x", *(uint16 *)&value);
break;
case 4:
dprintf(" 0x%08lx", *((uint32 *)address + i));
kprintf(" 0x%08lx", *(uint32 *)&value);
break;
default:
dprintf("huh?\n");
}
}
dprintf("\n");
kprintf("\n");
return 0;
}
@ -1705,30 +1724,30 @@ dump_cache_ref(int argc, char **argv)
vm_cache_ref *cache_ref;
if (argc < 2) {
dprintf("cache_ref: not enough arguments\n");
kprintf("cache_ref: not enough arguments\n");
return 0;
}
if (strlen(argv[1]) < 2 || argv[1][0] != '0' || argv[1][1] != 'x') {
dprintf("cache_ref: invalid argument, pass address\n");
kprintf("cache_ref: invalid argument, pass address\n");
return 0;
}
address = atoul(argv[1]);
cache_ref = (vm_cache_ref *)address;
dprintf("cache_ref at %p:\n", cache_ref);
dprintf("cache: %p\n", cache_ref->cache);
dprintf("lock.holder: %ld\n", cache_ref->lock.holder);
dprintf("lock.sem: 0x%lx\n", cache_ref->lock.sem);
dprintf("areas:\n");
kprintf("cache_ref at %p:\n", cache_ref);
kprintf("cache: %p\n", cache_ref->cache);
kprintf("lock.holder: %ld\n", cache_ref->lock.holder);
kprintf("lock.sem: 0x%lx\n", cache_ref->lock.sem);
kprintf("areas:\n");
for (area = cache_ref->areas; area != NULL; area = area->cache_next) {
dprintf(" area 0x%lx: ", area->id);
dprintf("base_addr = 0x%lx ", area->base);
dprintf("size = 0x%lx ", area->size);
dprintf("name = '%s' ", area->name);
dprintf("protection = 0x%lx\n", area->protection);
kprintf(" area 0x%lx: ", area->id);
kprintf("base_addr = 0x%lx ", area->base);
kprintf("size = 0x%lx ", area->size);
kprintf("name = '%s' ", area->name);
kprintf("protection = 0x%lx\n", area->protection);
}
dprintf("ref_count: %ld\n", cache_ref->ref_count);
kprintf("ref_count: %ld\n", cache_ref->ref_count);
return 0;
}
@ -1767,37 +1786,35 @@ dump_cache(int argc, char **argv)
vm_page *page;
if (argc < 2) {
dprintf("cache: not enough arguments\n");
kprintf("cache: not enough arguments\n");
return 0;
}
if (strlen(argv[1]) < 2 || argv[1][0] != '0' || argv[1][1] != 'x') {
dprintf("cache: invalid argument, pass address\n");
kprintf("cache: invalid argument, pass address\n");
return 0;
}
address = atoul(argv[1]);
cache = (vm_cache *)address;
dprintf("cache at %p:\n", cache);
dprintf("cache_ref: %p\n", cache->ref);
dprintf("source: %p\n", cache->source);
dprintf("store: %p\n", cache->store);
// XXX 64-bit
dprintf("virtual_size: 0x%Lx\n", cache->virtual_size);
dprintf("temporary: %ld\n", cache->temporary);
dprintf("scan_skip: %ld\n", cache->scan_skip);
dprintf("page_list:\n");
kprintf("cache at %p:\n", cache);
kprintf("cache_ref: %p\n", cache->ref);
kprintf("source: %p\n", cache->source);
kprintf("store: %p\n", cache->store);
kprintf("virtual_size: 0x%Lx\n", cache->virtual_size);
kprintf("temporary: %ld\n", cache->temporary);
kprintf("scan_skip: %ld\n", cache->scan_skip);
kprintf("page_list:\n");
for (page = cache->page_list; page != NULL; page = page->cache_next) {
// XXX offset is 64-bit
if (page->type == PAGE_TYPE_PHYSICAL) {
dprintf(" %p ppn 0x%lx offset 0x%Lx type %ld state %ld (%s) ref_count %ld\n",
kprintf(" %p ppn 0x%lx offset 0x%Lx type %ld state %ld (%s) ref_count %ld\n",
page, page->ppn, page->offset, page->type, page->state,
page_state_to_text(page->state), page->ref_count);
} else if(page->type == PAGE_TYPE_DUMMY) {
dprintf(" %p DUMMY PAGE state %ld (%s)\n",
kprintf(" %p DUMMY PAGE state %ld (%s)\n",
page, page->state, page_state_to_text(page->state));
} else
dprintf(" %p UNKNOWN PAGE type %ld\n", page, page->type);
kprintf(" %p UNKNOWN PAGE type %ld\n", page, page->type);
}
return 0;
}
@ -1806,56 +1823,51 @@ dump_cache(int argc, char **argv)
static void
_dump_area(vm_area *area)
{
dprintf("dump of area at %p:\n", area);
dprintf("name: '%s'\n", area->name);
dprintf("id: 0x%lx\n", area->id);
dprintf("base: 0x%lx\n", area->base);
dprintf("size: 0x%lx\n", area->size);
dprintf("protection: 0x%lx\n", area->protection);
dprintf("wiring: 0x%lx\n", area->wiring);
dprintf("ref_count: %ld\n", area->ref_count);
dprintf("cache_ref: %p\n", area->cache_ref);
// XXX 64-bit
dprintf("cache_offset: 0x%Lx\n", area->cache_offset);
dprintf("cache_next: %p\n", area->cache_next);
dprintf("cache_prev: %p\n", area->cache_prev);
kprintf("dump of area at %p:\n", area);
kprintf("name: '%s'\n", area->name);
kprintf("id: 0x%lx\n", area->id);
kprintf("base: 0x%lx\n", area->base);
kprintf("size: 0x%lx\n", area->size);
kprintf("protection: 0x%lx\n", area->protection);
kprintf("wiring: 0x%lx\n", area->wiring);
kprintf("ref_count: %ld\n", area->ref_count);
kprintf("cache_ref: %p\n", area->cache_ref);
kprintf("cache_offset: 0x%Lx\n", area->cache_offset);
kprintf("cache_next: %p\n", area->cache_next);
kprintf("cache_prev: %p\n", area->cache_prev);
}
static int
dump_area(int argc, char **argv)
{
// int i;
bool found = false;
vm_area *area;
addr_t num;
if (argc < 2) {
dprintf("area: not enough arguments\n");
kprintf("usage: area <id|address|name>\n");
return 0;
}
// if the argument looks like a hex number, treat it as such
if (strlen(argv[1]) > 2 && argv[1][0] == '0' && argv[1][1] == 'x') {
uint32 num = strtoul(argv[1], NULL, 16);
area_id id = num;
num = strtoul(argv[1], NULL, 0);
area = (vm_area *)hash_lookup(sAreaHash, &id);
if (area == NULL) {
dprintf("invalid area id\n");
} else {
_dump_area(area);
}
return 0;
} else {
// walk through the area list, looking for the arguments as a name
struct hash_iterator iter;
hash_open(sAreaHash, &iter);
while ((area = (vm_area *)hash_next(sAreaHash, &iter)) != NULL) {
if (area->name != NULL && strcmp(argv[1], area->name) == 0) {
if ((area->name != NULL && !strcmp(argv[1], area->name))
|| num != 0
&& ((addr_t)area->id == num
|| area->base <= num && area->base + area->size > num)) {
_dump_area(area);
found = true;
}
}
}
if (!found)
kprintf("could not find area %s (%ld)\n", argv[1], num);
return 0;
}
@ -1866,11 +1878,11 @@ dump_area_list(int argc, char **argv)
vm_area *area;
struct hash_iterator iter;
dprintf("addr\t id base\t\tsize\t\tprotect\tlock\tname\n");
kprintf("addr\t id base\t\tsize\t\tprotect\tlock\tname\n");
hash_open(sAreaHash, &iter);
while ((area = (vm_area *)hash_next(sAreaHash, &iter)) != NULL) {
dprintf("%p %5lx %p\t%p\t%ld\t%ld\t%s\n", area, area->id, (void *)area->base,
kprintf("%p %5lx %p\t%p\t%ld\t%ld\t%s\n", area, area->id, (void *)area->base,
(void *)area->size, area->protection, area->wiring, area->name);
}
hash_close(sAreaHash, &iter, false);