|
|
Home Connectivity Software
Support
WinDriver Support
Technical Documents
Technical Document #129
| Doc ID: |
129 |
| Product: |
WinDriver |
| Version: |
All |
Reserving and locking physical memory on Windows NT PCs.
|
To reserve a segment of the physical memory (RAM) on your Windows
NT 4.0/2000/XP/Server 2003/Vista PC for exclusive use, and then access this memory
using WinDriver, follow the steps outlined in this document.
*******************************************************************************
NOTE:
- In most cases, there is no need to resort to this method in
order to reserve segments of memory for exclusive use.
Normally, you can lock a safe Direct Memory Access (DMA) buffer
(e.g. using WinDriver's DMA APIs) and then access the
buffer from your driver. The method described in the present
document should be used only in rare cases of
"memory-intensive" driver projects and only when the
required memory block cannot be locked using standard methods,
such as allocation of a contiguous DMA buffer.
- When using this method, take special care not to write to the
wrong memory addresses, so as to avoid system crashes, etc.
*******************************************************************************
-
Reserve the desired amount of RAM
-
Calculate the base address of the reserved memory:
-
Access the memory using WinDriver
- Reserve the desired amount of RAM:
Modify the boot.ini file on your PC to add a
"burnmemory" parameter to the relevant Windows
configuration:
/burnmemory=<size_in_MB>
The following example reserves 100MB of RAM:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Enterprise" /fastdetect /NoExecute=OptIn /burnmemory=100
This instructs Windows to refrain from using the specified
amount of memory in the highest area of the PC's physical
memory (RAM).
NOTE: When selecting the amount of memory to reserve,
take care not to exceed or to take up too much of the memory
allocated by default to the operating system's highest address
space (see
step #2). If the size of the reserved memory segment is too
big, this might result in degraded OS performance.
- Calculate the base address of the reserved memory:
To acquire the base address of the reserved memory segment,
you must first determine the physical memory mapping on your
PC and retrieve the base address and length (in bytes) of the
highest address space used by the operating system. Then add
the length of this address space to its base address to receive
the base address of your reserved memory segment:
<reserved memory base address> =
<highest OS physical memory base address>
+
<length of the highest OS memory address space>
NOTE: To verify the size of your reserved memory block, compare
the length of the highest OS address space, before and after
modifying boot.ini to reserve the memory (as outlined in
step #1).
You can determine the highest physical memory base address
using either of the following methods:
-
From the registry:
Open the registry
(Start -->
Run --> regedit.exe) and navigate to
the HKEY_LOCAL_MACHINE\HARDWARE\RESOURCEMAP\System Resources\Physical Memory\.Translated
registry key. This key is of type
REG_RESOURCE_LIST
and holds information regarding the
physical memory mapping on your PC. To view a
parsed version of the mapped addresses,
double-click on the
.Translated
key, select the relevant resource
from the Resource Lists dialog, and
double-click on the resource (or select
Display...
) in order to display the
Resources dialog, which contains a list
of all memory address ranges for the selected
resource. The base address for your reserved
physical memory block is calculated by locating
the highest base address in the list and adding
to it the length of the relevant address space.
For example, for the following Resources
dialog, the highest base address is 0x1000000
and the length of the address space that begins
at this address is 0x1eff0000 =>
<reserved memory base address> =
0x1000000 + 0x1eff0000 =
0x1fff0000
-
From your code:
You can also retrieve the physical memory
mapping on your PC from a kernel-mode driver
application that calls the Windows DDK
MmGetPhysicalMemoryRanges() function,
which is defined in the ntddk.h header
file. You can easily incorporate such code, for
example, within a WinDriver
Kernel PlugIn driver.
NOTE: Microsoft's documentation
officially supports only system use of this
function; therefore using it from your
application will be done on your own accord.
MmGetPhysicalMemoryRanges() is declared
as follows:
NTKERNELAPI
PPHYSICAL_MEMORY_RANGE
MmGetPhysicalMemoryRanges (
VOID
);
The function returns an array of
PHYSICAL_MEMORY_RANGE structures, which
hold the information regarding the base
addresses and lengths of all physical memory
address spaces in the system:
typedef struct _PHYSICAL_MEMORY_RANGE {
PHYSICAL_ADDRESS BaseAddress;
LARGE_INTEGER NumberOfBytes;
} PHYSICAL_MEMORY_RANGE,
*PPHYSICAL_MEMORY_RANGE;
The end of the array is marked by a
PHYSICAL_MEMORY_RANGE item that has the
value 0 for both the
BaseAddress
and
NumberOfBytes fields.
Hence the base address of your reserved
memory block can be calculated in the following
manner:
int i;
PPHYSICAL_MEMORY_RANGE pMemMap;
pMemMap = MmGetPhysicalMemoryRanges();
for (i = 0;
pMemMap[i].BaseAddress ||
pMemMap[i].NumberOfBytes;
i++);
--i;
<reserved memory base address> =
pMemMap[i].BaseAddress +
pMemMap[i].NumberOfBytes;
- Access the memory using WinDriver:
Once you acquire the physical base address of the memory
segment that you reserved, you can easily access it using
WinDriver, as you would any memory on an ISA card.
You can use WinDriver's DriverWizard to test the access to the
memory you reserved: Use the wizard to create a new ISA project,
define the new memory item according to the information you
acquired in step #2
above, then proceed to access the memory with the wizard.
You can also use DriverWizard to generate a sample diagnostics
application that demonstrates how to lock and access the
reserved memory region using WinDriver's API.
The following code segment demonstrates how you can define and
lock the physical memory using WinDriver's WDC API. The handle
returned by the sample
LockReservedMemory()
function can be used to access the memory using WinDriver's
WDC memory access APIs, defined in the
WinDriver/include/wdc_lib.h header file:
/* LockReservedMemory: Returns a WDC handle for accessing
the reserved memory block.
Parameters:
dwReservedRegionBase: The physical base address
of the
reserved memory region (as calculated in
step #2)
dwReservedRegionLength: The length (in bytes) of the
reserved memory region, i.e.:
<size_in_MB> (set in boot.ini) * 0x100000
Note:
The function uses the high-level WDC APIs.
You can implement similar code using the low-level
WD_CardRegister()
API - see the WinDriver User's
Manual for details.
*/
WDC_DEVICE_HANDLE LockReservedMemory(DWORD dwReservedRegionBase,
DWORD dwReservedRegionLength)
{
DWORD dwStatus;
WDC_DEVICE_HANDLE hDev = NULL;
WD_CARD deviceInfo;
/* Set the reserved memory's resources information */
BZERO(deviceInfo);
SetMemoryItem(&deviceInfo, dwReservedRegionBase,
dwReservedRegionLength);
/* Get a handle to the reserved memory block */
dwStatus = WDC_IsaDeviceOpen(&hDev, &deviceInfo, NULL,
NULL, NULL, NULL);
if (WD_STATUS_SUCCESS != dwStatus)
{
printf(
"Failed opening a WDC device handle.
Error 0x%lx - %s\n", dwStatus,
Stat2Str(dwStatus));
return NULL;
}
/* Return the handle to the reserved memory */
return hDev;
}
/* SetMemoryItem: Initializes a WDC device information
structure for a specified memory region.
Parameters:
pDeviceInfo: Pointer to a resources information structure
dwAddr: The memory region's physical
base address
dwBytes: The memory region's length, in bytes
*/
void
SetMemoryItem(WD_CARD *pDeviceInfo, DWORD dwAddr,
DWORD dwBytes)
{
WD_ITEMS *pItem = pDeviceInfo->Item;
pDeviceInfo->dwItems = 2;
/* 1st item: Bus */
pItem[0].item = ITEM_BUS;
pItem[0].I.Bus.dwBusType = WD_BUS_ISA;
/* 2nd item: Memory */
pItem[1].item = ITEM_MEMORY;
/* Map physical memory as cached (applicable only to RAM)
(this option is supported on Windows NT+ and CE
beginning with version 7.02 of WinDriver) */
pItem[1].dwOptions = WD_ITEM_ALLOW_CACHE;
/* Lock the memory for exclusive use */
pItem[1].fNotSharable = TRUE;
/* Set the reserved memory's base address */
pItem[1].I.Mem.dwPhysicalAddr = dwAddr;
/* Set the reserved memory's size */
pItem[1].I.Mem.dwBytes = dwBytes;
/* Set the reserved memory's address space */
pItem[1].I.Mem.dwBar = 0;
}
Back to Top
|
|