1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 
7 #pragma once
8 
9 #include <arch/x86/apic.h>
10 #include <arch/x86/interrupts.h>
11 #include <arch/x86/vmx_state.h>
12 #include <fbl/ref_ptr.h>
13 #include <ktl/unique_ptr.h>
14 #include <hypervisor/guest_physical_address_space.h>
15 #include <hypervisor/id_allocator.h>
16 #include <hypervisor/interrupt_tracker.h>
17 #include <hypervisor/page.h>
18 #include <hypervisor/trap_map.h>
19 #include <kernel/event.h>
20 #include <kernel/spinlock.h>
21 #include <kernel/timer.h>
22 #include <zircon/types.h>
23 
24 struct VmxInfo;
25 
26 class VmxPage : public hypervisor::Page {
27 public:
28     zx_status_t Alloc(const VmxInfo& info, uint8_t fill);
29 
30 private:
31     using hypervisor::Page::Alloc;
32 };
33 
34 // Represents a guest within the hypervisor.
35 class Guest {
36 public:
37     static zx_status_t Create(ktl::unique_ptr<Guest>* out);
38     ~Guest();
39     DISALLOW_COPY_ASSIGN_AND_MOVE(Guest);
40 
41     zx_status_t SetTrap(uint32_t kind, zx_vaddr_t addr, size_t len,
42                         fbl::RefPtr<PortDispatcher> port, uint64_t key);
43 
AddressSpace()44     hypervisor::GuestPhysicalAddressSpace* AddressSpace() const { return gpas_.get(); }
Traps()45     hypervisor::TrapMap* Traps() { return &traps_; }
MsrBitmapsAddress()46     zx_paddr_t MsrBitmapsAddress() const { return msr_bitmaps_page_.PhysicalAddress(); }
47 
48     zx_status_t AllocVpid(uint16_t* vpid);
49     zx_status_t FreeVpid(uint16_t vpid);
50 
51 private:
52     ktl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas_;
53     hypervisor::TrapMap traps_;
54     VmxPage msr_bitmaps_page_;
55 
56     fbl::Mutex vcpu_mutex_;
57     // TODO(alexlegg): Find a good place for this constant to live (max VCPUs).
58     hypervisor::IdAllocator<uint16_t, 64> TA_GUARDED(vcpu_mutex_) vpid_allocator_;
59 
60     Guest() = default;
61 };
62 
63 // Stores the local APIC state across VM exits.
64 struct LocalApicState {
65     // Timer for APIC timer.
66     timer_t timer;
67     // Tracks pending interrupts.
68     hypervisor::InterruptTracker<X86_INT_COUNT> interrupt_tracker;
69     // LVT timer configuration
70     uint32_t lvt_timer = LVT_MASKED; // Initial state is masked (Vol 3 Section 10.12.5.1).
71     uint32_t lvt_initial_count;
72     uint32_t lvt_divide_config;
73 };
74 
75 // System time is time since boot time and boot time is some fixed point in the past. This
76 // structure keeps track of the state required to update system time in guest.
77 struct pvclock_system_time;
78 struct PvClockState {
79     bool is_stable = false;
80     uint32_t version = 0;
81     pvclock_system_time* system_time = nullptr;
82     hypervisor::GuestPtr guest_ptr;
83 };
84 
85 // Represents a virtual CPU within a guest.
86 class Vcpu {
87 public:
88     static zx_status_t Create(Guest* guest, zx_vaddr_t entry, ktl::unique_ptr<Vcpu>* out);
89     ~Vcpu();
90     DISALLOW_COPY_ASSIGN_AND_MOVE(Vcpu);
91 
92     zx_status_t Resume(zx_port_packet_t* packet);
93     cpu_mask_t Interrupt(uint32_t vector, hypervisor::InterruptType type);
94     void VirtualInterrupt(uint32_t vector);
95     zx_status_t ReadState(uint32_t kind, void* buf, size_t len) const;
96     zx_status_t WriteState(uint32_t kind, const void* buf, size_t len);
97 
98 private:
99     Guest* guest_;
100     const uint16_t vpid_;
101     const thread_t* thread_;
102     fbl::atomic_bool running_;
103     LocalApicState local_apic_state_;
104     PvClockState pvclock_state_;
105     VmxState vmx_state_;
106     VmxPage host_msr_page_;
107     VmxPage guest_msr_page_;
108     VmxPage vmcs_page_;
109 
110     Vcpu(Guest* guest, uint16_t vpid, const thread_t* thread);
111 };
112