[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [HVMLOADER] HVM loader initialises hypercall shim and uses



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.