From a875711af9518f0878e084aef00c323098b8f972 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Tue, 16 Apr 2013 09:45:20 -0500 Subject: i440fx-test: add test for PAM functionality This tests PAM settings for the i440fx. This test does a lot of byte MMIO which is fairly slow with qtest today. But the test does complete in under 2 seconds. We don't fully emulate PAM largely because of limitations with KVM so we #if 0 that part of the test case. Signed-off-by: Anthony Liguori Message-id: 1366123521-4330-7-git-send-email-aliguori@us.ibm.com --- tests/i440fx-test.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) (limited to 'tests/i440fx-test.c') diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c index 6fba741d97..08ce820ebd 100644 --- a/tests/i440fx-test.c +++ b/tests/i440fx-test.c @@ -17,10 +17,12 @@ #include "hw/pci/pci_regs.h" #include -#include +#include #define BROKEN 1 +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + typedef struct TestData { int num_cpus; @@ -119,6 +121,139 @@ static void test_i440fx_defaults(gconstpointer opaque) g_assert_cmpint(qpci_config_readb(dev, 0x93), ==, 0x00); /* TRC */ } +#define PAM_RE 1 +#define PAM_WE 2 + +static void pam_set(QPCIDevice *dev, int index, int flags) +{ + int regno = 0x59 + (index / 2); + uint8_t reg; + + reg = qpci_config_readb(dev, regno); + if (index & 1) { + reg = (reg & 0x0F) | (flags << 4); + } else { + reg = (reg & 0xF0) | flags; + } + qpci_config_writeb(dev, regno, reg); +} + +static gboolean verify_area(uint32_t start, uint32_t end, uint8_t value) +{ + uint32_t size = end - start + 1; + gboolean ret = TRUE; + uint8_t *data; + int i; + + data = g_malloc0(size); + memread(start, data, size); + + g_test_message("verify_area: data[0] = 0x%x", data[0]); + + for (i = 0; i < size; i++) { + if (data[i] != value) { + ret = FALSE; + break; + } + } + + g_free(data); + + return ret; +} + +static void write_area(uint32_t start, uint32_t end, uint8_t value) +{ + uint32_t size = end - start + 1; + uint8_t *data; + + data = g_malloc0(size); + memset(data, value, size); + memwrite(start, data, size); + + g_free(data); +} + +static void test_i440fx_pam(gconstpointer opaque) +{ + const TestData *s = opaque; + QPCIDevice *dev; + int i; + static struct { + uint32_t start; + uint32_t end; + } pam_area[] = { + { 0, 0 }, /* Reserved */ + { 0xF0000, 0xFFFFF }, /* BIOS Area */ + { 0xC0000, 0xC3FFF }, /* Option ROM */ + { 0xC4000, 0xC7FFF }, /* Option ROM */ + { 0xC8000, 0xCBFFF }, /* Option ROM */ + { 0xCC000, 0xCFFFF }, /* Option ROM */ + { 0xD0000, 0xD3FFF }, /* Option ROM */ + { 0xD4000, 0xD7FFF }, /* Option ROM */ + { 0xD8000, 0xDBFFF }, /* Option ROM */ + { 0xDC000, 0xDFFFF }, /* Option ROM */ + { 0xE0000, 0xE3FFF }, /* BIOS Extension */ + { 0xE4000, 0xE7FFF }, /* BIOS Extension */ + { 0xE8000, 0xEBFFF }, /* BIOS Extension */ + { 0xEC000, 0xEFFFF }, /* BIOS Extension */ + }; + + dev = qpci_device_find(s->bus, QPCI_DEVFN(0, 0)); + g_assert(dev != NULL); + + for (i = 0; i < ARRAY_SIZE(pam_area); i++) { + if (pam_area[i].start == pam_area[i].end) { + continue; + } + + g_test_message("Checking area 0x%05x..0x%05x", + pam_area[i].start, pam_area[i].end); + /* Switch to RE for the area */ + pam_set(dev, i, PAM_RE); + /* Verify the RAM is all zeros */ + g_assert(verify_area(pam_area[i].start, pam_area[i].end, 0)); + + /* Switch to WE for the area */ + pam_set(dev, i, PAM_RE | PAM_WE); + /* Write out a non-zero mask to the full area */ + write_area(pam_area[i].start, pam_area[i].end, 0x42); + +#ifndef BROKEN + /* QEMU only supports a limited form of PAM */ + + /* Switch to !RE for the area */ + pam_set(dev, i, PAM_WE); + /* Verify the area is not our mask */ + g_assert(!verify_area(pam_area[i].start, pam_area[i].end, 0x42)); +#endif + + /* Verify the area is our new mask */ + g_assert(verify_area(pam_area[i].start, pam_area[i].end, 0x42)); + + /* Write out a new mask */ + write_area(pam_area[i].start, pam_area[i].end, 0x82); + +#ifndef BROKEN + /* QEMU only supports a limited form of PAM */ + + /* Verify the area is not our mask */ + g_assert(!verify_area(pam_area[i].start, pam_area[i].end, 0x82)); + + /* Switch to RE for the area */ + pam_set(dev, i, PAM_RE | PAM_WE); +#endif + /* Verify the area is our new mask */ + g_assert(verify_area(pam_area[i].start, pam_area[i].end, 0x82)); + + /* Reset area */ + pam_set(dev, i, 0); + + /* Verify the area is not our new mask */ + g_assert(!verify_area(pam_area[i].start, pam_area[i].end, 0x82)); + } +} + int main(int argc, char **argv) { QTestState *s; @@ -137,6 +272,8 @@ int main(int argc, char **argv) data.bus = qpci_init_pc(); g_test_add_data_func("/i440fx/defaults", &data, test_i440fx_defaults); + g_test_add_data_func("/i440fx/pam", &data, test_i440fx_pam); + ret = g_test_run(); -- cgit v1.2.1