# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1219328285 -3600
# Node ID 2ec019301ad8a16d776cb4eb9fedcc596aa39732
# Parent 4f8518b00ab148ebabd93d4f024b2cf27b6f64c9
hvmloader: Debug build incorporates HVM environment tests which must
pass for the HVM guest to successfully boot.
Currently only one test (REP INS across page boundaries) but more will
be added in future.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
tools/firmware/Rules.mk | 4
tools/firmware/hvmloader/Makefile | 3
tools/firmware/hvmloader/hvmloader.c | 2
tools/firmware/hvmloader/tests.c | 164 +++++++++++++++++++++++++++++++++++
tools/firmware/hvmloader/util.h | 6 +
5 files changed, 179 insertions(+)
diff -r 4f8518b00ab1 -r 2ec019301ad8 tools/firmware/Rules.mk
--- a/tools/firmware/Rules.mk Thu Aug 21 11:12:21 2008 +0100
+++ b/tools/firmware/Rules.mk Thu Aug 21 15:18:05 2008 +0100
@@ -5,6 +5,10 @@ CFLAGS :=
CFLAGS :=
include $(XEN_ROOT)/tools/Rules.mk
+
+ifneq ($(debug),y)
+CFLAGS += -DNDEBUG
+endif
CFLAGS += -Werror
diff -r 4f8518b00ab1 -r 2ec019301ad8 tools/firmware/hvmloader/Makefile
--- a/tools/firmware/hvmloader/Makefile Thu Aug 21 11:12:21 2008 +0100
+++ b/tools/firmware/hvmloader/Makefile Thu Aug 21 15:18:05 2008 +0100
@@ -30,6 +30,9 @@ CFLAGS += $(CFLAGS_include) -I.
SRCS = hvmloader.c mp_tables.c util.c smbios.c
SRCS += 32bitbios_support.c smp.c cacheattr.c
+ifeq ($(debug),y)
+SRCS += tests.c
+endif
OBJS = $(patsubst %.c,%.o,$(SRCS))
.PHONY: all
diff -r 4f8518b00ab1 -r 2ec019301ad8 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Thu Aug 21 11:12:21 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c Thu Aug 21 15:18:05 2008 +0100
@@ -460,6 +460,8 @@ int main(void)
smp_initialise();
+ perform_tests();
+
printf("Writing SMBIOS tables ...\n");
smbios_sz = hvm_write_smbios_tables();
diff -r 4f8518b00ab1 -r 2ec019301ad8 tools/firmware/hvmloader/tests.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/hvmloader/tests.c Thu Aug 21 15:18:05 2008 +0100
@@ -0,0 +1,164 @@
+/*
+ * tests.c: HVM environment tests.
+ *
+ * Copyright (c) 2008, Citrix Systems, Inc.
+ *
+ * Authors:
+ * Keir Fraser <keir.fraser@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "util.h"
+
+/*
+ * Memory layout during tests:
+ * 4MB to 8MB is cleared.
+ * Page directory resides at 8MB.
+ * 4 page table pages reside at 8MB+4kB to 8MB+20kB.
+ * Pagetables identity-map 0-16MB, except 4kB at va 6MB maps to pa 5MB.
+ */
+#define PD_START (8ul << 20)
+#define PT_START (PD_START + 4096)
+
+static void setup_paging(void)
+{
+ uint32_t *pd = (uint32_t *)PD_START;
+ uint32_t *pt = (uint32_t *)PT_START;
+ uint32_t i;
+
+ /* Identity map 0-16MB. */
+ for ( i = 0; i < 4; i++ )
+ pd[i] = (unsigned long)pt + (i<<12) + 3;
+ for ( i = 0; i < (4*1024); i++ )
+ pt[i] = (i << 12) + 3;
+
+ /* Page at virtual 6MB maps to physical 5MB. */
+ pt[6u<<8] -= 0x100000u;
+}
+
+static void start_paging(void)
+{
+ asm volatile (
+ "mov %%eax,%%cr3; mov %%cr0,%%eax; "
+ "orl $0x80000000,%%eax; mov %%eax,%%cr0; "
+ "jmp 1f; 1:"
+ : : "a" (PD_START) : "memory" );
+}
+
+static void stop_paging(void)
+{
+ asm volatile (
+ "mov %%cr0,%%eax; andl $0x7fffffff,%%eax; mov %%eax,%%cr0; "
+ "jmp 1f; 1:"
+ : : : "eax", "memory" );
+}
+
+/*
+ * rep_io_test: Tests REP INSB both forwards and backwards (EF.DF={0,1}) across
+ * a discontiguous page boundary.
+ */
+static int rep_io_test(void)
+{
+ uint32_t *p;
+ uint32_t i, p0, p1, p2;
+ int okay = 1;
+
+ static const struct {
+ unsigned long addr;
+ uint32_t expected;
+ } check[] = {
+ { 0x00500000, 0x987654ff },
+ { 0x00500ffc, 0xff000000 },
+ { 0x005ffffc, 0xff000000 },
+ { 0x00601000, 0x000000ff },
+ { 0, 0 }
+ };
+
+ start_paging();
+
+ /* Phys 5MB = 0xdeadbeef */
+ *(uint32_t *)0x500000ul = 0xdeadbeef;
+
+ /* Phys 5MB = 0x98765432 */
+ *(uint32_t *)0x600000ul = 0x98765432;
+
+ /* Phys 0x5fffff = Phys 0x500000 = 0xff (byte) */
+ asm volatile (
+ "rep insb"
+ : "=d" (p0), "=c" (p1), "=D" (p2)
+ : "0" (0x5f), "1" (2), "2" (0x5ffffful) : "memory" );
+
+ /* Phys 0x500fff = Phys 0x601000 = 0xff (byte) */
+ asm volatile (
+ "std ; rep insb ; cld"
+ : "=d" (p0), "=c" (p1), "=D" (p2)
+ : "0" (0x5f), "1" (2), "2" (0x601000ul) : "memory" );
+
+ stop_paging();
+
+ i = 0;
+ for ( p = (uint32_t *)0x400000ul; p < (uint32_t *)0x700000ul; p++ )
+ {
+ uint32_t expected = 0;
+ if ( check[i].addr == (unsigned long)p )
+ {
+ expected = check[i].expected;
+ i++;
+ }
+ if ( *p != expected )
+ {
+ printf("Bad value at 0x%08lx: saw %08x expected %08x\n",
+ (unsigned long)p, *p, expected);
+ okay = 0;
+ }
+ }
+
+ return okay;
+}
+
+void perform_tests(void)
+{
+ int i, passed;
+
+ static struct {
+ int (* const test)(void);
+ const char *description;
+ } tests[] = {
+ { rep_io_test, "REP INSB across page boundaries" },
+ { NULL, NULL }
+ };
+
+ printf("Testing HVM environment:\n");
+
+ passed = 0;
+ for ( i = 0; tests[i].test; i++ )
+ {
+ printf(" - %s ... ", tests[i].description);
+ memset((char *)(4ul << 20), 0, 4ul << 20);
+ setup_paging();
+ if ( (*tests[i].test)() )
+ {
+ printf("passed\n");
+ passed++;
+ }
+ else
+ {
+ printf("failed\n");
+ }
+ }
+
+ printf("Passed %d/%d tests\n", passed, i);
+ BUG_ON(passed != i);
+}
diff -r 4f8518b00ab1 -r 2ec019301ad8 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Thu Aug 21 11:12:21 2008 +0100
+++ b/tools/firmware/hvmloader/util.h Thu Aug 21 15:18:05 2008 +0100
@@ -143,6 +143,12 @@ int hvm_write_smbios_tables(void);
int hvm_write_smbios_tables(void);
void smp_initialise(void);
+#ifndef NDEBUG
+void perform_tests(void);
+#else
+#define perform_tests() ((void)0)
+#endif
+
#define isdigit(c) ((c) >= '0' && (c) <= '9')
extern char _start[], _end[];
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|