mem: Clean up Request initialisation
[gem5.git] / src / cpu / kvm / vm.hh
1 /*
2 * Copyright 2014 Google, Inc.
3 * Copyright (c) 2012 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
50 struct KvmVMParams;
51 class 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 */
73 class Kvm
74 {
75 friend class KvmVM;
76
77 public:
78 typedef std::vector<struct kvm_cpuid_entry2> CPUIDVector;
79 typedef std::vector<uint32_t> MSRIndexVector;
80
81 virtual ~Kvm();
82
83 Kvm *create();
84
85 /** Get the version of the KVM API implemented by the kernel. */
86 int getAPIVersion() const { return apiVersion; }
87 /**
88 * Get the size of the MMAPed parameter area used to communicate
89 * vCPU parameters between the kernel and userspace. This area,
90 * amongst other things, contains the kvm_run data structure.
91 */
92 int getVCPUMMapSize() const { return vcpuMMapSize; }
93
94 /** @{ */
95 /** Support for KvmVM::setUserMemoryRegion() */
96 bool capUserMemory() const;
97 /** Support for KvmVM::setTSSAddress() */
98 bool capSetTSSAddress() const;
99 /** Support for BaseKvmCPU::setCPUID2 and getSupportedCPUID(). */
100 bool capExtendedCPUID() const;
101 /** Support for BaseKvmCPU::kvmNonMaskableInterrupt(). */
102 bool capUserNMI() const;
103
104 /**
105 * Check if coalesced MMIO is supported and which page in the
106 * MMAP'ed structure it stores requests in.
107 *
108 * @return Offset (in pages) into the mmap'ed vCPU area where the
109 * MMIO buffer is stored. 0 if unsupported.
110 */
111 int capCoalescedMMIO() const;
112
113 /**
114 * Attempt to determine how many memory slots are available. If it can't
115 * be determined, this function returns 0.
116 */
117 int capNumMemSlots() const;
118
119 /**
120 * Support for reading and writing single registers.
121 *
122 * @see BaseKvmCPU::getOneReg(), and BaseKvmCPU::setOneReg()
123 */
124 bool capOneReg() const;
125
126 /**
127 * Support for creating an in-kernel IRQ chip model.
128 *
129 * @see KvmVM::createIRQChip()
130 */
131 bool capIRQChip() const;
132
133 /** Support for getting and setting the kvm_vcpu_events structure. */
134 bool capVCPUEvents() const;
135
136 /** Support for getting and setting the kvm_debugregs structure. */
137 bool capDebugRegs() const;
138
139 /** Support for getting and setting the x86 XCRs. */
140 bool capXCRs() const;
141
142 /** Support for getting and setting the kvm_xsave structure. */
143 bool capXSave() const;
144 /** @} */
145
146 /**
147 * Get the CPUID features supported by the hardware and Kvm.
148 *
149 * @note Requires capExtendedCPUID().
150 *
151 * @return False if the allocation is too small, true on success.
152 */
153 bool getSupportedCPUID(struct kvm_cpuid2 &cpuid) const;
154
155 /**
156 * Get the CPUID features supported by the hardware and Kvm.
157 *
158 * @note Requires capExtendedCPUID().
159 *
160 * @note This method uses an internal cache to minimize the number
161 * of calls into the kernel.
162 *
163 * @return Reference to cached MSR index list.
164 */
165 const CPUIDVector &getSupportedCPUID() const;
166
167 /**
168 * Get the MSRs supported by the hardware and Kvm.
169 *
170 * @return False if the allocation is too small, true on success.
171 */
172 bool getSupportedMSRs(struct kvm_msr_list &msrs) const;
173
174 /**
175 * Get the MSRs supported by the hardware and Kvm.
176 *
177 * @note This method uses an internal cache to minimize the number
178 * of calls into the kernel.
179 *
180 * @return Reference to cached MSR index list.
181 */
182 const MSRIndexVector &getSupportedMSRs() const;
183
184 protected:
185 /**
186 * Check for the presence of an extension to the KVM API.
187 *
188 * The return value depends on the extension, but is always zero
189 * if it is unsupported or positive otherwise. Some extensions use
190 * the return value provide additional data about the extension.
191 *
192 * @return 0 if the extension is unsupported, positive integer
193 * otherwise.
194 */
195 int checkExtension(int extension) const;
196
197 /**
198 * @addtogroup KvmIoctl
199 * @{
200 */
201 /**
202 * Main VM ioctl interface.
203 *
204 * @param request KVM request
205 * @param p1 Optional request parameter
206 *
207 * @return -1 on error (error number in errno), ioctl dependent
208 * value otherwise.
209 */
210 int ioctl(int request, long p1) const;
211 int ioctl(int request, void *p1) const {
212 return ioctl(request, (long)p1);
213 }
214 int ioctl(int request) const {
215 return ioctl(request, 0L);
216 }
217 /** @} */
218
219 private:
220 // This object is a singleton, so prevent instantiation.
221 Kvm();
222
223 // Prevent copying
224 Kvm(const Kvm &kvm);
225 // Prevent assignment
226 Kvm &operator=(const Kvm &kvm);
227
228 /**
229 * Create a KVM Virtual Machine
230 *
231 * @return File descriptor pointing to the VM
232 */
233 int createVM();
234
235 /** KVM VM file descriptor */
236 int kvmFD;
237 /** KVM API version */
238 int apiVersion;
239 /** Size of the MMAPed vCPU parameter area. */
240 int vcpuMMapSize;
241
242 /** Cached vector of supported CPUID entries. */
243 mutable CPUIDVector supportedCPUIDCache;
244
245 /** Cached vector of supported MSRs. */
246 mutable MSRIndexVector supportedMSRCache;
247
248 /** Singleton instance */
249 static Kvm *instance;
250 };
251
252 /**
253 * KVM VM container
254 *
255 * A KVM VM container normally contains all the CPUs in a shared
256 * memory machine. The VM container handles things like physical
257 * memory and to some extent interrupts. Normally, the VM API is only
258 * used for interrupts when the PIC is emulated by the kernel, which
259 * is a feature we do not use. However, some architectures (notably
260 * ARM) use the VM interface to deliver interrupts to specific CPUs as
261 * well.
262 *
263 * VM initialization is a bit different from that of other
264 * SimObjects. When we initialize the VM, we discover all physical
265 * memory mappings in the system. Since AbstractMem::unserialize
266 * re-maps the guests memory, we need to make sure that this is done
267 * after the memory has been re-mapped, but before the vCPUs are
268 * initialized (KVM requires memory mappings to be setup before CPUs
269 * can be created). Normally, we would just initialize the VM in
270 * init() or startup(), however, we can not use init() since this is
271 * called before AbstractMem::unserialize() and we can not use
272 * startup() since it must be called before BaseKvmCPU::startup() and
273 * the simulator framework does not guarantee call order. We therefore
274 * call cpuStartup() from BaseKvmCPU::startup() instead and execute
275 * the initialization code once when the first CPU in the VM is
276 * starting.
277 */
278 class KvmVM : public SimObject
279 {
280 friend class BaseKvmCPU;
281
282 public:
283 KvmVM(KvmVMParams *params);
284 virtual ~KvmVM();
285
286 /**
287 * Setup a shared three-page memory region used by the internals
288 * of KVM. This is currently only needed by x86 implementations.
289 *
290 * @param tss_address Physical address of the start of the TSS
291 */
292 void setTSSAddress(Addr tss_address);
293
294 /** @{ */
295 /**
296 * Request coalescing MMIO for a memory range.
297 *
298 * @param start Physical start address in guest
299 * @param size Size of the MMIO region
300 */
301 void coalesceMMIO(Addr start, int size);
302
303 /**
304 * Request coalescing MMIO for a memory range.
305 *
306 * @param range Coalesced MMIO range
307 */
308 void coalesceMMIO(const AddrRange &range);
309 /** @} */
310
311 /**
312 * @addtogroup KvmInterrupts
313 * @{
314 */
315 /**
316 * Create an in-kernel interrupt controller
317 *
318 * @note This functionality depends on Kvm::capIRQChip().
319 */
320 void createIRQChip();
321
322 /**
323 * Set the status of an IRQ line using KVM_IRQ_LINE.
324 *
325 * @note This ioctl is usually only used if the interrupt
326 * controller is emulated by the kernel (i.e., after calling
327 * createIRQChip()). Some architectures (e.g., ARM) use it instead
328 * of BaseKvmCPU::kvmInterrupt().
329 *
330 * @param irq Interrupt number
331 * @param high Line level (true for high, false for low)
332 */
333 void setIRQLine(uint32_t irq, bool high);
334
335 /**
336 * Is in-kernel IRQ chip emulation enabled?
337 */
338 bool hasKernelIRQChip() const { return _hasKernelIRQChip; }
339 /** @} */
340
341 struct MemSlot
342 {
343 MemSlot(uint32_t _num) : num(_num)
344 {}
345 MemSlot() : num(-1)
346 {}
347
348 int32_t num;
349 };
350
351 /**
352 * Allocate a memory slot within the VM.
353 */
354 const MemSlot allocMemSlot(uint64_t size);
355
356 /**
357 * Setup a region of physical memory in the guest
358 *
359 * @param slot KVM memory slot ID returned by allocMemSlot
360 * @param host_addr Memory allocation backing the memory
361 * @param guest_addr Address in the guest
362 * @param flags Flags (see the KVM API documentation)
363 */
364 void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr,
365 uint32_t flags);
366
367 /**
368 * Disable a memory slot.
369 */
370 void disableMemSlot(const MemSlot slot);
371
372 /**
373 * Free a previously allocated memory slot.
374 */
375 void freeMemSlot(const MemSlot slot);
376
377 /** Global KVM interface */
378 Kvm kvm;
379
380 protected:
381 /**
382 * VM CPU initialization code.
383 *
384 * This method is called from BaseKvmCPU::startup() when a CPU in
385 * the VM executes its BaseKvmCPU::startup() method. The first
386 * time method is executed on a VM, it calls the delayedStartup()
387 * method.
388 */
389 void cpuStartup();
390
391 /**
392 * Delayed initialization, executed once before the first CPU
393 * starts.
394 *
395 * This method provides a way to do VM initialization once before
396 * the first CPU in a VM starts. It is needed since some resources
397 * (e.g., memory mappings) can change in the normal
398 * SimObject::startup() path. Since the call order of
399 * SimObject::startup() is not guaranteed, we simply defer some
400 * initialization until a CPU is about to start.
401 */
402 void delayedStartup();
403
404
405 /** @{ */
406 /**
407 * Setup a region of physical memory in the guest
408 *
409 * @param slot KVM memory slot ID (must be unique)
410 * @param host_addr Memory allocation backing the memory
411 * @param guest_addr Address in the guest
412 * @param len Size of the allocation in bytes
413 * @param flags Flags (see the KVM API documentation)
414 */
415 void setUserMemoryRegion(uint32_t slot,
416 void *host_addr, Addr guest_addr,
417 uint64_t len, uint32_t flags);
418 /** @} */
419
420 /**
421 * Create a new vCPU within a VM.
422 *
423 * @param vcpuID ID of the new CPU within the VM.
424 * @return File descriptor referencing the CPU.
425 */
426 int createVCPU(long vcpuID);
427
428 /**
429 * Allocate a new vCPU ID within the VM.
430 *
431 * The returned vCPU ID is guaranteed to be unique within the
432 * VM. New IDs are allocated sequentially starting from 0.
433 *
434 * @return ID of the new vCPU
435 */
436 long allocVCPUID();
437
438 /**
439 * @addtogroup KvmIoctl
440 * @{
441 */
442 /**
443 * KVM VM ioctl interface.
444 *
445 * @param request KVM VM request
446 * @param p1 Optional request parameter
447 *
448 * @return -1 on error (error number in errno), ioctl dependent
449 * value otherwise.
450 */
451 int ioctl(int request, long p1) const;
452 int ioctl(int request, void *p1) const {
453 return ioctl(request, (long)p1);
454 }
455 int ioctl(int request) const {
456 return ioctl(request, 0L);
457 }
458 /**@}*/
459
460 private:
461 // Prevent copying
462 KvmVM(const KvmVM &vm);
463 // Prevent assignment
464 KvmVM &operator=(const KvmVM &vm);
465
466 System *system;
467
468 /** KVM VM file descriptor */
469 const int vmFD;
470
471 /** Has delayedStartup() already been called? */
472 bool started;
473
474 /** Do we have in-kernel IRQ-chip emulation enabled? */
475 bool _hasKernelIRQChip;
476
477 /** Next unallocated vCPU ID */
478 long nextVCPUID;
479
480 /**
481 * Structures tracking memory slots.
482 */
483 class MemorySlot
484 {
485 public:
486 uint64_t size;
487 uint32_t slot;
488 bool active;
489 };
490 std::vector<MemorySlot> memorySlots;
491 uint32_t maxMemorySlot;
492 };
493
494 #endif