kvm: x86: Fix segment registers to make them VMX compatible
[gem5.git] / src / cpu / kvm / vm.hh
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
49 struct KvmVMParams;
50 class 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 */
72 class 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 */
271 class 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