ia64/xen-unstable

changeset 18358:2ec019301ad8

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@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Aug 21 15:18:05 2008 +0100 (2008-08-21)
parents 4f8518b00ab1
children de736eefb6e1 95f1dc27e182
files tools/firmware/Rules.mk tools/firmware/hvmloader/Makefile tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/tests.c tools/firmware/hvmloader/util.h
line diff
     1.1 --- a/tools/firmware/Rules.mk	Thu Aug 21 11:12:21 2008 +0100
     1.2 +++ b/tools/firmware/Rules.mk	Thu Aug 21 15:18:05 2008 +0100
     1.3 @@ -6,6 +6,10 @@ CFLAGS :=
     1.4  
     1.5  include $(XEN_ROOT)/tools/Rules.mk
     1.6  
     1.7 +ifneq ($(debug),y)
     1.8 +CFLAGS += -DNDEBUG
     1.9 +endif
    1.10 +
    1.11  CFLAGS += -Werror
    1.12  
    1.13  # Disable PIE/SSP if GCC supports them. They can break us.
     2.1 --- a/tools/firmware/hvmloader/Makefile	Thu Aug 21 11:12:21 2008 +0100
     2.2 +++ b/tools/firmware/hvmloader/Makefile	Thu Aug 21 15:18:05 2008 +0100
     2.3 @@ -30,6 +30,9 @@ CFLAGS += $(CFLAGS_include) -I.
     2.4  
     2.5  SRCS  = hvmloader.c mp_tables.c util.c smbios.c 
     2.6  SRCS += 32bitbios_support.c smp.c cacheattr.c
     2.7 +ifeq ($(debug),y)
     2.8 +SRCS += tests.c
     2.9 +endif
    2.10  OBJS  = $(patsubst %.c,%.o,$(SRCS))
    2.11  
    2.12  .PHONY: all
     3.1 --- a/tools/firmware/hvmloader/hvmloader.c	Thu Aug 21 11:12:21 2008 +0100
     3.2 +++ b/tools/firmware/hvmloader/hvmloader.c	Thu Aug 21 15:18:05 2008 +0100
     3.3 @@ -460,6 +460,8 @@ int main(void)
     3.4  
     3.5      smp_initialise();
     3.6  
     3.7 +    perform_tests();
     3.8 +
     3.9      printf("Writing SMBIOS tables ...\n");
    3.10      smbios_sz = hvm_write_smbios_tables();
    3.11  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/firmware/hvmloader/tests.c	Thu Aug 21 15:18:05 2008 +0100
     4.3 @@ -0,0 +1,164 @@
     4.4 +/*
     4.5 + * tests.c: HVM environment tests.
     4.6 + *
     4.7 + * Copyright (c) 2008, Citrix Systems, Inc.
     4.8 + * 
     4.9 + * Authors:
    4.10 + *    Keir Fraser <keir.fraser@citrix.com>
    4.11 + * 
    4.12 + * This program is free software; you can redistribute it and/or modify it
    4.13 + * under the terms and conditions of the GNU General Public License,
    4.14 + * version 2, as published by the Free Software Foundation.
    4.15 + *
    4.16 + * This program is distributed in the hope it will be useful, but WITHOUT
    4.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.18 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    4.19 + * more details.
    4.20 + *
    4.21 + * You should have received a copy of the GNU General Public License along with
    4.22 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    4.23 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    4.24 + */
    4.25 +
    4.26 +#include "util.h"
    4.27 +
    4.28 +/*
    4.29 + * Memory layout during tests:
    4.30 + *  4MB to 8MB is cleared.
    4.31 + *  Page directory resides at 8MB.
    4.32 + *  4 page table pages reside at 8MB+4kB to 8MB+20kB.
    4.33 + *  Pagetables identity-map 0-16MB, except 4kB at va 6MB maps to pa 5MB.
    4.34 + */
    4.35 +#define PD_START (8ul << 20)
    4.36 +#define PT_START (PD_START + 4096)
    4.37 +
    4.38 +static void setup_paging(void)
    4.39 +{
    4.40 +    uint32_t *pd = (uint32_t *)PD_START;
    4.41 +    uint32_t *pt = (uint32_t *)PT_START;
    4.42 +    uint32_t i;
    4.43 +
    4.44 +    /* Identity map 0-16MB. */
    4.45 +    for ( i = 0; i < 4; i++ )
    4.46 +        pd[i] = (unsigned long)pt + (i<<12) + 3;
    4.47 +    for ( i = 0; i < (4*1024); i++ )
    4.48 +        pt[i] = (i << 12) + 3;
    4.49 +
    4.50 +    /* Page at virtual 6MB maps to physical 5MB. */
    4.51 +    pt[6u<<8] -= 0x100000u;
    4.52 +}
    4.53 +
    4.54 +static void start_paging(void)
    4.55 +{
    4.56 +    asm volatile (
    4.57 +        "mov %%eax,%%cr3; mov %%cr0,%%eax; "
    4.58 +        "orl $0x80000000,%%eax; mov %%eax,%%cr0; "
    4.59 +        "jmp 1f; 1:"
    4.60 +        : : "a" (PD_START) : "memory" );
    4.61 +}
    4.62 +
    4.63 +static void stop_paging(void)
    4.64 +{
    4.65 +    asm volatile (
    4.66 +        "mov %%cr0,%%eax; andl $0x7fffffff,%%eax; mov %%eax,%%cr0; "
    4.67 +        "jmp 1f; 1:"
    4.68 +        : : : "eax", "memory" );
    4.69 +}
    4.70 +
    4.71 +/*
    4.72 + * rep_io_test: Tests REP INSB both forwards and backwards (EF.DF={0,1}) across
    4.73 + * a discontiguous page boundary.
    4.74 + */
    4.75 +static int rep_io_test(void)
    4.76 +{
    4.77 +    uint32_t *p;
    4.78 +    uint32_t i, p0, p1, p2;
    4.79 +    int okay = 1;
    4.80 +
    4.81 +    static const struct {
    4.82 +        unsigned long addr;
    4.83 +        uint32_t expected;
    4.84 +    } check[] = {
    4.85 +        { 0x00500000, 0x987654ff },
    4.86 +        { 0x00500ffc, 0xff000000 },
    4.87 +        { 0x005ffffc, 0xff000000 },
    4.88 +        { 0x00601000, 0x000000ff },
    4.89 +        { 0, 0 }
    4.90 +    };
    4.91 +
    4.92 +    start_paging();
    4.93 +
    4.94 +    /* Phys 5MB = 0xdeadbeef */
    4.95 +    *(uint32_t *)0x500000ul = 0xdeadbeef;
    4.96 +
    4.97 +    /* Phys 5MB = 0x98765432 */
    4.98 +    *(uint32_t *)0x600000ul = 0x98765432;
    4.99 +
   4.100 +    /* Phys 0x5fffff = Phys 0x500000 = 0xff (byte) */
   4.101 +    asm volatile (
   4.102 +        "rep insb"
   4.103 +        : "=d" (p0), "=c" (p1), "=D" (p2)
   4.104 +        : "0" (0x5f), "1" (2), "2" (0x5ffffful) : "memory" );
   4.105 +
   4.106 +    /* Phys 0x500fff = Phys 0x601000 = 0xff (byte) */
   4.107 +    asm volatile (
   4.108 +        "std ; rep insb ; cld"
   4.109 +        : "=d" (p0), "=c" (p1), "=D" (p2)
   4.110 +        : "0" (0x5f), "1" (2), "2" (0x601000ul) : "memory" );
   4.111 +
   4.112 +    stop_paging();
   4.113 +
   4.114 +    i = 0;
   4.115 +    for ( p = (uint32_t *)0x400000ul; p < (uint32_t *)0x700000ul; p++ )
   4.116 +    {
   4.117 +        uint32_t expected = 0;
   4.118 +        if ( check[i].addr == (unsigned long)p )
   4.119 +        {
   4.120 +            expected = check[i].expected;
   4.121 +            i++;
   4.122 +        }
   4.123 +        if ( *p != expected )
   4.124 +        {
   4.125 +            printf("Bad value at 0x%08lx: saw %08x expected %08x\n",
   4.126 +                   (unsigned long)p, *p, expected);
   4.127 +            okay = 0;
   4.128 +        }
   4.129 +    }
   4.130 +
   4.131 +    return okay;
   4.132 +}
   4.133 +
   4.134 +void perform_tests(void)
   4.135 +{
   4.136 +    int i, passed;
   4.137 +
   4.138 +    static struct {
   4.139 +        int (* const test)(void);
   4.140 +        const char *description;
   4.141 +    } tests[] = {
   4.142 +        { rep_io_test, "REP INSB across page boundaries" },
   4.143 +        { NULL, NULL }
   4.144 +    };
   4.145 +
   4.146 +    printf("Testing HVM environment:\n");
   4.147 +
   4.148 +    passed = 0;
   4.149 +    for ( i = 0; tests[i].test; i++ )
   4.150 +    {
   4.151 +        printf(" - %s ... ", tests[i].description);
   4.152 +        memset((char *)(4ul << 20), 0, 4ul << 20);
   4.153 +        setup_paging();
   4.154 +        if ( (*tests[i].test)() )
   4.155 +        {
   4.156 +            printf("passed\n");
   4.157 +            passed++;
   4.158 +        }
   4.159 +        else
   4.160 +        {
   4.161 +            printf("failed\n");
   4.162 +        }
   4.163 +    }
   4.164 +
   4.165 +    printf("Passed %d/%d tests\n", passed, i);
   4.166 +    BUG_ON(passed != i);
   4.167 +}
     5.1 --- a/tools/firmware/hvmloader/util.h	Thu Aug 21 11:12:21 2008 +0100
     5.2 +++ b/tools/firmware/hvmloader/util.h	Thu Aug 21 15:18:05 2008 +0100
     5.3 @@ -143,6 +143,12 @@ void create_mp_tables(void);
     5.4  int hvm_write_smbios_tables(void);
     5.5  void smp_initialise(void);
     5.6  
     5.7 +#ifndef NDEBUG
     5.8 +void perform_tests(void);
     5.9 +#else
    5.10 +#define perform_tests() ((void)0)
    5.11 +#endif
    5.12 +
    5.13  #define isdigit(c) ((c) >= '0' && (c) <= '9')
    5.14  
    5.15  extern char _start[], _end[];