WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [RFC][PATCH] Hypercalls from HVM guests (2/2)

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [RFC][PATCH] Hypercalls from HVM guests (2/2)
From: Steve Ofsthun <sofsthun@xxxxxxxxxxxxxxx>
Date: Wed, 12 Apr 2006 14:40:27 -0400
Delivery-date: Wed, 12 Apr 2006 11:42:10 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla Thunderbird 1.0.6 (X11/20050715)
A sample test module for the HVM hypercall interface.

Signed-off-by: Steve Ofsthun <sofsthun@xxxxxxxxxxxxxxx>

1) To use, put these files in a directory by themselves.
2) Edit the Makefile:
   Set XEN_ROOT to a populated xen tree.
   Set LINUX_ROOT to a linux build tree for your HVM domU kernel.
3) make

The output should be test.ko.  You should be able to load this
module on an HVM guest using:

# insmod test.ko

Module output on the console should appear like:

hypercall_page @ ffffffffa020f000
xen_features[0].writable_page_tables = 1
xen_features[0].writable_descriptor_tables = 0
xen_features[0].auto_translated_physmap = 1
xen_features[0].supervisor_mode_kernel = 0
xen_features[0].pae_pgdir_above_4gb = 1

Enjoy,
Steve
--
Steve Ofsthun - Virtual Iron Software, Inc.
# Makefile for test driver

#EXTRA_CFLAGS += -DDEBUG

obj-m := test.o

test-objs := features.o hypercall.o

# Point XEN_ROOT at a valid xen tree

ifeq ($(XEN_ROOT),)
XEN_ROOT = ~/BK/xen-unstable-test64/
endif

# Point LINUX_ROOT at a valid linux tree

ifeq ($(LINUX_ROOT),)
LINUX_ROOT = $(XEN_ROOT)/linux-2.6.16-xen/
endif

LOCAL_DRIVER_LIST = .
LOCAL_DRIVER_DIRS := $(foreach dir,$(LOCAL_DRIVER_LIST),$(shell pwd)/$(dir))

default:
        @if [ ! -d $(XEN_ROOT) ]; then \
                echo XEN_ROOT must be set; exit 1; \
        fi
        @if [ ! -d $(LINUX_ROOT) ]; then \
                echo LINUX_ROOT must be set; exit 1; \
        fi
        $(MAKE) -C $(LINUX_ROOT) SUBDIRS="$(LOCAL_DRIVER_DIRS)" modules

clean:
        $(MAKE) -C $(LINUX_ROOT) SUBDIRS="$(LOCAL_DRIVER_DIRS)" $@
/******************************************************************************
 * features.c
 *
 * Xen feature flags.
 *
 * Copyright (c) 2006, Ian Campbell, XenSource Inc.
 */
#include <linux/types.h>
#include <linux/cache.h>
#include <linux/module.h>
#include <asm/hypervisor.h>
#include <xen/features.h>

#ifndef __read_mostly
#define __read_mostly __cacheline_aligned
#endif

//#define DEBUG

u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
EXPORT_SYMBOL(xen_features);

#ifdef DEBUG
static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
    [XENFEAT_writable_page_tables]       = "writable_page_tables",
    [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
    [XENFEAT_auto_translated_physmap]    = "auto_translated_physmap",
    [XENFEAT_supervisor_mode_kernel]     = "supervisor_mode_kernel",
    [XENFEAT_pae_pgdir_above_4gb]        = "pae_pgdir_above_4gb"
};
#endif

void setup_xen_features(void)
{
        xen_feature_info_t fi;
        int i, j;

        for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
                fi.submap_idx = i;
                if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
                        break;
                for (j=0; j<32; j++)
                        xen_features[i*32+j] = !!(fi.submap & 1<<j);
        }
#ifdef DEBUG
        for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
                for (j=0; j<32; j++) {
                        if (feature_names[j])
                                printk("xen_features[%d].%s = %d\n", i,
                                        feature_names[j], xen_features[i*32+j]);
                }
        }
#endif
}
EXPORT_SYMBOL(setup_xen_features);
/******************************************************************************
 * hypercall.c
 *
 * Copyright (C) 2006, Virtual Iron Software, Inc.
 *
 * 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 <linux/module.h>

MODULE_LICENSE("GPL");

#include "hypercall.h"

char hypercall_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));

static inline int
HYPERVISOR_arg_test(long a, long b, long c, long d, long e)
{
        return _hypercall5(int, grant_table_op, a, b, c, d, e);
}

extern void setup_xen_features(void);

static int __init hypercall_page_setup(void)
{
    hypercall_page_init(&hypercall_page);
    printk(KERN_ERR "hypercall_page @ %p\n", &hypercall_page);
#if BITS_PER_LONG == 64
    HYPERVISOR_arg_test(0x1111111111111111, 0x2222222222222222,
        0x3333333333333333, 0x4444444444444444, 0x5555555555555555);
#else
    HYPERVISOR_arg_test(0x11111111, 0x22222222,
        0x33333333, 0x44444444, 0x55555555);
#endif
    setup_xen_features();
    return 0;
}

static void __exit hypercall_page_cleanup(void)
{
}

module_init(hypercall_page_setup);
module_exit(hypercall_page_cleanup);
/******************************************************************************
 * hypercall.h
 *
 * Copyright (C) 2006, Virtual Iron Software, Inc.
 *
 * 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 <linux/version.h>
#include <asm/hypervisor.h>
#include <xen/interface/xen.h>

static inline int
check_amd(void)
{
        char id[12];

        __asm__ __volatile__(
                "cpuid"
                : "=b" (*(int *)(&id[0])),
                  "=c" (*(int *)(&id[8])),
                  "=d" (*(int *)(&id[4]))
                : "a" (0)
        );
        return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
}

#define VMCALL_INSTR    0x0f,0x01,0xc1
#define VMMCALL_INSTR   0x0f,0x01,0xd6

#define NR_hypercalls (PAGE_SIZE/32)

static inline void hypercall_page_init(void *hypercall_page)
{
    int i;
    char *p;
    char vmcall[3] = { VMCALL_INSTR };
    char vmmcall[3] = { VMMCALL_INSTR };
    int amd = check_amd();

    for ( i = 0; i < NR_hypercalls; i++ )
    {
        p = (char *)(hypercall_page + (i * 32));
        /*
         * This call sequence works for 32-bit and 64-bit guests.
         */
        memset(p, 0xcc, 32);
        *(u8  *)(p+ 0) = 0xb8;          /* mov $<i>,%eax */
        *(u32 *)(p+ 1) = i;
        if (amd) {
            *(u8  *)(p+ 5) = vmmcall[0];
            *(u8  *)(p+ 6) = vmmcall[1];
            *(u8  *)(p+ 7) = vmmcall[2];
        } else {
            *(u8  *)(p+ 5) = vmcall[0];
            *(u8  *)(p+ 6) = vmcall[1];
            *(u8  *)(p+ 7) = vmcall[2];
        }
        *(u8  *)(p+ 8) = 0xc3;          /* ret */
    }
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>