mask repeat prefix out of insn prefix
[fkvm-libfkvm.git] / libfkvm-common.h
blob002ed70a45295355072e2ca76868af4f936bc4db
1 /*-
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>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
26 * SUCH DAMAGE.
29 #ifndef FKVM_COMMON_H
30 #define FKVM_COMMON_H
32 #include <sys/fkvm.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <stdbool.h>
36 #include <assert.h>
37 #include <stdio.h>
38 #include <inttypes.h>
40 #include "libkvm.h"
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
60 /* MISC MACROS */
62 #ifndef ARRAY_SIZE
63 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
64 #endif
66 static inline void
67 _fkvm_exit(const char *func, int line, const char *msg)
69 fprintf(stderr, "libfkvm: Error in function %s on line %d: %s\n",
70 func, line, msg);
71 sleep(10);
72 exit(1);
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)")
83 /* QEMU PROTOTYPES */
84 /* These should really callbacks... */
86 extern void
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 */
93 struct kvm_context {
94 // Callbacks that KVM uses to emulate various unvirtualizable functionality
95 struct kvm_callbacks *callbacks;
96 void *opaque;
97 struct kvm_run *kvm_run[MAX_VCPUS];
98 unsigned long phys_mem_bytes;
99 void **phys_mem_ptr;
100 struct kvm_cpuid_entry *cpuid_entries[MAX_VCPUS];
101 int ncpuid_entries[MAX_VCPUS];
104 static inline void *
105 get_guest_base(struct kvm_context *kvm) {
106 return *kvm->phys_mem_ptr;
109 void
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,
118 uint16_t port,
119 size_t size,
120 bool rep,
121 bool string,
122 bool in);
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,
134 int cr_num,
135 bool is_write);
137 static uint64_t
138 mask_reg(uint64_t reg_value, size_t size)
140 switch (size) {
141 case 1:
142 reg_value &= 0x00000000000000FF;
143 break;
144 case 2:
145 reg_value &= 0x000000000000FFFF;
146 break;
147 case 4:
148 reg_value &= 0x00000000FFFFFFFF;
149 break;
150 case 8:
151 reg_value &= 0xFFFFFFFFFFFFFFFF;
152 break;
153 default:
154 assert(0);
155 return -1;
158 return reg_value;
161 static inline bool
162 _test_repeat_noop(const bool repeat, const size_t reg_size, struct kvm_regs *regs)
164 if (repeat) {
165 return mask_reg(regs->rcx, reg_size) == 0;
167 else {
168 return false;
172 static inline bool
173 _test_repeat_tail(const bool repeat, const size_t reg_size, struct kvm_regs *regs)
175 if (repeat) {
176 regs->rcx--;
177 return mask_reg(regs->rcx, reg_size) != 0;
179 else {
180 return false;
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 */
186 static inline size_t
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
196 else {
197 //TODO: verify that the default size for Protected Mode is 4 bytes
198 return 4; //Protected Mode
201 else {
202 return 2; //Real Mode
206 #endif