/* * This file is part of the Palacios Virtual Machine Monitor developed * by the V3VEE Project with funding from the United States National * Science Foundation and the Department of Energy. * * The V3VEE Project is a joint project between Northwestern University * and the University of New Mexico. You can find out more at * http://www.v3vee.org * * Copyright (c) 2012, Jack Lange * Copyright (c) 2012, The V3VEE Project * All rights reserved. * * Author: Jack Lange * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ #include #include #include #include #include #define VMWARE_CPUID_LEAF 0x40000000 #define VMWARE_MAGIC 0x564D5868 #define VMWARE_IO_PORT 0x5658 #define VMWARE_IO_VERSION 10 #define VMWARE_IO_GETHZ 45 static int io_read(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data) { uint64_t cpu_hz = V3_CPU_KHZ() * 1000; uint32_t magic = (uint32_t)(core->vm_regs.rax); uint32_t cmd = (uint32_t)(core->vm_regs.rcx); PrintError(core->vm_info, core, "VMWARE IO READ of size %d (command=%d)\n", length, cmd); if (magic != VMWARE_MAGIC) { PrintError(core->vm_info, core, "Invalid VMWARE MAgic number in Persona interface, ignoring for now\n"); return length; } if (cmd == VMWARE_IO_GETHZ) { // EAX Takes low bytes // EBX takes high bytes core->vm_regs.rax = cpu_hz & 0x00000000ffffffffLL; core->vm_regs.rbx = (cpu_hz >> 32) & 0x00000000ffffffffLL; } else { PrintError(core->vm_info, core, "Unhandled VMWARE IO operation\n"); return -1; } return length; } static int io_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) { PrintError(core->vm_info, core, "VMWARE IO PORT WRITE\n"); return -1; } static int vmware_cpuid_handler(struct guest_info * core, uint32_t cpuid, uint32_t * eax, uint32_t * ebx, uint32_t * ecx, uint32_t * edx, void * priv_data) { // Don't Care (?) *eax = 0; // Set VMWARE Vendor string in EBX,ECX,EDX memcpy(ebx, "VMwa", 4); memcpy(ecx, "reVM", 4); memcpy(edx, "ware", 4); return 0; } static int vmware_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { V3_Print(vm, VCORE_NONE, "Using VMWARE virtualization persona\n"); /* v3_cpuid_add_fields(vm, 0x00000001, 0, 0, 0, 0, 0x80000000, 0x80000000, 0, 0 ); */ v3_hook_io_port(vm, VMWARE_IO_PORT, io_read, io_write, NULL); v3_hook_cpuid(vm, VMWARE_CPUID_LEAF, vmware_cpuid_handler, NULL); // hook io port // set CPUID hypervisor enabled // set VMWare CPUID return 0; } static struct v3_extension_impl vmware_impl = { .name = "VMWARE_IFACE", .init = NULL, .vm_init = vmware_init, .vm_deinit = NULL, .core_init = NULL, .core_deinit = NULL, .on_entry = NULL, .on_exit = NULL }; register_extension(&vmware_impl);