2 * Copyright (c) 2008 Brent Stephens <brents@rice.edu>
3 * Copyright (c) 2008 Diego Ongaro <diego.ongaro@rice.edu>
4 * Copyright (c) 2008 Oleg Pesok <olegpesok@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 /* HARDWARE DEFINITIONS */
44 #define MSR_EFER_LMA (1 << 10)
45 #define CR0_PE_MASK (1 << 0)
46 #define RFLAGS_VM (1 << 17)
48 #define RFLAGS_DF_SHIFT 10
49 #define RFLAGS_DF_MASK (1 << RFLAGS_DF_SHIFT)
51 #define CF_MASK 0x0001
52 #define PF_MASK 0x0002
53 #define AF_MASK 0x0008
54 #define ZF_MASK 0x0020
55 #define SF_MASK 0x0040
56 #define OF_MASK 0x0400
58 #define MSR_STAR 0xc0000081
63 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
67 _fkvm_exit(const char *func
, int line
, const char *msg
)
69 fprintf(stderr
, "libfkvm: Error in function %s on line %d: %s\n",
75 #define EXIT_API_STUB() _fkvm_exit(__FUNCTION__, __LINE__, \
76 "stubbed API function not implemented")
77 #define EXIT_ERR_PATH() _fkvm_exit(__FUNCTION__, __LINE__, \
78 "error path not implemented")
79 #define EXIT() _fkvm_exit(__FUNCTION__, __LINE__, \
80 "(no message provided)")
84 /* These should really callbacks... */
87 cpu_physical_memory_rw(unsigned long addr
, uint8_t *buf
, int len
, int is_write
);
89 extern unsigned long kvm_get_phys_addr(unsigned long gvaddr
);
91 /* LIBFKVM INTERNAL DATA STRUCTURES */
94 // Callbacks that KVM uses to emulate various unvirtualizable functionality
95 struct kvm_callbacks
*callbacks
;
97 struct kvm_run
*kvm_run
[MAX_VCPUS
];
98 unsigned long phys_mem_bytes
;
100 struct kvm_cpuid_entry
*cpuid_entries
[MAX_VCPUS
];
101 int ncpuid_entries
[MAX_VCPUS
];
105 get_guest_base(struct kvm_context
*kvm
) {
106 return *kvm
->phys_mem_ptr
;
110 cpu_virtual_memory_rw(unsigned long gvaddr
, uint8_t *buf
, int len
, int is_write
);
112 /* SHARED EMULATION HELPERS */
115 emulate_ioio(kvm_context_t kvm
,
116 struct kvm_regs
*regs
,
117 struct kvm_sregs
*sregs
,
125 emulate_mmio(kvm_context_t kvm
,
126 struct kvm_regs
*regs
,
127 struct kvm_sregs
*sregs
,
128 uint64_t fault_addr
);
131 emulate_cr(kvm_context_t kvm
,
132 struct kvm_regs
*regs
,
133 struct kvm_sregs
*sregs
,
138 mask_reg(uint64_t reg_value
, size_t size
)
142 reg_value
&= 0x00000000000000FF;
145 reg_value
&= 0x000000000000FFFF;
148 reg_value
&= 0x00000000FFFFFFFF;
151 reg_value
&= 0xFFFFFFFFFFFFFFFF;
162 _test_repeat_noop(const bool repeat
, const size_t reg_size
, struct kvm_regs
*regs
)
165 return mask_reg(regs
->rcx
, reg_size
) == 0;
173 _test_repeat_tail(const bool repeat
, const size_t reg_size
, struct kvm_regs
*regs
)
177 return mask_reg(regs
->rcx
, reg_size
) != 0;
184 /* XXX: What if 16 mode is trying to do 32-bit accesses? or other oddities?
185 * This is clearly broken and should be addressed */
187 _reg_size(const struct kvm_regs
*regs
, const struct kvm_sregs
*sregs
)
189 if ((sregs
->efer
& MSR_EFER_LMA
) != 0) {
190 return 8; //Long Mode
192 else if ((sregs
->cr0
& CR0_PE_MASK
) != 0) {
193 if ((regs
->rflags
& RFLAGS_VM
) != 0) {
194 return 2; //Virtual-8086 Mode
197 //TODO: verify that the default size for Protected Mode is 4 bytes
198 return 4; //Protected Mode
202 return 2; //Real Mode