vm.cc revision 9651
19651SAndreas.Sandberg@ARM.com/* 29651SAndreas.Sandberg@ARM.com * Copyright (c) 2012 ARM Limited 39651SAndreas.Sandberg@ARM.com * All rights reserved 49651SAndreas.Sandberg@ARM.com * 59651SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 69651SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 79651SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 89651SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 99651SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 109651SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 119651SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 129651SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 139651SAndreas.Sandberg@ARM.com * 149651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 159651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 169651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 179651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 189651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 199651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 209651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 219651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 229651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 239651SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 249651SAndreas.Sandberg@ARM.com * 259651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 269651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 279651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 289651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 299651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 309651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 319651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 329651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 339651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 349651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 359651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 369651SAndreas.Sandberg@ARM.com * 379651SAndreas.Sandberg@ARM.com * Authors: Andreas Sandberg 389651SAndreas.Sandberg@ARM.com */ 399651SAndreas.Sandberg@ARM.com 409651SAndreas.Sandberg@ARM.com#include <linux/kvm.h> 419651SAndreas.Sandberg@ARM.com#include <sys/ioctl.h> 429651SAndreas.Sandberg@ARM.com#include <sys/stat.h> 439651SAndreas.Sandberg@ARM.com#include <sys/types.h> 449651SAndreas.Sandberg@ARM.com#include <fcntl.h> 459651SAndreas.Sandberg@ARM.com#include <unistd.h> 469651SAndreas.Sandberg@ARM.com 479651SAndreas.Sandberg@ARM.com#include <cerrno> 489651SAndreas.Sandberg@ARM.com 499651SAndreas.Sandberg@ARM.com#include "cpu/kvm/vm.hh" 509651SAndreas.Sandberg@ARM.com#include "debug/Kvm.hh" 519651SAndreas.Sandberg@ARM.com#include "params/KvmVM.hh" 529651SAndreas.Sandberg@ARM.com#include "sim/system.hh" 539651SAndreas.Sandberg@ARM.com 549651SAndreas.Sandberg@ARM.com#define EXPECTED_KVM_API_VERSION 12 559651SAndreas.Sandberg@ARM.com 569651SAndreas.Sandberg@ARM.com#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION 579651SAndreas.Sandberg@ARM.com#error Unsupported KVM version 589651SAndreas.Sandberg@ARM.com#endif 599651SAndreas.Sandberg@ARM.com 609651SAndreas.Sandberg@ARM.comKvm *Kvm::instance = NULL; 619651SAndreas.Sandberg@ARM.com 629651SAndreas.Sandberg@ARM.comKvm::Kvm() 639651SAndreas.Sandberg@ARM.com : kvmFD(-1), apiVersion(-1), vcpuMMapSize(0) 649651SAndreas.Sandberg@ARM.com{ 659651SAndreas.Sandberg@ARM.com kvmFD = ::open("/dev/kvm", O_RDWR); 669651SAndreas.Sandberg@ARM.com if (kvmFD == -1) 679651SAndreas.Sandberg@ARM.com fatal("KVM: Failed to open /dev/kvm\n"); 689651SAndreas.Sandberg@ARM.com 699651SAndreas.Sandberg@ARM.com apiVersion = ioctl(KVM_GET_API_VERSION); 709651SAndreas.Sandberg@ARM.com if (apiVersion != EXPECTED_KVM_API_VERSION) 719651SAndreas.Sandberg@ARM.com fatal("KVM: Incompatible API version\n"); 729651SAndreas.Sandberg@ARM.com 739651SAndreas.Sandberg@ARM.com vcpuMMapSize = ioctl(KVM_GET_VCPU_MMAP_SIZE); 749651SAndreas.Sandberg@ARM.com if (vcpuMMapSize == -1) 759651SAndreas.Sandberg@ARM.com panic("KVM: Failed to get virtual CPU MMAP size\n"); 769651SAndreas.Sandberg@ARM.com} 779651SAndreas.Sandberg@ARM.com 789651SAndreas.Sandberg@ARM.comKvm::~Kvm() 799651SAndreas.Sandberg@ARM.com{ 809651SAndreas.Sandberg@ARM.com close(kvmFD); 819651SAndreas.Sandberg@ARM.com} 829651SAndreas.Sandberg@ARM.com 839651SAndreas.Sandberg@ARM.comKvm * 849651SAndreas.Sandberg@ARM.comKvm::create() 859651SAndreas.Sandberg@ARM.com{ 869651SAndreas.Sandberg@ARM.com if (!instance) 879651SAndreas.Sandberg@ARM.com instance = new Kvm(); 889651SAndreas.Sandberg@ARM.com 899651SAndreas.Sandberg@ARM.com return instance; 909651SAndreas.Sandberg@ARM.com} 919651SAndreas.Sandberg@ARM.com 929651SAndreas.Sandberg@ARM.combool 939651SAndreas.Sandberg@ARM.comKvm::capUserMemory() const 949651SAndreas.Sandberg@ARM.com{ 959651SAndreas.Sandberg@ARM.com return checkExtension(KVM_CAP_USER_MEMORY) != 0; 969651SAndreas.Sandberg@ARM.com} 979651SAndreas.Sandberg@ARM.com 989651SAndreas.Sandberg@ARM.combool 999651SAndreas.Sandberg@ARM.comKvm::capSetTSSAddress() const 1009651SAndreas.Sandberg@ARM.com{ 1019651SAndreas.Sandberg@ARM.com return checkExtension(KVM_CAP_SET_TSS_ADDR) != 0; 1029651SAndreas.Sandberg@ARM.com} 1039651SAndreas.Sandberg@ARM.com 1049651SAndreas.Sandberg@ARM.combool 1059651SAndreas.Sandberg@ARM.comKvm::capExtendedCPUID() const 1069651SAndreas.Sandberg@ARM.com{ 1079651SAndreas.Sandberg@ARM.com return checkExtension(KVM_CAP_EXT_CPUID) != 0; 1089651SAndreas.Sandberg@ARM.com} 1099651SAndreas.Sandberg@ARM.com 1109651SAndreas.Sandberg@ARM.combool 1119651SAndreas.Sandberg@ARM.comKvm::capUserNMI() const 1129651SAndreas.Sandberg@ARM.com{ 1139651SAndreas.Sandberg@ARM.com#ifdef KVM_CAP_USER_NMI 1149651SAndreas.Sandberg@ARM.com return checkExtension(KVM_CAP_USER_NMI) != 0; 1159651SAndreas.Sandberg@ARM.com#else 1169651SAndreas.Sandberg@ARM.com return false; 1179651SAndreas.Sandberg@ARM.com#endif 1189651SAndreas.Sandberg@ARM.com} 1199651SAndreas.Sandberg@ARM.com 1209651SAndreas.Sandberg@ARM.comint 1219651SAndreas.Sandberg@ARM.comKvm::capCoalescedMMIO() const 1229651SAndreas.Sandberg@ARM.com{ 1239651SAndreas.Sandberg@ARM.com return checkExtension(KVM_CAP_COALESCED_MMIO); 1249651SAndreas.Sandberg@ARM.com} 1259651SAndreas.Sandberg@ARM.com 1269651SAndreas.Sandberg@ARM.combool 1279651SAndreas.Sandberg@ARM.comKvm::capOneReg() const 1289651SAndreas.Sandberg@ARM.com{ 1299651SAndreas.Sandberg@ARM.com#ifdef KVM_CAP_ONE_REG 1309651SAndreas.Sandberg@ARM.com return checkExtension(KVM_CAP_ONE_REG) != 0; 1319651SAndreas.Sandberg@ARM.com#else 1329651SAndreas.Sandberg@ARM.com return false; 1339651SAndreas.Sandberg@ARM.com#endif 1349651SAndreas.Sandberg@ARM.com} 1359651SAndreas.Sandberg@ARM.com 1369651SAndreas.Sandberg@ARM.combool 1379651SAndreas.Sandberg@ARM.comKvm::capIRQChip() const 1389651SAndreas.Sandberg@ARM.com{ 1399651SAndreas.Sandberg@ARM.com return checkExtension(KVM_CAP_IRQCHIP) != 0; 1409651SAndreas.Sandberg@ARM.com} 1419651SAndreas.Sandberg@ARM.com 1429651SAndreas.Sandberg@ARM.combool 1439651SAndreas.Sandberg@ARM.comKvm::getSupportedCPUID(struct kvm_cpuid2 &cpuid) const 1449651SAndreas.Sandberg@ARM.com{ 1459651SAndreas.Sandberg@ARM.com#if defined(__i386__) || defined(__x86_64__) 1469651SAndreas.Sandberg@ARM.com if (ioctl(KVM_GET_SUPPORTED_CPUID, (void *)&cpuid) == -1) { 1479651SAndreas.Sandberg@ARM.com if (errno == E2BIG) 1489651SAndreas.Sandberg@ARM.com return false; 1499651SAndreas.Sandberg@ARM.com else 1509651SAndreas.Sandberg@ARM.com panic("KVM: Failed to get supported CPUID (errno: %i)\n", errno); 1519651SAndreas.Sandberg@ARM.com } else 1529651SAndreas.Sandberg@ARM.com return true; 1539651SAndreas.Sandberg@ARM.com#else 1549651SAndreas.Sandberg@ARM.com panic("KVM: getSupportedCPUID is unsupported on this platform.\n"); 1559651SAndreas.Sandberg@ARM.com#endif 1569651SAndreas.Sandberg@ARM.com} 1579651SAndreas.Sandberg@ARM.com 1589651SAndreas.Sandberg@ARM.comint 1599651SAndreas.Sandberg@ARM.comKvm::checkExtension(int extension) const 1609651SAndreas.Sandberg@ARM.com{ 1619651SAndreas.Sandberg@ARM.com int ret = ioctl(KVM_CHECK_EXTENSION, extension); 1629651SAndreas.Sandberg@ARM.com if (ret == -1) 1639651SAndreas.Sandberg@ARM.com panic("KVM: ioctl failed when checking for extension\n"); 1649651SAndreas.Sandberg@ARM.com return ret; 1659651SAndreas.Sandberg@ARM.com} 1669651SAndreas.Sandberg@ARM.com 1679651SAndreas.Sandberg@ARM.comint 1689651SAndreas.Sandberg@ARM.comKvm::ioctl(int request, long p1) const 1699651SAndreas.Sandberg@ARM.com{ 1709651SAndreas.Sandberg@ARM.com assert(kvmFD != -1); 1719651SAndreas.Sandberg@ARM.com 1729651SAndreas.Sandberg@ARM.com return ::ioctl(kvmFD, request, p1); 1739651SAndreas.Sandberg@ARM.com} 1749651SAndreas.Sandberg@ARM.com 1759651SAndreas.Sandberg@ARM.comint 1769651SAndreas.Sandberg@ARM.comKvm::createVM() 1779651SAndreas.Sandberg@ARM.com{ 1789651SAndreas.Sandberg@ARM.com int vmFD; 1799651SAndreas.Sandberg@ARM.com 1809651SAndreas.Sandberg@ARM.com vmFD = ioctl(KVM_CREATE_VM); 1819651SAndreas.Sandberg@ARM.com if (vmFD == -1) 1829651SAndreas.Sandberg@ARM.com panic("Failed to create KVM VM\n"); 1839651SAndreas.Sandberg@ARM.com 1849651SAndreas.Sandberg@ARM.com return vmFD; 1859651SAndreas.Sandberg@ARM.com} 1869651SAndreas.Sandberg@ARM.com 1879651SAndreas.Sandberg@ARM.com 1889651SAndreas.Sandberg@ARM.comKvmVM::KvmVM(KvmVMParams *params) 1899651SAndreas.Sandberg@ARM.com : SimObject(params), 1909651SAndreas.Sandberg@ARM.com kvm(), system(params->system), 1919651SAndreas.Sandberg@ARM.com vmFD(kvm.createVM()), 1929651SAndreas.Sandberg@ARM.com started(false), 1939651SAndreas.Sandberg@ARM.com nextVCPUID(0) 1949651SAndreas.Sandberg@ARM.com{ 1959651SAndreas.Sandberg@ARM.com /* Setup the coalesced MMIO regions */ 1969651SAndreas.Sandberg@ARM.com for (int i = 0; i < params->coalescedMMIO.size(); ++i) 1979651SAndreas.Sandberg@ARM.com coalesceMMIO(params->coalescedMMIO[i]); 1989651SAndreas.Sandberg@ARM.com} 1999651SAndreas.Sandberg@ARM.com 2009651SAndreas.Sandberg@ARM.comKvmVM::~KvmVM() 2019651SAndreas.Sandberg@ARM.com{ 2029651SAndreas.Sandberg@ARM.com close(vmFD); 2039651SAndreas.Sandberg@ARM.com} 2049651SAndreas.Sandberg@ARM.com 2059651SAndreas.Sandberg@ARM.comvoid 2069651SAndreas.Sandberg@ARM.comKvmVM::cpuStartup() 2079651SAndreas.Sandberg@ARM.com{ 2089651SAndreas.Sandberg@ARM.com if (started) 2099651SAndreas.Sandberg@ARM.com return; 2109651SAndreas.Sandberg@ARM.com started = true; 2119651SAndreas.Sandberg@ARM.com 2129651SAndreas.Sandberg@ARM.com delayedStartup(); 2139651SAndreas.Sandberg@ARM.com} 2149651SAndreas.Sandberg@ARM.com 2159651SAndreas.Sandberg@ARM.comvoid 2169651SAndreas.Sandberg@ARM.comKvmVM::delayedStartup() 2179651SAndreas.Sandberg@ARM.com{ 2189651SAndreas.Sandberg@ARM.com const std::vector<std::pair<AddrRange, uint8_t*> >&memories( 2199651SAndreas.Sandberg@ARM.com system->getPhysMem().getBackingStore()); 2209651SAndreas.Sandberg@ARM.com 2219651SAndreas.Sandberg@ARM.com DPRINTF(Kvm, "Mapping %i memory region(s)\n", memories.size()); 2229651SAndreas.Sandberg@ARM.com for (int slot(0); slot < memories.size(); ++slot) { 2239651SAndreas.Sandberg@ARM.com const AddrRange &range(memories[slot].first); 2249651SAndreas.Sandberg@ARM.com void *pmem(memories[slot].second); 2259651SAndreas.Sandberg@ARM.com 2269651SAndreas.Sandberg@ARM.com if (pmem) { 2279651SAndreas.Sandberg@ARM.com DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n", 2289651SAndreas.Sandberg@ARM.com pmem, range.start(), range.size()); 2299651SAndreas.Sandberg@ARM.com 2309651SAndreas.Sandberg@ARM.com setUserMemoryRegion(slot, pmem, range, 0 /* flags */); 2319651SAndreas.Sandberg@ARM.com } else { 2329651SAndreas.Sandberg@ARM.com DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start()); 2339651SAndreas.Sandberg@ARM.com hack("KVM: Zero memory handled as IO\n"); 2349651SAndreas.Sandberg@ARM.com } 2359651SAndreas.Sandberg@ARM.com } 2369651SAndreas.Sandberg@ARM.com} 2379651SAndreas.Sandberg@ARM.com 2389651SAndreas.Sandberg@ARM.comvoid 2399651SAndreas.Sandberg@ARM.comKvmVM::setUserMemoryRegion(uint32_t slot, 2409651SAndreas.Sandberg@ARM.com void *host_addr, AddrRange guest_range, 2419651SAndreas.Sandberg@ARM.com uint32_t flags) 2429651SAndreas.Sandberg@ARM.com{ 2439651SAndreas.Sandberg@ARM.com if (guest_range.interleaved()) 2449651SAndreas.Sandberg@ARM.com panic("Tried to map an interleaved memory range into a KVM VM.\n"); 2459651SAndreas.Sandberg@ARM.com 2469651SAndreas.Sandberg@ARM.com setUserMemoryRegion(slot, host_addr, 2479651SAndreas.Sandberg@ARM.com guest_range.start(), guest_range.size(), 2489651SAndreas.Sandberg@ARM.com flags); 2499651SAndreas.Sandberg@ARM.com} 2509651SAndreas.Sandberg@ARM.com 2519651SAndreas.Sandberg@ARM.comvoid 2529651SAndreas.Sandberg@ARM.comKvmVM::setUserMemoryRegion(uint32_t slot, 2539651SAndreas.Sandberg@ARM.com void *host_addr, Addr guest_addr, 2549651SAndreas.Sandberg@ARM.com uint64_t len, uint32_t flags) 2559651SAndreas.Sandberg@ARM.com{ 2569651SAndreas.Sandberg@ARM.com struct kvm_userspace_memory_region m; 2579651SAndreas.Sandberg@ARM.com 2589651SAndreas.Sandberg@ARM.com memset(&m, 0, sizeof(m)); 2599651SAndreas.Sandberg@ARM.com m.slot = slot; 2609651SAndreas.Sandberg@ARM.com m.flags = flags; 2619651SAndreas.Sandberg@ARM.com m.guest_phys_addr = (uint64_t)guest_addr; 2629651SAndreas.Sandberg@ARM.com m.memory_size = len; 2639651SAndreas.Sandberg@ARM.com m.userspace_addr = (__u64)host_addr; 2649651SAndreas.Sandberg@ARM.com 2659651SAndreas.Sandberg@ARM.com if (ioctl(KVM_SET_USER_MEMORY_REGION, (void *)&m) == -1) { 2669651SAndreas.Sandberg@ARM.com panic("Failed to setup KVM memory region:\n" 2679651SAndreas.Sandberg@ARM.com "\tHost Address: 0x%p\n" 2689651SAndreas.Sandberg@ARM.com "\tGuest Address: 0x%llx\n", 2699651SAndreas.Sandberg@ARM.com "\tSize: %ll\n", 2709651SAndreas.Sandberg@ARM.com "\tFlags: 0x%x\n", 2719651SAndreas.Sandberg@ARM.com m.userspace_addr, m.guest_phys_addr, 2729651SAndreas.Sandberg@ARM.com m.memory_size, m.flags); 2739651SAndreas.Sandberg@ARM.com } 2749651SAndreas.Sandberg@ARM.com} 2759651SAndreas.Sandberg@ARM.com 2769651SAndreas.Sandberg@ARM.comvoid 2779651SAndreas.Sandberg@ARM.comKvmVM::coalesceMMIO(const AddrRange &range) 2789651SAndreas.Sandberg@ARM.com{ 2799651SAndreas.Sandberg@ARM.com coalesceMMIO(range.start(), range.size()); 2809651SAndreas.Sandberg@ARM.com} 2819651SAndreas.Sandberg@ARM.com 2829651SAndreas.Sandberg@ARM.comvoid 2839651SAndreas.Sandberg@ARM.comKvmVM::coalesceMMIO(Addr start, int size) 2849651SAndreas.Sandberg@ARM.com{ 2859651SAndreas.Sandberg@ARM.com struct kvm_coalesced_mmio_zone zone; 2869651SAndreas.Sandberg@ARM.com 2879651SAndreas.Sandberg@ARM.com zone.addr = start; 2889651SAndreas.Sandberg@ARM.com zone.size = size; 2899651SAndreas.Sandberg@ARM.com zone.pad = 0; 2909651SAndreas.Sandberg@ARM.com 2919651SAndreas.Sandberg@ARM.com DPRINTF(Kvm, "KVM: Registering coalesced MMIO region [0x%x, 0x%x]\n", 2929651SAndreas.Sandberg@ARM.com zone.addr, zone.addr + zone.size - 1); 2939651SAndreas.Sandberg@ARM.com if (ioctl(KVM_REGISTER_COALESCED_MMIO, (void *)&zone) == -1) 2949651SAndreas.Sandberg@ARM.com panic("KVM: Failed to register coalesced MMIO region (%i)\n", 2959651SAndreas.Sandberg@ARM.com errno); 2969651SAndreas.Sandberg@ARM.com} 2979651SAndreas.Sandberg@ARM.com 2989651SAndreas.Sandberg@ARM.comvoid 2999651SAndreas.Sandberg@ARM.comKvmVM::setTSSAddress(Addr tss_address) 3009651SAndreas.Sandberg@ARM.com{ 3019651SAndreas.Sandberg@ARM.com if (ioctl(KVM_SET_TSS_ADDR, (unsigned long)tss_address) == -1) 3029651SAndreas.Sandberg@ARM.com panic("KVM: Failed to set VM TSS address\n"); 3039651SAndreas.Sandberg@ARM.com} 3049651SAndreas.Sandberg@ARM.com 3059651SAndreas.Sandberg@ARM.comvoid 3069651SAndreas.Sandberg@ARM.comKvmVM::createIRQChip() 3079651SAndreas.Sandberg@ARM.com{ 3089651SAndreas.Sandberg@ARM.com if (_hasKernelIRQChip) 3099651SAndreas.Sandberg@ARM.com panic("KvmVM::createIRQChip called twice.\n"); 3109651SAndreas.Sandberg@ARM.com 3119651SAndreas.Sandberg@ARM.com if (ioctl(KVM_CREATE_IRQCHIP) != -1) { 3129651SAndreas.Sandberg@ARM.com _hasKernelIRQChip = true; 3139651SAndreas.Sandberg@ARM.com } else { 3149651SAndreas.Sandberg@ARM.com warn("KVM: Failed to create in-kernel IRQ chip (errno: %i)\n", 3159651SAndreas.Sandberg@ARM.com errno); 3169651SAndreas.Sandberg@ARM.com _hasKernelIRQChip = false; 3179651SAndreas.Sandberg@ARM.com } 3189651SAndreas.Sandberg@ARM.com} 3199651SAndreas.Sandberg@ARM.com 3209651SAndreas.Sandberg@ARM.comvoid 3219651SAndreas.Sandberg@ARM.comKvmVM::setIRQLine(uint32_t irq, bool high) 3229651SAndreas.Sandberg@ARM.com{ 3239651SAndreas.Sandberg@ARM.com struct kvm_irq_level kvm_level; 3249651SAndreas.Sandberg@ARM.com 3259651SAndreas.Sandberg@ARM.com kvm_level.irq = irq; 3269651SAndreas.Sandberg@ARM.com kvm_level.level = high ? 1 : 0; 3279651SAndreas.Sandberg@ARM.com 3289651SAndreas.Sandberg@ARM.com if (ioctl(KVM_IRQ_LINE, &kvm_level) == -1) 3299651SAndreas.Sandberg@ARM.com panic("KVM: Failed to set IRQ line level (errno: %i)\n", 3309651SAndreas.Sandberg@ARM.com errno); 3319651SAndreas.Sandberg@ARM.com} 3329651SAndreas.Sandberg@ARM.com 3339651SAndreas.Sandberg@ARM.comint 3349651SAndreas.Sandberg@ARM.comKvmVM::createVCPU(long vcpuID) 3359651SAndreas.Sandberg@ARM.com{ 3369651SAndreas.Sandberg@ARM.com int fd; 3379651SAndreas.Sandberg@ARM.com 3389651SAndreas.Sandberg@ARM.com fd = ioctl(KVM_CREATE_VCPU, vcpuID); 3399651SAndreas.Sandberg@ARM.com if (fd == -1) 3409651SAndreas.Sandberg@ARM.com panic("KVM: Failed to create virtual CPU"); 3419651SAndreas.Sandberg@ARM.com 3429651SAndreas.Sandberg@ARM.com return fd; 3439651SAndreas.Sandberg@ARM.com} 3449651SAndreas.Sandberg@ARM.com 3459651SAndreas.Sandberg@ARM.comlong 3469651SAndreas.Sandberg@ARM.comKvmVM::allocVCPUID() 3479651SAndreas.Sandberg@ARM.com{ 3489651SAndreas.Sandberg@ARM.com return nextVCPUID++; 3499651SAndreas.Sandberg@ARM.com} 3509651SAndreas.Sandberg@ARM.com 3519651SAndreas.Sandberg@ARM.comint 3529651SAndreas.Sandberg@ARM.comKvmVM::ioctl(int request, long p1) const 3539651SAndreas.Sandberg@ARM.com{ 3549651SAndreas.Sandberg@ARM.com assert(vmFD != -1); 3559651SAndreas.Sandberg@ARM.com 3569651SAndreas.Sandberg@ARM.com return ::ioctl(vmFD, request, p1); 3579651SAndreas.Sandberg@ARM.com} 3589651SAndreas.Sandberg@ARM.com 3599651SAndreas.Sandberg@ARM.com 3609651SAndreas.Sandberg@ARM.comKvmVM * 3619651SAndreas.Sandberg@ARM.comKvmVMParams::create() 3629651SAndreas.Sandberg@ARM.com{ 3639651SAndreas.Sandberg@ARM.com static bool created = false; 3649651SAndreas.Sandberg@ARM.com if (created) 3659651SAndreas.Sandberg@ARM.com warn_once("Use of multiple KvmVMs is currently untested!\n"); 3669651SAndreas.Sandberg@ARM.com 3679651SAndreas.Sandberg@ARM.com created = true; 3689651SAndreas.Sandberg@ARM.com 3699651SAndreas.Sandberg@ARM.com return new KvmVM(this); 3709651SAndreas.Sandberg@ARM.com} 371