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