base.hh (9684:00dca8a9b560) base.hh (9688:cce7dd32aed3)
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_BASE_HH__
41#define __CPU_KVM_BASE_HH__
42
43#include <memory>
44
45#include "base/statistics.hh"
46#include "cpu/kvm/perfevent.hh"
47#include "cpu/kvm/timer.hh"
48#include "cpu/kvm/vm.hh"
49#include "cpu/base.hh"
50#include "cpu/simple_thread.hh"
51
52/** Signal to use to trigger time-based exits from KVM */
53#define KVM_TIMER_SIGNAL SIGRTMIN
54
55// forward declarations
56class ThreadContext;
57struct BaseKvmCPUParams;
58
59/**
60 * Base class for KVM based CPU models
61 *
62 * All architecture specific KVM implementation should inherit from
63 * this class. The most basic CPU models only need to override the
64 * updateKvmState() and updateThreadContext() methods to implement
65 * state synchronization between gem5 and KVM.
66 *
67 * The architecture specific implementation is also responsible for
68 * delivering interrupts into the VM. This is typically done by
69 * overriding tick() and checking the thread context before entering
70 * into the VM. In order to deliver an interrupt, the implementation
71 * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt()
72 * depending on the specifics of the underlying hardware/drivers.
73 */
74class BaseKvmCPU : public BaseCPU
75{
76 public:
77 BaseKvmCPU(BaseKvmCPUParams *params);
78 virtual ~BaseKvmCPU();
79
80 void init();
81 void startup();
82 void regStats();
83
84 void serializeThread(std::ostream &os, ThreadID tid);
85 void unserializeThread(Checkpoint *cp, const std::string &section,
86 ThreadID tid);
87
88 unsigned int drain(DrainManager *dm);
89 void drainResume();
90
91 void switchOut();
92 void takeOverFrom(BaseCPU *cpu);
93
94 void verifyMemoryMode() const;
95
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_BASE_HH__
41#define __CPU_KVM_BASE_HH__
42
43#include <memory>
44
45#include "base/statistics.hh"
46#include "cpu/kvm/perfevent.hh"
47#include "cpu/kvm/timer.hh"
48#include "cpu/kvm/vm.hh"
49#include "cpu/base.hh"
50#include "cpu/simple_thread.hh"
51
52/** Signal to use to trigger time-based exits from KVM */
53#define KVM_TIMER_SIGNAL SIGRTMIN
54
55// forward declarations
56class ThreadContext;
57struct BaseKvmCPUParams;
58
59/**
60 * Base class for KVM based CPU models
61 *
62 * All architecture specific KVM implementation should inherit from
63 * this class. The most basic CPU models only need to override the
64 * updateKvmState() and updateThreadContext() methods to implement
65 * state synchronization between gem5 and KVM.
66 *
67 * The architecture specific implementation is also responsible for
68 * delivering interrupts into the VM. This is typically done by
69 * overriding tick() and checking the thread context before entering
70 * into the VM. In order to deliver an interrupt, the implementation
71 * then calls KvmVM::setIRQLine() or BaseKvmCPU::kvmInterrupt()
72 * depending on the specifics of the underlying hardware/drivers.
73 */
74class BaseKvmCPU : public BaseCPU
75{
76 public:
77 BaseKvmCPU(BaseKvmCPUParams *params);
78 virtual ~BaseKvmCPU();
79
80 void init();
81 void startup();
82 void regStats();
83
84 void serializeThread(std::ostream &os, ThreadID tid);
85 void unserializeThread(Checkpoint *cp, const std::string &section,
86 ThreadID tid);
87
88 unsigned int drain(DrainManager *dm);
89 void drainResume();
90
91 void switchOut();
92 void takeOverFrom(BaseCPU *cpu);
93
94 void verifyMemoryMode() const;
95
96 CpuPort &getDataPort() { return dataPort; }
97 CpuPort &getInstPort() { return instPort; }
96 MasterPort &getDataPort() { return dataPort; }
97 MasterPort &getInstPort() { return instPort; }
98
99 void wakeup();
100 void activateContext(ThreadID thread_num, Cycles delay);
101 void suspendContext(ThreadID thread_num);
102 void deallocateContext(ThreadID thread_num);
103 void haltContext(ThreadID thread_num);
104
105 ThreadContext *getContext(int tn);
106
107 Counter totalInsts() const;
108 Counter totalOps() const;
109
110 /** Dump the internal state to the terminal. */
111 virtual void dump();
112
113 /**
114 * A cached copy of a thread's state in the form of a SimpleThread
115 * object.
116 *
117 * Normally the actual thread state is stored in the KVM vCPU. If KVM has
118 * been running this copy is will be out of date. If we recently handled
119 * some events within gem5 that required state to be updated this could be
120 * the most up-to-date copy. When getContext() or updateThreadContext() is
121 * called this copy gets updated. The method syncThreadContext can
122 * be used within a KVM CPU to update the thread context if the
123 * KVM state is dirty (i.e., the vCPU has been run since the last
124 * update).
125 */
126 SimpleThread *thread;
127
128 /** ThreadContext object, provides an interface for external
129 * objects to modify this thread's state.
130 */
131 ThreadContext *tc;
132
133 KvmVM &vm;
134
135 protected:
136 enum Status {
137 /** Context not scheduled in KVM */
138 Idle,
139 /** Running normally */
140 Running,
141 };
142
143 /** CPU run state */
144 Status _status;
145
146 /**
147 * Execute the CPU until the next event in the main event queue or
148 * until the guest needs service from gem5.
149 *
150 * @note This method is virtual in order to allow implementations
151 * to check for architecture specific events (e.g., interrupts)
152 * before entering the VM.
153 */
154 virtual void tick();
155
156 /**
157 * Request KVM to run the guest for a given number of ticks. The
158 * method returns the approximate number of ticks executed.
159 *
160 * @note The returned number of ticks can be both larger or
161 * smaller than the requested number of ticks. A smaller number
162 * can, for example, occur when the guest executes MMIO. A larger
163 * number is typically due to performance counter inaccuracies.
164 *
165 * @param ticks Number of ticks to execute
166 * @return Number of ticks executed (see note)
167 */
168 Tick kvmRun(Tick ticks);
169
170 /**
171 * Get a pointer to the kvm_run structure containing all the input
172 * and output parameters from kvmRun().
173 */
174 struct kvm_run *getKvmRunState() { return _kvmRun; };
175
176 /**
177 * Retrieve a pointer to guest data stored at the end of the
178 * kvm_run structure. This is mainly used for PIO operations
179 * (KVM_EXIT_IO).
180 *
181 * @param offset Offset as specified by the kvm_run structure
182 * @return Pointer to guest data
183 */
184 uint8_t *getGuestData(uint64_t offset) const {
185 return (uint8_t *)_kvmRun + offset;
186 };
187
188 /**
189 * @addtogroup KvmInterrupts
190 * @{
191 */
192 /**
193 * Send a non-maskable interrupt to the guest
194 *
195 * @note The presence of this call depends on Kvm::capUserNMI().
196 */
197 void kvmNonMaskableInterrupt();
198
199 /**
200 * Send a normal interrupt to the guest
201 *
202 * @note Make sure that ready_for_interrupt_injection in kvm_run
203 * is set prior to calling this function. If not, an interrupt
204 * window must be requested by setting request_interrupt_window in
205 * kvm_run to 1 and restarting the guest.
206 *
207 * @param interrupt Structure describing the interrupt to send
208 */
209 void kvmInterrupt(const struct kvm_interrupt &interrupt);
210
211 /** @} */
212
213 /** @{ */
214 /**
215 * Get/Set the register state of the guest vCPU
216 *
217 * KVM has two different interfaces for accessing the state of the
218 * guest CPU. One interface updates 'normal' registers and one
219 * updates 'special' registers. The distinction between special
220 * and normal registers isn't very clear and is architecture
221 * dependent.
222 */
223 void getRegisters(struct kvm_regs &regs) const;
224 void setRegisters(const struct kvm_regs &regs);
225 void getSpecialRegisters(struct kvm_sregs &regs) const;
226 void setSpecialRegisters(const struct kvm_sregs &regs);
227 /** @} */
228
229 /** @{ */
230 /**
231 * Get/Set the guest FPU/vector state
232 */
233 void getFPUState(struct kvm_fpu &state) const;
234 void setFPUState(const struct kvm_fpu &state);
235 /** @} */
236
237 /** @{ */
238 /**
239 * Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
240 *
241 * @note The presence of this call depends on Kvm::capOneReg().
242 */
243 void setOneReg(uint64_t id, const void *addr);
244 void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); }
245 void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); }
246 void getOneReg(uint64_t id, void *addr) const;
247 uint64_t getOneRegU64(uint64_t id) const {
248 uint64_t value;
249 getOneReg(id, &value);
250 return value;
251 }
252 uint32_t getOneRegU32(uint64_t id) const {
253 uint32_t value;
254 getOneReg(id, &value);
255 return value;
256 }
257 /** @} */
258
259 /**
260 * Get and format one register for printout.
261 *
262 * This function call getOneReg() to retrieve the contents of one
263 * register and automatically formats it for printing.
264 *
265 * @note The presence of this call depends on Kvm::capOneReg().
266 */
267 std::string getAndFormatOneReg(uint64_t id) const;
268
269 /** @{ */
270 /**
271 * Update the KVM state from the current thread context
272 *
273 * The base CPU calls this method before starting the guest CPU
274 * when the contextDirty flag is set. The architecture dependent
275 * CPU implementation is expected to update all guest state
276 * (registers, special registers, and FPU state).
277 */
278 virtual void updateKvmState() = 0;
279
280 /**
281 * Update the current thread context with the KVM state
282 *
283 * The base CPU after the guest updates any of the KVM state. In
284 * practice, this happens after kvmRun is called. The architecture
285 * dependent code is expected to read the state of the guest CPU
286 * and update gem5's thread state.
287 */
288 virtual void updateThreadContext() = 0;
289
290 /**
291 * Update a thread context if the KVM state is dirty with respect
292 * to the cached thread context.
293 */
294 void syncThreadContext();
295
296 /**
297 * Update the KVM if the thread context is dirty.
298 */
299 void syncKvmState();
300 /** @} */
301
302 /** @{ */
303 /**
304 * Main kvmRun exit handler, calls the relevant handleKvmExit*
305 * depending on exit type.
306 *
307 * @return Number of ticks spent servicing the exit request
308 */
309 virtual Tick handleKvmExit();
310
311 /**
312 * The guest performed a legacy IO request (out/inp on x86)
313 *
314 * @return Number of ticks spent servicing the IO request
315 */
316 virtual Tick handleKvmExitIO();
317
318 /**
319 * The guest requested a monitor service using a hypercall
320 *
321 * @return Number of ticks spent servicing the hypercall
322 */
323 virtual Tick handleKvmExitHypercall();
324
325 /**
326 * The guest exited because an interrupt window was requested
327 *
328 * The guest exited because an interrupt window was requested
329 * (request_interrupt_window in the kvm_run structure was set to 1
330 * before calling kvmRun) and it is now ready to receive
331 *
332 * @return Number of ticks spent servicing the IRQ
333 */
334 virtual Tick handleKvmExitIRQWindowOpen();
335
336 /**
337 * An unknown architecture dependent error occurred when starting
338 * the vCPU
339 *
340 * The kvm_run data structure contains the hardware error
341 * code. The defaults behavior of this method just prints the HW
342 * error code and panics. Architecture dependent implementations
343 * may want to override this method to provide better,
344 * hardware-aware, error messages.
345 *
346 * @return Number of ticks delay the next CPU tick
347 */
348 virtual Tick handleKvmExitUnknown();
349
350 /**
351 * An unhandled virtualization exception occured
352 *
353 * Some KVM virtualization drivers return unhandled exceptions to
354 * the user-space monitor. This interface is currently only used
355 * by the Intel VMX KVM driver.
356 *
357 * @return Number of ticks delay the next CPU tick
358 */
359 virtual Tick handleKvmExitException();
360
361 /**
362 * KVM failed to start the virtualized CPU
363 *
364 * The kvm_run data structure contains the hardware-specific error
365 * code.
366 *
367 * @return Number of ticks delay the next CPU tick
368 */
369 virtual Tick handleKvmExitFailEntry();
370 /** @} */
371
372 /**
373 * Inject a memory mapped IO request into gem5
374 *
375 * @param paddr Physical address
376 * @param data Pointer to the source/destination buffer
377 * @param size Memory access size
378 * @param write True if write, False if read
379 * @return Number of ticks spent servicing the memory access
380 */
381 Tick doMMIOAccess(Addr paddr, void *data, int size, bool write);
382
383
384 /**
385 * @addtogroup KvmIoctl
386 * @{
387 */
388 /**
389 * vCPU ioctl interface.
390 *
391 * @param request KVM vCPU request
392 * @param p1 Optional request parameter
393 *
394 * @return -1 on error (error number in errno), ioctl dependent
395 * value otherwise.
396 */
397 int ioctl(int request, long p1) const;
398 int ioctl(int request, void *p1) const {
399 return ioctl(request, (long)p1);
400 }
401 int ioctl(int request) const {
402 return ioctl(request, 0L);
403 }
404 /** @} */
405
98
99 void wakeup();
100 void activateContext(ThreadID thread_num, Cycles delay);
101 void suspendContext(ThreadID thread_num);
102 void deallocateContext(ThreadID thread_num);
103 void haltContext(ThreadID thread_num);
104
105 ThreadContext *getContext(int tn);
106
107 Counter totalInsts() const;
108 Counter totalOps() const;
109
110 /** Dump the internal state to the terminal. */
111 virtual void dump();
112
113 /**
114 * A cached copy of a thread's state in the form of a SimpleThread
115 * object.
116 *
117 * Normally the actual thread state is stored in the KVM vCPU. If KVM has
118 * been running this copy is will be out of date. If we recently handled
119 * some events within gem5 that required state to be updated this could be
120 * the most up-to-date copy. When getContext() or updateThreadContext() is
121 * called this copy gets updated. The method syncThreadContext can
122 * be used within a KVM CPU to update the thread context if the
123 * KVM state is dirty (i.e., the vCPU has been run since the last
124 * update).
125 */
126 SimpleThread *thread;
127
128 /** ThreadContext object, provides an interface for external
129 * objects to modify this thread's state.
130 */
131 ThreadContext *tc;
132
133 KvmVM &vm;
134
135 protected:
136 enum Status {
137 /** Context not scheduled in KVM */
138 Idle,
139 /** Running normally */
140 Running,
141 };
142
143 /** CPU run state */
144 Status _status;
145
146 /**
147 * Execute the CPU until the next event in the main event queue or
148 * until the guest needs service from gem5.
149 *
150 * @note This method is virtual in order to allow implementations
151 * to check for architecture specific events (e.g., interrupts)
152 * before entering the VM.
153 */
154 virtual void tick();
155
156 /**
157 * Request KVM to run the guest for a given number of ticks. The
158 * method returns the approximate number of ticks executed.
159 *
160 * @note The returned number of ticks can be both larger or
161 * smaller than the requested number of ticks. A smaller number
162 * can, for example, occur when the guest executes MMIO. A larger
163 * number is typically due to performance counter inaccuracies.
164 *
165 * @param ticks Number of ticks to execute
166 * @return Number of ticks executed (see note)
167 */
168 Tick kvmRun(Tick ticks);
169
170 /**
171 * Get a pointer to the kvm_run structure containing all the input
172 * and output parameters from kvmRun().
173 */
174 struct kvm_run *getKvmRunState() { return _kvmRun; };
175
176 /**
177 * Retrieve a pointer to guest data stored at the end of the
178 * kvm_run structure. This is mainly used for PIO operations
179 * (KVM_EXIT_IO).
180 *
181 * @param offset Offset as specified by the kvm_run structure
182 * @return Pointer to guest data
183 */
184 uint8_t *getGuestData(uint64_t offset) const {
185 return (uint8_t *)_kvmRun + offset;
186 };
187
188 /**
189 * @addtogroup KvmInterrupts
190 * @{
191 */
192 /**
193 * Send a non-maskable interrupt to the guest
194 *
195 * @note The presence of this call depends on Kvm::capUserNMI().
196 */
197 void kvmNonMaskableInterrupt();
198
199 /**
200 * Send a normal interrupt to the guest
201 *
202 * @note Make sure that ready_for_interrupt_injection in kvm_run
203 * is set prior to calling this function. If not, an interrupt
204 * window must be requested by setting request_interrupt_window in
205 * kvm_run to 1 and restarting the guest.
206 *
207 * @param interrupt Structure describing the interrupt to send
208 */
209 void kvmInterrupt(const struct kvm_interrupt &interrupt);
210
211 /** @} */
212
213 /** @{ */
214 /**
215 * Get/Set the register state of the guest vCPU
216 *
217 * KVM has two different interfaces for accessing the state of the
218 * guest CPU. One interface updates 'normal' registers and one
219 * updates 'special' registers. The distinction between special
220 * and normal registers isn't very clear and is architecture
221 * dependent.
222 */
223 void getRegisters(struct kvm_regs &regs) const;
224 void setRegisters(const struct kvm_regs &regs);
225 void getSpecialRegisters(struct kvm_sregs &regs) const;
226 void setSpecialRegisters(const struct kvm_sregs &regs);
227 /** @} */
228
229 /** @{ */
230 /**
231 * Get/Set the guest FPU/vector state
232 */
233 void getFPUState(struct kvm_fpu &state) const;
234 void setFPUState(const struct kvm_fpu &state);
235 /** @} */
236
237 /** @{ */
238 /**
239 * Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
240 *
241 * @note The presence of this call depends on Kvm::capOneReg().
242 */
243 void setOneReg(uint64_t id, const void *addr);
244 void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); }
245 void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); }
246 void getOneReg(uint64_t id, void *addr) const;
247 uint64_t getOneRegU64(uint64_t id) const {
248 uint64_t value;
249 getOneReg(id, &value);
250 return value;
251 }
252 uint32_t getOneRegU32(uint64_t id) const {
253 uint32_t value;
254 getOneReg(id, &value);
255 return value;
256 }
257 /** @} */
258
259 /**
260 * Get and format one register for printout.
261 *
262 * This function call getOneReg() to retrieve the contents of one
263 * register and automatically formats it for printing.
264 *
265 * @note The presence of this call depends on Kvm::capOneReg().
266 */
267 std::string getAndFormatOneReg(uint64_t id) const;
268
269 /** @{ */
270 /**
271 * Update the KVM state from the current thread context
272 *
273 * The base CPU calls this method before starting the guest CPU
274 * when the contextDirty flag is set. The architecture dependent
275 * CPU implementation is expected to update all guest state
276 * (registers, special registers, and FPU state).
277 */
278 virtual void updateKvmState() = 0;
279
280 /**
281 * Update the current thread context with the KVM state
282 *
283 * The base CPU after the guest updates any of the KVM state. In
284 * practice, this happens after kvmRun is called. The architecture
285 * dependent code is expected to read the state of the guest CPU
286 * and update gem5's thread state.
287 */
288 virtual void updateThreadContext() = 0;
289
290 /**
291 * Update a thread context if the KVM state is dirty with respect
292 * to the cached thread context.
293 */
294 void syncThreadContext();
295
296 /**
297 * Update the KVM if the thread context is dirty.
298 */
299 void syncKvmState();
300 /** @} */
301
302 /** @{ */
303 /**
304 * Main kvmRun exit handler, calls the relevant handleKvmExit*
305 * depending on exit type.
306 *
307 * @return Number of ticks spent servicing the exit request
308 */
309 virtual Tick handleKvmExit();
310
311 /**
312 * The guest performed a legacy IO request (out/inp on x86)
313 *
314 * @return Number of ticks spent servicing the IO request
315 */
316 virtual Tick handleKvmExitIO();
317
318 /**
319 * The guest requested a monitor service using a hypercall
320 *
321 * @return Number of ticks spent servicing the hypercall
322 */
323 virtual Tick handleKvmExitHypercall();
324
325 /**
326 * The guest exited because an interrupt window was requested
327 *
328 * The guest exited because an interrupt window was requested
329 * (request_interrupt_window in the kvm_run structure was set to 1
330 * before calling kvmRun) and it is now ready to receive
331 *
332 * @return Number of ticks spent servicing the IRQ
333 */
334 virtual Tick handleKvmExitIRQWindowOpen();
335
336 /**
337 * An unknown architecture dependent error occurred when starting
338 * the vCPU
339 *
340 * The kvm_run data structure contains the hardware error
341 * code. The defaults behavior of this method just prints the HW
342 * error code and panics. Architecture dependent implementations
343 * may want to override this method to provide better,
344 * hardware-aware, error messages.
345 *
346 * @return Number of ticks delay the next CPU tick
347 */
348 virtual Tick handleKvmExitUnknown();
349
350 /**
351 * An unhandled virtualization exception occured
352 *
353 * Some KVM virtualization drivers return unhandled exceptions to
354 * the user-space monitor. This interface is currently only used
355 * by the Intel VMX KVM driver.
356 *
357 * @return Number of ticks delay the next CPU tick
358 */
359 virtual Tick handleKvmExitException();
360
361 /**
362 * KVM failed to start the virtualized CPU
363 *
364 * The kvm_run data structure contains the hardware-specific error
365 * code.
366 *
367 * @return Number of ticks delay the next CPU tick
368 */
369 virtual Tick handleKvmExitFailEntry();
370 /** @} */
371
372 /**
373 * Inject a memory mapped IO request into gem5
374 *
375 * @param paddr Physical address
376 * @param data Pointer to the source/destination buffer
377 * @param size Memory access size
378 * @param write True if write, False if read
379 * @return Number of ticks spent servicing the memory access
380 */
381 Tick doMMIOAccess(Addr paddr, void *data, int size, bool write);
382
383
384 /**
385 * @addtogroup KvmIoctl
386 * @{
387 */
388 /**
389 * vCPU ioctl interface.
390 *
391 * @param request KVM vCPU request
392 * @param p1 Optional request parameter
393 *
394 * @return -1 on error (error number in errno), ioctl dependent
395 * value otherwise.
396 */
397 int ioctl(int request, long p1) const;
398 int ioctl(int request, void *p1) const {
399 return ioctl(request, (long)p1);
400 }
401 int ioctl(int request) const {
402 return ioctl(request, 0L);
403 }
404 /** @} */
405
406
407 /**
408 * KVM memory port. Uses the default MasterPort behavior, but
409 * panics on timing accesses.
410 */
411 class KVMCpuPort : public MasterPort
412 {
413
414 public:
415 KVMCpuPort(const std::string &_name, BaseKvmCPU *_cpu)
416 : MasterPort(_name, _cpu)
417 { }
418
419 protected:
420 bool recvTimingResp(PacketPtr pkt)
421 {
422 panic("The KVM CPU doesn't expect recvTimingResp!\n");
423 return true;
424 }
425
426 void recvRetry()
427 {
428 panic("The KVM CPU doesn't expect recvRetry!\n");
429 }
430
431 };
432
406 /** Port for data requests */
433 /** Port for data requests */
407 CpuPort dataPort;
434 KVMCpuPort dataPort;
408
409 /** Unused dummy port for the instruction interface */
435
436 /** Unused dummy port for the instruction interface */
410 CpuPort instPort;
437 KVMCpuPort instPort;
411
412 /** Pre-allocated MMIO memory request */
413 Request mmio_req;
414
415 /**
416 * Is the gem5 context dirty? Set to true to force an update of
417 * the KVM vCPU state upon the next call to kvmRun().
418 */
419 bool threadContextDirty;
420
421 /**
422 * Is the KVM state dirty? Set to true to force an update of
423 * the KVM vCPU state upon the next call to kvmRun().
424 */
425 bool kvmStateDirty;
426
427 /** KVM internal ID of the vCPU */
428 const long vcpuID;
429
430 private:
431 struct TickEvent : public Event
432 {
433 BaseKvmCPU &cpu;
434
435 TickEvent(BaseKvmCPU &c)
436 : Event(CPU_Tick_Pri), cpu(c) {}
437
438 void process() { cpu.tick(); }
439
440 const char *description() const {
441 return "BaseKvmCPU tick";
442 }
443 };
444
445 /**
446 * Service MMIO requests in the mmioRing.
447 *
448 *
449 * @return Number of ticks spent servicing the MMIO requests in
450 * the MMIO ring buffer
451 */
452 Tick flushCoalescedMMIO();
453
454 /**
455 * Setup a signal handler to catch the timer signal used to
456 * switch back to the monitor.
457 */
458 void setupSignalHandler();
459
460 /** Setup hardware performance counters */
461 void setupCounters();
462
463 /** KVM vCPU file descriptor */
464 int vcpuFD;
465 /** Size of MMAPed kvm_run area */
466 int vcpuMMapSize;
467 /**
468 * Pointer to the kvm_run structure used to communicate parameters
469 * with KVM.
470 *
471 * @note This is the base pointer of the MMAPed KVM region. The
472 * first page contains the kvm_run structure. Subsequent pages may
473 * contain other data such as the MMIO ring buffer.
474 */
475 struct kvm_run *_kvmRun;
476 /**
477 * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not
478 * supported.
479 */
480 struct kvm_coalesced_mmio_ring *mmioRing;
481 /** Cached page size of the host */
482 const long pageSize;
483
484 TickEvent tickEvent;
485
486 /** @{ */
487 /** Guest performance counters */
488 PerfKvmCounter hwCycles;
489 PerfKvmCounter hwInstructions;
490 /** @} */
491
492 /**
493 * Does the runTimer control the performance counters?
494 *
495 * The run timer will automatically enable and disable performance
496 * counters if a PerfEvent-based timer is used to control KVM
497 * exits.
498 */
499 bool perfControlledByTimer;
500
501 /**
502 * Timer used to force execution into the monitor after a
503 * specified number of simulation tick equivalents have executed
504 * in the guest. This counter generates the signal specified by
505 * KVM_TIMER_SIGNAL.
506 */
507 std::unique_ptr<BaseKvmTimer> runTimer;
508
509 float hostFactor;
510
511 public:
512 /* @{ */
513 Stats::Scalar numInsts;
514 Stats::Scalar numVMExits;
515 Stats::Scalar numMMIO;
516 Stats::Scalar numCoalescedMMIO;
517 Stats::Scalar numIO;
518 Stats::Scalar numHalt;
519 Stats::Scalar numInterrupts;
520 Stats::Scalar numHypercalls;
521 /* @} */
522};
523
524#endif
438
439 /** Pre-allocated MMIO memory request */
440 Request mmio_req;
441
442 /**
443 * Is the gem5 context dirty? Set to true to force an update of
444 * the KVM vCPU state upon the next call to kvmRun().
445 */
446 bool threadContextDirty;
447
448 /**
449 * Is the KVM state dirty? Set to true to force an update of
450 * the KVM vCPU state upon the next call to kvmRun().
451 */
452 bool kvmStateDirty;
453
454 /** KVM internal ID of the vCPU */
455 const long vcpuID;
456
457 private:
458 struct TickEvent : public Event
459 {
460 BaseKvmCPU &cpu;
461
462 TickEvent(BaseKvmCPU &c)
463 : Event(CPU_Tick_Pri), cpu(c) {}
464
465 void process() { cpu.tick(); }
466
467 const char *description() const {
468 return "BaseKvmCPU tick";
469 }
470 };
471
472 /**
473 * Service MMIO requests in the mmioRing.
474 *
475 *
476 * @return Number of ticks spent servicing the MMIO requests in
477 * the MMIO ring buffer
478 */
479 Tick flushCoalescedMMIO();
480
481 /**
482 * Setup a signal handler to catch the timer signal used to
483 * switch back to the monitor.
484 */
485 void setupSignalHandler();
486
487 /** Setup hardware performance counters */
488 void setupCounters();
489
490 /** KVM vCPU file descriptor */
491 int vcpuFD;
492 /** Size of MMAPed kvm_run area */
493 int vcpuMMapSize;
494 /**
495 * Pointer to the kvm_run structure used to communicate parameters
496 * with KVM.
497 *
498 * @note This is the base pointer of the MMAPed KVM region. The
499 * first page contains the kvm_run structure. Subsequent pages may
500 * contain other data such as the MMIO ring buffer.
501 */
502 struct kvm_run *_kvmRun;
503 /**
504 * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not
505 * supported.
506 */
507 struct kvm_coalesced_mmio_ring *mmioRing;
508 /** Cached page size of the host */
509 const long pageSize;
510
511 TickEvent tickEvent;
512
513 /** @{ */
514 /** Guest performance counters */
515 PerfKvmCounter hwCycles;
516 PerfKvmCounter hwInstructions;
517 /** @} */
518
519 /**
520 * Does the runTimer control the performance counters?
521 *
522 * The run timer will automatically enable and disable performance
523 * counters if a PerfEvent-based timer is used to control KVM
524 * exits.
525 */
526 bool perfControlledByTimer;
527
528 /**
529 * Timer used to force execution into the monitor after a
530 * specified number of simulation tick equivalents have executed
531 * in the guest. This counter generates the signal specified by
532 * KVM_TIMER_SIGNAL.
533 */
534 std::unique_ptr<BaseKvmTimer> runTimer;
535
536 float hostFactor;
537
538 public:
539 /* @{ */
540 Stats::Scalar numInsts;
541 Stats::Scalar numVMExits;
542 Stats::Scalar numMMIO;
543 Stats::Scalar numCoalescedMMIO;
544 Stats::Scalar numIO;
545 Stats::Scalar numHalt;
546 Stats::Scalar numInterrupts;
547 Stats::Scalar numHypercalls;
548 /* @} */
549};
550
551#endif