diff options
author | 2017-04-25 03:31:15 -0700 | |
---|---|---|
committer | 2017-05-22 06:48:08 +0000 | |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/ipxe/src/arch/x86/drivers | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/arch/x86/drivers')
-rw-r--r-- | qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c | 597 | ||||
-rw-r--r-- | qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h | 57 | ||||
-rw-r--r-- | qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c | 503 | ||||
-rw-r--r-- | qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h | 75 |
4 files changed, 0 insertions, 1232 deletions
diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c b/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c deleted file mode 100644 index f73829bd5..000000000 --- a/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Hyper-V driver - * - */ - -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> -#include <assert.h> -#include <errno.h> -#include <byteswap.h> -#include <pic8259.h> -#include <ipxe/malloc.h> -#include <ipxe/device.h> -#include <ipxe/cpuid.h> -#include <ipxe/msr.h> -#include <ipxe/hyperv.h> -#include <ipxe/vmbus.h> -#include "hyperv.h" - -/** Maximum time to wait for a message response - * - * This is a policy decision. - */ -#define HV_MESSAGE_MAX_WAIT_MS 1000 - -/** - * Convert a Hyper-V status code to an iPXE status code - * - * @v status Hyper-V status code - * @ret rc iPXE status code (before negation) - */ -#define EHV( status ) EPLATFORM ( EINFO_EPLATFORM, (status) ) - -/** - * Allocate zeroed pages - * - * @v hv Hyper-V hypervisor - * @v ... Page addresses to fill in, terminated by NULL - * @ret rc Return status code - */ -__attribute__ (( sentinel )) int -hv_alloc_pages ( struct hv_hypervisor *hv, ... ) { - va_list args; - void **page; - int i; - - /* Allocate and zero pages */ - va_start ( args, hv ); - for ( i = 0 ; ( ( page = va_arg ( args, void ** ) ) != NULL ); i++ ) { - *page = malloc_dma ( PAGE_SIZE, PAGE_SIZE ); - if ( ! *page ) - goto err_alloc; - memset ( *page, 0, PAGE_SIZE ); - } - va_end ( args ); - - return 0; - - err_alloc: - va_end ( args ); - va_start ( args, hv ); - for ( ; i >= 0 ; i-- ) { - page = va_arg ( args, void ** ); - free_dma ( *page, PAGE_SIZE ); - } - va_end ( args ); - return -ENOMEM; -} - -/** - * Free pages - * - * @v hv Hyper-V hypervisor - * @v ... Page addresses, terminated by NULL - */ -__attribute__ (( sentinel )) void -hv_free_pages ( struct hv_hypervisor *hv, ... ) { - va_list args; - void *page; - - va_start ( args, hv ); - while ( ( page = va_arg ( args, void * ) ) != NULL ) - free_dma ( page, PAGE_SIZE ); - va_end ( args ); -} - -/** - * Allocate message buffer - * - * @v hv Hyper-V hypervisor - * @ret rc Return status code - */ -static int hv_alloc_message ( struct hv_hypervisor *hv ) { - - /* Allocate buffer. Must be aligned to at least 8 bytes and - * must not cross a page boundary, so align on its own size. - */ - hv->message = malloc_dma ( sizeof ( *hv->message ), - sizeof ( *hv->message ) ); - if ( ! hv->message ) - return -ENOMEM; - - return 0; -} - -/** - * Free message buffer - * - * @v hv Hyper-V hypervisor - */ -static void hv_free_message ( struct hv_hypervisor *hv ) { - - /* Free buffer */ - free_dma ( hv->message, sizeof ( *hv->message ) ); -} - -/** - * Check whether or not we are running in Hyper-V - * - * @v hv Hyper-V hypervisor - * @ret rc Return status code - */ -static int hv_check_hv ( struct hv_hypervisor *hv ) { - struct x86_features features; - uint32_t interface_id; - uint32_t discard_ebx; - uint32_t discard_ecx; - uint32_t discard_edx; - uint32_t available; - uint32_t permissions; - - /* Check for presence of a hypervisor (not necessarily Hyper-V) */ - x86_features ( &features ); - if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_HYPERVISOR ) ) { - DBGC ( hv, "HV %p not running in a hypervisor\n", hv ); - return -ENODEV; - } - - /* Check that hypervisor is Hyper-V */ - cpuid ( HV_CPUID_INTERFACE_ID, &interface_id, &discard_ebx, - &discard_ecx, &discard_edx ); - if ( interface_id != HV_INTERFACE_ID ) { - DBGC ( hv, "HV %p not running in Hyper-V (interface ID " - "%#08x)\n", hv, interface_id ); - return -ENODEV; - } - - /* Check that required features and privileges are available */ - cpuid ( HV_CPUID_FEATURES, &available, &permissions, &discard_ecx, - &discard_edx ); - if ( ! ( available & HV_FEATURES_AVAIL_HYPERCALL_MSR ) ) { - DBGC ( hv, "HV %p has no hypercall MSRs (features %08x:%08x)\n", - hv, available, permissions ); - return -ENODEV; - } - if ( ! ( available & HV_FEATURES_AVAIL_SYNIC_MSR ) ) { - DBGC ( hv, "HV %p has no SynIC MSRs (features %08x:%08x)\n", - hv, available, permissions ); - return -ENODEV; - } - if ( ! ( permissions & HV_FEATURES_PERM_POST_MESSAGES ) ) { - DBGC ( hv, "HV %p cannot post messages (features %08x:%08x)\n", - hv, available, permissions ); - return -EACCES; - } - if ( ! ( permissions & HV_FEATURES_PERM_SIGNAL_EVENTS ) ) { - DBGC ( hv, "HV %p cannot signal events (features %08x:%08x)", - hv, available, permissions ); - return -EACCES; - } - - return 0; -} - -/** - * Map hypercall page - * - * @v hv Hyper-V hypervisor - * @ret rc Return status code - */ -static int hv_map_hypercall ( struct hv_hypervisor *hv ) { - union { - struct { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - } __attribute__ (( packed )); - char text[ 13 /* "bbbbccccdddd" + NUL */ ]; - } vendor_id; - uint32_t build; - uint32_t version; - uint32_t discard_eax; - uint32_t discard_ecx; - uint32_t discard_edx; - uint64_t guest_os_id; - uint64_t hypercall; - - /* Report guest OS identity */ - guest_os_id = rdmsr ( HV_X64_MSR_GUEST_OS_ID ); - if ( guest_os_id != 0 ) { - DBGC ( hv, "HV %p guest OS ID MSR already set to %#08llx\n", - hv, guest_os_id ); - return -EBUSY; - } - guest_os_id = HV_GUEST_OS_ID_IPXE; - DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id ); - wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id ); - - /* Get hypervisor system identity (for debugging) */ - cpuid ( HV_CPUID_VENDOR_ID, &discard_eax, &vendor_id.ebx, - &vendor_id.ecx, &vendor_id.edx ); - vendor_id.text[ sizeof ( vendor_id.text ) - 1 ] = '\0'; - cpuid ( HV_CPUID_HYPERVISOR_ID, &build, &version, &discard_ecx, - &discard_edx ); - DBGC ( hv, "HV %p detected \"%s\" version %d.%d build %d\n", hv, - vendor_id.text, ( version >> 16 ), ( version & 0xffff ), build ); - - /* Map hypercall page */ - hypercall = rdmsr ( HV_X64_MSR_HYPERCALL ); - hypercall &= ( PAGE_SIZE - 1 ); - hypercall |= ( virt_to_phys ( hv->hypercall ) | HV_HYPERCALL_ENABLE ); - DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall ); - wrmsr ( HV_X64_MSR_HYPERCALL, hypercall ); - - return 0; -} - -/** - * Unmap hypercall page - * - * @v hv Hyper-V hypervisor - */ -static void hv_unmap_hypercall ( struct hv_hypervisor *hv ) { - uint64_t hypercall; - uint64_t guest_os_id; - - /* Unmap the hypercall page */ - hypercall = rdmsr ( HV_X64_MSR_HYPERCALL ); - hypercall &= ( ( PAGE_SIZE - 1 ) & ~HV_HYPERCALL_ENABLE ); - DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall ); - wrmsr ( HV_X64_MSR_HYPERCALL, hypercall ); - - /* Reset the guest OS identity */ - guest_os_id = 0; - DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id ); - wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id ); -} - -/** - * Map synthetic interrupt controller - * - * @v hv Hyper-V hypervisor - * @ret rc Return status code - */ -static int hv_map_synic ( struct hv_hypervisor *hv ) { - uint64_t simp; - uint64_t siefp; - uint64_t scontrol; - - /* Map SynIC message page */ - simp = rdmsr ( HV_X64_MSR_SIMP ); - simp &= ( PAGE_SIZE - 1 ); - simp |= ( virt_to_phys ( hv->synic.message ) | HV_SIMP_ENABLE ); - DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp ); - wrmsr ( HV_X64_MSR_SIMP, simp ); - - /* Map SynIC event page */ - siefp = rdmsr ( HV_X64_MSR_SIEFP ); - siefp &= ( PAGE_SIZE - 1 ); - siefp |= ( virt_to_phys ( hv->synic.event ) | HV_SIEFP_ENABLE ); - DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp ); - wrmsr ( HV_X64_MSR_SIEFP, siefp ); - - /* Enable SynIC */ - scontrol = rdmsr ( HV_X64_MSR_SCONTROL ); - scontrol |= HV_SCONTROL_ENABLE; - DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol ); - wrmsr ( HV_X64_MSR_SCONTROL, scontrol ); - - return 0; -} - -/** - * Unmap synthetic interrupt controller - * - * @v hv Hyper-V hypervisor - */ -static void hv_unmap_synic ( struct hv_hypervisor *hv ) { - uint64_t scontrol; - uint64_t siefp; - uint64_t simp; - - /* Disable SynIC */ - scontrol = rdmsr ( HV_X64_MSR_SCONTROL ); - scontrol &= ~HV_SCONTROL_ENABLE; - DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol ); - wrmsr ( HV_X64_MSR_SCONTROL, scontrol ); - - /* Unmap SynIC event page */ - siefp = rdmsr ( HV_X64_MSR_SIEFP ); - siefp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIEFP_ENABLE ); - DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp ); - wrmsr ( HV_X64_MSR_SIEFP, siefp ); - - /* Unmap SynIC message page */ - simp = rdmsr ( HV_X64_MSR_SIMP ); - simp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIMP_ENABLE ); - DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp ); - wrmsr ( HV_X64_MSR_SIMP, simp ); -} - -/** - * Enable synthetic interrupt - * - * @v hv Hyper-V hypervisor - * @v sintx Synthetic interrupt number - */ -void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) { - unsigned long msr = HV_X64_MSR_SINT ( sintx ); - uint64_t sint; - - /* Enable synthetic interrupt - * - * We have to enable the interrupt, otherwise messages will - * not be delivered (even though the documentation implies - * that polling for messages is possible). We enable AutoEOI - * and hook the interrupt to the obsolete IRQ13 (FPU - * exception) vector, which will be implemented as a no-op. - */ - sint = rdmsr ( msr ); - sint &= ~( HV_SINT_MASKED | HV_SINT_VECTOR_MASK ); - sint |= ( HV_SINT_AUTO_EOI | - HV_SINT_VECTOR ( IRQ_INT ( 13 /* See comment above */ ) ) ); - DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint ); - wrmsr ( msr, sint ); -} - -/** - * Disable synthetic interrupt - * - * @v hv Hyper-V hypervisor - * @v sintx Synthetic interrupt number - */ -void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) { - unsigned long msr = HV_X64_MSR_SINT ( sintx ); - uint64_t sint; - - /* Disable synthetic interrupt */ - sint = rdmsr ( msr ); - sint &= ~HV_SINT_AUTO_EOI; - sint |= HV_SINT_MASKED; - DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint ); - wrmsr ( msr, sint ); -} - -/** - * Post message - * - * @v hv Hyper-V hypervisor - * @v id Connection ID - * @v type Message type - * @v data Message - * @v len Length of message - * @ret rc Return status code - */ -int hv_post_message ( struct hv_hypervisor *hv, unsigned int id, - unsigned int type, const void *data, size_t len ) { - struct hv_post_message *msg = &hv->message->posted; - int status; - int rc; - - /* Sanity check */ - assert ( len <= sizeof ( msg->data ) ); - - /* Construct message */ - memset ( msg, 0, sizeof ( *msg ) ); - msg->id = cpu_to_le32 ( id ); - msg->type = cpu_to_le32 ( type ); - msg->len = cpu_to_le32 ( len ); - memcpy ( msg->data, data, len ); - DBGC2 ( hv, "HV %p connection %d posting message type %#08x:\n", - hv, id, type ); - DBGC2_HDA ( hv, 0, msg->data, len ); - - /* Post message */ - if ( ( status = hv_call ( hv, HV_POST_MESSAGE, msg, NULL ) ) != 0 ) { - rc = -EHV ( status ); - DBGC ( hv, "HV %p could not post message to %#08x: %s\n", - hv, id, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Wait for received message - * - * @v hv Hyper-V hypervisor - * @v sintx Synthetic interrupt number - * @ret rc Return status code - */ -int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx ) { - struct hv_message *msg = &hv->message->received; - struct hv_message *src = &hv->synic.message[sintx]; - unsigned int retries; - size_t len; - - /* Wait for message to arrive */ - for ( retries = 0 ; retries < HV_MESSAGE_MAX_WAIT_MS ; retries++ ) { - - /* Check for message */ - if ( src->type ) { - - /* Copy message */ - memset ( msg, 0, sizeof ( *msg ) ); - len = src->len; - assert ( len <= sizeof ( *msg ) ); - memcpy ( msg, src, - ( offsetof ( typeof ( *msg ), data ) + len ) ); - DBGC2 ( hv, "HV %p SINT%d received message type " - "%#08x:\n", hv, sintx, - le32_to_cpu ( msg->type ) ); - DBGC2_HDA ( hv, 0, msg->data, len ); - - /* Consume message */ - src->type = 0; - - return 0; - } - - /* Trigger message delivery */ - wrmsr ( HV_X64_MSR_EOM, 0 ); - - /* Delay */ - mdelay ( 1 ); - } - - DBGC ( hv, "HV %p SINT%d timed out waiting for message\n", - hv, sintx ); - return -ETIMEDOUT; -} - -/** - * Signal event - * - * @v hv Hyper-V hypervisor - * @v id Connection ID - * @v flag Flag number - * @ret rc Return status code - */ -int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id, - unsigned int flag ) { - struct hv_signal_event *event = &hv->message->signalled; - int status; - int rc; - - /* Construct event */ - memset ( event, 0, sizeof ( *event ) ); - event->id = cpu_to_le32 ( id ); - event->flag = cpu_to_le16 ( flag ); - - /* Signal event */ - if ( ( status = hv_call ( hv, HV_SIGNAL_EVENT, event, NULL ) ) != 0 ) { - rc = -EHV ( status ); - DBGC ( hv, "HV %p could not signal event to %#08x: %s\n", - hv, id, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Probe root device - * - * @v rootdev Root device - * @ret rc Return status code - */ -static int hv_probe ( struct root_device *rootdev ) { - struct hv_hypervisor *hv; - int rc; - - /* Allocate and initialise structure */ - hv = zalloc ( sizeof ( *hv ) ); - if ( ! hv ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* Check we are running in Hyper-V */ - if ( ( rc = hv_check_hv ( hv ) ) != 0 ) - goto err_check_hv; - - /* Allocate pages */ - if ( ( rc = hv_alloc_pages ( hv, &hv->hypercall, &hv->synic.message, - &hv->synic.event, NULL ) ) != 0 ) - goto err_alloc_pages; - - /* Allocate message buffer */ - if ( ( rc = hv_alloc_message ( hv ) ) != 0 ) - goto err_alloc_message; - - /* Map hypercall page */ - if ( ( rc = hv_map_hypercall ( hv ) ) != 0 ) - goto err_map_hypercall; - - /* Map synthetic interrupt controller */ - if ( ( rc = hv_map_synic ( hv ) ) != 0 ) - goto err_map_synic; - - /* Probe Hyper-V devices */ - if ( ( rc = vmbus_probe ( hv, &rootdev->dev ) ) != 0 ) - goto err_vmbus_probe; - - rootdev_set_drvdata ( rootdev, hv ); - return 0; - - vmbus_remove ( hv, &rootdev->dev ); - err_vmbus_probe: - hv_unmap_synic ( hv ); - err_map_synic: - hv_unmap_hypercall ( hv ); - err_map_hypercall: - hv_free_message ( hv ); - err_alloc_message: - hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event, - NULL ); - err_alloc_pages: - err_check_hv: - free ( hv ); - err_alloc: - return rc; -} - -/** - * Remove root device - * - * @v rootdev Root device - */ -static void hv_remove ( struct root_device *rootdev ) { - struct hv_hypervisor *hv = rootdev_get_drvdata ( rootdev ); - - vmbus_remove ( hv, &rootdev->dev ); - hv_unmap_synic ( hv ); - hv_unmap_hypercall ( hv ); - hv_free_message ( hv ); - hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event, - NULL ); - free ( hv ); -} - -/** Hyper-V root device driver */ -static struct root_driver hv_root_driver = { - .probe = hv_probe, - .remove = hv_remove, -}; - -/** Hyper-V root device */ -struct root_device hv_root_device __root_device = { - .dev = { .name = "Hyper-V" }, - .driver = &hv_root_driver, -}; - -/* Drag in objects via hv_root_device */ -REQUIRING_SYMBOL ( hv_root_device ); - -/* Drag in netvsc driver */ -REQUIRE_OBJECT ( netvsc ); diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h b/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h deleted file mode 100644 index 0d09beb44..000000000 --- a/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _HYPERV_H -#define _HYPERV_H - -/** @file - * - * Hyper-V driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** Get vendor identification */ -#define HV_CPUID_VENDOR_ID 0x40000000UL - -/** Get interface identification */ -#define HV_CPUID_INTERFACE_ID 0x40000001UL - -/** Get hypervisor identification */ -#define HV_CPUID_HYPERVISOR_ID 0x40000002UL - -/** Get hypervisor features */ -#define HV_CPUID_FEATURES 0x40000003UL - -/** SynIC MSRs are available */ -#define HV_FEATURES_AVAIL_SYNIC_MSR 0x00000004UL - -/** Hypercall MSRs are available */ -#define HV_FEATURES_AVAIL_HYPERCALL_MSR 0x00000020UL - -/** Guest may post messages */ -#define HV_FEATURES_PERM_POST_MESSAGES 0x00000010UL - -/** Guest may signal events */ -#define HV_FEATURES_PERM_SIGNAL_EVENTS 0x00000020UL - -/** Guest OS identity MSR */ -#define HV_X64_MSR_GUEST_OS_ID 0x40000000UL - -/** Hypercall page MSR */ -#define HV_X64_MSR_HYPERCALL 0x40000001UL - -/** SynIC control MSR */ -#define HV_X64_MSR_SCONTROL 0x40000080UL - -/** SynIC event flags page MSR */ -#define HV_X64_MSR_SIEFP 0x40000082UL - -/** SynIC message page MSR */ -#define HV_X64_MSR_SIMP 0x40000083UL - -/** SynIC end of message MSR */ -#define HV_X64_MSR_EOM 0x40000084UL - -/** SynIC interrupt source MSRs */ -#define HV_X64_MSR_SINT(x) ( 0x40000090UL + (x) ) - -#endif /* _HYPERV_H */ diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c b/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c deleted file mode 100644 index 7ac32d54c..000000000 --- a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <stdio.h> -#include <errno.h> -#include <ipxe/malloc.h> -#include <ipxe/pci.h> -#include <ipxe/cpuid.h> -#include <ipxe/msr.h> -#include <ipxe/xen.h> -#include <ipxe/xenver.h> -#include <ipxe/xenmem.h> -#include <ipxe/xenstore.h> -#include <ipxe/xenbus.h> -#include <ipxe/xengrant.h> -#include "hvm.h" - -/** @file - * - * Xen HVM driver - * - */ - -/** - * Get CPUID base - * - * @v hvm HVM device - * @ret rc Return status code - */ -static int hvm_cpuid_base ( struct hvm_device *hvm ) { - struct { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - } __attribute__ (( packed )) signature; - uint32_t base; - uint32_t version; - uint32_t discard_eax; - uint32_t discard_ebx; - uint32_t discard_ecx; - uint32_t discard_edx; - - /* Scan for magic signature */ - for ( base = HVM_CPUID_MIN ; base <= HVM_CPUID_MAX ; - base += HVM_CPUID_STEP ) { - cpuid ( base, &discard_eax, &signature.ebx, &signature.ecx, - &signature.edx ); - if ( memcmp ( &signature, HVM_CPUID_MAGIC, - sizeof ( signature ) ) == 0 ) { - hvm->cpuid_base = base; - cpuid ( ( base + HVM_CPUID_VERSION ), &version, - &discard_ebx, &discard_ecx, &discard_edx ); - DBGC2 ( hvm, "HVM using CPUID base %#08x (v%d.%d)\n", - base, ( version >> 16 ), ( version & 0xffff ) ); - return 0; - } - } - - DBGC ( hvm, "HVM could not find hypervisor\n" ); - return -ENODEV; -} - -/** - * Map hypercall page(s) - * - * @v hvm HVM device - * @ret rc Return status code - */ -static int hvm_map_hypercall ( struct hvm_device *hvm ) { - uint32_t pages; - uint32_t msr; - uint32_t discard_ecx; - uint32_t discard_edx; - physaddr_t hypercall_phys; - uint32_t version; - static xen_extraversion_t extraversion; - int xenrc; - int rc; - - /* Get number of hypercall pages and MSR to use */ - cpuid ( ( hvm->cpuid_base + HVM_CPUID_PAGES ), &pages, &msr, - &discard_ecx, &discard_edx ); - - /* Allocate pages */ - hvm->hypercall_len = ( pages * PAGE_SIZE ); - hvm->xen.hypercall = malloc_dma ( hvm->hypercall_len, PAGE_SIZE ); - if ( ! hvm->xen.hypercall ) { - DBGC ( hvm, "HVM could not allocate %d hypercall page(s)\n", - pages ); - return -ENOMEM; - } - hypercall_phys = virt_to_phys ( hvm->xen.hypercall ); - DBGC2 ( hvm, "HVM hypercall page(s) at [%#08lx,%#08lx) via MSR %#08x\n", - hypercall_phys, ( hypercall_phys + hvm->hypercall_len ), msr ); - - /* Write to MSR */ - wrmsr ( msr, hypercall_phys ); - - /* Check that hypercall mechanism is working */ - version = xenver_version ( &hvm->xen ); - if ( ( xenrc = xenver_extraversion ( &hvm->xen, &extraversion ) ) != 0){ - rc = -EXEN ( xenrc ); - DBGC ( hvm, "HVM could not get extraversion: %s\n", - strerror ( rc ) ); - return rc; - } - DBGC2 ( hvm, "HVM found Xen version %d.%d%s\n", - ( version >> 16 ), ( version & 0xffff ) , extraversion ); - - return 0; -} - -/** - * Unmap hypercall page(s) - * - * @v hvm HVM device - */ -static void hvm_unmap_hypercall ( struct hvm_device *hvm ) { - - /* Free pages */ - free_dma ( hvm->xen.hypercall, hvm->hypercall_len ); -} - -/** - * Allocate and map MMIO space - * - * @v hvm HVM device - * @v space Source mapping space - * @v len Length (must be a multiple of PAGE_SIZE) - * @ret mmio MMIO space address, or NULL on error - */ -static void * hvm_ioremap ( struct hvm_device *hvm, unsigned int space, - size_t len ) { - struct xen_add_to_physmap add; - struct xen_remove_from_physmap remove; - unsigned int pages = ( len / PAGE_SIZE ); - physaddr_t mmio_phys; - unsigned int i; - void *mmio; - int xenrc; - int rc; - - /* Sanity check */ - assert ( ( len % PAGE_SIZE ) == 0 ); - - /* Check for available space */ - if ( ( hvm->mmio_offset + len ) > hvm->mmio_len ) { - DBGC ( hvm, "HVM could not allocate %zd bytes of MMIO space " - "(%zd of %zd remaining)\n", len, - ( hvm->mmio_len - hvm->mmio_offset ), hvm->mmio_len ); - goto err_no_space; - } - - /* Map this space */ - mmio = ioremap ( ( hvm->mmio + hvm->mmio_offset ), len ); - if ( ! mmio ) { - DBGC ( hvm, "HVM could not map MMIO space [%08lx,%08lx)\n", - ( hvm->mmio + hvm->mmio_offset ), - ( hvm->mmio + hvm->mmio_offset + len ) ); - goto err_ioremap; - } - mmio_phys = virt_to_phys ( mmio ); - - /* Add to physical address space */ - for ( i = 0 ; i < pages ; i++ ) { - add.domid = DOMID_SELF; - add.idx = i; - add.space = space; - add.gpfn = ( ( mmio_phys / PAGE_SIZE ) + i ); - if ( ( xenrc = xenmem_add_to_physmap ( &hvm->xen, &add ) ) !=0){ - rc = -EXEN ( xenrc ); - DBGC ( hvm, "HVM could not add space %d idx %d at " - "[%08lx,%08lx): %s\n", space, i, - ( mmio_phys + ( i * PAGE_SIZE ) ), - ( mmio_phys + ( ( i + 1 ) * PAGE_SIZE ) ), - strerror ( rc ) ); - goto err_add_to_physmap; - } - } - - /* Update offset */ - hvm->mmio_offset += len; - - return mmio; - - i = pages; - err_add_to_physmap: - for ( i-- ; ( signed int ) i >= 0 ; i-- ) { - remove.domid = DOMID_SELF; - add.gpfn = ( ( mmio_phys / PAGE_SIZE ) + i ); - xenmem_remove_from_physmap ( &hvm->xen, &remove ); - } - iounmap ( mmio ); - err_ioremap: - err_no_space: - return NULL; -} - -/** - * Unmap MMIO space - * - * @v hvm HVM device - * @v mmio MMIO space address - * @v len Length (must be a multiple of PAGE_SIZE) - */ -static void hvm_iounmap ( struct hvm_device *hvm, void *mmio, size_t len ) { - struct xen_remove_from_physmap remove; - physaddr_t mmio_phys = virt_to_phys ( mmio ); - unsigned int pages = ( len / PAGE_SIZE ); - unsigned int i; - int xenrc; - int rc; - - /* Unmap this space */ - iounmap ( mmio ); - - /* Remove from physical address space */ - for ( i = 0 ; i < pages ; i++ ) { - remove.domid = DOMID_SELF; - remove.gpfn = ( ( mmio_phys / PAGE_SIZE ) + i ); - if ( ( xenrc = xenmem_remove_from_physmap ( &hvm->xen, - &remove ) ) != 0 ) { - rc = -EXEN ( xenrc ); - DBGC ( hvm, "HVM could not remove space [%08lx,%08lx): " - "%s\n", ( mmio_phys + ( i * PAGE_SIZE ) ), - ( mmio_phys + ( ( i + 1 ) * PAGE_SIZE ) ), - strerror ( rc ) ); - /* Nothing we can do about this */ - } - } -} - -/** - * Map shared info page - * - * @v hvm HVM device - * @ret rc Return status code - */ -static int hvm_map_shared_info ( struct hvm_device *hvm ) { - physaddr_t shared_info_phys; - int rc; - - /* Map shared info page */ - hvm->xen.shared = hvm_ioremap ( hvm, XENMAPSPACE_shared_info, - PAGE_SIZE ); - if ( ! hvm->xen.shared ) { - rc = -ENOMEM; - goto err_alloc; - } - shared_info_phys = virt_to_phys ( hvm->xen.shared ); - DBGC2 ( hvm, "HVM shared info page at [%#08lx,%#08lx)\n", - shared_info_phys, ( shared_info_phys + PAGE_SIZE ) ); - - /* Sanity check */ - DBGC2 ( hvm, "HVM wallclock time is %d\n", - readl ( &hvm->xen.shared->wc_sec ) ); - - return 0; - - hvm_iounmap ( hvm, hvm->xen.shared, PAGE_SIZE ); - err_alloc: - return rc; -} - -/** - * Unmap shared info page - * - * @v hvm HVM device - */ -static void hvm_unmap_shared_info ( struct hvm_device *hvm ) { - - /* Unmap shared info page */ - hvm_iounmap ( hvm, hvm->xen.shared, PAGE_SIZE ); -} - -/** - * Map grant table - * - * @v hvm HVM device - * @ret rc Return status code - */ -static int hvm_map_grant ( struct hvm_device *hvm ) { - physaddr_t grant_phys; - int rc; - - /* Initialise grant table */ - if ( ( rc = xengrant_init ( &hvm->xen ) ) != 0 ) { - DBGC ( hvm, "HVM could not initialise grant table: %s\n", - strerror ( rc ) ); - return rc; - } - - /* Map grant table */ - hvm->xen.grant.table = hvm_ioremap ( hvm, XENMAPSPACE_grant_table, - hvm->xen.grant.len ); - if ( ! hvm->xen.grant.table ) - return -ENODEV; - - grant_phys = virt_to_phys ( hvm->xen.grant.table ); - DBGC2 ( hvm, "HVM mapped grant table at [%08lx,%08lx)\n", - grant_phys, ( grant_phys + hvm->xen.grant.len ) ); - return 0; -} - -/** - * Unmap grant table - * - * @v hvm HVM device - */ -static void hvm_unmap_grant ( struct hvm_device *hvm ) { - - /* Unmap grant table */ - hvm_iounmap ( hvm, hvm->xen.grant.table, hvm->xen.grant.len ); -} - -/** - * Map XenStore - * - * @v hvm HVM device - * @ret rc Return status code - */ -static int hvm_map_xenstore ( struct hvm_device *hvm ) { - uint64_t xenstore_evtchn; - uint64_t xenstore_pfn; - physaddr_t xenstore_phys; - char *name; - int xenrc; - int rc; - - /* Get XenStore event channel */ - if ( ( xenrc = xen_hvm_get_param ( &hvm->xen, HVM_PARAM_STORE_EVTCHN, - &xenstore_evtchn ) ) != 0 ) { - rc = -EXEN ( xenrc ); - DBGC ( hvm, "HVM could not get XenStore event channel: %s\n", - strerror ( rc ) ); - return rc; - } - hvm->xen.store.port = xenstore_evtchn; - - /* Get XenStore PFN */ - if ( ( xenrc = xen_hvm_get_param ( &hvm->xen, HVM_PARAM_STORE_PFN, - &xenstore_pfn ) ) != 0 ) { - rc = -EXEN ( xenrc ); - DBGC ( hvm, "HVM could not get XenStore PFN: %s\n", - strerror ( rc ) ); - return rc; - } - xenstore_phys = ( xenstore_pfn * PAGE_SIZE ); - - /* Map XenStore */ - hvm->xen.store.intf = ioremap ( xenstore_phys, PAGE_SIZE ); - if ( ! hvm->xen.store.intf ) { - DBGC ( hvm, "HVM could not map XenStore at [%08lx,%08lx)\n", - xenstore_phys, ( xenstore_phys + PAGE_SIZE ) ); - return -ENODEV; - } - DBGC2 ( hvm, "HVM mapped XenStore at [%08lx,%08lx) with event port " - "%d\n", xenstore_phys, ( xenstore_phys + PAGE_SIZE ), - hvm->xen.store.port ); - - /* Check that XenStore is working */ - if ( ( rc = xenstore_read ( &hvm->xen, &name, "name", NULL ) ) != 0 ) { - DBGC ( hvm, "HVM could not read domain name: %s\n", - strerror ( rc ) ); - return rc; - } - DBGC2 ( hvm, "HVM running in domain \"%s\"\n", name ); - free ( name ); - - return 0; -} - -/** - * Unmap XenStore - * - * @v hvm HVM device - */ -static void hvm_unmap_xenstore ( struct hvm_device *hvm ) { - - /* Unmap XenStore */ - iounmap ( hvm->xen.store.intf ); -} - -/** - * Probe PCI device - * - * @v pci PCI device - * @ret rc Return status code - */ -static int hvm_probe ( struct pci_device *pci ) { - struct hvm_device *hvm; - int rc; - - /* Allocate and initialise structure */ - hvm = zalloc ( sizeof ( *hvm ) ); - if ( ! hvm ) { - rc = -ENOMEM; - goto err_alloc; - } - hvm->mmio = pci_bar_start ( pci, HVM_MMIO_BAR ); - hvm->mmio_len = pci_bar_size ( pci, HVM_MMIO_BAR ); - DBGC2 ( hvm, "HVM has MMIO space [%08lx,%08lx)\n", - hvm->mmio, ( hvm->mmio + hvm->mmio_len ) ); - - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Attach to hypervisor */ - if ( ( rc = hvm_cpuid_base ( hvm ) ) != 0 ) - goto err_cpuid_base; - if ( ( rc = hvm_map_hypercall ( hvm ) ) != 0 ) - goto err_map_hypercall; - if ( ( rc = hvm_map_shared_info ( hvm ) ) != 0 ) - goto err_map_shared_info; - if ( ( rc = hvm_map_grant ( hvm ) ) != 0 ) - goto err_map_grant; - if ( ( rc = hvm_map_xenstore ( hvm ) ) != 0 ) - goto err_map_xenstore; - - /* Probe Xen devices */ - if ( ( rc = xenbus_probe ( &hvm->xen, &pci->dev ) ) != 0 ) { - DBGC ( hvm, "HVM could not probe Xen bus: %s\n", - strerror ( rc ) ); - goto err_xenbus_probe; - } - - pci_set_drvdata ( pci, hvm ); - return 0; - - xenbus_remove ( &hvm->xen, &pci->dev ); - err_xenbus_probe: - hvm_unmap_xenstore ( hvm ); - err_map_xenstore: - hvm_unmap_grant ( hvm ); - err_map_grant: - hvm_unmap_shared_info ( hvm ); - err_map_shared_info: - hvm_unmap_hypercall ( hvm ); - err_map_hypercall: - err_cpuid_base: - free ( hvm ); - err_alloc: - return rc; -} - -/** - * Remove PCI device - * - * @v pci PCI device - */ -static void hvm_remove ( struct pci_device *pci ) { - struct hvm_device *hvm = pci_get_drvdata ( pci ); - - xenbus_remove ( &hvm->xen, &pci->dev ); - hvm_unmap_xenstore ( hvm ); - hvm_unmap_grant ( hvm ); - hvm_unmap_shared_info ( hvm ); - hvm_unmap_hypercall ( hvm ); - free ( hvm ); -} - -/** PCI device IDs */ -static struct pci_device_id hvm_ids[] = { - PCI_ROM ( 0x5853, 0x0001, "hvm", "hvm", 0 ), - PCI_ROM ( 0x5853, 0x0002, "hvm2", "hvm2", 0 ), -}; - -/** PCI driver */ -struct pci_driver hvm_driver __pci_driver = { - .ids = hvm_ids, - .id_count = ( sizeof ( hvm_ids ) / sizeof ( hvm_ids[0] ) ), - .probe = hvm_probe, - .remove = hvm_remove, -}; - -/* Drag in objects via hvm_driver */ -REQUIRING_SYMBOL ( hvm_driver ); - -/* Drag in netfront driver */ -REQUIRE_OBJECT ( netfront ); diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h b/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h deleted file mode 100644 index 72ed94f6d..000000000 --- a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _HVM_H -#define _HVM_H - -/** @file - * - * Xen HVM driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <ipxe/xen.h> -#include <xen/hvm/hvm_op.h> -#include <xen/hvm/params.h> - -/** Minimum CPUID base */ -#define HVM_CPUID_MIN 0x40000000UL - -/** Maximum CPUID base */ -#define HVM_CPUID_MAX 0x4000ff00UL - -/** Increment between CPUID bases */ -#define HVM_CPUID_STEP 0x00000100UL - -/** Magic signature */ -#define HVM_CPUID_MAGIC "XenVMMXenVMM" - -/** Get Xen version */ -#define HVM_CPUID_VERSION 1 - -/** Get number of hypercall pages */ -#define HVM_CPUID_PAGES 2 - -/** PCI MMIO BAR */ -#define HVM_MMIO_BAR PCI_BASE_ADDRESS_1 - -/** A Xen HVM device */ -struct hvm_device { - /** Xen hypervisor */ - struct xen_hypervisor xen; - /** CPUID base */ - uint32_t cpuid_base; - /** Length of hypercall table */ - size_t hypercall_len; - /** MMIO base address */ - unsigned long mmio; - /** Current offset within MMIO address space */ - size_t mmio_offset; - /** Length of MMIO address space */ - size_t mmio_len; -}; - -/** - * Get HVM parameter value - * - * @v xen Xen hypervisor - * @v index Parameter index - * @v value Value to fill in - * @ret xenrc Xen status code - */ -static inline int xen_hvm_get_param ( struct xen_hypervisor *xen, - unsigned int index, uint64_t *value ) { - struct xen_hvm_param param; - int xenrc; - - param.domid = DOMID_SELF; - param.index = index; - xenrc = xen_hypercall_2 ( xen, __HYPERVISOR_hvm_op, HVMOP_get_param, - virt_to_phys ( ¶m ) ); - *value = param.value; - return xenrc; -} - -#endif /* _HVM_H */ |