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