>I was totally confused by the address spaces: Virtual Address, Physical
Address, Bus
Address, Adapter Address, …
Can anyone give me an in-depth explaination about the relationship among
those address
spaces? And how to get the other addresses if I have one of them?
I suggest reading something like the Intel Pentium III manuals for lots of
details on how addresses get translated by the processor.
In a nutshell…
Virtual Address - This is an address before it undergoes any mapping by the
processor. Virtual addresses are what software thinks of as a pointer. The
x86 processors have a 4GB virtual address space (32-bit), although
generally not every address is valid.
Physical address - These are the addresses that have passed through the
virtual to physical address mapping hardware. On an x86 processor, virtual
addresses are first mapped through segment registers to form a linear
address. The segment registers may be programmed to simply have a straight
through mapping, meaning a offset 0x3000 relative to some segment register
(like CS, the current code segment) maps to linear address 0x3000. After
translation by segment mapping (not optional), the linear address can use
(optionally) page tables to map from a linear address to a physical
address. In an x86 processor, “pages” are generally 4K bytes, although
there are also large pages (2M/4M bytes) for some special uses, like
mapping the OS kernel on NT. The translation from a linear address to a
physical address uses a cache of mappings known as the TLB (translation
lookaside buffers). The TLB’s contain recent page mappings. A TLB cache
miss requires the processor to read the correct page table entry from main
memory before accessing the actual desired physical address. I bring up
TLB’s because they can have a large negative impact on memory access
performance under certain access patterns. After mapping through a TLB
entry (which really is a copy of an memory page table), a physical address
is presented on the external processor bus.
Bus Address - Busses external to the processor, like PCI busses, have
interfaces that also can translate addresses they see. These are generally
called bridges, so to get from the processor bus to the PCI bus a bridge
chip is used (which may be integrated into something the like memory
controller chip). This means a physical address of 0x3000 generated by the
processor may not be 0x3000 when seen on the PCI bus. Often, the bus
interfaces are programmed (generally by the OS) to have a straight through
mapping, so a physical address of 0x3000 is also 0x3000 on the PCI bus.
The term “adapter address” seems a bit less clear. One definition could be
an address used by “Adapter” objects under NT. Adapter’s are an abstract
representation of a bus translation, generally for doing DMA. Some
hardware, generally not x86 systems, can apply an address mapping between
DMA transfers and memory physical addresses. This might allow your 32-bit
PCI device to DMA into addresses higher than 4GB. Or your ISA device to DMA
into addresses higher than 16M (ISA buses only have 24-bit address lines).
Often, there is no real address translation hardware for doing this on x86
systems, so the OS gives the driver the address of a memory buffer to
perform the DMA transfer to, and then when releasing ownership of the “map
registers”, actually does a memory copy to the correct physical memory. The
term “adapter address” might also refer to some address on a piece of I/O
hardware. For example, if you map the video frame buffer on a video card
into a bus address space, you generally think of those addresses as
“adapter addresses”. For a PCI device, the address for device memory to bus
memory mapping is controlled by PCI configuration space registers. The term
“adapter address” may also refer to things like PCI bus configuration
addresses. Each device has a composite “adapter address” for it’s
configuration registers. This allows a driver or OS to uniquely reference
each device attached to the system, before it’s configured by the driver.
How one translates between all these different addresses depends on many
factors. Describing all the variations would take at least a chapter in a
book. Perhaps someone offhand knows of such a chapter to refer to. Some of
the translations just automagically happen in the hardware, and sometimes
API calls must be made to figure out the correct “address” value to use.
You might also want to understand how kernel and user process address
spaces fit in, as these can become very important in some drivers.
Hope this helps.