Displaying the Physical Memory Map

The Apple Kernel Debug Kit comes with a kernel gdb macros file (kgmacros) that contains numerous macros useful during low-level development and analysis. One of the macros is showbootermemorymap, which dumps the physical memory map from EFI. The information in this map is very useful for certain types of development.

Since I am often mobile—without ready access to a two-machine debugging set up—I can’t use real kernel debugging much of the time. For introspection-only kernel "debugging", one can use the darwin-kernel gdb target on Mac OS X. It does require that you have a /dev/kmem device available. /dev/kmem is not enabled by default on Mac OS X, but you can enable it at boot time by including kmem=1 in the kernel’s boot arguments.

$ sudo nvram boot-args="-v kmem=1 ..."
$ sudo reboot
/* system reboots */
$ cd /path/to/kernel/debug/kit/for/current/system/
$ sudo gdb ./mach_kernel
...
(gdb) source kgmacros
Loading Kernel GDB Macros package.  Type "help kgm" for more info.
(gdb) target darwin-kernel
(gdb) attach
Connected.
(gdb) showbootermemorymap
Type       Physical Start   Number of Pages
available  0000000000000000 000000000000008f
ACPI_NVS   000000000008f000 0000000000000001
available  0000000000090000 0000000000000010
...
RT_data    0000000000a8c000 000000000000002b
RT_data    0000000000ab7000 0000000000000001
(gdb)

A more convenient alternative is to simply use DTrace to print this information. The following is a DTrace script that mimics the behavior of the showbootermemorymap kernel debug macro.

#! /usr/sbin/dtrace -s

/*
 * showbootermemorymap - DTrace script that prints out the physical memory
 *                       map from EFI. Mimics the output format of the
 *                       kernel debugging macro of the same name.
 *
 * Amit Singh
 * http://osxbook.com
 */

#pragma D option quiet

BEGIN
{
    self->inited = 1;

    self->kgm_boot_args = ((struct boot_args*)(`PE_state).bootArgs);
    self->kgm_msize = self->kgm_boot_args->MemoryMapDescriptorSize;
    self->kgm_mcount = self->kgm_boot_args->MemoryMapSize / self->kgm_msize;

    printf("Type       Physical Start   Number of Pages\n");

    self->kgm_i = 0;
}

fbt:::entry
/self->inited && self->kgm_i < self->kgm_mcount/
{
    this->kgm_mptr = (struct EfiMemoryRange*)
    ((unsigned long)self->kgm_boot_args->MemoryMap +
                    self->kgm_i * self->kgm_msize);

    self->kgm_i++;

    printf("%s", (this->kgm_mptr->Type == 0)  ? "reserved  " :
                 (this->kgm_mptr->Type == 1)  ? "LoaderCode" :
                 (this->kgm_mptr->Type == 2)  ? "LoaderData" :
                 (this->kgm_mptr->Type == 3)  ? "BS_code   " :
                 (this->kgm_mptr->Type == 4)  ? "BS_data   " :
                 (this->kgm_mptr->Type == 5)  ? "RT_code   " :
                 (this->kgm_mptr->Type == 6)  ? "RT_data   " :
                 (this->kgm_mptr->Type == 7)  ? "available " :
                 (this->kgm_mptr->Type == 8)  ? "Unusable  " :
                 (this->kgm_mptr->Type == 9)  ? "ACPI_recl " :
                 (this->kgm_mptr->Type == 10) ? "ACPI_NVS  " :
                 (this->kgm_mptr->Type == 11) ? "MemMapIO  " :
                 (this->kgm_mptr->Type == 12) ? "MemPortIO " :
                 (this->kgm_mptr->Type == 13) ? "PAL_code  " :
                                                "UNKNOWN   ");
    printf(" %016llx %016llx\n",
           this->kgm_mptr->PhysicalStart, this->kgm_mptr->NumberOfPages);
}

fbt:::return
/self->inited && self->kgm_i >= self->kgm_mcount/
{
    exit(0);
}

Comments are closed.


All contents of this site, unless otherwise noted, are ©1994-2014 Amit Singh. All Rights Reserved.