* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* This file contain code under public domain from the hvdos project:
* https://github.com/mist64/hvdos
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "sysemu/hvf.h"
+#include "sysemu/runstate.h"
#include "hvf-i386.h"
#include "vmcs.h"
#include "vmx.h"
#include "exec/address-spaces.h"
#include "hw/i386/apic_internal.h"
-#include "hw/boards.h"
#include "qemu/main-loop.h"
#include "sysemu/accel.h"
-#include "sysemu/sysemu.h"
#include "target/i386/cpu.h"
-pthread_rwlock_t mem_lock = PTHREAD_RWLOCK_INITIALIZER;
HVFState *hvf_state;
-int hvf_disabled = 1;
static void assert_hvf_ok(hv_return_t ret)
{
}
/* Memory slots */
-hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t end)
+hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
{
hvf_slot *slot;
int x;
for (x = 0; x < hvf_state->num_slots; ++x) {
slot = &hvf_state->slots[x];
if (slot->size && start < (slot->start + slot->size) &&
- end > slot->start) {
+ (start + size) > slot->start) {
return slot;
}
}
};
struct mac_slot mac_slots[32];
-#define ALIGN(x, y) (((x) + (y) - 1) & ~((y) - 1))
-static int do_hvf_set_memory(hvf_slot *slot)
+static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
{
struct mac_slot *macslot;
- hv_memory_flags_t flags;
hv_return_t ret;
macslot = &mac_slots[slot->slot_id];
return 0;
}
- flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
-
macslot->present = 1;
macslot->gpa_start = slot->start;
macslot->size = slot->size;
{
hvf_slot *mem;
MemoryRegion *area = section->mr;
+ bool writeable = !area->readonly && !area->rom_device;
+ hv_memory_flags_t flags;
if (!memory_region_is_ram(area)) {
- return;
+ if (writeable) {
+ return;
+ } else if (!memory_region_is_romd(area)) {
+ /*
+ * If the memory device is not in romd_mode, then we actually want
+ * to remove the hvf memory slot so all accesses will trap.
+ */
+ add = false;
+ }
}
mem = hvf_find_overlap_slot(
section->offset_within_address_space,
- section->offset_within_address_space + int128_get64(section->size));
+ int128_get64(section->size));
if (mem && add) {
if (mem->size == int128_get64(section->size) &&
/* Region needs to be reset. set the size to 0 and remap it. */
if (mem) {
mem->size = 0;
- if (do_hvf_set_memory(mem)) {
+ if (do_hvf_set_memory(mem, 0)) {
error_report("Failed to reset overlapping slot");
abort();
}
return;
}
+ if (area->readonly ||
+ (!memory_region_is_ram(area) && memory_region_is_romd(area))) {
+ flags = HV_MEMORY_READ | HV_MEMORY_EXEC;
+ } else {
+ flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
+ }
+
/* Now make a new slot. */
int x;
mem->start = section->offset_within_address_space;
mem->region = area;
- if (do_hvf_set_memory(mem)) {
+ if (do_hvf_set_memory(mem, flags)) {
error_report("Error registering new memory slot");
abort();
}
return false;
}
- return !slot;
+ if (!slot) {
+ return true;
+ }
+ if (!memory_region_is_ram(slot->region) &&
+ !(read && memory_region_is_romd(slot->region))) {
+ return true;
+ }
+ return false;
}
static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
slot = hvf_find_overlap_slot(
section->offset_within_address_space,
- section->offset_within_address_space + int128_get64(section->size));
+ int128_get64(section->size));
/* protect region against writes; begin tracking it */
if (on) {
wreg(cpu->hvf_fd, HV_X86_R8 + i, 0x0);
}
- hv_vm_sync_tsc(0);
- cpu->halted = 0;
hv_vcpu_invalidate_tlb(cpu->hvf_fd);
hv_vcpu_flush(cpu->hvf_fd);
}
wvmcs(cpu->hvf_fd, VMCS_TPR_THRESHOLD, 0);
- hvf_reset_vcpu(cpu);
-
x86cpu = X86_CPU(cpu);
- x86cpu->env.kvm_xsave_buf = qemu_memalign(4096, 4096);
+ x86cpu->env.xsave_buf = qemu_memalign(4096, 4096);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_STAR, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_LSTAR, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_GSBASE, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_KERNELGSBASE, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_TSC_AUX, 1);
- /*hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);*/
+ hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_CS, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_EIP, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_ESP, 1);
return 0;
}
-void hvf_disable(int shouldDisable)
-{
- hvf_disabled = shouldDisable;
-}
-
static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_info)
{
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
- env->exception_injected = -1;
+ env->exception_nr = -1;
+ env->exception_pending = 0;
+ env->exception_injected = 0;
env->interrupt_injected = -1;
env->nmi_injected = false;
if (idtvec_info & VMCS_IDT_VEC_VALID) {
break;
case VMCS_IDT_VEC_HWEXCEPTION:
case VMCS_IDT_VEC_SWEXCEPTION:
- env->exception_injected = idtvec_info & VMCS_IDT_VEC_VECNUM;
+ env->exception_nr = idtvec_info & VMCS_IDT_VEC_VECNUM;
+ env->exception_injected = 1;
break;
case VMCS_IDT_VEC_PRIV_SWEXCEPTION:
default:
int ret = 0;
uint64_t rip = 0;
- cpu->halted = 0;
-
if (hvf_process_events(cpu)) {
return EXCP_HLT;
}
!(idtvec_info & VMCS_IDT_VEC_VALID)) {
cpu->halted = 1;
ret = EXCP_HLT;
+ break;
}
ret = EXCP_INTERRUPT;
break;
ret = EXCP_INTERRUPT;
break;
}
- /* Need to check if MMIO or unmmaped fault */
+ /* Need to check if MMIO or unmapped fault */
case EXIT_REASON_EPT_FAULT:
{
hvf_slot *slot;
vmx_set_nmi_blocking(cpu);
}
- slot = hvf_find_overlap_slot(gpa, gpa);
+ slot = hvf_find_overlap_slot(gpa, 1);
/* mmio */
if (ept_emulation_fault(slot, gpa, exit_qual)) {
struct x86_decode decode;
macvm_set_rip(cpu, rip + ins_len);
break;
case VMX_REASON_VMCALL:
- env->exception_injected = EXCP0D_GPF;
+ env->exception_nr = EXCP0D_GPF;
+ env->exception_injected = 1;
env->has_error_code = true;
env->error_code = 0;
break;
return ret;
}
-static bool hvf_allowed;
+bool hvf_allowed;
static int hvf_accel_init(MachineState *ms)
{
hv_return_t ret;
HVFState *s;
- hvf_disable(0);
ret = hv_vm_create(HV_VM_DEFAULT);
assert_hvf_ok(ret);