Move libsel4vmm into libsel4vm A new library within seL4_projects_libs called libsel4vm has been created out of libsel4vmm and libsel4arm-vmm. Additionally, a snapshot of this library can be found in the sel4-deprecated repository where it will marked as deprecated.
diff --git a/CMakeLists.txt b/CMakeLists.txt index f00e268..cd6f8b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -25,4 +25,3 @@ add_subdirectory(libsel4sync) add_subdirectory(libsel4muslcsys) add_subdirectory(libsel4bench) -add_subdirectory(libsel4vmm)
diff --git a/libsel4vmm/CMakeLists.txt b/libsel4vmm/CMakeLists.txt deleted file mode 100644 index 5dc65a9..0000000 --- a/libsel4vmm/CMakeLists.txt +++ /dev/null
@@ -1,99 +0,0 @@ -# -# Copyright 2018, Data61 -# Commonwealth Scientific and Industrial Research Organisation (CSIRO) -# ABN 41 687 119 230. -# -# This software may be distributed and modified according to the terms of -# the BSD 2-Clause license. Note that NO WARRANTY is provided. -# See "LICENSE_BSD2.txt" for details. -# -# @TAG(DATA61_BSD) -# - -cmake_minimum_required(VERSION 3.8.2) - -project(libsel4vmm C) - -set(configure_string "") - -config_option(LibSel4VMMVESAFrameBuffer VMM_VESA_FRAMEBUFFER "Expose VESA Frame Buffer - Support for mapping the VESA frame buffer frames into the guest OS. - This option is useful for working around non-working video drivers otherwise, - due to missing features or such." DEFAULT ON) - -config_option(LibSel4VMMDebug LIB_VMM_DEBUG "Enable VMM debug output" DEFAULT ON) - -config_string(LibSel4VMMDebugLevel LIB_VMM_DEBUG_LEVEL "VMM Debug Output - Debug verbosity level. - 5 levels for debug messages: - 0: Always printout - 1: Main entry point in a module - 2: 2nd level entry point in a module - 3: Main entry point of a function - 4: Details inside a function" DEFAULT 3 UNQUOTE) - -config_option( - LibSel4VMMVMXTimerDebug - LIB_VMM_VMX_TIMER_DEBUG - "Use VMX Pre-Emption timer for debugging - Will cause a regular vmexit to happen based on VMX pre-emption - timer. At each exit the guest state will be printed out. This - can be used to aid debugging when running a guest causes nothing - to appear to happen" - DEFAULT - OFF -) - -config_string( - LibSel4VMMVMXTimerTimeout - LIB_VMM_VMX_TIMER_TIMEOUT - "Cycles between VMX timer pre-emptions - Cycles between timer exits. Time spent loading the VMCS context - count, so setting this too low may result in the guest making - no progress" - DEFAULT - 4000 - DEPENDS - "LibSel4VMMVMXTimerDebug" -) - -config_option(LibSel4VMMIgnoreEPTViolation VMM_IGNORE_EPT_VIOLATION "Ignore EPT Violations - If set then EPT faults will be ignored and the guest will be resumed" DEFAULT OFF) -mark_as_advanced( - LibSel4VMMVESAFrameBuffer - LibSel4VMMDebug - LibSel4VMMDebugLevel - LibSel4VMMVMXTimerDebug - LibSel4VMMVMXTimerTimeout - LibSel4VMMIgnoreEPTViolation -) -add_config_library(sel4vmm "${configure_string}") - -add_compile_options(-std=gnu99) - -file( - GLOB - sources - src/vmm/*.c - src/platform/*.c - src/driver/*.c - src/manager/*.c - src/processor/*.c -) - -add_library(sel4vmm STATIC EXCLUDE_FROM_ALL ${sources}) - -target_include_directories(sel4vmm PUBLIC include) -target_link_libraries( - sel4vmm - PUBLIC - muslc - sel4 - sel4utils - pci - sel4allocman - ethdrivers - platsupport - sel4vmm_Config - sel4_autoconf -)
diff --git a/libsel4vmm/LICENSE_GPLv2.txt b/libsel4vmm/LICENSE_GPLv2.txt deleted file mode 100644 index e418701..0000000 --- a/libsel4vmm/LICENSE_GPLv2.txt +++ /dev/null
@@ -1,295 +0,0 @@ - -Files described as being under the "GNU General Public License version 2" -or simply the "GPLv2" fall under the following license. - -Note that this copyright does not cover user programs that use kernel -services by normal system calls --- this is merely considered normal use -of the kernel, and does not fall under the heading of "derived work". - -Also note that while the Free Software Foundation owns the copyright to -the license text below, copyright for the actual files included in this -project are held by their respective owners, indicated at the top of -each file. - ------------------------------------------------------------------------ - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS
diff --git a/libsel4vmm/include/vmm/debug.h b/libsel4vmm/include/vmm/debug.h deleted file mode 100644 index e9a407b..0000000 --- a/libsel4vmm/include/vmm/debug.h +++ /dev/null
@@ -1,65 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> -#include "vmm/vmm.h" - -#ifndef COLOUR -#define COLOUR "\033[;1;%dm" -#define COLOUR_R "\033[;1;31m" -#define COLOUR_G "\033[;1;32m" -#define COLOUR_Y "\033[;1;33m" -#define COLOUR_B "\033[;1;34m" -#define COLOUR_M "\033[;1;35m" -#define COLOUR_C "\033[;1;36m" -#define COLOUR_RESET "\033[0m" -#endif - -#ifdef CONFIG_LIB_VMM_DEBUG - -#define DPRINTF(lvl, ...) \ - do{ \ - if(lvl <= 0 || lvl < CONFIG_LIB_VMM_DEBUG_LEVEL){ \ - printf("%s:%d | ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - } \ - }while(0) - -#define drun(lvl, cmd) \ - do{ \ - if(lvl < LIB_VMM_DEBUG_LEVEL){ \ - cmd; \ - } \ - }while(0) - -#else /* CONFIG_LIB_VMM_DEBUG */ - -#define DPRINTF(lvl, ...) do{ /* nothing */ }while(0) -#define drun() do{ /* nothing */ }while(0) - -#endif /* CONFIG_LIB_VMM_DEBUG */ - -#ifndef panic -#define panic(msg) \ - do{ \ - printf(COLOUR_R "!!!!!!!!!!!! LIBVMM PANIC !!!!!!!!!!!!! \n"\ - " @ %s: %d | %s\n" COLOUR_RESET, __func__, __LINE__, msg);\ - assert(!msg);\ - while(1);\ - }while(0) -#endif - -void vmm_print_guest_context(int, vmm_vcpu_t *); -
diff --git a/libsel4vmm/include/vmm/driver/pci.h b/libsel4vmm/include/vmm/driver/pci.h deleted file mode 100644 index bcd3ddc..0000000 --- a/libsel4vmm/include/vmm/driver/pci.h +++ /dev/null
@@ -1,63 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ -/* x86 VMM PCI Driver, which manages the host's PCI devices, and handles guest OS PCI config space - * read & writes. -*/ - -#pragma once - -#include <stdint.h> - -typedef struct vmm_pci_address { - uint8_t bus; - uint8_t dev; - uint8_t fun; -} vmm_pci_address_t; - -/* Functions for accessing the pci config space */ -typedef struct vmm_pci_config { - void *cookie; - uint8_t (*ioread8)(void *cookie, vmm_pci_address_t addr, unsigned int offset); - uint16_t (*ioread16)(void *cookie, vmm_pci_address_t addr, unsigned int offset); - uint32_t (*ioread32)(void *cookie, vmm_pci_address_t addr, unsigned int offset); - void (*iowrite8)(void *cookie, vmm_pci_address_t addr, unsigned int offset, uint8_t val); - void (*iowrite16)(void *cookie, vmm_pci_address_t addr, unsigned int offset, uint16_t val); - void (*iowrite32)(void *cookie, vmm_pci_address_t addr, unsigned int offset, uint32_t val); -} vmm_pci_config_t; - -/* Abstract virtual PCI thing. Could be a device or anything. This - * can be inserted into the virtual PCI configuration space */ -typedef struct vmm_pci_entry { - /* Callback functions for reading or writing its configuration space. - * Returns 0 on success, nonzero if an error occured */ - void *cookie; - int (*ioread)(void *cookie, int offset, int size, uint32_t *result); - int (*iowrite)(void *cookie, int offset, int size, uint32_t value); -} vmm_pci_entry_t; - -typedef struct vmm_pci_space { - /* Only support one bus at the moment. */ - vmm_pci_entry_t *bus0[32][8]; - /* For IO port emulation this is the current config address */ - uint32_t conf_port_addr; -} vmm_pci_space_t; - -/* Initialize PCI space */ -int vmm_pci_init(vmm_pci_space_t *space); - -/* Add a PCI entry. Optionally reports where it is located */ -int vmm_pci_add_entry(vmm_pci_space_t *space, vmm_pci_entry_t entry, vmm_pci_address_t *addr); - -/* Functions for emulating PCI config spaces over IO ports */ -int vmm_pci_io_port_in(void *cookie, unsigned int port_no, unsigned int size, unsigned int *result); -int vmm_pci_io_port_out(void *cookie, unsigned int port_no, unsigned int size, unsigned int value); -
diff --git a/libsel4vmm/include/vmm/driver/pci_helper.h b/libsel4vmm/include/vmm/driver/pci_helper.h deleted file mode 100644 index eb87f99..0000000 --- a/libsel4vmm/include/vmm/driver/pci_helper.h +++ /dev/null
@@ -1,101 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <stdint.h> -#include <pci/pci.h> - -#include "vmm/driver/pci.h" -#include "vmm/vmm.h" - -/* Struct definition of a PCI device. This is used for emulating a device from - * purely memory reads. This is not generally useful on its own, but provides - * a nice skeleton */ -typedef struct vmm_pci_device_def { - uint16_t vendor_id; - uint16_t device_id; - uint16_t command; - uint16_t status; - uint8_t revision_id; - uint8_t prog_if; - uint8_t subclass; - uint8_t class_code; - uint8_t cache_line_size; - uint8_t latency_timer; - uint8_t header_type; - uint8_t bist; - uint32_t bar0; - uint32_t bar1; - uint32_t bar2; - uint32_t bar3; - uint32_t bar4; - uint32_t bar5; - uint32_t cardbus; - uint16_t subsystem_vendor_id; - uint16_t subsystem_id; - uint32_t expansion_rom; - uint8_t caps_pointer; - uint8_t reserved1; - uint16_t reserved2; - uint32_t reserved3; - uint8_t interrupt_line; - uint8_t interrupt_pin; - uint8_t min_grant; - uint8_t max_latency; - /* Now additional pointer to arbitrary capabilities */ - int caps_len; - void *caps; -} __attribute__((packed)) vmm_pci_device_def_t; - -typedef struct vmm_pci_bar { - int ismem; - /* Address must be size aligned */ - uintptr_t address; - int size_bits; - /* only if memory */ - int prefetchable; -} vmm_pci_bar_t; - -/* Helper write function that just ignores any writes */ -int vmm_pci_entry_ignore_write(void *cookie, int offset, int size, uint32_t value); - -/* Read and write methods for a memory device */ -int vmm_pci_mem_device_read(void *cookie, int offset, int size, uint32_t *result); -int vmm_pci_mem_device_write(void *cookie, int offset, int size, uint32_t value); - -void define_pci_host_bridge(vmm_pci_device_def_t *bridge); - -/* Construct a pure passthrough device based on the real PCI. This is almost always useless as - * you will almost certainly want to rebase io memory */ -vmm_pci_entry_t vmm_pci_create_passthrough(vmm_pci_address_t addr, vmm_pci_config_t config); - -/* Bar read/write emulation, rest passed on */ -vmm_pci_entry_t vmm_pci_create_bar_emulation(vmm_pci_entry_t existing, int num_bars, vmm_pci_bar_t *bars); - -/* Interrupt read/write emulation, rest passed on */ -vmm_pci_entry_t vmm_pci_create_irq_emulation(vmm_pci_entry_t existing, int irq); - -/* Capability space emulation. Takes list of addresses to use to form a capability - * linked list, as well as a ranges of the capability space that should be - * directly disallowed. Assumes a type 0 device. - */ -vmm_pci_entry_t vmm_pci_create_cap_emulation(vmm_pci_entry_t existing, int num_caps, uint8_t *caps, int num_ranges, uint8_t *range_starts, uint8_t *range_ends); - -/* Finds the MSI capabilities and uses vmm_pci_create_cap_emulation to remove them */ -vmm_pci_entry_t vmm_pci_no_msi_cap_emulation(vmm_pci_entry_t existing); - -/* Takes a libpci device scan and adds the bar resources to the guest, creating - * new pci bar information that can be passed to a virtual config space creator. - * Creates at most 6 bars, returns how many it created, negative on error */ -int vmm_pci_helper_map_bars(vmm_t *vmm, libpci_device_iocfg_t *cfg, vmm_pci_bar_t *bars); -
diff --git a/libsel4vmm/include/vmm/driver/virtio_emul.h b/libsel4vmm/include/vmm/driver/virtio_emul.h deleted file mode 100644 index d0e9065..0000000 --- a/libsel4vmm/include/vmm/driver/virtio_emul.h +++ /dev/null
@@ -1,34 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <platsupport/io.h> -#include <ethdrivers/raw.h> -#include <vmm/platform/guest_vspace.h> - -struct ethif_virtio_emul_internal; - -typedef struct ethif_virtio_emul { - /* pointer to internal information */ - struct ethif_virtio_emul_internal *internal; - /* io port interface functions */ - int (*io_in)(struct ethif_virtio_emul *emul, unsigned int offset, unsigned int size, unsigned int *result); - int (*io_out)(struct ethif_virtio_emul *emul, unsigned int offset, unsigned int size, unsigned int value); - /* notify of a status change in the underlying driver. - * typically this would be due to link coming up - * meaning that transmits can finally happen */ - int (*notify)(struct ethif_virtio_emul *emul); -} ethif_virtio_emul_t; - -ethif_virtio_emul_t *ethif_virtio_emul_init(ps_io_ops_t io_ops, int queue_size, vspace_t *guest_vspace, ethif_driver_init driver, void *config); -
diff --git a/libsel4vmm/include/vmm/guest_state.h b/libsel4vmm/include/vmm/guest_state.h deleted file mode 100644 index 2bab43e..0000000 --- a/libsel4vmm/include/vmm/guest_state.h +++ /dev/null
@@ -1,390 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/vmcs.h" -#include "vmm/platform/vmcs.h" - -typedef struct guest_cr_virt_state { - /* mask represents bits that are owned by us, the host */ - unsigned int cr0_mask; - unsigned int cr4_mask; - /* the shadow represents what the values of our owned bits should be seen as by the guest. - * i.e. the value they set it to */ - unsigned int cr0_shadow; - unsigned int cr4_shadow; - /* for any bits owned by us, this represents what those bits should actually be set to */ - unsigned int cr0_host_bits; - unsigned int cr4_host_bits; - /* the raw cr3 is only valid if we're trapping guest accesses to cr3, which we - * only do if the guest has not yet enabled paging for itself. If the guest has - * enabled paging then the value should be retrieved from the guest machine state */ - uint32_t cr3_guest; -} guest_cr_virt_state_t; - -typedef struct guest_exit_information { - bool in_exit; - unsigned int reason; - unsigned int qualification; - unsigned int instruction_length; - unsigned int guest_physical; -} guest_exit_information_t; - -typedef enum machine_state_status { - /* Unknown means guest has run and we have no idea if - * our value is up to date */ - machine_state_unknown = 0, - /* Valid means the value we have is up to date and we - * have not modified it with respect to what the guest - * believes */ - machine_state_valid, - /* As part of the virtualization we have modified the value - * and this needs to be sycned back to the guest */ - machine_state_modified -} machine_state_status_t; - -#define MACHINE_STATE(type, name) machine_state_status_t name##_status; type name -#define MACHINE_STATE_READ(name, value) do { assert(name##_status == machine_state_unknown); name##_status = machine_state_valid; name = (value);} while(0) -#define MACHINE_STATE_DIRTY(name) do { name##_status = machine_state_modified; } while(0) -#define MACHINE_STATE_SYNC(name) do { assert(name##_status == machine_state_modified); name##_status = machine_state_valid; } while(0) -#define MACHINE_STATE_INVAL(name) do { assert(name##_status != machine_state_modified); name##_status = machine_state_unknown; } while(0) -#define MACHINE_STATE_SYNC_INVAL(name) do { MACHINE_STATE_SYNC(name); MACHINE_STATE_INVAL(name); } while(0) -#define IS_MACHINE_STATE_VALID(name) (name##_status == machine_state_valid) -#define IS_MACHINE_STATE_UNKNOWN(name) (name##_status == machine_state_unknown) -#define IS_MACHINE_STATE_MODIFIED(name) (name##_status == machine_state_modified) - -typedef struct guest_machine_state { - MACHINE_STATE(seL4_VCPUContext, context); - MACHINE_STATE(unsigned int, cr0); - MACHINE_STATE(unsigned int, cr3); - MACHINE_STATE(unsigned int, cr4); - MACHINE_STATE(unsigned int, rflags); - MACHINE_STATE(unsigned int, guest_interruptibility); - MACHINE_STATE(unsigned int, idt_base); - MACHINE_STATE(unsigned int, idt_limit); - MACHINE_STATE(unsigned int, gdt_base); - MACHINE_STATE(unsigned int, gdt_limit); - MACHINE_STATE(unsigned int, cs_selector); - MACHINE_STATE(unsigned int, entry_exception_error_code); - /* This is state that we set on VMentry and get back on - * a vmexit, therefore it is always valid and correct */ - unsigned int eip; - unsigned int control_entry; - unsigned int control_ppc; -} guest_machine_state_t; - -/* Define the seL4_UserContext layout so we can treat it as an array */ -#define USER_CONTEXT_EAX 0 -#define USER_CONTEXT_EBX 1 -#define USER_CONTEXT_ECX 2 -#define USER_CONTEXT_EDX 3 -#define USER_CONTEXT_ESI 4 -#define USER_CONTEXT_EDI 5 -#define USER_CONTEXT_EBP 6 - -typedef struct guest_virt_state { - guest_cr_virt_state_t cr; - /* are we hlt'ed waiting for an interrupted */ - int interrupt_halt; -} guest_virt_state_t; - -typedef struct guest_state { - /* Guest machine state. Bits of this may or may not be valid. - * This is all state that the guest itself observes and modifies. - * Either explicitly (registers) or implicitly (interruptability state) */ - guest_machine_state_t machine; - /* Internal state that we use for handling guest state virtualization. */ - guest_virt_state_t virt; - /* Information relating specifically to a guest exist, that is generated - * as a result of the exit */ - guest_exit_information_t exit; -} guest_state_t; - -static inline bool vmm_guest_state_no_modified(guest_state_t *gs) { - return !( - IS_MACHINE_STATE_MODIFIED(gs->machine.context) || - IS_MACHINE_STATE_MODIFIED(gs->machine.cr0) || - IS_MACHINE_STATE_MODIFIED(gs->machine.cr3) || - IS_MACHINE_STATE_MODIFIED(gs->machine.cr4) || - IS_MACHINE_STATE_MODIFIED(gs->machine.rflags) || - IS_MACHINE_STATE_MODIFIED(gs->machine.guest_interruptibility) || - IS_MACHINE_STATE_MODIFIED(gs->machine.idt_base) || - IS_MACHINE_STATE_MODIFIED(gs->machine.idt_limit) || - IS_MACHINE_STATE_MODIFIED(gs->machine.gdt_base) || - IS_MACHINE_STATE_MODIFIED(gs->machine.gdt_limit) || - IS_MACHINE_STATE_MODIFIED(gs->machine.cs_selector) || - IS_MACHINE_STATE_MODIFIED(gs->machine.entry_exception_error_code) - ); -} - -static inline void vmm_guest_state_invalidate_all(guest_state_t *gs) { - MACHINE_STATE_INVAL(gs->machine.context); - MACHINE_STATE_INVAL(gs->machine.cr0); - MACHINE_STATE_INVAL(gs->machine.cr3); - MACHINE_STATE_INVAL(gs->machine.cr4); - MACHINE_STATE_INVAL(gs->machine.rflags); - MACHINE_STATE_INVAL(gs->machine.guest_interruptibility); - MACHINE_STATE_INVAL(gs->machine.idt_base); - MACHINE_STATE_INVAL(gs->machine.idt_limit); - MACHINE_STATE_INVAL(gs->machine.gdt_base); - MACHINE_STATE_INVAL(gs->machine.gdt_limit); - MACHINE_STATE_INVAL(gs->machine.cs_selector); - MACHINE_STATE_INVAL(gs->machine.entry_exception_error_code); -} - -/* get */ -static inline uint32_t vmm_read_user_context(guest_state_t *gs, int reg) { - assert(!IS_MACHINE_STATE_UNKNOWN(gs->machine.context)); - assert(reg >= 0 && reg <= USER_CONTEXT_EBP); - return (&gs->machine.context.eax)[reg]; -} - -static inline unsigned int vmm_guest_state_get_eip(guest_state_t *gs) { - return gs->machine.eip; -} - -static inline unsigned int vmm_guest_state_get_cr0(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.cr0)) { - MACHINE_STATE_READ(gs->machine.cr0, vmm_vmcs_read(vcpu, VMX_GUEST_CR0)); - } - return gs->machine.cr0; -} - -static inline unsigned int vmm_guest_state_get_cr3(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.cr3)) { - MACHINE_STATE_READ(gs->machine.cr3, vmm_vmcs_read(vcpu, VMX_GUEST_CR3)); - } - return gs->machine.cr3; -} - -static inline unsigned int vmm_guest_state_get_cr4(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.cr4)) { - MACHINE_STATE_READ(gs->machine.cr4, vmm_vmcs_read(vcpu, VMX_GUEST_CR4)); - } - return gs->machine.cr4; -} - -static inline unsigned int vmm_guest_state_get_rflags(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.rflags)) { - MACHINE_STATE_READ(gs->machine.rflags, vmm_vmcs_read(vcpu, VMX_GUEST_RFLAGS)); - } - return gs->machine.rflags; -} - -static inline unsigned int vmm_guest_state_get_interruptibility(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.guest_interruptibility)) { - MACHINE_STATE_READ(gs->machine.guest_interruptibility, vmm_vmcs_read(vcpu, VMX_GUEST_INTERRUPTABILITY)); - } - return gs->machine.guest_interruptibility; -} - -static inline unsigned int vmm_guest_state_get_control_entry(guest_state_t *gs) { - return gs->machine.control_entry; -} - -static inline unsigned int vmm_guest_state_get_control_ppc(guest_state_t *gs) { - return gs->machine.control_ppc; -} - -static inline unsigned int vmm_guest_state_get_idt_base(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.idt_base)) { - MACHINE_STATE_READ(gs->machine.idt_base, vmm_vmcs_read(vcpu, VMX_GUEST_IDTR_BASE)); - } - return gs->machine.idt_base; -} - -static inline unsigned int vmm_guest_state_get_idt_limit(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.idt_limit)) { - MACHINE_STATE_READ(gs->machine.idt_limit, vmm_vmcs_read(vcpu, VMX_GUEST_IDTR_LIMIT)); - } - return gs->machine.idt_limit; -} - -static inline unsigned int vmm_guest_state_get_gdt_base(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.gdt_base)) { - MACHINE_STATE_READ(gs->machine.gdt_base, vmm_vmcs_read(vcpu, VMX_GUEST_GDTR_BASE)); - } - return gs->machine.gdt_base; -} - -static inline unsigned int vmm_guest_state_get_gdt_limit(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.gdt_limit)) { - MACHINE_STATE_READ(gs->machine.gdt_limit, vmm_vmcs_read(vcpu, VMX_GUEST_GDTR_LIMIT)); - } - return gs->machine.gdt_limit; -} - -static inline unsigned int vmm_guest_state_get_cs_selector(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_UNKNOWN(gs->machine.cs_selector)) { - MACHINE_STATE_READ(gs->machine.cs_selector, vmm_vmcs_read(vcpu, VMX_GUEST_CS_SELECTOR)); - } - return gs->machine.cs_selector; -} - -/* set */ -static inline void vmm_set_user_context(guest_state_t *gs, int reg, uint32_t val) { - MACHINE_STATE_DIRTY(gs->machine.context); - assert(reg >= 0 && reg <= USER_CONTEXT_EBP); - (&gs->machine.context.eax)[reg] = val; -} - -static inline void vmm_guest_state_set_eip(guest_state_t *gs, unsigned int val) { - gs->machine.eip = val; -} - -static inline void vmm_guest_state_set_cr0(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.cr0); - gs->machine.cr0 = val; -} - -static inline void vmm_guest_state_set_cr3(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.cr3); - gs->machine.cr3 = val; -} - -static inline void vmm_guest_state_set_cr4(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.cr4); - gs->machine.cr4 = val; -} - -static inline void vmm_guest_state_set_control_entry(guest_state_t *gs, unsigned int val) { - gs->machine.control_entry = val; -} - -static inline void vmm_guest_state_set_control_ppc(guest_state_t *gs, unsigned int val) { - gs->machine.control_ppc = val; -} - -static inline void vmm_guest_state_set_idt_base(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.idt_base); - gs->machine.idt_base = val; -} - -static inline void vmm_guest_state_set_idt_limit(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.idt_limit); - gs->machine.idt_limit = val; -} - -static inline void vmm_guest_state_set_gdt_base(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.gdt_base); - gs->machine.gdt_base = val; -} - -static inline void vmm_guest_state_set_gdt_limit(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.gdt_limit); - gs->machine.gdt_limit = val; -} - -static inline void vmm_guest_state_set_cs_selector(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.cs_selector); - gs->machine.cs_selector = val; -} - -static inline void vmm_guest_state_set_entry_exception_error_code(guest_state_t *gs, unsigned int val) { - MACHINE_STATE_DIRTY(gs->machine.entry_exception_error_code); - gs->machine.entry_exception_error_code = val; -} - -/* sync */ -static inline void vmm_guest_state_sync_cr0(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.cr0)) { - vmm_vmcs_write(vcpu, VMX_GUEST_CR0, gs->machine.cr0); - MACHINE_STATE_SYNC(gs->machine.cr0); - } -} - -static inline void vmm_guest_state_sync_cr3(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.cr3)) { - vmm_vmcs_write(vcpu, VMX_GUEST_CR3, gs->machine.cr3); - MACHINE_STATE_SYNC(gs->machine.cr3); - } -} - -static inline void vmm_guest_state_sync_cr4(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.cr4)) { - vmm_vmcs_write(vcpu, VMX_GUEST_CR4, gs->machine.cr4); - MACHINE_STATE_SYNC(gs->machine.cr4); - } -} - -static inline void vmm_guest_state_sync_idt_base(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.idt_base)) { - vmm_vmcs_write(vcpu, VMX_GUEST_IDTR_BASE, gs->machine.idt_base); - MACHINE_STATE_SYNC(gs->machine.idt_base); - } -} - -static inline void vmm_guest_state_sync_idt_limit(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.idt_limit)) { - vmm_vmcs_write(vcpu, VMX_GUEST_IDTR_LIMIT, gs->machine.idt_limit); - MACHINE_STATE_SYNC(gs->machine.idt_limit); - } -} - -static inline void vmm_guest_state_sync_gdt_base(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.gdt_base)) { - vmm_vmcs_write(vcpu, VMX_GUEST_GDTR_BASE, gs->machine.gdt_base); - MACHINE_STATE_SYNC(gs->machine.gdt_base); - } -} - -static inline void vmm_guest_state_sync_gdt_limit(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.gdt_limit)) { - vmm_vmcs_write(vcpu, VMX_GUEST_GDTR_LIMIT, gs->machine.gdt_limit); - MACHINE_STATE_SYNC(gs->machine.gdt_limit); - } -} - -static inline void vmm_guest_state_sync_cs_selector(guest_state_t *gs, seL4_CPtr vcpu) { - if(IS_MACHINE_STATE_MODIFIED(gs->machine.cs_selector)) { - vmm_vmcs_write(vcpu, VMX_GUEST_CS_SELECTOR, gs->machine.cs_selector); - MACHINE_STATE_SYNC(gs->machine.cs_selector); - } -} - -static inline void vmm_guest_state_sync_entry_exception_error_code(guest_state_t *gs, seL4_CPtr vcpu) { - if (IS_MACHINE_STATE_MODIFIED(gs->machine.entry_exception_error_code)) { - vmm_vmcs_write(vcpu, VMX_CONTROL_ENTRY_EXCEPTION_ERROR_CODE, gs->machine.entry_exception_error_code); - MACHINE_STATE_SYNC(gs->machine.entry_exception_error_code); - } -} - -/* Exit */ -static inline unsigned int vmm_guest_exit_get_reason(guest_state_t *gs) { - assert(gs->exit.in_exit); - return gs->exit.reason; -} - -static inline unsigned int vmm_guest_exit_get_physical(guest_state_t *gs) { - assert(gs->exit.in_exit); - return gs->exit.guest_physical; -} - -static inline unsigned int vmm_guest_exit_get_int_len(guest_state_t *gs) { - assert(gs->exit.in_exit); - return gs->exit.instruction_length; -} - -static inline unsigned int vmm_guest_exit_get_qualification(guest_state_t *gs) { - assert(gs->exit.in_exit); - return gs->exit.qualification; -} - -static inline void vmm_guest_exit_next_instruction(guest_state_t *gs, seL4_CPtr vcpu) { - vmm_guest_state_set_eip(gs, vmm_guest_state_get_eip(gs) + vmm_guest_exit_get_int_len(gs)); -} -
diff --git a/libsel4vmm/include/vmm/interrupt.h b/libsel4vmm/include/vmm/interrupt.h deleted file mode 100644 index 7becc6f..0000000 --- a/libsel4vmm/include/vmm/interrupt.h +++ /dev/null
@@ -1,39 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -typedef struct vmm_vcpu vmm_vcpu_t; - -/* Handler for a guest exit that is triggered when the guest is - * ready to receive interrupts */ -int vmm_pending_interrupt_handler(vmm_vcpu_t *vcpu); - -/* Request that the guest exist as soon as it is ready to receive - * interrupts */ -void wait_for_guest_ready(vmm_vcpu_t *vcpu); - -/* inject an exception */ -void vmm_inject_exception(vmm_vcpu_t *vcpu, int exception, int has_error, uint32_t error_code); - -/* Start an AP vcpu after a sipi with the requested vector */ -void vmm_start_ap_vcpu(vmm_vcpu_t *vcpu, unsigned int sipi_vector); - -/* Got interrupt(s) from PIC, propagate to relevant vcpu lapic */ -void vmm_check_external_interrupt(vmm_t *vmm); - -/* inject an interrupt from the lapic on the vcpu, whether or not it is in an exit */ -void vmm_vcpu_accept_interrupt(vmm_vcpu_t *vcpu); - -/* This function is called when a new interrupt has occured. */ -void vmm_have_pending_interrupt(vmm_vcpu_t *vcpu); -
diff --git a/libsel4vmm/include/vmm/io.h b/libsel4vmm/include/vmm/io.h deleted file mode 100644 index 1bde58f..0000000 --- a/libsel4vmm/include/vmm/io.h +++ /dev/null
@@ -1,54 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <stdint.h> - -#include <sel4/sel4.h> -#include <simple/simple.h> - -typedef int (*ioport_in_fn)(void *cookie, unsigned int port_no, unsigned int size, unsigned int *result); -typedef int (*ioport_out_fn)(void *cookie, unsigned int port_no, unsigned int size, unsigned int value); - -typedef struct ioport_range { - unsigned int port_start; - unsigned int port_end; - - int passthrough; - - /* If not passthrough, then handler functions */ - void *cookie; - ioport_in_fn port_in; - ioport_out_fn port_out; - - const char* desc; -} ioport_range_t; - -typedef struct vmm_io_list { - int num_ioports; - /* Sorted list of ioport functions */ - ioport_range_t *ioports; -} vmm_io_port_list_t; - -/* Initialize the io port list manager */ -int vmm_io_port_init(vmm_io_port_list_t *io_list); - -/* Add an io port range for pass through */ -int vmm_io_port_add_passthrough(vmm_io_port_list_t *io_list, uint16_t start, uint16_t end, const char *desc); - -/* Add an io port range for emulation */ -int vmm_io_port_add_handler(vmm_io_port_list_t *io_list, uint16_t start, uint16_t end, void *cookie, ioport_in_fn port_in, ioport_out_fn port_out, const char *desc); - -/* Add io ports to guest vcpu */ -int vmm_io_port_init_guest(vmm_io_port_list_t *io_list, simple_t *simple, seL4_CPtr vcpu, vka_t *vka); -
diff --git a/libsel4vmm/include/vmm/libvchan.h b/libsel4vmm/include/vmm/libvchan.h deleted file mode 100644 index 0d44c7d..0000000 --- a/libsel4vmm/include/vmm/libvchan.h +++ /dev/null
@@ -1,115 +0,0 @@ -/* @TAG(CUSTOM) *//* - * The Qubes OS Project, http://www.qubes-os.org - * - * Copyright (C) 2010 Rafal Wojtczuk <rafal@invisiblethingslab.com> - * - * 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. - * - */ - -#pragma once - -#include <stdint.h> -#include <stddef.h> -typedef int EVTCHN; - -struct libvchan; -typedef struct libvchan libvchan_t; - -/** -* Set up a vchan, including granting pages -* @return structure, or NULL in case of an error -*/ -libvchan_t *libvchan_server_init(int domain, int port, size_t read_min, size_t write_min); - -/** -* Connect to an existing vchan. Note: you can reconnect to an existing vchan -* safely, however no locking is performed, so you must prevent multiple clients -* from connecting to a single server. -*/ -libvchan_t *libvchan_client_init(int domain, int port); - -/** -* Waits for reads or writes to unblock, or for a close -*/ -int libvchan_wait(libvchan_t *ctrl); - - /** Amount of data ready to read, in bytes */ -int libvchan_data_ready(libvchan_t *ctrl); - -/** Amount of data it is possible to send without blocking */ -int libvchan_buffer_space(libvchan_t *ctrl); - -/** -* Packet-based receive: always reads exactly $size bytes. -* @param ctrl The vchan control structure -* @param data Buffer for data that was read -* @param size Size of the buffer and amount of data to read -* @return -1 on error, 0 if nonblocking and insufficient data is available, or $size -*/ -int libvchan_recv(libvchan_t *ctrl, void *data, size_t size); - -/** -* Packet-based send: send entire buffer if possible -* @param ctrl The vchan control structure -* @param data Buffer for data to send -* @param size Size of the buffer and amount of data to send -* @return -1 on error, 0 if nonblocking and insufficient space is available, or $size -*/ -int libvchan_send(libvchan_t *ctrl, const void *data, size_t size); - -/** -* Stream-based receive: reads as much data as possible. -* @param ctrl The vchan control structure -* @param data Buffer for data that was read -* @param size Size of the buffer -* @return -1 on error, otherwise the amount of data read (which may be zero if -* the vchan is nonblocking) -*/ -int libvchan_read(libvchan_t *ctrl, void *data, size_t size); - -/** -* Stream-based send: send as much data as possible. -* @param ctrl The vchan control structure -* @param data Buffer for data to send -* @param size Size of the buffer -* @return -1 on error, otherwise the amount of data sent (which may be zero if -* the vchan is nonblocking) -*/ -int libvchan_write(libvchan_t *ctrl, const void *data, size_t size); - -/** -* Query the state of the vchan shared page: -* return 0 when one side has called libxenvchan_close() or crashed -* return 1 when both sides are open -* return 2 [server only] when no client has yet connected -*/ -int libvchan_is_open(libvchan_t *ctrl); - -/// returns nonzero if the peer has closed connection -int libvchan_is_eof(libvchan_t *ctrl); - -/** -* Returns the event file descriptor for this vchan. When this FD is readable, -* libvchan() will not block, and the state of the vchan has changed since -* the last invocation of libvchan(). -*/ -int libvchan_fd_for_select(libvchan_t *ctrl); - -/** - * Notify the peer of closing. - */ -void libvchan_close(libvchan_t *ctrl); -
diff --git a/libsel4vmm/include/vmm/mmio.h b/libsel4vmm/include/vmm/mmio.h deleted file mode 100644 index 6603b23..0000000 --- a/libsel4vmm/include/vmm/mmio.h +++ /dev/null
@@ -1,51 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -typedef struct vmm_vcpu vmm_vcpu_t; - -// Deals with ranges of memory mapped io for emulated devices - -typedef void (*vmm_mmio_read_fn)(vmm_vcpu_t * vcpu, void *cookie, - uint32_t offset, int size, uint32_t *result); -typedef void (*vmm_mmio_write_fn)(vmm_vcpu_t *vcpu, void *cookie, - uint32_t offset, int size, uint32_t value); - -typedef struct vmm_mmio_range { - uintptr_t start; - uintptr_t end; - - vmm_mmio_read_fn read_handler; - vmm_mmio_write_fn write_handler; - - void *cookie; - - const char *name; -} vmm_mmio_range_t; - -typedef struct vmm_mmio_list { - vmm_mmio_range_t *ranges; // Sorted array - int num_ranges; -} vmm_mmio_list_t; - -// Initialise -int vmm_mmio_init(vmm_mmio_list_t *list); - -// Try to handle an exit with mmio -// Returns 0 if handled, or -1 otherwise -int vmm_mmio_exit_handler(vmm_vcpu_t *vcpu, uintptr_t addr, unsigned int qualification); - -int vmm_mmio_add_handler(vmm_mmio_list_t *list, uintptr_t start, uintptr_t end, - void *cookie, const char *name, - vmm_mmio_read_fn read_handler, vmm_mmio_write_fn write_handler); -
diff --git a/libsel4vmm/include/vmm/platform/acpi.h b/libsel4vmm/include/vmm/platform/acpi.h deleted file mode 100644 index c13daf3..0000000 --- a/libsel4vmm/include/vmm/platform/acpi.h +++ /dev/null
@@ -1,18 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#define ACPI_START (0xE0000) // Start of ACPI tables; RSD PTR is right here -#define MAX_ACPI_TABLES (2) - -int make_guest_acpi_tables(vmm_t *vmm);
diff --git a/libsel4vmm/include/vmm/platform/boot.h b/libsel4vmm/include/vmm/platform/boot.h deleted file mode 100644 index 7594eef..0000000 --- a/libsel4vmm/include/vmm/platform/boot.h +++ /dev/null
@@ -1,25 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <simple/simple.h> -#include <vka/vka.h> -#include <vspace/vspace.h> -#include <allocman/allocman.h> -#include "vmm/vmm.h" - -int vmm_init(vmm_t *vmm, allocman_t *allocman, simple_t simple, vka_t vka, vspace_t vspace, platform_callbacks_t callbacks); -int vmm_init_host(vmm_t *vmm); -int vmm_init_guest(vmm_t *vmm, int priority); -int vmm_init_guest_multi(vmm_t *vmm, int priority, int num_vcpus); -
diff --git a/libsel4vmm/include/vmm/platform/boot_guest.h b/libsel4vmm/include/vmm/platform/boot_guest.h deleted file mode 100644 index 14597ce..0000000 --- a/libsel4vmm/include/vmm/platform/boot_guest.h +++ /dev/null
@@ -1,23 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <stdint.h> -#include "vmm/vmm.h" - -void vmm_plat_guest_elf_relocate(vmm_t *vmm, const char *relocs_filename); -int vmm_guest_load_boot_module(vmm_t *vmm, const char *name); -void vmm_plat_init_guest_boot_structure(vmm_t *vmm, const char *cmdline); -void vmm_init_guest_thread_state(vmm_vcpu_t *vcpu); -int vmm_load_guest_elf(vmm_t *vmm, const char *elfname, size_t alignment); -
diff --git a/libsel4vmm/include/vmm/platform/bootinfo.h b/libsel4vmm/include/vmm/platform/bootinfo.h deleted file mode 100644 index 9f657b3..0000000 --- a/libsel4vmm/include/vmm/platform/bootinfo.h +++ /dev/null
@@ -1,302 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* Pretty sure most of this header was ripped straight from Linux */ - -#pragma once - -#define EDD_MBR_SIG_MAX 16 /* max number of signatures to store */ -#define E820MAX 128 /* number of entries in E820MAP */ -#define EDDMAXNR 6 /* number of edd_info structs starting at EDDBUF */ - -#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ -#define VIDEO_TYPE_CGA 0x11 /* CGA Display */ -#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */ -#define VIDEO_TYPE_EGAC 0x21 /* EGA in Color Mode */ -#define VIDEO_TYPE_VGAC 0x22 /* VGA+ in Color Mode */ -#define VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */ -#define VIDEO_TYPE_PICA_S3 0x30 /* ACER PICA-61 local S3 video */ -#define VIDEO_TYPE_MIPS_G364 0x31 /* MIPS Magnum 4000 G364 video */ -#define VIDEO_TYPE_SGI 0x33 /* Various SGI graphics hardware */ -#define VIDEO_TYPE_TGAC 0x40 /* DEC TGA */ -#define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */ -#define VIDEO_TYPE_SUNPCI 0x51 /* Sun PCI based frame buffer. */ -#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */ -#define VIDEO_TYPE_EFI 0x70 /* EFI graphic mode */ - -struct screen_info { - uint8_t orig_x; /* 0x00 */ - uint8_t orig_y; /* 0x01 */ - uint16_t ext_mem_k; /* 0x02 */ - uint16_t orig_video_page; /* 0x04 */ - uint8_t orig_video_mode; /* 0x06 */ - uint8_t orig_video_cols; /* 0x07 */ - uint8_t flags; /* 0x08 */ - uint8_t unused2; /* 0x09 */ - uint16_t orig_video_ega_bx;/* 0x0a */ - uint16_t unused3; /* 0x0c */ - uint8_t orig_video_lines; /* 0x0e */ - uint8_t orig_video_isVGA; /* 0x0f */ - uint16_t orig_video_points;/* 0x10 */ - - /* VESA graphic mode -- linear frame buffer */ - uint16_t lfb_width; /* 0x12 */ - uint16_t lfb_height; /* 0x14 */ - uint16_t lfb_depth; /* 0x16 */ - uint32_t lfb_base; /* 0x18 */ - uint32_t lfb_size; /* 0x1c */ - uint16_t cl_magic, cl_offset; /* 0x20 */ - uint16_t lfb_linelength; /* 0x24 */ - uint8_t red_size; /* 0x26 */ - uint8_t red_pos; /* 0x27 */ - uint8_t green_size; /* 0x28 */ - uint8_t green_pos; /* 0x29 */ - uint8_t blue_size; /* 0x2a */ - uint8_t blue_pos; /* 0x2b */ - uint8_t rsvd_size; /* 0x2c */ - uint8_t rsvd_pos; /* 0x2d */ - uint16_t vesapm_seg; /* 0x2e */ - uint16_t vesapm_off; /* 0x30 */ - uint16_t pages; /* 0x32 */ - uint16_t vesa_attributes; /* 0x34 */ - uint32_t capabilities; /* 0x36 */ - uint8_t _reserved[6]; /* 0x3a */ -} __attribute__((packed)); - -struct apm_bios_info { - uint16_t version; - uint16_t cseg; - uint32_t offset; - uint16_t cseg_16; - uint16_t dseg; - uint16_t flags; - uint16_t cseg_len; - uint16_t cseg_16_len; - uint16_t dseg_len; -}; - -struct ist_info { - uint32_t signature; - uint32_t command; - uint32_t event; - uint32_t perf_level; -}; - -struct sys_desc_table { - uint16_t length; - uint8_t table[14]; -}; - -struct efi_info { - uint32_t efi_loader_signature; - uint32_t efi_systab; - uint32_t efi_memdesc_size; - uint32_t efi_memdesc_version; - uint32_t efi_memmap; - uint32_t efi_memmap_size; - uint32_t efi_systab_hi; - uint32_t efi_memmap_hi; -}; - -struct edid_info { - unsigned char dummy[128]; -}; - -struct setup_header { - uint8_t setup_sects; - uint16_t root_flags; - uint32_t syssize; - uint16_t ram_size; -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 - uint16_t vid_mode; - uint16_t root_dev; - uint16_t boot_flag; - uint16_t jump; - uint32_t header; - uint16_t version; - uint32_t realmode_swtch; - uint16_t start_sys; - uint16_t kernel_version; - uint8_t type_of_loader; - uint8_t loadflags; -#define LOADED_HIGH (1<<0) -#define QUIET_FLAG (1<<5) -#define KEEP_SEGMENTS (1<<6) -#define CAN_USE_HEAP (1<<7) - uint16_t setup_move_size; - uint32_t code32_start; - uint32_t ramdisk_image; - uint32_t ramdisk_size; - uint32_t bootsect_kludge; - uint16_t heap_end_ptr; - uint8_t ext_loader_ver; - uint8_t ext_loader_type; - uint32_t cmd_line_ptr; - uint32_t initrd_addr_max; - uint32_t kernel_alignment; - uint8_t relocatable_kernel; - uint8_t _pad2[3]; - uint32_t cmdline_size; - uint32_t hardware_subarch; - uint64_t hardware_subarch_data; - uint32_t payload_offset; - uint32_t payload_length; - uint64_t setup_data; -} __attribute__((packed)); - -struct e820entry { - uint64_t addr; /* Start of memory segment */ - uint64_t size; /* Size of memory segment */ - uint32_t type; /* Type of memory segment */ -} __attribute__((packed)); - -struct edd_device_params { - uint16_t length; - uint16_t info_flags; - uint32_t num_default_cylinders; - uint32_t num_default_heads; - uint32_t sectors_per_track; - uint64_t number_of_sectors; - uint16_t bytes_per_sector; - uint32_t dpte_ptr; /* 0xFFFFFFFF for our purposes */ - uint16_t key; /* = 0xBEDD */ - uint8_t device_path_info_length; /* = 44 */ - uint8_t reserved2; - uint16_t reserved3; - uint8_t host_bus_type[4]; - uint8_t interface_type[8]; - union { - struct { - uint16_t base_address; - uint16_t reserved1; - uint32_t reserved2; - } __attribute__ ((packed)) isa; - struct { - uint8_t bus; - uint8_t slot; - uint8_t function; - uint8_t channel; - uint32_t reserved; - } __attribute__ ((packed)) pci; - /* pcix is same as pci */ - struct { - uint64_t reserved; - } __attribute__ ((packed)) ibnd; - struct { - uint64_t reserved; - } __attribute__ ((packed)) xprs; - struct { - uint64_t reserved; - } __attribute__ ((packed)) htpt; - struct { - uint64_t reserved; - } __attribute__ ((packed)) unknown; - } interface_path; - union { - struct { - uint8_t device; - uint8_t reserved1; - uint16_t reserved2; - uint32_t reserved3; - uint64_t reserved4; - } __attribute__ ((packed)) ata; - struct { - uint8_t device; - uint8_t lun; - uint8_t reserved1; - uint8_t reserved2; - uint32_t reserved3; - uint64_t reserved4; - } __attribute__ ((packed)) atapi; - struct { - uint16_t id; - uint64_t lun; - uint16_t reserved1; - uint32_t reserved2; - } __attribute__ ((packed)) scsi; - struct { - uint64_t serial_number; - uint64_t reserved; - } __attribute__ ((packed)) usb; - struct { - uint64_t eui; - uint64_t reserved; - } __attribute__ ((packed)) i1394; - struct { - uint64_t wwid; - uint64_t lun; - } __attribute__ ((packed)) fibre; - struct { - uint64_t identity_tag; - uint64_t reserved; - } __attribute__ ((packed)) i2o; - struct { - uint32_t array_number; - uint32_t reserved1; - uint64_t reserved2; - } __attribute__ ((packed)) raid; - struct { - uint8_t device; - uint8_t reserved1; - uint16_t reserved2; - uint32_t reserved3; - uint64_t reserved4; - } __attribute__ ((packed)) sata; - struct { - uint64_t reserved1; - uint64_t reserved2; - } __attribute__ ((packed)) unknown; - } device_path; - uint8_t reserved4; - uint8_t checksum; -} __attribute__ ((packed)); - -struct edd_info { - uint8_t device; - uint8_t version; - uint16_t interface_support; - uint16_t legacy_max_cylinder; - uint8_t legacy_max_head; - uint8_t legacy_sectors_per_track; - struct edd_device_params params; -} __attribute__ ((packed)); - -struct boot_params { - struct screen_info screen_info; /* 0x000 */ - struct apm_bios_info apm_bios_info; /* 0x040 */ - uint8_t _pad2[4]; /* 0x054 */ - uint64_t tboot_addr; /* 0x058 */ - struct ist_info ist_info; /* 0x060 */ - uint8_t _pad3[16]; /* 0x070 */ - uint8_t hd0_info[16]; /* obsolete! */ /* 0x080 */ - uint8_t hd1_info[16]; /* obsolete! */ /* 0x090 */ - struct sys_desc_table sys_desc_table; /* 0x0a0 */ - uint8_t _pad4[144]; /* 0x0b0 */ - struct edid_info edid_info; /* 0x140 */ - struct efi_info efi_info; /* 0x1c0 */ - uint32_t alt_mem_k; /* 0x1e0 */ - uint32_t scratch; /* Scratch field! */ /* 0x1e4 */ - uint8_t e820_entries; /* 0x1e8 */ - uint8_t eddbuf_entries; /* 0x1e9 */ - uint8_t edd_mbr_sig_buf_entries; /* 0x1ea */ - uint8_t _pad6[6]; /* 0x1eb */ - struct setup_header hdr; /* setup header */ /* 0x1f1 */ - uint8_t _pad7[0x290-0x1f1-sizeof(struct setup_header)]; - uint32_t edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ - struct e820entry e820_map[E820MAX]; /* 0x2d0 */ - uint8_t _pad8[48]; /* 0xcd0 */ - struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */ - uint8_t _pad9[276]; /* 0xeec */ -} __attribute__((packed)); -
diff --git a/libsel4vmm/include/vmm/platform/e820.h b/libsel4vmm/include/vmm/platform/e820.h deleted file mode 100644 index 2288b5a..0000000 --- a/libsel4vmm/include/vmm/platform/e820.h +++ /dev/null
@@ -1,23 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -/* e820 memory region types. */ -#define E820_RAM 1 -#define E820_RESERVED 2 -#define E820_ACPI 3 -#define E820_NVS 4 -#define E820_UNUSABLE 5 - -#define E820_MAX_REGIONS 128 /* E820 supports up to 128. */ -
diff --git a/libsel4vmm/include/vmm/platform/elf_helper.h b/libsel4vmm/include/vmm/platform/elf_helper.h deleted file mode 100644 index a70b7a7..0000000 --- a/libsel4vmm/include/vmm/platform/elf_helper.h +++ /dev/null
@@ -1,24 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include "vmm/vmm.h" -#include <stdio.h> -#include <elf/elf.h> - -/* - Reads the elf header and elf program headers from a file - when given a sufficiently large memory buffer -*/ -int vmm_read_elf_headers(void *buf, vmm_t *vmm, FILE *file, size_t buf_size, elf_t *elf); -
diff --git a/libsel4vmm/include/vmm/platform/guest_memory.h b/libsel4vmm/include/vmm/platform/guest_memory.h deleted file mode 100644 index e8813b5..0000000 --- a/libsel4vmm/include/vmm/platform/guest_memory.h +++ /dev/null
@@ -1,52 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <stdint.h> -#include <vspace/vspace.h> - -typedef struct guest_ram_region { - /* Guest physical start address */ - uintptr_t start; - /* size in bytes */ - size_t size; - /* whether or not this region has been 'allocated' - * an allocated region has initial guest information loaded into it - * this could be elf, initrd modules, etc */ - int allocated; -} guest_ram_region_t; - -typedef struct guest_memory { - /* Guest vspace management. This manages ALL mappings in the guest - * address space. This may include memory that we may tell the guest - * is not present/reserved */ - vspace_t vspace; - /* We maintain all pieces of ram as a sorted list of regions. - * This is memory that we will specifically give the guest as actual RAM */ - int num_ram_regions; - guest_ram_region_t *ram_regions; -} guest_memory_t; - -struct vmm; - -uintptr_t guest_ram_largest_free_region_start(guest_memory_t *guest_memory); -void print_guest_ram_regions(guest_memory_t *guest_memory); -void guest_ram_mark_allocated(guest_memory_t *guest_memory, uintptr_t start, size_t bytes); -uintptr_t guest_ram_allocate(guest_memory_t *guest_memory, size_t bytes); - -int vmm_alloc_guest_device_at(struct vmm *vmm, uintptr_t start, size_t bytes); -uintptr_t vmm_map_guest_device(struct vmm *vmm, uintptr_t paddr, size_t bytes, size_t align); -int vmm_map_guest_device_at(struct vmm *vmm, uintptr_t vaddr, uintptr_t paddr, size_t bytes); -int vmm_alloc_guest_ram_at(struct vmm *vmm, uintptr_t start, size_t bytes); -int vmm_alloc_guest_ram(struct vmm *vmm, size_t bytes, int onetoone); -
diff --git a/libsel4vmm/include/vmm/platform/guest_vspace.h b/libsel4vmm/include/vmm/platform/guest_vspace.h deleted file mode 100644 index d0a1fb3..0000000 --- a/libsel4vmm/include/vmm/platform/guest_vspace.h +++ /dev/null
@@ -1,48 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> -#include <sel4/sel4.h> -#include <vspace/vspace.h> -#include <vka/vka.h> - -/* Constructs a vspace that will duplicate mappings between an ept - * and several IO spaces as well as translation to mappings in the VMM vspace */ -int vmm_get_guest_vspace(vspace_t *loader, vspace_t *vmm_vspace, vspace_t *new_vspace, vka_t *vka, - seL4_CPtr page_directory); - -/* Helpers for use with touch below */ -int vmm_guest_get_phys_data_help(uintptr_t addr, void *vaddr, size_t size, - size_t offset, void *cookie); - -int vmm_guest_set_phys_data_help(uintptr_t addr, void *vaddr, size_t size, - size_t offset, void *cookie); - -/* callback used for each portion of vmm_guest_vspace_touch. - * if the return value is non zero this signals the parent - * loop to stop and return the given value */ -typedef int (*vmm_guest_vspace_touch_callback)(uintptr_t guest_phys, void *vmm_vaddr, size_t size, size_t offset, - void *cookie); - -/* 'touch' a series of guest physical addresses by invoking the callback function - * each equivalent range of addresses in the vmm vspace */ -int vmm_guest_vspace_touch(vspace_t *guest_vspace, uintptr_t addr, size_t size, - vmm_guest_vspace_touch_callback callback, void *cookie); - -#ifdef CONFIG_IOMMU -/* Attach an additional IO space to the vspace */ -int vmm_guest_vspace_add_iospace(vspace_t *loader, vspace_t *vspace, seL4_CPtr iospace); -#endif -
diff --git a/libsel4vmm/include/vmm/platform/ioports.h b/libsel4vmm/include/vmm/platform/ioports.h deleted file mode 100644 index 3bc928f..0000000 --- a/libsel4vmm/include/vmm/platform/ioports.h +++ /dev/null
@@ -1,68 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -/* Some IO ports in x86 systems. */ - -/*first programmable interrupt controller, master*/ -#define X86_IO_PIC_1_START 0x20 -#define X86_IO_PIC_1_END 0x21 - -/*programmable interval timer*/ -#define X86_IO_PIT_START 0x40 -#define X86_IO_PIT_END 0x5f - -/*PS/2 controller*/ -#define X86_IO_PS2C_START 0x60 -#define X86_IO_PS2C_END 0x64 - -/*read time clock / CMOS, NMI mask*/ -#define X86_IO_RTC_START 0x70 -#define X86_IO_RTC_END 0x7f - -/*ISA DMA*/ -#define X86_IO_ISA_DMA_START 0x80 -#define X86_IO_ISA_DMA_END 0x8f - -/*second programmable interrupt controller, slave*/ -#define X86_IO_PIC_2_START 0xa0 -#define X86_IO_PIC_2_END 0xa1 - -/*POS Programmable Option Select (PS/2)*/ -#define X86_IO_POS_START 0x100 -#define X86_IO_POS_END 0x10F - -/*serial port 2*/ -#define X86_IO_SERIAL_2_START 0x2f8 -#define X86_IO_SERIAL_2_END 0x2ff - -/*serial port 3*/ -#define X86_IO_SERIAL_3_START 0x3e8 -#define X86_IO_SERIAL_3_END 0x3ef - -/*serial port 1*/ -#define X86_IO_SERIAL_1_START 0x3f8 -#define X86_IO_SERIAL_1_END 0x3ff - -/*serial port 4*/ -#define X86_IO_SERIAL_4_START 0x2e8 -#define X86_IO_SERIAL_4_END 0x2ef - -/*ELCR (edge/level control register) for IRQ line*/ -#define X86_IO_ELCR_START 0x4d0 -#define X86_IO_ELCR_END 0x4d1 - -/*pci configuration space*/ -#define X86_IO_PCI_CONFIG_START 0xcf8 -#define X86_IO_PCI_CONFIG_END 0xcff -
diff --git a/libsel4vmm/include/vmm/platform/vmcs.h b/libsel4vmm/include/vmm/platform/vmcs.h deleted file mode 100644 index 802496a..0000000 --- a/libsel4vmm/include/vmm/platform/vmcs.h +++ /dev/null
@@ -1,103 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -/*control fields in vmcs*/ -#define VMX_GUEST_ES_SELECTOR 0x00000800 -#define VMX_GUEST_CS_SELECTOR 0x00000802 -#define VMX_GUEST_SS_SELECTOR 0x00000804 -#define VMX_GUEST_DS_SELECTOR 0x00000806 -#define VMX_GUEST_FS_SELECTOR 0x00000808 -#define VMX_GUEST_GS_SELECTOR 0x0000080A -#define VMX_GUEST_LDTR_SELECTOR 0x0000080C -#define VMX_GUEST_TR_SELECTOR 0x0000080E -#define VMX_GUEST_DEBUGCTRL 0x00002802 -#define VMX_GUEST_PAT 0x00002804 -#define VMX_GUEST_EFER 0x00002806 -#define VMX_GUEST_PERF_GLOBAL_CTRL 0x00002808 -#define VMX_GUEST_ES_LIMIT 0x00004800 -#define VMX_GUEST_CS_LIMIT 0x00004802 -#define VMX_GUEST_SS_LIMIT 0x00004804 -#define VMX_GUEST_DS_LIMIT 0x00004806 -#define VMX_GUEST_FS_LIMIT 0x00004808 -#define VMX_GUEST_GS_LIMIT 0x0000480A -#define VMX_GUEST_LDTR_LIMIT 0x0000480C -#define VMX_GUEST_TR_LIMIT 0x0000480E -#define VMX_GUEST_GDTR_LIMIT 0x00004810 -#define VMX_GUEST_IDTR_LIMIT 0x00004812 -#define VMX_GUEST_ES_ACCESS_RIGHTS 0x00004814 -#define VMX_GUEST_CS_ACCESS_RIGHTS 0x00004816 -#define VMX_GUEST_SS_ACCESS_RIGHTS 0x00004818 -#define VMX_GUEST_DS_ACCESS_RIGHTS 0x0000481A -#define VMX_GUEST_FS_ACCESS_RIGHTS 0x0000481C -#define VMX_GUEST_GS_ACCESS_RIGHTS 0x0000481E -#define VMX_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 -#define VMX_GUEST_TR_ACCESS_RIGHTS 0x00004822 -#define VMX_GUEST_INTERRUPTABILITY 0x00004824 -#define VMX_GUEST_ACTIVITY 0x00004826 -#define VMX_GUEST_SMBASE 0x00004828 -#define VMX_GUEST_SYSENTER_CS 0x0000482A -#define VMX_GUEST_CR0 0x00006800 -#define VMX_GUEST_CR3 0x00006802 -#define VMX_GUEST_CR4 0x00006804 -#define VMX_GUEST_ES_BASE 0x00006806 -#define VMX_GUEST_CS_BASE 0x00006808 -#define VMX_GUEST_SS_BASE 0x0000680A -#define VMX_GUEST_DS_BASE 0x0000680C -#define VMX_GUEST_FS_BASE 0x0000680E -#define VMX_GUEST_GS_BASE 0x00006810 -#define VMX_GUEST_LDTR_BASE 0x00006812 -#define VMX_GUEST_TR_BASE 0x00006814 -#define VMX_GUEST_GDTR_BASE 0x00006816 -#define VMX_GUEST_IDTR_BASE 0x00006818 -#define VMX_GUEST_PENDING_DEBUG_EXCEPTIONS 0x00006822 -#define VMX_GUEST_DR7 0x0000681A -#define VMX_GUEST_RSP 0x0000681C -#define VMX_GUEST_RIP 0x0000681E -#define VMX_GUEST_RFLAGS 0x00006820 -#define VMX_GUEST_SYSENTER_ESP 0x00006824 -#define VMX_GUEST_SYSENTER_EIP 0x00006826 -#define VMX_GUEST_VMX_PREEMPTION_TIMER_VALUE 0x0000482E - -#define VMX_DATA_INSTRUCTION_ERROR 0x00004400 -#define VMX_DATA_EXIT_REASON 0x00004402 -#define VMX_DATA_EXIT_INTERRUPT_INFO 0x00004404 -#define VMX_DATA_EXIT_INTERRUPT_ERROR 0x00004406 -#define VMX_DATA_IDT_VECTOR_INFO 0x00004408 -#define VMX_DATA_IDT_VECTOR_ERROR 0x0000440A -#define VMX_DATA_EXIT_INSTRUCTION_LENGTH 0x0000440C -#define VMX_DATA_EXIT_INSTRUCTION_INFO 0x0000440E - -#define VMX_DATA_EXIT_QUALIFICATION 0x00006400 -#define VMX_DATA_IO_RCX 0x00006402 -#define VMX_DATA_IO_RSI 0x00006404 -#define VMX_DATA_IO_RDI 0x00006406 -#define VMX_DATA_IO_RIP 0x00006408 -#define VMX_DATA_GUEST_LINEAR_ADDRESS 0x0000640A -#define VMX_DATA_GUEST_PHYSICAL 0x00002400 - -#define VMX_CONTROL_CR0_MASK 0x00006000 -#define VMX_CONTROL_CR4_MASK 0x00006002 -#define VMX_CONTROL_CR0_READ_SHADOW 0x00006004 -#define VMX_CONTROL_CR4_READ_SHADOW 0x00006006 - -#define VMX_CONTROL_PIN_EXECUTION_CONTROLS 0x00004000 -#define VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS 0x00004002 - #define VMX_CONTROL_PPC_HLT_EXITING BIT(7) - #define VMX_CONTROL_PPC_CR3_LOAD_EXITING BIT(15) - #define VMX_CONTROL_PPC_CR3_STORE_EXITING BIT(16) -#define VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS 0x0000401E -#define VMX_CONTROL_EXCEPTION_BITMAP 0x00004004 -#define VMX_CONTROL_EXIT_CONTROLS 0x0000400C -#define VMX_CONTROL_ENTRY_INTERRUPTION_INFO 0x00004016 -#define VMX_CONTROL_ENTRY_EXCEPTION_ERROR_CODE 0x00004018
diff --git a/libsel4vmm/include/vmm/platform/vmexit.h b/libsel4vmm/include/vmm/platform/vmexit.h deleted file mode 100644 index 9361cb1..0000000 --- a/libsel4vmm/include/vmm/platform/vmexit.h +++ /dev/null
@@ -1,97 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 - -#define EXIT_REASON_EXCEPTION_NMI 0 -#define EXIT_REASON_EXTERNAL_INTERRUPT 1 -#define EXIT_REASON_TRIPLE_FAULT 2 - -#define EXIT_REASON_PENDING_INTERRUPT 7 -#define EXIT_REASON_NMI_WINDOW 8 -#define EXIT_REASON_TASK_SWITCH 9 -#define EXIT_REASON_CPUID 10 -#define EXIT_REASON_HLT 12 -#define EXIT_REASON_INVD 13 -#define EXIT_REASON_INVLPG 14 -#define EXIT_REASON_RDPMC 15 -#define EXIT_REASON_RDTSC 16 -#define EXIT_REASON_VMCALL 18 -#define EXIT_REASON_VMCLEAR 19 -#define EXIT_REASON_VMLAUNCH 20 -#define EXIT_REASON_VMPTRLD 21 -#define EXIT_REASON_VMPTRST 22 -#define EXIT_REASON_VMREAD 23 -#define EXIT_REASON_VMRESUME 24 -#define EXIT_REASON_VMWRITE 25 -#define EXIT_REASON_VMOFF 26 -#define EXIT_REASON_VMON 27 -#define EXIT_REASON_CR_ACCESS 28 -#define EXIT_REASON_DR_ACCESS 29 -#define EXIT_REASON_IO_INSTRUCTION 30 -#define EXIT_REASON_MSR_READ 31 -#define EXIT_REASON_MSR_WRITE 32 -#define EXIT_REASON_INVALID_STATE 33 -#define EXIT_REASON_MWAIT_INSTRUCTION 36 -#define EXIT_REASON_MONITOR_INSTRUCTION 39 -#define EXIT_REASON_PAUSE_INSTRUCTION 40 -#define EXIT_REASON_MCE_DURING_VMENTRY 41 -#define EXIT_REASON_TPR_BELOW_THRESHOLD 43 -#define EXIT_REASON_APIC_ACCESS 44 -#define EXIT_REASON_EPT_VIOLATION 48 -#define EXIT_REASON_EPT_MISCONFIG 49 -#define EXIT_REASON_VMX_TIMER 52 -#define EXIT_REASON_WBINVD 54 -#define EXIT_REASON_XSETBV 55 -#define EXIT_REASON_INVPCID 58 - -#define VMM_EXIT_REASON_NUM 59 - -#define VMX_EXIT_REASONS \ - { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ - { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \ - { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \ - { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \ - { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \ - { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \ - { EXIT_REASON_CPUID, "CPUID" }, \ - { EXIT_REASON_HLT, "HLT" }, \ - { EXIT_REASON_INVLPG, "INVLPG" }, \ - { EXIT_REASON_RDPMC, "RDPMC" }, \ - { EXIT_REASON_RDTSC, "RDTSC" }, \ - { EXIT_REASON_VMCALL, "VMCALL" }, \ - { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \ - { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \ - { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \ - { EXIT_REASON_VMPTRST, "VMPTRST" }, \ - { EXIT_REASON_VMREAD, "VMREAD" }, \ - { EXIT_REASON_VMRESUME, "VMRESUME" }, \ - { EXIT_REASON_VMWRITE, "VMWRITE" }, \ - { EXIT_REASON_VMOFF, "VMOFF" }, \ - { EXIT_REASON_VMON, "VMON" }, \ - { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \ - { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \ - { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \ - { EXIT_REASON_MSR_READ, "MSR_READ" }, \ - { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \ - { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \ - { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \ - { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \ - { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ - { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ - { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ - { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ - { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ - { EXIT_REASON_WBINVD, "WBINVD" } -
diff --git a/libsel4vmm/include/vmm/processor/apicdef.h b/libsel4vmm/include/vmm/processor/apicdef.h deleted file mode 100644 index 64c7db0..0000000 --- a/libsel4vmm/include/vmm/processor/apicdef.h +++ /dev/null
@@ -1,460 +0,0 @@ -/* @TAG(CUSTOM) *//* Taken from Linux kernel 3.18 */ - -/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#pragma once - -/* - * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) - * - * Alan Cox <Alan.Cox@linux.org>, 1995. - * Ingo Molnar <mingo@redhat.com>, 1999, 2000 - */ - -#define IO_APIC_DEFAULT_PHYS_BASE 0xfec00000 -#define APIC_DEFAULT_PHYS_BASE 0xfee00000 - -/* - * This is the IO-APIC register space as specified - * by Intel docs: - */ -#define IO_APIC_SLOT_SIZE 1024 - -#define APIC_ID 0x20 - -#define APIC_LVR 0x30 -#define APIC_LVR_MASK 0xFF00FF -#define APIC_LVR_DIRECTED_EOI (BIT(24)) -#define GET_APIC_VERSION(x) ((x) & 0xFFu) -#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFFu) -#ifdef CONFIG_X86_32 -# define APIC_INTEGRATED(x) ((x) & 0xF0u) -#else -# define APIC_INTEGRATED(x) (1) -#endif -#define APIC_XAPIC(x) ((x) >= 0x14) -#define APIC_EXT_SPACE(x) ((x) & 0x80000000) -#define APIC_TASKPRI 0x80 -#define APIC_TPRI_MASK 0xFFu -#define APIC_ARBPRI 0x90 -#define APIC_ARBPRI_MASK 0xFFu -#define APIC_PROCPRI 0xA0 -#define APIC_EOI 0xB0 -#define APIC_EOI_ACK 0x0 /* Docs say 0 for future compat. */ -#define APIC_RRR 0xC0 -#define APIC_LDR 0xD0 -#define APIC_LDR_MASK (0xFFu << 24) -#define GET_APIC_LOGICAL_ID(x) (((x) >> 24) & 0xFFu) -#define SET_APIC_LOGICAL_ID(x) (((x) << 24)) -#define APIC_ALL_CPUS 0xFFu -#define APIC_DFR 0xE0 -#define APIC_DFR_CLUSTER 0x0FFFFFFFul -#define APIC_DFR_FLAT 0xFFFFFFFFul -#define APIC_SPIV 0xF0 -#define APIC_SPIV_DIRECTED_EOI (BIT(12)) -#define APIC_SPIV_FOCUS_DISABLED (BIT(9)) -#define APIC_SPIV_APIC_ENABLED (BIT(8)) -#define APIC_ISR 0x100 -#define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */ -#define APIC_TMR 0x180 -#define APIC_IRR 0x200 -#define APIC_ESR 0x280 -#define APIC_ESR_SEND_CS 0x00001 -#define APIC_ESR_RECV_CS 0x00002 -#define APIC_ESR_SEND_ACC 0x00004 -#define APIC_ESR_RECV_ACC 0x00008 -#define APIC_ESR_SENDILL 0x00020 -#define APIC_ESR_RECVILL 0x00040 -#define APIC_ESR_ILLREGA 0x00080 -#define APIC_LVTCMCI 0x2f0 -#define APIC_ICR 0x300 -#define APIC_DEST_SELF 0x40000 -#define APIC_DEST_ALLINC 0x80000 -#define APIC_DEST_ALLBUT 0xC0000 -#define APIC_ICR_RR_MASK 0x30000 -#define APIC_ICR_RR_INVALID 0x00000 -#define APIC_ICR_RR_INPROG 0x10000 -#define APIC_ICR_RR_VALID 0x20000 -#define APIC_INT_LEVELTRIG 0x08000 -#define APIC_INT_ASSERT 0x04000 -#define APIC_ICR_BUSY 0x01000 -#define APIC_DEST_LOGICAL 0x00800 -#define APIC_DEST_PHYSICAL 0x00000 -#define APIC_DM_FIXED 0x00000 -#define APIC_DM_FIXED_MASK 0x00700 -#define APIC_DM_LOWEST 0x00100 -#define APIC_DM_SMI 0x00200 -#define APIC_DM_REMRD 0x00300 -#define APIC_DM_NMI 0x00400 -#define APIC_DM_INIT 0x00500 -#define APIC_DM_STARTUP 0x00600 -#define APIC_DM_EXTINT 0x00700 -#define APIC_VECTOR_MASK 0x000FF -#define APIC_ICR2 0x310 -#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF) -#define SET_APIC_DEST_FIELD(x) ((x) << 24) -#define APIC_LVTT 0x320 -#define APIC_LVTTHMR 0x330 -#define APIC_LVTPC 0x340 -#define APIC_LVT0 0x350 -#define APIC_LVT_TIMER_BASE_MASK (0x3 << 18) -#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3) -#define SET_APIC_TIMER_BASE(x) (((x) << 18)) -#define APIC_TIMER_BASE_CLKIN 0x0 -#define APIC_TIMER_BASE_TMBASE 0x1 -#define APIC_TIMER_BASE_DIV 0x2 -#define APIC_LVT_TIMER_ONESHOT (0 << 17) -#define APIC_LVT_TIMER_PERIODIC (BIT(17)) -#define APIC_LVT_TIMER_TSCDEADLINE (2 << 17) -#define APIC_LVT_MASKED (BIT(16)) -#define APIC_LVT_LEVEL_TRIGGER (BIT(15)) -#define APIC_LVT_REMOTE_IRR (BIT(14)) -#define APIC_INPUT_POLARITY (BIT(13)) -#define APIC_SEND_PENDING (BIT(12)) -#define APIC_MODE_MASK 0x700 -#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7) -#define SET_APIC_DELIVERY_MODE(x, y) (((x) & ~0x700) | ((y) << 8)) -#define APIC_MODE_FIXED 0x0 -#define APIC_MODE_NMI 0x4 -#define APIC_MODE_EXTINT 0x7 -#define APIC_LVT1 0x360 -#define APIC_LVTERR 0x370 -#define APIC_TMICT 0x380 -#define APIC_TMCCT 0x390 -#define APIC_TDCR 0x3E0 -#define APIC_SELF_IPI 0x3F0 -#define APIC_TDR_DIV_TMBASE (BIT(2)) -#define APIC_TDR_DIV_1 0xB -#define APIC_TDR_DIV_2 0x0 -#define APIC_TDR_DIV_4 0x1 -#define APIC_TDR_DIV_8 0x2 -#define APIC_TDR_DIV_16 0x3 -#define APIC_TDR_DIV_32 0x8 -#define APIC_TDR_DIV_64 0x9 -#define APIC_TDR_DIV_128 0xA -#define APIC_EFEAT 0x400 -#define APIC_ECTRL 0x410 -#define APIC_EILVTn(n) (0x500 + 0x10 * n) -#define APIC_EILVT_NR_AMD_K8 1 /* # of extended interrupts */ -#define APIC_EILVT_NR_AMD_10H 4 -#define APIC_EILVT_NR_MAX APIC_EILVT_NR_AMD_10H -#define APIC_EILVT_LVTOFF(x) (((x) >> 4) & 0xF) -#define APIC_EILVT_MSG_FIX 0x0 -#define APIC_EILVT_MSG_SMI 0x2 -#define APIC_EILVT_MSG_NMI 0x4 -#define APIC_EILVT_MSG_EXT 0x7 -#define APIC_EILVT_MASKED (BIT(16)) - -#define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) -#define APIC_BASE_MSR 0x800 -#define XAPIC_ENABLE (1UL << 11) -#define X2APIC_ENABLE (1UL << 10) - -#ifdef CONFIG_X86_32 -# define MAX_IO_APICS 64 -# define MAX_LOCAL_APIC 256 -#else -# define MAX_IO_APICS 128 -# define MAX_LOCAL_APIC 32768 -#endif - -/* - * All x86-64 systems are xAPIC compatible. - * In the following, "apicid" is a physical APIC ID. - */ -#define XAPIC_DEST_CPUS_SHIFT 4 -#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) -#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) -#define APIC_CLUSTER(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) -#define APIC_CLUSTERID(apicid) (APIC_CLUSTER(apicid) >> XAPIC_DEST_CPUS_SHIFT) -#define APIC_CPUID(apicid) ((apicid) & XAPIC_DEST_CPUS_MASK) -#define NUM_APIC_CLUSTERS ((BAD_APICID + 1) >> XAPIC_DEST_CPUS_SHIFT) - -/* - * the local APIC register structure, memory mapped. Not terribly well - * tested, but we might eventually use this one in the future - the - * problem why we cannot use it right now is the P5 APIC, it has an - * errata which cannot take 8-bit reads and writes, only 32-bit ones ... - */ -#define u32 unsigned int - -struct local_apic_regs { - -/*000*/ struct { u32 __reserved[4]; } __reserved_01; - -/*010*/ struct { u32 __reserved[4]; } __reserved_02; - -/*020*/ struct { /* APIC ID Register */ - u32 __reserved_1 : 24, - phys_apic_id : 4, - __reserved_2 : 4; - u32 __reserved[3]; - } id; - -/*030*/ const - struct { /* APIC Version Register */ - u32 version : 8, - __reserved_1 : 8, - max_lvt : 8, - __reserved_2 : 8; - u32 __reserved[3]; - } version; - -/*040*/ struct { u32 __reserved[4]; } __reserved_03; - -/*050*/ struct { u32 __reserved[4]; } __reserved_04; - -/*060*/ struct { u32 __reserved[4]; } __reserved_05; - -/*070*/ struct { u32 __reserved[4]; } __reserved_06; - -/*080*/ struct { /* Task Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } tpr; - -/*090*/ const - struct { /* Arbitration Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } apr; - -/*0A0*/ const - struct { /* Processor Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } ppr; - -/*0B0*/ struct { /* End Of Interrupt Register */ - u32 eoi; - u32 __reserved[3]; - } eoi; - -/*0C0*/ struct { u32 __reserved[4]; } __reserved_07; - -/*0D0*/ struct { /* Logical Destination Register */ - u32 __reserved_1 : 24, - logical_dest : 8; - u32 __reserved_2[3]; - } ldr; - -/*0E0*/ struct { /* Destination Format Register */ - u32 __reserved_1 : 28, - model : 4; - u32 __reserved_2[3]; - } dfr; - -/*0F0*/ struct { /* Spurious Interrupt Vector Register */ - u32 spurious_vector : 8, - apic_enabled : 1, - focus_cpu : 1, - __reserved_2 : 22; - u32 __reserved_3[3]; - } svr; - -/*100*/ struct { /* In Service Register */ -/*170*/ u32 bitfield; - u32 __reserved[3]; - } isr [8]; - -/*180*/ struct { /* Trigger Mode Register */ -/*1F0*/ u32 bitfield; - u32 __reserved[3]; - } tmr [8]; - -/*200*/ struct { /* Interrupt Request Register */ -/*270*/ u32 bitfield; - u32 __reserved[3]; - } irr [8]; - -/*280*/ union { /* Error Status Register */ - struct { - u32 send_cs_error : 1, - receive_cs_error : 1, - send_accept_error : 1, - receive_accept_error : 1, - __reserved_1 : 1, - send_illegal_vector : 1, - receive_illegal_vector : 1, - illegal_register_address : 1, - __reserved_2 : 24; - u32 __reserved_3[3]; - } error_bits; - struct { - u32 errors; - u32 __reserved_3[3]; - } all_errors; - } esr; - -/*290*/ struct { u32 __reserved[4]; } __reserved_08; - -/*2A0*/ struct { u32 __reserved[4]; } __reserved_09; - -/*2B0*/ struct { u32 __reserved[4]; } __reserved_10; - -/*2C0*/ struct { u32 __reserved[4]; } __reserved_11; - -/*2D0*/ struct { u32 __reserved[4]; } __reserved_12; - -/*2E0*/ struct { u32 __reserved[4]; } __reserved_13; - -/*2F0*/ struct { u32 __reserved[4]; } __reserved_14; - -/*300*/ struct { /* Interrupt Command Register 1 */ - u32 vector : 8, - delivery_mode : 3, - destination_mode : 1, - delivery_status : 1, - __reserved_1 : 1, - level : 1, - trigger : 1, - __reserved_2 : 2, - shorthand : 2, - __reserved_3 : 12; - u32 __reserved_4[3]; - } icr1; - -/*310*/ struct { /* Interrupt Command Register 2 */ - union { - u32 __reserved_1 : 24, - phys_dest : 4, - __reserved_2 : 4; - u32 __reserved_3 : 24, - logical_dest : 8; - } dest; - u32 __reserved_4[3]; - } icr2; - -/*320*/ struct { /* LVT - Timer */ - u32 vector : 8, - __reserved_1 : 4, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - timer_mode : 1, - __reserved_3 : 14; - u32 __reserved_4[3]; - } lvt_timer; - -/*330*/ struct { /* LVT - Thermal Sensor */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_thermal; - -/*340*/ struct { /* LVT - Performance Counter */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_pc; - -/*350*/ struct { /* LVT - LINT0 */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - polarity : 1, - remote_irr : 1, - trigger : 1, - mask : 1, - __reserved_2 : 15; - u32 __reserved_3[3]; - } lvt_lint0; - -/*360*/ struct { /* LVT - LINT1 */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - polarity : 1, - remote_irr : 1, - trigger : 1, - mask : 1, - __reserved_2 : 15; - u32 __reserved_3[3]; - } lvt_lint1; - -/*370*/ struct { /* LVT - Error */ - u32 vector : 8, - __reserved_1 : 4, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_error; - -/*380*/ struct { /* Timer Initial Count Register */ - u32 initial_count; - u32 __reserved_2[3]; - } timer_icr; - -/*390*/ const - struct { /* Timer Current Count Register */ - u32 curr_count; - u32 __reserved_2[3]; - } timer_ccr; - -/*3A0*/ struct { u32 __reserved[4]; } __reserved_16; - -/*3B0*/ struct { u32 __reserved[4]; } __reserved_17; - -/*3C0*/ struct { u32 __reserved[4]; } __reserved_18; - -/*3D0*/ struct { u32 __reserved[4]; } __reserved_19; - -/*3E0*/ struct { /* Timer Divide Configuration Register */ - u32 divisor : 4, - __reserved_1 : 28; - u32 __reserved_2[3]; - } timer_dcr; - -/*3F0*/ struct { u32 __reserved[4]; } __reserved_20; - -} __attribute__ ((packed)); - -#undef u32 - -#ifdef CONFIG_X86_32 - #define BAD_APICID 0xFFu -#else - #define BAD_APICID 0xFFFFu -#endif - -enum ioapic_irq_destination_types { - dest_Fixed = 0, - dest_LowestPrio = 1, - dest_SMI = 2, - dest__reserved_1 = 3, - dest_NMI = 4, - dest_INIT = 5, - dest__reserved_2 = 6, - dest_ExtINT = 7 -}; -
diff --git a/libsel4vmm/include/vmm/processor/cpufeature.h b/libsel4vmm/include/vmm/processor/cpufeature.h deleted file mode 100644 index 2258d9f..0000000 --- a/libsel4vmm/include/vmm/processor/cpufeature.h +++ /dev/null
@@ -1,218 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* This file contains macros for CPU features defined in x86. - * Ported from arch/x86/include/asm/cpufeature.h Linux kernel source 3.8.8. - * Authors: - * Qian Ge - */ - -#pragma once - -/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ -#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ -#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ -#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ -#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ -#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ -#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers */ -#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ -#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Exception */ -#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ -#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ -#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ -#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ -#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ -#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ -#define X86_FEATURE_CMOV (0*32+15) /* CMOV instructions */ - /* (plus FCMOVcc, FCOMI with FPU) */ -#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ -#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ -#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ -#define X86_FEATURE_CLFLSH (0*32+19) /* "clflush" CLFLUSH instruction */ -#define X86_FEATURE_DS (0*32+21) /* "dts" Debug Store */ -#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ -#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ -#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ -#define X86_FEATURE_XMM (0*32+25) /* "sse" */ -#define X86_FEATURE_XMM2 (0*32+26) /* "sse2" */ -#define X86_FEATURE_SELFSNOOP (0*32+27) /* "ss" CPU self snoop */ -#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ -#define X86_FEATURE_ACC (0*32+29) /* "tm" Automatic clock control */ -#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ -#define X86_FEATURE_PBE (0*32+31) /* Pending Break Enable */ - -/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ -/* Don't duplicate feature flags which are redundant with Intel! */ -#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ -#define X86_FEATURE_MP (1*32+19) /* MP Capable. */ -#define X86_FEATURE_NX (1*32+20) /* Execute Disable */ -#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ -#define X86_FEATURE_FXSR_OPT (1*32+25) /* FXSAVE/FXRSTOR optimizations */ -#define X86_FEATURE_GBPAGES (1*32+26) /* "pdpe1gb" GB pages */ -#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */ -#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ -#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ -#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ - -/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ -#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ -#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ -#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ - -/* Other features, Linux-defined mapping, word 3 */ -/* This range is used for feature bits which conflict or are synthesized */ -#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ -#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ -#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ -#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ -/* cpu types for specific tunings: */ -#define X86_FEATURE_K8 (3*32+ 4) /* "" Opteron, Athlon64 */ -#define X86_FEATURE_K7 (3*32+ 5) /* "" Athlon */ -#define X86_FEATURE_P3 (3*32+ 6) /* "" P3 */ -#define X86_FEATURE_P4 (3*32+ 7) /* "" P4 */ -#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ -#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ -#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* "" FXSAVE leaks FOP/FIP/FOP */ -#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ -#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ -#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ -#define X86_FEATURE_SYSCALL32 (3*32+14) /* "" syscall in ia32 userspace */ -#define X86_FEATURE_SYSENTER32 (3*32+15) /* "" sysenter in ia32 userspace */ -#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well */ -#define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* "" Mfence synchronizes RDTSC */ -#define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* "" Lfence synchronizes RDTSC */ -#define X86_FEATURE_11AP (3*32+19) /* "" Bad local APIC aka 11AP */ -#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ - /* 21 available, was AMD_C1E */ -#define X86_FEATURE_XTOPOLOGY (3*32+22) /* cpu topology enum extensions */ -#define X86_FEATURE_TSC_RELIABLE (3*32+23) /* TSC is known to be reliable */ -#define X86_FEATURE_NONSTOP_TSC (3*32+24) /* TSC does not stop in C states */ -#define X86_FEATURE_CLFLUSH_MONITOR (3*32+25) /* "" clflush reqd with monitor */ -#define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ -#define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */ -#define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */ -#define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ -#define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ -#define X86_FEATURE_PCLMULQDQ (4*32+ 1) /* PCLMULQDQ instruction */ -#define X86_FEATURE_DTES64 (4*32+ 2) /* 64-bit Debug Store */ -#define X86_FEATURE_MWAIT (4*32+ 3) /* "monitor" Monitor/Mwait support */ -#define X86_FEATURE_DSCPL (4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */ -#define X86_FEATURE_VMX (4*32+ 5) /* Hardware virtualization */ -#define X86_FEATURE_SMX (4*32+ 6) /* Safer mode */ -#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ -#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ -#define X86_FEATURE_SSSE3 (4*32+ 9) /* Supplemental SSE-3 */ -#define X86_FEATURE_CID (4*32+10) /* Context ID */ -#define X86_FEATURE_FMA (4*32+12) /* Fused multiply-add */ -#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ -#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ -#define X86_FEATURE_PDCM (4*32+15) /* Performance Capabilities */ -#define X86_FEATURE_PCID (4*32+17) /* Process Context Identifiers */ -#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ -#define X86_FEATURE_XMM4_1 (4*32+19) /* "sse4_1" SSE-4.1 */ -#define X86_FEATURE_XMM4_2 (4*32+20) /* "sse4_2" SSE-4.2 */ -#define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */ -#define X86_FEATURE_MOVBE (4*32+22) /* MOVBE instruction */ -#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */ -#define X86_FEATURE_TSC_DEADLINE_TIMER (4*32+24) /* Tsc deadline timer */ -#define X86_FEATURE_AES (4*32+25) /* AES instructions */ -#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ -#define X86_FEATURE_OSXSAVE (4*32+27) /* "" XSAVE enabled in the OS */ -#define X86_FEATURE_AVX (4*32+28) /* Advanced Vector Extensions */ -#define X86_FEATURE_F16C (4*32+29) /* 16-bit fp conversions */ -#define X86_FEATURE_RDRAND (4*32+30) /* The RDRAND instruction */ -#define X86_FEATURE_HYPERVISOR (4*32+31) /* Running on a hypervisor */ - -/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ -#define X86_FEATURE_XSTORE (5*32+ 2) /* "rng" RNG present (xstore) */ -#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* "rng_en" RNG enabled */ -#define X86_FEATURE_XCRYPT (5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */ -#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* "ace_en" on-CPU crypto enabled */ -#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */ -#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */ -#define X86_FEATURE_PHE (5*32+10) /* PadLock Hash Engine */ -#define X86_FEATURE_PHE_EN (5*32+11) /* PHE enabled */ -#define X86_FEATURE_PMM (5*32+12) /* PadLock Montgomery Multiplier */ -#define X86_FEATURE_PMM_EN (5*32+13) /* PMM enabled */ - -/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ -#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ -#define X86_FEATURE_SVM (6*32+ 2) /* Secure virtual machine */ -#define X86_FEATURE_EXTAPIC (6*32+ 3) /* Extended APIC space */ -#define X86_FEATURE_CR8_LEGACY (6*32+ 4) /* CR8 in 32-bit mode */ -#define X86_FEATURE_ABM (6*32+ 5) /* Advanced bit manipulation */ -#define X86_FEATURE_SSE4A (6*32+ 6) /* SSE-4A */ -#define X86_FEATURE_MISALIGNSSE (6*32+ 7) /* Misaligned SSE mode */ -#define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */ -#define X86_FEATURE_OSVW (6*32+ 9) /* OS Visible Workaround */ -#define X86_FEATURE_IBS (6*32+10) /* Instruction Based Sampling */ -#define X86_FEATURE_XOP (6*32+11) /* extended AVX instructions */ -#define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */ -#define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ -#define X86_FEATURE_LWP (6*32+15) /* Light Weight Profiling */ -#define X86_FEATURE_FMA4 (6*32+16) /* 4 operands MAC instructions */ -#define X86_FEATURE_TCE (6*32+17) /* translation cache extension */ -#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */ -#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */ -#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */ -#define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */ - -/* - * Auxiliary flags: Linux defined - For features scattered in various - * CPUID levels like 0x6, 0xA etc, word 7 - */ -#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ -#define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */ -#define X86_FEATURE_CPB (7*32+ 2) /* AMD Core Performance Boost */ -#define X86_FEATURE_EPB (7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ -#define X86_FEATURE_XSAVEOPT (7*32+ 4) /* Optimized Xsave */ -#define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ -#define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ -#define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */ -#define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ - -/* Virtualization flags: Linux defined, word 8 */ -#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ -#define X86_FEATURE_VNMI (8*32+ 1) /* Intel Virtual NMI */ -#define X86_FEATURE_FLEXPRIORITY (8*32+ 2) /* Intel FlexPriority */ -#define X86_FEATURE_EPT (8*32+ 3) /* Intel Extended Page Table */ -#define X86_FEATURE_VPID (8*32+ 4) /* Intel Virtual Processor ID */ -#define X86_FEATURE_NPT (8*32+ 5) /* AMD Nested Page Table support */ -#define X86_FEATURE_LBRV (8*32+ 6) /* AMD LBR Virtualization support */ -#define X86_FEATURE_SVML (8*32+ 7) /* "svm_lock" AMD SVM locking MSR */ -#define X86_FEATURE_NRIPS (8*32+ 8) /* "nrip_save" AMD SVM next_rip save */ -#define X86_FEATURE_TSCRATEMSR (8*32+ 9) /* "tsc_scale" AMD TSC scaling support */ -#define X86_FEATURE_VMCBCLEAN (8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */ -#define X86_FEATURE_FLUSHBYASID (8*32+11) /* AMD flush-by-ASID support */ -#define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ -#define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ -#define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ - -/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ -#define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ -#define X86_FEATURE_TSC_ADJUST (9*32+ 1) /* TSC adjustment MSR 0x3b */ -#define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation extensions */ -#define X86_FEATURE_HLE (9*32+ 4) /* Hardware Lock Elision */ -#define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */ -#define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution Protection */ -#define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation extensions */ -#define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */ -#define X86_FEATURE_INVPCID (9*32+10) /* Invalidate Processor Context ID */ -#define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */ -#define X86_FEATURE_RDSEED (9*32+18) /* The RDSEED instruction */ -#define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */ -#define X86_FEATURE_SMAP (9*32+20) /* Supervisor Mode Access Prevention */ -
diff --git a/libsel4vmm/include/vmm/processor/cpuid.h b/libsel4vmm/include/vmm/processor/cpuid.h deleted file mode 100644 index 3f2cbed..0000000 --- a/libsel4vmm/include/vmm/processor/cpuid.h +++ /dev/null
@@ -1,52 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* This file contains macros for CPUID emulation in x86. - * Most of the code in this file is from arch/x86/kvm/cpuid.h Linux 3.8.8 - * This file should used only by cpuid.c - * - * Authors: - * Qian Ge - */ - -#pragma once - -#include <utils/util.h> - -#define F(x) BIT( (X86_FEATURE_##x) & 31) - -/* Basic information for the processor P4 hyperthread. */ -#define VMM_CPUID_EAX_P4_HT 0x5 -#define VMM_CPUID_P4_FAMILY (6 << 8) -#define VMM_CPUID_P4_MODLE (7 << 4) -#define VMM_CPUID_P4_STEP (1) - -/* Extended function information for p4 ht. */ -#define VMM_CPUID_P4_MAX_EXTFUNCTION 0x80000008 - -/* 32 bit for both phy & vir address space*/ -#define VMM_CPUID_P4_PHYADDR_SIZE 0x20 -#define VMM_CPUID_P4_VIRADDR_SIZE 0x20 - -/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx if running under KVM. */ -#define VMM_CPUID_KVM_SIGNATURE 0x40000000 -/* This CPUID returns a feature bitmap in eax */ -#define VMM_CPUID_KVM_FEATURES 0x40000001 - -/* CPUID instruction return value. */ -struct cpuid_val { - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; -}; -
diff --git a/libsel4vmm/include/vmm/processor/decode.h b/libsel4vmm/include/vmm/processor/decode.h deleted file mode 100644 index 48e1bbd..0000000 --- a/libsel4vmm/include/vmm/processor/decode.h +++ /dev/null
@@ -1,48 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ -#pragma once - -#include "vmm/vmm.h" -#include "vmm/guest_state.h" - -int vmm_fetch_instruction(vmm_vcpu_t *vcpu, uint32_t eip, uintptr_t cr3, int len, uint8_t *buf); - -int vmm_decode_instruction(uint8_t *instr, int instr_len, int *reg, uint32_t *imm, int *op_len); - -/* Interpret just enough virtual 8086 instructions to run trampoline code. - Returns the final jump address */ -uintptr_t vmm_emulate_realmode(guest_memory_t *gm, uint8_t *instr_buf, - uint16_t *segment, uintptr_t eip, uint32_t len, guest_state_t *gs); - -// TODO don't have these in a header, make them inline functions -const static int vmm_decoder_reg_mapw[] = { - USER_CONTEXT_EAX, - USER_CONTEXT_ECX, - USER_CONTEXT_EDX, - USER_CONTEXT_EBX, - /*USER_CONTEXT_ESP*/-1, - USER_CONTEXT_EBP, - USER_CONTEXT_ESI, - USER_CONTEXT_EDI -}; - -const static int vmm_decoder_reg_mapb[] = { - USER_CONTEXT_EAX, - USER_CONTEXT_ECX, - USER_CONTEXT_EDX, - USER_CONTEXT_EBX, - USER_CONTEXT_EAX, - USER_CONTEXT_ECX, - USER_CONTEXT_EDX, - USER_CONTEXT_EBX -}; -
diff --git a/libsel4vmm/include/vmm/processor/lapic.h b/libsel4vmm/include/vmm/processor/lapic.h deleted file mode 100644 index b6ccee0..0000000 --- a/libsel4vmm/include/vmm/processor/lapic.h +++ /dev/null
@@ -1,78 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -enum vmm_lapic_state { - LAPIC_STATE_NEW, - LAPIC_STATE_WAITSIPI, - LAPIC_STATE_RUN -}; - -#if 0 -struct vmm_timer { - struct hrtimer timer; - int64_t period; /* unit: ns */ - uint32_t timer_mode_mask; - uint64_t tscdeadline; - atomic_t pending; /* accumulated triggered timers */ -}; -#endif - -typedef struct vmm_lapic { - uint32_t apic_base; // BSP flag is ignored in this - - //struct vmm_timer lapic_timer; - uint32_t divide_count; - - bool irr_pending; - /* Number of bits set in ISR. */ - int16_t isr_count; - /* The highest vector set in ISR; if -1 - invalid, must scan ISR. */ - int highest_isr_cache; - /** - * APIC register page. The layout matches the register layout seen by - * the guest 1:1, because it is accessed by the vmx microcode. XXX ??? - * Note: Only one register, the TPR, is used by the microcode. - */ - void *regs; - unsigned int sipi_vector; - - enum vmm_lapic_state state; - int arb_prio; -} vmm_lapic_t; - -int vmm_apic_enabled(vmm_lapic_t *apic); - -int vmm_create_lapic(vmm_vcpu_t *vcpu, int enabled); -void vmm_free_lapic(vmm_vcpu_t *vcpu); - -int vmm_apic_has_interrupt(vmm_vcpu_t *vcpu); -int vmm_apic_get_interrupt(vmm_vcpu_t *vcpu); - -void vmm_apic_consume_extints(vmm_vcpu_t *vcpu, int (*get)(void)); - -/* MSR functions */ -void vmm_lapic_set_base_msr(vmm_vcpu_t *vcpu, uint32_t value); -uint32_t vmm_lapic_get_base_msr(vmm_vcpu_t *vcpu); - -int vmm_apic_local_deliver(vmm_vcpu_t *vcpu, int lvt_type); -int vmm_apic_accept_pic_intr(vmm_vcpu_t *vcpu); - -void vmm_apic_mmio_write(vmm_vcpu_t *vcpu, void *cookie, uint32_t offset, - int len, const uint32_t data); -void vmm_apic_mmio_read(vmm_vcpu_t *vcpu, void *cookie, uint32_t offset, - int len, uint32_t *data); - -uint64_t vmm_get_lapic_tscdeadline_msr(vmm_vcpu_t *vcpu); -void vmm_set_lapic_tscdeadline_msr(vmm_vcpu_t *vcpu, uint64_t data); -
diff --git a/libsel4vmm/include/vmm/processor/msr.h b/libsel4vmm/include/vmm/processor/msr.h deleted file mode 100644 index a41af45..0000000 --- a/libsel4vmm/include/vmm/processor/msr.h +++ /dev/null
@@ -1,292 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* CPU model specific register (MSR) numbers. - * Authors: - * Qian Ge - */ - -#pragma once - -/* Intel MSRs. Some also available on other CPUs */ - -#define MSR_IA32_PERFCTR0 0x000000c1 -#define MSR_IA32_PERFCTR1 0x000000c2 -#define MSR_FSB_FREQ 0x000000cd -#define MSR_NHM_PLATFORM_INFO 0x000000ce - -#define MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2 -#define NHM_C3_AUTO_DEMOTE (1UL << 25) -#define NHM_C1_AUTO_DEMOTE (1UL << 26) -#define ATM_LNC_C6_AUTO_DEMOTE (1UL << 25) -#define SNB_C1_AUTO_UNDEMOTE (1UL << 27) -#define SNB_C3_AUTO_UNDEMOTE (1UL << 28) - -#define MSR_MTRRcap 0x000000fe -#define MSR_IA32_BBL_CR_CTL 0x00000119 -#define MSR_IA32_BBL_CR_CTL3 0x0000011e - -#define MSR_IA32_SYSENTER_CS 0x00000174 -#define MSR_IA32_SYSENTER_ESP 0x00000175 -#define MSR_IA32_SYSENTER_EIP 0x00000176 - -#define MSR_IA32_MCG_CAP 0x00000179 -#define MSR_IA32_MCG_STATUS 0x0000017a -#define MSR_IA32_MCG_CTL 0x0000017b - -#define MSR_OFFCORE_RSP_0 0x000001a6 -#define MSR_OFFCORE_RSP_1 0x000001a7 -#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad -#define MSR_IVT_TURBO_RATIO_LIMIT 0x000001ae - -#define MSR_LBR_SELECT 0x000001c8 -#define MSR_LBR_TOS 0x000001c9 -#define MSR_LBR_NHM_FROM 0x00000680 -#define MSR_LBR_NHM_TO 0x000006c0 -#define MSR_LBR_CORE_FROM 0x00000040 -#define MSR_LBR_CORE_TO 0x00000060 - -#define MSR_IA32_PEBS_ENABLE 0x000003f1 -#define MSR_IA32_DS_AREA 0x00000600 -#define MSR_IA32_PERF_CAPABILITIES 0x00000345 - -#define MSR_MTRRfix64K_00000 0x00000250 -#define MSR_MTRRfix16K_80000 0x00000258 -#define MSR_MTRRfix16K_A0000 0x00000259 -#define MSR_MTRRfix4K_C0000 0x00000268 -#define MSR_MTRRfix4K_C8000 0x00000269 -#define MSR_MTRRfix4K_D0000 0x0000026a -#define MSR_MTRRfix4K_D8000 0x0000026b -#define MSR_MTRRfix4K_E0000 0x0000026c -#define MSR_MTRRfix4K_E8000 0x0000026d -#define MSR_MTRRfix4K_F0000 0x0000026e -#define MSR_MTRRfix4K_F8000 0x0000026f -#define MSR_MTRRdefType 0x000002ff - -#define MSR_IA32_CR_PAT 0x00000277 - -#define MSR_IA32_DEBUGCTLMSR 0x000001d9 -#define MSR_IA32_LASTBRANCHFROMIP 0x000001db -#define MSR_IA32_LASTBRANCHTOIP 0x000001dc -#define MSR_IA32_LASTINTFROMIP 0x000001dd -#define MSR_IA32_LASTINTTOIP 0x000001de - -/* DEBUGCTLMSR bits (others vary by model): */ -#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */ -#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ -#define DEBUGCTLMSR_TR (1UL << 6) -#define DEBUGCTLMSR_BTS (1UL << 7) -#define DEBUGCTLMSR_BTINT (1UL << 8) -#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9) -#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10) -#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11) - -#define MSR_IA32_MC0_CTL 0x00000400 -#define MSR_IA32_MC0_STATUS 0x00000401 -#define MSR_IA32_MC0_ADDR 0x00000402 -#define MSR_IA32_MC0_MISC 0x00000403 - -/* C-state Residency Counters */ -#define MSR_PKG_C3_RESIDENCY 0x000003f8 -#define MSR_PKG_C6_RESIDENCY 0x000003f9 -#define MSR_PKG_C7_RESIDENCY 0x000003fa -#define MSR_CORE_C3_RESIDENCY 0x000003fc -#define MSR_CORE_C6_RESIDENCY 0x000003fd -#define MSR_CORE_C7_RESIDENCY 0x000003fe -#define MSR_PKG_C2_RESIDENCY 0x0000060d - -/* Run Time Average Power Limiting (RAPL) Interface */ - -#define MSR_RAPL_POWER_UNIT 0x00000606 - -#define MSR_PKG_POWER_LIMIT 0x00000610 -#define MSR_PKG_ENERGY_STATUS 0x00000611 -#define MSR_PKG_PERF_STATUS 0x00000613 -#define MSR_PKG_POWER_INFO 0x00000614 - -#define MSR_DRAM_POWER_LIMIT 0x00000618 -#define MSR_DRAM_ENERGY_STATUS 0x00000619 -#define MSR_DRAM_PERF_STATUS 0x0000061b -#define MSR_DRAM_POWER_INFO 0x0000061c - -#define MSR_PP0_POWER_LIMIT 0x00000638 -#define MSR_PP0_ENERGY_STATUS 0x00000639 -#define MSR_PP0_POLICY 0x0000063a -#define MSR_PP0_PERF_STATUS 0x0000063b - -#define MSR_PP1_POWER_LIMIT 0x00000640 -#define MSR_PP1_ENERGY_STATUS 0x00000641 -#define MSR_PP1_POLICY 0x00000642 - -#define MSR_AMD64_MC0_MASK 0xc0010044 - -#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) -#define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x)) -#define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x)) -#define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x)) - -#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x)) - -/* These are consecutive and not in the normal 4er MCE bank block */ -#define MSR_IA32_MC0_CTL2 0x00000280 -#define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x)) - -#define MSR_P6_PERFCTR0 0x000000c1 -#define MSR_P6_PERFCTR1 0x000000c2 -#define MSR_P6_EVNTSEL0 0x00000186 -#define MSR_P6_EVNTSEL1 0x00000187 - -#define MSR_KNC_PERFCTR0 0x00000020 -#define MSR_KNC_PERFCTR1 0x00000021 -#define MSR_KNC_EVNTSEL0 0x00000028 -#define MSR_KNC_EVNTSEL1 0x00000029 - -/* Intel VT MSRs */ -#define MSR_IA32_VMX_BASIC 0x00000480 -#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 -#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482 -#define MSR_IA32_VMX_EXIT_CTLS 0x00000483 -#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484 -#define MSR_IA32_VMX_MISC 0x00000485 -#define MSR_IA32_VMX_CR0_FIXED0 0x00000486 -#define MSR_IA32_VMX_CR0_FIXED1 0x00000487 -#define MSR_IA32_VMX_CR4_FIXED0 0x00000488 -#define MSR_IA32_VMX_CR4_FIXED1 0x00000489 -#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a -#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b -#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c -#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x0000048d -#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e -#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f -#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 - -/* VMX_BASIC bits and bitmasks */ -#define VMX_BASIC_VMCS_SIZE_SHIFT 32 -#define VMX_BASIC_64 0x0001000000000000LLU -#define VMX_BASIC_MEM_TYPE_SHIFT 50 -#define VMX_BASIC_MEM_TYPE_MASK 0x003c000000000000LLU -#define VMX_BASIC_MEM_TYPE_WB 6LLU -#define VMX_BASIC_INOUT 0x0040000000000000LLU - -/* Intel defined MSRs. */ -#define MSR_IA32_P5_MC_ADDR 0x00000000 -#define MSR_IA32_P5_MC_TYPE 0x00000001 -#define MSR_IA32_TSC 0x00000010 -#define MSR_IA32_PLATFORM_ID 0x00000017 -#define MSR_IA32_EBL_CR_POWERON 0x0000002a -#define MSR_EBC_FREQUENCY_ID 0x0000002c -#define MSR_IA32_FEATURE_CONTROL 0x0000003a -#define MSR_IA32_TSC_ADJUST 0x0000003b - -#define FEATURE_CONTROL_LOCKED (1<<0) -#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) -#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2) - -#define MSR_IA32_APICBASE 0x0000001b -#define MSR_IA32_APICBASE_BSP (1<<8) -#define MSR_IA32_APICBASE_ENABLE (1<<11) -#define MSR_IA32_APICBASE_BASE (0xfffff<<12) - -#define MSR_IA32_TSCDEADLINE 0x000006e0 - -#define MSR_IA32_UCODE_WRITE 0x00000079 -#define MSR_IA32_UCODE_REV 0x0000008b - -#define MSR_IA32_PERF_STATUS 0x00000198 -#define MSR_IA32_PERF_CTL 0x00000199 -#define MSR_IA32_PERF_GLOBAL_STATUS_SET 0x00000391 -#define MSR_AMD_PSTATE_DEF_BASE 0xc0010064 -#define MSR_AMD_PERF_STATUS 0xc0010063 -#define MSR_AMD_PERF_CTL 0xc0010062 - -#define MSR_IA32_MPERF 0x000000e7 -#define MSR_IA32_APERF 0x000000e8 - -#define MSR_IA32_THERM_CONTROL 0x0000019a -#define MSR_IA32_THERM_INTERRUPT 0x0000019b - -#define THERM_INT_HIGH_ENABLE (BIT(0)) -#define THERM_INT_LOW_ENABLE (BIT(1)) -#define THERM_INT_PLN_ENABLE (BIT(24)) - -#define MSR_IA32_THERM_STATUS 0x0000019c - -#define THERM_STATUS_PROCHOT (BIT(0)) -#define THERM_STATUS_POWER_LIMIT (BIT(10)) - -#define MSR_THERM2_CTL 0x0000019d - -#define MSR_THERM2_CTL_TM_SELECT (1ULL << 16) - -#define MSR_IA32_MISC_ENABLE 0x000001a0 - -#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 - -#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 -#define ENERGY_PERF_BIAS_PERFORMANCE 0 -#define ENERGY_PERF_BIAS_NORMAL 6 -#define ENERGY_PERF_BIAS_POWERSAVE 15 - -#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1 - -#define PACKAGE_THERM_STATUS_PROCHOT (BIT(0)) -#define PACKAGE_THERM_STATUS_POWER_LIMIT (BIT(10)) - -#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2 - -#define PACKAGE_THERM_INT_HIGH_ENABLE (BIT(0)) -#define PACKAGE_THERM_INT_LOW_ENABLE (BIT(1)) -#define PACKAGE_THERM_INT_PLN_ENABLE (BIT(24)) - -/* Thermal Thresholds Support */ -#define THERM_INT_THRESHOLD0_ENABLE (BIT(15)) -#define THERM_SHIFT_THRESHOLD0 8 -#define THERM_MASK_THRESHOLD0 (0x7f << THERM_SHIFT_THRESHOLD0) -#define THERM_INT_THRESHOLD1_ENABLE (BIT(23)) -#define THERM_SHIFT_THRESHOLD1 16 -#define THERM_MASK_THRESHOLD1 (0x7f << THERM_SHIFT_THRESHOLD1) -#define THERM_STATUS_THRESHOLD0 (BIT(6)) -#define THERM_LOG_THRESHOLD0 (BIT(7)) -#define THERM_STATUS_THRESHOLD1 (BIT(8)) -#define THERM_LOG_THRESHOLD1 (BIT(9)) - -/* MISC_ENABLE bits: architectural */ -#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) -#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) -#define MSR_IA32_MISC_ENABLE_EMON (1ULL << 7) -#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1ULL << 11) -#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1ULL << 12) -#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16) -#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18) -#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22) -#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << 23) -#define MSR_IA32_MISC_ENABLE_XD_DISABLE (1ULL << 34) - -/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */ -#define MSR_IA32_MISC_ENABLE_X87_COMPAT (1ULL << 2) -#define MSR_IA32_MISC_ENABLE_TM1 (1ULL << 3) -#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE (1ULL << 4) -#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE (1ULL << 6) -#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK (1ULL << 8) -#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE (1ULL << 9) -#define MSR_IA32_MISC_ENABLE_FERR (1ULL << 10) -#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << 10) -#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << 13) -#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE (1ULL << 19) -#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20) -#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT (1ULL << 24) -#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE (1ULL << 37) -#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) -#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39) - -#define MSR_IA32_TSC_DEADLINE 0x000006E0 -
diff --git a/libsel4vmm/include/vmm/processor/platfeature.h b/libsel4vmm/include/vmm/processor/platfeature.h deleted file mode 100644 index 4542197..0000000 --- a/libsel4vmm/include/vmm/processor/platfeature.h +++ /dev/null
@@ -1,270 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* This file contains definitions related with features in x86 platform - * Authors: - * Qian Ge - */ - -#pragma once - -/* Exception vector. */ - -#define DE_VECTOR 0 -#define DB_VECTOR 1 -#define BP_VECTOR 3 -#define OF_VECTOR 4 -#define BR_VECTOR 5 -#define UD_VECTOR 6 -#define NM_VECTOR 7 -#define DF_VECTOR 8 -#define TS_VECTOR 10 -#define NP_VECTOR 11 -#define SS_VECTOR 12 -#define GP_VECTOR 13 -#define PF_VECTOR 14 -#define MF_VECTOR 16 -#define MC_VECTOR 18 - -/* Processor flags. */ - -/* - * EFLAGS bits - */ -#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ -#define X86_EFLAGS_BIT1 0x00000002 /* Bit 1 - always on */ -#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ -#define X86_EFLAGS_AF 0x00000010 /* Auxiliary carry Flag */ -#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ -#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ -#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ -#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ -#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ -#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ -#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ -#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ -#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ -#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ -#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ -#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ -#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ -#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ - -/* - * Basic CPU control in CR0 - */ -#define X86_CR0_PE 0x00000001 /* Protection Enable */ -#define X86_CR0_MP 0x00000002 /* Monitor Coprocessor */ -#define X86_CR0_EM 0x00000004 /* Emulation */ -#define X86_CR0_TS 0x00000008 /* Task Switched */ -#define X86_CR0_ET 0x00000010 /* Extension Type */ -#define X86_CR0_NE 0x00000020 /* Numeric Error */ -#define X86_CR0_WP 0x00010000 /* Write Protect */ -#define X86_CR0_AM 0x00040000 /* Alignment Mask */ -#define X86_CR0_NW 0x20000000 /* Not Write-through */ -#define X86_CR0_CD 0x40000000 /* Cache Disable */ -#define X86_CR0_PG 0x80000000 /* Paging */ - -/* - * Paging options in CR3 - */ -#define X86_CR3_PWT 0x00000008 /* Page Write Through */ -#define X86_CR3_PCD 0x00000010 /* Page Cache Disable */ -#define X86_CR3_PCID_MASK 0x00000fff /* PCID Mask */ - -/* - * Intel CPU features in CR4 - */ -#define X86_CR4_VME 0x00000001 /* enable vm86 extensions */ -#define X86_CR4_PVI 0x00000002 /* virtual interrupts flag enable */ -#define X86_CR4_TSD 0x00000004 /* disable time stamp at ipl 3 */ -#define X86_CR4_DE 0x00000008 /* enable debugging extensions */ -#define X86_CR4_PSE 0x00000010 /* enable page size extensions */ -#define X86_CR4_PAE 0x00000020 /* enable physical address extensions */ -#define X86_CR4_MCE 0x00000040 /* Machine check enable */ -#define X86_CR4_PGE 0x00000080 /* enable global pages */ -#define X86_CR4_PCE 0x00000100 /* enable performance counters at ipl 3 */ -#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */ -#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */ -#define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */ -#define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */ -#define X86_CR4_PCIDE 0x00020000 /* enable PCID support */ -#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */ -#define X86_CR4_SMEP 0x00100000 /* enable SMEP support */ -#define X86_CR4_SMAP 0x00200000 /* enable SMAP support */ - -/* - * x86-64 Task Priority Register, CR8 - */ -#define X86_CR8_TPR 0x0000000F /* task priority register */ - -/* Reserved bits for CR registers. */ -#define CR0_RESERVED_BITS \ - (~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \ - | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM \ - | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG)) - -#define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1) -#define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | X86_CR3_PCD)) -#define CR3_PCID_ENABLED_RESERVED_BITS 0xFFFFFF0000000000ULL -#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS | \ - 0xFFFFFF0000000000ULL) -#define CR4_RESERVED_BITS \ - (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\ - | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ - | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_PCIDE \ - | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_RDWRGSFS \ - | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE)) - -#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR) - -/* - * Definitions of Primary Processor-Based VM-Execution Controls. - */ -#define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 -#define CPU_BASED_USE_TSC_OFFSETING 0x00000008 -#define CPU_BASED_HLT_EXITING 0x00000080 -#define CPU_BASED_INVLPG_EXITING 0x00000200 -#define CPU_BASED_MWAIT_EXITING 0x00000400 -#define CPU_BASED_RDPMC_EXITING 0x00000800 -#define CPU_BASED_RDTSC_EXITING 0x00001000 -#define CPU_BASED_CR3_LOAD_EXITING 0x00008000 -#define CPU_BASED_CR3_STORE_EXITING 0x00010000 -#define CPU_BASED_CR8_LOAD_EXITING 0x00080000 -#define CPU_BASED_CR8_STORE_EXITING 0x00100000 -#define CPU_BASED_TPR_SHADOW 0x00200000 -#define CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000 -#define CPU_BASED_MOV_DR_EXITING 0x00800000 -#define CPU_BASED_UNCOND_IO_EXITING 0x01000000 -#define CPU_BASED_USE_IO_BITMAPS 0x02000000 -#define CPU_BASED_USE_MSR_BITMAPS 0x10000000 -#define CPU_BASED_MONITOR_EXITING 0x20000000 -#define CPU_BASED_PAUSE_EXITING 0x40000000 -#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000 -/* - * Definitions of Secondary Processor-Based VM-Execution Controls. - */ -#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 -#define SECONDARY_EXEC_ENABLE_EPT 0x00000002 -#define SECONDARY_EXEC_RDTSCP 0x00000008 -#define SECONDARY_EXEC_ENABLE_VPID 0x00000020 -#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040 -#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 -#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400 -#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000 - -#define PIN_BASED_EXT_INTR_MASK 0x00000001 -#define PIN_BASED_NMI_EXITING 0x00000008 -#define PIN_BASED_VIRTUAL_NMIS 0x00000020 - -#define VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000002 -#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200 -#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000 -#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 -#define VM_EXIT_SAVE_IA32_PAT 0x00040000 -#define VM_EXIT_LOAD_IA32_PAT 0x00080000 -#define VM_EXIT_SAVE_IA32_EFER 0x00100000 -#define VM_EXIT_LOAD_IA32_EFER 0x00200000 -#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000 - -#define VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000002 -#define VM_ENTRY_IA32E_MODE 0x00000200 -#define VM_ENTRY_SMM 0x00000400 -#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 -#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000 -#define VM_ENTRY_LOAD_IA32_PAT 0x00004000 -#define VM_ENTRY_LOAD_IA32_EFER 0x00008000 - -/* Interruption-information format. */ - -#define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */ -#define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */ -#define INTR_INFO_DELIVER_CODE_MASK 0x800 /* 11 */ -#define INTR_INFO_UNBLOCK_NMI 0x1000 /* 12 */ -#define INTR_INFO_VALID_MASK 0x80000000 /* 31 */ -#define INTR_INFO_RESVD_BITS_MASK 0x7ffff000 - -#define VECTORING_INFO_VECTOR_MASK INTR_INFO_VECTOR_MASK -#define VECTORING_INFO_TYPE_MASK INTR_INFO_INTR_TYPE_MASK -#define VECTORING_INFO_DELIVER_CODE_MASK INTR_INFO_DELIVER_CODE_MASK -#define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK - -#define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ -#define INTR_TYPE_NMI_INTR (2 << 8) /* NMI */ -#define INTR_TYPE_HARD_EXCEPTION (3 << 8) /* processor exception */ -#define INTR_TYPE_SOFT_INTR (4 << 8) /* software interrupt */ -#define INTR_TYPE_SOFT_EXCEPTION (6 << 8) /* software exception */ - -/* GUEST_INTERRUPTIBILITY_INFO flags. */ -#define GUEST_INTR_STATE_STI 0x00000001 -#define GUEST_INTR_STATE_MOV_SS 0x00000002 -#define GUEST_INTR_STATE_SMI 0x00000004 -#define GUEST_INTR_STATE_NMI 0x00000008 - -/* GUEST_ACTIVITY_STATE flags */ -#define GUEST_ACTIVITY_ACTIVE 0 -#define GUEST_ACTIVITY_HLT 1 -#define GUEST_ACTIVITY_SHUTDOWN 2 -#define GUEST_ACTIVITY_WAIT_SIPI 3 - -/* Exit Qualifications for MOV for Control Register Access. */ -#define CONTROL_REG_ACCESS_NUM 0x7 /* 2:0, number of control reg.*/ -#define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */ -#define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose reg. */ -#define LMSW_SOURCE_DATA_SHIFT 16 -#define LMSW_SOURCE_DATA (0xFFFF << LMSW_SOURCE_DATA_SHIFT) /* 16:31 lmsw source */ -#define REG_EAX (0 << 8) -#define REG_ECX (1 << 8) -#define REG_EDX (2 << 8) -#define REG_EBX (3 << 8) -#define REG_ESP (4 << 8) -#define REG_EBP (5 << 8) -#define REG_ESI (6 << 8) -#define REG_EDI (7 << 8) -#define REG_R8 (8 << 8) -#define REG_R9 (9 << 8) -#define REG_R10 (10 << 8) -#define REG_R11 (11 << 8) -#define REG_R12 (12 << 8) -#define REG_R13 (13 << 8) -#define REG_R14 (14 << 8) -#define REG_R15 (15 << 8) - -/* VM-instruction error numbers. */ -enum vm_instruction_error_number { - VMXERR_VMCALL_IN_VMX_ROOT_OPERATION = 1, - VMXERR_VMCLEAR_INVALID_ADDRESS = 2, - VMXERR_VMCLEAR_VMXON_POINTER = 3, - VMXERR_VMLAUNCH_NONCLEAR_VMCS = 4, - VMXERR_VMRESUME_NONLAUNCHED_VMCS = 5, - VMXERR_VMRESUME_AFTER_VMXOFF = 6, - VMXERR_ENTRY_INVALID_CONTROL_FIELD = 7, - VMXERR_ENTRY_INVALID_HOST_STATE_FIELD = 8, - VMXERR_VMPTRLD_INVALID_ADDRESS = 9, - VMXERR_VMPTRLD_VMXON_POINTER = 10, - VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID = 11, - VMXERR_UNSUPPORTED_VMCS_COMPONENT = 12, - VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT = 13, - VMXERR_VMXON_IN_VMX_ROOT_OPERATION = 15, - VMXERR_ENTRY_INVALID_EXECUTIVE_VMCS_POINTER = 16, - VMXERR_ENTRY_NONLAUNCHED_EXECUTIVE_VMCS = 17, - VMXERR_ENTRY_EXECUTIVE_VMCS_POINTER_NOT_VMXON_POINTER = 18, - VMXERR_VMCALL_NONCLEAR_VMCS = 19, - VMXERR_VMCALL_INVALID_VM_EXIT_CONTROL_FIELDS = 20, - VMXERR_VMCALL_INCORRECT_MSEG_REVISION_ID = 22, - VMXERR_VMXOFF_UNDER_DUAL_MONITOR_TREATMENT_OF_SMIS_AND_SMM = 23, - VMXERR_VMCALL_INVALID_SMM_MONITOR_FEATURES = 24, - VMXERR_ENTRY_INVALID_VM_EXECUTION_CONTROL_FIELDS_IN_EXECUTIVE_VMCS = 25, - VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS = 26, - VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID = 28, -}; -
diff --git a/libsel4vmm/include/vmm/vchan_component.h b/libsel4vmm/include/vmm/vchan_component.h deleted file mode 100644 index a2898e4..0000000 --- a/libsel4vmm/include/vmm/vchan_component.h +++ /dev/null
@@ -1,58 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include "libvchan.h" -#include "vchan_sharemem.h" -#include "vchan_copy.h" - -typedef void (*callback_func_t)(void *); - -typedef struct camkes_vchan_con { - /* Domain */ - int component_dom_num; - void *data_buf; - - /* Function Pointers */ - int (*connect)(vchan_connect_t); - int (*disconnect)(vchan_connect_t); - intptr_t (*get_buf)(vchan_ctrl_t, int); - int (*status)(vchan_ctrl_t); - int (*alert_status)(vchan_ctrl_t); - - void (*wait)(void); - void (*alert)(void); - int (*poll)(void); - - int (*reg_callback)(callback_func_t, void *); -} camkes_vchan_con_t; - -struct libvchan { - int is_server; - int server_persists; - int blocking; - int domain_num, port_num; - - camkes_vchan_con_t *con; -}; - -void init_camkes_vchan(camkes_vchan_con_t *c); - -int vchan_set_callback(callback_func_t cb, void *data); - -vchan_buf_t *get_vchan_buf(vchan_ctrl_t *args, camkes_vchan_con_t *c, int action); - -void vevent_wait(void); -int vevent_poll(void); -int vevent_reg_callback(void (*callback)(void*), void *arg); -
diff --git a/libsel4vmm/include/vmm/vchan_copy.h b/libsel4vmm/include/vmm/vchan_copy.h deleted file mode 100644 index f0a6389..0000000 --- a/libsel4vmm/include/vmm/vchan_copy.h +++ /dev/null
@@ -1,96 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#define VCHAN_EVENT_IRQ 10 - -#define DATATYPE_INT 0 -#define DATATYPE_STRING 1 - -/* Vchan defines */ -#define VCHAN_PACKET_SIZE 4096 -#define FILE_DATAPORT_MAX_SIZE 4096 - -#define NOWAIT_DATA_READY 1 -#define NOWAIT_BUF_SPACE 2 - -#define VCHAN_CLIENT 0 -#define VCHAN_SERVER 1 - -#define VCHAN_CLOSED_DATA 0 -#define VCHAN_CLOSED 1 -#define VCHAN_EMPTY_BUF 2 -#define VCHAN_BUF_DATA 3 -#define VCHAN_BUF_FULL 4 - -#define DPORT_KERN_ADDR 0xEE00000 -#define VCHAN_DATA_TOKEN 0xDEADBEEF - -/* Used in arguments referring to a vchan instance */ -typedef struct vchan_ctrl { - int domain; - int dest; - int port; -} vchan_ctrl_t; - -/* Used in arguments referring to a vchan instance */ -typedef struct vchan_alert { - int alert; - int dest; - int port; -} vchan_alert_t; - -/* Arguments structure used for vchan write/read actions between guest os's */ -typedef struct vchan_args { - vchan_ctrl_t v; - void *mmap_ptr; - int stream; - int size; - int mmap_phys_ptr; -} vchan_args_t; - -/* Argument structure used for vchan */ -typedef struct vchan_check_args { - vchan_ctrl_t v; - int nowait; - int state; - int checktype; -} vchan_check_args_t; - -/* Argument structure used for vchan connects */ -typedef struct vchan_connect { - vchan_ctrl_t v; - int server; - int eventfd; - uintptr_t event_mon; -} vchan_connect_t; - -void volatile_copy(void *dest, void *rec, int size); - -/* Used for helloworld testsuite */ -#define MSG_HELLO 0 -#define MSG_ACK 1 -#define MSG_CONC 2 -#define TEST_VCHAN_PAK_GUARD 0xBEEDEADA - -typedef struct vchan_header { - int msg_type; - int len; -} vchan_header_t; - -typedef struct vchan_packet { - int pnum; - int datah[4]; - int guard; -} vchan_packet_t; -
diff --git a/libsel4vmm/include/vmm/vchan_sharemem.h b/libsel4vmm/include/vmm/vchan_sharemem.h deleted file mode 100644 index 33e951e..0000000 --- a/libsel4vmm/include/vmm/vchan_sharemem.h +++ /dev/null
@@ -1,45 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sel4/sel4.h> -#include <sel4utils/util.h> -#include <simple/simple.h> - -#define VCHAN_BUF_SIZE PAGE_SIZE_4K -#define NUM_BUFFERS 2 - -typedef struct vchan_buf { - int owner; - char sync_data[VCHAN_BUF_SIZE]; - int filled; - int read_pos, write_pos; -} vchan_buf_t; - -/* - Handles managing of packets, storing packets in shared mem, - copying in memory and reading from memory for sync comms -*/ -typedef struct vchan_shared_mem { - int alloced; - vchan_buf_t bufs[2]; -} vchan_shared_mem_t; - -typedef struct vchan_shared_mem_headers { - vchan_shared_mem_t shared_buffers[NUM_BUFFERS]; - int token; -} vchan_headers_t; -
diff --git a/libsel4vmm/include/vmm/vmcall.h b/libsel4vmm/include/vmm/vmcall.h deleted file mode 100644 index 0d2e4da..0000000 --- a/libsel4vmm/include/vmm/vmcall.h +++ /dev/null
@@ -1,37 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include "vmm.h" - -typedef int (*vmcall_handler)(vmm_vcpu_t *vcpu); - -/* - A handler for a given vmcall function - Called in a vmcall exception if its token matches the vcpu register eax -*/ -typedef struct vmcall_handler { - int token; - vmcall_handler func; -} vmcall_handler_t; - -/* - Simple functions for registering handlers, - calling a handler -*/ -int reg_new_handler(vmm_t *vmm, vmcall_handler func, int token); -int vmm_vmcall_handler(vmm_vcpu_t *vcpu); - -/* Handlers that can be registered */ -int vchan_handler(vmm_vcpu_t *vcpu); -
diff --git a/libsel4vmm/include/vmm/vmcs.h b/libsel4vmm/include/vmm/vmcs.h deleted file mode 100644 index 37ad121..0000000 --- a/libsel4vmm/include/vmm/vmcs.h +++ /dev/null
@@ -1,22 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <sel4/sel4.h> - -#include <vmm/vmm.h> - -int vmm_vmcs_read(seL4_CPtr vcpu, seL4_Word field); -void vmm_vmcs_write(seL4_CPtr vcpu, seL4_Word field, seL4_Word value); -void vmm_vmcs_init_guest(vmm_vcpu_t *vcpu); -
diff --git a/libsel4vmm/include/vmm/vmexit.h b/libsel4vmm/include/vmm/vmexit.h deleted file mode 100644 index 6d18b8a..0000000 --- a/libsel4vmm/include/vmm/vmexit.h +++ /dev/null
@@ -1,30 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#include <vmm/interrupt.h> -#include <vmm/vmm.h> - -typedef int(*vmexit_handler_ptr)(vmm_vcpu_t *vcpu); - -/*vm exit handlers*/ -int vmm_cpuid_handler(vmm_vcpu_t *vcpu); -int vmm_ept_violation_handler(vmm_vcpu_t *vcpu); -int vmm_wrmsr_handler(vmm_vcpu_t *vcpu); -int vmm_rdmsr_handler(vmm_vcpu_t *vcpu); -int vmm_io_instruction_handler(vmm_vcpu_t *vcpu); -int vmm_hlt_handler(vmm_vcpu_t *vcpu); -int vmm_vmx_timer_handler(vmm_vcpu_t *vcpu); -int vmm_cr_access_handler(vmm_vcpu_t *vcpu); -int vmm_vmcall_handler(vmm_vcpu_t *vcpu); -
diff --git a/libsel4vmm/include/vmm/vmm.h b/libsel4vmm/include/vmm/vmm.h deleted file mode 100644 index aada081..0000000 --- a/libsel4vmm/include/vmm/vmm.h +++ /dev/null
@@ -1,161 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/*This file contains structure definitions and function prototype related with VMM.*/ - -#pragma once - -#include <sel4/sel4.h> - -#include <vka/vka.h> -#include <simple/simple.h> -#include <vspace/vspace.h> -#include <allocman/allocman.h> - -typedef struct vmm vmm_t; -typedef struct vmm_vcpu vmm_vcpu_t; - -#include "vmm/platform/vmexit.h" -#include "vmm/driver/pci.h" -#include "vmm/io.h" -#include "vmm/platform/guest_memory.h" -#include "vmm/guest_state.h" -#include "vmm/vmexit.h" -#include "vmm/mmio.h" -#include "vmm/processor/lapic.h" -#include "vmm/vmcall.h" -#include "vmm/vmm_manager.h" - -/* ID of the boot vcpu in a vmm */ -#define BOOT_VCPU 0 - -/* System callbacks passed from the user to the library. These need to - * be passed in as their definitions are invisible to this library */ -typedef struct platform_callbacks { - int (*get_interrupt)(); - int (*has_interrupt)(); - int (*do_async)(seL4_Word badge); - seL4_CPtr (*get_async_event_notification)(); -} platform_callbacks_t; - -/* Stores informatoin about the guest image we are loading. This information probably stops - * being relevant / useful after we start running. Most of this assumes - * we are loading a guest kernel elf image and that we are acting as some kind of bootloader */ -typedef struct guest_image { - /* Alignment we used when loading the kernel image */ - size_t alignment; - /* Entry point when the VM starts */ - uintptr_t entry; - /* Base address (in guest physical) where the image was loaded */ - uintptr_t load_paddr; - /* Base physical address the image was linked for */ - uintptr_t link_paddr; - uintptr_t link_vaddr; - /* If we are loading a guest elf then we may not have been able to put it where it - * requested. This is the relocation offset */ - int relocation_offset; - /* Guest physical address of where we built its page directory */ - uintptr_t pd; - /* Guest physical address of where we stashed the kernel cmd line */ - uintptr_t cmd_line; - size_t cmd_line_len; - /* Guest physical address of where we created the boot information */ - uintptr_t boot_info; - /* Boot module information */ - uintptr_t boot_module_paddr; - size_t boot_module_size; -} guest_image_t; - -/* Represents a libsel4vmm vcpu */ -typedef struct vmm_vcpu { - /* kernel objects */ - seL4_CPtr guest_vcpu; - - /* context */ - guest_state_t guest_state; - - /* parent vmm */ - vmm_t *vmm; - - vmm_lapic_t *lapic; - int vcpu_id; - - /* is the vcpu online */ - int online; -} vmm_vcpu_t; - -/* Represents a vmm instance that runs a single guest with one or more vcpus */ -typedef struct vmm { - /* Debugging state for sanity */ - int done_host_init; - int done_guest_init; - /* Allocators, vspaces, and other things for resource management */ - vka_t vka; - simple_t host_simple; - vspace_t host_vspace; - /* due ot limitation of the vka interface we still need an explicit allocman */ - allocman_t *allocman; - - /* TCB of the VMM thread - * TODO: Should eventually have one vmm thread per vcpu */ - seL4_CPtr tcb; - seL4_CPtr sc; - seL4_CPtr sched_ctrl; - - /* platform callback functions */ - platform_callbacks_t plat_callbacks; - - /* Default page size to use */ - int page_size; - - /* Memory related */ - guest_image_t guest_image; - seL4_CPtr guest_pd; - guest_memory_t guest_mem; - - /* Exit handling table */ - vmexit_handler_ptr vmexit_handlers[VMM_EXIT_REASON_NUM]; - /* PCI emulation state */ - vmm_pci_space_t pci; - - /* IO port management */ - vmm_io_port_list_t io_port; - - /* MMIO management. Should probably be per-vcpu, e.g. we can't handle the - * guest trying to remap a local APIC */ - vmm_mmio_list_t mmio_list; - - unsigned int num_vcpus; - vmm_vcpu_t *vcpus; - - vmcall_handler_t *vmcall_handlers; - unsigned int vmcall_num_handlers; - - /*TODO add - map of vcpu affinities - */ -} vmm_t; - -/* Finalize the VM before running it */ -int vmm_finalize(vmm_t *vmm); - -/*running vmm moudle*/ -void vmm_run(vmm_t *vmm); - -/* TODO htf did these get here? lets refactor everything */ -void vmm_sync_guest_state(vmm_vcpu_t *vcpu); -void vmm_sync_guest_context(vmm_vcpu_t *vcpu); -void vmm_reply_vm_exit(vmm_vcpu_t *vcpu); - -/* mint a badged copy of the vmm's async event notification cap */ -seL4_CPtr vmm_create_async_event_notification_cap(vmm_t *vmm, seL4_Word badge); -
diff --git a/libsel4vmm/include/vmm/vmm_manager.h b/libsel4vmm/include/vmm/vmm_manager.h deleted file mode 100644 index c5bbf23..0000000 --- a/libsel4vmm/include/vmm/vmm_manager.h +++ /dev/null
@@ -1,73 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#pragma once - -#define VMM_MAGIC 'V' -#define NUM_VMM_OPS 50 - -/* vmm_args_t */ -#define VMM_MANAGER_OPEN 0 -#define VMM_MANAGER_CLOSE 1 -#define VMM_PROBE 6 -#define VMM_NUM_OF_DOM 7 -#define VMM_LIST_DOM 8 -#define VMM_CONNECT 14 -#define VMM_DISCONNECT 15 -#define VMM_TESTS 16 - -/* vchan_args_T */ -#define VCHAN_SEND 19 -#define VCHAN_RECV 20 - -/* vchan_check_args_t */ -#define VMM_GUEST_NUM 23 -#define SEL4_VCHAN_CONNECT 24 -#define SEL4_VCHAN_CLOSE 25 -#define SEL4_VCHAN_STATE 26 -#define SEL4_VCHAN_WAIT 27 -#define SEL4_VCHAN_BUF 28 - -#define DATATYPE_INT 0 - -#define DRIVER_NAME "vmm_manager" - -/* Arguments used in initial vmcall call */ -#define DRIVER_ARGS_MAX_SIZE 256 -#define VMM_MANAGER_TOKEN 0xfabbdad - -typedef int vmm_datatype_t; - -/* User Level - Macros for interacting with the vmm_driver ioctl */ -#define VM_IOCTL_CMD(cmd, sz) _IOR(VMM_MAGIC, cmd, sz) - -/* Main structure used for a hypervisor call */ -typedef struct vmcall_args { - int cmd; /* Used for verifying that a vmcall is from a virtual linux driver */ - void *data; /* Pointer to a further data struct that is manipulated in a vmcall */ - int phys_data; - int err; - unsigned size; -} vmcall_args_t; - -/* Used for passing arguments to the vchan linux driver */ -typedef struct ioctl_arg { - unsigned size; - void *ptr; -} ioctl_arg_t; - -/* Argument structure used for query commands to the hypervisor */ -typedef struct vmm_args { - char ret_data[DRIVER_ARGS_MAX_SIZE]; - vmm_datatype_t datatype; -} vmm_args_t; -
diff --git a/libsel4vmm/src/driver/pci.c b/libsel4vmm/src/driver/pci.c deleted file mode 100644 index 1c5a602..0000000 --- a/libsel4vmm/src/driver/pci.c +++ /dev/null
@@ -1,157 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ -/* x86 VMM PCI Driver, which manages the host's PCI devices, and handles guest OS PCI config space - * read & writes. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <sel4/sel4.h> -#include <pci/pci.h> -#include <pci/helper.h> - -#include "vmm/debug.h" -#include "vmm/vmm.h" -#include "vmm/driver/pci.h" -#include "vmm/driver/pci_helper.h" - -int vmm_pci_init(vmm_pci_space_t *space) { - for (int i = 0; i < 32; i++) { - for(int j = 0; j < 8; j++) { - space->bus0[i][j] = NULL; - } - } - space->conf_port_addr = 0; - /* Define the initial PCI bridge */ - vmm_pci_device_def_t *bridge = malloc(sizeof(*bridge)); - if (!bridge) { - ZF_LOGE("Failed to malloc memory for pci bridge"); - return -1; - } - define_pci_host_bridge(bridge); - return vmm_pci_add_entry(space, (vmm_pci_entry_t){.cookie = bridge, .ioread = vmm_pci_mem_device_read, .iowrite = vmm_pci_entry_ignore_write}, NULL); -} - -int vmm_pci_add_entry(vmm_pci_space_t *space, vmm_pci_entry_t entry, vmm_pci_address_t *addr) { - /* Find empty dev */ - for (int i = 0; i < 32; i++) { - if (!space->bus0[i][0]) { - /* Allocate an entry */ - space->bus0[i][0] = malloc(sizeof(entry)); - *space->bus0[i][0] = entry; - /* Report addr if reqeusted */ - if (addr) { - *addr = (vmm_pci_address_t){.bus = 0, .dev = i, .fun = 0}; - } - ZF_LOGI("Adding virtual PCI device at %02x:%02x.%d", 0, i, 0); - return 0; - } - } - ZF_LOGE("No free device slot on bus 0 to add virtual pci device"); - return -1; -} - -static void make_addr_reg_from_config(uint32_t conf, vmm_pci_address_t *addr, uint8_t *reg) { - addr->bus = (conf >> 16) & MASK(8); - addr->dev = (conf >> 11) & MASK(5); - addr->fun = (conf >> 8) & MASK(3); - *reg = conf & MASK(8); -} - -static vmm_pci_entry_t *find_device(vmm_pci_space_t *self, vmm_pci_address_t addr) { - if (addr.bus != 0 || addr.dev >= 32 || addr.fun >= 8) { - return NULL; - } - return self->bus0[addr.dev][addr.fun]; -} - -int vmm_pci_io_port_in(void *cookie, unsigned int port_no, unsigned int size, unsigned int *result) { - vmm_pci_space_t *self = (vmm_pci_space_t*)cookie; - uint8_t offset; - - if (port_no >= PCI_CONF_PORT_ADDR && port_no < PCI_CONF_PORT_ADDR_END) { - offset = port_no - PCI_CONF_PORT_ADDR; - assert(port_no + size <= PCI_CONF_PORT_ADDR_END); - /* Emulate read addr. */ - *result = 0; - memcpy(result, ((char*)&self->conf_port_addr) + offset, size); - return 0; - } - assert(port_no >= PCI_CONF_PORT_DATA && port_no + size <= PCI_CONF_PORT_DATA_END); - offset = port_no - PCI_CONF_PORT_DATA; - - /* construct a pci address from the current value in the config port */ - vmm_pci_address_t addr; - uint8_t reg; - make_addr_reg_from_config(self->conf_port_addr, &addr, ®); - reg += offset; - - /* Check if this device exists */ - vmm_pci_entry_t *dev = find_device(self, addr); - if (!dev) { - /* if the guest strayed from bus 0 then somethign went wrong. otherwise random reads - * could just be it probing for devices */ - if (addr.bus != 0) { - ZF_LOGI("Guest attempted access to non existent device %02x:%02x.%d register 0x%x", addr.bus, addr.dev, addr.fun, reg); - } else { - DPRINTF(3, "Ignoring guest probe for device %02x:%02x.%d register 0x%x\n", addr.bus, addr.dev, addr.fun, reg); - } - *result = -1; - return 0; - } - int error = dev->ioread(dev->cookie, reg, size, result); - if (error) { - return error; - } - /* Strip out any multi function reporting */ - if (reg + size > PCI_HEADER_TYPE && reg <= PCI_HEADER_TYPE) { - /* This read overlapped with the header type, work out where it is and mask - * the MF bit out */ - int header_offset = PCI_HEADER_TYPE - reg; - unsigned int mf_mask = ~(BIT(7) << (header_offset * 8)); - (*result) &= mf_mask; - } - return 0; -} - -int vmm_pci_io_port_out(void *cookie, unsigned int port_no, unsigned int size, unsigned int value) { - vmm_pci_space_t *self = (vmm_pci_space_t*)cookie; - uint8_t offset; - - if (port_no >= PCI_CONF_PORT_ADDR && port_no < PCI_CONF_PORT_ADDR_END) { - offset = port_no - PCI_CONF_PORT_ADDR; - assert(port_no + size <= PCI_CONF_PORT_ADDR_END); - /* Emulated set addr. First mask out the bottom two bits of the address that - * should never be used*/ - value &= ~MASK(2); - memcpy(((char*)&self->conf_port_addr) + offset, &value, size); - return 0; - } - assert(port_no >= PCI_CONF_PORT_DATA && port_no + size <= PCI_CONF_PORT_DATA_END); - offset = port_no - PCI_CONF_PORT_DATA; - - /* construct a pci address from the current value in the config port */ - vmm_pci_address_t addr; - uint8_t reg; - make_addr_reg_from_config(self->conf_port_addr, &addr, ®); - reg += offset; - - /* Check if this device exists */ - vmm_pci_entry_t *dev = find_device(self, addr); - if (!dev) { - ZF_LOGI("Guest attempted access to non existent device %02x:%02x.%d register 0x%x", addr.bus, addr.dev, addr.fun, reg); - return 0; - } - return dev->iowrite(dev->cookie, reg + offset, size, value); -}
diff --git a/libsel4vmm/src/driver/pci_helper.c b/libsel4vmm/src/driver/pci_helper.c deleted file mode 100644 index d4f873c..0000000 --- a/libsel4vmm/src/driver/pci_helper.c +++ /dev/null
@@ -1,436 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sel4/sel4.h> - -#include <pci/virtual_pci.h> -#include <pci/helper.h> - -#include "vmm/driver/pci_helper.h" - -typedef struct pci_bar_emulation { - vmm_pci_entry_t passthrough; - int num_bars; - vmm_pci_bar_t bars[6]; - uint32_t bar_writes[6]; -} pci_bar_emulation_t; - -typedef struct pci_irq_emulation { - vmm_pci_entry_t passthrough; - int irq; -} pci_irq_emulation_t; - -typedef struct pci_passthrough_device { - /* The address on the host system of this device */ - vmm_pci_address_t addr; - /* Ops for accessing config space */ - vmm_pci_config_t config; -} pci_passthrough_device_t; - -typedef struct pci_cap_emulation { - vmm_pci_entry_t passthrough; - int num_caps; - uint8_t *caps; - int num_ignore; - uint8_t *ignore_start; - uint8_t *ignore_end; -} pci_cap_emulation_t; - -int vmm_pci_mem_device_read(void *cookie, int offset, int size, uint32_t *result) { - if (offset < 0) { - ZF_LOGE("Offset should not be negative"); - return -1; - } - if (offset + size >= 0x40) { - ZF_LOGI("Indexing capability space not yet supported, returning 0"); - *result = 0; - return 0; - } - *result = 0; - memcpy(result, cookie + offset, size); - return 0; -} - -int vmm_pci_entry_ignore_write(void *cookie, int offset, int size, uint32_t value) { - return 0; -} - -void define_pci_host_bridge(vmm_pci_device_def_t *bridge) { - *bridge = (vmm_pci_device_def_t) { - .vendor_id = 0x5E14, - .device_id = 0x42, - .command = 0, - .status = 0, - .revision_id = 0x1, - .prog_if = 0, - .subclass = 0x0, - .class_code = 0x06, - .cache_line_size = 0, - .latency_timer = 0, - .header_type = 0x00, - .bist = 0, - .bar0 = 0, - .bar1 = 0, - .bar2 = 0, - .bar3 = 0, - .bar4 = 0, - .bar5 = 0, - .cardbus = 0, - .subsystem_vendor_id = 0, - .subsystem_id = 0, - .expansion_rom = 0, - .caps_pointer = 0, - .reserved1 = 0, - .reserved2 = 0, - .reserved3 = 0, - .interrupt_line = 0, - .interrupt_pin = 0, - .min_grant = 0, - .max_latency = 0, - .caps_len = 0, - .caps = NULL - }; -} - -static int passthrough_pci_config_ioread(void *cookie, int offset, int size, uint32_t *result) { - pci_passthrough_device_t *dev = (pci_passthrough_device_t*)cookie; - switch(size) { - case 1: - *result = dev->config.ioread8(dev->config.cookie, dev->addr, offset); - break; - case 2: - *result = dev->config.ioread16(dev->config.cookie, dev->addr, offset); - break; - case 4: - *result = dev->config.ioread32(dev->config.cookie, dev->addr, offset); - break; - default: - assert(!"Invalid size"); - } - return 0; -} - -static int passthrough_pci_config_iowrite(void *cookie, int offset, int size, uint32_t val) { - pci_passthrough_device_t *dev = (pci_passthrough_device_t*)cookie; - switch(size) { - case 1: - dev->config.iowrite8(dev->config.cookie, dev->addr, offset, val); - break; - case 2: - dev->config.iowrite16(dev->config.cookie, dev->addr, offset, val); - break; - case 4: - dev->config.iowrite32(dev->config.cookie, dev->addr, offset, val); - break; - default: - assert(!"Invalid size"); - } - return 0; -} - -static int pci_bar_emul_check_range(unsigned int offset, unsigned int size) { - if (offset < PCI_BASE_ADDRESS_0 || offset + size > PCI_BASE_ADDRESS_5 + 4) { - return 1; - } - return 0; -} - -static uint32_t pci_make_bar(pci_bar_emulation_t *emul, int bar) { - if (bar >= emul->num_bars) { - return 0; - } - uint32_t raw = 0; - raw |= emul->bars[bar].address; - if (!emul->bars[bar].ismem) { - raw |= 1; - } else { - if (emul->bars[bar].prefetchable) { - raw |= BIT(3); - } - } - raw |= (emul->bar_writes[bar] & ~MASK(emul->bars[bar].size_bits)); - return raw; -} - -static int pci_irq_emul_read(void *cookie, int offset, int size, uint32_t *result) { - pci_irq_emulation_t *emul = (pci_irq_emulation_t*)cookie; - if(offset <= PCI_INTERRUPT_LINE && offset + size > PCI_INTERRUPT_LINE) { - /* do the regular read, then patch in our value */ - int ret = emul->passthrough.ioread(emul->passthrough.cookie, offset, size, result); - if (ret) { - return ret; - } - int bit_offset = (PCI_INTERRUPT_LINE - offset) * 8; - *result &= ~(MASK(8) << bit_offset); - *result |= (emul->irq << bit_offset); - return 0; - } else { - return emul->passthrough.ioread(emul->passthrough.cookie, offset, size, result); - } -} - -static int pci_irq_emul_write(void *cookie, int offset, int size, uint32_t value) { - pci_irq_emulation_t *emul = (pci_irq_emulation_t*)cookie; - if (offset == PCI_INTERRUPT_LINE && size == 1) { - /* ignore */ - return 0; - } else if(offset < PCI_INTERRUPT_LINE && offset + size >= PCI_INTERRUPT_LINE) { - assert(!"Guest writing PCI configuration in an unsupported way"); - return -1; - } else { - return emul->passthrough.iowrite(emul->passthrough.cookie, offset, size, value); - } -} - -static int pci_bar_emul_read(void *cookie, int offset, int size, uint32_t *result) { - pci_bar_emulation_t *emul = (pci_bar_emulation_t*)cookie; - if (pci_bar_emul_check_range(offset, size)) { - return emul->passthrough.ioread(emul->passthrough.cookie, offset, size, result); - } - /* Construct the bar value */ - int bar = (offset - PCI_BASE_ADDRESS_0) / 4; - int bar_offset = offset & 3; - uint32_t bar_raw = pci_make_bar(emul, bar); - char *barp = (char*)&bar_raw; - *result = 0; - memcpy(result, barp + bar_offset, size); - return 0; -} - -static int pci_bar_emul_write(void *cookie, int offset, int size, uint32_t value) { - pci_bar_emulation_t *emul = (pci_bar_emulation_t*)cookie; - if (pci_bar_emul_check_range(offset, size)) { - return emul->passthrough.iowrite(emul->passthrough.cookie, offset, size, value); - } - /* Construct the bar value */ - int bar = (offset - PCI_BASE_ADDRESS_0) / 4; - int bar_offset = offset & 3; - char *barp = (char*)&emul->bar_writes[bar]; - memcpy(barp + bar_offset, &value, size); - return 0; -} - -vmm_pci_entry_t vmm_pci_create_bar_emulation(vmm_pci_entry_t existing, int num_bars, vmm_pci_bar_t *bars) { - pci_bar_emulation_t *bar_emul = malloc(sizeof(*bar_emul)); - assert(bar_emul); - memcpy(bar_emul->bars, bars, sizeof(vmm_pci_bar_t) * num_bars); - bar_emul->passthrough = existing; - bar_emul->num_bars = num_bars; - memset(bar_emul->bar_writes, 0, sizeof(bar_emul->bar_writes)); - return (vmm_pci_entry_t) {.cookie = bar_emul, .ioread = pci_bar_emul_read, .iowrite = pci_bar_emul_write}; -} - -vmm_pci_entry_t vmm_pci_create_irq_emulation(vmm_pci_entry_t existing, int irq) { - pci_irq_emulation_t *irq_emul = malloc(sizeof(*irq_emul)); - assert(irq_emul); - irq_emul->passthrough = existing; - irq_emul->irq = irq; - return (vmm_pci_entry_t) {.cookie = irq_emul, .ioread = pci_irq_emul_read, .iowrite = pci_irq_emul_write}; -} - -vmm_pci_entry_t vmm_pci_create_passthrough(vmm_pci_address_t addr, vmm_pci_config_t config) { - pci_passthrough_device_t *dev = malloc(sizeof(*dev)); - assert(dev); - dev->addr = addr; - dev->config = config; - ZF_LOGI("Creating passthrough device for %02x:%02x.%d", addr.bus, addr.dev, addr.fun); - return (vmm_pci_entry_t){.cookie = dev, .ioread = passthrough_pci_config_ioread, .iowrite = passthrough_pci_config_iowrite}; -} - -int vmm_pci_helper_map_bars(vmm_t *vmm, libpci_device_iocfg_t *cfg, vmm_pci_bar_t *bars) { - int i; - int bar = 0; - for (i = 0; i < 6; i++) { - if (cfg->base_addr[i] == 0) { - continue; - } - size_t size = cfg->base_addr_size[i]; - assert(size != 0); - int size_bits = 31 - CLZ(size); - if (BIT(size_bits) != size) { - ZF_LOGE("PCI bar is not power of 2 size (%zu)", size); - return -1; - } - bars[bar].size_bits = size_bits; - if (cfg->base_addr_space[i] == PCI_BASE_ADDRESS_SPACE_MEMORY) { - /* Need to map into the VMM. Make sure it is aligned */ - uintptr_t addr = vmm_map_guest_device(vmm, cfg->base_addr[i], size, BIT(size_bits)); - if(addr == 0) { - ZF_LOGE("Failed to map PCI bar %p size %zu", (void*)(uintptr_t)cfg->base_addr[i], size); - return -1; - } - bars[bar].ismem = 1; - bars[bar].address = addr; - bars[bar].prefetchable = cfg->base_addr_prefetchable[i]; - } else { - /* Need to add the IO port range */ - int error = vmm_io_port_add_passthrough(&vmm->io_port, cfg->base_addr[i], cfg->base_addr[i] + size - 1, "PCI Passthrough Device"); - if (error) { - return error; - } - bars[bar].ismem=0; - bars[bar].address = cfg->base_addr[i]; - bars[bar].prefetchable = 0; - } - bar++; - } - return bar; -} - -static int pci_cap_emul_read(void *cookie, int offset, int size, uint32_t *result) { - pci_cap_emulation_t *emul = (pci_cap_emulation_t*)cookie; - if(offset <= PCI_STATUS && offset + size > PCI_STATUS) { - /* do the regular read, then patch in our value */ - int ret = emul->passthrough.ioread(emul->passthrough.cookie, offset, size, result); - if (ret) { - return ret; - } - int bit_offset = (PCI_STATUS - offset) * 8; - *result &= ~(PCI_STATUS_CAP_LIST << bit_offset); - if (emul->num_caps > 0) { - *result |= (PCI_STATUS_CAP_LIST << bit_offset); - } - return 0; - } else if(offset <= PCI_CAPABILITY_LIST && offset + size > PCI_CAPABILITY_LIST) { - /* do the regular read, then patch in our value */ - int ret = emul->passthrough.ioread(emul->passthrough.cookie, offset, size, result); - if (ret) { - return ret; - } - int bit_offset = (PCI_CAPABILITY_LIST - offset) * 8; - *result &= ~(MASK(8) << bit_offset); - if (emul->num_caps > 0) { - *result |= (emul->caps[0] << bit_offset); - } - return 0; - } - /* see if we are reading from any location that we would prefer not to */ - int i; - for (i = 0; i < emul->num_ignore; i++) { - if (offset <= emul->ignore_start[i] && offset+size > emul->ignore_end[i]) { - /* who cares about the size, just ignore everything */ - ZF_LOGI("Attempted read at 0x%x of size %d from region 0x%x-0x%x", offset, size, emul->ignore_start[i], emul->ignore_end[i]); - *result = 0; - return 0; - } - } - /* See if we are reading a capability index */ - for (i = 0; i < emul->num_caps; i++) { - if (offset <= emul->caps[i] + 1 && offset + size > emul->caps[i] + 1) { - /* do the regular read, then patch in our value */ - int ret = emul->passthrough.ioread(emul->passthrough.cookie, offset, size, result); - if (ret) { - return ret; - } - int bit_offset = (emul->caps[i] + 1 - offset) * 8; - *result &= ~(MASK(8) << bit_offset); - if (i + 1 < emul->num_caps) { - *result |= (emul->caps[i + 1] << bit_offset); - } - return 0; - } - } - /* Pass through whatever is left */ - return emul->passthrough.ioread(emul->passthrough.cookie, offset, size, result); -} - -static int pci_cap_emul_write(void *cookie, int offset, int size, uint32_t value) { - pci_cap_emulation_t *emul = (pci_cap_emulation_t*)cookie; - /* Prevents writes to our ignored ranges. but let anything else through */ - int i; - for (i = 0; i < emul->num_ignore; i++) { - if (offset <= emul->ignore_start[i] && offset+size > emul->ignore_end[i]) { - /* who cares about the size, just ignore everything */ - ZF_LOGI("Attempted write at 0x%x of size %d from region 0x%x-0x%x", offset, size, emul->ignore_start[i], emul->ignore_end[i]); - return 0; - } - } - return emul->passthrough.iowrite(emul->passthrough.cookie, offset, size, value); -} - -vmm_pci_entry_t vmm_pci_create_cap_emulation(vmm_pci_entry_t existing, int num_caps, uint8_t *caps, int num_ranges, uint8_t *range_starts, uint8_t *range_ends) { - pci_cap_emulation_t *emul = malloc(sizeof(*emul)); - emul->passthrough = existing; - assert(emul); - emul->num_caps = num_caps; - emul->caps = malloc(sizeof(uint8_t) * num_caps); - assert(emul->caps); - memcpy(emul->caps, caps, sizeof(uint8_t) * num_caps); - emul->num_ignore = num_ranges; - emul->ignore_start = malloc(sizeof(uint8_t) * num_ranges); - assert(emul->ignore_start); - emul->ignore_end = malloc(sizeof(uint8_t) * num_ranges); - assert(emul->ignore_end); - memcpy(emul->ignore_start, range_starts, sizeof(uint8_t) * num_ranges); - memcpy(emul->ignore_end, range_ends, sizeof(uint8_t) * num_ranges); - return (vmm_pci_entry_t) {.cookie = emul, .ioread = pci_cap_emul_read, .iowrite = pci_cap_emul_write}; -} - -#define MAX_CAPS 256 - -vmm_pci_entry_t vmm_pci_no_msi_cap_emulation(vmm_pci_entry_t existing) { - uint32_t value; - int UNUSED error; - /* Ensure this is a type 0 device */ - value = 0; - error = existing.ioread(existing.cookie, PCI_HEADER_TYPE, 1, &value); - assert(!error); - assert( (value & (~BIT(7))) == PCI_HEADER_TYPE_NORMAL); - /* Check if it has capability space */ - error = existing.ioread(existing.cookie, PCI_STATUS, 1, &value); - assert(!error); - if (! (value & PCI_STATUS_CAP_LIST)) { - return existing; - } - /* First we need to scan the capability space, and detect any PCI caps - * while we're at it */ - int num_caps; - uint8_t caps[MAX_CAPS]; - int num_ignore; - uint8_t ignore_start[2]; - uint8_t ignore_end[2]; - error = existing.ioread(existing.cookie, PCI_CAPABILITY_LIST, 1, &value); - assert(!error); - /* Mask off the bottom 2 bits, which are reserved */ - value &= ~MASK(2); - num_caps = 0; - num_ignore = 0; - while (value != 0) { - uint32_t cap_type = 0; - error = existing.ioread(existing.cookie, value, 1, &cap_type); - assert(!error); - if (cap_type == PCI_CAP_ID_MSI) { - assert(num_ignore < 2); - ignore_start[num_ignore] = value; - ignore_end[num_ignore] = value + 20; - num_ignore++; - } else if (cap_type == PCI_CAP_ID_MSIX) { - ignore_start[num_ignore] = value; - ignore_end[num_ignore] = value + 8; - num_ignore++; - } else { - assert(num_caps < MAX_CAPS); - caps[num_caps] = (uint8_t)value; - num_caps++; - } - error = existing.ioread(existing.cookie, value + 1, 1, &value); - assert(!error); - } - if (num_ignore > 0) { - return vmm_pci_create_cap_emulation(existing, num_caps, caps, num_ignore, ignore_start, ignore_end); - } else { - return existing; - } -}
diff --git a/libsel4vmm/src/driver/virtio_emul.c b/libsel4vmm/src/driver/virtio_emul.c deleted file mode 100644 index 80bfb0d..0000000 --- a/libsel4vmm/src/driver/virtio_emul.c +++ /dev/null
@@ -1,418 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> - -#include <string.h> - -#include <vmm/driver/virtio_emul.h> -#include <ethdrivers/virtio/virtio_pci.h> -#include <ethdrivers/virtio/virtio_net.h> -#include <ethdrivers/virtio/virtio_ring.h> -#include <ethdrivers/virtio/virtio_config.h> - -#define RX_QUEUE 0 -#define TX_QUEUE 1 - -#define BUF_SIZE 2048 - -typedef struct ethif_virtio_emul_internal { - struct eth_driver driver; - int status; - uint8_t mac[6]; - uint16_t queue; - struct vring vring[2]; - uint16_t queue_size[2]; - uint32_t queue_pfn[2]; - uint16_t last_idx[2]; - vspace_t guest_vspace; - ps_dma_man_t dma_man; -} ethif_virtio_emul_internal_t; - -typedef struct emul_tx_cookie { - uint16_t desc_head; - void *vaddr; -} emul_tx_cookie_t; - -static int read_guest_mem(uintptr_t phys, void *vaddr, size_t size, size_t offset, void *cookie) -{ - memcpy(cookie + offset, vaddr, size); - return 0; -} - -static int write_guest_mem(uintptr_t phys, void *vaddr, size_t size, size_t offset, void *cookie) -{ - memcpy(vaddr, cookie + offset, size); - return 0; -} - -static uint16_t ring_avail_idx(ethif_virtio_emul_t *emul, struct vring *vring) -{ - uint16_t idx; - vmm_guest_vspace_touch(&emul->internal->guest_vspace, (uintptr_t)&vring->avail->idx, sizeof(vring->avail->idx), - read_guest_mem, &idx); - return idx; -} - -static uint16_t ring_avail(ethif_virtio_emul_t *emul, struct vring *vring, uint16_t idx) -{ - uint16_t elem; - vmm_guest_vspace_touch(&emul->internal->guest_vspace, (uintptr_t) & (vring->avail->ring[idx % vring->num]), - sizeof(elem), read_guest_mem, &elem); - return elem; -} - -static struct vring_desc ring_desc(ethif_virtio_emul_t *emul, struct vring *vring, uint16_t idx) -{ - struct vring_desc desc; - vmm_guest_vspace_touch(&emul->internal->guest_vspace, (uintptr_t) & (vring->desc[idx]), sizeof(desc), read_guest_mem, - &desc); - return desc; -} - -static void ring_used_add(ethif_virtio_emul_t *emul, struct vring *vring, struct vring_used_elem elem) -{ - uint16_t guest_idx; - vmm_guest_vspace_touch(&emul->internal->guest_vspace, (uintptr_t)&vring->used->idx, sizeof(vring->used->idx), - read_guest_mem, &guest_idx); - vmm_guest_vspace_touch(&emul->internal->guest_vspace, (uintptr_t)&vring->used->ring[guest_idx % vring->num], - sizeof(elem), write_guest_mem, &elem); - guest_idx++; - vmm_guest_vspace_touch(&emul->internal->guest_vspace, (uintptr_t)&vring->used->idx, sizeof(vring->used->idx), - write_guest_mem, &guest_idx); -} - -static uintptr_t emul_allocate_rx_buf(void *iface, size_t buf_size, void **cookie) -{ - ethif_virtio_emul_t *emul = (ethif_virtio_emul_t *)iface; - ethif_virtio_emul_internal_t *net = emul->internal; - if (buf_size > BUF_SIZE) { - return 0; - } - void *vaddr = ps_dma_alloc(&net->dma_man, BUF_SIZE, net->driver.dma_alignment, 1, PS_MEM_NORMAL); - if (!vaddr) { - return 0; - } - uintptr_t phys = ps_dma_pin(&net->dma_man, vaddr, BUF_SIZE); - *cookie = vaddr; - return phys; -} - -static void emul_rx_complete(void *iface, unsigned int num_bufs, void **cookies, unsigned int *lens) -{ - ethif_virtio_emul_t *emul = (ethif_virtio_emul_t *)iface; - ethif_virtio_emul_internal_t *net = emul->internal; - unsigned int tot_len = 0; - int i; - struct vring *vring = &net->vring[RX_QUEUE]; - for (i = 0; i < num_bufs; i++) { - tot_len += lens[i]; - } - /* grab the next receive chain */ - struct virtio_net_hdr virtio_hdr; - memset(&virtio_hdr, 0, sizeof(virtio_hdr)); - uint16_t guest_idx = ring_avail_idx(emul, vring); - uint16_t idx = net->last_idx[RX_QUEUE]; - if (idx != guest_idx) { - /* total length of the written packet so far */ - size_t tot_written = 0; - /* amount of the current descriptor written */ - size_t desc_written = 0; - /* how much we have written of the current buffer */ - size_t buf_written = 0; - /* the current buffer. -1 indicates the virtio net buffer */ - int current_buf = -1; - uint16_t desc_head = ring_avail(emul, vring, idx); - /* start walking the descriptors */ - struct vring_desc desc; - uint16_t desc_idx = desc_head; - do { - desc = ring_desc(emul, vring, desc_idx); - /* determine how much we can copy */ - uint32_t copy; - void *buf_base = NULL; - if (current_buf == -1) { - copy = sizeof(struct virtio_net_hdr) - buf_written; - buf_base = &virtio_hdr; - } else { - copy = lens[current_buf] - buf_written; - buf_base = cookies[current_buf]; - } - copy = MIN(copy, desc.len - desc_written); - /* copy it */ - vmm_guest_vspace_touch(&net->guest_vspace, (uintptr_t)desc.addr + desc_written, copy, write_guest_mem, - buf_base + buf_written); - /* update amounts */ - tot_written += copy; - desc_written += copy; - buf_written += copy; - /* see what's gone over */ - if (desc_written == desc.len) { - if (!desc.flags & VRING_DESC_F_NEXT) { - /* descriptor chain is too short to hold the whole packet. - * just truncate */ - break; - } - desc_idx = desc.next; - desc_written = 0; - } - if (current_buf == -1) { - if (buf_written == sizeof(struct virtio_net_hdr)) { - current_buf++; - buf_written = 0; - } - } else { - if (buf_written == lens[current_buf]) { - current_buf++; - buf_written = 0; - } - } - } while (current_buf < num_bufs); - /* now put it in the used ring */ - struct vring_used_elem used_elem = {desc_head, tot_written}; - ring_used_add(emul, vring, used_elem); - - /* record that we've used this descriptor chain now */ - net->last_idx[RX_QUEUE]++; - /* notify the guest that there is something in its used ring */ - net->driver.i_fn.raw_handleIRQ(&net->driver, 0); - } - for (i = 0; i < num_bufs; i++) { - ps_dma_unpin(&net->dma_man, cookies[i], BUF_SIZE); - ps_dma_free(&net->dma_man, cookies[i], BUF_SIZE); - } -} - -static void emul_tx_complete(void *iface, void *cookie) -{ - ethif_virtio_emul_t *emul = (ethif_virtio_emul_t *)iface; - ethif_virtio_emul_internal_t *net = emul->internal; - emul_tx_cookie_t *tx_cookie = (emul_tx_cookie_t *)cookie; - /* free the dma memory */ - ps_dma_unpin(&net->dma_man, tx_cookie->vaddr, BUF_SIZE); - ps_dma_free(&net->dma_man, tx_cookie->vaddr, BUF_SIZE); - /* put the descriptor chain into the used list */ - struct vring_used_elem used_elem = {tx_cookie->desc_head, 0}; - ring_used_add(emul, &net->vring[TX_QUEUE], used_elem); - free(tx_cookie); - /* notify the guest that we have completed some of its buffers */ - net->driver.i_fn.raw_handleIRQ(&net->driver, 0); -} - -static void emul_notify_tx(ethif_virtio_emul_t *emul) -{ - ethif_virtio_emul_internal_t *net = emul->internal; - struct vring *vring = &net->vring[TX_QUEUE]; - /* read the index */ - uint16_t guest_idx = ring_avail_idx(emul, vring); - /* process what we can of the ring */ - uint16_t idx = net->last_idx[TX_QUEUE]; - while (idx != guest_idx) { - uint16_t desc_head; - /* read the head of the descriptor chain */ - desc_head = ring_avail(emul, vring, idx); - /* allocate a packet */ - void *vaddr = ps_dma_alloc(&net->dma_man, BUF_SIZE, net->driver.dma_alignment, 1, PS_MEM_NORMAL); - if (!vaddr) { - /* try again later */ - break; - } - uintptr_t phys = ps_dma_pin(&net->dma_man, vaddr, BUF_SIZE); - assert(phys); - /* length of the final packet to deliver */ - uint32_t len = 0; - /* we want to skip the initial virtio header, as this should - * not be sent to the actual ethernet driver. This records - * how much we have skipped so far. */ - uint32_t skipped = 0; - /* start walking the descriptors */ - struct vring_desc desc; - uint16_t desc_idx = desc_head; - do { - desc = ring_desc(emul, vring, desc_idx); - uint32_t skip = 0; - /* if we haven't yet skipped the full virtio net header, work - * out how much of this descriptor should be skipped */ - if (skipped < sizeof(struct virtio_net_hdr)) { - skip = MIN(sizeof(struct virtio_net_hdr) - skipped, desc.len); - skipped += skip; - } - /* truncate packets that are too large */ - uint32_t this_len = desc.len - skip; - this_len = MIN(BUF_SIZE - len, this_len); - vmm_guest_vspace_touch(&net->guest_vspace, (uintptr_t)desc.addr + skip, this_len, read_guest_mem, vaddr + len); - len += this_len; - desc_idx = desc.next; - } while (desc.flags & VRING_DESC_F_NEXT); - /* ship it */ - emul_tx_cookie_t *cookie = malloc(sizeof(*cookie)); - assert(cookie); - cookie->desc_head = desc_head; - cookie->vaddr = vaddr; - int result = net->driver.i_fn.raw_tx(&net->driver, 1, &phys, &len, cookie); - switch (result) { - case ETHIF_TX_COMPLETE: - emul_tx_complete(emul, cookie); - break; - case ETHIF_TX_FAILED: - ps_dma_unpin(&net->dma_man, vaddr, BUF_SIZE); - ps_dma_free(&net->dma_man, vaddr, BUF_SIZE); - free(cookie); - break; - } - /* next */ - idx++; - } - /* update which parts of the ring we have processed */ - net->last_idx[TX_QUEUE] = idx; -} - -static void emul_tx_complete_external(void *iface, void *cookie) -{ - emul_tx_complete(iface, cookie); - /* space may have cleared for additional transmits */ - emul_notify_tx(iface); -} - -static struct raw_iface_callbacks emul_callbacks = { - .tx_complete = emul_tx_complete_external, - .rx_complete = emul_rx_complete, - .allocate_rx_buf = emul_allocate_rx_buf -}; - -static int emul_io_in(struct ethif_virtio_emul *emul, unsigned int offset, unsigned int size, unsigned int *result) -{ - switch (offset) { - case VIRTIO_PCI_HOST_FEATURES: - assert(size == 4); - *result = BIT(VIRTIO_NET_F_MAC); - break; - case VIRTIO_PCI_STATUS: - assert(size == 1); - *result = emul->internal->status; - break; - case VIRTIO_PCI_QUEUE_NUM: - assert(size == 2); - *result = emul->internal->queue_size[emul->internal->queue]; - break; - case 0x14 ... 0x19: - assert(size == 1); - *result = emul->internal->mac[offset - 0x14]; - break; - case VIRTIO_PCI_QUEUE_PFN: - assert(size == 4); - *result = emul->internal->queue_pfn[emul->internal->queue]; - break; - case VIRTIO_PCI_ISR: - assert(size == 1); - *result = 1; - break; - default: - printf("Unhandled offset of 0x%x of size %d, reading\n", offset, size); - assert(!"panic"); - } - return 0; -} - -static int emul_io_out(struct ethif_virtio_emul *emul, unsigned int offset, unsigned int size, unsigned int value) -{ - switch (offset) { - case VIRTIO_PCI_GUEST_FEATURES: - assert(size == 4); - assert(value == BIT(VIRTIO_NET_F_MAC)); - break; - case VIRTIO_PCI_STATUS: - assert(size == 1); - emul->internal->status = value & 0xff; - break; - case VIRTIO_PCI_QUEUE_SEL: - assert(size == 2); - emul->internal->queue = (value & 0xffff); - assert(emul->internal->queue == 0 || emul->internal->queue == 1); - break; - case VIRTIO_PCI_QUEUE_PFN: { - assert(size == 4); - int queue = emul->internal->queue; - emul->internal->queue_pfn[queue] = value; - vring_init(&emul->internal->vring[queue], emul->internal->queue_size[queue], (void *)(uintptr_t)(value << 12), - VIRTIO_PCI_VRING_ALIGN); - break; - } - case VIRTIO_PCI_QUEUE_NOTIFY: - if (value == RX_QUEUE) { - /* Currently RX packets will just get dropped if there was no space - * so we will never have work to do if the client suddenly adds - * more buffers */ - } else if (value == TX_QUEUE) { - emul_notify_tx(emul); - } - break; - default: - printf("Unhandled offset of 0x%x of size %d, writing 0x%x\n", offset, size, value); - assert(!"panic"); - } - return 0; -} - -static int emul_notify(ethif_virtio_emul_t *emul) -{ - if (emul->internal->status != VIRTIO_CONFIG_S_DRIVER_OK) { - return -1; - } - emul_notify_tx(emul); - return 0; -} - -ethif_virtio_emul_t *ethif_virtio_emul_init(ps_io_ops_t io_ops, int queue_size, vspace_t *guest_vspace, - ethif_driver_init driver, void *config) -{ - ethif_virtio_emul_t *emul = NULL; - ethif_virtio_emul_internal_t *internal = NULL; - int err; - emul = malloc(sizeof(*emul)); - internal = malloc(sizeof(*internal)); - if (!emul || !internal) { - goto error; - } - memset(emul, 0, sizeof(*emul)); - memset(internal, 0, sizeof(*internal)); - emul->internal = internal; - emul->io_in = emul_io_in; - emul->io_out = emul_io_out; - emul->notify = emul_notify; - internal->queue_size[RX_QUEUE] = queue_size; - internal->queue_size[TX_QUEUE] = queue_size; - /* create dummy rings. we never actually dereference the rings so they can be null */ - vring_init(&internal->vring[RX_QUEUE], emul->internal->queue_size[RX_QUEUE], 0, VIRTIO_PCI_VRING_ALIGN); - vring_init(&internal->vring[TX_QUEUE], emul->internal->queue_size[RX_QUEUE], 0, VIRTIO_PCI_VRING_ALIGN); - internal->driver.cb_cookie = emul; - internal->driver.i_cb = emul_callbacks; - internal->guest_vspace = *guest_vspace; - internal->dma_man = io_ops.dma_manager; - err = driver(&internal->driver, io_ops, config); - if (err) { - ZF_LOGE("Fafiled to initialize driver"); - goto error; - } - int mtu; - internal->driver.i_fn.low_level_init(&internal->driver, internal->mac, &mtu); - return emul; -error: - if (emul) { - free(emul); - } - if (internal) { - free(internal); - } - return NULL; -}
diff --git a/libsel4vmm/src/platform/acpi.c b/libsel4vmm/src/platform/acpi.c deleted file mode 100644 index 8d60571..0000000 --- a/libsel4vmm/src/platform/acpi.c +++ /dev/null
@@ -1,194 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* Routines for generating guest ACPI tables. -Author: W.A. */ - -#include <stdlib.h> -#include <string.h> - -#include "vmm/debug.h" -#include "vmm/platform/acpi.h" -#include "vmm/platform/guest_memory.h" -#include "vmm/platform/guest_vspace.h" -#include "vmm/processor/apicdef.h" - -#include "platsupport/plat/acpi/acpi.h" - -#define APIC_FLAGS_ENABLED (1) - -uint8_t acpi_calc_checksum(const char* table, int length) -{ - uint32_t sum = 0; - - for (int i = 0; i < length; i++) { - sum += *table++; - } - - return 0x100 - (sum & 0xFF); -} - -static void acpi_fill_table_head(acpi_header_t *head, const char *signature, uint8_t rev) { - const char *oem = "NICTA "; - const char *padd = " "; - memcpy(head->signature, signature, sizeof(head->signature)); - memcpy(head->oem_id, oem, sizeof(head->oem_id)); - memcpy(head->creator_id, oem, sizeof(head->creator_id)); - memcpy(head->oem_table_id, signature, sizeof(head->signature)); - memcpy(head->oem_table_id + sizeof(head->signature), padd, 4); - - head->revision = rev; - head->checksum = 0; - head->length = sizeof(*head); - head->oem_revision = rev; - head->creator_revision = 1; -} - -static int make_guest_acpi_tables_continued(uintptr_t paddr, void *vaddr, - size_t size, size_t offset, void *cookie) { - (void)offset; - memcpy((char *)vaddr, (char *)cookie, size); - return 0; -} - -// Give some ACPI tables to the guest -int make_guest_acpi_tables(vmm_t *vmm) { - DPRINTF(2, "Making ACPI tables\n"); - - int cpus = vmm->num_vcpus; - - int err; - - // XSDT and other tables - void *tables[MAX_ACPI_TABLES]; - size_t table_sizes[MAX_ACPI_TABLES]; - int num_tables = 1; - - // MADT - int madt_size = sizeof(acpi_madt_t) - /* + sizeof(acpi_madt_ioapic_t)*/ - + sizeof(acpi_madt_local_apic_t) * cpus; - acpi_madt_t *madt = malloc(madt_size); - acpi_fill_table_head(&madt->header, "APIC", 3); - madt->local_int_crt_address = APIC_DEFAULT_PHYS_BASE; - madt->flags = 1; - - char *madt_entry = (char *)madt + sizeof(acpi_madt_t); - -#if 0 - acpi_madt_ioapic_t ioapic = { // MADT IOAPIC entry - .header = { - .type = ACPI_APIC_IOAPIC, - .length = sizeof(acpi_madt_ioapic_t) - }, - .ioapic_id = 0, - .address = IOAPIC_DEFAULT_PHYS_BASE, - .gs_interrupt_base = 0 // TODO set this up? - }; - memcpy(madt_entry, &ioapic, sizeof(ioapic)); - madt_entry += sizeof(ioapic); -#endif - - for (int i = 0; i < cpus; i++) { // MADT APIC entries - acpi_madt_local_apic_t apic = { - .header = { - .type = ACPI_APIC_LOCAL, - .length = sizeof(acpi_madt_local_apic_t) - }, - .processor_id = i + 1, - .apic_id = i, - .flags = APIC_FLAGS_ENABLED - }; - memcpy(madt_entry, &apic, sizeof(apic)); - madt_entry += sizeof(apic); - } - - madt->header.length = madt_size; - madt->header.checksum = acpi_calc_checksum((char *)madt, madt_size); - - tables[num_tables] = madt; - table_sizes[num_tables] = madt_size; - num_tables++; - - // Could set up other tables here... - - // XSDT - size_t xsdt_size = sizeof(acpi_xsdt_t) + sizeof(uint64_t) * (num_tables - 1); - - // How much space will all the tables take up? - size_t acpi_size = xsdt_size; - for (int i = 1; i < num_tables; i++) { - acpi_size += table_sizes[i]; - } - - // Allocate some frames for this - uintptr_t xsdt_addr = 0xe1000; // TODO actually allocate frames, can be anywhere - - acpi_xsdt_t *xsdt = malloc(xsdt_size); - acpi_fill_table_head(&xsdt->header, "XSDT", 1); - - // Add previous tables to XSDT pointer list - uintptr_t table_paddr = xsdt_addr + xsdt_size; - uint64_t *entry = (uint64_t *)((char *)xsdt + sizeof(acpi_xsdt_t)); - for (int i = 1; i < num_tables; i++) { - *entry++ = (uint64_t)table_paddr; - table_paddr += table_sizes[i]; - } - - xsdt->header.length = xsdt_size; - xsdt->header.checksum = acpi_calc_checksum((char *)xsdt, xsdt_size); - - tables[0] = xsdt; - table_sizes[0] = xsdt_size; - - // Copy all the tables to guest - table_paddr = xsdt_addr; - for (int i = 0; i < num_tables; i++) { - DPRINTF(2, "ACPI table \"%.4s\", addr = %p, size = %zu bytes\n", - (char *)tables[i], (void*)table_paddr, table_sizes[i]); - err = vmm_guest_vspace_touch(&vmm->guest_mem.vspace, table_paddr, - table_sizes[i], make_guest_acpi_tables_continued, tables[i]); - if (err) { - return err; - } - table_paddr += table_sizes[i]; - } - - // RSDP - uintptr_t rsdp_addr = ACPI_START; - err = vmm_alloc_guest_device_at(vmm, ACPI_START, sizeof(acpi_rsdp_t)); - if (err) { - return err; - } - - acpi_rsdp_t rsdp = { - .signature = "RSD PTR ", - .oem_id = "NICTA ", - .revision = 2, /* ACPI v3*/ - .checksum = 0, - .rsdt_address = xsdt_addr, - /* rsdt_addrss will not be inspected as the xsdt is present. - This is not ACPI 1 compliant */ - .length = sizeof(acpi_rsdp_t), - .xsdt_address = xsdt_addr, - .extended_checksum = 0, - .reserved = {0} - }; - - rsdp.checksum = acpi_calc_checksum((char *)&rsdp, 20); - rsdp.extended_checksum = acpi_calc_checksum((char *)&rsdp, sizeof(rsdp)); - - DPRINTF(2, "ACPI RSDP addr = %p\n", (void*)rsdp_addr); - - return vmm_guest_vspace_touch(&vmm->guest_mem.vspace, rsdp_addr, sizeof(rsdp), - make_guest_acpi_tables_continued, &rsdp); -}
diff --git a/libsel4vmm/src/platform/boot.c b/libsel4vmm/src/platform/boot.c deleted file mode 100644 index d9eadf1..0000000 --- a/libsel4vmm/src/platform/boot.c +++ /dev/null
@@ -1,150 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* Initialization functions related to the seL4 side of vmm - * booting and management. */ - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#include <sel4/sel4.h> -#include <simple/simple.h> -#include <vka/capops.h> - -#include "vmm/platform/boot.h" -#include "vmm/platform/guest_vspace.h" -#include "vmm/processor/apicdef.h" -#include "vmm/processor/lapic.h" - -int vmm_init(vmm_t *vmm, allocman_t *allocman, simple_t simple, vka_t vka, vspace_t vspace, - platform_callbacks_t callbacks) -{ - int err; - memset(vmm, 0, sizeof(vmm_t)); - vmm->allocman = allocman; - vmm->vka = vka; - vmm->host_simple = simple; - vmm->host_vspace = vspace; - vmm->plat_callbacks = callbacks; - vmm->tcb = simple_get_tcb(&simple); - vmm->sc = simple_get_sc(&simple); - vmm->sched_ctrl = simple_get_sched_ctrl(&simple, 0); - // Currently set this to 4k pages by default - vmm->page_size = seL4_PageBits; - err = vmm_pci_init(&vmm->pci); - if (err) { - return err; - } - err = vmm_io_port_init(&vmm->io_port); - if (err) { - return err; - } - err = vmm_mmio_init(&vmm->mmio_list); - if (err) { - return err; - } - - vmm->vmcall_handlers = NULL; - vmm->vmcall_num_handlers = 0; - - return 0; -} - -int vmm_init_host(vmm_t *vmm) -{ - vmm->done_host_init = 1; - return 0; -} - -static int vmm_init_vcpu(vmm_t *vmm, unsigned int vcpu_num, int priority) -{ - int UNUSED error; - assert(vcpu_num < vmm->num_vcpus); - vmm_vcpu_t *vcpu = &vmm->vcpus[vcpu_num]; - - /* sel4 vcpu (vmcs) */ - vcpu->guest_vcpu = vka_alloc_vcpu_leaky(&vmm->vka); - if (vcpu->guest_vcpu == 0) { - return -1; - } - - /* bind the VCPU to the VMM thread */ - error = seL4_X86_VCPU_SetTCB(vcpu->guest_vcpu, vmm->tcb); - assert(error == seL4_NoError); - - vcpu->vmm = vmm; - vcpu->vcpu_id = vcpu_num; - - /* All LAPICs are created enabled, in virtual wire mode */ - vmm_create_lapic(vcpu, 1); - - return 0; -} - -int vmm_init_guest(vmm_t *vmm, int priority) -{ - return vmm_init_guest_multi(vmm, priority, 1); -} - -int vmm_init_guest_multi(vmm_t *vmm, int priority, int num_vcpus) -{ - int error; - - assert(vmm->done_host_init); - - vmm->num_vcpus = num_vcpus; - vmm->vcpus = malloc(num_vcpus * sizeof(vmm_vcpu_t)); - if (!vmm->vcpus) { - return -1; - } - - /* Create an EPT which is the pd for all the vcpu tcbs */ - vmm->guest_pd = vka_alloc_ept_pml4_leaky(&vmm->vka); - if (vmm->guest_pd == 0) { - return -1; - } - /* Assign an ASID */ - error = simple_ASIDPool_assign(&vmm->host_simple, vmm->guest_pd); - if (error != seL4_NoError) { - ZF_LOGE("Failed to assign ASID pool to EPT root"); - return -1; - } - /* Install the guest PD */ - error = seL4_TCB_SetEPTRoot(vmm->tcb, vmm->guest_pd); - assert(error == seL4_NoError); - /* Initialize a vspace for the guest */ - error = vmm_get_guest_vspace(&vmm->host_vspace, &vmm->host_vspace, - &vmm->guest_mem.vspace, &vmm->vka, vmm->guest_pd); - if (error) { - return error; - } - - for (int i = 0; i < num_vcpus; i++) { - vmm_init_vcpu(vmm, i, priority); - } - - /* Init guest memory information. - * TODO: should probably done elsewhere */ - vmm->guest_mem.num_ram_regions = 0; - vmm->guest_mem.ram_regions = malloc(0); - - vmm_mmio_add_handler(&vmm->mmio_list, APIC_DEFAULT_PHYS_BASE, - APIC_DEFAULT_PHYS_BASE + sizeof(struct local_apic_regs) - 1, - NULL, "Local APIC", vmm_apic_mmio_read, vmm_apic_mmio_write); - - vmm->done_guest_init = 1; - return 0; -}
diff --git a/libsel4vmm/src/platform/boot_guest.c b/libsel4vmm/src/platform/boot_guest.c deleted file mode 100644 index 00d3dc0..0000000 --- a/libsel4vmm/src/platform/boot_guest.c +++ /dev/null
@@ -1,646 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* Guest specific booting to do with elf loading and bootinfo - * manipulation */ - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cpio/cpio.h> -#include <elf/elf.h> -#include <sel4utils/mapping.h> -#include <vka/capops.h> - -#include "vmm/debug.h" -#include "vmm/processor/platfeature.h" -#include "vmm/platform/boot_guest.h" -#include "vmm/platform/guest_memory.h" -#include "vmm/platform/e820.h" -#include "vmm/platform/bootinfo.h" -#include "vmm/platform/guest_vspace.h" -#include "vmm/platform/elf_helper.h" -#include "vmm/platform/acpi.h" - -#include <sel4/arch/bootinfo_types.h> - -#define VMM_VMCS_CR0_MASK (X86_CR0_PG | X86_CR0_PE) -#define VMM_VMCS_CR0_VALUE VMM_VMCS_CR0_MASK - -// We need to own the PSE and PAE bits up until the guest has actually turned on paging, -// then it can control them -#define VMM_VMCS_CR4_MASK (X86_CR4_PSE | X86_CR4_PAE | X86_CR4_VMXE) -#define VMM_VMCS_CR4_VALUE (X86_CR4_PSE | X86_CR4_VMXE) - -typedef struct boot_guest_cookie { - vmm_t *vmm; - FILE *file; -} boot_guest_cookie_t; - -static int guest_elf_write_address(uintptr_t paddr, void *vaddr, size_t size, size_t offset, void *cookie) -{ - memcpy(vaddr, cookie + offset, size); - return 0; -} - -static int guest_elf_read_address(uintptr_t paddr, void *vaddr, size_t size, size_t offset, void *cookie) -{ - memcpy(cookie + offset, vaddr, size); - return 0; -} - -void vmm_plat_guest_elf_relocate(vmm_t *vmm, const char *relocs_filename) -{ - guest_image_t *image = &vmm->guest_image; - int delta = image->relocation_offset; - if (delta == 0) { - /* No relocation needed. */ - return; - } - - uintptr_t load_addr = image->link_paddr; - DPRINTF(1, "plat: relocating guest kernel from 0x%x --> 0x%x\n", (unsigned int)load_addr, - (unsigned int)(load_addr + delta)); - - /* Open the relocs file. */ - DPRINTF(2, "plat: opening relocs file %s\n", relocs_filename); - - size_t relocs_size = 0; - FILE *file = fopen(relocs_filename, "r"); - if (!file) { - printf(COLOUR_Y "ERROR: Guest OS kernel relocation is required, but corresponding" - "%s was not found. This is most likely due to a Makefile" - "error, or configuration error.\n", relocs_filename); - panic("Relocation required but relocation data file not found."); - return; - } - fseek(file, 0, SEEK_END); - relocs_size = ftell(file); - fseek(file, 0, SEEK_SET); - - /* The relocs file is the same relocs file format used by the Linux kernel decompressor to - * relocate the Linux kernel: - * - * 0 - zero terminator for 64 bit relocations - * 64 bit relocation repeated - * 0 - zero terminator for 32 bit relocations - * 32 bit relocation repeated - * <EOF> - * - * So we work backwards from the end of the file, and modify the guest kernel OS binary. - * We only support 32-bit relocations, and ignore the 64-bit data. - * - * src: Linux kernel 3.5.3 arch/x86/boot/compressed/misc.c - */ - uint32_t last_relocated_vaddr = 0xFFFFFFFF; - uint32_t num_relocations = relocs_size / sizeof(uint32_t) - 1; - for (int i = 0; ; i++) { - uint32_t vaddr; - /* Get the next relocation from the relocs file. */ - uint32_t offset = relocs_size - (sizeof(uint32_t) * (i + 1)); - fseek(file, offset, SEEK_SET); - size_t result = fread(&vaddr, sizeof(uint32_t), 1, file); - ZF_LOGF_IF(result != 1, "Read failed unexpectedly"); - if (!vaddr) { - break; - } - assert(i * sizeof(uint32_t) < relocs_size); - last_relocated_vaddr = vaddr; - - /* Calculate the corresponding guest-physical address at which we have already - allocated and mapped the ELF contents into. */ - assert(vaddr >= (uint32_t)image->link_vaddr); - uintptr_t guest_paddr = (uintptr_t)vaddr - (uintptr_t)image->link_vaddr + - (uintptr_t)(load_addr + delta); -// assert(vmm_guest_mem_check_elf_segment(resource, guest_paddr, guest_paddr + 4)); - - /* Perform the relocation. */ - DPRINTF(5, " reloc vaddr 0x%x guest_addr 0x%x\n", (unsigned int)vaddr, (unsigned int)guest_paddr); - uint32_t addr; - vmm_guest_vspace_touch(&vmm->guest_mem.vspace, guest_paddr, sizeof(int), - guest_elf_read_address, &addr); - addr += delta; - vmm_guest_vspace_touch(&vmm->guest_mem.vspace, guest_paddr, sizeof(int), - guest_elf_write_address, &addr); - - if (i && i % 50000 == 0) { - DPRINTF(2, " %u relocs done.\n", i); - } - } - DPRINTF(3, "plat: last relocated addr was %d\n", last_relocated_vaddr); - DPRINTF(2, "plat: %d kernel relocations completed.\n", num_relocations); - (void) last_relocated_vaddr; - - if (num_relocations == 0) { - panic("Relocation required, but Kernel has not been build with CONFIG_RELOCATABLE."); - } - - fclose(file); - -} - -static int vmm_guest_load_boot_module_continued(uintptr_t paddr, void *addr, size_t size, size_t offset, void *cookie) -{ - boot_guest_cookie_t *pass = (boot_guest_cookie_t *) cookie; - fseek(pass->file, offset, SEEK_SET); - size_t result = fread(addr, size, 1, pass->file); - ZF_LOGF_IF(result != 1, "Read failed unexpectedly"); - - return 0; -} - -int vmm_guest_load_boot_module(vmm_t *vmm, const char *name) -{ - uintptr_t load_addr = guest_ram_largest_free_region_start(&vmm->guest_mem); - printf("Loading boot module \"%s\" at 0x%x\n", name, (unsigned int)load_addr); - - size_t initrd_size = 0; - FILE *file = fopen(name, "r"); - if (!file) { - ZF_LOGE("Boot module \"%s\" not found.", name); - return -1; - } - fseek(file, 0, SEEK_END); - initrd_size = ftell(file); - fseek(file, 0, SEEK_SET); - if (!initrd_size) { - ZF_LOGE("Boot module has zero size. This is probably not what you want."); - return -1; - } - - vmm->guest_image.boot_module_paddr = load_addr; - vmm->guest_image.boot_module_size = initrd_size; - - guest_ram_mark_allocated(&vmm->guest_mem, load_addr, initrd_size); - boot_guest_cookie_t pass = { .vmm = vmm, .file = file}; - vmm_guest_vspace_touch(&vmm->guest_mem.vspace, load_addr, initrd_size, vmm_guest_load_boot_module_continued, &pass); - - printf("Guest memory after loading initrd:\n"); - print_guest_ram_regions(&vmm->guest_mem); - - fclose(file); - - return 0; -} - -static inline uint32_t vmm_plat_vesa_fbuffer_size(seL4_VBEModeInfoBlock_t *block) -{ - assert(block); - return ALIGN_UP(block->vbe_common.bytesPerScanLine * block->vbe12_part1.yRes, 65536); -} - -static int make_guest_page_dir_continued(uintptr_t guest_phys, void *vaddr, size_t size, size_t offset, void *cookie) -{ - assert(offset == 0); - assert(size == BIT(seL4_PageBits)); - /* Write into this frame as the init page directory: 4M pages, 1 to 1 mapping. */ - uint32_t *pd = vaddr; - for (int i = 0; i < 1024; i++) { - /* Present, write, user, page size 4M */ - pd[i] = (i << PAGE_BITS_4M) | 0x87; - } - return 0; -} - -static int make_guest_page_dir(vmm_t *vmm) -{ - /* Create a 4K Page to be our 1-1 pd */ - /* This is constructed with magical new memory that we will not tell Linux about */ - uintptr_t pd = (uintptr_t)vspace_new_pages(&vmm->guest_mem.vspace, seL4_AllRights, 1, seL4_PageBits); - if (pd == 0) { - ZF_LOGE("Failed to allocate page for initial guest pd"); - return -1; - } - printf("Guest page dir allocated at 0x%x. Creating 1-1 entries\n", (unsigned int)pd); - vmm->guest_image.pd = pd; - return vmm_guest_vspace_touch(&vmm->guest_mem.vspace, pd, BIT(seL4_PageBits), make_guest_page_dir_continued, NULL); -} - -static int make_guest_cmd_line_continued(uintptr_t phys, void *vaddr, size_t size, size_t offset, void *cookie) -{ - /* Copy the string to this area. */ - const char *cmdline = (const char *)cookie; - memcpy(vaddr, cmdline + offset, size); - return 0; -} - -static int make_guest_cmd_line(vmm_t *vmm, const char *cmdline) -{ - /* Allocate command line from guest ram */ - int len = strlen(cmdline); - uintptr_t cmd_addr = guest_ram_allocate(&vmm->guest_mem, len + 1); - if (cmd_addr == 0) { - ZF_LOGE("Failed to allocate guest cmdline (length %d)", len); - return -1; - } - printf("Constructing guest cmdline at 0x%x of size %d\n", (unsigned int)cmd_addr, len); - vmm->guest_image.cmd_line = cmd_addr; - vmm->guest_image.cmd_line_len = len; - return vmm_guest_vspace_touch(&vmm->guest_mem.vspace, cmd_addr, len + 1, make_guest_cmd_line_continued, - (void *)cmdline); -} - -static void make_guest_screen_info(vmm_t *vmm, struct screen_info *info) -{ - /* VESA information */ - seL4_X86_BootInfo_VBE vbeinfo; - ssize_t result; - int error; - result = simple_get_extended_bootinfo(&vmm->host_simple, SEL4_BOOTINFO_HEADER_X86_VBE, &vbeinfo, - sizeof(seL4_X86_BootInfo_VBE)); - uintptr_t base = 0; - size_t fbuffer_size; - if (config_set(CONFIG_VMM_VESA_FRAMEBUFFER) && result != -1) { - /* map the protected mode interface at the same location we are told about it at. - * this is just to guarantee that it ends up within the segment addressable range */ - uintptr_t pm_base = (vbeinfo.vbeInterfaceSeg << 4) + vbeinfo.vbeInterfaceOff; - error = 0; - if (pm_base > 0xc000) { - /* construct a page size and aligned region to map */ - uintptr_t aligned_pm = ROUND_DOWN(pm_base, PAGE_SIZE_4K); - int size = vbeinfo.vbeInterfaceLen + (pm_base - aligned_pm); - size = ROUND_UP(size, PAGE_SIZE_4K); - error = vmm_map_guest_device_at(vmm, aligned_pm, aligned_pm, size); - } - if (error) { - ZF_LOGE("Failed to map vbe protected mode interface for VESA frame buffer. Disabling"); - } else { - fbuffer_size = vmm_plat_vesa_fbuffer_size(&vbeinfo.vbeModeInfoBlock); - base = vmm_map_guest_device(vmm, vbeinfo.vbeModeInfoBlock.vbe20.physBasePtr, fbuffer_size, PAGE_SIZE_4K); - if (!base) { - ZF_LOGE("Failed to map base pointer for VESA frame buffer. Disabling"); - } - } - } - if (base) { - info->orig_video_isVGA = 0x23; // Tell Linux it's a VESA mode - info->lfb_width = vbeinfo.vbeModeInfoBlock.vbe12_part1.xRes; - info->lfb_height = vbeinfo.vbeModeInfoBlock.vbe12_part1.yRes; - info->lfb_depth = vbeinfo.vbeModeInfoBlock.vbe12_part1.bitsPerPixel; - - info->lfb_base = base; - info->lfb_size = fbuffer_size >> 16; - info->lfb_linelength = vbeinfo.vbeModeInfoBlock.vbe_common.bytesPerScanLine; - - info->red_size = vbeinfo.vbeModeInfoBlock.vbe12_part2.redLen; - info->red_pos = vbeinfo.vbeModeInfoBlock.vbe12_part2.redOff; - info->green_size = vbeinfo.vbeModeInfoBlock.vbe12_part2.greenLen; - info->green_pos = vbeinfo.vbeModeInfoBlock.vbe12_part2.greenOff; - info->blue_size = vbeinfo.vbeModeInfoBlock.vbe12_part2.blueLen; - info->blue_pos = vbeinfo.vbeModeInfoBlock.vbe12_part2.blueOff; - info->rsvd_size = vbeinfo.vbeModeInfoBlock.vbe12_part2.rsvdLen; - info->rsvd_pos = vbeinfo.vbeModeInfoBlock.vbe12_part2.rsvdOff; - info->vesapm_seg = vbeinfo.vbeInterfaceSeg; - info->vesapm_off = vbeinfo.vbeInterfaceOff; - info->pages = vbeinfo.vbeModeInfoBlock.vbe12_part1.planes; - } else { - memset(info, 0, sizeof(*info)); - } -} - -static int make_guest_e820_map(struct e820entry *e820, guest_memory_t *guest_memory) -{ - int i; - int entry = 0; - printf("Constructing e820 memory map for guest with:\n"); - print_guest_ram_regions(guest_memory); - /* Create an initial entry at 0 that is reserved */ - e820[entry].addr = 0; - e820[entry].size = 0; - e820[entry].type = E820_RESERVED; - assert(guest_memory->num_ram_regions > 0); - for (i = 0; i < guest_memory->num_ram_regions; i++) { - /* Check for discontinuity. We need this check since we can have multiple - * regions that are contiguous if they have different allocation flags. - * However we are reporting ALL of this memory to the guest */ - if (e820[entry].addr + e820[entry].size != guest_memory->ram_regions[i].start) { - /* Finish region. Unless it was zero sized */ - if (e820[entry].size != 0) { - entry++; - assert(entry < E820MAX); - e820[entry].addr = e820[entry - 1].addr + e820[entry - 1].size; - e820[entry].type = E820_RESERVED; - } - /* Pad region */ - e820[entry].size = guest_memory->ram_regions[i].start - e820[entry].addr; - /* Now start a new RAM region */ - entry++; - assert(entry < E820MAX); - e820[entry].addr = guest_memory->ram_regions[i].start; - e820[entry].type = E820_RAM; - } - /* Increase region to size */ - e820[entry].size = guest_memory->ram_regions[i].start - e820[entry].addr + guest_memory->ram_regions[i].size; - } - /* Create empty region at the end */ - entry++; - assert(entry < E820MAX); - e820[entry].addr = e820[entry - 1].addr + e820[entry - 1].size; - e820[entry].size = 0x100000000ull - e820[entry].addr; - e820[entry].type = E820_RESERVED; - printf("Final e820 map is:\n"); - for (i = 0; i <= entry; i++) { - printf("\t0x%x - 0x%x type %d\n", (unsigned int)e820[i].addr, (unsigned int)(e820[i].addr + e820[i].size), - e820[i].type); - assert(e820[i].addr < e820[i].addr + e820[i].size); - } - return entry + 1; -} - -static int make_guest_boot_info(vmm_t *vmm) -{ - /* TODO: Bootinfo struct needs to be allocated in location accessable by real mode? */ - uintptr_t addr = guest_ram_allocate(&vmm->guest_mem, sizeof(struct boot_params)); - if (addr == 0) { - ZF_LOGE("Failed to allocate %zu bytes for guest boot info struct", sizeof(struct boot_params)); - return -1; - } - printf("Guest boot info allocated at %p. Populating...\n", (void *)addr); - vmm->guest_image.boot_info = addr; - - /* Map in BIOS boot info structure. */ - struct boot_params boot_info; - memset(&boot_info, 0, sizeof(struct boot_params)); - - /* Initialise basic bootinfo structure. Src: Linux kernel Documentation/x86/boot.txt */ - boot_info.hdr.header = 0x53726448; /* Magic number 'HdrS' */ - boot_info.hdr.boot_flag = 0xAA55; /* Magic number for Linux. */ - boot_info.hdr.type_of_loader = 0xFF; /* Undefined loeader type. */ - boot_info.hdr.code32_start = vmm->guest_image.load_paddr; - boot_info.hdr.kernel_alignment = vmm->guest_image.alignment; - boot_info.hdr.relocatable_kernel = true; - - /* Set up screen information. */ - /* Tell Guest OS about VESA mode. */ - make_guest_screen_info(vmm, &boot_info.screen_info); - - /* Create e820 memory map */ - boot_info.e820_entries = make_guest_e820_map(boot_info.e820_map, &vmm->guest_mem); - - /* Pass in the command line string. */ - boot_info.hdr.cmd_line_ptr = vmm->guest_image.cmd_line; - boot_info.hdr.cmdline_size = vmm->guest_image.cmd_line_len; - - /* These are not needed to be precise, because Linux uses these values - * only to raise an error when the decompression code cannot find good - * space. ref: GRUB2 source code loader/i386/linux.c */ - boot_info.alt_mem_k = 0;//((32 * 0x100000) >> 10); - - /* Pass in initramfs. */ - if (vmm->guest_image.boot_module_paddr) { - boot_info.hdr.ramdisk_image = (uint32_t) vmm->guest_image.boot_module_paddr; - boot_info.hdr.ramdisk_size = vmm->guest_image.boot_module_size; - boot_info.hdr.root_dev = 0x0100; - boot_info.hdr.version = 0x0204; /* Report version 2.04 in order to report ramdisk_image. */ - } else { - boot_info.hdr.version = 0x0202; - } - return vmm_guest_vspace_touch(&vmm->guest_mem.vspace, addr, sizeof(boot_info), guest_elf_write_address, &boot_info); -} - -/* Init the guest page directory, cmd line args and boot info structures. */ -void vmm_plat_init_guest_boot_structure(vmm_t *vmm, const char *cmdline) -{ - int UNUSED err; - - err = make_guest_page_dir(vmm); - assert(!err); - - err = make_guest_cmd_line(vmm, cmdline); - assert(!err); - - err = make_guest_boot_info(vmm); - assert(!err); - - err = make_guest_acpi_tables(vmm); - assert(!err); -} - -void vmm_init_guest_thread_state(vmm_vcpu_t *vcpu) -{ - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EAX, 0); - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EBX, 0); - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_ECX, 0); - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EDX, 0); - - /* Entry point. */ - printf("Initializing guest to start running at 0x%x\n", (unsigned int)vcpu->vmm->guest_image.entry); - vmm_guest_state_set_eip(&vcpu->guest_state, vcpu->vmm->guest_image.entry); - /* The boot_param structure. */ - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_ESI, vcpu->vmm->guest_image.boot_info); - - /* Set the initial CR state */ - vcpu->guest_state.virt.cr.cr0_mask = VMM_VMCS_CR0_MASK; - vcpu->guest_state.virt.cr.cr0_shadow = 0; - vcpu->guest_state.virt.cr.cr0_host_bits = VMM_VMCS_CR0_VALUE; - - vcpu->guest_state.virt.cr.cr4_mask = VMM_VMCS_CR4_MASK; - vcpu->guest_state.virt.cr.cr4_shadow = 0; - vcpu->guest_state.virt.cr.cr4_host_bits = VMM_VMCS_CR4_VALUE; - - /* Set the initial CR states */ - vmm_guest_state_set_cr0(&vcpu->guest_state, vcpu->guest_state.virt.cr.cr0_host_bits); - vmm_guest_state_set_cr3(&vcpu->guest_state, vcpu->vmm->guest_image.pd); - vmm_guest_state_set_cr4(&vcpu->guest_state, vcpu->guest_state.virt.cr.cr4_host_bits); - - /* Init guest OS vcpu state. */ - vmm_vmcs_init_guest(vcpu); -} - -/* TODO: Refactor and stop rewriting fucking elf loading code */ -static int vmm_load_guest_segment(vmm_t *vmm, seL4_Word source_offset, - seL4_Word dest_addr, unsigned int segment_size, unsigned int file_size, FILE *file) -{ - - int ret; - unsigned int page_size = vmm->page_size; - assert(file_size <= segment_size); - - /* Allocate a cslot for duplicating frame caps */ - cspacepath_t dup_slot; - ret = vka_cspace_alloc_path(&vmm->vka, &dup_slot); - if (ret) { - ZF_LOGE("Failed to allocate slot"); - return ret; - } - - size_t current = 0; - size_t remain = file_size; - while (current < segment_size) { - /* Retrieve the mapping */ - seL4_CPtr cap; - cap = vspace_get_cap(&vmm->guest_mem.vspace, (void *)dest_addr); - if (!cap) { - ZF_LOGE("Failed to find frame cap while loading elf segment at %p", (void *)dest_addr); - return -1; - } - cspacepath_t cap_path; - vka_cspace_make_path(&vmm->vka, cap, &cap_path); - - /* Copy cap and map into our vspace */ - vka_cnode_copy(&dup_slot, &cap_path, seL4_AllRights); - void *map_vaddr = vspace_map_pages(&vmm->host_vspace, &dup_slot.capPtr, NULL, seL4_AllRights, 1, page_size, 1); - if (!map_vaddr) { - ZF_LOGE("Failed to map page into host vspace"); - return -1; - } - - /* Copy the contents of page from ELF into the mapped frame. */ - size_t offset = dest_addr & ((BIT(page_size)) - 1); - - void *copy_vaddr = map_vaddr + offset; - size_t copy_len = (BIT(page_size)) - offset; - - if (remain > 0) { - if (copy_len > remain) { - /* Don't copy past end of data. */ - copy_len = remain; - } - - DPRINTF(5, "load page src %zu dest %p remain %zu offset %zu copy vaddr %p " - "copy len %zu\n", source_offset, (void *)dest_addr, remain, offset, copy_vaddr, copy_len); - - fseek(file, source_offset, SEEK_SET); - size_t result = fread(copy_vaddr, copy_len, 1, file); - ZF_LOGF_IF(result != 1, "Read failed unexpectedly"); - source_offset += copy_len; - remain -= copy_len; - } else { - memset(copy_vaddr, 0, copy_len); - } - - dest_addr += copy_len; - - current += copy_len; - - /* Unamp the page and delete the temporary cap */ - vspace_unmap_pages(&vmm->host_vspace, map_vaddr, 1, page_size, NULL); - vka_cnode_delete(&dup_slot); - } - - return 0; -} - -/* Load the actual ELF file contents into pre-allocated frames. - Used for both host and guest threads. - - @param resource the thread structure for resource - @param elf_name the name of elf file - -*/ -/* TODO: refactor yet more elf loading code */ -int vmm_load_guest_elf(vmm_t *vmm, const char *elfname, size_t alignment) -{ - int ret; - char elf_file[256]; - elf_t elf; - - DPRINTF(4, "Loading guest elf %s\n", elfname); - FILE *file = fopen(elfname, "r"); - if (!file) { - ZF_LOGE("Guest elf \"%s\" not found.", elfname); - return -1; - } - - ret = vmm_read_elf_headers(elf_file, vmm, file, sizeof(elf_file), &elf); - if (ret < 0) { - ZF_LOGE("Guest elf \"%s\" invalid.", elfname); - return -1; - } - - unsigned int n_headers = elf_getNumProgramHeaders(&elf); - - /* Find the largest guest ram region and use that for loading */ - uintptr_t load_addr = guest_ram_largest_free_region_start(&vmm->guest_mem); - /* Round up by the alignemnt. We just hope its still in the memory region. - * if it isn't we will just fail when we try and get the frame */ - load_addr = ROUND_UP(load_addr, alignment); - /* Calculate relocation offset. */ - uintptr_t guest_kernel_addr = 0xFFFFFFFF; - uintptr_t guest_kernel_vaddr = 0xFFFFFFFF; - for (int i = 0; i < n_headers; i++) { - if (elf_getProgramHeaderType(&elf, i) != PT_LOAD) { - continue; - } - uint32_t addr = elf_getProgramHeaderPaddr(&elf, i); - if (addr < guest_kernel_addr) { - guest_kernel_addr = addr; - } - uint32_t vaddr = elf_getProgramHeaderVaddr(&elf, i); - if (vaddr < guest_kernel_vaddr) { - guest_kernel_vaddr = vaddr; - } - } - - printf("Guest kernel is compiled to be located at paddr 0x%x vaddr 0x%x\n", - (unsigned int)guest_kernel_addr, (unsigned int)guest_kernel_vaddr); - printf("Guest kernel allocated 1:1 start is at paddr = 0x%x\n", (unsigned int)load_addr); - int guest_relocation_offset = (int)((int64_t)load_addr - (int64_t)guest_kernel_addr); - printf("Therefore relocation offset is %d (%s0x%x)\n", - guest_relocation_offset, - guest_relocation_offset < 0 ? "-" : "", - abs(guest_relocation_offset)); - - for (int i = 0; i < n_headers; i++) { - seL4_Word source_offset, dest_addr; - unsigned int file_size, segment_size; - - /* Skip unloadable program headers. */ - if (elf_getProgramHeaderType(&elf, i) != PT_LOAD) { - continue; - } - - /* Fetch information about this segment. */ - source_offset = elf_getProgramHeaderOffset(&elf, i); - file_size = elf_getProgramHeaderFileSize(&elf, i); - segment_size = elf_getProgramHeaderMemorySize(&elf, i); - - dest_addr = elf_getProgramHeaderPaddr(&elf, i); - dest_addr += guest_relocation_offset; - - if (!segment_size) { - /* Zero sized segment, ignore. */ - continue; - } - - /* Load this ELf segment. */ - ret = vmm_load_guest_segment(vmm, source_offset, dest_addr, segment_size, file_size, file); - if (ret) { - return ret; - } - - /* Record it as allocated */ - guest_ram_mark_allocated(&vmm->guest_mem, dest_addr, segment_size); - } - - /* Record the entry point. */ - vmm->guest_image.entry = elf_getEntryPoint(&elf); - vmm->guest_image.entry += guest_relocation_offset; - - /* Remember where we started loading the kernel to fix up relocations in future */ - vmm->guest_image.load_paddr = load_addr; - vmm->guest_image.link_paddr = guest_kernel_addr; - vmm->guest_image.link_vaddr = guest_kernel_vaddr; - vmm->guest_image.relocation_offset = guest_relocation_offset; - vmm->guest_image.alignment = alignment; - - printf("Guest memory layout after loading elf\n"); - print_guest_ram_regions(&vmm->guest_mem); - - fclose(file); - - return 0; -}
diff --git a/libsel4vmm/src/platform/elf_helper.c b/libsel4vmm/src/platform/elf_helper.c deleted file mode 100644 index 7a227c3..0000000 --- a/libsel4vmm/src/platform/elf_helper.c +++ /dev/null
@@ -1,31 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include <elf/elf.h> -#include "vmm/platform/elf_helper.h" - -/* - Reads the elf header and elf program headers from a file - when given a sufficiently large memory buffer -*/ -int vmm_read_elf_headers(void *buf, vmm_t *vmm, FILE *file, size_t buf_size, elf_t *elf) { - size_t result; - if(buf_size < sizeof(Elf32_Ehdr)) - return -1; - - fseek(file, 0, SEEK_SET); - result = fread(buf, buf_size, 1, file); - if(result != 1) - return -1; - - return elf_newFile_maybe_unsafe(buf, buf_size, true, false, elf); -}
diff --git a/libsel4vmm/src/platform/guest_memory.c b/libsel4vmm/src/platform/guest_memory.c deleted file mode 100644 index 418fcc1..0000000 --- a/libsel4vmm/src/platform/guest_memory.c +++ /dev/null
@@ -1,419 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <sel4/sel4.h> -#include <utils/util.h> -#include <vka/capops.h> - -#include "vmm/vmm.h" -#include "vmm/debug.h" -#include "vmm/platform/guest_memory.h" - -static void push_guest_ram_region(guest_memory_t *guest_memory, uintptr_t start, size_t size, int allocated) -{ - int last_region = guest_memory->num_ram_regions; - if (size == 0) { - return; - } - guest_memory->ram_regions = realloc(guest_memory->ram_regions, sizeof(guest_ram_region_t) * (last_region + 1)); - assert(guest_memory->ram_regions); - - guest_memory->ram_regions[last_region].start = start; - guest_memory->ram_regions[last_region].size = size; - guest_memory->ram_regions[last_region].allocated = allocated; - guest_memory->num_ram_regions++; -} - -static int ram_region_cmp(const void *a, const void *b) -{ - const guest_ram_region_t *aa = a; - const guest_ram_region_t *bb = b; - return aa->start - bb->start; -} - -static void sort_guest_ram_regions(guest_memory_t *guest_memory) -{ - qsort(guest_memory->ram_regions, guest_memory->num_ram_regions, sizeof(guest_ram_region_t), ram_region_cmp); -} - -static void guest_ram_remove_region(guest_memory_t *guest_memory, int region) -{ - assert(region < guest_memory->num_ram_regions); - guest_memory->num_ram_regions--; - memcpy(&guest_memory->ram_regions[region], &guest_memory->ram_regions[region + 1], - sizeof(guest_ram_region_t) * (guest_memory->num_ram_regions - region)); - /* realloc it smaller */ - guest_memory->ram_regions = realloc(guest_memory->ram_regions, - sizeof(guest_ram_region_t) * guest_memory->num_ram_regions); - assert(guest_memory->ram_regions); -} - -static void collapse_guest_ram_regions(guest_memory_t *guest_memory) -{ - int i; - for (i = 1; i < guest_memory->num_ram_regions;) { - /* Only collapse regions with the same allocation flag that are contiguous */ - if (guest_memory->ram_regions[i - 1].allocated == guest_memory->ram_regions[i]. allocated && - guest_memory->ram_regions[i - 1].start + guest_memory->ram_regions[i - 1].size == guest_memory->ram_regions[i].start) { - - guest_memory->ram_regions[i - 1].size += guest_memory->ram_regions[i].size; - guest_ram_remove_region(guest_memory, i); - } else { - /* We are satisified that this entry cannot be merged. So now we - * move onto the next one */ - i++; - } - } -} - -static int expand_guest_ram_region(guest_memory_t *guest_memory, uintptr_t start, size_t bytes) -{ - /* blindly put a new region at the end */ - push_guest_ram_region(guest_memory, start, bytes, 0); - /* sort the region we just added */ - sort_guest_ram_regions(guest_memory); - /* collapse any contiguous regions */ - collapse_guest_ram_regions(guest_memory); - return 0; -} - -uintptr_t guest_ram_largest_free_region_start(guest_memory_t *guest_memory) -{ - int largest = -1; - int i; - /* find a first region */ - for (i = 0; i < guest_memory->num_ram_regions && largest == -1; i++) { - if (!guest_memory->ram_regions[i].allocated) { - largest = i; - } - } - assert(largest != -1); - for (i++; i < guest_memory->num_ram_regions; i++) { - if (!guest_memory->ram_regions[i].allocated && - guest_memory->ram_regions[i].size > guest_memory->ram_regions[largest].size) { - largest = i; - } - } - return guest_memory->ram_regions[largest].start; -} - -void print_guest_ram_regions(guest_memory_t *guest_memory) -{ - int i; - for (i = 0; i < guest_memory->num_ram_regions; i++) { - char size_char = 'B'; - size_t size = guest_memory->ram_regions[i].size; - if (size >= 1024) { - size >>= 10; - size_char = 'K'; - } - if (size >= 1024) { - size >>= 10; - size_char = 'M'; - } - printf("\t0x%x-0x%x (%zu%c) %s\n", - (unsigned int)guest_memory->ram_regions[i].start, - (unsigned int)(guest_memory->ram_regions[i].start + guest_memory->ram_regions[i].size), - size, size_char, - guest_memory->ram_regions[i].allocated ? "allocated" : "free"); - } -} - -void guest_ram_mark_allocated(guest_memory_t *guest_memory, uintptr_t start, size_t bytes) -{ - /* Find the region */ - int i; - int region = -1; - for (i = 0; i < guest_memory->num_ram_regions; i++) { - if (guest_memory->ram_regions[i].start <= start && - guest_memory->ram_regions[i].start + guest_memory->ram_regions[i].size >= start + bytes) { - region = i; - break; - } - } - assert(region != -1); - assert(!guest_memory->ram_regions[region].allocated); - /* Remove the region */ - guest_ram_region_t r = guest_memory->ram_regions[region]; - guest_ram_remove_region(guest_memory, region); - /* Split the region into three pieces and add them */ - push_guest_ram_region(guest_memory, r.start, start - r.start, 0); - push_guest_ram_region(guest_memory, start, bytes, 1); - push_guest_ram_region(guest_memory, start + bytes, r.size - bytes - (start - r.start), 0); - /* sort and collapse */ - sort_guest_ram_regions(guest_memory); - collapse_guest_ram_regions(guest_memory); -} - -uintptr_t guest_ram_allocate(guest_memory_t *guest_memory, size_t bytes) -{ - /* Do the obvious dumb search through the regions */ - for (int i = 0; i < guest_memory->num_ram_regions; i++) { - if (!guest_memory->ram_regions[i].allocated && guest_memory->ram_regions[i].size >= bytes) { - uintptr_t addr = guest_memory->ram_regions[i].start; - guest_ram_mark_allocated(guest_memory, addr, bytes); - return addr; - } - } - ZF_LOGE("Failed to allocate %zu bytes of guest RAM", bytes); - return 0; -} - -static int vmm_alloc_guest_ram_one_to_one(vmm_t *vmm, size_t bytes) -{ - int ret; - int i; - int page_size = vmm->page_size; - int num_pages = ROUND_UP(bytes, BIT(page_size)) >> page_size; - guest_memory_t *guest_memory = &vmm->guest_mem; - - DPRINTF(0, "Allocating %d frames of size %d for guest RAM\n", num_pages, page_size); - /* Allocate all the frames first */ - vka_object_t *objects = malloc(sizeof(vka_object_t) * num_pages); - assert(objects); - for (i = 0; i < num_pages; i++) { - ret = vka_alloc_frame(&vmm->vka, page_size, &objects[i]); - if (ret) { - ZF_LOGE("Failed to allocate frame %d/%d", i, num_pages); - return -1; - } - } - - for (i = 0; i < num_pages; i++) { - /* Get its physical address */ - uintptr_t paddr = vka_object_paddr(&vmm->vka, &objects[i]); - if (paddr == VKA_NO_PADDR) { - ZF_LOGE("Allocated frame has no physical address"); - return -1; - } - reservation_t reservation = vspace_reserve_range_at(&guest_memory->vspace, (void *)paddr, BIT(page_size), - seL4_AllRights, 1); - if (!reservation.res) { - ZF_LOGI("Failed to reserve address 0x%x in guest vspace. Skipping frame and leaking memory!", (unsigned int)paddr); - continue; - } - /* Map in */ - ret = vspace_map_pages_at_vaddr(&guest_memory->vspace, &objects[i].cptr, NULL, (void *)paddr, 1, page_size, - reservation); - if (ret) { - ZF_LOGE("Failed to map page %d/%d into guest vspace at 0x%x\n", i, num_pages, (unsigned int)paddr); - return -1; - } - /* Free the reservation */ - vspace_free_reservation(&guest_memory->vspace, reservation); - - /* Add the frame to our list */ - ret = expand_guest_ram_region(guest_memory, paddr, BIT(page_size)); - if (ret) { - return ret; - } - } - printf("Guest RAM regions after allocation:\n"); - print_guest_ram_regions(guest_memory); - /* free the objects */ - ZF_LOGI("sys_munmap not currently implemented. Leaking memory!"); - //free(objects); - return 0; -} - -int vmm_alloc_guest_device_at(vmm_t *vmm, uintptr_t start, size_t bytes) -{ - int page_size = vmm->page_size; - int num_pages = ROUND_UP(bytes, BIT(page_size)) >> page_size; - int ret; - int i; - guest_memory_t *guest_memory = &vmm->guest_mem; - uintptr_t page_start = ROUND_DOWN(start, BIT(page_size)); - printf("Add guest memory region 0x%x-0x%x\n", (unsigned int)start, (unsigned int)(start + bytes)); - printf("Will be allocating region 0x%x-0x%x after page alignment\n", (unsigned int)page_start, - (unsigned int)(page_start + num_pages * BIT(page_size))); - for (i = 0; i < num_pages; i++) { - reservation_t reservation = vspace_reserve_range_at(&guest_memory->vspace, (void *)(page_start + i * BIT(page_size)), 1, - seL4_AllRights, 1); - if (!reservation.res) { - ZF_LOGI("Failed to create reservation for guest memory page 0x%x size %d, assuming already allocated", - (unsigned int)(page_start + i * BIT(page_size)), page_size); - continue; - } - ret = vspace_new_pages_at_vaddr(&guest_memory->vspace, (void *)(page_start + i * BIT(page_size)), 1, page_size, - reservation); - if (ret) { - ZF_LOGE("Failed to create page 0x%x size %d in guest memory region", (unsigned int)(page_start + i * BIT(page_size)), - page_size); - return -1; - } - vspace_free_reservation(&guest_memory->vspace, reservation); - } - return 0; -} - -static int vmm_map_guest_device_reservation(vmm_t *vmm, uintptr_t paddr, size_t bytes, reservation_t reservation, - uintptr_t map_base) -{ - int page_size = vmm->page_size; - int error; - guest_memory_t *guest_memory = &vmm->guest_mem; - ZF_LOGI("Mapping passthrough device region 0x%x-0x%x to 0x%x", (unsigned int)paddr, (unsigned int)(paddr + bytes), - (unsigned int)map_base); - /* Go through and try and map all the frames */ - uintptr_t current_paddr; - uintptr_t current_map; - for (current_paddr = paddr, current_map = map_base; current_paddr < paddr + bytes; - current_paddr += BIT(page_size), current_map += BIT(page_size)) { - cspacepath_t path; - error = vka_cspace_alloc_path(&vmm->vka, &path); - if (error) { - ZF_LOGE("Failed to allocate cslot"); - return error; - } - error = simple_get_frame_cap(&vmm->host_simple, (void *)current_paddr, page_size, &path); - uintptr_t cookie; - bool allocated = false; - if (error) { - /* attempt to allocate */ - allocated = true; - error = vka_utspace_alloc_at(&vmm->vka, &path, kobject_get_type(KOBJECT_FRAME, page_size), page_size, current_paddr, - &cookie); - } - if (error) { - ZF_LOGE("Failed to find device frame 0x%x size 0x%x for region 0x%x 0x%x", (unsigned int)current_paddr, - (unsigned int)BIT(page_size), (unsigned int)paddr, (unsigned int)bytes); - vka_cnode_delete(&path); - vka_cspace_free(&vmm->vka, path.capPtr); - return error; - } - error = vspace_map_pages_at_vaddr(&guest_memory->vspace, &path.capPtr, NULL, (void *)current_map, 1, page_size, - reservation); - if (error) { - ZF_LOGE("Failed to map device page 0x%x at 0x%x from region 0x%x 0x%x\n", (unsigned int)current_paddr, - (unsigned int)current_map, (unsigned int)paddr, (unsigned int)bytes); - if (allocated) { - vka_utspace_free(&vmm->vka, kobject_get_type(KOBJECT_FRAME, page_size), page_size, cookie); - } - vka_cnode_delete(&path); - vka_cspace_free(&vmm->vka, path.capPtr); - return error; - } - } - return 0; -} - -uintptr_t vmm_map_guest_device(vmm_t *vmm, uintptr_t paddr, size_t bytes, size_t align) -{ - int error; - /* Reserve a region that is guaranteed to have an aligned region in it */ - guest_memory_t *guest_memory = &vmm->guest_mem; - uintptr_t reservation_base; - reservation_t reservation = vspace_reserve_range(&guest_memory->vspace, bytes + align, seL4_AllRights, 1, - (void **)&reservation_base); - if (!reservation.res) { - ZF_LOGE("Failed to allocate reservation of size %zu when mapping memory from %p", bytes + align, (void *)paddr); - return 0; - } - /* Round up reservation so it is aligned. Hopefully it also ends up page aligned with the - * sun moon and stars and we can actually find a frame cap and map it */ - uintptr_t map_base = ROUND_UP(reservation_base, align); - error = vmm_map_guest_device_reservation(vmm, paddr, bytes, reservation, map_base); - vspace_free_reservation(&guest_memory->vspace, reservation); - if (error) { - return 0; - } - return map_base; -} - -int vmm_map_guest_device_at(vmm_t *vmm, uintptr_t vaddr, uintptr_t paddr, size_t bytes) -{ - int error; - /* Reserve a region that is guaranteed to have an aligned region in it */ - guest_memory_t *guest_memory = &vmm->guest_mem; - reservation_t reservation = vspace_reserve_range_at(&guest_memory->vspace, (void *)vaddr, bytes, seL4_AllRights, 1); - if (!reservation.res) { - ZF_LOGE("Failed to allocate reservation of size %zu when mapping device from %p at %p", bytes, (void *)paddr, - (void *)vaddr); - return -1; - } - error = vmm_map_guest_device_reservation(vmm, paddr, bytes, reservation, vaddr); - vspace_free_reservation(&guest_memory->vspace, reservation); - return error; -} - -int vmm_alloc_guest_ram_at(vmm_t *vmm, uintptr_t start, size_t bytes) -{ - int ret; - ret = vmm_alloc_guest_device_at(vmm, start, bytes); - if (ret) { - return ret; - } - ret = expand_guest_ram_region(&vmm->guest_mem, start, bytes); - if (ret) { - return ret; - } - printf("Guest RAM regions after allocating range 0x%x-0x%x:\n", (unsigned int)start, (unsigned int)(start + bytes)); - print_guest_ram_regions(&vmm->guest_mem); - return 0; -} - -int vmm_alloc_guest_ram(vmm_t *vmm, size_t bytes, int onetoone) -{ - if (onetoone) { - return vmm_alloc_guest_ram_one_to_one(vmm, bytes); - } - /* Allocate ram anywhere */ - guest_memory_t *guest_memory = &vmm->guest_mem; - int page_size = vmm->page_size; - uintptr_t base; - int error; - int num_pages = ROUND_UP(bytes, BIT(page_size)) >> page_size; - reservation_t reservation = vspace_reserve_range(&guest_memory->vspace, num_pages * BIT(page_size), seL4_AllRights, 1, - (void **)&base); - if (!reservation.res) { - ZF_LOGE("Failed to create reservation for %zu guest ram bytes", bytes); - return -1; - } - /* Create pages */ - for (int i = 0 ; i < num_pages; i++) { - seL4_Word cookie; - cspacepath_t path; - error = vka_cspace_alloc_path(&vmm->vka, &path); - if (error) { - ZF_LOGE("Failed to allocate path"); - return -1; - } - cookie = allocman_utspace_alloc(vmm->allocman, page_size, kobject_get_type(KOBJECT_FRAME, page_size), &path, true, - &error); - if (error) { - ZF_LOGE("Failed to allocate page"); - return -1; - } - error = vspace_map_pages_at_vaddr(&guest_memory->vspace, &path.capPtr, &cookie, (void *)(base + i * BIT(page_size)), 1, - page_size, reservation); - if (error) { - ZF_LOGE("Failed to map page"); - return -1; - } - } - error = expand_guest_ram_region(&vmm->guest_mem, base, bytes); - if (error) { - return error; - } - vspace_free_reservation(&guest_memory->vspace, reservation); - printf("Guest RAM regions after allocating range 0x%x-0x%x:\n", (unsigned int)base, (unsigned int)(base + bytes)); - print_guest_ram_regions(&vmm->guest_mem); - return 0; -}
diff --git a/libsel4vmm/src/platform/guest_vspace.c b/libsel4vmm/src/platform/guest_vspace.c deleted file mode 100644 index 5d1d96f..0000000 --- a/libsel4vmm/src/platform/guest_vspace.c +++ /dev/null
@@ -1,295 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> - -#include <stdlib.h> -#include <string.h> - -#include <vspace/vspace.h> -#include <sel4utils/vspace.h> -#include <sel4utils/vspace_internal.h> -#include <vka/capops.h> - -#include "vmm/platform/guest_vspace.h" - -#ifdef CONFIG_IOMMU -typedef struct guest_iospace { - seL4_CPtr iospace; - struct sel4utils_alloc_data iospace_vspace_data; - vspace_t iospace_vspace; -} guest_iospace_t; -#endif - -typedef struct guest_vspace { - /* We abuse struct ordering and this member MUST be the first - * thing in the struct */ - struct sel4utils_alloc_data vspace_data; - /* additional vspace to place all mappings into. We will maintain - * a translation between this and the guest */ - vspace_t vmm_vspace; - /* use a vspace implementation as a sparse data structure to track - * the translation from guest to vmm */ - struct sel4utils_alloc_data translation_vspace_data; - vspace_t translation_vspace; -#ifdef CONFIG_IOMMU - /* debug flag for checking if we add io spaces late */ - int done_mapping; - int num_iospaces; - guest_iospace_t *iospaces; -#endif -} guest_vspace_t; - -static int guest_vspace_map(vspace_t *vspace, seL4_CPtr cap, void *vaddr, seL4_CapRights_t rights, - int cacheable, size_t size_bits) -{ - struct sel4utils_alloc_data *data = get_alloc_data(vspace); - int error; - /* this type cast works because the alloc data was at the start of the struct - * so it has the same address. - * This conversion is guaranteed to work by the C standard */ - guest_vspace_t *guest_vspace = (guest_vspace_t *) data; - /* perfrom the ept mapping */ - error = sel4utils_map_page_ept(vspace, cap, vaddr, rights, cacheable, size_bits); - if (error) { - return error; - } - /* duplicate the cap so we can do a mapping */ - cspacepath_t orig_path; - vka_cspace_make_path(guest_vspace->vspace_data.vka, cap, &orig_path); - cspacepath_t new_path; - error = vka_cspace_alloc_path(guest_vspace->vspace_data.vka, &new_path); - if (error) { - ZF_LOGE("Failed to allocate cslot to duplicate frame cap"); - return error; - } - error = vka_cnode_copy(&new_path, &orig_path, seL4_AllRights); - assert(error == seL4_NoError); - /* perform the regular mapping */ - void *vmm_vaddr = vspace_map_pages(&guest_vspace->vmm_vspace, &new_path.capPtr, NULL, seL4_AllRights, 1, size_bits, - cacheable); - if (!vmm_vaddr) { - ZF_LOGE("Failed to map into VMM vspace"); - return -1; - } - /* add translation information. give dummy cap value of 42 as it cannot be zero - * but we really just want to store information in the cookie */ - error = update_entries(&guest_vspace->translation_vspace, (uintptr_t)vaddr, 42, size_bits, (uintptr_t)vmm_vaddr); - if (error) { - ZF_LOGE("Failed to add translation information"); - return error; - } -#ifdef CONFIG_IOMMU - /* set the mapping bit */ - guest_vspace->done_mapping = 1; - /* map into all the io spaces */ - for (int i = 0; i < guest_vspace->num_iospaces; i++) { - error = vka_cspace_alloc_path(guest_vspace->vspace_data.vka, &new_path); - if (error) { - ZF_LOGE("Failed to allocate cslot to duplicate frame cap"); - return error; - } - error = vka_cnode_copy(&new_path, &orig_path, seL4_AllRights); - - guest_iospace_t *guest_iospace = &guest_vspace->iospaces[i]; - - assert(error == seL4_NoError); - error = sel4utils_map_iospace_page(guest_vspace->vspace_data.vka, guest_iospace->iospace, - new_path.capPtr, (uintptr_t)vaddr, rights, cacheable, - size_bits, NULL, NULL); - if (error) { - ZF_LOGE("Failed to map page into iospace"); - return error; - } - - /* Store the slot of the frame cap copy in a vspace so they can be looked up and - * freed when this address gets unmapped. */ - error = update_entries(&guest_iospace->iospace_vspace, (uintptr_t)vaddr, new_path.capPtr, size_bits, 0 /* cookie */); - if (error) { - ZF_LOGE("Failed to add iospace mapping information"); - return error; - } - } -#else - (void)guest_vspace; -#endif - return 0; -} - -void guest_vspace_unmap(vspace_t *vspace, void *vaddr, size_t num_pages, size_t size_bits, vka_t *vka) -{ - struct sel4utils_alloc_data *data = get_alloc_data(vspace); - guest_vspace_t *guest_vspace = (guest_vspace_t *) data; - - int error; - - // Unmap pages from EPT. - // vaddr is a guest physical address. - // This can be done in a single call as mappings are contiguous in this vspace. - sel4utils_unmap_pages(vspace, vaddr, num_pages, size_bits, vka); - - // Each page must be unmapped individually from the vmm vspace, as mappings are not - // necessarily host-virtually contiguous. - size_t page_size = BIT(size_bits); - - for (int i = 0; i < num_pages; i++) { - - void *page_vaddr = (void *)(vaddr + i * page_size); - - // look up vaddr in vmm vspace by consulting entry in translation vspace - void *vmm_vaddr = (void *)vspace_get_cookie(&guest_vspace->translation_vspace, page_vaddr); - - // remove mapping from vmm vspace - vspace_unmap_pages(&guest_vspace->vmm_vspace, vmm_vaddr, 1 /* num pages */, size_bits, vka); - - // remove mapping from translation vspace - error = clear_entries(&guest_vspace->translation_vspace, (uintptr_t)page_vaddr, size_bits); - - if (error) { - ZF_LOGE("Failed to clear translation information"); - return; - } - -#ifdef CONFIG_IOMMU - /* Unmap the vaddr from each iospace, freeing the cslots used to store the - * copy of the frame cap. */ - for (int i = 0; i < guest_vspace->num_iospaces; i++) { - guest_iospace_t *guest_iospace = &guest_vspace->iospaces[i]; - seL4_CPtr iospace_frame_cap_copy = vspace_get_cap(&guest_iospace->iospace_vspace, page_vaddr); - - error = seL4_ARCH_Page_Unmap(iospace_frame_cap_copy); - if (error) { - ZF_LOGE("Failed to unmap page from iospace"); - return; - } - - cspacepath_t path; - vka_cspace_make_path(guest_vspace->vspace_data.vka, iospace_frame_cap_copy, &path); - error = vka_cnode_delete(&path); - if (error) { - ZF_LOGE("Failed to delete frame cap copy"); - return; - } - - vka_cspace_free(guest_vspace->vspace_data.vka, iospace_frame_cap_copy); - - error = clear_entries(&guest_iospace->iospace_vspace, (uintptr_t)page_vaddr, size_bits); - if (error) { - ZF_LOGE("Failed to clear iospace mapping information"); - return; - } - } -#endif - } -} - -#ifdef CONFIG_IOMMU -int vmm_guest_vspace_add_iospace(vspace_t *loader, vspace_t *vspace, seL4_CPtr iospace) -{ - struct sel4utils_alloc_data *data = get_alloc_data(vspace); - guest_vspace_t *guest_vspace = (guest_vspace_t *) data; - - assert(!guest_vspace->done_mapping); - - guest_vspace->iospaces = realloc(guest_vspace->iospaces, sizeof(guest_iospace_t) * (guest_vspace->num_iospaces + 1)); - assert(guest_vspace->iospaces); - - guest_iospace_t *guest_iospace = &guest_vspace->iospaces[guest_vspace->num_iospaces]; - guest_iospace->iospace = iospace; - int error = sel4utils_get_vspace(loader, &guest_iospace->iospace_vspace, &guest_iospace->iospace_vspace_data, - guest_vspace->vspace_data.vka, seL4_CapNull, NULL, NULL); - if (error) { - ZF_LOGE("Failed to allocate vspace for new iospace"); - return error; - } - - guest_vspace->num_iospaces++; - return 0; -} -#endif - -int vmm_get_guest_vspace(vspace_t *loader, vspace_t *vmm, vspace_t *new_vspace, vka_t *vka, seL4_CPtr page_directory) -{ - int error; - guest_vspace_t *vspace = malloc(sizeof(*vspace)); - if (!vspace) { - ZF_LOGE("Malloc failed"); - return -1; - } -#ifdef CONFIG_IOMMU - vspace->done_mapping = 0; - vspace->num_iospaces = 0; - vspace->iospaces = malloc(0); - assert(vspace->iospaces); -#endif - vspace->vmm_vspace = *vmm; - error = sel4utils_get_vspace(loader, &vspace->translation_vspace, &vspace->translation_vspace_data, vka, page_directory, - NULL, NULL); - if (error) { - ZF_LOGE("Failed to create translation vspace"); - return error; - } - error = sel4utils_get_vspace_with_map(loader, new_vspace, &vspace->vspace_data, vka, page_directory, NULL, NULL, - guest_vspace_map); - if (error) { - ZF_LOGE("Failed to create guest vspace"); - return error; - } - - new_vspace->unmap_pages = guest_vspace_unmap; - - return 0; -} - -/* Helpers for use with touch below */ -int vmm_guest_get_phys_data_help(uintptr_t addr, void *vaddr, size_t size, - size_t offset, void *cookie) -{ - memcpy(cookie, vaddr, size); - - return 0; -} - -int vmm_guest_set_phys_data_help(uintptr_t addr, void *vaddr, size_t size, - size_t offset, void *cookie) -{ - memcpy(vaddr, cookie, size); - - return 0; -} - -int vmm_guest_vspace_touch(vspace_t *vspace, uintptr_t addr, size_t size, vmm_guest_vspace_touch_callback callback, - void *cookie) -{ - struct sel4utils_alloc_data *data = get_alloc_data(vspace); - guest_vspace_t *guest_vspace = (guest_vspace_t *) data; - uintptr_t current_addr; - uintptr_t next_addr; - uintptr_t end_addr = (uintptr_t)(addr + size); - for (current_addr = (uintptr_t)addr; current_addr < end_addr; current_addr = next_addr) { - uintptr_t current_aligned = PAGE_ALIGN_4K(current_addr); - uintptr_t next_page_start = current_aligned + PAGE_SIZE_4K; - next_addr = MIN(end_addr, next_page_start); - void *vaddr = (void *)sel4utils_get_cookie(&guest_vspace->translation_vspace, (void *)current_aligned); - if (!vaddr) { - ZF_LOGE("Failed to get cookie at %p", (void *)current_aligned); - return -1; - } - int result = callback(current_addr, (void *)(vaddr + (current_addr - current_aligned)), next_addr - current_addr, - current_addr - addr, cookie); - if (result) { - return result; - } - } - return 0; -}
diff --git a/libsel4vmm/src/processor/cpuid.c b/libsel4vmm/src/processor/cpuid.c deleted file mode 100644 index b401bc5..0000000 --- a/libsel4vmm/src/processor/cpuid.c +++ /dev/null
@@ -1,383 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* This file contains macros for CPUID emulation in x86. - * Most of the code in this file is from arch/x86/kvm/cpuid.h Linux 3.8.8 - - * Authors: - * Qian Ge - */ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/debug.h" - -#include "vmm/vmm.h" - -#include "vmm/processor/cpuid.h" -#include "vmm/processor/cpufeature.h" - -static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx) { - /* ecx is often an input as well as an output. */ - asm volatile("cpuid" - : "=a" (*eax), - "=b" (*ebx), - "=c" (*ecx), - "=d" (*edx) - : "0" (*eax), "2" (*ecx) - : "memory"); -} - -static int vmm_cpuid_virt(unsigned int function, unsigned int index, struct cpuid_val *val, vmm_vcpu_t *vcpu) { - unsigned int eax, ebx, ecx, edx; - - eax = function; - ecx = index; - - native_cpuid(&eax, &ebx, &ecx, &edx); - - /* cpuid 1.edx */ - const unsigned int kvm_supported_word0_x86_features = - F(FPU) | 0 /*F(VME)*/ | 0 /*F(DE)*/ | 0/*F(PSE)*/ | - F(TSC) | 0/*F(MSR)*/ | 0 /*F(PAE)*/ | 0/*F(MCE)*/ | - 0 /*F(CX8)*/ | F(APIC) | 0 /* Reserved */ | F(SEP) | - /*F(MTRR)*/ 0 | F(PGE) | 0/*F(MCA)*/ | F(CMOV) | - 0 /*F(PAT)*/ | 0 /* F(PSE36)*/ | 0 /* PSN */ | 0/*F(CLFLSH)*/ | - 0 /* Reserved, DS, ACPI */ | F(MMX) | - F(FXSR) | F(XMM) | F(XMM2) | 0/*F(SELFSNOOP)*/ | - 0 /* HTT, TM, Reserved, PBE */; - - /* cpuid 1.ecx */ - const unsigned int kvm_supported_word4_x86_features = - F(XMM3) | 0 /*F(PCLMULQDQ)*/ | 0 /* DTES64, MONITOR */ | - 0 /* DS-CPL, VMX, SMX, EST */ | - 0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ | - 0 /*F(FMA)*/ | 0 /*F(CX16)*/ | 0 /* xTPR Update, PDCM */ | - 0 /*F(PCID)*/ | 0 /* Reserved, DCA */ | F(XMM4_1) | - F(XMM4_2) | 0 /*F(X2APIC)*/ | 0 /*F(MOVBE)*/ | 0 /*F(POPCNT)*/ | - 0 /* Reserved*/ | 0 /*F(AES)*/ | 0/*F(XSAVE)*/ | 0/*F(OSXSAVE)*/ | 0 /*F(AVX)*/ | - 0 /*F(F16C)*/ | 0 /*F(RDRAND)*/; - - /* cpuid 0x80000001.edx */ - const unsigned int kvm_supported_word1_x86_features = - 0 /*F(NX)*/ | 0/*F(RDTSCP)*/; /*not support x86 64*/ - - /* cpuid 0x80000001.ecx */ - const unsigned int kvm_supported_word6_x86_features = 0; - -#if 0 - /* cpuid 0xC0000001.edx */ - const unsigned int kvm_supported_word5_x86_features = - F(XSTORE) | F(XSTORE_EN) | F(XCRYPT) | F(XCRYPT_EN) | - F(ACE2) | F(ACE2_EN) | F(PHE) | F(PHE_EN) | - F(PMM) | F(PMM_EN); -#endif - - /* cpuid 7.0.ebx */ - const unsigned int kvm_supported_word9_x86_features = - F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | - F(BMI2) | F(ERMS) | 0 /*F(INVPCID)*/| F(RTM); - - /* Virtualize the return value according to the function. */ - - DPRINTF(4, "cpuid function 0x%x index 0x%x eax 0x%x ebx 0%x ecx 0x%x edx 0x%x\n", function, index, eax, ebx, ecx, edx); - - /* ref: http://www.sandpile.org/x86/cpuid.htm */ - - switch (function) { - case 0: /* Get highest function supported plus vendor ID */ - if (eax > 0xb) - eax = 0xb; - break; - - case 1: /* Processor, info and feature. family, model, stepping */ - edx &= kvm_supported_word0_x86_features; - ecx &= kvm_supported_word4_x86_features; - break; - - case 2: - case 4: /* Cache and TLB descriptor information */ - /* Simply pass through information from native CPUID. */ - break; - - case 7: /* Extended flags */ - ebx &= kvm_supported_word9_x86_features; - break; - - case 0xa: /* disable performance monitoring */ - eax = ebx = ecx = edx = 0; - break; - - case 0xb: /* Disable topology information */ - eax = ebx = ecx = edx = 0; - break; - - case VMM_CPUID_KVM_SIGNATURE: /* Unsupported KVM features. We are not KVM. */ - case VMM_CPUID_KVM_FEATURES: - eax = ebx = ecx = edx = 0; - break; - - case 0x80000000: /* Get highest extended function supported */ - break; - - case 0x80000001: /* extended processor info and feature bits */ - ecx &= kvm_supported_word6_x86_features; - edx &= kvm_supported_word1_x86_features; - break; - - case 0x80000002: /* Get processor name string. */ - case 0x80000003: - case 0x80000004: - case 0x80000005: - case 0x80000006: /* Cache information. */ - /* Pass through brand name from native CPUID. */ - break; - - case 0x80000008: /* Virtual and Physics address sizes */ - break; - - case 3: /* Processor serial number. */ - break; - case 5: /* MONITOR / MWAIT */ - case 6: /* Thermal management */ - case 0x80000007: /* Advanced power management - unsupported. */ - case 0xC0000002: - case 0xC0000003: - case 0xC0000004: - eax = ebx = ecx = edx = 0; - break; - - default: - /* TODO: Adding more CPUID functions whenever necessary */ - DPRINTF(1, "CPUID unimplemented function 0x%x\n", function); - return -1; - - } - - val->eax = eax; - val->ebx = ebx; - val->ecx = ecx; - val->edx = edx; - - DPRINTF(4, "cpuid virt value eax 0x%x ebx 0x%x ecx 0x%x edx 0x%x\n", eax, ebx, ecx, edx); - - return 0; - -} - -#if 0 - /* function 2 entries are STATEFUL. That is, repeated cpuid commands - * may return different values. This forces us to get_cpu() before - * issuing the first command, and also to emulate this annoying behavior - * in kvm_emulate_cpuid() using KVM_CPUID_FLAG_STATE_READ_NEXT */ - case 2: { - int t, times = entry->eax & 0xff; - - entry->flags |= KVM_CPUID_FLAG_STATEFUL_FUNC; - entry->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; - for (t = 1; t < times; ++t) { - if (*nent >= maxnent) - goto out; - - do_cpuid_1_ent(&entry[t], function, 0); - entry[t].flags |= KVM_CPUID_FLAG_STATEFUL_FUNC; - ++*nent; - } - break; - } - /* function 4 has additional index. */ - case 4: { - int i, cache_type; - - entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; - /* read more entries until cache_type is zero */ - for (i = 1; ; ++i) { - if (*nent >= maxnent) - goto out; - - cache_type = entry[i - 1].eax & 0x1f; - if (!cache_type) - break; - do_cpuid_1_ent(&entry[i], function, i); - entry[i].flags |= - KVM_CPUID_FLAG_SIGNIFCANT_INDEX; - ++*nent; - } - break; - } - case 7: { - entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; - /* Mask ebx against host capability word 9 */ - if (index == 0) { - entry->ebx &= kvm_supported_word9_x86_features; - cpuid_mask(&entry->ebx, 9); - // TSC_ADJUST is emulated - entry->ebx |= F(TSC_ADJUST); - } else - entry->ebx = 0; - entry->eax = 0; - entry->ecx = 0; - entry->edx = 0; - break; - } - case 9: - break; - case 0xa: { /* Architectural Performance Monitoring */ - struct x86_pmu_capability cap; - union cpuid10_eax eax; - union cpuid10_edx edx; - - perf_get_x86_pmu_capability(&cap); - - /* - * Only support guest architectural pmu on a host - * with architectural pmu. - */ - if (!cap.version) - memset(&cap, 0, sizeof(cap)); - - eax.split.version_id = min(cap.version, 2); - eax.split.num_counters = cap.num_counters_gp; - eax.split.bit_width = cap.bit_width_gp; - eax.split.mask_length = cap.events_mask_len; - - edx.split.num_counters_fixed = cap.num_counters_fixed; - edx.split.bit_width_fixed = cap.bit_width_fixed; - edx.split.reserved = 0; - - entry->eax = eax.full; - entry->ebx = cap.events_mask; - entry->ecx = 0; - entry->edx = edx.full; - break; - } - /* function 0xb has additional index. */ - case 0xb: { - int i, level_type; - - entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; - /* read more entries until level_type is zero */ - for (i = 1; ; ++i) { - if (*nent >= maxnent) - goto out; - - level_type = entry[i - 1].ecx & 0xff00; - if (!level_type) - break; - do_cpuid_1_ent(&entry[i], function, i); - entry[i].flags |= - KVM_CPUID_FLAG_SIGNIFCANT_INDEX; - ++*nent; - } - break; - } - case 0xd: { - int idx, i; - - entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; - for (idx = 1, i = 1; idx < 64; ++idx) { - if (*nent >= maxnent) - goto out; - - do_cpuid_1_ent(&entry[i], function, idx); - if (entry[i].eax == 0 || !supported_xcr0_bit(idx)) - continue; - entry[i].flags |= - KVM_CPUID_FLAG_SIGNIFCANT_INDEX; - ++*nent; - ++i; - } - break; - } - case KVM_CPUID_SIGNATURE: { - static const char signature[12] = "KVMKVMKVM\0\0"; - const unsigned int *sigptr = (const unsigned int *)signature; - entry->eax = KVM_CPUID_FEATURES; - entry->ebx = sigptr[0]; - entry->ecx = sigptr[1]; - entry->edx = sigptr[2]; - break; - } - case KVM_CPUID_FEATURES: - entry->eax = (BIT(KVM_FEATURE_CLOCKSOURCE)) | - (BIT(KVM_FEATURE_NOP_IO_DELAY)) | - (BIT(KVM_FEATURE_CLOCKSOURCE2)) | - (BIT(KVM_FEATURE_ASYNC_PF)) | - (BIT(KVM_FEATURE_PV_EOI)) | - (BIT(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)); - - if (sched_info_on()) - entry->eax |= (BIT(KVM_FEATURE_STEAL_TIME)); - - entry->ebx = 0; - entry->ecx = 0; - entry->edx = 0; - break; - case 0x80000019: - entry->ecx = entry->edx = 0; - break; - case 0x8000001a: - break; - case 0x8000001d: - break; - /*Add support for Centaur's CPUID instruction*/ - case 0xC0000000: - /*Just support up to 0xC0000004 now*/ - entry->eax = min(entry->eax, 0xC0000004); - break; - case 0xC0000001: - entry->edx &= kvm_supported_word5_x86_features; - cpuid_mask(&entry->edx, 5); - break; - case 3: /* Processor serial number */ - case 5: /* MONITOR/MWAIT */ - case 6: /* Thermal management */ - case 0x80000007: /* Advanced power management */ - case 0xC0000002: - case 0xC0000003: - case 0xC0000004: - default: - entry->eax = entry->ebx = entry->ecx = entry->edx = 0; - break; - } -#endif - -/* VM exit handler: for the CPUID instruction. */ -int vmm_cpuid_handler(vmm_vcpu_t *vcpu) { - - int ret; - struct cpuid_val val; - - /* Read parameter information. */ - unsigned int function = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); - unsigned int index = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX); - - /* Virtualise the CPUID instruction. */ - ret = vmm_cpuid_virt(function, index, &val, vcpu); - if (ret) - return ret; - - /* Set the return values in guest context. */ - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EAX, val.eax); - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EBX, val.ebx); - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_ECX, val.ecx); - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EDX, val.edx); - - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - - /* Return success. */ - return 0; -}
diff --git a/libsel4vmm/src/processor/cr.c b/libsel4vmm/src/processor/cr.c deleted file mode 100644 index d017dd9..0000000 --- a/libsel4vmm/src/processor/cr.c +++ /dev/null
@@ -1,232 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/*vm exit handler for control register access*/ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> -#include <utils/util.h> - -#include "vmm/debug.h" -#include "vmm/processor/platfeature.h" -#include "vmm/platform/vmcs.h" - -#include "vmm/vmm.h" - -static inline unsigned int apply_cr_bits(unsigned int cr, unsigned int mask, unsigned int host_bits) { - /* force any bit in the mask to be the value from the shadow (both enabled and disabled) */ - cr |= (mask & host_bits); - cr &= ~(mask & (~host_bits)); - return cr; -} - -static int vmm_cr_set_cr0(vmm_vcpu_t *vcpu, unsigned int value) { - - if (value & CR0_RESERVED_BITS) - return -1; - - /* check if paging is being enabled */ - if ((value & X86_CR0_PG) && !(vcpu->guest_state.virt.cr.cr0_shadow & X86_CR0_PG)) { - /* guest is taking over paging. So we can no longer care about some of our CR4 values, and - * we don't need cr3 load/store exiting anymore */ - unsigned int new_mask = vcpu->guest_state.virt.cr.cr4_mask & ~(X86_CR4_PSE | X86_CR4_PAE); - unsigned int cr4_value = vmm_guest_state_get_cr4(&vcpu->guest_state, vcpu->guest_vcpu); - /* for any bits that have changed in the mask, grab them from the shadow */ - cr4_value = apply_cr_bits(cr4_value, new_mask ^ vcpu->guest_state.virt.cr.cr4_mask, vcpu->guest_state.virt.cr.cr4_shadow); - /* update mask and cr4 value */ - vcpu->guest_state.virt.cr.cr4_mask = new_mask; - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR4_MASK, new_mask); - vmm_guest_state_set_cr4(&vcpu->guest_state, cr4_value); - /* now turn of cr3 load/store exiting */ - unsigned int ppc = vmm_guest_state_get_control_ppc(&vcpu->guest_state); - ppc &= ~(VMX_CONTROL_PPC_CR3_LOAD_EXITING | VMX_CONTROL_PPC_CR3_STORE_EXITING); - vmm_guest_state_set_control_ppc(&vcpu->guest_state, ppc); - /* load the cached cr3 value */ - vmm_guest_state_set_cr3(&vcpu->guest_state, vcpu->guest_state.virt.cr.cr3_guest); - } - - /* check if paging is being disabled */ - if (!(value & X86_CR0_PG) && (vcpu->guest_state.virt.cr.cr0_shadow & X86_CR0_PG)) { - ZF_LOGE("Do not support paging being disabled"); - /* if we did support disabling paging we should re-enable cr3 load/store exiting, - * watch the pae bit in cr4 again and then */ - return -1; - } - - /* update the guest shadow */ - vcpu->guest_state.virt.cr.cr0_shadow = value; - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR0_READ_SHADOW, value); - - value = apply_cr_bits(value, vcpu->guest_state.virt.cr.cr0_mask, vcpu->guest_state.virt.cr.cr0_host_bits); - - vmm_guest_state_set_cr0(&vcpu->guest_state, value); - - return 0; -} - -static int vmm_cr_set_cr3(vmm_vcpu_t *vcpu, unsigned int value) { - /* if the guest hasn't turned on paging then just cache this */ - vcpu->guest_state.virt.cr.cr3_guest = value; - if (vcpu->guest_state.virt.cr.cr0_shadow & X86_CR0_PG) { - vmm_guest_state_set_cr3(&vcpu->guest_state, value); - } - return 0; -} - -static int vmm_cr_get_cr3(vmm_vcpu_t *vcpu, unsigned int *value) { - if (vcpu->guest_state.virt.cr.cr0_shadow & X86_CR0_PG) { - *value = vmm_guest_state_get_cr3(&vcpu->guest_state, vcpu->guest_vcpu); - } else { - *value = vcpu->guest_state.virt.cr.cr3_guest; - } - return 0; - -} - -static int vmm_cr_set_cr4(vmm_vcpu_t *vcpu, unsigned int value) { - - if (value & CR4_RESERVED_BITS) - return -1; - - /* update the guest shadow */ - vcpu->guest_state.virt.cr.cr4_shadow = value; - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR4_READ_SHADOW, value); - - value = apply_cr_bits(value, vcpu->guest_state.virt.cr.cr4_mask, vcpu->guest_state.virt.cr.cr4_host_bits); - - vmm_guest_state_set_cr4(&vcpu->guest_state, value); - - return 0; -} - -static int vmm_cr_clts(vmm_vcpu_t *vcpu) { - ZF_LOGI("Ignoring call of clts"); - - return -1; -} - -static int vmm_cr_lmsw(vmm_vcpu_t *vcpu, unsigned int value) { - ZF_LOGI("Ignoring call of lmsw"); - - return -1; - -} - -/* Convert exit regs to seL4 user context */ -static int crExitRegs[] = { - USER_CONTEXT_EAX, - USER_CONTEXT_ECX, - USER_CONTEXT_EDX, - USER_CONTEXT_EBX, - /*USER_CONTEXT_ESP*/-1, - USER_CONTEXT_EBP, - USER_CONTEXT_ESI, - USER_CONTEXT_EDI -}; - -int vmm_cr_access_handler(vmm_vcpu_t *vcpu) { - - unsigned int exit_qualification, val; - int cr, reg, ret = -1; - - exit_qualification = vmm_guest_exit_get_qualification(&vcpu->guest_state); - cr = exit_qualification & 15; - reg = (exit_qualification >> 8) & 15; - - switch ((exit_qualification >> 4) & 3) { - case 0: /* mov to cr */ - if (crExitRegs[reg] < 0) { - return -1; - } - val = vmm_read_user_context(&vcpu->guest_state, crExitRegs[reg]); - - switch (cr) { - case 0: - ret = vmm_cr_set_cr0(vcpu, val); - break; - case 3: - ret = vmm_cr_set_cr3(vcpu, val); - break; - case 4: - ret = vmm_cr_set_cr4(vcpu, val); - break; - case 8: - -#if 0 - - u8 cr8_prev = kvm_get_cr8(vcpu); - u8 cr8 = kvm_register_read(vcpu, reg); - err = kvm_set_cr8(vcpu, cr8); - kvm_complete_insn_gp(vcpu, err); - if (irqchip_in_kernel(vcpu->kvm)) - return 1; - if (cr8_prev <= cr8) - return 1; - vcpu->run->exit_reason = KVM_EXIT_SET_TPR; - return 0; -#endif - - default: - DPRINTF(4, "unhandled control register: op %d cr %d\n", - (int)(exit_qualification >> 4) & 3, cr); - break; - - } - break; - - case 1: /*mov from cr*/ - switch (cr) { - case 3: - - ret = vmm_cr_get_cr3(vcpu, &val); - if (!ret) - vmm_set_user_context(&vcpu->guest_state, crExitRegs[reg], val); - - break; - case 8: -#if 0 - val = kvm_get_cr8(vcpu); - kvm_register_write(vcpu, reg, val); - trace_kvm_cr_read(cr, val); - skip_emulated_instruction(vcpu); - return 1; -#endif - default: - DPRINTF(4, "unhandled control register: op %d cr %d\n", - (int)(exit_qualification >> 4) & 3, cr); - break; - - } - break; - case 2: /* clts */ - ret = vmm_cr_clts(vcpu); - break; - - case 3: /* lmsw */ - val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f; - ret = vmm_cr_lmsw(vcpu, val); - break; - - default: - DPRINTF(4, "unhandled control register: op %d cr %d\n", - (int)(exit_qualification >> 4) & 3, cr); - break; - } - - if (!ret) { - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - } - - return ret; -}
diff --git a/libsel4vmm/src/processor/decode.c b/libsel4vmm/src/processor/decode.c deleted file mode 100644 index e780efc..0000000 --- a/libsel4vmm/src/processor/decode.c +++ /dev/null
@@ -1,342 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* x86 fetch/decode/emulate code - -Author: W.A. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "vmm/debug.h" -#include "vmm/platform/guest_vspace.h" -#include "vmm/platform/guest_memory.h" -#include "vmm/guest_state.h" -#include "vmm/processor/platfeature.h" - -/* TODO are these defined elsewhere? */ -#define IA32_PDE_SIZE(pde) (pde & BIT(7)) -#define IA32_PDE_PRESENT(pde) (pde & BIT(0)) -#define IA32_PTE_ADDR(pte) (pte & 0xFFFFF000) -#define IA32_PSE_ADDR(pde) (pde & 0xFFC00000) - -#define IA32_OPCODE_S(op) (op & BIT(0)) -#define IA32_OPCODE_D(op) (op & BIT(1)) -#define IA32_OPCODY_BODY(op) (op & 0b11111100) -#define IA32_MODRM_REG(m) ((m & 0b00111000) >> 3) - -#define SEG_MULT (0x10) - -/* Get a word from a guest physical address */ -inline static uint32_t guest_get_phys_word(vmm_t *vmm, uintptr_t addr) { - uint32_t val; - - vmm_guest_vspace_touch(&vmm->guest_mem.vspace, addr, sizeof(uint32_t), - vmm_guest_get_phys_data_help, &val); - - return val; -} - -/* Fetch a guest's instruction */ -int vmm_fetch_instruction(vmm_vcpu_t *vcpu, uint32_t eip, uintptr_t cr3, - int len, uint8_t *buf) { - /* Walk page tables to get physical address of instruction */ - uintptr_t instr_phys = 0; - - /* ensure that PAE is not enabled */ - if (vmm_guest_state_get_cr4(&vcpu->guest_state, vcpu->guest_vcpu) & X86_CR4_PAE) { - ZF_LOGE("Do not support walking PAE paging structures"); - return -1; - } - - // TODO implement page-boundary crossing properly - assert((eip >> 12) == ((eip + len) >> 12)); - - uint32_t pdi = eip >> 22; - uint32_t pti = (eip >> 12) & 0x3FF; - - uint32_t pde = guest_get_phys_word(vcpu->vmm, cr3 + pdi * 4); - - assert(IA32_PDE_PRESENT(pde)); /* WTF? */ - - if (IA32_PDE_SIZE(pde)) { - /* PSE is used, 4M pages */ - instr_phys = (uintptr_t)IA32_PSE_ADDR(pde) + (eip & 0x3FFFFF); - } else { - /* 4k pages */ - uint32_t pte = guest_get_phys_word(vcpu->vmm, - (uintptr_t)IA32_PTE_ADDR(pde) + pti * 4); - - assert(IA32_PDE_PRESENT(pte)); - - instr_phys = (uintptr_t)IA32_PTE_ADDR(pte) + (eip & 0xFFF); - } - - /* Fetch instruction */ - vmm_guest_vspace_touch(&vcpu->vmm->guest_mem.vspace, instr_phys, len, - vmm_guest_get_phys_data_help, buf); - - return 0; -} - -/* Returns 1 if this byte is an x86 instruction prefix */ -static int is_prefix(uint8_t byte) { - switch (byte) { - case 0x26: - case 0x2e: - case 0x36: - case 0x3e: - case 0x64: - case 0x65: - case 0x67: - case 0x66: - return 1; - } - - return 0; -} - -static void debug_print_instruction(uint8_t *instr, int instr_len) { - printf("instruction dump: "); - for (int j = 0; j < instr_len; j++) { - printf("%2x ", instr[j]); - } - printf("\n"); -} - -/* Partial support to decode an instruction for a memory access - This is very crude. It can break in many ways. */ -int vmm_decode_instruction(uint8_t *instr, int instr_len, int *reg, uint32_t *imm, int *op_len) { - /* First loop through and check prefixes */ - int oplen = 1; /* Operand length */ - int i; - for (i = 0; i < instr_len; i++) { - if (is_prefix(instr[i])) { - if (instr[i] == 0x66) { - /* 16 bit modifier */ - oplen = 2; - } - } else { - /* We've hit the opcode */ - break; - } - } - assert(i < instr_len); /* We still need an opcode */ - - uint8_t opcode = instr[i]; - //uint8_t opcode_ex = 0; - if (opcode == 0x0f) { - printf("can't emulate instruction with multi-byte opcode!\n"); - debug_print_instruction(instr, instr_len); - assert(0); /* We don't handle >1 byte opcodes */ - } - if (oplen != 2 && IA32_OPCODE_S(opcode)) { - oplen = 4; - } - - uint8_t modrm = instr[++i]; - switch (opcode) { - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - case 0x8c: - // Mov with register - *reg = IA32_MODRM_REG(modrm); - *op_len = oplen; - break; - case 0xc6: - case 0xc7: - // Mov with immediate - *reg = -1; - *op_len = oplen; - uint32_t immediate = 0; - for (int j = 0; j < oplen; j++) { - immediate <<= 8; - immediate |= instr[instr_len - j - 1]; - } - *imm = immediate; - break; - default: - printf("can't emulate this instruction!\n"); - debug_print_instruction(instr, instr_len); - assert(0); - } - - return 0; -} - -/* - Useful information: The GDT loaded by the Linux SMP trampoline looks like: -0x00: 00 00 00 00 00 00 00 00 -0x08: 00 00 00 00 00 00 00 00 -0x10: ff ff 00 00 00 9b cf 00 <- Executable 0x00000000-0xffffffff -0x18: ff ff 00 00 00 93 cf 00 <- RW data 0x00000000-0xffffffff -*/ - -/* Interpret just enough virtual 8086 instructions to run trampoline code. - Returns the final jump address */ -uintptr_t vmm_emulate_realmode(guest_memory_t *gm, uint8_t *instr_buf, - uint16_t *segment, uintptr_t eip, uint32_t len, guest_state_t *gs) -{ - /* We only track one segment, and assume that code and data are in the same - segment, which is valid for most trampoline and bootloader code */ - uint8_t *instr = instr_buf; - assert(segment); - - while (instr - instr_buf < len) { - uintptr_t mem = 0; - uint32_t lit = 0; - int m66 = 0; - - uint32_t base = 0; - uint32_t limit = 0; - - if (*instr == 0x66) { - m66 = 1; - instr++; - } - - if (*instr == 0x0f) { - instr++; - if (*instr == 0x01) { - instr++; - if (*instr == 0x1e) { - // lidtl - instr++; - memcpy(&mem, instr, 2); - mem += *segment * SEG_MULT; - instr += 2; - - /* Limit is first 2 bytes, base is next 4 bytes */ - vmm_guest_vspace_touch(&gm->vspace, mem, - 2, vmm_guest_get_phys_data_help, &limit); - vmm_guest_vspace_touch(&gm->vspace, mem + 2, - 4, vmm_guest_get_phys_data_help, &base); - DPRINTF(4, "lidtl %p\n", (void*)mem); - - vmm_guest_state_set_idt_base(gs, base); - vmm_guest_state_set_idt_limit(gs, limit); - } else if (*instr == 0x16) { - // lgdtl - instr++; - memcpy(&mem, instr, 2); - mem += *segment * SEG_MULT; - instr += 2; - - /* Limit is first 2 bytes, base is next 4 bytes */ - vmm_guest_vspace_touch(&gm->vspace, mem, - 2, vmm_guest_get_phys_data_help, &limit); - vmm_guest_vspace_touch(&gm->vspace, mem + 2, - 4, vmm_guest_get_phys_data_help, &base); - DPRINTF(4, "lgdtl %p; base = %x, limit = %x\n", (void*)mem, - base, limit); - - vmm_guest_state_set_gdt_base(gs, base); - vmm_guest_state_set_gdt_limit(gs, limit); - } else { - //ignore - instr++; - } - } else { - //ignore - instr++; - } - } else if (*instr == 0xea) { - /* Absolute jmp */ - instr++; - uint32_t base = 0; - uintptr_t jmp_addr = 0; - if (m66) { - // base is 4 bytes - /* Make the wild assumptions that we are now in protected mode - and the relevant GDT entry just covers all memory. Therefore - the base address is our absolute address. This just happens - to work with Linux and probably other modern systems that - don't use the GDT much. */ - memcpy(&base, instr, 4); - instr += 4; - jmp_addr = base; - memcpy(segment, instr, 2); - } else { - memcpy(&base, instr, 2); - instr += 2; - memcpy(segment, instr, 2); - jmp_addr = *segment * SEG_MULT + base; - } - instr += 2; - DPRINTF(4, "absolute jmpf $%p, cs now %04x\n", (void*)jmp_addr, *segment); - if (((int64_t)jmp_addr - (int64_t)(len + eip)) >= 0) { - vmm_guest_state_set_cs_selector(gs, *segment); - return jmp_addr; - } else { - instr = jmp_addr - eip + instr_buf; - } - } else { - switch (*instr) { - case 0xa1: - /* mov offset memory to eax */ - instr++; - memcpy(&mem, instr, 2); - instr += 2; - mem += *segment * SEG_MULT; - DPRINTF(4, "mov %p, eax\n", (void*)mem); - uint32_t eax; - vmm_guest_vspace_touch(&gm->vspace, mem, - 4, vmm_guest_get_phys_data_help, &eax); - vmm_set_user_context(gs, USER_CONTEXT_EAX, eax); - break; - case 0xc7: - instr++; - if (*instr == 0x06) { // modrm - int size; - instr++; - /* mov literal to memory */ - memcpy(&mem, instr, 2); - mem += *segment * SEG_MULT; - instr += 2; - if (m66) { - memcpy(&lit, instr, 4); - size = 4; - } else { - memcpy(&lit, instr, 2); - size = 2; - } - instr += size; - DPRINTF(4, "mov $0x%x, %p\n", lit, (void*)mem); - vmm_guest_vspace_touch(&gm->vspace, mem, - size, vmm_guest_set_phys_data_help, &lit); - } - break; - case 0xba: - //?????mov literal to dx - /* ignore */ - instr += 2; - break; - case 0x8c: - case 0x8e: - /* mov to/from sreg. ignore */ - instr += 2; - break; - default: - /* Assume this is a single byte instruction we can ignore */ - instr++; - } - } - - DPRINTF(6, "read %zu bytes\n", (size_t)(instr - instr_buf)); - } - - return 0; -}
diff --git a/libsel4vmm/src/processor/lapic.c b/libsel4vmm/src/processor/lapic.c deleted file mode 100644 index 03943af..0000000 --- a/libsel4vmm/src/processor/lapic.c +++ /dev/null
@@ -1,1064 +0,0 @@ -/* @TAG(OTHER_GPL) */ - -/* - * Local APIC virtualization - * - * Copyright (C) 2006 Qumranet, Inc. - * Copyright (C) 2007 Novell - * Copyright (C) 2007 Intel - * Copyright 2009 Red Hat, Inc. and/or its affiliates. - * - * Authors: - * Dor Laor <dor.laor@qumranet.com> - * Gregory Haskins <ghaskins@novell.com> - * Yaozu (Eddie) Dong <eddie.dong@intel.com> - * - * Based on Xen 3.1 code, Copyright (c) 2004, Intel Corporation. - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <utils/util.h> - -#include "vmm/debug.h" - -#include "vmm/processor/lapic.h" -#include "vmm/processor/apicdef.h" -#include "vmm/processor/msr.h" -#include "vmm/mmio.h" - -#define APIC_BUS_CYCLE_NS 1 - -#define APIC_DEBUG 0 -#define apic_debug(lvl,...) do{ if(lvl < APIC_DEBUG){printf(__VA_ARGS__);fflush(stdout);}}while (0) - -#define APIC_LVT_NUM 6 -/* 14 is the version for Xeon and Pentium 8.4.8*/ -#define APIC_VERSION (0x14UL | ((APIC_LVT_NUM - 1) << 16)) -#define LAPIC_MMIO_LENGTH (BIT(12)) -/* followed define is not in apicdef.h */ -#define APIC_SHORT_MASK 0xc0000 -#define APIC_DEST_NOSHORT 0x0 -#define APIC_DEST_MASK 0x800 -#define MAX_APIC_VECTOR 256 -#define APIC_VECTORS_PER_REG 32 - -inline static int pic_get_interrupt(vmm_t *vmm) -{ - return vmm->plat_callbacks.get_interrupt(); -} - -inline static int pic_has_interrupt(vmm_t *vmm) -{ - return vmm->plat_callbacks.has_interrupt(); -} - -struct vmm_lapic_irq { - uint32_t vector; - uint32_t delivery_mode; - uint32_t dest_mode; - uint32_t level; - uint32_t trig_mode; - uint32_t shorthand; - uint32_t dest_id; -}; - -/* Generic bit operations; TODO move these elsewhere */ -static inline int fls(int x) -{ - int r = 32; - - if (!x) - return 0; - - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; -} - -static uint32_t hweight32(unsigned int w) -{ - uint32_t res = w - ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res + (res >> 4)) & 0x0F0F0F0F; - res = res + (res >> 8); - return (res + (res >> 16)) & 0x000000FF; -} -/* End generic bit ops */ - -void vmm_lapic_reset(vmm_vcpu_t *vcpu); - -// Returns whether the irq delivery mode is lowest prio -inline static bool vmm_is_dm_lowest_prio(struct vmm_lapic_irq *irq) -{ - return irq->delivery_mode == APIC_DM_LOWEST; -} - -// Access register field -static inline void apic_set_reg(vmm_lapic_t *apic, int reg_off, uint32_t val) -{ - *((uint32_t *) (apic->regs + reg_off)) = val; -} - -static inline uint32_t vmm_apic_get_reg(vmm_lapic_t *apic, int reg_off) -{ - return *((uint32_t *) (apic->regs + reg_off)); -} - -static inline int apic_test_vector(int vec, void *bitmap) -{ - return ((1UL << (vec & 31)) & ((uint32_t *)bitmap)[vec >> 5]) != 0; -} - -bool vmm_apic_pending_eoi(vmm_vcpu_t *vcpu, int vector) -{ - vmm_lapic_t *apic = vcpu->lapic; - - return apic_test_vector(vector, apic->regs + APIC_ISR) || - apic_test_vector(vector, apic->regs + APIC_IRR); -} - -static inline void apic_set_vector(int vec, void *bitmap) -{ - ((uint32_t *)bitmap)[vec >> 5] |= 1UL << (vec & 31); -} - -static inline void apic_clear_vector(int vec, void *bitmap) -{ - ((uint32_t *)bitmap)[vec >> 5] &= ~(1UL << (vec & 31)); -} - -static inline int vmm_apic_sw_enabled(vmm_lapic_t *apic) -{ - return vmm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_APIC_ENABLED; -} - -static inline int vmm_apic_hw_enabled(vmm_lapic_t *apic) -{ - return apic->apic_base & MSR_IA32_APICBASE_ENABLE; -} - -inline int vmm_apic_enabled(vmm_lapic_t *apic) -{ - return vmm_apic_sw_enabled(apic) && vmm_apic_hw_enabled(apic); -} - -#define LVT_MASK \ - (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK) - -#define LINT_MASK \ - (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \ - APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER) - -static inline int vmm_apic_id(vmm_lapic_t *apic) -{ - return (vmm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff; -} - -static inline void apic_set_spiv(vmm_lapic_t *apic, uint32_t val) -{ - apic_set_reg(apic, APIC_SPIV, val); -} - -static const unsigned int apic_lvt_mask[APIC_LVT_NUM] = { - LVT_MASK , /* part LVTT mask, timer mode mask added at runtime */ - LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */ - LVT_MASK | APIC_MODE_MASK, /* LVTPC */ - LINT_MASK, LINT_MASK, /* LVT0-1 */ - LVT_MASK /* LVTERR */ -}; - -static inline void vmm_apic_set_id(vmm_lapic_t *apic, uint8_t id) -{ - apic_set_reg(apic, APIC_ID, id << 24); -} - -static inline void vmm_apic_set_ldr(vmm_lapic_t *apic, uint32_t id) -{ - apic_set_reg(apic, APIC_LDR, id); -} - -static inline int apic_lvt_enabled(vmm_lapic_t *apic, int lvt_type) -{ - return !(vmm_apic_get_reg(apic, lvt_type) & APIC_LVT_MASKED); -} - -static inline int apic_lvt_vector(vmm_lapic_t *apic, int lvt_type) -{ - return vmm_apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK; -} - -static inline int vmm_vcpu_is_bsp(vmm_vcpu_t *vcpu) -{ - return vcpu->vcpu_id == BOOT_VCPU; -} - -static inline int apic_lvt_nmi_mode(uint32_t lvt_val) -{ - return (lvt_val & (APIC_MODE_MASK | APIC_LVT_MASKED)) == APIC_DM_NMI; -} - -int vmm_apic_compare_prio(vmm_vcpu_t *vcpu1, vmm_vcpu_t *vcpu2) -{ - return vcpu1->lapic->arb_prio - vcpu2->lapic->arb_prio; -} - -static void UNUSED dump_vector(const char *name, void *bitmap) -{ - int vec; - uint32_t *reg = bitmap; - - printf("%s = 0x", name); - - for (vec = MAX_APIC_VECTOR - APIC_VECTORS_PER_REG; - vec >= 0; vec -= APIC_VECTORS_PER_REG) { - printf("%08x", reg[vec >> 5]); - } - - printf("\n"); -} - -static int find_highest_vector(void *bitmap) -{ - int vec; - uint32_t *reg = bitmap; - - for (vec = MAX_APIC_VECTOR - APIC_VECTORS_PER_REG; - vec >= 0; vec -= APIC_VECTORS_PER_REG) { - if (reg[vec >> 5]) - return fls(reg[vec >> 5]) - 1 + vec; - } - - return -1; -} - -static uint8_t UNUSED count_vectors(void *bitmap) -{ - int vec; - uint32_t *reg = bitmap; - uint8_t count = 0; - - for (vec = 0; vec < MAX_APIC_VECTOR; vec += APIC_VECTORS_PER_REG) { - count += hweight32(reg[vec >> 5]); - } - - return count; -} - -static inline int apic_search_irr(vmm_lapic_t *apic) -{ - return find_highest_vector(apic->regs + APIC_IRR); -} - -static inline int apic_find_highest_irr(vmm_lapic_t *apic) -{ - int result; - - if (!apic->irr_pending) - return -1; - - result = apic_search_irr(apic); - assert(result == -1 || result >= 16); - - return result; -} - -static inline void apic_set_irr(int vec, vmm_lapic_t *apic) -{ - if (vec != 0x30) { - apic_debug(5, "!settting irr 0x%x\n", vec); - } - - apic->irr_pending = true; - apic_set_vector(vec, apic->regs + APIC_IRR); -} - -static inline void apic_clear_irr(int vec, vmm_lapic_t *apic) -{ - apic_clear_vector(vec, apic->regs + APIC_IRR); - - vec = apic_search_irr(apic); - apic->irr_pending = (vec != -1); -} - -static inline void apic_set_isr(int vec, vmm_lapic_t *apic) -{ - if (apic_test_vector(vec, apic->regs + APIC_ISR)) { - return; - } - apic_set_vector(vec, apic->regs + APIC_ISR); - - ++apic->isr_count; - /* - * ISR (in service register) bit is set when injecting an interrupt. - * The highest vector is injected. Thus the latest bit set matches - * the highest bit in ISR. - */ -} - -static inline int apic_find_highest_isr(vmm_lapic_t *apic) -{ - int result; - - /* - * Note that isr_count is always 1, and highest_isr_cache - * is always -1, with APIC virtualization enabled. - */ - if (!apic->isr_count) - return -1; - if (apic->highest_isr_cache != -1) - return apic->highest_isr_cache; - - result = find_highest_vector(apic->regs + APIC_ISR); - assert(result == -1 || result >= 16); - - return result; -} - -static inline void apic_clear_isr(int vec, vmm_lapic_t *apic) -{ - if (!apic_test_vector(vec, apic->regs + APIC_ISR)) { - return; - } - apic_clear_vector(vec, apic->regs + APIC_ISR); - - --apic->isr_count; - apic->highest_isr_cache = -1; -} - -int vmm_lapic_find_highest_irr(vmm_vcpu_t *vcpu) -{ - int highest_irr; - - highest_irr = apic_find_highest_irr(vcpu->lapic); - - return highest_irr; -} - -static int __apic_accept_irq(vmm_vcpu_t *vcpu, int delivery_mode, - int vector, int level, int trig_mode, - unsigned long *dest_map); - -int vmm_apic_set_irq(vmm_vcpu_t *vcpu, struct vmm_lapic_irq *irq, - unsigned long *dest_map) -{ - return __apic_accept_irq(vcpu, irq->delivery_mode, irq->vector, - irq->level, irq->trig_mode, dest_map); -} - -void vmm_apic_update_tmr(vmm_vcpu_t *vcpu, uint32_t *tmr) -{ - vmm_lapic_t *apic = vcpu->lapic; - int i; - - for (i = 0; i < 8; i++) - apic_set_reg(apic, APIC_TMR + 0x10 * i, tmr[i]); -} - -static void apic_update_ppr(vmm_vcpu_t *vcpu) -{ - uint32_t tpr, isrv, ppr, old_ppr; - int isr; - vmm_lapic_t *apic = vcpu->lapic; - - old_ppr = vmm_apic_get_reg(apic, APIC_PROCPRI); - tpr = vmm_apic_get_reg(apic, APIC_TASKPRI); - isr = apic_find_highest_isr(apic); - isrv = (isr != -1) ? isr : 0; - - if ((tpr & 0xf0) >= (isrv & 0xf0)) - ppr = tpr & 0xff; - else - ppr = isrv & 0xf0; - - apic_debug(6, "vlapic %p, ppr 0x%x, isr 0x%x, isrv 0x%x\n", - apic, ppr, isr, isrv); - - if (old_ppr != ppr) { - apic_set_reg(apic, APIC_PROCPRI, ppr); - if (ppr < old_ppr) { - /* Might have unmasked some pending interrupts */ - vmm_vcpu_accept_interrupt(vcpu); - } - } -} - -static void apic_set_tpr(vmm_vcpu_t *vcpu, uint32_t tpr) -{ - apic_set_reg(vcpu->lapic, APIC_TASKPRI, tpr); - apic_debug(3, "vcpu %d lapic TPR set to %d\n", vcpu->vcpu_id, tpr); - apic_update_ppr(vcpu); -} - -int vmm_apic_match_physical_addr(vmm_lapic_t *apic, uint16_t dest) -{ - return dest == 0xff || vmm_apic_id(apic) == dest; -} - -int vmm_apic_match_logical_addr(vmm_lapic_t *apic, uint8_t mda) -{ - int result = 0; - uint32_t logical_id; - - logical_id = GET_APIC_LOGICAL_ID(vmm_apic_get_reg(apic, APIC_LDR)); - - switch (vmm_apic_get_reg(apic, APIC_DFR)) { - case APIC_DFR_FLAT: - if (logical_id & mda) - result = 1; - break; - case APIC_DFR_CLUSTER: - if (((logical_id >> 4) == (mda >> 0x4)) - && (logical_id & mda & 0xf)) - result = 1; - break; - default: - apic_debug(1, "Bad DFR: %08x\n", vmm_apic_get_reg(apic, APIC_DFR)); - break; - } - - return result; -} - -int vmm_apic_match_dest(vmm_vcpu_t *vcpu, vmm_lapic_t *source, - int short_hand, int dest, int dest_mode) -{ - int result = 0; - vmm_lapic_t *target = vcpu->lapic; - - assert(target); - switch (short_hand) { - case APIC_DEST_NOSHORT: - if (dest_mode == 0) - /* Physical mode. */ - result = vmm_apic_match_physical_addr(target, dest); - else - /* Logical mode. */ - result = vmm_apic_match_logical_addr(target, dest); - break; - case APIC_DEST_SELF: - result = (target == source); - break; - case APIC_DEST_ALLINC: - result = 1; - break; - case APIC_DEST_ALLBUT: - result = (target != source); - break; - default: - apic_debug(2, "apic: Bad dest shorthand value %x\n", - short_hand); - break; - } - - apic_debug(4, "target %p, source %p, dest 0x%x, " - "dest_mode 0x%x, short_hand 0x%x", - target, source, dest, dest_mode, short_hand); - if (result) { - apic_debug(4, " MATCH\n"); - } else { - apic_debug(4, "\n"); - } - - return result; -} - -int vmm_irq_delivery_to_apic(vmm_vcpu_t *src_vcpu, struct vmm_lapic_irq *irq, unsigned long *dest_map) -{ - int i, r = -1; - vmm_lapic_t *src = src_vcpu->lapic; - vmm_t *vmm = src_vcpu->vmm; - - vmm_vcpu_t *lowest = NULL; - - if (irq->shorthand == APIC_DEST_SELF) { - return vmm_apic_set_irq(src_vcpu, irq, dest_map); - } - - for (i = 0; i < vmm->num_vcpus; i++) { - vmm_vcpu_t *dest_vcpu = &vmm->vcpus[i]; - - if (!vmm_apic_hw_enabled(dest_vcpu->lapic)) { - continue; - } - - if (!vmm_apic_match_dest(dest_vcpu, src, irq->shorthand, - irq->dest_id, irq->dest_mode)) { - continue; - } - - if (!vmm_is_dm_lowest_prio(irq)) { - // Normal delivery - if (r < 0) { - r = 0; - } - r += vmm_apic_set_irq(dest_vcpu, irq, dest_map); - } else if (vmm_apic_enabled(dest_vcpu->lapic)) { - // Pick vcpu with lowest priority to deliver to - if (!lowest) { - lowest = dest_vcpu; - } else if (vmm_apic_compare_prio(dest_vcpu, lowest) < 0) { - lowest = dest_vcpu; - } - } - } - - if (lowest) { - r = vmm_apic_set_irq(lowest, irq, dest_map); - } - - return r; -} - -/* - * Add a pending IRQ into lapic. - * Return 1 if successfully added and 0 if discarded. - */ -static int __apic_accept_irq(vmm_vcpu_t *vcpu, int delivery_mode, - int vector, int level, int trig_mode, - unsigned long *dest_map) -{ - int result = 0; - vmm_lapic_t *apic = vcpu->lapic; - - switch (delivery_mode) { - case APIC_DM_LOWEST: - apic->arb_prio++; - case APIC_DM_FIXED: - /* FIXME add logic for vcpu on reset */ - if (!vmm_apic_enabled(apic)) { - break; - } - apic_debug(4, "####fixed ipi 0x%x to vcpu %d\n", vector, vcpu->vcpu_id); - - result = 1; - apic_set_irr(vector, apic); - vmm_vcpu_accept_interrupt(vcpu); - break; - - case APIC_DM_NMI: - case APIC_DM_REMRD: - result = 1; - vmm_vcpu_accept_interrupt(vcpu); - break; - - case APIC_DM_SMI: - apic_debug(2, "Ignoring guest SMI\n"); - break; - - case APIC_DM_INIT: - apic_debug(2, "Got init ipi on vcpu %d\n", vcpu->vcpu_id); - if (!trig_mode || level) { - if (apic->state == LAPIC_STATE_RUN) { - /* Already running, ignore inits */ - break; - } - result = 1; - vmm_lapic_reset(vcpu); - apic->arb_prio = vmm_apic_id(apic); - apic->state = LAPIC_STATE_WAITSIPI; - } else { - apic_debug(2, "Ignoring de-assert INIT to vcpu %d\n", - vcpu->vcpu_id); - } - break; - - case APIC_DM_STARTUP: - if (apic->state != LAPIC_STATE_WAITSIPI) { - apic_debug(1, "Received SIPI while processor was not in wait for SIPI state\n"); - } else { - apic_debug(2, "SIPI to vcpu %d vector 0x%02x\n", - vcpu->vcpu_id, vector); - result = 1; - apic->sipi_vector = vector; - apic->state = LAPIC_STATE_RUN; - - /* Start the VCPU thread. */ - vmm_start_ap_vcpu(vcpu, vector); - } - break; - - case APIC_DM_EXTINT: - /* extints are handled by vmm_apic_consume_extints */ - printf("extint should not come to this function. vcpu %d\n", vcpu->vcpu_id); - assert(0); - break; - - default: - printf("TODO: unsupported lapic ipi delivery mode %x", delivery_mode); - assert(0); - break; - } - return result; -} - -static int apic_set_eoi(vmm_vcpu_t *vcpu) -{ - vmm_lapic_t *apic = vcpu->lapic; - int vector = apic_find_highest_isr(apic); - - /* - * Not every write EOI will has corresponding ISR, - * one example is when Kernel check timer on setup_IO_APIC - */ - if (vector == -1) - return vector; - - apic_clear_isr(vector, apic); - apic_update_ppr(vcpu); - - /* If another interrupt is pending, raise it */ - vmm_vcpu_accept_interrupt(vcpu); - - return vector; -} - -static void apic_send_ipi(vmm_vcpu_t *vcpu) -{ - vmm_lapic_t *apic = vcpu->lapic; - uint32_t icr_low = vmm_apic_get_reg(apic, APIC_ICR); - uint32_t icr_high = vmm_apic_get_reg(apic, APIC_ICR2); - struct vmm_lapic_irq irq; - - irq.vector = icr_low & APIC_VECTOR_MASK; - irq.delivery_mode = icr_low & APIC_MODE_MASK; - irq.dest_mode = icr_low & APIC_DEST_MASK; - irq.level = icr_low & APIC_INT_ASSERT; - irq.trig_mode = icr_low & APIC_INT_LEVELTRIG; - irq.shorthand = icr_low & APIC_SHORT_MASK; - irq.dest_id = GET_APIC_DEST_FIELD(icr_high); - - apic_debug(3, "icr_high 0x%x, icr_low 0x%x, " - "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, " - "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n", - icr_high, icr_low, irq.shorthand, irq.dest_id, - irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode, - irq.vector); - - vmm_irq_delivery_to_apic(vcpu, &irq, NULL); -} - -static uint32_t __apic_read(vmm_lapic_t *apic, unsigned int offset) -{ - uint32_t val = 0; - - if (offset >= LAPIC_MMIO_LENGTH) - return 0; - - switch (offset) { - case APIC_ID: - val = vmm_apic_id(apic) << 24; - break; - case APIC_ARBPRI: - apic_debug(2, "Access APIC ARBPRI register which is for P6\n"); - break; - - case APIC_TMCCT: /* Timer CCR */ - break; - case APIC_PROCPRI: - val = vmm_apic_get_reg(apic, offset); - break; - default: - val = vmm_apic_get_reg(apic, offset); - break; - } - - return val; -} - -static void apic_manage_nmi_watchdog(vmm_lapic_t *apic, uint32_t lvt0_val) -{ - int nmi_wd_enabled = apic_lvt_nmi_mode(vmm_apic_get_reg(apic, APIC_LVT0)); - - if (apic_lvt_nmi_mode(lvt0_val)) { - if (!nmi_wd_enabled) { - apic_debug(4, "Receive NMI setting on APIC_LVT0 \n"); - } - } -} - -static int apic_reg_write(vmm_vcpu_t *vcpu, uint32_t reg, uint32_t val) -{ - vmm_lapic_t *apic = vcpu->lapic; - int ret = 0; - - switch (reg) { - case APIC_ID: /* Local APIC ID */ - vmm_apic_set_id(apic, val >> 24); - break; - - case APIC_TASKPRI: - apic_set_tpr(vcpu, val & 0xff); - break; - - case APIC_EOI: - apic_set_eoi(vcpu); - break; - - case APIC_LDR: - vmm_apic_set_ldr(apic, val & APIC_LDR_MASK); - break; - - case APIC_DFR: - apic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF); - break; - - case APIC_SPIV: { - uint32_t mask = 0x3ff; - if (vmm_apic_get_reg(apic, APIC_LVR) & APIC_LVR_DIRECTED_EOI) - mask |= APIC_SPIV_DIRECTED_EOI; - apic_set_spiv(apic, val & mask); - if (!(val & APIC_SPIV_APIC_ENABLED)) { - int i; - uint32_t lvt_val; - - for (i = 0; i < APIC_LVT_NUM; i++) { - lvt_val = vmm_apic_get_reg(apic, - APIC_LVTT + 0x10 * i); - apic_set_reg(apic, APIC_LVTT + 0x10 * i, - lvt_val | APIC_LVT_MASKED); - } - // atomic_set(&apic->lapic_timer.pending, 0); - - } - break; - } - case APIC_ICR: - /* No delay here, so we always clear the pending bit */ - apic_set_reg(apic, APIC_ICR, val & ~(BIT(12))); - apic_send_ipi(vcpu); - break; - - case APIC_ICR2: - val &= 0xff000000; - apic_set_reg(apic, APIC_ICR2, val); - break; - - case APIC_LVT0: - apic_manage_nmi_watchdog(apic, val); - case APIC_LVTTHMR: - case APIC_LVTPC: - case APIC_LVT1: - case APIC_LVTERR: - /* TODO: Check vector */ - if (!vmm_apic_sw_enabled(apic)) - val |= APIC_LVT_MASKED; - - val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4]; - apic_set_reg(apic, reg, val); - - break; - - case APIC_LVTT: - apic_set_reg(apic, APIC_LVTT, val); - break; - - case APIC_TMICT: - apic_set_reg(apic, APIC_TMICT, val); - break; - - case APIC_TDCR: - apic_set_reg(apic, APIC_TDCR, val); - break; - - default: - ret = 1; - break; - } - if (ret) - apic_debug(2, "Local APIC Write to read-only register %x\n", reg); - return ret; -} - -void vmm_apic_mmio_write(vmm_vcpu_t *vcpu, void *cookie, uint32_t offset, - int len, const uint32_t data) -{ - (void)cookie; - - /* - * APIC register must be aligned on 128-bits boundary. - * 32/64/128 bits registers must be accessed thru 32 bits. - * Refer SDM 8.4.1 - */ - if (len != 4 || (offset & 0xf)) { - apic_debug(1, "apic write: bad size=%d %x\n", len, offset); - return; - } - - /* too common printing */ - if (offset != APIC_EOI) - apic_debug(6, "lapic mmio write at %s: offset 0x%x with length 0x%x, and value is " - "0x%x\n", __func__, offset, len, data); - - apic_reg_write(vcpu, offset & 0xff0, data); -} - -static int apic_reg_read(vmm_lapic_t *apic, uint32_t offset, int len, - void *data) -{ - unsigned char alignment = offset & 0xf; - uint32_t result; - /* this bitmask has a bit cleared for each reserved register */ - static const uint64_t rmask = 0x43ff01ffffffe70cULL; - - if ((alignment + len) > 4) { - apic_debug(2, "APIC READ: alignment error %x %d\n", - offset, len); - return 1; - } - - if (offset > 0x3f0 || !(rmask & (1ULL << (offset >> 4)))) { - apic_debug(2, "APIC_READ: read reserved register %x\n", - offset); - return 1; - } - - result = __apic_read(apic, offset & ~0xf); - - switch (len) { - case 1: - case 2: - case 4: - memcpy(data, (char *)&result + alignment, len); - break; - default: - apic_debug(2, "Local APIC read with len = %x, " - "should be 1,2, or 4 instead\n", len); - break; - } - return 0; -} - -void vmm_apic_mmio_read(vmm_vcpu_t *vcpu, void *cookie, uint32_t offset, - int len, uint32_t *data) -{ - vmm_lapic_t *apic = vcpu->lapic; - (void)cookie; - - apic_reg_read(apic, offset, len, data); - - apic_debug(6, "lapic mmio read on vcpu %d, reg %08x = %08x\n", vcpu->vcpu_id, offset, *data); - - return; -} - -void vmm_free_lapic(vmm_vcpu_t *vcpu) -{ - vmm_lapic_t *apic = vcpu->lapic; - - if (!apic) - return; - - if (apic->regs) { - free(apic->regs); - } - - free(apic); -} - -void vmm_lapic_set_base_msr(vmm_vcpu_t *vcpu, uint32_t value) -{ - apic_debug(2, "IA32_APIC_BASE MSR set to %08x on vcpu %d\n", value, vcpu->vcpu_id); - - if (!(value & MSR_IA32_APICBASE_ENABLE)) { - printf("Warning! Local apic has been disabled by MSR on vcpu %d. " - "This will probably not work!\n", vcpu->vcpu_id); - } - - vcpu->lapic->apic_base = value; -} - -uint32_t vmm_lapic_get_base_msr(vmm_vcpu_t *vcpu) -{ - uint32_t value = vcpu->lapic->apic_base; - - if (vmm_vcpu_is_bsp(vcpu)) { - value |= MSR_IA32_APICBASE_BSP; - } else { - value &= ~MSR_IA32_APICBASE_BSP; - } - - apic_debug(2, "Read from IA32_APIC_BASE MSR returns %08x on vcpu %d\n", value, vcpu->vcpu_id); - - return value; -} - -void vmm_lapic_reset(vmm_vcpu_t *vcpu) -{ - vmm_lapic_t *apic; - int i; - - apic_debug(4, "%s\n", __func__); - - assert(vcpu); - apic = vcpu->lapic; - assert(apic != NULL); - - /* Stop the timer in case it's a reset to an active apic */ - - vmm_apic_set_id(apic, vcpu->vcpu_id); /* In agreement with ACPI code */ - apic_set_reg(apic, APIC_LVR, APIC_VERSION); - - for (i = 0; i < APIC_LVT_NUM; i++) - apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); - - apic_set_reg(apic, APIC_DFR, 0xffffffffU); - apic_set_spiv(apic, 0xff); - apic_set_reg(apic, APIC_TASKPRI, 0); - vmm_apic_set_ldr(apic, 0); - apic_set_reg(apic, APIC_ESR, 0); - apic_set_reg(apic, APIC_ICR, 0); - apic_set_reg(apic, APIC_ICR2, 0); - apic_set_reg(apic, APIC_TDCR, 0); - apic_set_reg(apic, APIC_TMICT, 0); - for (i = 0; i < 8; i++) { - apic_set_reg(apic, APIC_IRR + 0x10 * i, 0); - apic_set_reg(apic, APIC_ISR + 0x10 * i, 0); - apic_set_reg(apic, APIC_TMR + 0x10 * i, 0); - } - apic->irr_pending = 0; - apic->isr_count = 0; - apic->highest_isr_cache = -1; - apic_update_ppr(vcpu); - - vcpu->lapic->arb_prio = 0; - - apic_debug(4, "%s: vcpu=%p, id=%d, base_msr=" - "0x%016x\n", __func__, - vcpu, vmm_apic_id(apic), - apic->apic_base); - - if (vcpu->vcpu_id == BOOT_VCPU) { - /* Bootstrap boot vcpu lapic in virtual wire mode */ - apic_set_reg(apic, APIC_LVT0, - SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); - apic_set_reg(apic, APIC_SPIV, APIC_SPIV_APIC_ENABLED); - - assert(vmm_apic_sw_enabled(apic)); - } else { - apic_set_reg(apic, APIC_SPIV, 0); - } -} - -int vmm_create_lapic(vmm_vcpu_t *vcpu, int enabled) -{ - vmm_lapic_t *apic; - - assert(vcpu != NULL); - apic_debug(2, "apic_init %d\n", vcpu->vcpu_id); - - apic = malloc(sizeof(*apic)); - if (!apic) - goto nomem; - - vcpu->lapic = apic; - - apic->regs = malloc(sizeof(struct local_apic_regs)); // TODO this is a page; allocate a page - if (!apic->regs) { - printf("malloc apic regs error for vcpu %x\n", - vcpu->vcpu_id); - goto nomem_free_apic; - } - - if (enabled) { - vmm_lapic_set_base_msr(vcpu, APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE); - } else { - vmm_lapic_set_base_msr(vcpu, APIC_DEFAULT_PHYS_BASE); - } - - /* mainly init registers */ - vmm_lapic_reset(vcpu); - - return 0; -nomem_free_apic: - free(apic); -nomem: - return -1; -} - -/* Return 1 if this vcpu should accept a PIC interrupt */ -int vmm_apic_accept_pic_intr(vmm_vcpu_t *vcpu) -{ - vmm_lapic_t *apic = vcpu->lapic; - uint32_t lvt0 = vmm_apic_get_reg(apic, APIC_LVT0); - - return ((lvt0 & APIC_LVT_MASKED) == 0 && - GET_APIC_DELIVERY_MODE(lvt0) == APIC_MODE_EXTINT && - vmm_apic_sw_enabled(vcpu->lapic)); -} - -/* Service an interrupt */ -int vmm_apic_get_interrupt(vmm_vcpu_t *vcpu) -{ - vmm_lapic_t *apic = vcpu->lapic; - int vector = vmm_apic_has_interrupt(vcpu); - - if (vector == 1) { - return pic_get_interrupt(vcpu->vmm); - } else if (vector == -1) { - return -1; - } - - apic_set_isr(vector, apic); - apic_update_ppr(vcpu); - apic_clear_irr(vector, apic); - return vector; -} - -/* Return which vector is next up for servicing */ -int vmm_apic_has_interrupt(vmm_vcpu_t *vcpu) -{ - vmm_lapic_t *apic = vcpu->lapic; - int highest_irr; - - if (vmm_apic_accept_pic_intr(vcpu) && pic_has_interrupt(vcpu->vmm)) { - return 1; - } - - highest_irr = apic_find_highest_irr(apic); - if ((highest_irr == -1) || - ((highest_irr & 0xF0) <= vmm_apic_get_reg(apic, APIC_PROCPRI))) { - return -1; - } - - return highest_irr; -} - -#if 0 -int vmm_apic_local_deliver(vmm_vcpu_t *vcpu, int lvt_type) -{ - vmm_lapic_t *apic = vcpu->lapic; - uint32_t reg = vmm_apic_get_reg(apic, lvt_type); - int vector, mode, trig_mode; - - if (!(reg & APIC_LVT_MASKED)) { - vector = reg & APIC_VECTOR_MASK; - mode = reg & APIC_MODE_MASK; - trig_mode = reg & APIC_LVT_LEVEL_TRIGGER; - return __apic_accept_irq(vcpu, mode, vector, 1, trig_mode, NULL); - } - return 0; -} -#endif
diff --git a/libsel4vmm/src/processor/msr.c b/libsel4vmm/src/processor/msr.c deleted file mode 100644 index 235732e..0000000 --- a/libsel4vmm/src/processor/msr.c +++ /dev/null
@@ -1,126 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/*handling msr read & write exceptions*/ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/debug.h" -#include "vmm/vmm.h" -#include "vmm/processor/msr.h" - -int vmm_rdmsr_handler(vmm_vcpu_t *vcpu) { - - int ret = 0; - unsigned int msr_no = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX); - uint64_t data = 0; - - DPRINTF(4, "rdmsr ecx 0x%x\n", msr_no); - - // src reference: Linux kernel 3.11 kvm arch/x86/kvm/x86.c - switch (msr_no) { - case MSR_IA32_PLATFORM_ID: - case MSR_IA32_EBL_CR_POWERON: - case MSR_IA32_DEBUGCTLMSR: - case MSR_IA32_LASTBRANCHFROMIP: - case MSR_IA32_LASTBRANCHTOIP: - case MSR_IA32_LASTINTFROMIP: - case MSR_IA32_LASTINTTOIP: - case MSR_IA32_MISC_ENABLE: - data = 0; - break; - - case MSR_IA32_UCODE_REV: - data = 0x100000000ULL; - break; - - case MSR_P6_PERFCTR0: - case MSR_P6_PERFCTR1: - case MSR_P6_EVNTSEL0: - case MSR_P6_EVNTSEL1: - case MSR_IA32_PERF_GLOBAL_STATUS_SET: - /* performance counters not supported. */ - data = 0; - break; - - case 0xcd: /* fsb frequency */ - data = 3; - break; - - case MSR_EBC_FREQUENCY_ID: - data = 1 << 24; - break; - - case MSR_IA32_APICBASE: - data = vmm_lapic_get_base_msr(vcpu); - break; - - default: - DPRINTF(1, "rdmsr WARNING unsupported msr_no 0x%x\n", msr_no); - // generate a GP fault - vmm_inject_exception(vcpu, 13, 1, 0); - return 0; - - } - - if (!ret) { - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EAX, (uint32_t)(data & 0xffffffff)); - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EDX, (uint32_t)(data >> 32)); - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - } - - return ret; -} - -int vmm_wrmsr_handler(vmm_vcpu_t *vcpu) { - - int ret = 0; - - unsigned int msr_no = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX); - unsigned int val_high = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EDX); - unsigned int val_low = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); - - DPRINTF(4, "wrmsr ecx 0x%x value: 0x%x 0x%x\n", msr_no, val_high, val_low); - - // src reference: Linux kernel 3.11 kvm arch/x86/kvm/x86.c - switch (msr_no) { - case MSR_IA32_UCODE_REV: - case MSR_IA32_UCODE_WRITE: - break; - - case MSR_P6_PERFCTR0: - case MSR_P6_PERFCTR1: - case MSR_P6_EVNTSEL0: - case MSR_P6_EVNTSEL1: - case MSR_IA32_PERF_GLOBAL_STATUS_SET: - /* performance counters not supported. */ - break; - - case MSR_IA32_APICBASE: - vmm_lapic_set_base_msr(vcpu, val_low); - break; - - default: - DPRINTF(1, "wrmsr WARNING unsupported msr_no 0x%x\n", msr_no); - // generate a GP fault - vmm_inject_exception(vcpu, 13, 1, 0); - return 0; - } - - if (!ret) - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - - return ret; -}
diff --git a/libsel4vmm/src/vmm/debug.c b/libsel4vmm/src/vmm/debug.c deleted file mode 100644 index addc189..0000000 --- a/libsel4vmm/src/vmm/debug.c +++ /dev/null
@@ -1,46 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* Debugging helper functions used by VMM lib. - * Authors: - * Qian Ge - */ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/debug.h" - -/* Print out the context of a guest OS thread. */ -void vmm_print_guest_context(int level, vmm_vcpu_t *vcpu) { - DPRINTF(level, "================== GUEST OS CONTEXT =================\n"); - - DPRINTF(level, "exit info : reason 0x%x qualification 0x%x instruction len 0x%x interrupt info 0x%x interrupt error 0x%x\n", - vmm_guest_exit_get_reason(&vcpu->guest_state), vmm_guest_exit_get_qualification(&vcpu->guest_state), vmm_guest_exit_get_int_len(&vcpu->guest_state), vmm_vmcs_read(vcpu->guest_vcpu, VMX_DATA_EXIT_INTERRUPT_INFO), vmm_vmcs_read(vcpu->guest_vcpu, VMX_DATA_EXIT_INTERRUPT_ERROR)); - DPRINTF(level, " guest physical 0x%x rflags 0x%x \n", - vmm_guest_exit_get_physical(&vcpu->guest_state), vmm_guest_state_get_rflags(&vcpu->guest_state, vcpu->guest_vcpu)); - DPRINTF(level, " guest interruptibility 0x%x control entry 0x%x\n", - vmm_guest_state_get_interruptibility(&vcpu->guest_state, vcpu->guest_vcpu), vmm_guest_state_get_control_entry(&vcpu->guest_state)); - - DPRINTF(level, "eip 0x%8x\n", - vmm_guest_state_get_eip(&vcpu->guest_state)); - DPRINTF(level, "eax 0x%8x ebx 0x%8x ecx 0x%8x\n", - vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX), vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EBX), vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX)); - DPRINTF(level, "edx 0x%8x esi 0x%8x edi 0x%8x\n", - vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EDX), vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ESI), vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EDI)); - DPRINTF(level, "ebp 0x%8x\n", - vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EBP)); - - DPRINTF(level, "cr0 0x%x cr3 0x%x cr4 0x%x\n", vmm_guest_state_get_cr0(&vcpu->guest_state, vcpu->guest_vcpu), vmm_guest_state_get_cr3(&vcpu->guest_state, vcpu->guest_vcpu), vmm_guest_state_get_cr4(&vcpu->guest_state, vcpu->guest_vcpu)); -}
diff --git a/libsel4vmm/src/vmm/ept.c b/libsel4vmm/src/vmm/ept.c deleted file mode 100644 index d5840aa..0000000 --- a/libsel4vmm/src/vmm/ept.c +++ /dev/null
@@ -1,53 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/*vm exits related with ept violations*/ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/debug.h" -#include "vmm/vmm.h" -#include "vmm/platform/vmcs.h" -#include "vmm/mmio.h" - -/* Handling EPT violation VMExit Events. */ -int vmm_ept_violation_handler(vmm_vcpu_t *vcpu) { - - uintptr_t guest_phys = vmm_guest_exit_get_physical(&vcpu->guest_state); - unsigned int qualification = vmm_guest_exit_get_qualification(&vcpu->guest_state); - - int e = vmm_mmio_exit_handler(vcpu, guest_phys, qualification); - - if (e == 0) { - DPRINTF(5, "EPT violation handled by mmio\n"); - } else { - /* Read linear address that guest is trying to access. */ - unsigned int linear_address = vmm_vmcs_read(vcpu->guest_vcpu, VMX_DATA_GUEST_LINEAR_ADDRESS); - printf(COLOUR_R "!!!!!!!! ALERT :: GUEST OS PAGE FAULT !!!!!!!!\n"); - printf(" Guest OS VMExit due to EPT Violation:\n"); - printf(" Linear address 0x%x.\n", linear_address); - printf(" Guest-Physical address 0x%x.\n", vmm_guest_exit_get_physical(&vcpu->guest_state)); - printf(" Instruction pointer 0x%x.\n", vmm_guest_state_get_eip(&vcpu->guest_state)); - printf(" This is most likely due to a bug or misconfiguration.\n" COLOUR_RESET); - } - -#ifndef CONFIG_VMM_IGNORE_EPT_VIOLATION - printf(COLOUR_R " The faulting Guest OS thread will now be blocked forever.\n" COLOUR_RESET); - return -1; -#else - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - return 0; -#endif -}
diff --git a/libsel4vmm/src/vmm/halt.c b/libsel4vmm/src/vmm/halt.c deleted file mode 100644 index 5f5c9fa..0000000 --- a/libsel4vmm/src/vmm/halt.c +++ /dev/null
@@ -1,35 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/*vm exits related with hlt'ing*/ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/vmm.h" - -/* Handling halt instruction VMExit Events. */ -int vmm_hlt_handler(vmm_vcpu_t *vcpu) { - if (!(vmm_guest_state_get_rflags(&vcpu->guest_state, vcpu->guest_vcpu) & BIT(9))) { - printf("vcpu %d is halted forever :(\n", vcpu->vcpu_id); - } - - if (vmm_apic_has_interrupt(vcpu) == -1) { - /* Halted, don't reply until we get an interrupt */ - vcpu->guest_state.virt.interrupt_halt = 1; - } - - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - return 0; -}
diff --git a/libsel4vmm/src/vmm/interrupt.c b/libsel4vmm/src/vmm/interrupt.c deleted file mode 100644 index 8d74f75..0000000 --- a/libsel4vmm/src/vmm/interrupt.c +++ /dev/null
@@ -1,172 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* vm exits and general handling of interrupt injection */ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/debug.h" -#include "vmm/vmm.h" -#include "vmm/processor/decode.h" - -#define TRAMPOLINE_LENGTH (100) - -static void resume_guest(vmm_vcpu_t *vcpu) { - /* Disable exit-for-interrupt in guest state to allow the guest to resume. */ - uint32_t state = vmm_guest_state_get_control_ppc(&vcpu->guest_state); - state &= ~BIT(2); /* clear the exit for interrupt flag */ - vmm_guest_state_set_control_ppc(&vcpu->guest_state, state); -} - -static void inject_irq(vmm_vcpu_t *vcpu, int irq) { - /* Inject a vectored exception into the guest */ - assert(irq >= 16); - vmm_guest_state_set_control_entry(&vcpu->guest_state, BIT(31) | irq); -} - -void vmm_inject_exception(vmm_vcpu_t *vcpu, int exception, int has_error, uint32_t error_code) { - assert(exception < 16); - // ensure we are not already injecting an interrupt or exception - uint32_t int_control = vmm_guest_state_get_control_entry(&vcpu->guest_state); - if ( (int_control & BIT(31)) != 0) { - ZF_LOGF("Cannot inject exception"); - } - if (has_error) { - vmm_guest_state_set_entry_exception_error_code(&vcpu->guest_state, error_code); - } - vmm_guest_state_set_control_entry(&vcpu->guest_state, BIT(31) | exception | 3 << 8 | (has_error ? BIT(11) : 0)); -} - -void wait_for_guest_ready(vmm_vcpu_t *vcpu) { - /* Request that the guest exit at the earliest point that we can inject an interrupt. */ - uint32_t state = vmm_guest_state_get_control_ppc(&vcpu->guest_state); - state |= BIT(2); /* set the exit for interrupt flag */ - vmm_guest_state_set_control_ppc(&vcpu->guest_state, state); -} - -int can_inject(vmm_vcpu_t *vcpu) { - uint32_t rflags = vmm_guest_state_get_rflags(&vcpu->guest_state, vcpu->guest_vcpu); - uint32_t guest_int = vmm_guest_state_get_interruptibility(&vcpu->guest_state, vcpu->guest_vcpu); - uint32_t int_control = vmm_guest_state_get_control_entry(&vcpu->guest_state); - - /* we can only inject if the interrupt mask flag is not set in flags, - guest is not in an uninterruptable state and we are not already trying to - inject an interrupt */ - - if ( (rflags & BIT(9)) && (guest_int & 0xF) == 0 && (int_control & BIT(31)) == 0) { - return 1; - } - return 0; -} - -/* This function is called by the local apic when a new interrupt has occured. */ -void vmm_have_pending_interrupt(vmm_vcpu_t *vcpu) { - if (vmm_apic_has_interrupt(vcpu) >= 0) { - /* there is actually an interrupt to inject */ - if (can_inject(vcpu)) { - if (vcpu->guest_state.virt.interrupt_halt) { - /* currently halted. need to put the guest - * in a state where it can inject again */ - wait_for_guest_ready(vcpu); - vcpu->guest_state.virt.interrupt_halt = 0; - vmm_sync_guest_state(vcpu); - vmm_reply_vm_exit(vcpu); /* unblock the guest */ - } else { - int irq = vmm_apic_get_interrupt(vcpu); - inject_irq(vcpu, irq); - /* see if there are more */ - if (vmm_apic_has_interrupt(vcpu) >= 0) { - wait_for_guest_ready(vcpu); - } - } - } else { - wait_for_guest_ready(vcpu); - if (vcpu->guest_state.virt.interrupt_halt) { - vcpu->guest_state.virt.interrupt_halt = 0; - vmm_sync_guest_state(vcpu); - vmm_reply_vm_exit(vcpu); /* unblock the guest */ - } - } - } -} - -int vmm_pending_interrupt_handler(vmm_vcpu_t *vcpu) { - /* see if there is actually a pending interrupt */ - assert(can_inject(vcpu)); - int irq = vmm_apic_get_interrupt(vcpu); - if (irq == -1) { - resume_guest(vcpu); - } else { - /* inject the interrupt */ - inject_irq(vcpu, irq); - if (!(vmm_apic_has_interrupt(vcpu) >= 0)) { - resume_guest(vcpu); - } - vcpu->guest_state.virt.interrupt_halt = 0; - } - return 0; -} - -/* Start an AP vcpu after a sipi with the requested vector */ -void vmm_start_ap_vcpu(vmm_vcpu_t *vcpu, unsigned int sipi_vector) -{ - DPRINTF(1, "trying to start vcpu %d\n", vcpu->vcpu_id); - - uint16_t segment = sipi_vector * 0x100; - uintptr_t eip = sipi_vector * 0x1000; - guest_state_t *gs = &vcpu->guest_state; - - /* Emulate up to 100 bytes of trampoline code */ - uint8_t instr[TRAMPOLINE_LENGTH]; - vmm_fetch_instruction(vcpu, eip, vmm_guest_state_get_cr3(gs, vcpu->guest_vcpu), - TRAMPOLINE_LENGTH, instr); - - eip = vmm_emulate_realmode(&vcpu->vmm->guest_mem, instr, &segment, eip, - TRAMPOLINE_LENGTH, gs); - - vmm_guest_state_set_eip(&vcpu->guest_state, eip); - - vmm_sync_guest_context(vcpu); - vmm_sync_guest_state(vcpu); - - assert(!"no tcb"); -// seL4_TCB_Resume(vcpu->guest_tcb); -} - -/* Got interrupt(s) from PIC, propagate to relevant vcpu lapic */ -void vmm_check_external_interrupt(vmm_t *vmm) -{ - /* TODO if all lapics are enabled, store which lapic - (only one allowed) receives extints, and short circuit this */ - if (vmm->plat_callbacks.has_interrupt() != -1) { - for (int i = 0; i < vmm->num_vcpus; i++) { - vmm_vcpu_t *vcpu = &vmm->vcpus[i]; - if (vmm_apic_accept_pic_intr(vcpu)) { - vmm_vcpu_accept_interrupt(vcpu); - break; /* Only one VCPU can take a PIC interrupt */ - } - } - } -} - -void vmm_vcpu_accept_interrupt(vmm_vcpu_t *vcpu) -{ - if (vmm_apic_has_interrupt(vcpu) == -1) { - return; - } - - /* in an exit, can call the regular injection method */ - vmm_have_pending_interrupt(vcpu); -}
diff --git a/libsel4vmm/src/vmm/io.c b/libsel4vmm/src/vmm/io.c deleted file mode 100644 index c9c005d..0000000 --- a/libsel4vmm/src/vmm/io.c +++ /dev/null
@@ -1,196 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/*vm exits related with io instructions*/ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> -#include <sel4utils/util.h> -#include <simple/simple.h> - -#include "vmm/debug.h" -#include "vmm/io.h" -#include "vmm/vmm.h" - -static int io_port_cmp(const void *pkey, const void *pelem) { - unsigned int key = (unsigned int)(uintptr_t)pkey; - const ioport_range_t *elem = (const ioport_range_t*)pelem; - if (key < elem->port_start) { - return -1; - } - if (key > elem->port_end) { - return 1; - } - return 0; -} - -static int io_port_cmp2(const void *a, const void *b) { - const ioport_range_t *aa = (const ioport_range_t*) a; - const ioport_range_t *bb = (const ioport_range_t*) b; - return aa->port_start - bb->port_start; -} - -static ioport_range_t *search_port(vmm_io_port_list_t *io_port, unsigned int port_no) { - return (ioport_range_t*)bsearch((void*)(uintptr_t)port_no, io_port->ioports, io_port->num_ioports, sizeof(ioport_range_t), io_port_cmp); -} - -/* Debug helper function for port no. */ -static const char* vmm_debug_io_portno_desc(vmm_io_port_list_t *io_port, int port_no) { - ioport_range_t *port = search_port(io_port, port_no); - return port ? port->desc : "Unknown IO Port"; -} - -/* IO instruction execution handler. */ -int vmm_io_instruction_handler(vmm_vcpu_t *vcpu) { - - unsigned int exit_qualification = vmm_guest_exit_get_qualification(&vcpu->guest_state); - unsigned int string, rep; - int ret; - unsigned int port_no; - unsigned int size; - unsigned int value; - int is_in; - - string = (exit_qualification & 16) != 0; - is_in = (exit_qualification & 8) != 0; - port_no = exit_qualification >> 16; - size = (exit_qualification & 7) + 1; - rep = (exit_qualification & 0x20) >> 5; - - DPRINTF(4, "vm exit io request: string %d in %d rep %d port no 0x%x (%s) size %d\n", string, - is_in, rep, port_no, vmm_debug_io_portno_desc(&vcpu->vmm->io_port, port_no), size); - - /*FIXME: does not support string and rep instructions*/ - if (string || rep) { - DPRINTF(0, "vm exit io request: FIXME: does not support string and rep instructions"); - DPRINTF(0, "vm exit io ERROR: string %d in %d rep %d port no 0x%x (%s) size %d\n", 0, - is_in, 0, port_no, vmm_debug_io_portno_desc(&vcpu->vmm->io_port, port_no), size); - return -1; - } - - ioport_range_t *port = search_port(&vcpu->vmm->io_port, port_no); - if (!port) { - static int last_port = -1; - if (last_port != port_no) { - DPRINTF(3, "vm exit io request: WARNING - ignoring unsupported ioport 0x%x (%s)\n", port_no, - vmm_debug_io_portno_desc(&vcpu->vmm->io_port, port_no)); - last_port = port_no; - } - if (is_in) { - uint32_t eax; - if ( size < 4) { - eax = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); - eax |= MASK(size * 8); - } else { - eax = -1; - } - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EAX, eax); - } - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - return 0; - } - - if (is_in) { - uint32_t eax; - ret = port->port_in(port->cookie, port_no, size, &value); - if (size < 4) { - eax = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); - eax &= ~MASK(size * 8); - eax |= value; - } else { - eax = value; - } - vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EAX, eax); - } else { - value = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); - if (size < 4) - value &= MASK(size * 8); - ret = port->port_out(port->cookie, port_no, size, value); - } - - if (ret) { - ZF_LOGE("vm exit io request: handler returned error."); - ZF_LOGE("vm exit io ERROR: string %d in %d rep %d port no 0x%x (%s) size %d", 0, - is_in, 0, port_no, vmm_debug_io_portno_desc(&vcpu->vmm->io_port, port_no), size); - return -1; - } - - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - - return 0; -} - -static int add_io_port_range(vmm_io_port_list_t *io_list, ioport_range_t port) { - /* ensure this range does not overlap */ - for (int i = 0; i < io_list->num_ioports; i++) { - if (io_list->ioports[i].port_end >= port.port_start && io_list->ioports[i].port_start <= port.port_end) { - ZF_LOGE("Requested ioport range 0x%x-0x%x for %s overlaps with existing range 0x%x-0x%x for %s", - port.port_start, port.port_end, port.desc ? port.desc : "Unknown IO Port", io_list->ioports[i].port_start, io_list->ioports[i].port_end, io_list->ioports[i].desc ? io_list->ioports[i].desc : "Unknown IO Port"); - return -1; - } - } - /* grow the array */ - io_list->ioports = realloc(io_list->ioports, sizeof(ioport_range_t) * (io_list->num_ioports + 1)); - assert(io_list->ioports); - /* add the new entry */ - io_list->ioports[io_list->num_ioports] = port; - io_list->num_ioports++; - /* sort */ - qsort(io_list->ioports, io_list->num_ioports, sizeof(ioport_range_t), io_port_cmp2); - return 0; -} - -int vmm_io_port_add_passthrough(vmm_io_port_list_t *io_list, uint16_t start, uint16_t end, const char *desc) { - return add_io_port_range(io_list, (ioport_range_t){start, end, 1, NULL, NULL, NULL, desc}); -} - -/* Add an io port range for emulation */ -int vmm_io_port_add_handler(vmm_io_port_list_t *io_list, uint16_t start, uint16_t end, void *cookie, ioport_in_fn port_in, ioport_out_fn port_out, const char *desc) { - return add_io_port_range(io_list, (ioport_range_t){start, end, 0, cookie, port_in, port_out, desc}); -} - -/*configure io ports for a guest*/ -int vmm_io_port_init_guest(vmm_io_port_list_t *io_list, simple_t *simple, seL4_CPtr vcpu, vka_t *vka) { - int UNUSED error; - - for (int i = 0; i < io_list->num_ioports; i++) { - ioport_range_t *port = &io_list->ioports[i]; - if (port->passthrough) { - DPRINTF(1, "vmm io port: setting %s IO port 0x%x - 0x%x to passthrough\n", port->desc, port->port_start, port->port_end); - cspacepath_t path; - int error; - error = vka_cspace_alloc_path(vka, &path); - if (error) { - ZF_LOGE("Failed to allocate slot"); - return error; - } - error = simple_get_IOPort_cap(simple, port->port_start, port->port_end, path.root, path.capPtr, path.capDepth); - if (error) { - ZF_LOGE("Failed to get \"%s\" io port from simple for range 0x%x - 0x%x", port->desc, port->port_start, port->port_end); - return error; - } - error = seL4_X86_VCPU_EnableIOPort(vcpu, path.capPtr, port->port_start, port->port_end); - assert(error == seL4_NoError); - } - } - - return 0; -} - -int vmm_io_port_init(vmm_io_port_list_t *io_list) { - io_list->num_ioports = 0; - io_list->ioports = malloc(0); - assert(io_list->ioports); - return 0; -}
diff --git a/libsel4vmm/src/vmm/mmio.c b/libsel4vmm/src/vmm/mmio.c deleted file mode 100644 index 1dde9e8..0000000 --- a/libsel4vmm/src/vmm/mmio.c +++ /dev/null
@@ -1,136 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -// Deals with ranges of memory mapped io - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <sel4/sel4.h> - -#include "vmm/debug.h" -#include "vmm/vmm.h" -#include "vmm/platform/vmcs.h" -#include "vmm/platform/vmexit.h" -#include "vmm/mmio.h" -#include "vmm/processor/decode.h" - -#define EPT_VIOL_READ(qual) ((qual) & BIT(0)) -#define EPT_VIOL_WRITE(qual) ((qual) & BIT(1)) -#define EPT_VIOL_FETCH(qual) ((qual) & BIT(2)) - -int vmm_mmio_init(vmm_mmio_list_t *list) { - list->num_ranges = 0; - list->ranges = malloc(0); - assert(list->ranges); - - return 0; -} - -// Returns 0 if the exit was handled -int vmm_mmio_exit_handler(vmm_vcpu_t *vcpu, uintptr_t addr, unsigned int qualification) { - int read = EPT_VIOL_READ(qualification); - int write = EPT_VIOL_WRITE(qualification); - int fetch = EPT_VIOL_FETCH(qualification); - if (read && write) { - // Indicates a fault while walking EPT - return -1; - } - if (fetch) { - // This is not MMIO - return -1; - } - - // Search the list - for (int i = 0; i < vcpu->vmm->mmio_list.num_ranges; i++) { - vmm_mmio_range_t *range = &vcpu->vmm->mmio_list.ranges[i]; - - if (addr < range->start) { - return -1; - } - - if (addr <= range->end) { - // Found a match - if (read && range->read_handler == NULL) { - return -1; - } - if (write && range->write_handler == NULL) { - return -1; - } - - // Decode instruction - uint8_t ibuf[15]; - int instr_len = vmm_guest_exit_get_int_len(&vcpu->guest_state); - vmm_fetch_instruction(vcpu, - vmm_guest_state_get_eip(&vcpu->guest_state), - vmm_guest_state_get_cr3(&vcpu->guest_state, vcpu->guest_vcpu), - instr_len, ibuf); - - int reg; - uint32_t imm; - int size; - vmm_decode_instruction(ibuf, instr_len, ®, &imm, &size); -assert(size == 4); // we don't support non-32 bit accesses. TODO fix this - - // Call handler - if (read) { - uint32_t result; - range->read_handler(vcpu, range->cookie, addr - range->start, size, &result); - - // Inject into register - assert(reg >= 0 && reg < 8); - int vcpu_reg = vmm_decoder_reg_mapw[reg]; - assert(vcpu_reg >= 0); - vmm_set_user_context(&vcpu->guest_state, - vcpu_reg, result); - } else { - // Get value to pass in - uint32_t value = imm; - assert (reg >= 0); - int vcpu_reg = vmm_decoder_reg_mapw[reg]; - assert(vcpu_reg >= 0); - value = vmm_read_user_context(&vcpu->guest_state, - vcpu_reg); - - range->write_handler(vcpu, range->cookie, addr - range->start, size, value); - } - - return 0; - } - } - - return -1; -} - -static int range_cmp(const void *a, const void *b) { - return ((const vmm_mmio_range_t *)a)->start - ((const vmm_mmio_range_t *)b)->start; -} - -int vmm_mmio_add_handler(vmm_mmio_list_t *list, uintptr_t start, uintptr_t end, - void *cookie, const char *name, - vmm_mmio_read_fn read_handler, vmm_mmio_write_fn write_handler) { - vmm_mmio_range_t *new = malloc(sizeof(*new)); - new->start = start; - new->end = end; - new->cookie = cookie; - new->read_handler = read_handler; - new->write_handler = write_handler; - new->name = name; - - list->ranges = realloc(list->ranges, sizeof(vmm_mmio_range_t) * (list->num_ranges + 1)); - memcpy(&list->ranges[list->num_ranges++], new, sizeof(vmm_mmio_range_t)); - - qsort(list->ranges, list->num_ranges, sizeof(vmm_mmio_range_t), range_cmp); - - return 0; -}
diff --git a/libsel4vmm/src/vmm/vchan_component.c b/libsel4vmm/src/vmm/vchan_component.c deleted file mode 100644 index 0121845..0000000 --- a/libsel4vmm/src/vmm/vchan_component.c +++ /dev/null
@@ -1,302 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include "vmm/vmm.h" -#include "vmm/vmm_manager.h" -#include "vmm/vchan_component.h" -#include "vmm/debug.h" -#include "vmm/vchan_sharemem.h" - -static libvchan_t *vchan_init(int domain, int port, int server); -static int libvchan_readwrite_action(libvchan_t *ctrl, void *data, size_t size, int stream, int action); - -static camkes_vchan_con_t *vchan_comp_con = NULL; - -/* - Set up the vchan connection interface - Currently, the number of vchan connection interfaces allowed is hardcoded to 1 per component -*/ -void init_camkes_vchan(camkes_vchan_con_t *c) { - vchan_comp_con = c; -} - -/* - Register a callback to be fired whenever a vchan event occurs -*/ -int vchan_set_callback(callback_func_t cb, void *data) { - vchan_comp_con->reg_callback(cb, data); - return 0; -} - -/* - Create a new vchan server instance -*/ -libvchan_t *libvchan_server_init(int domain, int port, size_t read_min, size_t write_min) { - return vchan_init(domain, port, 1); -} - -/* - Create a new vchan client instance -*/ -libvchan_t *libvchan_client_init(int domain, int port) { - return vchan_init(domain, port, 0); -} - -/* - Create a new client/server instance -*/ -libvchan_t *vchan_init(int domain, int port, int server) { - if(vchan_comp_con == NULL) { - return NULL; - } - - libvchan_t *new_connection = malloc(sizeof(libvchan_t)); - if(new_connection == NULL) { - return NULL; - } - - new_connection->is_server = server; - new_connection->server_persists = 1; - new_connection->blocking = 1; - new_connection->domain_num = domain; - new_connection->port_num = port; - new_connection->con = vchan_comp_con; - - /* Perform vchan component initialisation */ - vchan_connect_t t = { - .v.domain = vchan_comp_con->component_dom_num, - .v.dest = domain, - .v.port = port, - .server = new_connection->is_server, - }; - - if(vchan_comp_con->connect(t) < 0) { - free(new_connection); - return NULL; - } - - return new_connection; -} - -/* - Reading and writing to the vchan -*/ -int libvchan_write(libvchan_t *ctrl, const void *data, size_t size) { - return libvchan_readwrite_action(ctrl, (void *) data, size, 1, VCHAN_SEND); -} - -int libvchan_send(libvchan_t *ctrl, const void *data, size_t size) { - return libvchan_readwrite_action(ctrl, (void *) data, size, 1, VCHAN_SEND); -} - -int libvchan_read(libvchan_t *ctrl, void *data, size_t size) { - return libvchan_readwrite_action(ctrl, data, size, 1, VCHAN_RECV); -} - -int libvchan_recv(libvchan_t *ctrl, void *data, size_t size) { - return libvchan_readwrite_action(ctrl, data, size, 1, VCHAN_RECV); -} - -/* - Return correct buffer for given vchan read/write action -*/ -vchan_buf_t *get_vchan_buf(vchan_ctrl_t *args, camkes_vchan_con_t *c, int action) { - if(c->data_buf == NULL) { - ZF_LOGE("Mangled vchan connection: null data buffer\n"); - return NULL; - } - - int buf_pos = c->get_buf(*args, action); - /* Check that a buffer was retrieved */ - if(buf_pos < 0) { - return NULL; - } - - void *addr = c->data_buf; - addr += buf_pos; - vchan_buf_t *b = (vchan_buf_t *) (addr); - - return b; -} - -/* - Helper function - Allows connected components to get correct vchan buffer for read/write -*/ -vchan_buf_t *get_vchan_ctrl_databuf(libvchan_t *ctrl, int action) { - vchan_ctrl_t args = { - .domain = ctrl->con->component_dom_num, - .dest = ctrl->domain_num, - .port = ctrl->port_num, - }; - - return get_vchan_buf(&args, ctrl->con, action); -} - -/* - Perform a vchan read/write action into a given buffer - This function is intended for non Init components, Init components have a different method -*/ -int libvchan_readwrite_action(libvchan_t *ctrl, void *data, size_t size, int stream, int action) { - int *update; - vchan_buf_t *b = get_vchan_ctrl_databuf(ctrl, action); - if(b == NULL) { - return -1; - } - - /* - How data is stored in a given vchan buffer - - Position of data in buffer is given by - (either b->write_pos or b->read_pos) % VCHAN_BUF_SIZE - read_pos is incremented by x when x bytes are read from the buffer - write_pos is incremented by x when x bytes are read from the buffer - - Amount of bytes in buffer is given by the difference between read_pos and write_pos - if write_pos > read_pos, there is data yet to be read - */ - size_t filled = abs(b->write_pos - b->read_pos); - if(action == VCHAN_SEND) { - while(filled == VCHAN_BUF_SIZE) { - ctrl->con->wait(); - filled = abs(b->write_pos - b->read_pos); - } - - if(stream) { - size = MIN(VCHAN_BUF_SIZE - filled, size); - } else if(size > VCHAN_BUF_SIZE - filled) { - return -1; - } - - update = &b->write_pos; - } else { - while(filled == 0) { - ctrl->con->wait(); - filled = abs(b->write_pos - b->read_pos); - } - - if(stream) { - size = MIN(filled, size); - } else if(size > filled) { - return -1; - } - - update = &b->read_pos; - } - - /* - Because this buffer is circular, - data may have to wrap around to the start of the buffer - This is achieved by doing two copies, one to buffer end - And one at start of buffer for remaining data - - E.g if buffer size = 12 - and if write pos = 7 && number of bytes to write = 8 - - Start: - write_pos - V - [oooooooooooo] - End: - write_pos - V - [xxxooooxxxxx] - - */ - off_t start = (*update % VCHAN_BUF_SIZE); - off_t remain = 0; - - if(start + size > VCHAN_BUF_SIZE) { - remain = (start + size) - VCHAN_BUF_SIZE; - size -= remain; - } - - void *dbuf = &b->sync_data; - - if(action == VCHAN_SEND) { - memcpy(dbuf + start, data, size); - memcpy(dbuf, data + size, remain); - } else { - memcpy(data, ((void *) dbuf) + start, size); - memcpy(data + size, dbuf, remain); - } - __sync_synchronize(); - - /* - Update either the read byte counter or the written byte counter - With how much was written or read - */ - *update += (size + remain); - - ctrl->con->alert(); - - return (size + remain); -} - -/* - Wait for data to arrive to a component from a given vchan -*/ -int libvchan_wait(libvchan_t *ctrl) { - vchan_buf_t *b = get_vchan_ctrl_databuf(ctrl, VCHAN_RECV); - assert(b != NULL); - - size_t filled = abs(b->write_pos - b->read_pos); - while(filled == 0) { - ctrl->con->wait(); - b = get_vchan_ctrl_databuf(ctrl, VCHAN_RECV); - filled = abs(b->write_pos - b->read_pos); - } - - return 0; -} - -void libvchan_close(libvchan_t *ctrl) { - /* Perform vchan component initialisation */ - vchan_connect_t t = { - .v.domain = ctrl->con->component_dom_num, - .v.dest = ctrl->domain_num, - .v.port = ctrl->port_num, - .server = ctrl->is_server, - }; - - ctrl->con->disconnect(t); - free(ctrl); - ctrl = NULL; -} - -int libvchan_is_open(libvchan_t *ctrl) { - vchan_ctrl_t args = { - .domain = ctrl->con->component_dom_num, - .dest = ctrl->domain_num, - .port = ctrl->port_num, - }; - - return ctrl->con->status(args); -} - -/* - How much data can be read from the vchan -*/ -int libvchan_data_ready(libvchan_t *ctrl) { - vchan_buf_t *b = get_vchan_ctrl_databuf(ctrl, VCHAN_RECV); - size_t filled = abs(b->write_pos - b->read_pos); - return filled; -} - -/* - How much data can be written to the vchan -*/ -int libvchan_buffer_space(libvchan_t *ctrl) { - vchan_buf_t *b = get_vchan_ctrl_databuf(ctrl, VCHAN_SEND); - size_t filled = abs(b->write_pos - b->read_pos); - return VCHAN_BUF_SIZE - filled; -}
diff --git a/libsel4vmm/src/vmm/vmcall.c b/libsel4vmm/src/vmm/vmcall.c deleted file mode 100644 index aeb7b5e..0000000 --- a/libsel4vmm/src/vmm/vmcall.c +++ /dev/null
@@ -1,66 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include "vmm/vmm.h" -#include "vmm/debug.h" -#include "vmm/vmcall.h" - -static vmcall_handler_t *get_handle(vmm_t *vmm, int token); - -static vmcall_handler_t *get_handle(vmm_t *vmm, int token) { - int i; - for(i = 0; i < vmm->vmcall_num_handlers; i++) { - if(vmm->vmcall_handlers[i].token == token) { - return &vmm->vmcall_handlers[i]; - } - } - - return NULL; -} - -int reg_new_handler(vmm_t *vmm, vmcall_handler func, int token) { - unsigned int *hnum = &(vmm->vmcall_num_handlers); - if(get_handle(vmm, token) != NULL) { - return -1; - } - - vmm->vmcall_handlers = realloc(vmm->vmcall_handlers, sizeof(vmcall_handler_t) * (*hnum + 1)); - if(vmm->vmcall_handlers == NULL) { - return -1; - } - - vmm->vmcall_handlers[*hnum].func = func; - vmm->vmcall_handlers[*hnum].token = token; - vmm->vmcall_num_handlers++; - - DPRINTF(4, "Reg. handler %u for vmm, total = %u\n", *hnum - 1, *hnum); - return 0; -} - -int vmm_vmcall_handler(vmm_vcpu_t *vcpu) { - int res; - vmcall_handler_t *h; - int token = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); - h = get_handle(vcpu->vmm, token); - if(h == NULL) { - DPRINTF(2, "Failed to find handler for token:%x\n", token); - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - return 0; - } - - res = h->func(vcpu); - if(res == 0) { - vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); - } - - return res; -}
diff --git a/libsel4vmm/src/vmm/vmcs.c b/libsel4vmm/src/vmm/vmcs.c deleted file mode 100644 index a00c101..0000000 --- a/libsel4vmm/src/vmm/vmcs.c +++ /dev/null
@@ -1,98 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/vmm.h" -#include "vmm/platform/vmcs.h" - -int vmm_vmcs_read(seL4_CPtr vcpu, seL4_Word field) { - - seL4_X86_VCPU_ReadVMCS_t UNUSED result; - - assert(vcpu); - - result = seL4_X86_VCPU_ReadVMCS(vcpu, field); - assert(result.error == seL4_NoError); - return result.value; -} - -/*write a field and its value into the VMCS*/ -void vmm_vmcs_write(seL4_CPtr vcpu, seL4_Word field, seL4_Word value) { - - seL4_X86_VCPU_WriteVMCS_t UNUSED result; - assert(vcpu); - - result = seL4_X86_VCPU_WriteVMCS(vcpu, field, value); - assert(result.error == seL4_NoError); -} - -/*init the vmcs structure for a guest os thread*/ -void vmm_vmcs_init_guest(vmm_vcpu_t *vcpu) { - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_SELECTOR, 2 << 3); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_SELECTOR, BIT(3)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_SELECTOR, 2 << 3); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_SELECTOR, 2 << 3); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_SELECTOR, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_SELECTOR, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_SELECTOR, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_SELECTOR, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_LIMIT, ~0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_LIMIT, ~0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_LIMIT, ~0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_LIMIT, ~0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_LIMIT, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_LIMIT, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_LIMIT, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_LIMIT, 0x0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GDTR_LIMIT, 0x0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_IDTR_LIMIT, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_ACCESS_RIGHTS, 0xC093); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_ACCESS_RIGHTS, 0xC09B); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_ACCESS_RIGHTS, 0xC093); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_ACCESS_RIGHTS, 0xC093); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_ACCESS_RIGHTS, BIT(16)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_ACCESS_RIGHTS, BIT(16)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_ACCESS_RIGHTS, BIT(16)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_ACCESS_RIGHTS, 0x8B); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SYSENTER_CS, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR0_MASK, vcpu->guest_state.virt.cr.cr0_mask); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR4_MASK, vcpu->guest_state.virt.cr.cr4_mask); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR0_READ_SHADOW, vcpu->guest_state.virt.cr.cr0_shadow); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR4_READ_SHADOW, vcpu->guest_state.virt.cr.cr4_shadow); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GDTR_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_IDTR_BASE, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_RFLAGS, BIT(1)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SYSENTER_ESP, 0); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SYSENTER_EIP, 0); - vcpu->guest_state.machine.control_ppc = VMX_CONTROL_PPC_HLT_EXITING | VMX_CONTROL_PPC_CR3_LOAD_EXITING | VMX_CONTROL_PPC_CR3_STORE_EXITING; - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS, vcpu->guest_state.machine.control_ppc); - vcpu->guest_state.machine.control_entry = vmm_vmcs_read(vcpu->guest_vcpu, VMX_CONTROL_ENTRY_INTERRUPTION_INFO); - -#ifdef CONFIG_LIB_VMM_VMX_TIMER_DEBUG - /* Enable pre-emption timer */ - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_PIN_EXECUTION_CONTROLS, BIT(6)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_EXIT_CONTROLS, BIT(22)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_VMX_PREEMPTION_TIMER_VALUE, CONFIG_LIB_VMM_VMX_TIMER_TIMEOUT); -#endif -}
diff --git a/libsel4vmm/src/vmm/vmm.c b/libsel4vmm/src/vmm/vmm.c deleted file mode 100644 index 484d8b5..0000000 --- a/libsel4vmm/src/vmm/vmm.c +++ /dev/null
@@ -1,288 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/* Functions for VMM main host thread. - * - * Authors: - * Qian Ge - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <sel4/sel4.h> -#include <vka/capops.h> -#include <platsupport/arch/tsc.h> -#include <sel4/arch/vmenter.h> - -#include "vmm/debug.h" -#include "vmm/vmm.h" -#include "vmm/interrupt.h" -#include "vmm/platform/boot_guest.h" - -void vmm_sync_guest_context(vmm_vcpu_t *vcpu) { - if (IS_MACHINE_STATE_MODIFIED(vcpu->guest_state.machine.context)) { - seL4_VCPUContext context; - context.eax = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); - context.ebx = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EBX); - context.ecx = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX); - context.edx = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EDX); - context.esi = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ESI); - context.edi = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EDI); - context.ebp = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EBP); - seL4_X86_VCPU_WriteRegisters(vcpu->guest_vcpu, &context); - /* Sync our context */ - MACHINE_STATE_SYNC(vcpu->guest_state.machine.context); - } -} - -void vmm_reply_vm_exit(vmm_vcpu_t *vcpu) { - assert(vcpu->guest_state.exit.in_exit); - - if (IS_MACHINE_STATE_MODIFIED(vcpu->guest_state.machine.context)) { - vmm_sync_guest_context(vcpu); - } - - /* Before we resume the guest, ensure there is no dirty state around */ - assert(vmm_guest_state_no_modified(&vcpu->guest_state)); - vmm_guest_state_invalidate_all(&vcpu->guest_state); - - vcpu->guest_state.exit.in_exit = 0; -} - -void vmm_sync_guest_state(vmm_vcpu_t *vcpu) { - vmm_guest_state_sync_cr0(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_cr3(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_cr4(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_idt_base(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_idt_limit(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_gdt_base(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_gdt_limit(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_cs_selector(&vcpu->guest_state, vcpu->guest_vcpu); - vmm_guest_state_sync_entry_exception_error_code(&vcpu->guest_state, vcpu->guest_vcpu); -} - -/* Handle VM exit in VMM module. */ -static void vmm_handle_vm_exit(vmm_vcpu_t *vcpu) { - int reason = vmm_guest_exit_get_reason(&vcpu->guest_state); - - /* Distribute the task according to the exit info. */ - vmm_print_guest_context(3, vcpu); - - if (reason == -1) { - ZF_LOGF("Kernel failed to perform vmlaunch or vmresume, we have no recourse"); - } - - if (!vcpu->vmm->vmexit_handlers[reason]) { - printf("VM_FATAL_ERROR ::: vm exit handler is NULL for reason 0x%x.\n", reason); - vmm_print_guest_context(0, vcpu); - vcpu->online = 0; - return; - } - - /* Call the handler. */ - if (vcpu->vmm->vmexit_handlers[reason](vcpu)) { - printf("VM_FATAL_ERROR ::: vmexit handler return error\n"); - vmm_print_guest_context(0, vcpu); - vcpu->online = 0; - return; - } - - /* Reply to the VM exit exception to resume guest. */ - vmm_sync_guest_state(vcpu); - if (vcpu->guest_state.exit.in_exit && !vcpu->guest_state.virt.interrupt_halt) { - /* Guest is blocked, but we are no longer halted. Reply to it */ - vmm_reply_vm_exit(vcpu); - } -} - -static void vmm_update_guest_state_from_interrupt(vmm_vcpu_t *vcpu, seL4_Word *msg) { - vcpu->guest_state.machine.eip = msg[SEL4_VMENTER_CALL_EIP_MR]; - vcpu->guest_state.machine.control_ppc = msg[SEL4_VMENTER_CALL_CONTROL_PPC_MR]; - vcpu->guest_state.machine.control_entry = msg[SEL4_VMENTER_CALL_CONTROL_ENTRY_MR]; -} - -static void vmm_update_guest_state_from_fault(vmm_vcpu_t *vcpu, seL4_Word *msg) { - assert(vcpu->guest_state.exit.in_exit); - - /* The interrupt state is a subset of the fault state */ - vmm_update_guest_state_from_interrupt(vcpu, msg); - - vcpu->guest_state.exit.reason = msg[SEL4_VMENTER_FAULT_REASON_MR]; - vcpu->guest_state.exit.qualification = msg[SEL4_VMENTER_FAULT_QUALIFICATION_MR]; - vcpu->guest_state.exit.instruction_length = msg[SEL4_VMENTER_FAULT_INSTRUCTION_LEN_MR]; - vcpu->guest_state.exit.guest_physical = msg[SEL4_VMENTER_FAULT_GUEST_PHYSICAL_MR]; - - MACHINE_STATE_READ(vcpu->guest_state.machine.rflags, msg[SEL4_VMENTER_FAULT_RFLAGS_MR]); - MACHINE_STATE_READ(vcpu->guest_state.machine.guest_interruptibility, msg[SEL4_VMENTER_FAULT_GUEST_INT_MR]); - - MACHINE_STATE_READ(vcpu->guest_state.machine.cr3, msg[SEL4_VMENTER_FAULT_CR3_MR]); - - seL4_VCPUContext context; - context.eax = msg[SEL4_VMENTER_FAULT_EAX]; - context.ebx = msg[SEL4_VMENTER_FAULT_EBX]; - context.ecx = msg[SEL4_VMENTER_FAULT_ECX]; - context.edx = msg[SEL4_VMENTER_FAULT_EDX]; - context.esi = msg[SEL4_VMENTER_FAULT_ESI]; - context.edi = msg[SEL4_VMENTER_FAULT_EDI]; - context.ebp = msg[SEL4_VMENTER_FAULT_EBP]; - MACHINE_STATE_READ(vcpu->guest_state.machine.context, context); -} - -/* Entry point of of VMM main host module. */ -void vmm_run(vmm_t *vmm) { - int UNUSED error; - DPRINTF(2, "VMM MAIN HOST MODULE STARTED\n"); - - for (int i = 0; i < vmm->num_vcpus; i++) { - vmm_vcpu_t *vcpu = &vmm->vcpus[i]; - - vcpu->guest_state.virt.interrupt_halt = 0; - vcpu->guest_state.exit.in_exit = 0; - - /* sync the existing guest state */ - vmm_sync_guest_state(vcpu); - vmm_sync_guest_context(vcpu); - /* now invalidate everything */ - assert(vmm_guest_state_no_modified(&vcpu->guest_state)); - vmm_guest_state_invalidate_all(&vcpu->guest_state); - } - - /* Start the boot vcpu guest thread running */ - vmm->vcpus[BOOT_VCPU].online = 1; - - /* Get our interrupt pending callback happening */ - seL4_CPtr notification = vmm->plat_callbacks.get_async_event_notification(); - error = seL4_TCB_BindNotification(simple_get_init_cap(&vmm->host_simple, seL4_CapInitThreadTCB), vmm->plat_callbacks.get_async_event_notification()); - assert(error == seL4_NoError); - - while (1) { - /* Block and wait for incoming msg or VM exits. */ - seL4_Word badge; - int fault; - - vmm_vcpu_t *vcpu = &vmm->vcpus[BOOT_VCPU]; - - if (vcpu->online && !vcpu->guest_state.virt.interrupt_halt && !vcpu->guest_state.exit.in_exit) { - seL4_SetMR(0, vmm_guest_state_get_eip(&vcpu->guest_state)); - seL4_SetMR(1, vmm_guest_state_get_control_ppc(&vcpu->guest_state)); - seL4_SetMR(2, vmm_guest_state_get_control_entry(&vcpu->guest_state)); - fault = seL4_VMEnter(&badge); - - if (fault == SEL4_VMENTER_RESULT_FAULT) { - /* We in a fault */ - vcpu->guest_state.exit.in_exit = 1; - - /* Update the guest state from a fault */ - seL4_Word fault_message[SEL4_VMENTER_RESULT_FAULT_LEN]; - for (int i = 0 ; i < SEL4_VMENTER_RESULT_FAULT_LEN; i++) { - fault_message[i] = seL4_GetMR(i); - } - vmm_guest_state_invalidate_all(&vcpu->guest_state); - vmm_update_guest_state_from_fault(vcpu, fault_message); - } else { - /* update the guest state from a non fault */ - seL4_Word int_message[SEL4_VMENTER_RESULT_NOTIF_LEN]; - for (int i = 0 ; i < SEL4_VMENTER_RESULT_NOTIF_LEN; i++) { - int_message[i] = seL4_GetMR(i); - } - vmm_guest_state_invalidate_all(&vcpu->guest_state); - vmm_update_guest_state_from_interrupt(vcpu, int_message); - } - } else { - seL4_Wait(notification, &badge); - fault = SEL4_VMENTER_RESULT_NOTIF; - } - - if (fault == SEL4_VMENTER_RESULT_NOTIF) { - assert(badge >= vmm->num_vcpus); - /* assume interrupt */ - int raise = vmm->plat_callbacks.do_async(badge); - if (raise == 0) { - /* Check if this caused PIC to generate interrupt */ - vmm_check_external_interrupt(vmm); - } - - continue; - } - - /* Handle the vm exit */ - vmm_handle_vm_exit(vcpu); - - vmm_check_external_interrupt(vmm); - - DPRINTF(5, "VMM main host blocking for another message...\n"); - } - -} - -static void vmm_exit_init(vmm_t *vmm) { - /* Connect VM exit handlers to correct function pointers */ - vmm->vmexit_handlers[EXIT_REASON_PENDING_INTERRUPT] = vmm_pending_interrupt_handler; - //vmm->vmexit_handlers[EXIT_REASON_EXCEPTION_NMI] = vmm_exception_handler; - vmm->vmexit_handlers[EXIT_REASON_CPUID] = vmm_cpuid_handler; - vmm->vmexit_handlers[EXIT_REASON_MSR_READ] = vmm_rdmsr_handler; - vmm->vmexit_handlers[EXIT_REASON_MSR_WRITE] = vmm_wrmsr_handler; - vmm->vmexit_handlers[EXIT_REASON_EPT_VIOLATION] = vmm_ept_violation_handler; - vmm->vmexit_handlers[EXIT_REASON_CR_ACCESS] = vmm_cr_access_handler; - vmm->vmexit_handlers[EXIT_REASON_IO_INSTRUCTION] = vmm_io_instruction_handler; -/* vmm->vmexit_handlers[EXIT_REASON_RDTSC] = vmm_rdtsc_instruction_handler;*/ - vmm->vmexit_handlers[EXIT_REASON_HLT] = vmm_hlt_handler; - vmm->vmexit_handlers[EXIT_REASON_VMX_TIMER] = vmm_vmx_timer_handler; - vmm->vmexit_handlers[EXIT_REASON_VMCALL] = vmm_vmcall_handler; -} - -int vmm_finalize(vmm_t *vmm) { - int err; - vmm_exit_init(vmm); - - for (int i = 0; i < vmm->num_vcpus; i++) { - vmm_vcpu_t *vcpu = &vmm->vcpus[i]; - - vmm_init_guest_thread_state(vcpu); - err = vmm_io_port_init_guest(&vmm->io_port, &vmm->host_simple, vcpu->guest_vcpu, &vmm->vka); - if (err) { - return err; - } - } - return 0; -} - -seL4_CPtr vmm_create_async_event_notification_cap(vmm_t *vmm, seL4_Word badge) { - - if (!(badge & BIT(27))) { - ZF_LOGE("Invalid badge"); - return seL4_CapNull; - } - - // notification cap - seL4_CPtr ntfn = vmm->plat_callbacks.get_async_event_notification(); - - // path to notification cap slot - cspacepath_t ntfn_path; - vka_cspace_make_path(&vmm->vka, ntfn, &ntfn_path); - - // allocate slot to store copy - cspacepath_t minted_ntfn_path = {}; - vka_cspace_alloc_path(&vmm->vka, &minted_ntfn_path); - - // mint the notification cap - int error = vka_cnode_mint(&minted_ntfn_path, &ntfn_path, seL4_AllRights, badge); - - if (error != seL4_NoError) { - ZF_LOGE("Failed to mint notification cap"); - return seL4_CapNull; - } - - return minted_ntfn_path.capPtr; -}
diff --git a/libsel4vmm/src/vmm/vmx_timer.c b/libsel4vmm/src/vmm/vmx_timer.c deleted file mode 100644 index 422e38c..0000000 --- a/libsel4vmm/src/vmm/vmx_timer.c +++ /dev/null
@@ -1,35 +0,0 @@ -/* - * Copyright 2017, Data61 - * Commonwealth Scientific and Industrial Research Organisation (CSIRO) - * ABN 41 687 119 230. - * - * This software may be distributed and modified according to the terms of - * the GNU General Public License version 2. Note that NO WARRANTY is provided. - * See "LICENSE_GPLv2.txt" for details. - * - * @TAG(DATA61_GPL) - */ - -/*vm exits related with vmx timer*/ - -#include <autoconf.h> -#include <sel4vmm/gen_config.h> -#include <stdio.h> -#include <stdlib.h> - -#include <sel4/sel4.h> - -#include "vmm/vmm.h" -#include "vmm/platform/vmcs.h" - -int vmm_vmx_timer_handler(vmm_vcpu_t *vcpu) -{ -#ifdef CONFIG_LIB_VMM_VMX_TIMER_DEBUG - vmm_print_guest_context(0, vcpu); -// vmm_vmcs_write(vmm->guest_vcpu, VMX_CONTROL_PIN_EXECUTION_CONTROLS, vmm_vmcs_read(vmm->guest_vcpu, VMX_CONTROL_PIN_EXECUTION_CONTROLS) | BIT(6)); - vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_VMX_PREEMPTION_TIMER_VALUE, CONFIG_LIB_VMM_VMX_TIMER_TIMEOUT); - return 0; -#else - return -1; -#endif -}