440fx: fix PAM, PCI holes

The current implementation of PAM and the PCI holes is broken in several
ways:

  - PCI BARs are not restricted to the PCI hole (a BAR may hide memory)
  - PCI devices do not respect PAM (if a PCI device maps a region while
    PAM maps the region to RAM, the request will be honored)

This patch fixes things by introducing a pci address space, and using
memory region aliases to represent PAM regions, SMRAM, and PCI holes.

The memory hierarchy looks something like

system_memory
 |
 +--- low memory alias (0-0xe0000000)
 |      |
 |      +-- ram@0
 |
 +--- high memory alias (0x100000000-EOM)
 |      |
 |      +-- ram@0xe0000000
 |
 +--- pci hole alias (end of low memory-0x100000000)
 |      |
 |      +-- pci@end-of-low-memory
 |
 |
 +--- pam[n] (0xc0000-0xc3fff etc) (when set to pci, priority 1)
 |      |
 |      +-- pci@0xc4000 etc
 |
 +--- smram (0xa0000-0xbffff) (when set to pci/vga, priority 1)
        |
        +-- pci@0xa0000 etc

ram (simple ram region)

pci
 |
 +--- BARn
 |
 +--- VGA 0xa0000-0xbffff
 |
 +--- ROMs

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Avi Kivity 2011-08-15 17:17:38 +03:00 committed by Anthony Liguori
parent be20f9e902
commit ae0a54664c
4 changed files with 115 additions and 46 deletions

View file

@ -22,6 +22,8 @@
* THE SOFTWARE.
*/
#include <glib.h>
#include "hw.h"
#include "pc.h"
#include "apic.h"
@ -93,6 +95,8 @@ static void pc_init1(MemoryRegion *system_memory,
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
BusState *idebus[MAX_IDE_BUS];
ISADevice *rtc_state;
MemoryRegion *ram_memory;
MemoryRegion *pci_memory;
pc_cpus_init(cpu_model);
@ -108,11 +112,15 @@ static void pc_init1(MemoryRegion *system_memory,
below_4g_mem_size = ram_size;
}
pci_memory = g_new(MemoryRegion, 1);
memory_region_init(pci_memory, "pci", INT64_MAX);
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
pc_memory_init(system_memory,
kernel_filename, kernel_cmdline, initrd_filename,
below_4g_mem_size, above_4g_mem_size);
below_4g_mem_size, above_4g_mem_size,
pci_memory, &ram_memory);
}
if (!xen_enabled()) {
@ -130,7 +138,14 @@ static void pc_init1(MemoryRegion *system_memory,
if (pci_enabled) {
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq,
system_memory, system_io, ram_size);
system_memory, system_io, ram_size,
below_4g_mem_size,
0x100000000ULL - below_4g_mem_size,
0x100000000ULL + above_4g_mem_size,
(sizeof(target_phys_addr_t) == 4
? 0
: ((uint64_t)1 << 62)),
pci_memory, ram_memory);
} else {
pci_bus = NULL;
i440fx_state = NULL;
@ -202,10 +217,6 @@ static void pc_init1(MemoryRegion *system_memory,
smbus_eeprom_init(smbus, 8, NULL, 0);
}
if (i440fx_state) {
i440fx_init_memory_mappings(i440fx_state);
}
if (pci_enabled) {
pc_pci_device_init(pci_bus);
}