direct-io.hg

changeset 10948:49dcd838b7df

[HVMLOADER] HVM loader initialises hypercall shim and uses
it to interrogate Xen version information. Also add support
for HVM hypercall execution on 64-bit host.

Signed-off-by: Steven Smith <ssmith@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Aug 04 20:30:12 2006 +0100 (2006-08-04)
parents 7684f9032f9f
children ffa5b2975dff
files tools/firmware/Makefile tools/firmware/hvmloader/Makefile tools/firmware/hvmloader/acpi_madt.c tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/hypercall.h tools/firmware/hvmloader/mp_tables.c tools/firmware/hvmloader/util.c tools/firmware/hvmloader/util.h xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/platform.c xen/common/kernel.c xen/include/asm-x86/guest_access.h xen/include/asm-x86/hvm/guest_access.h xen/include/public/version.h
line diff
     1.1 --- a/tools/firmware/Makefile	Fri Aug 04 16:07:58 2006 +0100
     1.2 +++ b/tools/firmware/Makefile	Fri Aug 04 20:30:12 2006 +0100
     1.3 @@ -30,7 +30,7 @@ all:
     1.4  .PHONY: install
     1.5  install: all
     1.6  	[ -d $(INSTALL_DIR) ] || install -d -m0755 $(INSTALL_DIR)
     1.7 -	[ ! -e $(TARGET) ] || install -m0644 $(TARGET) $(INSTALL_DIR)
     1.8 +	install -m0644 $(TARGET) $(INSTALL_DIR)
     1.9  
    1.10  .PHONY: clean
    1.11  clean: 
     2.1 --- a/tools/firmware/hvmloader/Makefile	Fri Aug 04 16:07:58 2006 +0100
     2.2 +++ b/tools/firmware/hvmloader/Makefile	Fri Aug 04 20:30:12 2006 +0100
     2.3 @@ -42,12 +42,15 @@ OBJCOPY  = objcopy
     2.4  CFLAGS  += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
     2.5  LDFLAGS  = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
     2.6  
     2.7 +SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c
     2.8 +OBJS = $(patsubst %.c,%.o,$(SRCS))
     2.9 +
    2.10  .PHONY: all
    2.11  all: hvmloader
    2.12  
    2.13 -hvmloader: roms.h hvmloader.c acpi_madt.c mp_tables.c
    2.14 -	$(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c mp_tables.c
    2.15 -	$(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o mp_tables.o
    2.16 +hvmloader: roms.h $(SRCS)
    2.17 +	$(CC) $(CFLAGS) -c $(SRCS)
    2.18 +	$(CC) $(LDFLAGS) -o hvmloader.tmp $(OBJS)
    2.19  	$(OBJCOPY) hvmloader.tmp hvmloader
    2.20  	rm -f hvmloader.tmp
    2.21  
     3.1 --- a/tools/firmware/hvmloader/acpi_madt.c	Fri Aug 04 16:07:58 2006 +0100
     3.2 +++ b/tools/firmware/hvmloader/acpi_madt.c	Fri Aug 04 20:30:12 2006 +0100
     3.3 @@ -20,13 +20,11 @@
     3.4  
     3.5  #include "../acpi/acpi2_0.h"
     3.6  #include "../acpi/acpi_madt.h"
     3.7 -
     3.8 +#include "util.h"
     3.9  #include <xen/hvm/hvm_info_table.h>
    3.10  
    3.11  #define NULL ((void*)0)
    3.12  
    3.13 -extern int puts(const char *s);
    3.14 -
    3.15  static struct hvm_info_table *table = NULL;
    3.16  
    3.17  static int validate_hvm_info(struct hvm_info_table *t)
     4.1 --- a/tools/firmware/hvmloader/hvmloader.c	Fri Aug 04 16:07:58 2006 +0100
     4.2 +++ b/tools/firmware/hvmloader/hvmloader.c	Fri Aug 04 20:30:12 2006 +0100
     4.3 @@ -23,9 +23,13 @@
     4.4   */
     4.5  #include "roms.h"
     4.6  #include "../acpi/acpi2_0.h"  /* for ACPI_PHYSICAL_ADDRESS */
     4.7 +#include "hypercall.h"
     4.8 +#include "util.h"
     4.9 +#include <xen/version.h>
    4.10  #include <xen/hvm/hvm_info_table.h>
    4.11  
    4.12  /* memory map */
    4.13 +#define HYPERCALL_PHYSICAL_ADDRESS	0x00080000
    4.14  #define VGABIOS_PHYSICAL_ADDRESS	0x000C0000
    4.15  #define	VMXASSIST_PHYSICAL_ADDRESS	0x000D0000
    4.16  #define	ROMBIOS_PHYSICAL_ADDRESS	0x000F0000
    4.17 @@ -75,65 +79,14 @@ extern int acpi_madt_update(unsigned cha
    4.18  extern void create_mp_tables(void);
    4.19  struct hvm_info_table *get_hvm_info_table(void);
    4.20  
    4.21 -static inline void
    4.22 -outw(unsigned short addr, unsigned short val)
    4.23 -{
    4.24 -        __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
    4.25 -}
    4.26 -
    4.27 -static inline void
    4.28 -outb(unsigned short addr, unsigned char val)
    4.29 -{
    4.30 -        __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
    4.31 -}
    4.32 -
    4.33 -static inline unsigned char
    4.34 -inb(unsigned short addr)
    4.35 -{
    4.36 -        unsigned char val;
    4.37 -
    4.38 -        __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
    4.39 -        return val;
    4.40 -}
    4.41 -
    4.42 -void *
    4.43 -memcpy(void *dest, const void *src, unsigned n)
    4.44 -{
    4.45 -	int t0, t1, t2;
    4.46 -
    4.47 -	__asm__ __volatile__(
    4.48 -		"cld\n"
    4.49 -		"rep; movsl\n"
    4.50 -		"testb $2,%b4\n"
    4.51 -		"je 1f\n"
    4.52 -		"movsw\n"
    4.53 -		"1: testb $1,%b4\n"
    4.54 -		"je 2f\n"
    4.55 -		"movsb\n"
    4.56 -		"2:"
    4.57 -		: "=&c" (t0), "=&D" (t1), "=&S" (t2)
    4.58 -		: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
    4.59 -		: "memory"
    4.60 -	);
    4.61 -	return dest;
    4.62 -}
    4.63 -
    4.64 -int
    4.65 -puts(const char *s)
    4.66 -{
    4.67 -	while (*s)
    4.68 -		outb(0xE9, *s++);
    4.69 -	return 0;
    4.70 -}
    4.71 -
    4.72 -int
    4.73 +static int
    4.74  cirrus_check(void)
    4.75  {
    4.76  	outw(0x3C4, 0x9206);
    4.77  	return inb(0x3C5) == 0x12;
    4.78  }
    4.79  
    4.80 -int
    4.81 +static int
    4.82  vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx)
    4.83  {
    4.84          int eax;
    4.85 @@ -147,7 +100,7 @@ vmmcall(int function, int edi, int esi, 
    4.86          return eax;
    4.87  }
    4.88  
    4.89 -int
    4.90 +static int
    4.91  check_amd(void)
    4.92  {
    4.93  	char id[12];
    4.94 @@ -162,6 +115,60 @@ check_amd(void)
    4.95  	return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
    4.96  }
    4.97  
    4.98 +static void
    4.99 +cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
   4.100 +{
   4.101 +	__asm__ __volatile__(
   4.102 +		"cpuid"
   4.103 +		: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
   4.104 +		: "0" (idx) );
   4.105 +}
   4.106 +
   4.107 +static void
   4.108 +wrmsr(uint32_t idx, uint64_t v)
   4.109 +{
   4.110 +	__asm__ __volatile__(
   4.111 +		"wrmsr"
   4.112 +		: : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );
   4.113 +}
   4.114 +
   4.115 +static void
   4.116 +init_hypercalls(void)
   4.117 +{
   4.118 +	uint32_t eax, ebx, ecx, edx;
   4.119 +	unsigned long i;
   4.120 +	char signature[13], number[13];
   4.121 +	xen_extraversion_t extraversion;
   4.122 +
   4.123 +	cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
   4.124 +
   4.125 +	*(uint32_t *)(signature + 0) = ebx;
   4.126 +	*(uint32_t *)(signature + 4) = ecx;
   4.127 +	*(uint32_t *)(signature + 8) = edx;
   4.128 +	signature[12] = '\0';
   4.129 +
   4.130 +	if (strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002)) {
   4.131 +		puts("FATAL: Xen hypervisor not detected\n");
   4.132 +		__asm__ __volatile__( "ud2" );
   4.133 +	}
   4.134 +
   4.135 +	cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
   4.136 +
   4.137 +	puts("Detected Xen v");
   4.138 +	puts(itoa(number, eax >> 16));
   4.139 +	puts(".");
   4.140 +	puts(itoa(number, eax & 0xffff));
   4.141 +
   4.142 +	cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
   4.143 +
   4.144 +	for (i = 0; i < eax; i++)
   4.145 +		wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
   4.146 +
   4.147 +	hypercall_xen_version(XENVER_extraversion, extraversion);
   4.148 +	puts(extraversion);
   4.149 +	puts("\n");
   4.150 +}
   4.151 +
   4.152  int
   4.153  main(void)
   4.154  {
   4.155 @@ -169,6 +176,8 @@ main(void)
   4.156  
   4.157  	puts("HVM Loader\n");
   4.158  
   4.159 +	init_hypercalls();
   4.160 +
   4.161  	puts("Loading ROMBIOS ...\n");
   4.162  	memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
   4.163  	if (t->apic_enabled)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/firmware/hvmloader/hypercall.h	Fri Aug 04 20:30:12 2006 +0100
     5.3 @@ -0,0 +1,180 @@
     5.4 +/******************************************************************************
     5.5 + * hypercall.h
     5.6 + * 
     5.7 + * Copyright (c) 2002-2006, K A Fraser
     5.8 + * 
     5.9 + * This program is free software; you can redistribute it and/or
    5.10 + * modify it under the terms of the GNU General Public License version 2
    5.11 + * as published by the Free Software Foundation; or, when distributed
    5.12 + * separately from the Linux kernel or incorporated into other
    5.13 + * software packages, subject to the following license:
    5.14 + * 
    5.15 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    5.16 + * of this source file (the "Software"), to deal in the Software without
    5.17 + * restriction, including without limitation the rights to use, copy, modify,
    5.18 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    5.19 + * and to permit persons to whom the Software is furnished to do so, subject to
    5.20 + * the following conditions:
    5.21 + * 
    5.22 + * The above copyright notice and this permission notice shall be included in
    5.23 + * all copies or substantial portions of the Software.
    5.24 + * 
    5.25 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    5.26 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    5.27 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    5.28 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    5.29 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    5.30 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    5.31 + * IN THE SOFTWARE.
    5.32 + */
    5.33 +
    5.34 +#ifndef __HVMLOADER_HYPERCALL_H__
    5.35 +#define __HVMLOADER_HYPERCALL_H__
    5.36 +
    5.37 +/*
    5.38 + * NB. Hypercall address needs to be relative to a linkage symbol for
    5.39 + * some version of ld to relocate the relative calls properly.
    5.40 + * Keep this in sync with HYPERCALL_PHYSICAL_ADDRESS in hvmloader.c!
    5.41 + */
    5.42 +#define hypercall_pa "_start - 0x80000"
    5.43 +
    5.44 +#define __STR(x) #x
    5.45 +#define STR(x) __STR(x)
    5.46 +
    5.47 +#define _hypercall0(type, name)						\
    5.48 +({									\
    5.49 +	long __res;							\
    5.50 +	asm volatile (							\
    5.51 +		"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32)	\
    5.52 +		: "=a" (__res)						\
    5.53 +		:							\
    5.54 +		: "memory" );						\
    5.55 +	(type)__res;							\
    5.56 +})
    5.57 +
    5.58 +#define _hypercall1(type, name, a1)					\
    5.59 +({									\
    5.60 +	long __res, __ign1;						\
    5.61 +	asm volatile (							\
    5.62 +		"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32)	\
    5.63 +		: "=a" (__res), "=b" (__ign1)				\
    5.64 +		: "1" ((long)(a1))					\
    5.65 +		: "memory" );						\
    5.66 +	(type)__res;							\
    5.67 +})
    5.68 +
    5.69 +#define _hypercall2(type, name, a1, a2)					\
    5.70 +({									\
    5.71 +	long __res, __ign1, __ign2;					\
    5.72 +	asm volatile (							\
    5.73 +		"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32)	\
    5.74 +		: "=a" (__res), "=b" (__ign1), "=c" (__ign2)		\
    5.75 +		: "1" ((long)(a1)), "2" ((long)(a2))			\
    5.76 +		: "memory" );						\
    5.77 +	(type)__res;							\
    5.78 +})
    5.79 +
    5.80 +#define _hypercall3(type, name, a1, a2, a3)				\
    5.81 +({									\
    5.82 +	long __res, __ign1, __ign2, __ign3;				\
    5.83 +	asm volatile (							\
    5.84 +		"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32)	\
    5.85 +		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
    5.86 +		"=d" (__ign3)						\
    5.87 +		: "1" ((long)(a1)), "2" ((long)(a2)),			\
    5.88 +		"3" ((long)(a3))					\
    5.89 +		: "memory" );						\
    5.90 +	(type)__res;							\
    5.91 +})
    5.92 +
    5.93 +#define _hypercall4(type, name, a1, a2, a3, a4)				\
    5.94 +({									\
    5.95 +	long __res, __ign1, __ign2, __ign3, __ign4;			\
    5.96 +	asm volatile (							\
    5.97 +		"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32)	\
    5.98 +		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
    5.99 +		"=d" (__ign3), "=S" (__ign4)				\
   5.100 +		: "1" ((long)(a1)), "2" ((long)(a2)),			\
   5.101 +		"3" ((long)(a3)), "4" ((long)(a4))			\
   5.102 +		: "memory" );						\
   5.103 +	(type)__res;							\
   5.104 +})
   5.105 +
   5.106 +#define _hypercall5(type, name, a1, a2, a3, a4, a5)			\
   5.107 +({									\
   5.108 +	long __res, __ign1, __ign2, __ign3, __ign4, __ign5;		\
   5.109 +	asm volatile (							\
   5.110 +		"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32)	\
   5.111 +		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
   5.112 +		"=d" (__ign3), "=S" (__ign4), "=D" (__ign5)		\
   5.113 +		: "1" ((long)(a1)), "2" ((long)(a2)),			\
   5.114 +		"3" ((long)(a3)), "4" ((long)(a4)),			\
   5.115 +		"5" ((long)(a5))					\
   5.116 +		: "memory" );						\
   5.117 +	(type)__res;							\
   5.118 +})
   5.119 +
   5.120 +static inline int
   5.121 +hypercall_sched_op(
   5.122 +	int cmd, void *arg)
   5.123 +{
   5.124 +	return _hypercall2(int, sched_op, cmd, arg);
   5.125 +}
   5.126 +
   5.127 +static inline int
   5.128 +hypercall_memory_op(
   5.129 +	unsigned int cmd, void *arg)
   5.130 +{
   5.131 +	return _hypercall2(int, memory_op, cmd, arg);
   5.132 +}
   5.133 +
   5.134 +static inline int
   5.135 +hypercall_multicall(
   5.136 +	void *call_list, int nr_calls)
   5.137 +{
   5.138 +	return _hypercall2(int, multicall, call_list, nr_calls);
   5.139 +}
   5.140 +
   5.141 +static inline int
   5.142 +hypercall_event_channel_op(
   5.143 +	int cmd, void *arg)
   5.144 +{
   5.145 +	return _hypercall2(int, event_channel_op, cmd, arg);
   5.146 +}
   5.147 +
   5.148 +static inline int
   5.149 +hypercall_xen_version(
   5.150 +	int cmd, void *arg)
   5.151 +{
   5.152 +	return _hypercall2(int, xen_version, cmd, arg);
   5.153 +}
   5.154 +
   5.155 +static inline int
   5.156 +hypercall_console_io(
   5.157 +	int cmd, int count, char *str)
   5.158 +{
   5.159 +	return _hypercall3(int, console_io, cmd, count, str);
   5.160 +}
   5.161 +
   5.162 +static inline int
   5.163 +hypercall_vm_assist(
   5.164 +	unsigned int cmd, unsigned int type)
   5.165 +{
   5.166 +	return _hypercall2(int, vm_assist, cmd, type);
   5.167 +}
   5.168 +
   5.169 +static inline int
   5.170 +hypercall_vcpu_op(
   5.171 +	int cmd, int vcpuid, void *extra_args)
   5.172 +{
   5.173 +	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
   5.174 +}
   5.175 +
   5.176 +static inline int
   5.177 +hypercall_hvm_op(
   5.178 +	int cmd, void *arg)
   5.179 +{
   5.180 +	return _hypercall2(int, hvm_op, cmd, arg);
   5.181 +}
   5.182 +
   5.183 +#endif /* __HVMLOADER_HYPERCALL_H__ */
     6.1 --- a/tools/firmware/hvmloader/mp_tables.c	Fri Aug 04 16:07:58 2006 +0100
     6.2 +++ b/tools/firmware/hvmloader/mp_tables.c	Fri Aug 04 20:30:12 2006 +0100
     6.3 @@ -93,7 +93,8 @@ typedef   signed long int64_t;
     6.4  
     6.5  #define INTR_MAX_NR            16
     6.6  
     6.7 -extern int puts(const char *); /* for printing */
     6.8 +#include "util.h"
     6.9 +
    6.10  extern int get_vcpu_nr(void);  /* for the guest's VCPU count */
    6.11  
    6.12  /*
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/firmware/hvmloader/util.c	Fri Aug 04 20:30:12 2006 +0100
     7.3 @@ -0,0 +1,96 @@
     7.4 +/*
     7.5 + * util.c: Helper library functions for HVMLoader.
     7.6 + *
     7.7 + * Leendert van Doorn, leendert@watson.ibm.com
     7.8 + * Copyright (c) 2005, International Business Machines Corporation.
     7.9 + *
    7.10 + * This program is free software; you can redistribute it and/or modify it
    7.11 + * under the terms and conditions of the GNU General Public License,
    7.12 + * version 2, as published by the Free Software Foundation.
    7.13 + *
    7.14 + * This program is distributed in the hope it will be useful, but WITHOUT
    7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    7.17 + * more details.
    7.18 + *
    7.19 + * You should have received a copy of the GNU General Public License along with
    7.20 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    7.21 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    7.22 + */
    7.23 +
    7.24 +#include "../acpi/acpi2_0.h"  /* for ACPI_PHYSICAL_ADDRESS */
    7.25 +#include "util.h"
    7.26 +
    7.27 +void outw(uint16_t addr, uint16_t val)
    7.28 +{
    7.29 +	__asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
    7.30 +}
    7.31 +
    7.32 +void outb(uint16_t addr, uint8_t val)
    7.33 +{
    7.34 +	__asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
    7.35 +}
    7.36 +
    7.37 +uint8_t inb(uint16_t addr)
    7.38 +{
    7.39 +	uint8_t val;
    7.40 +	__asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
    7.41 +	return val;
    7.42 +}
    7.43 +
    7.44 +char *itoa(char *a, unsigned int i)
    7.45 +{
    7.46 +	unsigned int _i = i, x = 0;
    7.47 +
    7.48 +	do {
    7.49 +		x++;
    7.50 +		_i /= 10;
    7.51 +	} while (_i != 0);
    7.52 +
    7.53 +	a += x;
    7.54 +	*a-- = '\0';
    7.55 +
    7.56 +	do {
    7.57 +		*a-- = (i % 10) + '0';
    7.58 +		i /= 10;
    7.59 +	} while (i != 0);
    7.60 +
    7.61 +	return a + 1;
    7.62 +}
    7.63 +
    7.64 +int strcmp(const char *cs, const char *ct)
    7.65 +{
    7.66 +	signed char res;
    7.67 +
    7.68 +	while (((res = *cs - *ct++) == 0) && (*cs++ != '\0'))
    7.69 +		continue;
    7.70 +
    7.71 +	return res;
    7.72 +}
    7.73 +
    7.74 +void *memcpy(void *dest, const void *src, unsigned n)
    7.75 +{
    7.76 +	int t0, t1, t2;
    7.77 +
    7.78 +	__asm__ __volatile__(
    7.79 +		"cld\n"
    7.80 +		"rep; movsl\n"
    7.81 +		"testb $2,%b4\n"
    7.82 +		"je 1f\n"
    7.83 +		"movsw\n"
    7.84 +		"1: testb $1,%b4\n"
    7.85 +		"je 2f\n"
    7.86 +		"movsb\n"
    7.87 +		"2:"
    7.88 +		: "=&c" (t0), "=&D" (t1), "=&S" (t2)
    7.89 +		: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
    7.90 +		: "memory"
    7.91 +	);
    7.92 +	return dest;
    7.93 +}
    7.94 +
    7.95 +void puts(const char *s)
    7.96 +{
    7.97 +	while (*s)
    7.98 +		outb(0xE9, *s++);
    7.99 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/firmware/hvmloader/util.h	Fri Aug 04 20:30:12 2006 +0100
     8.3 @@ -0,0 +1,19 @@
     8.4 +#ifndef __HVMLOADER_UTIL_H__
     8.5 +#define __HVMLOADER_UTIL_H__
     8.6 +
     8.7 +/* I/O output */
     8.8 +void outw(uint16_t addr, uint16_t val);
     8.9 +void outb(uint16_t addr, uint8_t val);
    8.10 +
    8.11 +/* I/O input */
    8.12 +uint8_t inb(uint16_t addr);
    8.13 +
    8.14 +/* String and memory functions */
    8.15 +int strcmp(const char *cs, const char *ct);
    8.16 +void *memcpy(void *dest, const void *src, unsigned n);
    8.17 +char *itoa(char *a, unsigned int i);
    8.18 +
    8.19 +/* Debug output */
    8.20 +void puts(const char *s);
    8.21 +
    8.22 +#endif /* __HVMLOADER_UTIL_H__ */
     9.1 --- a/xen/arch/x86/hvm/hvm.c	Fri Aug 04 16:07:58 2006 +0100
     9.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Aug 04 20:30:12 2006 +0100
     9.3 @@ -28,6 +28,7 @@
     9.4  #include <xen/domain.h>
     9.5  #include <xen/domain_page.h>
     9.6  #include <xen/hypercall.h>
     9.7 +#include <xen/guest_access.h>
     9.8  #include <asm/current.h>
     9.9  #include <asm/io.h>
    9.10  #include <asm/shadow.h>
    9.11 @@ -46,7 +47,8 @@
    9.12  #include <public/sched.h>
    9.13  #include <public/hvm/ioreq.h>
    9.14  #include <public/hvm/hvm_info_table.h>
    9.15 -#include <xen/guest_access.h>
    9.16 +#include <public/version.h>
    9.17 +#include <public/memory.h>
    9.18  
    9.19  int hvm_enabled = 0;
    9.20  
    9.21 @@ -305,55 +307,139 @@ void hvm_print_line(struct vcpu *v, cons
    9.22  	pbuf[(*index)++] = c;
    9.23  }
    9.24  
    9.25 -#if defined(__i386__)
    9.26 -
    9.27  typedef unsigned long hvm_hypercall_t(
    9.28      unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
    9.29 -#define HYPERCALL(x) [ __HYPERVISOR_ ## x ] = (hvm_hypercall_t *) do_ ## x
    9.30 +
    9.31 +#define HYPERCALL(x)                                        \
    9.32 +    [ __HYPERVISOR_ ## x ] = (hvm_hypercall_t *) do_ ## x
    9.33 +#define HYPERCALL_COMPAT32(x)                               \
    9.34 +    [ __HYPERVISOR_ ## x ] = (hvm_hypercall_t *) do_ ## x ## _compat32
    9.35 +
    9.36 +#if defined(__i386__)
    9.37 +
    9.38  static hvm_hypercall_t *hvm_hypercall_table[] = {
    9.39 -    HYPERCALL(mmu_update),
    9.40      HYPERCALL(memory_op),
    9.41      HYPERCALL(multicall),
    9.42 -    HYPERCALL(update_va_mapping),
    9.43 -    HYPERCALL(event_channel_op_compat),
    9.44      HYPERCALL(xen_version),
    9.45 -    HYPERCALL(grant_table_op),
    9.46      HYPERCALL(event_channel_op),
    9.47      HYPERCALL(hvm_op)
    9.48  };
    9.49 -#undef HYPERCALL
    9.50  
    9.51  void hvm_do_hypercall(struct cpu_user_regs *pregs)
    9.52  {
    9.53 -    if ( ring_3(pregs) )
    9.54 +    if ( unlikely(ring_3(pregs)) )
    9.55      {
    9.56          pregs->eax = -EPERM;
    9.57          return;
    9.58      }
    9.59  
    9.60 -    if ( pregs->eax > ARRAY_SIZE(hvm_hypercall_table) ||
    9.61 -         !hvm_hypercall_table[pregs->eax] )
    9.62 +    if ( (pregs->eax >= NR_hypercalls) || !hvm_hypercall_table[pregs->eax] )
    9.63      {
    9.64          DPRINTK("HVM vcpu %d:%d did a bad hypercall %d.\n",
    9.65                  current->domain->domain_id, current->vcpu_id,
    9.66                  pregs->eax);
    9.67          pregs->eax = -ENOSYS;
    9.68 +        return;
    9.69 +    }
    9.70 +
    9.71 +    pregs->eax = hvm_hypercall_table[pregs->eax](
    9.72 +        pregs->ebx, pregs->ecx, pregs->edx, pregs->esi, pregs->edi);
    9.73 +}
    9.74 +
    9.75 +#else /* defined(__x86_64__) */
    9.76 +
    9.77 +static long do_memory_op_compat32(int cmd, XEN_GUEST_HANDLE(void) arg)
    9.78 +{
    9.79 +    extern long do_add_to_physmap(struct xen_add_to_physmap *xatp);
    9.80 +    long rc;
    9.81 +
    9.82 +    switch ( cmd )
    9.83 +    {
    9.84 +    case XENMEM_add_to_physmap:
    9.85 +    {
    9.86 +        struct {
    9.87 +            domid_t domid;
    9.88 +            uint32_t space;
    9.89 +            uint32_t idx;
    9.90 +            uint32_t gpfn;
    9.91 +        } u;
    9.92 +        struct xen_add_to_physmap h;
    9.93 +
    9.94 +        if ( copy_from_guest(&u, arg, 1) )
    9.95 +            return -EFAULT;
    9.96 +
    9.97 +        h.domid = u.domid;
    9.98 +        h.space = u.space;
    9.99 +        h.idx = u.idx;
   9.100 +        h.gpfn = u.gpfn;
   9.101 +
   9.102 +        this_cpu(guest_handles_in_xen_space) = 1;
   9.103 +        rc = do_memory_op(cmd, guest_handle_from_ptr(&h, void));
   9.104 +        this_cpu(guest_handles_in_xen_space) = 0;
   9.105 +
   9.106 +        break;
   9.107 +    }
   9.108 +
   9.109 +    default:
   9.110 +        DPRINTK("memory_op %d.\n", cmd);
   9.111 +        rc = -ENOSYS;
   9.112 +        break;
   9.113 +    }
   9.114 +
   9.115 +    return rc;
   9.116 +}
   9.117 +
   9.118 +static hvm_hypercall_t *hvm_hypercall64_table[NR_hypercalls] = {
   9.119 +    HYPERCALL(memory_op),
   9.120 +    HYPERCALL(xen_version),
   9.121 +    HYPERCALL(hvm_op),
   9.122 +    HYPERCALL(event_channel_op)
   9.123 +};
   9.124 +
   9.125 +static hvm_hypercall_t *hvm_hypercall32_table[NR_hypercalls] = {
   9.126 +    HYPERCALL_COMPAT32(memory_op),
   9.127 +    HYPERCALL(xen_version),
   9.128 +    HYPERCALL(hvm_op),
   9.129 +    HYPERCALL(event_channel_op)
   9.130 +};
   9.131 +
   9.132 +void hvm_do_hypercall(struct cpu_user_regs *pregs)
   9.133 +{
   9.134 +    if ( unlikely(ring_3(pregs)) )
   9.135 +    {
   9.136 +        pregs->rax = -EPERM;
   9.137 +        return;
   9.138 +    }
   9.139 +
   9.140 +    pregs->rax = (uint32_t)pregs->eax; /* mask in case compat32 caller */
   9.141 +    if ( (pregs->rax >= NR_hypercalls) || !hvm_hypercall64_table[pregs->rax] )
   9.142 +    {
   9.143 +        DPRINTK("HVM vcpu %d:%d did a bad hypercall %ld.\n",
   9.144 +                current->domain->domain_id, current->vcpu_id,
   9.145 +                pregs->rax);
   9.146 +        pregs->rax = -ENOSYS;
   9.147 +        return;
   9.148 +    }
   9.149 +
   9.150 +    if ( current->domain->arch.ops->guest_paging_levels == PAGING_L4 )
   9.151 +    {
   9.152 +        pregs->rax = hvm_hypercall64_table[pregs->rax](pregs->rdi,
   9.153 +                                                       pregs->rsi,
   9.154 +                                                       pregs->rdx,
   9.155 +                                                       pregs->r10,
   9.156 +                                                       pregs->r8);
   9.157      }
   9.158      else
   9.159      {
   9.160 -        pregs->eax = hvm_hypercall_table[pregs->eax](
   9.161 -            pregs->ebx, pregs->ecx, pregs->edx, pregs->esi, pregs->edi);
   9.162 +        pregs->eax = hvm_hypercall32_table[pregs->eax]((uint32_t)pregs->ebx,
   9.163 +                                                       (uint32_t)pregs->ecx,
   9.164 +                                                       (uint32_t)pregs->edx,
   9.165 +                                                       (uint32_t)pregs->esi,
   9.166 +                                                       (uint32_t)pregs->edi);
   9.167      }
   9.168  }
   9.169  
   9.170 -#else /* __x86_64__ */
   9.171 -
   9.172 -void hvm_do_hypercall(struct cpu_user_regs *pregs)
   9.173 -{
   9.174 -    printk("not supported yet!\n");
   9.175 -}
   9.176 -
   9.177 -#endif
   9.178 +#endif /* defined(__x86_64__) */
   9.179  
   9.180  /* Initialise a hypercall transfer page for a VMX domain using
   9.181     paravirtualised drivers. */
    10.1 --- a/xen/arch/x86/hvm/platform.c	Fri Aug 04 16:07:58 2006 +0100
    10.2 +++ b/xen/arch/x86/hvm/platform.c	Fri Aug 04 20:30:12 2006 +0100
    10.3 @@ -1034,17 +1034,31 @@ void handle_mmio(unsigned long va, unsig
    10.4      }
    10.5  }
    10.6  
    10.7 +DEFINE_PER_CPU(int, guest_handles_in_xen_space);
    10.8 +
    10.9  /* Note that copy_{to,from}_user_hvm don't set the A and D bits on
   10.10     PTEs, and require the PTE to be writable even when they're only
   10.11     trying to read from it.  The guest is expected to deal with
   10.12     this. */
   10.13  unsigned long copy_to_user_hvm(void *to, const void *from, unsigned len)
   10.14  {
   10.15 +    if ( this_cpu(guest_handles_in_xen_space) )
   10.16 +    {
   10.17 +        memcpy(to, from, len);
   10.18 +        return 0;
   10.19 +    }
   10.20 +
   10.21      return !hvm_copy((void *)from, (unsigned long)to, len, HVM_COPY_OUT);
   10.22  }
   10.23  
   10.24  unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len)
   10.25  {
   10.26 +    if ( this_cpu(guest_handles_in_xen_space) )
   10.27 +    {
   10.28 +        memcpy(to, from, len);
   10.29 +        return 0;
   10.30 +    }
   10.31 +
   10.32      return !hvm_copy(to, (unsigned long)from, len, HVM_COPY_IN);
   10.33  }
   10.34  
    11.1 --- a/xen/common/kernel.c	Fri Aug 04 16:07:58 2006 +0100
    11.2 +++ b/xen/common/kernel.c	Fri Aug 04 20:30:12 2006 +0100
    11.3 @@ -217,6 +217,13 @@ long do_xen_version(int cmd, XEN_GUEST_H
    11.4          return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
    11.5      }
    11.6  
    11.7 +    case XENVER_guest_handle:
    11.8 +    {
    11.9 +        if ( copy_to_guest(arg, (char *)current->domain->handle,
   11.10 +                           sizeof(current->domain->handle)) )
   11.11 +            return -EFAULT;
   11.12 +        return 0;
   11.13 +    }    
   11.14      }
   11.15  
   11.16      return -ENOSYS;
    12.1 --- a/xen/include/asm-x86/guest_access.h	Fri Aug 04 16:07:58 2006 +0100
    12.2 +++ b/xen/include/asm-x86/guest_access.h	Fri Aug 04 20:30:12 2006 +0100
    12.3 @@ -20,9 +20,12 @@
    12.4  /* Cast a guest handle to the specified type of handle. */
    12.5  #define guest_handle_cast(hnd, type) ({         \
    12.6      type *_x = (hnd).p;                         \
    12.7 -    (XEN_GUEST_HANDLE(type)) { _x };                \
    12.8 +    (XEN_GUEST_HANDLE(type)) { _x };            \
    12.9  })
   12.10  
   12.11 +#define guest_handle_from_ptr(ptr, type)        \
   12.12 +    ((XEN_GUEST_HANDLE(type)) { (type *)ptr })
   12.13 +
   12.14  /*
   12.15   * Copy an array of objects to guest context via a guest handle,
   12.16   * specifying an offset into the guest array.
    13.1 --- a/xen/include/asm-x86/hvm/guest_access.h	Fri Aug 04 16:07:58 2006 +0100
    13.2 +++ b/xen/include/asm-x86/hvm/guest_access.h	Fri Aug 04 20:30:12 2006 +0100
    13.3 @@ -1,6 +1,9 @@
    13.4  #ifndef __ASM_X86_HVM_GUEST_ACCESS_H__
    13.5  #define __ASM_X86_HVM_GUEST_ACCESS_H__
    13.6  
    13.7 +#include <xen/percpu.h>
    13.8 +DECLARE_PER_CPU(int, guest_handles_in_xen_space);
    13.9 +
   13.10  unsigned long copy_to_user_hvm(void *to, const void *from, unsigned len);
   13.11  unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len);
   13.12  
    14.1 --- a/xen/include/public/version.h	Fri Aug 04 16:07:58 2006 +0100
    14.2 +++ b/xen/include/public/version.h	Fri Aug 04 20:30:12 2006 +0100
    14.3 @@ -57,6 +57,9 @@ typedef struct xen_feature_info xen_feat
    14.4  /* arg == NULL; returns host memory page size. */
    14.5  #define XENVER_pagesize 7
    14.6  
    14.7 +/* arg == xen_domain_handle_t. */
    14.8 +#define XENVER_guest_handle 8
    14.9 +
   14.10  #endif /* __XEN_PUBLIC_VERSION_H__ */
   14.11  
   14.12  /*