tools/cpu-policy: Add unit tests

These will be extended with further libx86 work.

Fix the sorting of the CPUID_GUEST_NR_* constants, noticed while writing the
unit tests.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2019-03-12 14:12:31 +00:00
1 parent f48363c9ca
commit 919ddc3c0e
5 files changed
+289 -1

No files matched your search

+1
View File
@@ -5,6 +5,7 @@ CFLAGS += $(CFLAGS_libxenctrl)
LDLIBS += $(LDLIBS_libxenctrl)
SUBDIRS-y :=
SUBDIRS-$(CONFIG_X86) += cpu-policy
SUBDIRS-$(CONFIG_X86) += mce-test
SUBDIRS-y += mem-sharing
ifneq ($(clang),y)
+1
View File
@@ -0,0 +1 @@
test-cpu-policy
+28
View File
@@ -0,0 +1,28 @@
XEN_ROOT = $(CURDIR)/../../..
include $(XEN_ROOT)/tools/Rules.mk
.PHONY: all
all: test-cpu-policy
.PHONY: clean
clean:
$(RM) -f -- *.o .*.d .*.d2 test-cpu-policy
.PHONY: distclean
distclean: clean
$(RM) -f -- *~
.PHONY: install
install: all
.PHONY: uninstall
CFLAGS += -Werror $(CFLAGS_xeninclude) -D__XEN_TOOLS__ -O3
CFLAGS += $(APPEND_CFLAGS)
vpath %.c ../../../xen/lib/x86
test-cpu-policy: test-cpu-policy.o msr.o cpuid.o
$(CC) $(CFLAGS) $^ -o $@
-include $(DEPS_INCLUDE)
+258
View File
@@ -0,0 +1,258 @@
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <xen-tools/libs.h>
#include <xen/lib/x86/cpuid.h>
#include <xen/lib/x86/msr.h>
#include <xen/domctl.h>
static unsigned int nr_failures;
#define fail(fmt, ...) \
({ \
nr_failures++; \
printf(fmt, ##__VA_ARGS__); \
})
static void test_cpuid_serialise_success(void)
{
static const struct test {
struct cpuid_policy p;
const char *name;
unsigned int nr_leaves;
} tests[] = {
{
.name = "empty policy",
.nr_leaves = 4,
},
};
printf("Testing CPUID serialise success:\n");
for ( size_t i = 0; i < ARRAY_SIZE(tests); ++i )
{
const struct test *t = &tests[i];
unsigned int nr = t->nr_leaves;
xen_cpuid_leaf_t *leaves = malloc(nr * sizeof(*leaves));
int rc;
if ( !leaves )
err(1, "%s() malloc failure", __func__);
rc = x86_cpuid_copy_to_buffer(&t->p, leaves, &nr);
if ( rc != 0 )
{
fail(" Test %s, expected rc 0, got %d\n",
t->name, rc);
goto test_done;
}
if ( nr != t->nr_leaves )
{
fail(" Test %s, expected %u leaves, got %u\n",
t->name, t->nr_leaves, nr);
goto test_done;
}
test_done:
free(leaves);
}
}
static void test_msr_serialise_success(void)
{
static const struct test {
struct msr_policy p;
const char *name;
unsigned int nr_msrs;
} tests[] = {
{
.name = "empty policy",
.nr_msrs = MSR_MAX_SERIALISED_ENTRIES,
},
};
printf("Testing MSR serialise success:\n");
for ( size_t i = 0; i < ARRAY_SIZE(tests); ++i )
{
const struct test *t = &tests[i];
unsigned int nr = t->nr_msrs;
xen_msr_entry_t *msrs = malloc(nr * sizeof(*msrs));
int rc;
if ( !msrs )
err(1, "%s() malloc failure", __func__);
rc = x86_msr_copy_to_buffer(&t->p, msrs, &nr);
if ( rc != 0 )
{
fail(" Test %s, expected rc 0, got %d\n",
t->name, rc);
goto test_done;
}
if ( nr != t->nr_msrs )
{
fail(" Test %s, expected %u msrs, got %u\n",
t->name, t->nr_msrs, nr);
goto test_done;
}
test_done:
free(msrs);
}
}
static void test_cpuid_deserialise_failure(void)
{
static const struct test {
const char *name;
xen_cpuid_leaf_t leaf;
} tests[] = {
{
.name = "incorrect basic subleaf",
.leaf = { .leaf = 0, .subleaf = 0 },
},
{
.name = "incorrect hv1 subleaf",
.leaf = { .leaf = 0x40000000, .subleaf = 0 },
},
{
.name = "incorrect hv2 subleaf",
.leaf = { .leaf = 0x40000100, .subleaf = 0 },
},
{
.name = "incorrect extd subleaf",
.leaf = { .leaf = 0x80000000, .subleaf = 0 },
},
{
.name = "OoB basic leaf",
.leaf = { .leaf = CPUID_GUEST_NR_BASIC },
},
{
.name = "OoB cache leaf",
.leaf = { .leaf = 0x4, .subleaf = CPUID_GUEST_NR_CACHE },
},
{
.name = "OoB feat leaf",
.leaf = { .leaf = 0x7, .subleaf = CPUID_GUEST_NR_FEAT },
},
{
.name = "OoB topo leaf",
.leaf = { .leaf = 0xb, .subleaf = CPUID_GUEST_NR_TOPO },
},
{
.name = "OoB xstate leaf",
.leaf = { .leaf = 0xd, .subleaf = CPUID_GUEST_NR_XSTATE },
},
{
.name = "OoB extd leaf",
.leaf = { .leaf = 0x80000000 | CPUID_GUEST_NR_EXTD },
},
};
printf("Testing CPUID deserialise failure:\n");
for ( size_t i = 0; i < ARRAY_SIZE(tests); ++i )
{
const struct test *t = &tests[i];
uint32_t err_leaf = ~0u, err_subleaf = ~0u;
int rc;
/* No writes should occur. Use NULL to catch errors. */
rc = x86_cpuid_copy_from_buffer(NULL, &t->leaf, 1,
&err_leaf, &err_subleaf);
if ( rc != -ERANGE )
{
fail(" Test %s, expected rc %d, got %d\n",
t->name, -ERANGE, rc);
continue;
}
if ( err_leaf != t->leaf.leaf || err_subleaf != t->leaf.subleaf )
{
fail(" Test %s, expected err %08x:%08x, got %08x:%08x\n",
t->name, t->leaf.leaf, t->leaf.subleaf,
err_leaf, err_subleaf);
continue;
}
}
}
static void test_msr_deserialise_failure(void)
{
static const struct test {
const char *name;
xen_msr_entry_t msr;
int rc;
} tests[] = {
{
.name = "bad msr index",
.msr = { .idx = 0xdeadc0de },
.rc = -ERANGE,
},
{
.name = "nonzero flags",
.msr = { .idx = 0xce, .flags = 1 },
.rc = -EINVAL,
},
{
.name = "truncated val",
.msr = { .idx = 0xce, .val = ~0ull },
.rc = -EOVERFLOW,
},
};
printf("Testing MSR deserialise failure:\n");
for ( size_t i = 0; i < ARRAY_SIZE(tests); ++i )
{
const struct test *t = &tests[i];
uint32_t err_msr = ~0u;
int rc;
/* No writes should occur. Use NULL to catch errors. */
rc = x86_msr_copy_from_buffer(NULL, &t->msr, 1, &err_msr);
if ( rc != t->rc )
{
fail(" Test %s, expected rc %d, got %d\n",
t->name, t->rc, rc);
continue;
}
if ( err_msr != t->msr.idx )
{
fail(" Test %s, expected err_msr %#x, got %#x\n",
t->name, t->msr.idx, err_msr);
continue;
}
}
}
int main(int argc, char **argv)
{
printf("CPU Policy unit tests\n");
test_cpuid_serialise_success();
test_msr_serialise_success();
test_cpuid_deserialise_failure();
test_msr_deserialise_failure();
if ( nr_failures )
printf("Done: %u failures\n", nr_failures);
else
printf("Done: all ok\n");
return !!nr_failures;
}
+1 -1
View File
@@ -66,8 +66,8 @@ static inline void cpuid_count_leaf(
#undef XCHG
#define CPUID_GUEST_NR_BASIC (0xdu + 1)
#define CPUID_GUEST_NR_FEAT (0u + 1)
#define CPUID_GUEST_NR_CACHE (5u + 1)
#define CPUID_GUEST_NR_FEAT (0u + 1)
#define CPUID_GUEST_NR_TOPO (1u + 1)
#define CPUID_GUEST_NR_XSTATE (62u + 1)
#define CPUID_GUEST_NR_EXTD_INTEL (0x8u + 1)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.