vm.hh revision 11363:f3f72c0ab03e
1/*
2 * Copyright 2014 Google, Inc.
3 * Copyright (c) 2012, 2015 ARM Limited
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder.  You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are
17 * met: redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer;
19 * redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution;
22 * neither the name of the copyright holders nor the names of its
23 * contributors may be used to endorse or promote products derived from
24 * this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * Authors: Andreas Sandberg
39 */
40
41#ifndef __CPU_KVM_KVMVM_HH__
42#define __CPU_KVM_KVMVM_HH__
43
44#include <vector>
45
46#include "base/addr_range.hh"
47#include "sim/sim_object.hh"
48
49// forward declarations
50struct KvmVMParams;
51class System;
52
53/**
54 * @defgroup KvmInterrupts KVM Interrupt handling.
55 *
56 * These methods control interrupt delivery to the guest system.
57 */
58
59/**
60 * @defgroup KvmIoctl KVM low-level ioctl interface.
61 *
62 * These methods provide a low-level interface to the underlying KVM
63 * layer.
64 */
65
66/**
67 * KVM parent interface
68 *
69 * The main Kvm object is used to provide functionality that is not
70 * specific to a VM or CPU. For example, it allows checking of the
71 * optional features and creation of VM containers.
72 */
73class Kvm
74{
75    friend class KvmVM;
76
77  public:
78    virtual ~Kvm();
79
80    Kvm *create();
81
82    /** Get the version of the KVM API implemented by the kernel. */
83    int getAPIVersion() const { return apiVersion; }
84    /**
85     * Get the size of the MMAPed parameter area used to communicate
86     * vCPU parameters between the kernel and userspace. This area,
87     * amongst other things, contains the kvm_run data structure.
88     */
89    int getVCPUMMapSize() const { return vcpuMMapSize; }
90
91    /** @{ */
92    /** Support for KvmVM::setUserMemoryRegion() */
93    bool capUserMemory() const;
94    /** Support for KvmVM::setTSSAddress() */
95    bool capSetTSSAddress() const;
96    /** Support for BaseKvmCPU::setCPUID2 and getSupportedCPUID(). */
97    bool capExtendedCPUID() const;
98    /** Support for BaseKvmCPU::kvmNonMaskableInterrupt(). */
99    bool capUserNMI() const;
100
101    /**
102     * Check if coalesced MMIO is supported and which page in the
103     * MMAP'ed structure it stores requests in.
104     *
105     * @return Offset (in pages) into the mmap'ed vCPU area where the
106     * MMIO buffer is stored. 0 if unsupported.
107     */
108    int capCoalescedMMIO() const;
109
110    /**
111     * Attempt to determine how many memory slots are available. If it can't
112     * be determined, this function returns 0.
113     */
114    int capNumMemSlots() const;
115
116    /**
117     * Support for reading and writing single registers.
118     *
119     * @see BaseKvmCPU::getOneReg(), and BaseKvmCPU::setOneReg()
120     */
121    bool capOneReg() const;
122
123    /**
124     * Support for creating an in-kernel IRQ chip model.
125     *
126     * @see KvmVM::createIRQChip()
127     */
128    bool capIRQChip() const;
129
130    /** Support for getting and setting the kvm_vcpu_events structure. */
131    bool capVCPUEvents() const;
132
133    /** Support for getting and setting the kvm_debugregs structure. */
134    bool capDebugRegs() const;
135
136    /** Support for getting and setting the x86 XCRs. */
137    bool capXCRs() const;
138
139    /** Support for getting and setting the kvm_xsave structure. */
140    bool capXSave() const;
141    /** @} */
142
143#if defined(__i386__) || defined(__x86_64__)
144  public: // x86-specific
145    /**
146     * @{
147     * @name X86-specific APIs
148     */
149
150    typedef std::vector<struct kvm_cpuid_entry2> CPUIDVector;
151    typedef std::vector<uint32_t> MSRIndexVector;
152
153    /**
154     * Get the CPUID features supported by the hardware and Kvm.
155     *
156     * @note Requires capExtendedCPUID().
157     *
158     * @return False if the allocation is too small, true on success.
159     */
160    bool getSupportedCPUID(struct kvm_cpuid2 &cpuid) const;
161
162    /**
163     * Get the CPUID features supported by the hardware and Kvm.
164     *
165     * @note Requires capExtendedCPUID().
166     *
167     * @note This method uses an internal cache to minimize the number
168     * of calls into the kernel.
169     *
170     * @return Reference to cached MSR index list.
171     */
172    const CPUIDVector &getSupportedCPUID() const;
173
174    /**
175     * Get the MSRs supported by the hardware and Kvm.
176     *
177     * @return False if the allocation is too small, true on success.
178     */
179    bool getSupportedMSRs(struct kvm_msr_list &msrs) const;
180
181    /**
182     * Get the MSRs supported by the hardware and Kvm.
183     *
184     * @note This method uses an internal cache to minimize the number
185     * of calls into the kernel.
186     *
187     * @return Reference to cached MSR index list.
188     */
189    const MSRIndexVector &getSupportedMSRs() const;
190
191  private: // x86-specific
192    /** Cached vector of supported CPUID entries. */
193    mutable CPUIDVector supportedCPUIDCache;
194
195    /** Cached vector of supported MSRs. */
196    mutable MSRIndexVector supportedMSRCache;
197
198
199    /** @} */
200#endif
201
202  protected:
203    /**
204     * Check for the presence of an extension to the KVM API.
205     *
206     * The return value depends on the extension, but is always zero
207     * if it is unsupported or positive otherwise. Some extensions use
208     * the return value provide additional data about the extension.
209     *
210     * @return 0 if the extension is unsupported, positive integer
211     * otherwise.
212     */
213    int checkExtension(int extension) const;
214
215    /**
216     * @addtogroup KvmIoctl
217     * @{
218     */
219    /**
220     * Main VM ioctl interface.
221     *
222     * @param request KVM request
223     * @param p1 Optional request parameter
224     *
225     * @return -1 on error (error number in errno), ioctl dependent
226     * value otherwise.
227     */
228    int ioctl(int request, long p1) const;
229    int ioctl(int request, void *p1) const {
230        return ioctl(request, (long)p1);
231    }
232    int ioctl(int request) const {
233        return ioctl(request, 0L);
234    }
235    /** @} */
236
237  private:
238    // This object is a singleton, so prevent instantiation.
239    Kvm();
240
241    // Prevent copying
242    Kvm(const Kvm &kvm);
243    // Prevent assignment
244    Kvm &operator=(const Kvm &kvm);
245
246    /**
247     * Create a KVM Virtual Machine
248     *
249     * @return File descriptor pointing to the VM
250     */
251    int createVM();
252
253    /** KVM VM file descriptor */
254    int kvmFD;
255    /** KVM API version */
256    int apiVersion;
257    /** Size of the MMAPed vCPU parameter area. */
258    int vcpuMMapSize;
259
260    /** Singleton instance */
261    static Kvm *instance;
262};
263
264/**
265 * KVM VM container
266 *
267 * A KVM VM container normally contains all the CPUs in a shared
268 * memory machine. The VM container handles things like physical
269 * memory and to some extent interrupts. Normally, the VM API is only
270 * used for interrupts when the PIC is emulated by the kernel, which
271 * is a feature we do not use. However, some architectures (notably
272 * ARM) use the VM interface to deliver interrupts to specific CPUs as
273 * well.
274 *
275 * VM initialization is a bit different from that of other
276 * SimObjects. When we initialize the VM, we discover all physical
277 * memory mappings in the system. Since AbstractMem::unserialize
278 * re-maps the guests memory, we need to make sure that this is done
279 * after the memory has been re-mapped, but before the vCPUs are
280 * initialized (KVM requires memory mappings to be setup before CPUs
281 * can be created). Normally, we would just initialize the VM in
282 * init() or startup(), however, we can not use init() since this is
283 * called before AbstractMem::unserialize() and we can not use
284 * startup() since it must be called before BaseKvmCPU::startup() and
285 * the simulator framework does not guarantee call order. We therefore
286 * call cpuStartup() from BaseKvmCPU::startup() instead and execute
287 * the initialization code once when the first CPU in the VM is
288 * starting.
289 */
290class KvmVM : public SimObject
291{
292    friend class BaseKvmCPU;
293
294  public:
295    KvmVM(KvmVMParams *params);
296    virtual ~KvmVM();
297
298    void notifyFork();
299
300    /**
301     * Setup a shared three-page memory region used by the internals
302     * of KVM. This is currently only needed by x86 implementations.
303     *
304     * @param tss_address Physical address of the start of the TSS
305     */
306    void setTSSAddress(Addr tss_address);
307
308    /** @{ */
309    /**
310     * Request coalescing MMIO for a memory range.
311     *
312     * @param start Physical start address in guest
313     * @param size Size of the MMIO region
314     */
315    void coalesceMMIO(Addr start, int size);
316
317    /**
318     * Request coalescing MMIO for a memory range.
319     *
320     * @param range Coalesced MMIO range
321     */
322    void coalesceMMIO(const AddrRange &range);
323    /** @} */
324
325    /**
326     * @addtogroup KvmInterrupts
327     * @{
328     */
329    /**
330     * Create an in-kernel interrupt  controller
331     *
332     * @note This functionality depends on Kvm::capIRQChip().
333     */
334    void createIRQChip();
335
336    /**
337     * Set the status of an IRQ line using KVM_IRQ_LINE.
338     *
339     * @note This ioctl is usually only used if the interrupt
340     * controller is emulated by the kernel (i.e., after calling
341     * createIRQChip()). Some architectures (e.g., ARM) use it instead
342     * of BaseKvmCPU::kvmInterrupt().
343     *
344     * @param irq Interrupt number
345     * @param high Line level (true for high, false for low)
346     */
347    void setIRQLine(uint32_t irq, bool high);
348
349    /**
350     * Is in-kernel IRQ chip emulation enabled?
351     */
352    bool hasKernelIRQChip() const { return _hasKernelIRQChip; }
353    /** @} */
354
355    struct MemSlot
356    {
357        MemSlot(uint32_t _num) : num(_num)
358        {}
359        MemSlot() : num(-1)
360        {}
361
362        int32_t num;
363    };
364
365    /**
366     *  Allocate a memory slot within the VM.
367     */
368    const MemSlot allocMemSlot(uint64_t size);
369
370    /**
371     * Setup a region of physical memory in the guest
372     *
373     * @param slot KVM memory slot ID returned by allocMemSlot
374     * @param host_addr Memory allocation backing the memory
375     * @param guest_addr Address in the guest
376     * @param flags Flags (see the KVM API documentation)
377     */
378    void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr,
379                      uint32_t flags);
380
381    /**
382     * Disable a memory slot.
383     */
384    void disableMemSlot(const MemSlot slot);
385
386    /**
387     *  Free a previously allocated memory slot.
388     */
389    void freeMemSlot(const MemSlot slot);
390
391    /**
392     * Create an in-kernel device model.
393     *
394     * @param type Device type (KVM_DEV_TYPE_xxx)
395     * @param flags Creation flags (KVM_CREATE_DEVICE_xxx)
396     * @return Device file descriptor
397     */
398    int createDevice(uint32_t type, uint32_t flags = 0);
399
400    /** Global KVM interface */
401    Kvm *kvm;
402
403#if defined(__aarch64__)
404  public: // ARM-specific
405    /**
406     * Ask the kernel for the preferred CPU target to simulate.
407     *
408     * When creating an ARM vCPU in Kvm, we need to initialize it with
409     * a call to BaseArmKvmCPU::kvmArmVCpuInit(). When calling this
410     * function, we need to know what type of CPU the host has. This
411     * call sets up the kvm_vcpu_init structure with the values the
412     * kernel wants.
413     *
414     * @param[out] target Target structure to initialize.
415     */
416    void kvmArmPreferredTarget(struct kvm_vcpu_init &target) const;
417
418#endif
419
420  protected:
421    /**
422     * VM CPU initialization code.
423     *
424     * This method is called from BaseKvmCPU::startup() when a CPU in
425     * the VM executes its BaseKvmCPU::startup() method. The first
426     * time method is executed on a VM, it calls the delayedStartup()
427     * method.
428     */
429    void cpuStartup();
430
431    /**
432     * Delayed initialization, executed once before the first CPU
433     * starts.
434     *
435     * This method provides a way to do VM initialization once before
436     * the first CPU in a VM starts. It is needed since some resources
437     * (e.g., memory mappings) can change in the normal
438     * SimObject::startup() path. Since the call order of
439     * SimObject::startup() is not guaranteed, we simply defer some
440     * initialization until a CPU is about to start.
441     */
442    void delayedStartup();
443
444
445    /** @{ */
446    /**
447     * Setup a region of physical memory in the guest
448     *
449     * @param slot KVM memory slot ID (must be unique)
450     * @param host_addr Memory allocation backing the memory
451     * @param guest_addr Address in the guest
452     * @param len Size of the allocation in bytes
453     * @param flags Flags (see the KVM API documentation)
454     */
455    void setUserMemoryRegion(uint32_t slot,
456                             void *host_addr, Addr guest_addr,
457                             uint64_t len, uint32_t flags);
458    /** @} */
459
460    /**
461     * Create a new vCPU within a VM.
462     *
463     * @param vcpuID ID of the new CPU within the VM.
464     * @return File descriptor referencing the CPU.
465     */
466    int createVCPU(long vcpuID);
467
468    /**
469     * Allocate a new vCPU ID within the VM.
470     *
471     * The returned vCPU ID is guaranteed to be unique within the
472     * VM. New IDs are allocated sequentially starting from 0.
473     *
474     * @return ID of the new vCPU
475     */
476    long allocVCPUID();
477
478    /**
479     * @addtogroup KvmIoctl
480     * @{
481     */
482    /**
483     * KVM VM ioctl interface.
484     *
485     * @param request KVM VM request
486     * @param p1 Optional request parameter
487     *
488     * @return -1 on error (error number in errno), ioctl dependent
489     * value otherwise.
490     */
491    int ioctl(int request, long p1) const;
492    int ioctl(int request, void *p1) const {
493        return ioctl(request, (long)p1);
494    }
495    int ioctl(int request) const {
496        return ioctl(request, 0L);
497    }
498    /**@}*/
499
500  private:
501    // Prevent copying
502    KvmVM(const KvmVM &vm);
503    // Prevent assignment
504    KvmVM &operator=(const KvmVM &vm);
505
506    System *system;
507
508    /** KVM VM file descriptor */
509    int vmFD;
510
511    /** Has delayedStartup() already been called? */
512    bool started;
513
514    /** Do we have in-kernel IRQ-chip emulation enabled? */
515    bool _hasKernelIRQChip;
516
517    /** Next unallocated vCPU ID */
518    long nextVCPUID;
519
520    /**
521     *  Structures tracking memory slots.
522     */
523    class MemorySlot
524    {
525      public:
526        uint64_t size;
527        uint32_t slot;
528        bool active;
529    };
530    std::vector<MemorySlot> memorySlots;
531    uint32_t maxMemorySlot;
532};
533
534#endif
535