vm.cc revision 11363:f3f72c0ab03e
12381SN/A/* 212652Sandreas.sandberg@arm.com * Copyright 2014 Google, Inc. 38949Sandreas.hansson@arm.com * Copyright (c) 2012, 2015 ARM Limited 48949Sandreas.hansson@arm.com * All rights reserved 58949Sandreas.hansson@arm.com * 68949Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 78949Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 88949Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 98949Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 108949Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 118949Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 128949Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 138949Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 142592SN/A * 1510975Sdavid.hashe@amd.com * Redistribution and use in source and binary forms, with or without 162381SN/A * modification, are permitted provided that the following conditions are 172381SN/A * met: redistributions of source code must retain the above copyright 182381SN/A * notice, this list of conditions and the following disclaimer; 192381SN/A * redistributions in binary form must reproduce the above copyright 202381SN/A * notice, this list of conditions and the following disclaimer in the 212381SN/A * documentation and/or other materials provided with the distribution; 222381SN/A * neither the name of the copyright holders nor the names of its 232381SN/A * contributors may be used to endorse or promote products derived from 242381SN/A * this software without specific prior written permission. 252381SN/A * 262381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 272381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 282381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 292381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 302381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 312381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 322381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 332381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 342381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 352381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 362381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 372381SN/A * 382381SN/A * Authors: Andreas Sandberg 392381SN/A */ 402665Ssaidi@eecs.umich.edu 412665Ssaidi@eecs.umich.edu#include <linux/kvm.h> 422665Ssaidi@eecs.umich.edu#include <sys/ioctl.h> 432665Ssaidi@eecs.umich.edu#include <sys/stat.h> 449031Sandreas.hansson@arm.com#include <sys/types.h> 4512349Snikos.nikoleris@arm.com#include <fcntl.h> 462381SN/A#include <unistd.h> 472381SN/A 482381SN/A#include <cerrno> 492381SN/A#include <memory> 502662Sstever@eecs.umich.edu 512381SN/A#include "cpu/kvm/vm.hh" 522381SN/A#include "debug/Kvm.hh" 532381SN/A#include "params/KvmVM.hh" 542381SN/A#include "sim/system.hh" 552381SN/A 568229Snate@binkert.org#define EXPECTED_KVM_API_VERSION 12 573348Sbinkertn@umich.edu 583348Sbinkertn@umich.edu#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION 593348Sbinkertn@umich.edu#error Unsupported KVM version 605735Snate@binkert.org#endif 614024Sbinkertn@umich.edu 625735Snate@binkert.orgKvm *Kvm::instance = NULL; 6312334Sgabeblack@google.com 645314Sstever@gmail.comKvm::Kvm() 656216Snate@binkert.org : kvmFD(-1), apiVersion(-1), vcpuMMapSize(0) 6613347Sgabeblack@google.com{ 672392SN/A kvmFD = ::open("/dev/kvm", O_RDWR); 684167Sbinkertn@umich.edu if (kvmFD == -1) 692394SN/A fatal("KVM: Failed to open /dev/kvm\n"); 708737Skoansin.tan@gmail.com 713349Sbinkertn@umich.edu apiVersion = ioctl(KVM_GET_API_VERSION); 722394SN/A if (apiVersion != EXPECTED_KVM_API_VERSION) 732812Srdreslin@umich.edu fatal("KVM: Incompatible API version\n"); 7412351Snikos.nikoleris@arm.com 752812Srdreslin@umich.edu vcpuMMapSize = ioctl(KVM_GET_VCPU_MMAP_SIZE); 764022Sstever@eecs.umich.edu if (vcpuMMapSize == -1) 774022Sstever@eecs.umich.edu panic("KVM: Failed to get virtual CPU MMAP size\n"); 785735Snate@binkert.org} 795735Snate@binkert.org 804022Sstever@eecs.umich.eduKvm::~Kvm() 815735Snate@binkert.org{ 825735Snate@binkert.org close(kvmFD); 835735Snate@binkert.org} 844022Sstever@eecs.umich.edu 854022Sstever@eecs.umich.eduKvm * 864022Sstever@eecs.umich.eduKvm::create() 874022Sstever@eecs.umich.edu{ 884473Sstever@eecs.umich.edu if (!instance) 895319Sstever@gmail.com instance = new Kvm(); 904022Sstever@eecs.umich.edu 914022Sstever@eecs.umich.edu return instance; 9211199Sandreas.hansson@arm.com} 9311199Sandreas.hansson@arm.com 9412344Snikos.nikoleris@arm.combool 9510883Sali.jafri@arm.comKvm::capUserMemory() const 964022Sstever@eecs.umich.edu{ 974022Sstever@eecs.umich.edu return checkExtension(KVM_CAP_USER_MEMORY) != 0; 984022Sstever@eecs.umich.edu} 994022Sstever@eecs.umich.edu 10010886Sandreas.hansson@arm.combool 1014022Sstever@eecs.umich.eduKvm::capSetTSSAddress() const 1027465Ssteve.reinhardt@amd.com{ 1034628Sstever@eecs.umich.edu return checkExtension(KVM_CAP_SET_TSS_ADDR) != 0; 1047465Ssteve.reinhardt@amd.com} 1057465Ssteve.reinhardt@amd.com 1064022Sstever@eecs.umich.edubool 1074022Sstever@eecs.umich.eduKvm::capExtendedCPUID() const 10810885Sandreas.hansson@arm.com{ 10910885Sandreas.hansson@arm.com return checkExtension(KVM_CAP_EXT_CPUID) != 0; 1104626Sstever@eecs.umich.edu} 1114626Sstever@eecs.umich.edu 1127669Ssteve.reinhardt@amd.combool 1134626Sstever@eecs.umich.eduKvm::capUserNMI() const 1144040Ssaidi@eecs.umich.edu{ 1154040Ssaidi@eecs.umich.edu#ifdef KVM_CAP_USER_NMI 1165650Sgblack@eecs.umich.edu return checkExtension(KVM_CAP_USER_NMI) != 0; 1175650Sgblack@eecs.umich.edu#else 11811256Santhony.gutierrez@amd.com return false; 11911256Santhony.gutierrez@amd.com#endif 12012347Snikos.nikoleris@arm.com} 12112347Snikos.nikoleris@arm.com 12212347Snikos.nikoleris@arm.comint 12312347Snikos.nikoleris@arm.comKvm::capCoalescedMMIO() const 1244870Sstever@eecs.umich.edu{ 1254870Sstever@eecs.umich.edu return checkExtension(KVM_CAP_COALESCED_MMIO); 1264870Sstever@eecs.umich.edu} 1274870Sstever@eecs.umich.edu 1284870Sstever@eecs.umich.eduint 1294870Sstever@eecs.umich.eduKvm::capNumMemSlots() const 1308436SBrad.Beckmann@amd.com{ 1318436SBrad.Beckmann@amd.com#ifdef KVM_CAP_NR_MEMSLOTS 1325314Sstever@gmail.com return checkExtension(KVM_CAP_NR_MEMSLOTS); 1335314Sstever@gmail.com#else 1348184Ssomayeh@cs.wisc.edu return 0; 13510886Sandreas.hansson@arm.com#endif 13610886Sandreas.hansson@arm.com} 1374022Sstever@eecs.umich.edu 1384022Sstever@eecs.umich.edubool 1394022Sstever@eecs.umich.eduKvm::capOneReg() const 1404022Sstever@eecs.umich.edu{ 1415735Snate@binkert.org#ifdef KVM_CAP_ONE_REG 1425735Snate@binkert.org return checkExtension(KVM_CAP_ONE_REG) != 0; 1435735Snate@binkert.org#else 1444022Sstever@eecs.umich.edu return false; 1454022Sstever@eecs.umich.edu#endif 1464626Sstever@eecs.umich.edu} 1474626Sstever@eecs.umich.edu 1487465Ssteve.reinhardt@amd.combool 1494022Sstever@eecs.umich.eduKvm::capIRQChip() const 15012347Snikos.nikoleris@arm.com{ 15111284Sandreas.hansson@arm.com return checkExtension(KVM_CAP_IRQCHIP) != 0; 1524626Sstever@eecs.umich.edu} 1534626Sstever@eecs.umich.edu 1544626Sstever@eecs.umich.edubool 15511199Sandreas.hansson@arm.comKvm::capVCPUEvents() const 1564022Sstever@eecs.umich.edu{ 1574022Sstever@eecs.umich.edu#ifdef KVM_CAP_VCPU_EVENTS 1586076Sgblack@eecs.umich.edu return checkExtension(KVM_CAP_VCPU_EVENTS) != 0; 1594626Sstever@eecs.umich.edu#else 1604870Sstever@eecs.umich.edu return false; 1615314Sstever@gmail.com#endif 1628184Ssomayeh@cs.wisc.edu} 16311600Sandreas.hansson@arm.com 1644022Sstever@eecs.umich.edubool 1654022Sstever@eecs.umich.eduKvm::capDebugRegs() const 1664022Sstever@eecs.umich.edu{ 1675735Snate@binkert.org#ifdef KVM_CAP_DEBUGREGS 1685735Snate@binkert.org return checkExtension(KVM_CAP_DEBUGREGS) != 0; 1695735Snate@binkert.org#else 1705735Snate@binkert.org return false; 1715735Snate@binkert.org#endif 1725735Snate@binkert.org} 1735735Snate@binkert.org 1744022Sstever@eecs.umich.edubool 1755735Snate@binkert.orgKvm::capXCRs() const 1765735Snate@binkert.org{ 1774022Sstever@eecs.umich.edu#ifdef KVM_CAP_XCRS 1785735Snate@binkert.org return checkExtension(KVM_CAP_XCRS) != 0; 1794022Sstever@eecs.umich.edu#else 1804022Sstever@eecs.umich.edu return false; 1814022Sstever@eecs.umich.edu#endif 1825735Snate@binkert.org} 1834022Sstever@eecs.umich.edu 1844022Sstever@eecs.umich.edubool 1854022Sstever@eecs.umich.eduKvm::capXSave() const 1864022Sstever@eecs.umich.edu{ 1874022Sstever@eecs.umich.edu#ifdef KVM_CAP_XSAVE 1884022Sstever@eecs.umich.edu return checkExtension(KVM_CAP_XSAVE) != 0; 1895735Snate@binkert.org#else 1905735Snate@binkert.org return false; 1915735Snate@binkert.org#endif 1924022Sstever@eecs.umich.edu} 1934022Sstever@eecs.umich.edu 1944022Sstever@eecs.umich.edu 1954022Sstever@eecs.umich.edu#if defined(__i386__) || defined(__x86_64__) 1964022Sstever@eecs.umich.edubool 19710583SCurtis.Dunham@arm.comKvm::getSupportedCPUID(struct kvm_cpuid2 &cpuid) const 19810583SCurtis.Dunham@arm.com{ 19910583SCurtis.Dunham@arm.com if (ioctl(KVM_GET_SUPPORTED_CPUID, (void *)&cpuid) == -1) { 20010583SCurtis.Dunham@arm.com if (errno == E2BIG) 20110583SCurtis.Dunham@arm.com return false; 20211284Sandreas.hansson@arm.com else 20310583SCurtis.Dunham@arm.com panic("KVM: Failed to get supported CPUID (errno: %i)\n", errno); 20410583SCurtis.Dunham@arm.com } else 20511199Sandreas.hansson@arm.com return true; 20612347Snikos.nikoleris@arm.com} 20711600Sandreas.hansson@arm.com 20811199Sandreas.hansson@arm.comconst Kvm::CPUIDVector & 20911199Sandreas.hansson@arm.comKvm::getSupportedCPUID() const 21011199Sandreas.hansson@arm.com{ 21111199Sandreas.hansson@arm.com if (supportedCPUIDCache.empty()) { 21211199Sandreas.hansson@arm.com std::unique_ptr<struct kvm_cpuid2> cpuid; 21311199Sandreas.hansson@arm.com int i(1); 21410570Sandreas.hansson@arm.com do { 21510570Sandreas.hansson@arm.com cpuid.reset((struct kvm_cpuid2 *)operator new( 21610570Sandreas.hansson@arm.com sizeof(kvm_cpuid2) + i * sizeof(kvm_cpuid_entry2))); 21710570Sandreas.hansson@arm.com 21810570Sandreas.hansson@arm.com cpuid->nent = i; 21910570Sandreas.hansson@arm.com ++i; 2204022Sstever@eecs.umich.edu } while (!getSupportedCPUID(*cpuid)); 2216102Sgblack@eecs.umich.edu supportedCPUIDCache.assign(cpuid->entries, 22210343SCurtis.Dunham@arm.com cpuid->entries + cpuid->nent); 22310343SCurtis.Dunham@arm.com } 22410343SCurtis.Dunham@arm.com 22510343SCurtis.Dunham@arm.com return supportedCPUIDCache; 2264870Sstever@eecs.umich.edu} 2275314Sstever@gmail.com 2288184Ssomayeh@cs.wisc.edubool 2294022Sstever@eecs.umich.eduKvm::getSupportedMSRs(struct kvm_msr_list &msrs) const 23011294Sandreas.hansson@arm.com{ 2315735Snate@binkert.org if (ioctl(KVM_GET_MSR_INDEX_LIST, (void *)&msrs) == -1) { 2325735Snate@binkert.org if (errno == E2BIG) 2334022Sstever@eecs.umich.edu return false; 2344022Sstever@eecs.umich.edu else 2354022Sstever@eecs.umich.edu panic("KVM: Failed to get supported CPUID (errno: %i)\n", errno); 2365735Snate@binkert.org } else 2375735Snate@binkert.org return true; 2384022Sstever@eecs.umich.edu} 2394022Sstever@eecs.umich.edu 2405735Snate@binkert.orgconst Kvm::MSRIndexVector & 2415735Snate@binkert.orgKvm::getSupportedMSRs() const 2425735Snate@binkert.org{ 2434022Sstever@eecs.umich.edu if (supportedMSRCache.empty()) { 2445735Snate@binkert.org std::unique_ptr<struct kvm_msr_list> msrs; 2455735Snate@binkert.org int i(0); 2464022Sstever@eecs.umich.edu do { 2474022Sstever@eecs.umich.edu msrs.reset((struct kvm_msr_list *)operator new( 2482381SN/A sizeof(kvm_msr_list) + i * sizeof(uint32_t))); 2492662Sstever@eecs.umich.edu 2502662Sstever@eecs.umich.edu msrs->nmsrs = i; 2512662Sstever@eecs.umich.edu ++i; 2522662Sstever@eecs.umich.edu } while (!getSupportedMSRs(*msrs)); 2532662Sstever@eecs.umich.edu supportedMSRCache.assign(msrs->indices, msrs->indices + msrs->nmsrs); 2542381SN/A } 2559044SAli.Saidi@ARM.com 2562381SN/A return supportedMSRCache; 2572813Srdreslin@umich.edu} 2585735Snate@binkert.org 2595735Snate@binkert.org#endif // x86-specific 2604022Sstever@eecs.umich.edu 2615735Snate@binkert.org 2625735Snate@binkert.orgint 26310938Sandreas.hansson@arm.comKvm::checkExtension(int extension) const 26410938Sandreas.hansson@arm.com{ 26512349Snikos.nikoleris@arm.com int ret = ioctl(KVM_CHECK_EXTENSION, extension); 26610938Sandreas.hansson@arm.com if (ret == -1) 26711284Sandreas.hansson@arm.com panic("KVM: ioctl failed when checking for extension\n"); 26811284Sandreas.hansson@arm.com return ret; 26911284Sandreas.hansson@arm.com} 27011284Sandreas.hansson@arm.com 27110938Sandreas.hansson@arm.comint 27210938Sandreas.hansson@arm.comKvm::ioctl(int request, long p1) const 27310938Sandreas.hansson@arm.com{ 27411284Sandreas.hansson@arm.com assert(kvmFD != -1); 27511284Sandreas.hansson@arm.com 27611284Sandreas.hansson@arm.com return ::ioctl(kvmFD, request, p1); 27711284Sandreas.hansson@arm.com} 27811284Sandreas.hansson@arm.com 27911284Sandreas.hansson@arm.comint 28011284Sandreas.hansson@arm.comKvm::createVM() 28111284Sandreas.hansson@arm.com{ 28211284Sandreas.hansson@arm.com int vmFD; 28310938Sandreas.hansson@arm.com 28412346Snikos.nikoleris@arm.com vmFD = ioctl(KVM_CREATE_VM); 28512346Snikos.nikoleris@arm.com if (vmFD == -1) 28612346Snikos.nikoleris@arm.com panic("Failed to create KVM VM\n"); 28712346Snikos.nikoleris@arm.com 28812349Snikos.nikoleris@arm.com return vmFD; 28912349Snikos.nikoleris@arm.com} 29012349Snikos.nikoleris@arm.com 29112349Snikos.nikoleris@arm.com 29211057Sandreas.hansson@arm.comKvmVM::KvmVM(KvmVMParams *params) 29311057Sandreas.hansson@arm.com : SimObject(params), 29411057Sandreas.hansson@arm.com kvm(new Kvm()), system(params->system), 29511057Sandreas.hansson@arm.com vmFD(kvm->createVM()), 29610938Sandreas.hansson@arm.com started(false), 29710938Sandreas.hansson@arm.com nextVCPUID(0) 29810938Sandreas.hansson@arm.com{ 29910938Sandreas.hansson@arm.com maxMemorySlot = kvm->capNumMemSlots(); 30010938Sandreas.hansson@arm.com /* If we couldn't determine how memory slots there are, guess 32. */ 30110938Sandreas.hansson@arm.com if (!maxMemorySlot) 30210938Sandreas.hansson@arm.com maxMemorySlot = 32; 30310938Sandreas.hansson@arm.com /* Setup the coalesced MMIO regions */ 30410938Sandreas.hansson@arm.com for (int i = 0; i < params->coalescedMMIO.size(); ++i) 30510938Sandreas.hansson@arm.com coalesceMMIO(params->coalescedMMIO[i]); 30610938Sandreas.hansson@arm.com} 30710938Sandreas.hansson@arm.com 30810938Sandreas.hansson@arm.comKvmVM::~KvmVM() 30910938Sandreas.hansson@arm.com{ 31010938Sandreas.hansson@arm.com if (vmFD != -1) 31110938Sandreas.hansson@arm.com close(vmFD); 3125735Snate@binkert.org 3135735Snate@binkert.org if (kvm) 3145735Snate@binkert.org delete kvm; 3155735Snate@binkert.org} 3164022Sstever@eecs.umich.edu 3174022Sstever@eecs.umich.eduvoid 3185735Snate@binkert.orgKvmVM::notifyFork() 3194870Sstever@eecs.umich.edu{ 3204870Sstever@eecs.umich.edu if (vmFD != -1) { 32112351Snikos.nikoleris@arm.com if (close(vmFD) == -1) 32212351Snikos.nikoleris@arm.com warn("kvm VM: notifyFork failed to close vmFD\n"); 3235735Snate@binkert.org 32412749Sgiacomo.travaglini@arm.com vmFD = -1; 3254870Sstever@eecs.umich.edu 3262566SN/A delete kvm; 3275735Snate@binkert.org kvm = NULL; 32812633Sodanrc@yahoo.com.br } 32912633Sodanrc@yahoo.com.br} 3305735Snate@binkert.org 33112633Sodanrc@yahoo.com.brvoid 3325735Snate@binkert.orgKvmVM::cpuStartup() 3332566SN/A{ 3342566SN/A if (started) 3352566SN/A return; 3365735Snate@binkert.org started = true; 3375735Snate@binkert.org 3382381SN/A delayedStartup(); 3392381SN/A} 34010028SGiacomo.Gabrielli@arm.com 34110028SGiacomo.Gabrielli@arm.comvoid 34210028SGiacomo.Gabrielli@arm.comKvmVM::delayedStartup() 3435735Snate@binkert.org{ 3446227Snate@binkert.org const std::vector<std::pair<AddrRange, uint8_t*> >&memories( 3452381SN/A system->getPhysMem().getBackingStore()); 3465735Snate@binkert.org 34710723Sandreas.hansson@arm.com DPRINTF(Kvm, "Mapping %i memory region(s)\n", memories.size()); 3488668Sgeoffrey.blake@arm.com for (int slot(0); slot < memories.size(); ++slot) { 34910723Sandreas.hansson@arm.com const AddrRange &range(memories[slot].first); 3508668Sgeoffrey.blake@arm.com void *pmem(memories[slot].second); 35112966SMatteo.Andreozzi@arm.com 35212966SMatteo.Andreozzi@arm.com if (pmem) { 35312966SMatteo.Andreozzi@arm.com DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n", 3542641Sstever@eecs.umich.edu pmem, range.start(), range.size()); 3552811Srdreslin@umich.edu 3569547Sandreas.hansson@arm.com if (range.interleaved()) { 35710694SMarco.Balboni@ARM.com panic("Tried to map an interleaved memory range into " 35810405Sandreas.hansson@arm.com "a KVM VM.\n"); 35910405Sandreas.hansson@arm.com } 36010405Sandreas.hansson@arm.com 36110405Sandreas.hansson@arm.com const MemSlot slot = allocMemSlot(range.size()); 3629547Sandreas.hansson@arm.com setupMemSlot(slot, pmem, range.start(), 0/* flags */); 36310694SMarco.Balboni@ARM.com } else { 3643218Sgblack@eecs.umich.edu DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start()); 3659547Sandreas.hansson@arm.com hack("KVM: Zero memory handled as IO\n"); 36611127Sandreas.hansson@arm.com } 36711127Sandreas.hansson@arm.com } 36811127Sandreas.hansson@arm.com} 36911127Sandreas.hansson@arm.com 37011127Sandreas.hansson@arm.comconst KvmVM::MemSlot 37111127Sandreas.hansson@arm.comKvmVM::allocMemSlot(uint64_t size) 37211127Sandreas.hansson@arm.com{ 37311127Sandreas.hansson@arm.com if (!size) 37410694SMarco.Balboni@ARM.com panic("Memory slots must have non-zero size.\n"); 37510694SMarco.Balboni@ARM.com 37610694SMarco.Balboni@ARM.com std::vector<MemorySlot>::iterator pos; 37710694SMarco.Balboni@ARM.com for (pos = memorySlots.begin(); pos != memorySlots.end(); pos++) { 37810405Sandreas.hansson@arm.com if (!pos->size) { 37910405Sandreas.hansson@arm.com pos->size = size; 3809547Sandreas.hansson@arm.com pos->active = false; 38110694SMarco.Balboni@ARM.com return pos->slot; 3823218Sgblack@eecs.umich.edu } 3835735Snate@binkert.org } 3845735Snate@binkert.org 3859542Sandreas.hansson@arm.com uint32_t nextSlot = memorySlots.size(); 3869542Sandreas.hansson@arm.com if (nextSlot > maxMemorySlot) 3879542Sandreas.hansson@arm.com panic("Out of memory slots.\n"); 3889542Sandreas.hansson@arm.com 3899542Sandreas.hansson@arm.com MemorySlot slot; 3909542Sandreas.hansson@arm.com slot.size = size; 3919542Sandreas.hansson@arm.com slot.slot = nextSlot; 3929542Sandreas.hansson@arm.com slot.active = false; 3939542Sandreas.hansson@arm.com 3949542Sandreas.hansson@arm.com memorySlots.push_back(slot); 3959542Sandreas.hansson@arm.com return MemSlot(slot.slot); 3969542Sandreas.hansson@arm.com} 3979542Sandreas.hansson@arm.com 3989542Sandreas.hansson@arm.comvoid 3995735Snate@binkert.orgKvmVM::setupMemSlot(const KvmVM::MemSlot num, void *host_addr, Addr guest, 4005735Snate@binkert.org uint32_t flags) 4015735Snate@binkert.org{ 4029542Sandreas.hansson@arm.com MemorySlot &slot = memorySlots.at(num.num); 4039542Sandreas.hansson@arm.com slot.active = true; 4042641Sstever@eecs.umich.edu setUserMemoryRegion(num.num, host_addr, guest, slot.size, flags); 4052641Sstever@eecs.umich.edu} 4062641Sstever@eecs.umich.edu 4075315Sstever@gmail.comvoid 4085315Sstever@gmail.comKvmVM::disableMemSlot(const KvmVM::MemSlot num) 4095315Sstever@gmail.com{ 4105315Sstever@gmail.com MemorySlot &slot = memorySlots.at(num.num); 4119044SAli.Saidi@ARM.com if (slot.active) 4125735Snate@binkert.org setUserMemoryRegion(num.num, NULL, 0, 0, 0); 4135735Snate@binkert.org slot.active = false; 4145735Snate@binkert.org} 4155735Snate@binkert.org 4165735Snate@binkert.orgvoid 4175735Snate@binkert.orgKvmVM::freeMemSlot(const KvmVM::MemSlot num) 4185735Snate@binkert.org{ 4195314Sstever@gmail.com disableMemSlot(num.num); 4205314Sstever@gmail.com MemorySlot &slot = memorySlots.at(num.num); 4215314Sstever@gmail.com slot.size = 0; 4225735Snate@binkert.org} 4235314Sstever@gmail.com 4245314Sstever@gmail.comvoid 4255314Sstever@gmail.comKvmVM::setUserMemoryRegion(uint32_t slot, 4265314Sstever@gmail.com void *host_addr, Addr guest_addr, 4275314Sstever@gmail.com uint64_t len, uint32_t flags) 4285314Sstever@gmail.com{ 4295314Sstever@gmail.com struct kvm_userspace_memory_region m; 4305314Sstever@gmail.com 4315314Sstever@gmail.com memset(&m, 0, sizeof(m)); 4325314Sstever@gmail.com m.slot = slot; 4335314Sstever@gmail.com m.flags = flags; 4345314Sstever@gmail.com m.guest_phys_addr = (uint64_t)guest_addr; 4355314Sstever@gmail.com m.memory_size = len; 4365314Sstever@gmail.com m.userspace_addr = (__u64)host_addr; 4375735Snate@binkert.org 4385735Snate@binkert.org if (ioctl(KVM_SET_USER_MEMORY_REGION, (void *)&m) == -1) { 4395735Snate@binkert.org panic("Failed to setup KVM memory region:\n" 4405314Sstever@gmail.com "\tHost Address: 0x%p\n" 4415315Sstever@gmail.com "\tGuest Address: 0x%llx\n", 4425735Snate@binkert.org "\tSize: %ll\n", 4435735Snate@binkert.org "\tFlags: 0x%x\n", 4445315Sstever@gmail.com m.userspace_addr, m.guest_phys_addr, 4455735Snate@binkert.org m.memory_size, m.flags); 4465735Snate@binkert.org } 4475314Sstever@gmail.com} 4485314Sstever@gmail.com 4495735Snate@binkert.orgvoid 4505735Snate@binkert.orgKvmVM::coalesceMMIO(const AddrRange &range) 4515735Snate@binkert.org{ 4525735Snate@binkert.org coalesceMMIO(range.start(), range.size()); 4535314Sstever@gmail.com} 4545735Snate@binkert.org 4555735Snate@binkert.orgvoid 4565735Snate@binkert.orgKvmVM::coalesceMMIO(Addr start, int size) 4575315Sstever@gmail.com{ 4585735Snate@binkert.org struct kvm_coalesced_mmio_zone zone; 4595735Snate@binkert.org 4605314Sstever@gmail.com zone.addr = start; 4615735Snate@binkert.org zone.size = size; 4625735Snate@binkert.org zone.pad = 0; 4635735Snate@binkert.org 4645735Snate@binkert.org DPRINTF(Kvm, "KVM: Registering coalesced MMIO region [0x%x, 0x%x]\n", 4655735Snate@binkert.org zone.addr, zone.addr + zone.size - 1); 4665314Sstever@gmail.com if (ioctl(KVM_REGISTER_COALESCED_MMIO, (void *)&zone) == -1) 4675314Sstever@gmail.com panic("KVM: Failed to register coalesced MMIO region (%i)\n", 4685314Sstever@gmail.com errno); 4695735Snate@binkert.org} 4705735Snate@binkert.org 4715735Snate@binkert.orgvoid 4725735Snate@binkert.orgKvmVM::setTSSAddress(Addr tss_address) 4739542Sandreas.hansson@arm.com{ 4745735Snate@binkert.org if (ioctl(KVM_SET_TSS_ADDR, (unsigned long)tss_address) == -1) 4755735Snate@binkert.org panic("KVM: Failed to set VM TSS address\n"); 4765735Snate@binkert.org} 4772662Sstever@eecs.umich.edu 4782641Sstever@eecs.umich.eduvoid 4799542Sandreas.hansson@arm.comKvmVM::createIRQChip() 4809542Sandreas.hansson@arm.com{ 4819542Sandreas.hansson@arm.com if (_hasKernelIRQChip) 4829542Sandreas.hansson@arm.com panic("KvmVM::createIRQChip called twice.\n"); 4839542Sandreas.hansson@arm.com 4849542Sandreas.hansson@arm.com if (ioctl(KVM_CREATE_IRQCHIP) != -1) { 4859542Sandreas.hansson@arm.com _hasKernelIRQChip = true; 4869542Sandreas.hansson@arm.com } else { 4879542Sandreas.hansson@arm.com warn("KVM: Failed to create in-kernel IRQ chip (errno: %i)\n", 4889542Sandreas.hansson@arm.com errno); 4899542Sandreas.hansson@arm.com _hasKernelIRQChip = false; 4909542Sandreas.hansson@arm.com } 4919542Sandreas.hansson@arm.com} 4929542Sandreas.hansson@arm.com 4939542Sandreas.hansson@arm.comvoid 4949542Sandreas.hansson@arm.comKvmVM::setIRQLine(uint32_t irq, bool high) 4959542Sandreas.hansson@arm.com{ 4969542Sandreas.hansson@arm.com struct kvm_irq_level kvm_level; 4979542Sandreas.hansson@arm.com 4989542Sandreas.hansson@arm.com kvm_level.irq = irq; 4999543Ssascha.bischoff@arm.com kvm_level.level = high ? 1 : 0; 5009543Ssascha.bischoff@arm.com 5019543Ssascha.bischoff@arm.com if (ioctl(KVM_IRQ_LINE, &kvm_level) == -1) 5029543Ssascha.bischoff@arm.com panic("KVM: Failed to set IRQ line level (errno: %i)\n", 5039543Ssascha.bischoff@arm.com errno); 5049543Ssascha.bischoff@arm.com} 5059543Ssascha.bischoff@arm.com 5069543Ssascha.bischoff@arm.comint 5079543Ssascha.bischoff@arm.comKvmVM::createDevice(uint32_t type, uint32_t flags) 5089543Ssascha.bischoff@arm.com{ 5099543Ssascha.bischoff@arm.com#if defined(KVM_CREATE_DEVICE) 5109543Ssascha.bischoff@arm.com struct kvm_create_device dev = { type, 0, flags }; 5119543Ssascha.bischoff@arm.com 5129543Ssascha.bischoff@arm.com if (ioctl(KVM_CREATE_DEVICE, &dev) == -1) { 5139543Ssascha.bischoff@arm.com panic("KVM: Failed to create device (errno: %i)\n", 5149543Ssascha.bischoff@arm.com errno); 5159543Ssascha.bischoff@arm.com } 5169543Ssascha.bischoff@arm.com 5179543Ssascha.bischoff@arm.com return dev.fd; 5185735Snate@binkert.org#else 5195735Snate@binkert.org panic("Kernel headers don't support KVM_CREATE_DEVICE\n"); 5204022Sstever@eecs.umich.edu#endif 5212811Srdreslin@umich.edu} 5225735Snate@binkert.org 5234022Sstever@eecs.umich.eduint 5242811Srdreslin@umich.eduKvmVM::createVCPU(long vcpuID) 52510583SCurtis.Dunham@arm.com{ 52610583SCurtis.Dunham@arm.com int fd; 52710583SCurtis.Dunham@arm.com 52810583SCurtis.Dunham@arm.com fd = ioctl(KVM_CREATE_VCPU, vcpuID); 52910583SCurtis.Dunham@arm.com if (fd == -1) 53011287Sandreas.hansson@arm.com panic("KVM: Failed to create virtual CPU"); 53111287Sandreas.hansson@arm.com 53211287Sandreas.hansson@arm.com return fd; 53311287Sandreas.hansson@arm.com} 53411287Sandreas.hansson@arm.com 53511287Sandreas.hansson@arm.comlong 53611287Sandreas.hansson@arm.comKvmVM::allocVCPUID() 53711287Sandreas.hansson@arm.com{ 53811287Sandreas.hansson@arm.com return nextVCPUID++; 53910583SCurtis.Dunham@arm.com} 54010583SCurtis.Dunham@arm.com 54111199Sandreas.hansson@arm.com#if defined(__aarch64__) 54212347Snikos.nikoleris@arm.comvoid 54311600Sandreas.hansson@arm.comKvmVM::kvmArmPreferredTarget(struct kvm_vcpu_init &target) const 54411199Sandreas.hansson@arm.com{ 54510583SCurtis.Dunham@arm.com if (ioctl(KVM_ARM_PREFERRED_TARGET, &target) == -1) { 54611286Sandreas.hansson@arm.com panic("KVM: Failed to get ARM preferred CPU target (errno: %i)\n", 54711286Sandreas.hansson@arm.com errno); 54811286Sandreas.hansson@arm.com } 54911286Sandreas.hansson@arm.com} 55011286Sandreas.hansson@arm.com#endif 55110583SCurtis.Dunham@arm.com 55210583SCurtis.Dunham@arm.comint 55310583SCurtis.Dunham@arm.comKvmVM::ioctl(int request, long p1) const 55410583SCurtis.Dunham@arm.com{ 5552812Srdreslin@umich.edu assert(vmFD != -1); 55611284Sandreas.hansson@arm.com 55711284Sandreas.hansson@arm.com return ::ioctl(vmFD, request, p1); 55811284Sandreas.hansson@arm.com} 55911284Sandreas.hansson@arm.com 56011284Sandreas.hansson@arm.com 56111284Sandreas.hansson@arm.comKvmVM * 56211284Sandreas.hansson@arm.comKvmVMParams::create() 56311284Sandreas.hansson@arm.com{ 56411284Sandreas.hansson@arm.com static bool created = false; 56511284Sandreas.hansson@arm.com if (created) 56611284Sandreas.hansson@arm.com warn_once("Use of multiple KvmVMs is currently untested!\n"); 56711284Sandreas.hansson@arm.com 56811284Sandreas.hansson@arm.com created = true; 56911284Sandreas.hansson@arm.com 57011284Sandreas.hansson@arm.com return new KvmVM(this); 57111284Sandreas.hansson@arm.com} 57211284Sandreas.hansson@arm.com