19657SN/A/*
29657SN/A * Copyright (c) 2012 ARM Limited
39657SN/A * All rights reserved
49657SN/A *
59657SN/A * The license below extends only to copyright in the software and shall
69657SN/A * not be construed as granting a license to any other intellectual
79657SN/A * property including but not limited to intellectual property relating
89657SN/A * to a hardware implementation of the functionality of the software
99657SN/A * licensed hereunder.  You may use the software subject to the license
109657SN/A * terms below provided that you ensure that this notice is replicated
119657SN/A * unmodified and in its entirety in all distributions of the software,
129657SN/A * modified or unmodified, in source code or in binary form.
139657SN/A *
149657SN/A * Redistribution and use in source and binary forms, with or without
159657SN/A * modification, are permitted provided that the following conditions are
169657SN/A * met: redistributions of source code must retain the above copyright
179657SN/A * notice, this list of conditions and the following disclaimer;
189657SN/A * redistributions in binary form must reproduce the above copyright
199657SN/A * notice, this list of conditions and the following disclaimer in the
209657SN/A * documentation and/or other materials provided with the distribution;
219657SN/A * neither the name of the copyright holders nor the names of its
229657SN/A * contributors may be used to endorse or promote products derived from
239657SN/A * this software without specific prior written permission.
249657SN/A *
259657SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269657SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279657SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289657SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299657SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309657SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319657SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329657SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339657SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349657SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359657SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369657SN/A *
379657SN/A * Authors: Andreas Sandberg
389657SN/A */
399657SN/A
4010857Sandreas.sandberg@arm.com#ifndef __ARCH_ARM_KVM_ARM_CPU_HH__
4110857Sandreas.sandberg@arm.com#define __ARCH_ARM_KVM_ARM_CPU_HH__
429657SN/A
439657SN/A#include <set>
449657SN/A#include <vector>
459657SN/A
469657SN/A#include "cpu/kvm/base.hh"
479657SN/A#include "params/ArmKvmCPU.hh"
489657SN/A
499657SN/A/**
509657SN/A * ARM implementation of a KVM-based hardware virtualized CPU.
519657SN/A * Architecture specific limitations:
529657SN/A *  * LPAE is currently not supported by gem5. We therefore panic if LPAE
539657SN/A *    is enabled when returning to gem5.
549657SN/A *  * The co-processor based interface to the architected timer is
559657SN/A *    unsupported. We can't support this due to limitations in the KVM
569657SN/A *    API on ARM.
579657SN/A *  * M5 ops are currently not supported. This requires either a kernel
589657SN/A *  hack or a memory mapped device that handles the guest<->m5
599657SN/A *  interface.
609657SN/A */
619657SN/Aclass ArmKvmCPU : public BaseKvmCPU
629657SN/A{
639657SN/A  public:
649657SN/A    ArmKvmCPU(ArmKvmCPUParams *params);
659657SN/A    virtual ~ArmKvmCPU();
669657SN/A
679657SN/A    void startup();
689657SN/A
699658SN/A    void dump();
709658SN/A
719657SN/A  protected:
729657SN/A    struct KvmIntRegInfo {
739657SN/A        /** KVM ID */
749657SN/A        const uint64_t id;
759657SN/A        /** gem5 index */
769657SN/A        const IntRegIndex idx;
779657SN/A        /** Name in debug output */
789657SN/A        const char *name;
799657SN/A    };
809657SN/A
819657SN/A    struct KvmCoreMiscRegInfo {
829657SN/A        /** KVM ID */
839657SN/A        const uint64_t id;
849657SN/A        /** gem5 index */
859657SN/A        const MiscRegIndex idx;
869657SN/A        /** Name in debug output */
879657SN/A        const char *name;
889657SN/A    };
899657SN/A
909657SN/A    typedef std::vector<uint64_t> RegIndexVector;
919657SN/A
929753SN/A    Tick kvmRun(Tick ticks);
939657SN/A
949657SN/A    void updateKvmState();
959657SN/A    void updateThreadContext();
969657SN/A
979660SN/A    Tick onKvmExitHypercall();
989660SN/A
999657SN/A    /**
1009657SN/A     * Get a list of registers supported by getOneReg() and setOneReg().
1019657SN/A     */
1029657SN/A    const RegIndexVector &getRegList() const;
1039657SN/A
1049657SN/A    void kvmArmVCpuInit(uint32_t target);
1059657SN/A    void kvmArmVCpuInit(const struct kvm_vcpu_init &init);
1069657SN/A
1079657SN/A    ArmISA::MiscRegIndex decodeCoProcReg(uint64_t id) const;
1089657SN/A
1099657SN/A    ArmISA::MiscRegIndex decodeVFPCtrlReg(uint64_t id) const;
1109657SN/A
1119657SN/A    /**
1129657SN/A     * Determine if a register is invariant.
1139657SN/A     *
1149657SN/A     * Some registers must have the same value in both the host and
1159657SN/A     * the guest. Such registers are referred to as "invariant"
1169657SN/A     * registers in KVM. This is a restriction imposed by KVM as
1179657SN/A     * having different values in ID registers (e.g., the cache
1189657SN/A     * identification registers) would confuse the guest kernel.
1199657SN/A     */
1209657SN/A    bool isInvariantReg(uint64_t id);
1219657SN/A
1229657SN/A    static KvmIntRegInfo kvmIntRegs[];
1239657SN/A    static KvmCoreMiscRegInfo kvmCoreMiscRegs[];
1249657SN/A
1259657SN/A  private:
1269657SN/A    /**
1279657SN/A     * Get a list of registers supported by getOneReg() and setOneReg().
1289657SN/A     *
1299657SN/A     * @return False if the number of elements allocated in the list
1309657SN/A     * is too small to hold the complete register list (the required
1319657SN/A     * value is written into n in this case). True on success.
1329657SN/A     */
1339657SN/A    bool getRegList(struct kvm_reg_list &regs) const;
1349657SN/A
1359658SN/A    void dumpKvmStateCore();
1369658SN/A    void dumpKvmStateMisc();
1379658SN/A    void dumpKvmStateCoProc(uint64_t id);
1389658SN/A    void dumpKvmStateVFP(uint64_t id);
1399658SN/A
1409657SN/A    void updateKvmStateCore();
1419657SN/A    void updateKvmStateMisc();
1429657SN/A    void updateKvmStateCoProc(uint64_t id, bool show_warnings);
1439657SN/A    void updateKvmStateVFP(uint64_t id, bool show_warnings);
1449657SN/A
1459657SN/A    void updateTCStateCore();
1469657SN/A    void updateTCStateMisc();
1479657SN/A    void updateTCStateCoProc(uint64_t id, bool show_warnings);
1489657SN/A    void updateTCStateVFP(uint64_t id, bool show_warnings);
1499657SN/A
1509657SN/A
1519657SN/A    /** Cached state of the IRQ line */
1529657SN/A    bool irqAsserted;
1539657SN/A    /** Cached state of the FIQ line */
1549657SN/A    bool fiqAsserted;
1559657SN/A
1569657SN/A    /**
1579657SN/A     * Cached copy of the list of co-processor registers supported by
1589657SN/A     * KVM
1599657SN/A     */
1609657SN/A    mutable RegIndexVector _regIndexList;
1619657SN/A
1629657SN/A    /**
1639657SN/A     * List of co-processor registers that KVM requires to be
1649657SN/A     * identical on both the host and the guest. KVM does not allow
1659657SN/A     * writes to these registers.
1669657SN/A     */
1679657SN/A    static const std::set<uint64_t> invariant_regs;
1689657SN/A};
1699657SN/A
17010857Sandreas.sandberg@arm.com#endif // __ARCH_ARM_KVM_ARM_CPU_HH__
171