base.hh revision 9651
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; }
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    Counter totalInsts() const;
106    Counter totalOps() const;
107
108    /** Dump the internal state to the terminal. */
109    virtual void dump();
110
111    /** SimpleThread object, provides all the architectural state. */
112    SimpleThread *thread;
113
114    /** ThreadContext object, provides an interface for external
115     * objects to modify this thread's state.
116     */
117    ThreadContext *tc;
118
119    KvmVM &vm;
120
121  protected:
122    enum Status {
123        /** Context not scheduled in KVM */
124        Idle,
125        /** Running normally */
126        Running,
127    };
128
129    /** CPU run state */
130    Status _status;
131
132    /**
133     * Execute the CPU until the next event in the main event queue or
134     * until the guest needs service from gem5.
135     *
136     * @note This method is virtual in order to allow implementations
137     * to check for architecture specific events (e.g., interrupts)
138     * before entering the VM.
139     */
140    virtual void tick();
141
142    /**
143     * Request KVM to run the guest for a given number of ticks. The
144     * method returns the approximate number of ticks executed.
145     *
146     * @note The returned number of ticks can be both larger or
147     * smaller than the requested number of ticks. A smaller number
148     * can, for example, occur when the guest executes MMIO. A larger
149     * number is typically due to performance counter inaccuracies.
150     *
151     * @param ticks Number of ticks to execute
152     * @return Number of ticks executed (see note)
153     */
154    Tick kvmRun(Tick ticks);
155
156    /**
157     * Get a pointer to the kvm_run structure containing all the input
158     * and output parameters from kvmRun().
159     */
160    struct kvm_run *getKvmRunState() { return _kvmRun; };
161
162    /**
163     * Retrieve a pointer to guest data stored at the end of the
164     * kvm_run structure. This is mainly used for PIO operations
165     * (KVM_EXIT_IO).
166     *
167     * @param offset Offset as specified by the kvm_run structure
168     * @return Pointer to guest data
169     */
170    uint8_t *getGuestData(uint64_t offset) const {
171        return (uint8_t *)_kvmRun + offset;
172    };
173
174    /**
175     * @addtogroup KvmInterrupts
176     * @{
177     */
178    /**
179     * Send a non-maskable interrupt to the guest
180     *
181     * @note The presence of this call depends on Kvm::capUserNMI().
182     */
183    void kvmNonMaskableInterrupt();
184
185    /**
186     * Send a normal interrupt to the guest
187     *
188     * @note Make sure that ready_for_interrupt_injection in kvm_run
189     * is set prior to calling this function. If not, an interrupt
190     * window must be requested by setting request_interrupt_window in
191     * kvm_run to 1 and restarting the guest.
192     *
193     * @param interrupt Structure describing the interrupt to send
194     */
195    void kvmInterrupt(const struct kvm_interrupt &interrupt);
196
197    /** @} */
198
199    /** @{ */
200    /**
201     * Get/Set the register state of the guest vCPU
202     *
203     * KVM has two different interfaces for accessing the state of the
204     * guest CPU. One interface updates 'normal' registers and one
205     * updates 'special' registers. The distinction between special
206     * and normal registers isn't very clear and is architecture
207     * dependent.
208     */
209    void getRegisters(struct kvm_regs &regs) const;
210    void setRegisters(const struct kvm_regs &regs);
211    void getSpecialRegisters(struct kvm_sregs &regs) const;
212    void setSpecialRegisters(const struct kvm_sregs &regs);
213    /** @} */
214
215    /** @{ */
216    /**
217     * Get/Set the guest FPU/vector state
218     */
219    void getFPUState(struct kvm_fpu &state) const;
220    void setFPUState(const struct kvm_fpu &state);
221    /** @} */
222
223    /** @{ */
224    /**
225     * Get/Set single register using the KVM_(SET|GET)_ONE_REG API.
226     *
227     * @note The presence of this call depends on Kvm::capOneReg().
228     */
229    void setOneReg(uint64_t id, const void *addr);
230    void setOneReg(uint64_t id, uint64_t value) { setOneReg(id, &value); }
231    void setOneReg(uint64_t id, uint32_t value) { setOneReg(id, &value); }
232    void getOneReg(uint64_t id, void *addr) const;
233    uint64_t getOneRegU64(uint64_t id) const {
234        uint64_t value;
235        getOneReg(id, &value);
236        return value;
237    }
238    uint32_t getOneRegU32(uint64_t id) const {
239        uint32_t value;
240        getOneReg(id, &value);
241        return value;
242    }
243    /** @} */
244
245    /**
246     * Get and format one register for printout.
247     *
248     * This function call getOneReg() to retrieve the contents of one
249     * register and automatically formats it for printing.
250     *
251     * @note The presence of this call depends on Kvm::capOneReg().
252     */
253    std::string getAndFormatOneReg(uint64_t id) const;
254
255    /** @{ */
256    /**
257     * Update the KVM state from the current thread context
258     *
259     * The base CPU calls this method before starting the guest CPU
260     * when the contextDirty flag is set. The architecture dependent
261     * CPU implementation is expected to update all guest state
262     * (registers, special registers, and FPU state).
263     */
264    virtual void updateKvmState() = 0;
265
266    /**
267     * Update the current thread context with the KVM state
268     *
269     * The base CPU after the guest updates any of the KVM state. In
270     * practice, this happens after kvmRun is called. The architecture
271     * dependent code is expected to read the state of the guest CPU
272     * and update gem5's thread state.
273     */
274    virtual void updateThreadContext() = 0;
275    /** @} */
276
277    /** @{ */
278    /**
279     * Main kvmRun exit handler, calls the relevant handleKvmExit*
280     * depending on exit type.
281     *
282     * @return Number of ticks spent servicing the exit request
283     */
284    virtual Tick handleKvmExit();
285
286    /**
287     * The guest performed a legacy IO request (out/inp on x86)
288     *
289     * @return Number of ticks spent servicing the IO request
290     */
291    virtual Tick handleKvmExitIO();
292
293    /**
294     * The guest requested a monitor service using a hypercall
295     *
296     * @return Number of ticks spent servicing the hypercall
297     */
298    virtual Tick handleKvmExitHypercall();
299
300    /**
301     * The guest exited because an interrupt window was requested
302     *
303     * The guest exited because an interrupt window was requested
304     * (request_interrupt_window in the kvm_run structure was set to 1
305     * before calling kvmRun) and it is now ready to receive
306     *
307     * @return Number of ticks spent servicing the IRQ
308     */
309    virtual Tick handleKvmExitIRQWindowOpen();
310
311    /**
312     * An unknown architecture dependent error occurred when starting
313     * the vCPU
314     *
315     * The kvm_run data structure contains the hardware error
316     * code. The defaults behavior of this method just prints the HW
317     * error code and panics. Architecture dependent implementations
318     * may want to override this method to provide better,
319     * hardware-aware, error messages.
320     *
321     * @return Number of ticks delay the next CPU tick
322     */
323    virtual Tick handleKvmExitUnknown();
324
325    /**
326     * An unhandled virtualization exception occured
327     *
328     * Some KVM virtualization drivers return unhandled exceptions to
329     * the user-space monitor. This interface is currently only used
330     * by the Intel VMX KVM driver.
331     *
332     * @return Number of ticks delay the next CPU tick
333     */
334    virtual Tick handleKvmExitException();
335
336    /**
337     * KVM failed to start the virtualized CPU
338     *
339     * The kvm_run data structure contains the hardware-specific error
340     * code.
341     *
342     * @return Number of ticks delay the next CPU tick
343     */
344    virtual Tick handleKvmExitFailEntry();
345    /** @} */
346
347    /**
348     * Inject a memory mapped IO request into gem5
349     *
350     * @param paddr Physical address
351     * @param data Pointer to the source/destination buffer
352     * @param size Memory access size
353     * @param write True if write, False if read
354     * @return Number of ticks spent servicing the memory access
355     */
356    Tick doMMIOAccess(Addr paddr, void *data, int size, bool write);
357
358
359    /**
360     * @addtogroup KvmIoctl
361     * @{
362     */
363    /**
364     * vCPU ioctl interface.
365     *
366     * @param request KVM vCPU request
367     * @param p1 Optional request parameter
368     *
369     * @return -1 on error (error number in errno), ioctl dependent
370     * value otherwise.
371     */
372    int ioctl(int request, long p1) const;
373    int ioctl(int request, void *p1) const {
374        return ioctl(request, (long)p1);
375    }
376    int ioctl(int request) const {
377        return ioctl(request, 0L);
378    }
379    /** @} */
380
381    /** Port for data requests */
382    CpuPort dataPort;
383
384    /** Unused dummy port for the instruction interface */
385    CpuPort instPort;
386
387    /** Pre-allocated MMIO memory request */
388    Request mmio_req;
389
390    /**
391     * Is the gem5 context dirty? Set to true to force an update of
392     * the KVM vCPU state upon the next call to kvmRun().
393     */
394    bool contextDirty;
395
396    /** KVM internal ID of the vCPU */
397    const long vcpuID;
398
399  private:
400    struct TickEvent : public Event
401    {
402        BaseKvmCPU &cpu;
403
404        TickEvent(BaseKvmCPU &c)
405            : Event(CPU_Tick_Pri), cpu(c) {}
406
407        void process() { cpu.tick(); }
408
409        const char *description() const {
410            return "BaseKvmCPU tick";
411        }
412    };
413
414    /**
415     * Service MMIO requests in the mmioRing.
416     *
417     *
418     * @return Number of ticks spent servicing the MMIO requests in
419     * the MMIO ring buffer
420     */
421    Tick flushCoalescedMMIO();
422
423    /**
424     * Setup a signal handler to catch the timer signal used to
425     * switch back to the monitor.
426     */
427    void setupSignalHandler();
428
429    /** Setup hardware performance counters */
430    void setupCounters();
431
432    /** @{ */
433    /** Start/stop counting HW performance events */
434    void startCounters();
435    void stopCounters();
436    /** @} */
437
438    /** KVM vCPU file descriptor */
439    int vcpuFD;
440    /** Size of MMAPed kvm_run area */
441    int vcpuMMapSize;
442    /**
443     * Pointer to the kvm_run structure used to communicate parameters
444     * with KVM.
445     *
446     * @note This is the base pointer of the MMAPed KVM region. The
447     * first page contains the kvm_run structure. Subsequent pages may
448     * contain other data such as the MMIO ring buffer.
449     */
450    struct kvm_run *_kvmRun;
451    /**
452     * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not
453     * supported.
454     */
455    struct kvm_coalesced_mmio_ring *mmioRing;
456    /** Cached page size of the host */
457    const long pageSize;
458
459    TickEvent tickEvent;
460
461    /** @{ */
462    /** Guest performance counters */
463    PerfKvmCounter hwCycles;
464    PerfKvmCounter hwInstructions;
465    /** @} */
466
467    /**
468     * Timer used to force execution into the monitor after a
469     * specified number of simulation tick equivalents have executed
470     * in the guest. This counter generates the signal specified by
471     * KVM_TIMER_SIGNAL.
472     */
473    std::unique_ptr<BaseKvmTimer> runTimer;
474
475    float hostFactor;
476
477  public:
478    /* @{ */
479    Stats::Scalar numVMExits;
480    Stats::Scalar numMMIO;
481    Stats::Scalar numCoalescedMMIO;
482    Stats::Scalar numIO;
483    Stats::Scalar numHalt;
484    Stats::Scalar numInterrupts;
485    Stats::Scalar numHypercalls;
486    /* @} */
487};
488
489#endif
490