aboutsummaryrefslogtreecommitdiff
path: root/hw/pci-host
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-06-08 15:57:41 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-06-08 15:57:41 +0100
commitee09f84e6bf5383a23c9624115c26b72aa1e076c (patch)
tree49fe5c021ca71f8be8fc6ae630d4792c5b8b9354 /hw/pci-host
parent2e29dd7c44db30e3d3c108ab2a622cbdac6d16f0 (diff)
parent24a314269281a175b5540b3b6a8981ed2e8220e1 (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.c20
-rw-r--r--hw/pci-host/piix.c44
-rw-r--r--hw/pci-host/q35.c142
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);