vm.hh (10859:0ba6f47025d1) vm.hh (10860:cba0f26038b4)
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 /**
299 * Setup a shared three-page memory region used by the internals
300 * of KVM. This is currently only needed by x86 implementations.
301 *
302 * @param tss_address Physical address of the start of the TSS
303 */
304 void setTSSAddress(Addr tss_address);
305
306 /** @{ */
307 /**
308 * Request coalescing MMIO for a memory range.
309 *
310 * @param start Physical start address in guest
311 * @param size Size of the MMIO region
312 */
313 void coalesceMMIO(Addr start, int size);
314
315 /**
316 * Request coalescing MMIO for a memory range.
317 *
318 * @param range Coalesced MMIO range
319 */
320 void coalesceMMIO(const AddrRange &range);
321 /** @} */
322
323 /**
324 * @addtogroup KvmInterrupts
325 * @{
326 */
327 /**
328 * Create an in-kernel interrupt controller
329 *
330 * @note This functionality depends on Kvm::capIRQChip().
331 */
332 void createIRQChip();
333
334 /**
335 * Set the status of an IRQ line using KVM_IRQ_LINE.
336 *
337 * @note This ioctl is usually only used if the interrupt
338 * controller is emulated by the kernel (i.e., after calling
339 * createIRQChip()). Some architectures (e.g., ARM) use it instead
340 * of BaseKvmCPU::kvmInterrupt().
341 *
342 * @param irq Interrupt number
343 * @param high Line level (true for high, false for low)
344 */
345 void setIRQLine(uint32_t irq, bool high);
346
347 /**
348 * Is in-kernel IRQ chip emulation enabled?
349 */
350 bool hasKernelIRQChip() const { return _hasKernelIRQChip; }
351 /** @} */
352
353 struct MemSlot
354 {
355 MemSlot(uint32_t _num) : num(_num)
356 {}
357 MemSlot() : num(-1)
358 {}
359
360 int32_t num;
361 };
362
363 /**
364 * Allocate a memory slot within the VM.
365 */
366 const MemSlot allocMemSlot(uint64_t size);
367
368 /**
369 * Setup a region of physical memory in the guest
370 *
371 * @param slot KVM memory slot ID returned by allocMemSlot
372 * @param host_addr Memory allocation backing the memory
373 * @param guest_addr Address in the guest
374 * @param flags Flags (see the KVM API documentation)
375 */
376 void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr,
377 uint32_t flags);
378
379 /**
380 * Disable a memory slot.
381 */
382 void disableMemSlot(const MemSlot slot);
383
384 /**
385 * Free a previously allocated memory slot.
386 */
387 void freeMemSlot(const MemSlot slot);
388
389 /**
390 * Create an in-kernel device model.
391 *
392 * @param type Device type (KVM_DEV_TYPE_xxx)
393 * @param flags Creation flags (KVM_CREATE_DEVICE_xxx)
394 * @return Device file descriptor
395 */
396 int createDevice(uint32_t type, uint32_t flags = 0);
397
398 /** Global KVM interface */
399 Kvm kvm;
400
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 /**
299 * Setup a shared three-page memory region used by the internals
300 * of KVM. This is currently only needed by x86 implementations.
301 *
302 * @param tss_address Physical address of the start of the TSS
303 */
304 void setTSSAddress(Addr tss_address);
305
306 /** @{ */
307 /**
308 * Request coalescing MMIO for a memory range.
309 *
310 * @param start Physical start address in guest
311 * @param size Size of the MMIO region
312 */
313 void coalesceMMIO(Addr start, int size);
314
315 /**
316 * Request coalescing MMIO for a memory range.
317 *
318 * @param range Coalesced MMIO range
319 */
320 void coalesceMMIO(const AddrRange &range);
321 /** @} */
322
323 /**
324 * @addtogroup KvmInterrupts
325 * @{
326 */
327 /**
328 * Create an in-kernel interrupt controller
329 *
330 * @note This functionality depends on Kvm::capIRQChip().
331 */
332 void createIRQChip();
333
334 /**
335 * Set the status of an IRQ line using KVM_IRQ_LINE.
336 *
337 * @note This ioctl is usually only used if the interrupt
338 * controller is emulated by the kernel (i.e., after calling
339 * createIRQChip()). Some architectures (e.g., ARM) use it instead
340 * of BaseKvmCPU::kvmInterrupt().
341 *
342 * @param irq Interrupt number
343 * @param high Line level (true for high, false for low)
344 */
345 void setIRQLine(uint32_t irq, bool high);
346
347 /**
348 * Is in-kernel IRQ chip emulation enabled?
349 */
350 bool hasKernelIRQChip() const { return _hasKernelIRQChip; }
351 /** @} */
352
353 struct MemSlot
354 {
355 MemSlot(uint32_t _num) : num(_num)
356 {}
357 MemSlot() : num(-1)
358 {}
359
360 int32_t num;
361 };
362
363 /**
364 * Allocate a memory slot within the VM.
365 */
366 const MemSlot allocMemSlot(uint64_t size);
367
368 /**
369 * Setup a region of physical memory in the guest
370 *
371 * @param slot KVM memory slot ID returned by allocMemSlot
372 * @param host_addr Memory allocation backing the memory
373 * @param guest_addr Address in the guest
374 * @param flags Flags (see the KVM API documentation)
375 */
376 void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr,
377 uint32_t flags);
378
379 /**
380 * Disable a memory slot.
381 */
382 void disableMemSlot(const MemSlot slot);
383
384 /**
385 * Free a previously allocated memory slot.
386 */
387 void freeMemSlot(const MemSlot slot);
388
389 /**
390 * Create an in-kernel device model.
391 *
392 * @param type Device type (KVM_DEV_TYPE_xxx)
393 * @param flags Creation flags (KVM_CREATE_DEVICE_xxx)
394 * @return Device file descriptor
395 */
396 int createDevice(uint32_t type, uint32_t flags = 0);
397
398 /** Global KVM interface */
399 Kvm kvm;
400
401#if defined(__aarch64__)
402 public: // ARM-specific
403 /**
404 * Ask the kernel for the preferred CPU target to simulate.
405 *
406 * When creating an ARM vCPU in Kvm, we need to initialize it with
407 * a call to BaseArmKvmCPU::kvmArmVCpuInit(). When calling this
408 * function, we need to know what type of CPU the host has. This
409 * call sets up the kvm_vcpu_init structure with the values the
410 * kernel wants.
411 *
412 * @param[out] target Target structure to initialize.
413 */
414 void kvmArmPreferredTarget(struct kvm_vcpu_init &target) const;
415
416#endif
417
401 protected:
402 /**
403 * VM CPU initialization code.
404 *
405 * This method is called from BaseKvmCPU::startup() when a CPU in
406 * the VM executes its BaseKvmCPU::startup() method. The first
407 * time method is executed on a VM, it calls the delayedStartup()
408 * method.
409 */
410 void cpuStartup();
411
412 /**
413 * Delayed initialization, executed once before the first CPU
414 * starts.
415 *
416 * This method provides a way to do VM initialization once before
417 * the first CPU in a VM starts. It is needed since some resources
418 * (e.g., memory mappings) can change in the normal
419 * SimObject::startup() path. Since the call order of
420 * SimObject::startup() is not guaranteed, we simply defer some
421 * initialization until a CPU is about to start.
422 */
423 void delayedStartup();
424
425
426 /** @{ */
427 /**
428 * Setup a region of physical memory in the guest
429 *
430 * @param slot KVM memory slot ID (must be unique)
431 * @param host_addr Memory allocation backing the memory
432 * @param guest_addr Address in the guest
433 * @param len Size of the allocation in bytes
434 * @param flags Flags (see the KVM API documentation)
435 */
436 void setUserMemoryRegion(uint32_t slot,
437 void *host_addr, Addr guest_addr,
438 uint64_t len, uint32_t flags);
439 /** @} */
440
441 /**
442 * Create a new vCPU within a VM.
443 *
444 * @param vcpuID ID of the new CPU within the VM.
445 * @return File descriptor referencing the CPU.
446 */
447 int createVCPU(long vcpuID);
448
449 /**
450 * Allocate a new vCPU ID within the VM.
451 *
452 * The returned vCPU ID is guaranteed to be unique within the
453 * VM. New IDs are allocated sequentially starting from 0.
454 *
455 * @return ID of the new vCPU
456 */
457 long allocVCPUID();
458
459 /**
460 * @addtogroup KvmIoctl
461 * @{
462 */
463 /**
464 * KVM VM ioctl interface.
465 *
466 * @param request KVM VM request
467 * @param p1 Optional request parameter
468 *
469 * @return -1 on error (error number in errno), ioctl dependent
470 * value otherwise.
471 */
472 int ioctl(int request, long p1) const;
473 int ioctl(int request, void *p1) const {
474 return ioctl(request, (long)p1);
475 }
476 int ioctl(int request) const {
477 return ioctl(request, 0L);
478 }
479 /**@}*/
480
481 private:
482 // Prevent copying
483 KvmVM(const KvmVM &vm);
484 // Prevent assignment
485 KvmVM &operator=(const KvmVM &vm);
486
487 System *system;
488
489 /** KVM VM file descriptor */
490 const int vmFD;
491
492 /** Has delayedStartup() already been called? */
493 bool started;
494
495 /** Do we have in-kernel IRQ-chip emulation enabled? */
496 bool _hasKernelIRQChip;
497
498 /** Next unallocated vCPU ID */
499 long nextVCPUID;
500
501 /**
502 * Structures tracking memory slots.
503 */
504 class MemorySlot
505 {
506 public:
507 uint64_t size;
508 uint32_t slot;
509 bool active;
510 };
511 std::vector<MemorySlot> memorySlots;
512 uint32_t maxMemorySlot;
513};
514
515#endif
418 protected:
419 /**
420 * VM CPU initialization code.
421 *
422 * This method is called from BaseKvmCPU::startup() when a CPU in
423 * the VM executes its BaseKvmCPU::startup() method. The first
424 * time method is executed on a VM, it calls the delayedStartup()
425 * method.
426 */
427 void cpuStartup();
428
429 /**
430 * Delayed initialization, executed once before the first CPU
431 * starts.
432 *
433 * This method provides a way to do VM initialization once before
434 * the first CPU in a VM starts. It is needed since some resources
435 * (e.g., memory mappings) can change in the normal
436 * SimObject::startup() path. Since the call order of
437 * SimObject::startup() is not guaranteed, we simply defer some
438 * initialization until a CPU is about to start.
439 */
440 void delayedStartup();
441
442
443 /** @{ */
444 /**
445 * Setup a region of physical memory in the guest
446 *
447 * @param slot KVM memory slot ID (must be unique)
448 * @param host_addr Memory allocation backing the memory
449 * @param guest_addr Address in the guest
450 * @param len Size of the allocation in bytes
451 * @param flags Flags (see the KVM API documentation)
452 */
453 void setUserMemoryRegion(uint32_t slot,
454 void *host_addr, Addr guest_addr,
455 uint64_t len, uint32_t flags);
456 /** @} */
457
458 /**
459 * Create a new vCPU within a VM.
460 *
461 * @param vcpuID ID of the new CPU within the VM.
462 * @return File descriptor referencing the CPU.
463 */
464 int createVCPU(long vcpuID);
465
466 /**
467 * Allocate a new vCPU ID within the VM.
468 *
469 * The returned vCPU ID is guaranteed to be unique within the
470 * VM. New IDs are allocated sequentially starting from 0.
471 *
472 * @return ID of the new vCPU
473 */
474 long allocVCPUID();
475
476 /**
477 * @addtogroup KvmIoctl
478 * @{
479 */
480 /**
481 * KVM VM ioctl interface.
482 *
483 * @param request KVM VM request
484 * @param p1 Optional request parameter
485 *
486 * @return -1 on error (error number in errno), ioctl dependent
487 * value otherwise.
488 */
489 int ioctl(int request, long p1) const;
490 int ioctl(int request, void *p1) const {
491 return ioctl(request, (long)p1);
492 }
493 int ioctl(int request) const {
494 return ioctl(request, 0L);
495 }
496 /**@}*/
497
498 private:
499 // Prevent copying
500 KvmVM(const KvmVM &vm);
501 // Prevent assignment
502 KvmVM &operator=(const KvmVM &vm);
503
504 System *system;
505
506 /** KVM VM file descriptor */
507 const int vmFD;
508
509 /** Has delayedStartup() already been called? */
510 bool started;
511
512 /** Do we have in-kernel IRQ-chip emulation enabled? */
513 bool _hasKernelIRQChip;
514
515 /** Next unallocated vCPU ID */
516 long nextVCPUID;
517
518 /**
519 * Structures tracking memory slots.
520 */
521 class MemorySlot
522 {
523 public:
524 uint64_t size;
525 uint32_t slot;
526 bool active;
527 };
528 std::vector<MemorySlot> memorySlots;
529 uint32_t maxMemorySlot;
530};
531
532#endif