diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-06-08 15:57:41 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-06-08 15:57:41 +0100 |
commit | ee09f84e6bf5383a23c9624115c26b72aa1e076c (patch) | |
tree | 49fe5c021ca71f8be8fc6ae630d4792c5b8b9354 /hw/pci-host | |
parent | 2e29dd7c44db30e3d3c108ab2a622cbdac6d16f0 (diff) | |
parent | 24a314269281a175b5540b3b6a8981ed2e8220e1 (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* KVM error improvement from Laurent
* CONFIG_PARALLEL fix from Mirek
* Atomic/optimized dirty bitmap access from myself and Stefan
* BUILD_DIR convenience/bugfix from Peter C
* Memory leak fix from Shannon
* SMM improvements (though still TCG only) from myself and Gerd, acked by mst
# gpg: Signature made Fri Jun 5 18:45:20 2015 BST using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (62 commits)
update Linux headers from kvm/next
atomics: add explicit compiler fence in __atomic memory barriers
ich9: implement SMI_LOCK
q35: implement TSEG
q35: add test for SMRAM.D_LCK
q35: implement SMRAM.D_LCK
q35: add config space wmask for SMRAM and ESMRAMC
q35: fix ESMRAMC default
q35: implement high SMRAM
hw/i386: remove smram_update
target-i386: use memory API to implement SMRAM
hw/i386: add a separate region that tracks the SMRAME bit
target-i386: create a separate AddressSpace for each CPU
vl: run "late" notifiers immediately
qom: add object_property_add_const_link
vl: allow full-blown QemuOpts syntax for -global
pflash_cfi01: add secure property
pflash_cfi01: change to new-style MMIO accessors
pflash_cfi01: change big-endian property to BIT type
target-i386: wake up processors that receive an SMI
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/pci-host')
-rw-r--r-- | hw/pci-host/pam.c | 20 | ||||
-rw-r--r-- | hw/pci-host/piix.c | 44 | ||||
-rw-r--r-- | hw/pci-host/q35.c | 142 |
3 files changed, 150 insertions, 56 deletions
diff --git a/hw/pci-host/pam.c b/hw/pci-host/pam.c index 8272de3f28..17d826cba5 100644 --- a/hw/pci-host/pam.c +++ b/hw/pci-host/pam.c @@ -31,26 +31,6 @@ #include "sysemu/sysemu.h" #include "hw/pci-host/pam.h" -void smram_update(MemoryRegion *smram_region, uint8_t smram, - uint8_t smm_enabled) -{ - bool smram_enabled; - - smram_enabled = ((smm_enabled && (smram & SMRAM_G_SMRAME)) || - (smram & SMRAM_D_OPEN)); - memory_region_set_enabled(smram_region, !smram_enabled); -} - -void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram, - MemoryRegion *smram_region) -{ - uint8_t smm_enabled = (smm != 0); - if (*host_smm_enabled != smm_enabled) { - *host_smm_enabled = smm_enabled; - smram_update(smram_region, smram, *host_smm_enabled); - } -} - void init_pam(DeviceState *dev, MemoryRegion *ram_memory, MemoryRegion *system_memory, MemoryRegion *pci_address_space, PAMMemoryRegion *mem, uint32_t start, uint32_t size) diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 723836fb0e..f1712b86fe 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -105,7 +105,7 @@ struct PCII440FXState { MemoryRegion *ram_memory; PAMMemoryRegion pam_regions[13]; MemoryRegion smram_region; - uint8_t smm_enabled; + MemoryRegion smram, low_smram; }; @@ -138,18 +138,10 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) pam_update(&d->pam_regions[i], i, pd->config[I440FX_PAM + ((i + 1) / 2)]); } - smram_update(&d->smram_region, pd->config[I440FX_SMRAM], d->smm_enabled); - memory_region_transaction_commit(); -} - -static void i440fx_set_smm(int val, void *arg) -{ - PCII440FXState *d = arg; - PCIDevice *pd = PCI_DEVICE(d); - - memory_region_transaction_begin(); - smram_set_smm(&d->smm_enabled, val, pd->config[I440FX_SMRAM], - &d->smram_region); + memory_region_set_enabled(&d->smram_region, + !(pd->config[I440FX_SMRAM] & SMRAM_D_OPEN)); + memory_region_set_enabled(&d->smram, + pd->config[I440FX_SMRAM] & SMRAM_G_SMRAME); memory_region_transaction_commit(); } @@ -172,12 +164,13 @@ static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id) PCII440FXState *d = opaque; PCIDevice *pd = PCI_DEVICE(d); int ret, i; + uint8_t smm_enabled; ret = pci_device_load(pd, f); if (ret < 0) return ret; i440fx_update_memory_mappings(d); - qemu_get_8s(f, &d->smm_enabled); + qemu_get_8s(f, &smm_enabled); if (version_id == 2) { for (i = 0; i < PIIX_NUM_PIRQS; i++) { @@ -205,7 +198,10 @@ static const VMStateDescription vmstate_i440fx = { .post_load = i440fx_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, PCII440FXState), - VMSTATE_UINT8(smm_enabled, PCII440FXState), + /* Used to be smm_enabled, which was basically always zero because + * SeaBIOS hardly uses SMM. SMRAM is now handled by CPU code. + */ + VMSTATE_UNUSED(1), VMSTATE_END_OF_LIST() } }; @@ -297,11 +293,7 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error **errp) static void i440fx_realize(PCIDevice *dev, Error **errp) { - PCII440FXState *d = I440FX_PCI_DEVICE(dev); - dev->config[I440FX_SMRAM] = 0x02; - - cpu_smm_register(&i440fx_set_smm, d); } PCIBus *i440fx_init(PCII440FXState **pi440fx_state, @@ -346,11 +338,23 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, pc_pci_as_mapping_init(OBJECT(f), f->system_memory, f->pci_address_space); + /* if *disabled* show SMRAM to all CPUs */ memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region", f->pci_address_space, 0xa0000, 0x20000); memory_region_add_subregion_overlap(f->system_memory, 0xa0000, &f->smram_region, 1); - memory_region_set_enabled(&f->smram_region, false); + memory_region_set_enabled(&f->smram_region, true); + + /* smram, as seen by SMM CPUs */ + memory_region_init(&f->smram, OBJECT(d), "smram", 1ull << 32); + memory_region_set_enabled(&f->smram, true); + memory_region_init_alias(&f->low_smram, OBJECT(d), "smram-low", + f->ram_memory, 0xa0000, 0x20000); + memory_region_set_enabled(&f->low_smram, true); + memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram); + object_property_add_const_link(qdev_get_machine(), "smram", + OBJECT(&f->smram), &error_abort); + init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space, &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); for (i = 0; i < 12; ++i) { diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index c8827cc000..bd7409456f 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -198,6 +198,28 @@ static const TypeInfo q35_host_info = { * MCH D0:F0 */ +static uint64_t tseg_blackhole_read(void *ptr, hwaddr reg, unsigned size) +{ + return 0xffffffff; +} + +static void tseg_blackhole_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + /* nothing */ +} + +static const MemoryRegionOps tseg_blackhole_ops = { + .read = tseg_blackhole_read, + .write = tseg_blackhole_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 4, + .impl.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + /* PCIe MMCFG */ static void mch_update_pciexbar(MCHPCIState *mch) { @@ -266,21 +288,70 @@ static void mch_update_pam(MCHPCIState *mch) static void mch_update_smram(MCHPCIState *mch) { PCIDevice *pd = PCI_DEVICE(mch); + bool h_smrame = (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME); + uint32_t tseg_size; + + /* implement SMRAM.D_LCK */ + if (pd->config[MCH_HOST_BRIDGE_SMRAM] & MCH_HOST_BRIDGE_SMRAM_D_LCK) { + pd->config[MCH_HOST_BRIDGE_SMRAM] &= ~MCH_HOST_BRIDGE_SMRAM_D_OPEN; + pd->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK_LCK; + pd->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK_LCK; + } memory_region_transaction_begin(); - smram_update(&mch->smram_region, pd->config[MCH_HOST_BRIDGE_SMRAM], - mch->smm_enabled); - memory_region_transaction_commit(); -} -static void mch_set_smm(int smm, void *arg) -{ - MCHPCIState *mch = arg; - PCIDevice *pd = PCI_DEVICE(mch); + if (pd->config[MCH_HOST_BRIDGE_SMRAM] & SMRAM_D_OPEN) { + /* Hide (!) low SMRAM if H_SMRAME = 1 */ + memory_region_set_enabled(&mch->smram_region, h_smrame); + /* Show high SMRAM if H_SMRAME = 1 */ + memory_region_set_enabled(&mch->open_high_smram, h_smrame); + } else { + /* Hide high SMRAM and low SMRAM */ + memory_region_set_enabled(&mch->smram_region, true); + memory_region_set_enabled(&mch->open_high_smram, false); + } + + if (pd->config[MCH_HOST_BRIDGE_SMRAM] & SMRAM_G_SMRAME) { + memory_region_set_enabled(&mch->low_smram, !h_smrame); + memory_region_set_enabled(&mch->high_smram, h_smrame); + } else { + memory_region_set_enabled(&mch->low_smram, false); + memory_region_set_enabled(&mch->high_smram, false); + } + + if (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & MCH_HOST_BRIDGE_ESMRAMC_T_EN) { + switch (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & + MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK) { + case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB: + tseg_size = 1024 * 1024; + break; + case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB: + tseg_size = 1024 * 1024 * 2; + break; + case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB: + tseg_size = 1024 * 1024 * 8; + break; + default: + tseg_size = 0; + break; + } + } else { + tseg_size = 0; + } + memory_region_del_subregion(mch->system_memory, &mch->tseg_blackhole); + memory_region_set_enabled(&mch->tseg_blackhole, tseg_size); + memory_region_set_size(&mch->tseg_blackhole, tseg_size); + memory_region_add_subregion_overlap(mch->system_memory, + mch->below_4g_mem_size - tseg_size, + &mch->tseg_blackhole, 1); + + memory_region_set_enabled(&mch->tseg_window, tseg_size); + memory_region_set_size(&mch->tseg_window, tseg_size); + memory_region_set_address(&mch->tseg_window, + mch->below_4g_mem_size - tseg_size); + memory_region_set_alias_offset(&mch->tseg_window, + mch->below_4g_mem_size - tseg_size); - memory_region_transaction_begin(); - smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRIDGE_SMRAM], - &mch->smram_region); memory_region_transaction_commit(); } @@ -289,7 +360,6 @@ static void mch_write_config(PCIDevice *d, { MCHPCIState *mch = MCH_PCI_DEVICE(d); - /* XXX: implement SMRAM.D_LOCK */ pci_default_write_config(d, address, val, len); if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM0, @@ -329,7 +399,10 @@ static const VMStateDescription vmstate_mch = { .post_load = mch_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, MCHPCIState), - VMSTATE_UINT8(smm_enabled, MCHPCIState), + /* Used to be smm_enabled, which was basically always zero because + * SeaBIOS hardly uses SMM. SMRAM is now handled by CPU code. + */ + VMSTATE_UNUSED(1), VMSTATE_END_OF_LIST() } }; @@ -343,6 +416,9 @@ static void mch_reset(DeviceState *qdev) MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT); d->config[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT; + d->config[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_DEFAULT; + d->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK; + d->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK; mch_update(mch); } @@ -399,13 +475,47 @@ static void mch_realize(PCIDevice *d, Error **errp) pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory, mch->pci_address_space); - /* smram */ - cpu_smm_register(&mch_set_smm, mch); + /* if *disabled* show SMRAM to all CPUs */ memory_region_init_alias(&mch->smram_region, OBJECT(mch), "smram-region", mch->pci_address_space, 0xa0000, 0x20000); memory_region_add_subregion_overlap(mch->system_memory, 0xa0000, &mch->smram_region, 1); - memory_region_set_enabled(&mch->smram_region, false); + memory_region_set_enabled(&mch->smram_region, true); + + memory_region_init_alias(&mch->open_high_smram, OBJECT(mch), "smram-open-high", + mch->ram_memory, 0xa0000, 0x20000); + memory_region_add_subregion_overlap(mch->system_memory, 0xfeda0000, + &mch->open_high_smram, 1); + memory_region_set_enabled(&mch->open_high_smram, false); + + /* smram, as seen by SMM CPUs */ + memory_region_init(&mch->smram, OBJECT(mch), "smram", 1ull << 32); + memory_region_set_enabled(&mch->smram, true); + memory_region_init_alias(&mch->low_smram, OBJECT(mch), "smram-low", + mch->ram_memory, 0xa0000, 0x20000); + memory_region_set_enabled(&mch->low_smram, true); + memory_region_add_subregion(&mch->smram, 0xa0000, &mch->low_smram); + memory_region_init_alias(&mch->high_smram, OBJECT(mch), "smram-high", + mch->ram_memory, 0xa0000, 0x20000); + memory_region_set_enabled(&mch->high_smram, true); + memory_region_add_subregion(&mch->smram, 0xfeda0000, &mch->high_smram); + + memory_region_init_io(&mch->tseg_blackhole, OBJECT(mch), + &tseg_blackhole_ops, NULL, + "tseg-blackhole", 0); + memory_region_set_enabled(&mch->tseg_blackhole, false); + memory_region_add_subregion_overlap(mch->system_memory, + mch->below_4g_mem_size, + &mch->tseg_blackhole, 1); + + memory_region_init_alias(&mch->tseg_window, OBJECT(mch), "tseg-window", + mch->ram_memory, mch->below_4g_mem_size, 0); + memory_region_set_enabled(&mch->tseg_window, false); + memory_region_add_subregion(&mch->smram, mch->below_4g_mem_size, + &mch->tseg_window); + object_property_add_const_link(qdev_get_machine(), "smram", + OBJECT(&mch->smram), &error_abort); + init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, mch->pci_address_space, &mch->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); |