pc: fixes, cleanups, features
Some fixes and cleanups. Extended TSEG sizes. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJZQ/0DAAoJECgfDbjSjVRpqkQH/A83wqyTJJp7V87FqsC4l5Yc W7sIAqI/nrdSurzPyV98hUusOX+GgQ6AviQyjbtH/jKtaFK1kSD+nLudcDbQCeu7 l4bskTupKuSdzEOm8ybbM1bcIlw0RnaQTMQOfB0QRTNOhPv8dA8uclrIACVA3LSb 0IQT5wj8ni50bc56qNrJjY8F02M0CzUBVq5HdGrpOolm2c9yvNmCg8JZWwQP5iQp F0FvvcyJ2XqhNSKI3mcuf9/z90lDm1C+pEAc3GtLarDlfQIIsZhkAHmBNBIIxAAa +1qsFfLGYaKcmEzvNmLoUlP1cQ6X7kU7A7KEpnVv93uzmuVo1oHIM8jKpHOaohg= =Xzi1 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging pc: fixes, cleanups, features Some fixes and cleanups. Extended TSEG sizes. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Fri 16 Jun 2017 16:45:07 BST # gpg: using RSA key 0x281F0DB8D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * remotes/mst/tags/for_upstream: hw/i386: fix nvdimm check error path intel_iommu: cleanup vtd_interrupt_remap_msi() intel_iommu: cleanup vtd_{do_}iommu_translate() intel_iommu: switching the rest DPRINTF to trace tests/q35-test: add TSEG size checks tests/q35-test: push down qtest_start / qtest_end to test case(s) q35/mch: implement extended TSEG sizes Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e85c0d1401
File diff suppressed because it is too large
Load Diff
@ -384,6 +384,7 @@ typedef struct VTDIOTLBPageInvInfo VTDIOTLBPageInvInfo;
|
||||
/* Pagesize of VTD paging structures, including root and context tables */
|
||||
#define VTD_PAGE_SHIFT 12
|
||||
#define VTD_PAGE_SIZE (1ULL << VTD_PAGE_SHIFT)
|
||||
#define VTD_PAGE_MASK (VTD_PAGE_SIZE - 1)
|
||||
|
||||
#define VTD_PAGE_SHIFT_4K 12
|
||||
#define VTD_PAGE_MASK_4K (~((1ULL << VTD_PAGE_SHIFT_4K) - 1))
|
||||
|
14
hw/i386/pc.c
14
hw/i386/pc.c
@ -1692,6 +1692,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
|
||||
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
|
||||
MemoryRegion *mr = ddc->get_memory_region(dimm);
|
||||
uint64_t align = TARGET_PAGE_SIZE;
|
||||
bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
|
||||
|
||||
if (memory_region_get_alignment(mr) && pcmc->enforce_aligned_dimm) {
|
||||
align = memory_region_get_alignment(mr);
|
||||
@ -1703,17 +1704,18 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_nvdimm && !pcms->acpi_nvdimm_state.is_enabled) {
|
||||
error_setg(&local_err,
|
||||
"nvdimm is not enabled: missing 'nvdimm' in '-M'");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
|
||||
if (!pcms->acpi_nvdimm_state.is_enabled) {
|
||||
error_setg(&local_err,
|
||||
"nvdimm is not enabled: missing 'nvdimm' in '-M'");
|
||||
goto out;
|
||||
}
|
||||
if (is_nvdimm) {
|
||||
nvdimm_plug(&pcms->acpi_nvdimm_state);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,13 @@ vtd_inv_desc_wait_sw(uint64_t addr, uint32_t data) "wait invalidate status write
|
||||
vtd_inv_desc_wait_irq(const char *msg) "%s"
|
||||
vtd_inv_desc_wait_invalid(uint64_t hi, uint64_t lo) "invalid wait desc hi 0x%"PRIx64" lo 0x%"PRIx64
|
||||
vtd_inv_desc_wait_write_fail(uint64_t hi, uint64_t lo) "write fail for wait desc hi 0x%"PRIx64" lo 0x%"PRIx64
|
||||
vtd_inv_desc_iec(uint32_t granularity, uint32_t index, uint32_t mask) "granularity 0x%"PRIx32" index 0x%"PRIx32" mask 0x%"PRIx32
|
||||
vtd_inv_qi_enable(bool enable) "enabled %d"
|
||||
vtd_inv_qi_setup(uint64_t addr, int size) "addr 0x%"PRIx64" size %d"
|
||||
vtd_inv_qi_head(uint16_t head) "read head %d"
|
||||
vtd_inv_qi_tail(uint16_t head) "write tail %d"
|
||||
vtd_inv_qi_fetch(void) ""
|
||||
vtd_context_cache_reset(void) ""
|
||||
vtd_re_not_present(uint8_t bus) "Root entry bus %"PRIu8" not present"
|
||||
vtd_re_invalid(uint64_t hi, uint64_t lo) "invalid root entry hi 0x%"PRIx64" lo 0x%"PRIx64
|
||||
vtd_ce_not_present(uint8_t bus, uint8_t devfn) "Context entry bus %"PRIu8" devfn %"PRIu8" not present"
|
||||
@ -40,6 +47,43 @@ vtd_switch_address_space(uint8_t bus, uint8_t slot, uint8_t fn, bool on) "Device
|
||||
vtd_as_unmap_whole(uint8_t bus, uint8_t slot, uint8_t fn, uint64_t iova, uint64_t size) "Device %02x:%02x.%x start 0x%"PRIx64" size 0x%"PRIx64
|
||||
vtd_translate_pt(uint16_t sid, uint64_t addr) "source id 0x%"PRIu16", iova 0x%"PRIx64
|
||||
vtd_pt_enable_fast_path(uint16_t sid, bool success) "sid 0x%"PRIu16" %d"
|
||||
vtd_irq_generate(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" data 0x%"PRIx64
|
||||
vtd_reg_read(uint64_t addr, uint64_t size) "addr 0x%"PRIx64" size 0x%"PRIx64
|
||||
vtd_reg_write(uint64_t addr, uint64_t size, uint64_t val) "addr 0x%"PRIx64" size 0x%"PRIx64" value 0x%"PRIx64
|
||||
vtd_reg_dmar_root(uint64_t addr, bool extended) "addr 0x%"PRIx64" extended %d"
|
||||
vtd_reg_ir_root(uint64_t addr, uint32_t size) "addr 0x%"PRIx64" size 0x%"PRIx32
|
||||
vtd_reg_write_gcmd(uint32_t status, uint32_t val) "status 0x%"PRIx32" value 0x%"PRIx32
|
||||
vtd_reg_write_fectl(uint32_t value) "value 0x%"PRIx32
|
||||
vtd_reg_write_iectl(uint32_t value) "value 0x%"PRIx32
|
||||
vtd_reg_ics_clear_ip(void) ""
|
||||
vtd_dmar_translate(uint8_t bus, uint8_t slot, uint8_t func, uint64_t iova, uint64_t gpa, uint64_t mask) "dev %02x:%02x.%02x iova 0x%"PRIx64" -> gpa 0x%"PRIx64" mask 0x%"PRIx64
|
||||
vtd_dmar_enable(bool en) "enable %d"
|
||||
vtd_dmar_fault(uint16_t sid, int fault, uint64_t addr, bool is_write) "sid 0x%"PRIx16" fault %d addr 0x%"PRIx64" write %d"
|
||||
vtd_ir_enable(bool en) "enable %d"
|
||||
vtd_ir_irte_get(int index, uint64_t lo, uint64_t hi) "index %d low 0x%"PRIx64" high 0x%"PRIx64
|
||||
vtd_ir_remap(int index, int tri, int vec, int deliver, uint32_t dest, int dest_mode) "index %d trigger %d vector %d deliver %d dest 0x%"PRIx32" mode %d"
|
||||
vtd_ir_remap_type(const char *type) "%s"
|
||||
vtd_ir_remap_msi(uint64_t addr, uint64_t data, uint64_t addr2, uint64_t data2) "(addr 0x%"PRIx64", data 0x%"PRIx64") -> (addr 0x%"PRIx64", data 0x%"PRIx64")"
|
||||
vtd_ir_remap_msi_req(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" data 0x%"PRIx64
|
||||
vtd_fsts_ppf(bool set) "FSTS PPF bit set to %d"
|
||||
vtd_fsts_clear_ip(void) ""
|
||||
vtd_frr_new(int index, uint64_t hi, uint64_t lo) "index %d high 0x%"PRIx64" low 0x%"PRIx64
|
||||
vtd_err(const char *str) "%s"
|
||||
vtd_err_dmar_iova_overflow(uint64_t iova) "iova 0x%"PRIx64
|
||||
vtd_err_dmar_slpte_read_error(uint64_t iova, int level) "iova 0x%"PRIx64" level %d"
|
||||
vtd_err_dmar_slpte_perm_error(uint64_t iova, int level, uint64_t slpte, bool is_write) "iova 0x%"PRIx64" level %d slpte 0x%"PRIx64" write %d"
|
||||
vtd_err_dmar_slpte_resv_error(uint64_t iova, int level, uint64_t slpte) "iova 0x%"PRIx64" level %d slpte 0x%"PRIx64
|
||||
vtd_err_dmar_translate(uint8_t bus, uint8_t slot, uint8_t func, uint64_t iova) "dev %02x:%02x.%02x iova 0x%"PRIx64
|
||||
vtd_err_qi_enable(uint16_t tail) "tail 0x%"PRIx16
|
||||
vtd_err_qi_disable(uint16_t head, uint16_t tail, int type) "head 0x%"PRIx16" tail 0x%"PRIx16" last_desc_type %d"
|
||||
vtd_err_qi_tail(uint16_t tail, uint16_t size) "tail 0x%"PRIx16" size 0x%"PRIx16
|
||||
vtd_err_irte(int index, uint64_t lo, uint64_t hi) "index %d low 0x%"PRIx64" high 0x%"PRIx64
|
||||
vtd_err_irte_sid(int index, uint16_t req, uint16_t target) "index %d SVT_ALL sid 0x%"PRIx16" (should be: 0x%"PRIx16")"
|
||||
vtd_err_irte_sid_bus(int index, uint8_t bus, uint8_t min, uint8_t max) "index %d SVT_BUS bus 0x%"PRIx8" (should be: 0x%"PRIx8"-0x%"PRIx8")"
|
||||
vtd_err_irte_svt(int index, int type) "index %d SVT type %d"
|
||||
vtd_err_ir_msi_invalid(uint16_t sid, uint64_t addr, uint64_t data) "sid 0x%"PRIx16" addr 0x%"PRIx64" data 0x%"PRIx64
|
||||
vtd_warn_ir_vector(uint16_t sid, int index, int vec, int target) "sid 0x%"PRIx16" index %d vec %d (should be: %d)"
|
||||
vtd_warn_ir_trigger(uint16_t sid, int index, int trig, int target) "sid 0x%"PRIx16" index %d trigger %d (should be: %d)"
|
||||
|
||||
# hw/i386/amd_iommu.c
|
||||
amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at addr 0x%"PRIx64" + offset 0x%"PRIx32
|
||||
|
@ -134,7 +134,7 @@ static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name,
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static Property mch_props[] = {
|
||||
static Property q35_host_props[] = {
|
||||
DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr,
|
||||
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
|
||||
DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
|
||||
@ -154,7 +154,7 @@ static void q35_host_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
hc->root_bus_path = q35_host_root_bus_path;
|
||||
dc->realize = q35_host_realize;
|
||||
dc->props = mch_props;
|
||||
dc->props = q35_host_props;
|
||||
/* Reason: needs to be wired up by pc_q35_init */
|
||||
dc->user_creatable = false;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
@ -369,7 +369,7 @@ static void mch_update_smram(MCHPCIState *mch)
|
||||
tseg_size = 1024 * 1024 * 8;
|
||||
break;
|
||||
default:
|
||||
tseg_size = 0;
|
||||
tseg_size = 1024 * 1024 * (uint32_t)mch->ext_tseg_mbytes;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -392,6 +392,17 @@ static void mch_update_smram(MCHPCIState *mch)
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
static void mch_update_ext_tseg_mbytes(MCHPCIState *mch)
|
||||
{
|
||||
PCIDevice *pd = PCI_DEVICE(mch);
|
||||
uint8_t *reg = pd->config + MCH_HOST_BRIDGE_EXT_TSEG_MBYTES;
|
||||
|
||||
if (mch->ext_tseg_mbytes > 0 &&
|
||||
pci_get_word(reg) == MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY) {
|
||||
pci_set_word(reg, mch->ext_tseg_mbytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void mch_write_config(PCIDevice *d,
|
||||
uint32_t address, uint32_t val, int len)
|
||||
{
|
||||
@ -413,6 +424,11 @@ static void mch_write_config(PCIDevice *d,
|
||||
MCH_HOST_BRIDGE_SMRAM_SIZE)) {
|
||||
mch_update_smram(mch);
|
||||
}
|
||||
|
||||
if (ranges_overlap(address, len, MCH_HOST_BRIDGE_EXT_TSEG_MBYTES,
|
||||
MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_SIZE)) {
|
||||
mch_update_ext_tseg_mbytes(mch);
|
||||
}
|
||||
}
|
||||
|
||||
static void mch_update(MCHPCIState *mch)
|
||||
@ -420,6 +436,7 @@ static void mch_update(MCHPCIState *mch)
|
||||
mch_update_pciexbar(mch);
|
||||
mch_update_pam(mch);
|
||||
mch_update_smram(mch);
|
||||
mch_update_ext_tseg_mbytes(mch);
|
||||
}
|
||||
|
||||
static int mch_post_load(void *opaque, int version_id)
|
||||
@ -457,6 +474,11 @@ static void mch_reset(DeviceState *qdev)
|
||||
d->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK;
|
||||
d->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK;
|
||||
|
||||
if (mch->ext_tseg_mbytes > 0) {
|
||||
pci_set_word(d->config + MCH_HOST_BRIDGE_EXT_TSEG_MBYTES,
|
||||
MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY);
|
||||
}
|
||||
|
||||
mch_update(mch);
|
||||
}
|
||||
|
||||
@ -465,6 +487,12 @@ static void mch_realize(PCIDevice *d, Error **errp)
|
||||
int i;
|
||||
MCHPCIState *mch = MCH_PCI_DEVICE(d);
|
||||
|
||||
if (mch->ext_tseg_mbytes > MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_MAX) {
|
||||
error_setg(errp, "invalid extended-tseg-mbytes value: %" PRIu16,
|
||||
mch->ext_tseg_mbytes);
|
||||
return;
|
||||
}
|
||||
|
||||
/* setup pci memory mapping */
|
||||
pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory,
|
||||
mch->pci_address_space);
|
||||
@ -530,6 +558,12 @@ uint64_t mch_mcfg_base(void)
|
||||
return MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
|
||||
}
|
||||
|
||||
static Property mch_props[] = {
|
||||
DEFINE_PROP_UINT16("extended-tseg-mbytes", MCHPCIState, ext_tseg_mbytes,
|
||||
16),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void mch_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
@ -538,6 +572,7 @@ static void mch_class_init(ObjectClass *klass, void *data)
|
||||
k->realize = mch_realize;
|
||||
k->config_write = mch_write_config;
|
||||
dc->reset = mch_reset;
|
||||
dc->props = mch_props;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
dc->desc = "Host bridge";
|
||||
dc->vmsd = &vmstate_mch;
|
||||
|
@ -384,6 +384,11 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
#define PC_COMPAT_2_9 \
|
||||
HW_COMPAT_2_9 \
|
||||
{\
|
||||
.driver = "mch",\
|
||||
.property = "extended-tseg-mbytes",\
|
||||
.value = stringify(0),\
|
||||
},\
|
||||
|
||||
#define PC_COMPAT_2_8 \
|
||||
HW_COMPAT_2_8 \
|
||||
|
@ -60,6 +60,7 @@ typedef struct MCHPCIState {
|
||||
uint64_t above_4g_mem_size;
|
||||
uint64_t pci_hole64_size;
|
||||
uint32_t short_root_bus;
|
||||
uint16_t ext_tseg_mbytes;
|
||||
} MCHPCIState;
|
||||
|
||||
typedef struct Q35PCIHost {
|
||||
@ -91,6 +92,11 @@ typedef struct Q35PCIHost {
|
||||
/* D0:F0 configuration space */
|
||||
#define MCH_HOST_BRIDGE_REVISION_DEFAULT 0x0
|
||||
|
||||
#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES 0x50
|
||||
#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_SIZE 2
|
||||
#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY 0xffff
|
||||
#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_MAX 0xfff
|
||||
|
||||
#define MCH_HOST_BRIDGE_PCIEXBAR 0x60 /* 64bit register */
|
||||
#define MCH_HOST_BRIDGE_PCIEXBAR_SIZE 8 /* 64bit register */
|
||||
#define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xb0000000
|
||||
|
125
tests/q35-test.c
125
tests/q35-test.c
@ -15,6 +15,48 @@
|
||||
#include "libqos/pci-pc.h"
|
||||
#include "hw/pci-host/q35.h"
|
||||
|
||||
#define TSEG_SIZE_TEST_GUEST_RAM_MBYTES 128
|
||||
|
||||
/* @esmramc_tseg_sz: ESMRAMC.TSEG_SZ bitmask for selecting the requested TSEG
|
||||
* size. Must be a subset of
|
||||
* MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK.
|
||||
*
|
||||
* @extended_tseg_mbytes: Size of the extended TSEG. Only consulted if
|
||||
* @esmramc_tseg_sz equals
|
||||
* MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK precisely.
|
||||
*
|
||||
* @expected_tseg_mbytes: Expected guest-visible TSEG size in megabytes,
|
||||
* matching @esmramc_tseg_sz and @extended_tseg_mbytes
|
||||
* above.
|
||||
*/
|
||||
struct TsegSizeArgs {
|
||||
uint8_t esmramc_tseg_sz;
|
||||
uint16_t extended_tseg_mbytes;
|
||||
uint16_t expected_tseg_mbytes;
|
||||
};
|
||||
typedef struct TsegSizeArgs TsegSizeArgs;
|
||||
|
||||
static const TsegSizeArgs tseg_1mb = {
|
||||
.esmramc_tseg_sz = MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB,
|
||||
.extended_tseg_mbytes = 0,
|
||||
.expected_tseg_mbytes = 1,
|
||||
};
|
||||
static const TsegSizeArgs tseg_2mb = {
|
||||
.esmramc_tseg_sz = MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB,
|
||||
.extended_tseg_mbytes = 0,
|
||||
.expected_tseg_mbytes = 2,
|
||||
};
|
||||
static const TsegSizeArgs tseg_8mb = {
|
||||
.esmramc_tseg_sz = MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB,
|
||||
.extended_tseg_mbytes = 0,
|
||||
.expected_tseg_mbytes = 8,
|
||||
};
|
||||
static const TsegSizeArgs tseg_ext_16mb = {
|
||||
.esmramc_tseg_sz = MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK,
|
||||
.extended_tseg_mbytes = 16,
|
||||
.expected_tseg_mbytes = 16,
|
||||
};
|
||||
|
||||
static void smram_set_bit(QPCIDevice *pcidev, uint8_t mask, bool enabled)
|
||||
{
|
||||
uint8_t smram;
|
||||
@ -42,6 +84,8 @@ static void test_smram_lock(void)
|
||||
QPCIDevice *pcidev;
|
||||
QDict *response;
|
||||
|
||||
qtest_start("-M q35");
|
||||
|
||||
pcibus = qpci_init_pc(NULL);
|
||||
g_assert(pcibus != NULL);
|
||||
|
||||
@ -74,19 +118,86 @@ static void test_smram_lock(void)
|
||||
|
||||
g_free(pcidev);
|
||||
qpci_free_pc(pcibus);
|
||||
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
static void test_tseg_size(const void *data)
|
||||
{
|
||||
const TsegSizeArgs *args = data;
|
||||
char *cmdline;
|
||||
QPCIBus *pcibus;
|
||||
QPCIDevice *pcidev;
|
||||
uint8_t smram_val;
|
||||
uint8_t esmramc_val;
|
||||
uint32_t ram_offs;
|
||||
|
||||
if (args->esmramc_tseg_sz == MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK) {
|
||||
cmdline = g_strdup_printf("-M q35 -m %uM "
|
||||
"-global mch.extended-tseg-mbytes=%u",
|
||||
TSEG_SIZE_TEST_GUEST_RAM_MBYTES,
|
||||
args->extended_tseg_mbytes);
|
||||
} else {
|
||||
cmdline = g_strdup_printf("-M q35 -m %uM",
|
||||
TSEG_SIZE_TEST_GUEST_RAM_MBYTES);
|
||||
}
|
||||
qtest_start(cmdline);
|
||||
g_free(cmdline);
|
||||
|
||||
/* locate the DRAM controller */
|
||||
pcibus = qpci_init_pc(NULL);
|
||||
g_assert(pcibus != NULL);
|
||||
pcidev = qpci_device_find(pcibus, 0);
|
||||
g_assert(pcidev != NULL);
|
||||
|
||||
/* Set TSEG size. Restrict TSEG visibility to SMM by setting T_EN. */
|
||||
esmramc_val = qpci_config_readb(pcidev, MCH_HOST_BRIDGE_ESMRAMC);
|
||||
esmramc_val &= ~MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK;
|
||||
esmramc_val |= args->esmramc_tseg_sz;
|
||||
esmramc_val |= MCH_HOST_BRIDGE_ESMRAMC_T_EN;
|
||||
qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_ESMRAMC, esmramc_val);
|
||||
|
||||
/* Enable TSEG by setting G_SMRAME. Close TSEG by setting D_CLS. */
|
||||
smram_val = qpci_config_readb(pcidev, MCH_HOST_BRIDGE_SMRAM);
|
||||
smram_val &= ~(MCH_HOST_BRIDGE_SMRAM_D_OPEN |
|
||||
MCH_HOST_BRIDGE_SMRAM_D_LCK);
|
||||
smram_val |= (MCH_HOST_BRIDGE_SMRAM_D_CLS |
|
||||
MCH_HOST_BRIDGE_SMRAM_G_SMRAME);
|
||||
qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_SMRAM, smram_val);
|
||||
|
||||
/* lock TSEG */
|
||||
smram_val |= MCH_HOST_BRIDGE_SMRAM_D_LCK;
|
||||
qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_SMRAM, smram_val);
|
||||
|
||||
/* Now check that the byte right before the TSEG is r/w, and that the first
|
||||
* byte in the TSEG always reads as 0xff.
|
||||
*/
|
||||
ram_offs = (TSEG_SIZE_TEST_GUEST_RAM_MBYTES - args->expected_tseg_mbytes) *
|
||||
1024 * 1024 - 1;
|
||||
g_assert_cmpint(readb(ram_offs), ==, 0);
|
||||
writeb(ram_offs, 1);
|
||||
g_assert_cmpint(readb(ram_offs), ==, 1);
|
||||
|
||||
ram_offs++;
|
||||
g_assert_cmpint(readb(ram_offs), ==, 0xff);
|
||||
writeb(ram_offs, 1);
|
||||
g_assert_cmpint(readb(ram_offs), ==, 0xff);
|
||||
|
||||
g_free(pcidev);
|
||||
qpci_free_pc(pcibus);
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
qtest_add_func("/q35/smram/lock", test_smram_lock);
|
||||
|
||||
qtest_start("-M q35");
|
||||
ret = g_test_run();
|
||||
qtest_end();
|
||||
|
||||
return ret;
|
||||
qtest_add_data_func("/q35/tseg-size/1mb", &tseg_1mb, test_tseg_size);
|
||||
qtest_add_data_func("/q35/tseg-size/2mb", &tseg_2mb, test_tseg_size);
|
||||
qtest_add_data_func("/q35/tseg-size/8mb", &tseg_8mb, test_tseg_size);
|
||||
qtest_add_data_func("/q35/tseg-size/ext/16mb", &tseg_ext_16mb,
|
||||
test_tseg_size);
|
||||
return g_test_run();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user