This enables Palacios' internal implementation of vsnrprintf
+config BUILT_IN_USERSPACE_SYMS
+ bool "Enable build in versions of user space symbols needed"
+ default y
+ help
+ This enables a set of dummy symbols corresponding to user space.
+ This is needed to link user space libraries such as XED.
+
+
+config BUILT_IN_STDIN
+ bool "FILE * stdin;"
+ default y
+ depends on BUILT_IN_USERSPACE_SYMS
+ help
+ Includes the stdin file pointer
+
+config BUILT_IN_STDOUT
+ bool "FILE * stdout;"
+ default y
+ depends on BUILT_IN_USERSPACE_SYMS
+ help
+ Includes the stdout file pointer
+
+config BUILT_IN_STDERR
+ bool "FILE * stderr;"
+ default y
+ depends on BUILT_IN_USERSPACE_SYMS
+ help
+ Includes the stderr file pointer
+
+
+config BUILT_IN_FPRINTF
+ bool "fprintf();"
+ default y
+ depends on BUILT_IN_USERSPACE_SYMS
+ help
+ Includes fprintf()
+
+config BUILT_IN_PRINTF
+ bool "printf();"
+ default y
+ depends on BUILT_IN_USERSPACE_SYMS
+ help
+ Includes printf();
+
+config BUILT_IN_FFLUSH
+ bool "fflush();"
+ default y
+ depends on BUILT_IN_USERSPACE_SYMS
+ help
+ Includes fflush()
+
+config BUILT_IN_ABORT
+ bool "abort();"
+ default y
+ depends on BUILT_IN_USERSPACE_SYMS
+ help
+ Includes abort();
+
+
endmenu
VMCS_LINK_PTR_HIGH = 0x00002801,
VMCS_GUEST_DBG_CTL = 0x00002802,
VMCS_GUEST_DBG_CTL_HIGH = 0x00002803,
- VMCS_GUEST_EFER = 0x00002805,
+ VMCS_GUEST_EFER = 0x00002806,
VMCS_GUEST_EFER_HIGH = 0x00002807,
VMCS_GUEST_PERF_GLOBAL_CTRL = 0x00002808,
VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH = 0x00002809,
#define __VMM_H__
-//#include <palacios/vm_guest.h>
+/*#include <palacios/vm_guest.h>*/
#include <palacios/vmm_mem.h>
#include <palacios/vmm_types.h>
-#define V3_CREATE_THREAD(fn, arg, name) \
- do { \
- extern struct v3_os_hooks * os_hooks; \
- if ((os_hooks) && (os_hooks)->start_kernel_thread) { \
- (os_hooks)->start_kernel_thread(fn, arg, name); \
- } \
- } while (0)
-
-
-
-
#define V3_Hook_Interrupt(vm, irq) ({ \
int ret = 0; \
}) \
+#define V3_ACK_IRQ(irq) \
+ do { \
+ extern struct v3_os_hooks * os_hooks; \
+ if ((os_hooks) && (os_hooks)->ack_irq) { \
+ (os_hooks)->ack_irq(irq); \
+ } \
+ } while (0)
+
+
+
#define V3_Get_CPU() ({ \
int ret = 0; \
extern struct v3_os_hooks * os_hooks; \
ret; \
})
+
+#ifdef CONFIG_MULTITHREAD_OS
+
+#define V3_CREATE_THREAD(fn, arg, name) \
+ do { \
+ extern struct v3_os_hooks * os_hooks; \
+ if ((os_hooks) && (os_hooks)->start_kernel_thread) { \
+ (os_hooks)->start_kernel_thread(fn, arg, name); \
+ } \
+ } while (0)
+
+
+
+
+
+
#define V3_Call_On_CPU(cpu, fn, arg) \
do { \
extern struct v3_os_hooks * os_hooks; \
})
-#define V3_ACK_IRQ(irq) \
- do { \
- extern struct v3_os_hooks * os_hooks; \
- if ((os_hooks) && (os_hooks)->ack_irq) { \
- (os_hooks)->ack_irq(irq); \
- } \
- } while (0)
+#endif
+
#define V3_Reparent_Threadd() \
void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector);
-unsigned int v3_get_cpu_id();
v3_cpu_arch_t v3_get_cpu_type(int cpu_id);
int v3_vm_enter(struct guest_info * info);
-#endif //!__V3VEE__
+#endif /*!__V3VEE__ */
unsigned int (*get_cpu_khz)(void);
- void (*start_kernel_thread)(int (*fn)(void * arg), void * arg, char * thread_name);
void (*yield_cpu)(void);
void (*mutex_unlock)(void * mutex);
unsigned int (*get_cpu)(void);
+
+
+#ifdef CONFIG_MULTITHREAD_OS
+ void (*start_kernel_thread)(int (*fn)(void * arg), void * arg, char * thread_name);
void (*interrupt_cpu)(struct v3_vm_info * vm, int logical_cpu, int vector);
void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg);
void * (*start_thread_on_cpu)(int cpu_id, int (*fn)(void * arg), void * arg, char * thread_name);
};
-//
-//
-// This is the interrupt state that the VMM's interrupt handlers need to see
-//
+/*
+ *
+ * This is the interrupt state that the VMM's interrupt handlers need to see
+ */
struct v3_interrupt {
unsigned int irq;
unsigned int error;
- unsigned int should_ack; // Should the vmm ack this interrupt, or will
- // the host OS do it?
+ unsigned int should_ack; /* Should the vmm ack this interrupt, or will
+ * the host OS do it? */
};
struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data);
int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
-
+int v3_stop_vm(struct v3_vm_info * vm);
int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr);
-#endif // ! __V3VEE__
+#endif /* ! __V3VEE__ */
#endif
typedef ulong_t addr_t;
typedef ullong_t v3_reg_t;
-#endif // ! __V3VEE__
+#endif /* ! __V3VEE__ */
#endif
/* Standard I/O predefined streams
*/
static FILE _streams = {0, 0, 0, 0, 0, NULL, NULL, 0, 0};
+#ifdef CONFIG_BUILT_IN_STDIN
FILE *stdin = (&_streams);
+#endif
+
+#ifdef CONFIG_BUILT_IN_STDOUT
FILE *stdout = (&_streams);
+#endif
+
+#ifdef CONFIG_BUILT_IN_STDERR
FILE *stderr = (&_streams);
+#endif
-int fprintf(FILE *file, char *fmt, ...)
-{
+#ifdef CONFIG_BUILT_IN_FPRINTF
+int fprintf(FILE *file, char *fmt, ...) {
// PrintDebug("In fprintf!!\n");
-
return 0;
}
+#endif
-int printf(char *fmt, ...)
-{
+#ifdef CONFIG_BUILT_IN_PRINTF
+int printf(char *fmt, ...) {
// PrintDebug("In fprintf!!\n");
-
return 0;
-
}
+#endif
-int fflush(FILE *stream)
-{
+#ifdef CONFIG_BUILT_IN_FFLUSH
+int fflush(FILE *stream) {
//PrintDebug("In fflush!!\n");
-
return 0;
}
+#endif
+#ifdef CONFIG_BUILT_IN_ABORT
void abort(void)
{
//PrintDebug("Abort!!\n");
//__asm__ __volatile__("trap");
//__builtin_unreached();
-
- while(1);
-
+ while(1);
}
+#endif
reload_val = 0xffff;
}
- // TODO: Check this....
- // Is this correct???
- if (reload_val == 0) {
- reload_val = 1;
- }
-
oscillations -= ch->counter;
ch->counter = 0;
channel_cycles = 1;
reload_val -= reload_val % 2;
}
+ // TODO: Check this....
+ // Is this correct???
+ if (reload_val == 0) {
+ reload_val = 1;
+ }
+
channel_cycles += oscillations / reload_val;
oscillations = oscillations % reload_val;
#include <palacios/vmm_host_events.h>
#include <palacios/vmm_lock.h>
#include <palacios/vmm_string.h>
+#include <palacios/vm_guest.h>
#include <devices/console.h>
static int dma_read(struct guest_info * core, struct vm_device * dev, struct ide_channel * channel) {
struct ide_drive * drive = get_selected_drive(channel);
// This is at top level scope to do the EOT test at the end
- struct ide_dma_prd prd_entry;
+ struct ide_dma_prd prd_entry = {};
uint_t bytes_left = drive->transfer_length;
// Read in the data buffer....
static int dma_write(struct guest_info * core, struct vm_device * dev, struct ide_channel * channel) {
struct ide_drive * drive = get_selected_drive(channel);
// This is at top level scope to do the EOT test at the end
- struct ide_dma_prd prd_entry;
+ struct ide_dma_prd prd_entry = {};
uint_t bytes_left = drive->transfer_length;
v3_start_time(info);
while (1) {
+
+ if (info->vm_info->run_state == VM_STOPPED) {
+ info->core_run_state = CORE_STOPPED;
+ break;
+ }
+
if (v3_svm_enter(info) == -1) {
vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
addr_t host_addr;
break;
}
+
+
+ if (info->vm_info->run_state == VM_STOPPED) {
+ info->core_run_state = CORE_STOPPED;
+ break;
+ }
+
/*
if ((info->num_exits % 5000) == 0) {
#include <palacios/vmcs.h>
#include <palacios/vmcb.h>
static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_data) {
- v3_cpu_arch_t cpu_type = v3_get_cpu_type(v3_get_cpu_id());
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
int cpu_valid = 0;
v3_print_guest_state(core);
int v3_init_vm(struct v3_vm_info * vm) {
- v3_cpu_arch_t cpu_type = v3_get_cpu_type(v3_get_cpu_id());
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
int cpu_valid = 0;
if (v3_get_foreground_vm() == NULL) {
}
int v3_init_core(struct guest_info * core) {
- v3_cpu_arch_t cpu_type = v3_get_cpu_type(v3_get_cpu_id());
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
struct v3_vm_info * vm = core->vm_info;
/*
check_vmcs_read(VMCS_GUEST_RFLAGS, &(info->ctrl_regs.rflags));
if (((struct vmx_data *)info->vmm_data)->ia32e_avail) {
+#ifdef __V3_64BIT__
check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer));
+#else
+ uint32_t hi, lo;
+ check_vmcs_read(VMCS_GUEST_EFER, &hi);
+ check_vmcs_read(VMCS_GUEST_EFER_HIGH, &lo);
+ info->ctrl_regs.efer = ((uint64_t) hi << 32) | lo;
+#endif
}
error = v3_read_vmcs_segments(&(info->segments));
v3_init_vnet();
#endif
+
+#ifdef CONFIG_MULTITHREAD_OS
if ((hooks) && (hooks->call_on_cpu)) {
for (i = 0; i < num_cpus; i++) {
hooks->call_on_cpu(i, &init_cpu, (void *)(addr_t)i);
}
}
+#else
+ init_cpu(0);
+#endif
+
}
return 0;
}
-
+#ifdef CONFIG_MULTITHREAD_OS
// For the moment very ugly. Eventually we will shift the cpu_mask to an arbitrary sized type...
#define MAX_CORES 32
-int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
+
+static int start_vm_multicore(struct v3_vm_info * vm, unsigned int cpu_mask) {
uint32_t i;
char tname[16];
int vcore_id = 0;
return 0;
}
+#endif
+
+
+int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
+#ifdef CONFIG_MULTITHREAD_OS
+ return start_vm_multicore(vm, cpu_mask);
+#else
+ return start_core(&(vm->cores[0]));
+#endif
+}
+
+
+int v3_stop_vm(struct v3_vm_info * vm) {
+
+ vm->run_state = VM_STOPPED;
+
+
+ // force exit all cores via a cross call/IPI
+
+ // Wait for all cores to enter CORE_STOPPED state
+
+ // deinitialize guest (free memory, etc...)
+
+ return 0;
+}
#ifdef __V3_32BIT__
}
-
+#ifdef CONFIG_MULTITHREAD_OS
void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
extern struct v3_os_hooks * os_hooks;
(os_hooks)->interrupt_cpu(vm, logical_cpu, vector);
}
}
-
-
-
-unsigned int v3_get_cpu_id() {
- extern struct v3_os_hooks * os_hooks;
- unsigned int ret = (unsigned int)-1;
-
- if ((os_hooks) && (os_hooks)->get_cpu) {
- ret = os_hooks->get_cpu();
- }
-
- return ret;
-}
+#endif
struct v3_vm_info * v3_config_guest(void * cfg_blob) {
- v3_cpu_arch_t cpu_type = v3_get_cpu_type(v3_get_cpu_id());
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
struct v3_config * cfg_data = NULL;
struct v3_vm_info * vm = NULL;
int num_cores = 0;
addr_t tmp_rcx = 0;
addr_t src_addr = 0;
- if (dec_instr->dst_operand.operand != write_gva) {
- PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
- (void *)dec_instr->dst_operand.operand, (void *)write_gva);
- return -1;
+ if (info->shdw_pg_mode == SHADOW_PAGING) {
+ if (dec_instr->dst_operand.operand != write_gva) {
+ PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
+ (void *)dec_instr->dst_operand.operand, (void *)write_gva);
+ return -1;
+ }
+ } else {
+ // Nested paging (Need check??)
}
-
+
/*emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
dec_instr->str_op_length :
(0x1000 - PAGE_OFFSET_4KB(write_gva)));*/
static int handle_mem_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa,
struct v3_mem_region * reg, pf_error_t access_info) {
struct mem_hook * hook = reg->priv_data;
+ struct v3_mem_hooks * hooks = &(info->vm_info->mem_hooks);
addr_t op_addr = 0;
if (reg->flags.alloced == 0) {
- op_addr = hook->hook_hva;
+ if (hook->hook_hva & 0xfff) {
+ op_addr = (addr_t)(hooks->hook_hvas + (PAGE_SIZE * info->cpu_id));
+ } else {
+ op_addr = hook->hook_hva;
+ }
} else {
if (v3_gpa_to_hva(info, guest_pa, &op_addr) == -1) {
PrintError("Could not translate hook address (%p)\n", (void *)guest_pa);
struct v3_mem_region * entry = NULL;
struct mem_hook * hook = V3_Malloc(sizeof(struct mem_hook));
- struct v3_mem_hooks * hooks = &(vm->mem_hooks);
+ // struct v3_mem_hooks * hooks = &(vm->mem_hooks);
memset(hook, 0, sizeof(struct mem_hook));
hook->write = write;
hook->read = read;
hook->priv_data = priv_data;
- hook->hook_hva = (addr_t)hooks->hook_hvas + (PAGE_SIZE_4KB * core_id);
+ hook->hook_hva = (addr_t)0xfff;
entry = v3_create_mem_region(vm, core_id, guest_addr_start, guest_addr_end);
info->dbg_regs.dr7 = 0x400;
+#ifdef __V3_64BIT__
vmx_ret |= check_vmcs_write(VMCS_LINK_PTR, (addr_t)0xffffffffffffffffULL);
-
+#else
+ vmx_ret |= check_vmcs_write(VMCS_LINK_PTR, (addr_t)0xffffffffUL);
+ vmx_ret |= check_vmcs_write(VMCS_LINK_PTR_HIGH, (addr_t)0xffffffffUL);
+#endif
if (v3_update_vmcs_ctrl_fields(info)) {
PrintError("Could not write control fields!\n");
v3_start_time(info);
while (1) {
+
+ if (info->vm_info->run_state == VM_STOPPED) {
+ info->core_run_state = CORE_STOPPED;
+ break;
+ }
+
if (v3_vmx_enter(info) == -1) {
v3_print_vmcs();
print_exit_log(info);
return -1;
}
+
+
+ if (info->vm_info->run_state == VM_STOPPED) {
+ info->core_run_state = CORE_STOPPED;
+ break;
+ }
/*
if ((info->num_exits % 5000) == 0) {
V3_Print("VMX Exit number %d\n", (uint32_t)info->num_exits);
#define PRE_LAUNCH(return_target) \
+ push %ebp; \
+ movl %esp, %ebp; \
pushf; \
PUSHA; \
- pushl %edi; \
- pushl %edx; \
+ \
+ movl 8(%ebp), %edi; \
+ movl 12(%ebp), %esi; \
+ movl 16(%ebp), %edx; \
\
movl %esp, %eax; \
movl $VMCS_HOST_RSP, %ebx; \
restore_registers(%edi);
+// 32 bit GCC passes arguments via stack
+
.align 4
.globl v3_vmx_resume
v3_vmx_resume:
jmp .Lreturn
.Lreturn:
+ pop %ebp;
ret
#endif
return memcmp(s + slen - sublen, sub, sublen);
}
+#ifdef __minix
+/* MINIX does not support memory-mapped files;
+ * fortunately we only need to read the file which means we can just
+ * use malloc and read to achieve a similar effect
+ */
+#define mmap mmap_hack
+#define munmap munmap_hack
+
+#include <assert.h>
+
+static void *mmap(void *start, size_t size, int prot, int flags, int fd,
+ off_t offset)
+{
+ void *map;
+ off_t position;
+ ssize_t sizeread;
+
+ /* verify that we can handle this request */
+ assert(start == NULL);
+ assert(prot == PROT_READ);
+ assert(flags == MAP_PRIVATE);
+
+ /* seek to offset, storing old file pointer */
+ if ((position = lseek(fd, 0, SEEK_CUR)) == -1 ||
+ lseek(fd, offset, SEEK_SET) != offset) {
+ perror("fixdep: lseek");
+ }
+
+ /* allocate memory for file buffer */
+ map = malloc(size);
+ if (map) {
+ /* read the file data */
+ sizeread = read(fd, map, size);
+ if (sizeread != size) {
+ /* read failed or file size not as expected,
+ * return mmap error code
+ */
+ free(map);
+ map = (void *) -1L;
+ }
+ } else {
+ /* malloc failed, return mmap error code */
+ map = (void *) -1L;
+ }
+
+ /* restore old file pointer */
+ if (lseek(fd, position, SEEK_SET) != position) {
+ perror("fixdep: lseek");
+ }
+
+ return map;
+}
+
+static int munmap(void *start, size_t length)
+{
+ free(start);
+ return 0;
+}
+#endif
+
void do_config_file(char *filename)
{
struct stat st;