OSD Home

- # - Physical memory layout of the PC
- # - Determining RAM sizes
- # - Allocating RAM
- # - DMA restrictions on physical memory
- # - Code snippets
- # - Links
- REPORT BUGS OR ERRORS IN THIS DOCUMENT

## Physical memory layout of the PC

linear address range | real-mode address range | memory type | use
--- | --- | --- | ---
0- 3FF | 0000:0000-0000:03FF | RAM | real-mode interrupt vector table (IVT)
400- 4FF | 0040:0000-0040:00FF | BIOS data area (BDA)
500- 9FBFF | 0050:0000-9000:FBFF | free conventional memory (below 1 meg)
9FC00- 9FFFF | 9000:FC00-9000:FFFF | extended BIOS data area (EBDA)
A0000- BFFFF | A000:0000-B000:FFFF | video RAM | VGA framebuffers
C0000- C7FFF | C000:0000-C000:7FFF | ROM | video BIOS (32K is typical size)
C8000- EFFFF | C800:0000-E000:FFFF | NOTHING |
F0000- FFFFF | F000:0000-F000:FFFF | ROM | motherboard BIOS (64K is typical size)
100000- FEBFFFFF |  | RAM | free extended memory (1 meg and above)
FEC00000- FFFFFFFF |  | various | motherboard BIOS, PnP NVRAM, ACPI, etc.

The IVT and BDA contain information that is useful even to pmode OSes. For information on the contents of these structures, see Ralf Brown's Interrupt List: http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html

Bootsectors and MBRs are loaded at addresses 7C00h - 7DFFh. Depending on how it's written, this code may use additional memory outside this range. The DOS 7 MBR copies itself to 600h - 7FFh, leaving 7C00h - 7DFFh free for successive MBRs or bootsectors.

The EBDA shown here is 1K. Some computers don't have an EBDA, others have an EBDA larger than 1K.

## Determining RAM sizes

The top of conventional memory may contain an extended BIOS data area (EBDA). Use INT 12h (or read the 16-bit value at linear address 0413h) to get the top of conventional memory, and don't use conventional memory above this limit. When DOS is running, it's possible to have more than 640K of conventional memory if EMM386 is loaded like this:

            DEVICE=C:\DOS\EMM386.EXE I=A000-AFFF

Real-mode code may be able to take advantage of the extra 64K, but switching to protected mode in this situation will probably cause the extra memory to 'disappear'. If INT 12h returns a value greater than 0x280 (640), limit this value to 0x280.

Determining extended memory size is surprisingly difficult:

- Use BIOS calls:
  1. INT 15h AX=E820h (32-bit CPU only). If this fails...
  2. ...use INT 15h AX=E801h. If this fails...
  3. ...use INT 15h AH=88h.
- Read the extended memory size from CMOS only if all of the BIOS calls listed above fail.
- These BIOS calls are buggy on some computers -- see Ralf Brown's list and http://marc.theaimsgroup.com/?l=linux-kernel&m=99322719013363&w=2
- You should not attempt to 'probe' memory size. It's difficult to write robust code that will do this correctly and safely on all PCs.
- The GRUB bootloader will determine memory size and layout for you. Use GRUB and you don't have to worry about probing, 16-bit BIOS calls, or BIOS bugs.

## Allocating RAM

    xxx
    Physical memory allocation:
    - Heap algorithms to use if paging is not used, or on top of paging:
    	BogoMalloc, first-fit, dlmalloc (bins), object-based (slab), other?
    - Algorithms for allocating pages: bitmap, stack, buddy, trees?
      Page coloring (x86 CPU uses associative L1 cache, so page coloring
      is more for other CPUs with direct-mapped cache -- right?)
    - Zone memory: low RAM for ISA DMA, slow NUMA or uncached memory for
      page tables (since they're cached in the TLB)

## DMA restrictions on physical memory

Memory used by ISA (8- and 16-bit) DMA must be below 16 meg. This type of DMA is used by the floppy drive and by ISA sound boards. Memory used by 8-bit DMA (DMA channels 0-3) can not cross a 64K boundary; memory used by 16-bit DMA (channels 4-7) can not cross a 128K boundary.

PCI (32-bit) DMA; also known as bus-mastering, does not have these restrictions.

## Code snippets

Get memory size with BIOS calls or from CMOS: see bootstrap code snippets

Simple `malloc()`: first-fit, `free()` coalesces adjacent free blocks, fixed- or variable-sized heap, no `mmap()`

ROMs can be detected with INT 15h AX=E820h (look for type 2 memory), or by scanning for 16-bit BIOS ROM extensions

## Links

Doug Lea's `malloc()`: http://g.oswego.edu/dl/html/malloc.html. Public domain, portable, good performance. Can use `sbrk()` or `mmap()` or both to enlarge the heap.

John Walker's BGET: http://www.fourmilab.ch/bget/. Reasonably portable. Public-domain.

      http://www.cs.colorado.edu/~zorn/Malloc.html
      http://nondot.org/sabre/os/articles/MemoryManagement/

## TO DO

## REPORT BUGS OR ERRORS IN THIS DOCUMENT