# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 49dcd838b7df72bfe66ab9233e360b52ceca3115
# Parent 7684f9032f9fb9521de665a277be23d52c87c2de
[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@xxxxxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
tools/firmware/Makefile | 2
tools/firmware/hvmloader/Makefile | 9 +
tools/firmware/hvmloader/acpi_madt.c | 4
tools/firmware/hvmloader/hvmloader.c | 117 +++++++++++----------
tools/firmware/hvmloader/hypercall.h | 180 +++++++++++++++++++++++++++++++++
tools/firmware/hvmloader/mp_tables.c | 3
tools/firmware/hvmloader/util.c | 96 +++++++++++++++++
tools/firmware/hvmloader/util.h | 19 +++
xen/arch/x86/hvm/hvm.c | 136 ++++++++++++++++++++----
xen/arch/x86/hvm/platform.c | 14 ++
xen/common/kernel.c | 7 +
xen/include/asm-x86/guest_access.h | 5
xen/include/asm-x86/hvm/guest_access.h | 3
xen/include/public/version.h | 3
14 files changed, 510 insertions(+), 88 deletions(-)
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/Makefile
--- a/tools/firmware/Makefile Fri Aug 04 16:07:58 2006 +0100
+++ b/tools/firmware/Makefile Fri Aug 04 20:30:12 2006 +0100
@@ -30,7 +30,7 @@ all:
.PHONY: install
install: all
[ -d $(INSTALL_DIR) ] || install -d -m0755 $(INSTALL_DIR)
- [ ! -e $(TARGET) ] || install -m0644 $(TARGET) $(INSTALL_DIR)
+ install -m0644 $(TARGET) $(INSTALL_DIR)
.PHONY: clean
clean:
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/hvmloader/Makefile
--- a/tools/firmware/hvmloader/Makefile Fri Aug 04 16:07:58 2006 +0100
+++ b/tools/firmware/hvmloader/Makefile Fri Aug 04 20:30:12 2006 +0100
@@ -42,12 +42,15 @@ CFLAGS += $(DEFINES) -I. $(XENINC) -fno
CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
+SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
.PHONY: all
all: hvmloader
-hvmloader: roms.h hvmloader.c acpi_madt.c mp_tables.c
- $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c mp_tables.c
- $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o mp_tables.o
+hvmloader: roms.h $(SRCS)
+ $(CC) $(CFLAGS) -c $(SRCS)
+ $(CC) $(LDFLAGS) -o hvmloader.tmp $(OBJS)
$(OBJCOPY) hvmloader.tmp hvmloader
rm -f hvmloader.tmp
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/hvmloader/acpi_madt.c
--- a/tools/firmware/hvmloader/acpi_madt.c Fri Aug 04 16:07:58 2006 +0100
+++ b/tools/firmware/hvmloader/acpi_madt.c Fri Aug 04 20:30:12 2006 +0100
@@ -20,12 +20,10 @@
#include "../acpi/acpi2_0.h"
#include "../acpi/acpi_madt.h"
-
+#include "util.h"
#include <xen/hvm/hvm_info_table.h>
#define NULL ((void*)0)
-
-extern int puts(const char *s);
static struct hvm_info_table *table = NULL;
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Fri Aug 04 16:07:58 2006 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c Fri Aug 04 20:30:12 2006 +0100
@@ -23,9 +23,13 @@
*/
#include "roms.h"
#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
+#include "hypercall.h"
+#include "util.h"
+#include <xen/version.h>
#include <xen/hvm/hvm_info_table.h>
/* memory map */
+#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
@@ -75,65 +79,14 @@ extern void create_mp_tables(void);
extern void create_mp_tables(void);
struct hvm_info_table *get_hvm_info_table(void);
-static inline void
-outw(unsigned short addr, unsigned short val)
-{
- __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
-}
-
-static inline void
-outb(unsigned short addr, unsigned char val)
-{
- __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
-}
-
-static inline unsigned char
-inb(unsigned short addr)
-{
- unsigned char val;
-
- __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
- return val;
-}
-
-void *
-memcpy(void *dest, const void *src, unsigned n)
-{
- int t0, t1, t2;
-
- __asm__ __volatile__(
- "cld\n"
- "rep; movsl\n"
- "testb $2,%b4\n"
- "je 1f\n"
- "movsw\n"
- "1: testb $1,%b4\n"
- "je 2f\n"
- "movsb\n"
- "2:"
- : "=&c" (t0), "=&D" (t1), "=&S" (t2)
- : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
- : "memory"
- );
- return dest;
-}
-
-int
-puts(const char *s)
-{
- while (*s)
- outb(0xE9, *s++);
- return 0;
-}
-
-int
+static int
cirrus_check(void)
{
outw(0x3C4, 0x9206);
return inb(0x3C5) == 0x12;
}
-int
+static int
vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx)
{
int eax;
@@ -147,7 +100,7 @@ vmmcall(int function, int edi, int esi,
return eax;
}
-int
+static int
check_amd(void)
{
char id[12];
@@ -162,12 +115,68 @@ check_amd(void)
return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
}
+static void
+cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+ __asm__ __volatile__(
+ "cpuid"
+ : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+ : "0" (idx) );
+}
+
+static void
+wrmsr(uint32_t idx, uint64_t v)
+{
+ __asm__ __volatile__(
+ "wrmsr"
+ : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );
+}
+
+static void
+init_hypercalls(void)
+{
+ uint32_t eax, ebx, ecx, edx;
+ unsigned long i;
+ char signature[13], number[13];
+ xen_extraversion_t extraversion;
+
+ cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
+
+ *(uint32_t *)(signature + 0) = ebx;
+ *(uint32_t *)(signature + 4) = ecx;
+ *(uint32_t *)(signature + 8) = edx;
+ signature[12] = '\0';
+
+ if (strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002)) {
+ puts("FATAL: Xen hypervisor not detected\n");
+ __asm__ __volatile__( "ud2" );
+ }
+
+ cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
+
+ puts("Detected Xen v");
+ puts(itoa(number, eax >> 16));
+ puts(".");
+ puts(itoa(number, eax & 0xffff));
+
+ cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
+
+ for (i = 0; i < eax; i++)
+ wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
+
+ hypercall_xen_version(XENVER_extraversion, extraversion);
+ puts(extraversion);
+ puts("\n");
+}
+
int
main(void)
{
struct hvm_info_table *t = get_hvm_info_table();
puts("HVM Loader\n");
+
+ init_hypercalls();
puts("Loading ROMBIOS ...\n");
memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/hvmloader/mp_tables.c
--- a/tools/firmware/hvmloader/mp_tables.c Fri Aug 04 16:07:58 2006 +0100
+++ b/tools/firmware/hvmloader/mp_tables.c Fri Aug 04 20:30:12 2006 +0100
@@ -93,7 +93,8 @@ typedef signed long int64_t;
#define INTR_MAX_NR 16
-extern int puts(const char *); /* for printing */
+#include "util.h"
+
extern int get_vcpu_nr(void); /* for the guest's VCPU count */
/*
diff -r 7684f9032f9f -r 49dcd838b7df xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Fri Aug 04 16:07:58 2006 +0100
+++ b/xen/arch/x86/hvm/hvm.c Fri Aug 04 20:30:12 2006 +0100
@@ -28,6 +28,7 @@
#include <xen/domain.h>
#include <xen/domain_page.h>
#include <xen/hypercall.h>
+#include <xen/guest_access.h>
#include <asm/current.h>
#include <asm/io.h>
#include <asm/shadow.h>
@@ -46,7 +47,8 @@
#include <public/sched.h>
#include <public/hvm/ioreq.h>
#include <public/hvm/hvm_info_table.h>
-#include <xen/guest_access.h>
+#include <public/version.h>
+#include <public/memory.h>
int hvm_enabled = 0;
@@ -305,55 +307,139 @@ void hvm_print_line(struct vcpu *v, cons
pbuf[(*index)++] = c;
}
-#if defined(__i386__)
-
typedef unsigned long hvm_hypercall_t(
unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
-#define HYPERCALL(x) [ __HYPERVISOR_ ## x ] = (hvm_hypercall_t *) do_ ## x
+
+#define HYPERCALL(x) \
+ [ __HYPERVISOR_ ## x ] = (hvm_hypercall_t *) do_ ## x
+#define HYPERCALL_COMPAT32(x) \
+ [ __HYPERVISOR_ ## x ] = (hvm_hypercall_t *) do_ ## x ## _compat32
+
+#if defined(__i386__)
+
static hvm_hypercall_t *hvm_hypercall_table[] = {
- HYPERCALL(mmu_update),
HYPERCALL(memory_op),
HYPERCALL(multicall),
- HYPERCALL(update_va_mapping),
- HYPERCALL(event_channel_op_compat),
HYPERCALL(xen_version),
- HYPERCALL(grant_table_op),
HYPERCALL(event_channel_op),
HYPERCALL(hvm_op)
};
-#undef HYPERCALL
void hvm_do_hypercall(struct cpu_user_regs *pregs)
{
- if ( ring_3(pregs) )
+ if ( unlikely(ring_3(pregs)) )
{
pregs->eax = -EPERM;
return;
}
- if ( pregs->eax > ARRAY_SIZE(hvm_hypercall_table) ||
- !hvm_hypercall_table[pregs->eax] )
+ if ( (pregs->eax >= NR_hypercalls) || !hvm_hypercall_table[pregs->eax] )
{
DPRINTK("HVM vcpu %d:%d did a bad hypercall %d.\n",
current->domain->domain_id, current->vcpu_id,
pregs->eax);
pregs->eax = -ENOSYS;
+ return;
+ }
+
+ pregs->eax = hvm_hypercall_table[pregs->eax](
+ pregs->ebx, pregs->ecx, pregs->edx, pregs->esi, pregs->edi);
+}
+
+#else /* defined(__x86_64__) */
+
+static long do_memory_op_compat32(int cmd, XEN_GUEST_HANDLE(void) arg)
+{
+ extern long do_add_to_physmap(struct xen_add_to_physmap *xatp);
+ long rc;
+
+ switch ( cmd )
+ {
+ case XENMEM_add_to_physmap:
+ {
+ struct {
+ domid_t domid;
+ uint32_t space;
+ uint32_t idx;
+ uint32_t gpfn;
+ } u;
+ struct xen_add_to_physmap h;
+
+ if ( copy_from_guest(&u, arg, 1) )
+ return -EFAULT;
+
+ h.domid = u.domid;
+ h.space = u.space;
+ h.idx = u.idx;
+ h.gpfn = u.gpfn;
+
+ this_cpu(guest_handles_in_xen_space) = 1;
+ rc = do_memory_op(cmd, guest_handle_from_ptr(&h, void));
+ this_cpu(guest_handles_in_xen_space) = 0;
+
+ break;
+ }
+
+ default:
+ DPRINTK("memory_op %d.\n", cmd);
+ rc = -ENOSYS;
+ break;
+ }
+
+ return rc;
+}
+
+static hvm_hypercall_t *hvm_hypercall64_table[NR_hypercalls] = {
+ HYPERCALL(memory_op),
+ HYPERCALL(xen_version),
+ HYPERCALL(hvm_op),
+ HYPERCALL(event_channel_op)
+};
+
+static hvm_hypercall_t *hvm_hypercall32_table[NR_hypercalls] = {
+ HYPERCALL_COMPAT32(memory_op),
+ HYPERCALL(xen_version),
+ HYPERCALL(hvm_op),
+ HYPERCALL(event_channel_op)
+};
+
+void hvm_do_hypercall(struct cpu_user_regs *pregs)
+{
+ if ( unlikely(ring_3(pregs)) )
+ {
+ pregs->rax = -EPERM;
+ return;
+ }
+
+ pregs->rax = (uint32_t)pregs->eax; /* mask in case compat32 caller */
+ if ( (pregs->rax >= NR_hypercalls) || !hvm_hypercall64_table[pregs->rax] )
+ {
+ DPRINTK("HVM vcpu %d:%d did a bad hypercall %ld.\n",
+ current->domain->domain_id, current->vcpu_id,
+ pregs->rax);
+ pregs->rax = -ENOSYS;
+ return;
+ }
+
+ if ( current->domain->arch.ops->guest_paging_levels == PAGING_L4 )
+ {
+ pregs->rax = hvm_hypercall64_table[pregs->rax](pregs->rdi,
+ pregs->rsi,
+ pregs->rdx,
+ pregs->r10,
+ pregs->r8);
}
else
{
- pregs->eax = hvm_hypercall_table[pregs->eax](
- pregs->ebx, pregs->ecx, pregs->edx, pregs->esi, pregs->edi);
- }
-}
-
-#else /* __x86_64__ */
-
-void hvm_do_hypercall(struct cpu_user_regs *pregs)
-{
- printk("not supported yet!\n");
-}
-
-#endif
+ pregs->eax = hvm_hypercall32_table[pregs->eax]((uint32_t)pregs->ebx,
+ (uint32_t)pregs->ecx,
+ (uint32_t)pregs->edx,
+ (uint32_t)pregs->esi,
+ (uint32_t)pregs->edi);
+ }
+}
+
+#endif /* defined(__x86_64__) */
/* Initialise a hypercall transfer page for a VMX domain using
paravirtualised drivers. */
diff -r 7684f9032f9f -r 49dcd838b7df xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c Fri Aug 04 16:07:58 2006 +0100
+++ b/xen/arch/x86/hvm/platform.c Fri Aug 04 20:30:12 2006 +0100
@@ -1034,17 +1034,31 @@ void handle_mmio(unsigned long va, unsig
}
}
+DEFINE_PER_CPU(int, guest_handles_in_xen_space);
+
/* Note that copy_{to,from}_user_hvm don't set the A and D bits on
PTEs, and require the PTE to be writable even when they're only
trying to read from it. The guest is expected to deal with
this. */
unsigned long copy_to_user_hvm(void *to, const void *from, unsigned len)
{
+ if ( this_cpu(guest_handles_in_xen_space) )
+ {
+ memcpy(to, from, len);
+ return 0;
+ }
+
return !hvm_copy((void *)from, (unsigned long)to, len, HVM_COPY_OUT);
}
unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len)
{
+ if ( this_cpu(guest_handles_in_xen_space) )
+ {
+ memcpy(to, from, len);
+ return 0;
+ }
+
return !hvm_copy(to, (unsigned long)from, len, HVM_COPY_IN);
}
diff -r 7684f9032f9f -r 49dcd838b7df xen/common/kernel.c
--- a/xen/common/kernel.c Fri Aug 04 16:07:58 2006 +0100
+++ b/xen/common/kernel.c Fri Aug 04 20:30:12 2006 +0100
@@ -217,6 +217,13 @@ long do_xen_version(int cmd, XEN_GUEST_H
return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
}
+ case XENVER_guest_handle:
+ {
+ if ( copy_to_guest(arg, (char *)current->domain->handle,
+ sizeof(current->domain->handle)) )
+ return -EFAULT;
+ return 0;
+ }
}
return -ENOSYS;
diff -r 7684f9032f9f -r 49dcd838b7df xen/include/asm-x86/guest_access.h
--- a/xen/include/asm-x86/guest_access.h Fri Aug 04 16:07:58 2006 +0100
+++ b/xen/include/asm-x86/guest_access.h Fri Aug 04 20:30:12 2006 +0100
@@ -20,8 +20,11 @@
/* Cast a guest handle to the specified type of handle. */
#define guest_handle_cast(hnd, type) ({ \
type *_x = (hnd).p; \
- (XEN_GUEST_HANDLE(type)) { _x }; \
+ (XEN_GUEST_HANDLE(type)) { _x }; \
})
+
+#define guest_handle_from_ptr(ptr, type) \
+ ((XEN_GUEST_HANDLE(type)) { (type *)ptr })
/*
* Copy an array of objects to guest context via a guest handle,
diff -r 7684f9032f9f -r 49dcd838b7df xen/include/asm-x86/hvm/guest_access.h
--- a/xen/include/asm-x86/hvm/guest_access.h Fri Aug 04 16:07:58 2006 +0100
+++ b/xen/include/asm-x86/hvm/guest_access.h Fri Aug 04 20:30:12 2006 +0100
@@ -1,5 +1,8 @@
#ifndef __ASM_X86_HVM_GUEST_ACCESS_H__
#define __ASM_X86_HVM_GUEST_ACCESS_H__
+
+#include <xen/percpu.h>
+DECLARE_PER_CPU(int, guest_handles_in_xen_space);
unsigned long copy_to_user_hvm(void *to, const void *from, unsigned len);
unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len);
diff -r 7684f9032f9f -r 49dcd838b7df xen/include/public/version.h
--- a/xen/include/public/version.h Fri Aug 04 16:07:58 2006 +0100
+++ b/xen/include/public/version.h Fri Aug 04 20:30:12 2006 +0100
@@ -57,6 +57,9 @@ typedef struct xen_feature_info xen_feat
/* arg == NULL; returns host memory page size. */
#define XENVER_pagesize 7
+/* arg == xen_domain_handle_t. */
+#define XENVER_guest_handle 8
+
#endif /* __XEN_PUBLIC_VERSION_H__ */
/*
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/hvmloader/hypercall.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/hvmloader/hypercall.h Fri Aug 04 20:30:12 2006 +0100
@@ -0,0 +1,180 @@
+/******************************************************************************
+ * hypercall.h
+ *
+ * Copyright (c) 2002-2006, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HVMLOADER_HYPERCALL_H__
+#define __HVMLOADER_HYPERCALL_H__
+
+/*
+ * NB. Hypercall address needs to be relative to a linkage symbol for
+ * some version of ld to relocate the relative calls properly.
+ * Keep this in sync with HYPERCALL_PHYSICAL_ADDRESS in hvmloader.c!
+ */
+#define hypercall_pa "_start - 0x80000"
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+#define _hypercall0(type, name)
\
+({ \
+ long __res; \
+ asm volatile ( \
+ "call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
+ : "=a" (__res) \
+ : \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res, __ign1; \
+ asm volatile ( \
+ "call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
+ : "=a" (__res), "=b" (__ign1) \
+ : "1" ((long)(a1)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2)
\
+({ \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ "call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
+ : "1" ((long)(a1)), "2" ((long)(a2)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4)
\
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4; \
+ asm volatile ( \
+ "call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "4" ((long)(a4)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
+ asm volatile ( \
+ "call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "4" ((long)(a4)), \
+ "5" ((long)(a5)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+static inline int
+hypercall_sched_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
+static inline int
+hypercall_memory_op(
+ unsigned int cmd, void *arg)
+{
+ return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int
+hypercall_multicall(
+ void *call_list, int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+static inline int
+hypercall_event_channel_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, event_channel_op, cmd, arg);
+}
+
+static inline int
+hypercall_xen_version(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+hypercall_console_io(
+ int cmd, int count, char *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int
+hypercall_vm_assist(
+ unsigned int cmd, unsigned int type)
+{
+ return _hypercall2(int, vm_assist, cmd, type);
+}
+
+static inline int
+hypercall_vcpu_op(
+ int cmd, int vcpuid, void *extra_args)
+{
+ return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+}
+
+static inline int
+hypercall_hvm_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, hvm_op, cmd, arg);
+}
+
+#endif /* __HVMLOADER_HYPERCALL_H__ */
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/hvmloader/util.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/hvmloader/util.c Fri Aug 04 20:30:12 2006 +0100
@@ -0,0 +1,96 @@
+/*
+ * util.c: Helper library functions for HVMLoader.
+ *
+ * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
+ * Copyright (c) 2005, International Business Machines Corporation.
+ *
+ * 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 "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
+#include "util.h"
+
+void outw(uint16_t addr, uint16_t val)
+{
+ __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
+}
+
+void outb(uint16_t addr, uint8_t val)
+{
+ __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
+}
+
+uint8_t inb(uint16_t addr)
+{
+ uint8_t val;
+ __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
+ return val;
+}
+
+char *itoa(char *a, unsigned int i)
+{
+ unsigned int _i = i, x = 0;
+
+ do {
+ x++;
+ _i /= 10;
+ } while (_i != 0);
+
+ a += x;
+ *a-- = '\0';
+
+ do {
+ *a-- = (i % 10) + '0';
+ i /= 10;
+ } while (i != 0);
+
+ return a + 1;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+ signed char res;
+
+ while (((res = *cs - *ct++) == 0) && (*cs++ != '\0'))
+ continue;
+
+ return res;
+}
+
+void *memcpy(void *dest, const void *src, unsigned n)
+{
+ int t0, t1, t2;
+
+ __asm__ __volatile__(
+ "cld\n"
+ "rep; movsl\n"
+ "testb $2,%b4\n"
+ "je 1f\n"
+ "movsw\n"
+ "1: testb $1,%b4\n"
+ "je 2f\n"
+ "movsb\n"
+ "2:"
+ : "=&c" (t0), "=&D" (t1), "=&S" (t2)
+ : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
+ : "memory"
+ );
+ return dest;
+}
+
+void puts(const char *s)
+{
+ while (*s)
+ outb(0xE9, *s++);
+}
diff -r 7684f9032f9f -r 49dcd838b7df tools/firmware/hvmloader/util.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/hvmloader/util.h Fri Aug 04 20:30:12 2006 +0100
@@ -0,0 +1,19 @@
+#ifndef __HVMLOADER_UTIL_H__
+#define __HVMLOADER_UTIL_H__
+
+/* I/O output */
+void outw(uint16_t addr, uint16_t val);
+void outb(uint16_t addr, uint8_t val);
+
+/* I/O input */
+uint8_t inb(uint16_t addr);
+
+/* String and memory functions */
+int strcmp(const char *cs, const char *ct);
+void *memcpy(void *dest, const void *src, unsigned n);
+char *itoa(char *a, unsigned int i);
+
+/* Debug output */
+void puts(const char *s);
+
+#endif /* __HVMLOADER_UTIL_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|