19883Sandreas@sandberg.pp.se/* 29883Sandreas@sandberg.pp.se * Copyright (c) 2013 Andreas Sandberg 39883Sandreas@sandberg.pp.se * All rights reserved 49883Sandreas@sandberg.pp.se * 59883Sandreas@sandberg.pp.se * Redistribution and use in source and binary forms, with or without 69883Sandreas@sandberg.pp.se * modification, are permitted provided that the following conditions are 79883Sandreas@sandberg.pp.se * met: redistributions of source code must retain the above copyright 89883Sandreas@sandberg.pp.se * notice, this list of conditions and the following disclaimer; 99883Sandreas@sandberg.pp.se * redistributions in binary form must reproduce the above copyright 109883Sandreas@sandberg.pp.se * notice, this list of conditions and the following disclaimer in the 119883Sandreas@sandberg.pp.se * documentation and/or other materials provided with the distribution; 129883Sandreas@sandberg.pp.se * neither the name of the copyright holders nor the names of its 139883Sandreas@sandberg.pp.se * contributors may be used to endorse or promote products derived from 149883Sandreas@sandberg.pp.se * this software without specific prior written permission. 159883Sandreas@sandberg.pp.se * 169883Sandreas@sandberg.pp.se * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179883Sandreas@sandberg.pp.se * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189883Sandreas@sandberg.pp.se * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199883Sandreas@sandberg.pp.se * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209883Sandreas@sandberg.pp.se * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219883Sandreas@sandberg.pp.se * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229883Sandreas@sandberg.pp.se * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239883Sandreas@sandberg.pp.se * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249883Sandreas@sandberg.pp.se * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259883Sandreas@sandberg.pp.se * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269883Sandreas@sandberg.pp.se * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279883Sandreas@sandberg.pp.se * 289883Sandreas@sandberg.pp.se * Authors: Andreas Sandberg 299883Sandreas@sandberg.pp.se */ 309883Sandreas@sandberg.pp.se 319883Sandreas@sandberg.pp.se#ifndef __CPU_KVM_X86_CPU_HH__ 329883Sandreas@sandberg.pp.se#define __CPU_KVM_X86_CPU_HH__ 339883Sandreas@sandberg.pp.se 349883Sandreas@sandberg.pp.se#include "cpu/kvm/base.hh" 359883Sandreas@sandberg.pp.se#include "cpu/kvm/vm.hh" 369883Sandreas@sandberg.pp.se#include "params/X86KvmCPU.hh" 379883Sandreas@sandberg.pp.se 389883Sandreas@sandberg.pp.se/** 399883Sandreas@sandberg.pp.se * x86 implementation of a KVM-based hardware virtualized CPU. 409883Sandreas@sandberg.pp.se */ 419883Sandreas@sandberg.pp.seclass X86KvmCPU : public BaseKvmCPU 429883Sandreas@sandberg.pp.se{ 439883Sandreas@sandberg.pp.se public: 449883Sandreas@sandberg.pp.se X86KvmCPU(X86KvmCPUParams *params); 459883Sandreas@sandberg.pp.se virtual ~X86KvmCPU(); 469883Sandreas@sandberg.pp.se 4711341Sandreas.hansson@arm.com void startup() override; 489883Sandreas@sandberg.pp.se 499883Sandreas@sandberg.pp.se /** @{ */ 5011168Sandreas.hansson@arm.com void dump() const override; 519883Sandreas@sandberg.pp.se void dumpFpuRegs() const; 529883Sandreas@sandberg.pp.se void dumpIntRegs() const; 539883Sandreas@sandberg.pp.se void dumpSpecRegs() const; 549883Sandreas@sandberg.pp.se void dumpDebugRegs() const; 559883Sandreas@sandberg.pp.se void dumpXCRs() const; 569883Sandreas@sandberg.pp.se void dumpXSave() const; 579883Sandreas@sandberg.pp.se void dumpVCpuEvents() const; 589883Sandreas@sandberg.pp.se void dumpMSRs() const; 599883Sandreas@sandberg.pp.se /** @} */ 609883Sandreas@sandberg.pp.se 619883Sandreas@sandberg.pp.se protected: 629883Sandreas@sandberg.pp.se typedef std::vector<struct kvm_msr_entry> KvmMSRVector; 639883Sandreas@sandberg.pp.se 6411341Sandreas.hansson@arm.com Tick kvmRun(Tick ticks) override; 659883Sandreas@sandberg.pp.se 669883Sandreas@sandberg.pp.se /** 679883Sandreas@sandberg.pp.se * Run the virtual CPU until draining completes. 689883Sandreas@sandberg.pp.se * 699883Sandreas@sandberg.pp.se * In addition to the base functionality provided by 709883Sandreas@sandberg.pp.se * BaseKvmCPU::kvmRunDrain(), this method handles x86-specific 719883Sandreas@sandberg.pp.se * cases where there are pending interrupt events in the virtual 729883Sandreas@sandberg.pp.se * CPU. These are handled by requesting an interrupt window if 739883Sandreas@sandberg.pp.se * interrupts are pending (causing the vCPU to execute until 749883Sandreas@sandberg.pp.se * interrupts can be delivered again). 759883Sandreas@sandberg.pp.se * 769883Sandreas@sandberg.pp.se * @see BaseKvmCPU::kvmRunDrain() 779883Sandreas@sandberg.pp.se * @see archIsDrained() 789883Sandreas@sandberg.pp.se * 799883Sandreas@sandberg.pp.se * @return Number of ticks executed 809883Sandreas@sandberg.pp.se */ 8111341Sandreas.hansson@arm.com Tick kvmRunDrain() override; 829883Sandreas@sandberg.pp.se 839883Sandreas@sandberg.pp.se /** Wrapper that synchronizes state in kvm_run */ 849883Sandreas@sandberg.pp.se Tick kvmRunWrapper(Tick ticks); 859883Sandreas@sandberg.pp.se 8611341Sandreas.hansson@arm.com uint64_t getHostCycles() const override; 879883Sandreas@sandberg.pp.se 889883Sandreas@sandberg.pp.se /** 899883Sandreas@sandberg.pp.se * Methods to access CPUID information using the extended 909883Sandreas@sandberg.pp.se * API. Only available if Kvm::capExtendedCPUID() is true. 919883Sandreas@sandberg.pp.se * 929883Sandreas@sandberg.pp.se * @{ 939883Sandreas@sandberg.pp.se */ 949883Sandreas@sandberg.pp.se void setCPUID(const struct kvm_cpuid2 &cpuid); 959883Sandreas@sandberg.pp.se void setCPUID(const Kvm::CPUIDVector &cpuid); 969883Sandreas@sandberg.pp.se /** @} */ 979883Sandreas@sandberg.pp.se 989883Sandreas@sandberg.pp.se /** 999883Sandreas@sandberg.pp.se * Methods to access MSRs in the guest. 1009883Sandreas@sandberg.pp.se * 1019883Sandreas@sandberg.pp.se * @{ 1029883Sandreas@sandberg.pp.se */ 1039883Sandreas@sandberg.pp.se void setMSRs(const struct kvm_msrs &msrs); 1049883Sandreas@sandberg.pp.se void setMSRs(const KvmMSRVector &msrs); 1059883Sandreas@sandberg.pp.se void getMSRs(struct kvm_msrs &msrs) const; 1069883Sandreas@sandberg.pp.se void setMSR(uint32_t index, uint64_t value); 1079883Sandreas@sandberg.pp.se uint64_t getMSR(uint32_t index) const; 1089883Sandreas@sandberg.pp.se /** @} */ 1099883Sandreas@sandberg.pp.se 1109883Sandreas@sandberg.pp.se /** 1119883Sandreas@sandberg.pp.se * Get a list of MSRs supported by both gem5 and KVM. 1129883Sandreas@sandberg.pp.se * 1139883Sandreas@sandberg.pp.se * @note This method uses an internal cache and only generates the 1149883Sandreas@sandberg.pp.se * MSR list once. 1159883Sandreas@sandberg.pp.se * 1169883Sandreas@sandberg.pp.se * @return reference to a list of msr indices 1179883Sandreas@sandberg.pp.se */ 1189883Sandreas@sandberg.pp.se const Kvm::MSRIndexVector &getMsrIntersection() const; 1199883Sandreas@sandberg.pp.se 1209883Sandreas@sandberg.pp.se /** 1219883Sandreas@sandberg.pp.se * Wrappers around KVM's state transfer methods. 1229883Sandreas@sandberg.pp.se * 1239883Sandreas@sandberg.pp.se * @{ 1249883Sandreas@sandberg.pp.se */ 1259883Sandreas@sandberg.pp.se void getDebugRegisters(struct kvm_debugregs ®s) const; 1269883Sandreas@sandberg.pp.se void setDebugRegisters(const struct kvm_debugregs ®s); 1279883Sandreas@sandberg.pp.se void getXCRs(struct kvm_xcrs ®s) const; 1289883Sandreas@sandberg.pp.se void setXCRs(const struct kvm_xcrs ®s); 1299883Sandreas@sandberg.pp.se void getXSave(struct kvm_xsave &xsave) const; 1309883Sandreas@sandberg.pp.se void setXSave(const struct kvm_xsave &xsave); 1319883Sandreas@sandberg.pp.se void getVCpuEvents(struct kvm_vcpu_events &events) const; 1329883Sandreas@sandberg.pp.se void setVCpuEvents(const struct kvm_vcpu_events &events); 1339883Sandreas@sandberg.pp.se /** @} */ 1349883Sandreas@sandberg.pp.se 13511341Sandreas.hansson@arm.com void updateKvmState() override; 13611341Sandreas.hansson@arm.com void updateThreadContext() override; 1379883Sandreas@sandberg.pp.se 1389883Sandreas@sandberg.pp.se /** 1399883Sandreas@sandberg.pp.se * Inject pending interrupts from gem5 into the virtual CPU. 1409883Sandreas@sandberg.pp.se */ 1419883Sandreas@sandberg.pp.se void deliverInterrupts(); 1429883Sandreas@sandberg.pp.se 1439883Sandreas@sandberg.pp.se /** 1449883Sandreas@sandberg.pp.se * Handle x86 legacy IO (in/out) 1459883Sandreas@sandberg.pp.se */ 14611341Sandreas.hansson@arm.com Tick handleKvmExitIO() override; 1479883Sandreas@sandberg.pp.se 14811341Sandreas.hansson@arm.com Tick handleKvmExitIRQWindowOpen() override; 1499883Sandreas@sandberg.pp.se 1509883Sandreas@sandberg.pp.se /** 1519883Sandreas@sandberg.pp.se * Check if there are pending events in the vCPU that prevents it 1529883Sandreas@sandberg.pp.se * from being drained. 1539883Sandreas@sandberg.pp.se * 1549883Sandreas@sandberg.pp.se * There are cases after interrupt injection where the interrupt 1559883Sandreas@sandberg.pp.se * is still pending in the guest. This method detects such cases 1569883Sandreas@sandberg.pp.se * and requests additional draining. 1579883Sandreas@sandberg.pp.se * 1589883Sandreas@sandberg.pp.se * @return False if there are pending events in the guest, True 1599883Sandreas@sandberg.pp.se * otherwise. 1609883Sandreas@sandberg.pp.se */ 16111341Sandreas.hansson@arm.com bool archIsDrained() const override; 1629883Sandreas@sandberg.pp.se 1639883Sandreas@sandberg.pp.se private: 1649883Sandreas@sandberg.pp.se /** 1659883Sandreas@sandberg.pp.se * Support routines to update the state of the KVM CPU from gem5's 1669883Sandreas@sandberg.pp.se * state representation. 1679883Sandreas@sandberg.pp.se * 1689883Sandreas@sandberg.pp.se * @{ 1699883Sandreas@sandberg.pp.se */ 1709883Sandreas@sandberg.pp.se /** Update integer registers */ 1719883Sandreas@sandberg.pp.se void updateKvmStateRegs(); 1729883Sandreas@sandberg.pp.se /** Update control registers (CRx, segments, etc.) */ 1739883Sandreas@sandberg.pp.se void updateKvmStateSRegs(); 1749890Sandreas@sandberg.pp.se /** 1759890Sandreas@sandberg.pp.se * Update FPU and SIMD registers 1769890Sandreas@sandberg.pp.se * 1779890Sandreas@sandberg.pp.se * This method uses the appropriate (depending on availability and 1789890Sandreas@sandberg.pp.se * user configuration) kernel API by calling 1799890Sandreas@sandberg.pp.se * updateKvmStateFPULegacy() or updateKvmStateFPUXSave(). 1809890Sandreas@sandberg.pp.se * 1819890Sandreas@sandberg.pp.se * @see updateKvmStateFPULegacy() 1829890Sandreas@sandberg.pp.se * @see updateKvmStateFPUXSave() 1839890Sandreas@sandberg.pp.se */ 1849883Sandreas@sandberg.pp.se void updateKvmStateFPU(); 1859890Sandreas@sandberg.pp.se /** 1869890Sandreas@sandberg.pp.se * Update FPU and SIMD registers using the legacy API 1879890Sandreas@sandberg.pp.se * 1889890Sandreas@sandberg.pp.se * @note This method should normally only be called by 1899890Sandreas@sandberg.pp.se * updateKvmStateFPU() which automatically chooses between 1909890Sandreas@sandberg.pp.se * available APIs. 1919890Sandreas@sandberg.pp.se */ 1929890Sandreas@sandberg.pp.se void updateKvmStateFPULegacy(); 1939890Sandreas@sandberg.pp.se /** 1949890Sandreas@sandberg.pp.se * Update FPU and SIMD registers using the XSave API 1959890Sandreas@sandberg.pp.se * 1969890Sandreas@sandberg.pp.se * @note This method should normally only be called by 1979890Sandreas@sandberg.pp.se * updateKvmStateFPU() which automatically chooses between 1989890Sandreas@sandberg.pp.se * available APIs. 1999890Sandreas@sandberg.pp.se */ 2009890Sandreas@sandberg.pp.se void updateKvmStateFPUXSave(); 2019883Sandreas@sandberg.pp.se /** Update MSR registers */ 2029883Sandreas@sandberg.pp.se void updateKvmStateMSRs(); 2039883Sandreas@sandberg.pp.se /** @} */ 2049883Sandreas@sandberg.pp.se 2059883Sandreas@sandberg.pp.se /** 2069883Sandreas@sandberg.pp.se * Support routines to update the state of gem5's thread context from 2079883Sandreas@sandberg.pp.se * KVM's state representation. 2089883Sandreas@sandberg.pp.se * 2099883Sandreas@sandberg.pp.se * @{ 2109883Sandreas@sandberg.pp.se */ 2119883Sandreas@sandberg.pp.se /** Update integer registers */ 21210113Sandreas@sandberg.pp.se void updateThreadContextRegs(const struct kvm_regs ®s, 21310113Sandreas@sandberg.pp.se const struct kvm_sregs &sregs); 2149883Sandreas@sandberg.pp.se /** Update control registers (CRx, segments, etc.) */ 21510113Sandreas@sandberg.pp.se void updateThreadContextSRegs(const struct kvm_sregs &sregs); 2169890Sandreas@sandberg.pp.se /** Update FPU and SIMD registers using the legacy API */ 21710113Sandreas@sandberg.pp.se void updateThreadContextFPU(const struct kvm_fpu &fpu); 2189890Sandreas@sandberg.pp.se /** Update FPU and SIMD registers using the XSave API */ 21910113Sandreas@sandberg.pp.se void updateThreadContextXSave(const struct kvm_xsave &kxsave); 2209883Sandreas@sandberg.pp.se /** Update MSR registers */ 2219883Sandreas@sandberg.pp.se void updateThreadContextMSRs(); 2229883Sandreas@sandberg.pp.se /** @} */ 2239883Sandreas@sandberg.pp.se 2249883Sandreas@sandberg.pp.se /** Transfer gem5's CPUID values into the virtual CPU. */ 2259883Sandreas@sandberg.pp.se void updateCPUID(); 2269883Sandreas@sandberg.pp.se 2279883Sandreas@sandberg.pp.se /** 2289883Sandreas@sandberg.pp.se * Handle a 32-bit IO access that should be mapped to a MiscReg. 2299883Sandreas@sandberg.pp.se * 2309883Sandreas@sandberg.pp.se * @note This method can only be called on when handling IO after 2319883Sandreas@sandberg.pp.se * a KVM_EXIT_IO. 2329883Sandreas@sandberg.pp.se * 2339883Sandreas@sandberg.pp.se * @param miscreg Register to map the current IO access to. 2349883Sandreas@sandberg.pp.se */ 2359883Sandreas@sandberg.pp.se void handleIOMiscReg32(int miscreg); 2369883Sandreas@sandberg.pp.se 2379883Sandreas@sandberg.pp.se /** Cached intersection of supported MSRs */ 2389883Sandreas@sandberg.pp.se mutable Kvm::MSRIndexVector cachedMsrIntersection; 2399883Sandreas@sandberg.pp.se 2409883Sandreas@sandberg.pp.se /** @{ */ 2419883Sandreas@sandberg.pp.se /** Kvm::capDebugRegs() available? */ 2429883Sandreas@sandberg.pp.se bool haveDebugRegs; 2439883Sandreas@sandberg.pp.se /** Kvm::capXSave() available? */ 2449883Sandreas@sandberg.pp.se bool haveXSave; 2459890Sandreas@sandberg.pp.se /** 2469890Sandreas@sandberg.pp.se * Should the XSave interface be used to sync the FPU and SIMD 2479890Sandreas@sandberg.pp.se * registers? 2489890Sandreas@sandberg.pp.se */ 2499890Sandreas@sandberg.pp.se bool useXSave; 2509883Sandreas@sandberg.pp.se /** Kvm::capXCRs() available? */ 2519883Sandreas@sandberg.pp.se bool haveXCRs; 2529883Sandreas@sandberg.pp.se /** @} */ 2539883Sandreas@sandberg.pp.se}; 2549883Sandreas@sandberg.pp.se 2559883Sandreas@sandberg.pp.se#endif 256