mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* target/i386: Fix model number of Zhaoxin YongFeng vCPU template * target/i386: Reset parked vCPUs together with the online ones * scsi: add conversion from ENODEV to sense * target/i386: tweaks to flag handling * target/i386: tweaks to SHLD/SHRD code generation * target/i386: remove some global temporaries from TCG * target/i386: pull emulator outside target/i386/hvf * host/i386: consolidate getting host CPU vendor * rust/hpet: preparation for migration support * rust/pl011: bring over more commits from C version # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmgItXAUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroNrwgf/TAiz0LdO9q3O9Ob2FJVdAL6jn0YH # /yDjAOpRT9WBOoKi+fikMuX6FlxVNpb6K5xx/WMbXDiO3PLMMNYet3fnXpjGBCj0 # aLcrHxG0TUfUk2mYssBoyZ1IG5bjevRZjjRFAXGubJZp/l6oXCCPrZ4mkW9MRP9U # GzzwhSC2U0CuZREz4YxurPZmgx9lKRcf71lVExh6AHWpPPU3tWk0F51zE+PxObWk # WvNwVvBPPYryC88DcN9YytiNn0jLtIozf3sxTDAi6jsg5T6PzeGU+LTck3DtQJIY # 3eAoTpLW1ZEYMIcbA/upLHz+obqDCgWZUPQydHvJS/xlIcnO+RYkWobOxg== # =06CN # -----END PGP SIGNATURE----- # gpg: Signature made Wed 23 Apr 2025 05:40:00 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (34 commits) rust/hw/char/pl011: Extract DR write logic into separate function rust/hw/char/pl011: Extract extract DR read logic into separate function rust/vmstate_test: Fix typo in test_vmstate_macro_array_of_pointer_wrapped() rust/hpet: Fix a clippy error rust/hpet: convert HPETTimer index to u8 type rust/hpet: convert num_timers to u8 type i386/cpu: Consolidate the helper to get Host's vendor target/i386/emulate: remove flags_mask MAINTAINERS: add an entry for the x86 instruction emulator target/i386: move x86 instruction emulator out of hvf target/i386/emulate: add a panic.h target/i386: add a directory for x86 instruction emulator target/i386/hvf: rename some include guards target/i386/hvf: drop unused headers target/i386: rename lazy flags field and its type target/i386/hvf: provide and use simulate_{wrmsr, rdmsr} in emul_ops target/i386/hvf: provide and use write_mem in emul_ops target/i386/hvf: use emul_ops->read_mem in x86_emu.c target/i386: rename hvf_mmio_buf to emu_mmio_buf target/i386/hvf: provide and use handle_io in emul_ops ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -534,6 +534,14 @@ S: Supported
|
||||
F: target/i386/whpx/
|
||||
F: include/system/whpx.h
|
||||
|
||||
X86 Instruction Emulator
|
||||
M: Cameron Esfahani <dirty@apple.com>
|
||||
M: Roman Bolshakov <rbolshakov@ddn.com>
|
||||
R: Phil Dennis-Jordan <phil@philjordan.eu>
|
||||
R: Wei Liu <wei.liu@kernel.org>
|
||||
S: Maintained
|
||||
F: target/i386/emulate/
|
||||
|
||||
Guest CPU Cores (Xen)
|
||||
---------------------
|
||||
X86 Xen CPUs
|
||||
|
||||
+5
-3
@@ -437,9 +437,8 @@ int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id)
|
||||
return kvm_fd;
|
||||
}
|
||||
|
||||
static void kvm_reset_parked_vcpus(void *param)
|
||||
static void kvm_reset_parked_vcpus(KVMState *s)
|
||||
{
|
||||
KVMState *s = param;
|
||||
struct KVMParkedVcpu *cpu;
|
||||
|
||||
QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
|
||||
@@ -2738,7 +2737,6 @@ static int kvm_init(MachineState *ms)
|
||||
}
|
||||
|
||||
qemu_register_reset(kvm_unpoison_all, NULL);
|
||||
qemu_register_reset(kvm_reset_parked_vcpus, s);
|
||||
|
||||
if (s->kernel_irqchip_allowed) {
|
||||
kvm_irqchip_create(s);
|
||||
@@ -2908,6 +2906,10 @@ static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg
|
||||
void kvm_cpu_synchronize_post_reset(CPUState *cpu)
|
||||
{
|
||||
run_on_cpu(cpu, do_kvm_cpu_synchronize_post_reset, RUN_ON_CPU_NULL);
|
||||
|
||||
if (cpu == first_cpu) {
|
||||
kvm_reset_parked_vcpus(kvm_state);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
|
||||
|
||||
@@ -190,25 +190,7 @@ impl PL011Registers {
|
||||
|
||||
let mut update = false;
|
||||
let result = match offset {
|
||||
DR => {
|
||||
self.flags.set_receive_fifo_full(false);
|
||||
let c = self.read_fifo[self.read_pos];
|
||||
if self.read_count > 0 {
|
||||
self.read_count -= 1;
|
||||
self.read_pos = (self.read_pos + 1) & (self.fifo_depth() - 1);
|
||||
}
|
||||
if self.read_count == 0 {
|
||||
self.flags.set_receive_fifo_empty(true);
|
||||
}
|
||||
if self.read_count + 1 == self.read_trigger {
|
||||
self.int_level &= !Interrupt::RX.0;
|
||||
}
|
||||
// Update error bits.
|
||||
self.receive_status_error_clear.set_from_data(c);
|
||||
// Must call qemu_chr_fe_accept_input
|
||||
update = true;
|
||||
u32::from(c)
|
||||
}
|
||||
DR => self.read_data_register(&mut update),
|
||||
RSR => u32::from(self.receive_status_error_clear),
|
||||
FR => u32::from(self.flags),
|
||||
FBRD => self.fbrd,
|
||||
@@ -239,12 +221,7 @@ impl PL011Registers {
|
||||
// eprintln!("write offset {offset} value {value}");
|
||||
use RegisterOffset::*;
|
||||
match offset {
|
||||
DR => {
|
||||
// interrupts always checked
|
||||
let _ = self.loopback_tx(value.into());
|
||||
self.int_level |= Interrupt::TX.0;
|
||||
return true;
|
||||
}
|
||||
DR => return self.write_data_register(value),
|
||||
RSR => {
|
||||
self.receive_status_error_clear = 0.into();
|
||||
}
|
||||
@@ -306,6 +283,32 @@ impl PL011Registers {
|
||||
false
|
||||
}
|
||||
|
||||
fn read_data_register(&mut self, update: &mut bool) -> u32 {
|
||||
self.flags.set_receive_fifo_full(false);
|
||||
let c = self.read_fifo[self.read_pos];
|
||||
|
||||
if self.read_count > 0 {
|
||||
self.read_count -= 1;
|
||||
self.read_pos = (self.read_pos + 1) & (self.fifo_depth() - 1);
|
||||
}
|
||||
if self.read_count == 0 {
|
||||
self.flags.set_receive_fifo_empty(true);
|
||||
}
|
||||
if self.read_count + 1 == self.read_trigger {
|
||||
self.int_level &= !Interrupt::RX.0;
|
||||
}
|
||||
self.receive_status_error_clear.set_from_data(c);
|
||||
*update = true;
|
||||
u32::from(c)
|
||||
}
|
||||
|
||||
fn write_data_register(&mut self, value: u32) -> bool {
|
||||
// interrupts always checked
|
||||
let _ = self.loopback_tx(value.into());
|
||||
self.int_level |= Interrupt::TX.0;
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn loopback_tx(&mut self, value: registers::Data) -> bool {
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::{
|
||||
use qemu_api::{
|
||||
bindings::{
|
||||
address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_prop_bool,
|
||||
qdev_prop_uint32, qdev_prop_usize,
|
||||
qdev_prop_uint32, qdev_prop_uint8,
|
||||
},
|
||||
c_str,
|
||||
cell::{BqlCell, BqlRefCell},
|
||||
@@ -34,9 +34,9 @@ use crate::fw_cfg::HPETFwConfig;
|
||||
const HPET_REG_SPACE_LEN: u64 = 0x400; // 1024 bytes
|
||||
|
||||
/// Minimum recommended hardware implementation.
|
||||
const HPET_MIN_TIMERS: usize = 3;
|
||||
const HPET_MIN_TIMERS: u8 = 3;
|
||||
/// Maximum timers in each timer block.
|
||||
const HPET_MAX_TIMERS: usize = 32;
|
||||
const HPET_MAX_TIMERS: u8 = 32;
|
||||
|
||||
/// Flags that HPETState.flags supports.
|
||||
const HPET_FLAG_MSI_SUPPORT_SHIFT: usize = 0;
|
||||
@@ -184,7 +184,7 @@ fn timer_handler(timer_cell: &BqlRefCell<HPETTimer>) {
|
||||
pub struct HPETTimer {
|
||||
/// timer N index within the timer block (`HPETState`)
|
||||
#[doc(alias = "tn")]
|
||||
index: usize,
|
||||
index: u8,
|
||||
qemu_timer: Timer,
|
||||
/// timer block abstraction containing this timer
|
||||
state: NonNull<HPETState>,
|
||||
@@ -210,7 +210,7 @@ pub struct HPETTimer {
|
||||
}
|
||||
|
||||
impl HPETTimer {
|
||||
fn init(&mut self, index: usize, state: &HPETState) {
|
||||
fn init(&mut self, index: u8, state: &HPETState) {
|
||||
*self = HPETTimer {
|
||||
index,
|
||||
// SAFETY: the HPETTimer will only be used after the timer
|
||||
@@ -235,7 +235,7 @@ impl HPETTimer {
|
||||
Timer::NS,
|
||||
0,
|
||||
timer_handler,
|
||||
&state.timers[self.index],
|
||||
&state.timers[self.index as usize],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ impl HPETTimer {
|
||||
}
|
||||
|
||||
fn is_int_active(&self) -> bool {
|
||||
self.get_state().is_timer_int_active(self.index)
|
||||
self.get_state().is_timer_int_active(self.index.into())
|
||||
}
|
||||
|
||||
const fn is_fsb_route_enabled(&self) -> bool {
|
||||
@@ -353,7 +353,7 @@ impl HPETTimer {
|
||||
// still operate and generate appropriate status bits, but
|
||||
// will not cause an interrupt"
|
||||
self.get_state()
|
||||
.update_int_status(self.index as u32, set && self.is_int_level_triggered());
|
||||
.update_int_status(self.index.into(), set && self.is_int_level_triggered());
|
||||
self.set_irq(set);
|
||||
}
|
||||
|
||||
@@ -559,14 +559,19 @@ pub struct HPETState {
|
||||
|
||||
/// HPET timer array managed by this timer block.
|
||||
#[doc(alias = "timer")]
|
||||
timers: [BqlRefCell<HPETTimer>; HPET_MAX_TIMERS],
|
||||
num_timers: BqlCell<usize>,
|
||||
timers: [BqlRefCell<HPETTimer>; HPET_MAX_TIMERS as usize],
|
||||
num_timers: BqlCell<u8>,
|
||||
|
||||
/// Instance id (HPET timer block ID).
|
||||
hpet_id: BqlCell<usize>,
|
||||
}
|
||||
|
||||
impl HPETState {
|
||||
// Get num_timers with `usize` type, which is useful to play with array index.
|
||||
fn get_num_timers(&self) -> usize {
|
||||
self.num_timers.get().into()
|
||||
}
|
||||
|
||||
const fn has_msi_flag(&self) -> bool {
|
||||
self.flags & (1 << HPET_FLAG_MSI_SUPPORT_SHIFT) != 0
|
||||
}
|
||||
@@ -606,7 +611,7 @@ impl HPETState {
|
||||
|
||||
fn init_timer(&self) {
|
||||
for (index, timer) in self.timers.iter().enumerate() {
|
||||
timer.borrow_mut().init(index, self);
|
||||
timer.borrow_mut().init(index.try_into().unwrap(), self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,7 +633,7 @@ impl HPETState {
|
||||
self.hpet_offset
|
||||
.set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns());
|
||||
|
||||
for timer in self.timers.iter().take(self.num_timers.get()) {
|
||||
for timer in self.timers.iter().take(self.get_num_timers()) {
|
||||
let mut t = timer.borrow_mut();
|
||||
|
||||
if t.is_int_enabled() && t.is_int_active() {
|
||||
@@ -640,7 +645,7 @@ impl HPETState {
|
||||
// Halt main counter and disable interrupt generation.
|
||||
self.counter.set(self.get_ticks());
|
||||
|
||||
for timer in self.timers.iter().take(self.num_timers.get()) {
|
||||
for timer in self.timers.iter().take(self.get_num_timers()) {
|
||||
timer.borrow_mut().del_timer();
|
||||
}
|
||||
}
|
||||
@@ -663,7 +668,7 @@ impl HPETState {
|
||||
let new_val = val << shift;
|
||||
let cleared = new_val & self.int_status.get();
|
||||
|
||||
for (index, timer) in self.timers.iter().take(self.num_timers.get()).enumerate() {
|
||||
for (index, timer) in self.timers.iter().take(self.get_num_timers()).enumerate() {
|
||||
if cleared & (1 << index) != 0 {
|
||||
timer.borrow_mut().update_irq(false);
|
||||
}
|
||||
@@ -737,7 +742,7 @@ impl HPETState {
|
||||
1 << HPET_CAP_COUNT_SIZE_CAP_SHIFT |
|
||||
1 << HPET_CAP_LEG_RT_CAP_SHIFT |
|
||||
HPET_CAP_VENDER_ID_VALUE << HPET_CAP_VENDER_ID_SHIFT |
|
||||
((self.num_timers.get() - 1) as u64) << HPET_CAP_NUM_TIM_SHIFT | // indicate the last timer
|
||||
((self.get_num_timers() - 1) as u64) << HPET_CAP_NUM_TIM_SHIFT | // indicate the last timer
|
||||
(HPET_CLK_PERIOD * FS_PER_NS) << HPET_CAP_CNT_CLK_PERIOD_SHIFT, // 10 ns
|
||||
);
|
||||
|
||||
@@ -746,7 +751,7 @@ impl HPETState {
|
||||
}
|
||||
|
||||
fn reset_hold(&self, _type: ResetType) {
|
||||
for timer in self.timers.iter().take(self.num_timers.get()) {
|
||||
for timer in self.timers.iter().take(self.get_num_timers()) {
|
||||
timer.borrow_mut().reset();
|
||||
}
|
||||
|
||||
@@ -774,7 +779,7 @@ impl HPETState {
|
||||
GlobalRegister::try_from(addr).map(HPETRegister::Global)
|
||||
} else {
|
||||
let timer_id: usize = ((addr - 0x100) / 0x20) as usize;
|
||||
if timer_id <= self.num_timers.get() {
|
||||
if timer_id <= self.get_num_timers() {
|
||||
// TODO: Add trace point - trace_hpet_ram_[read|write]_timer_id(timer_id)
|
||||
TimerRegister::try_from(addr & 0x18)
|
||||
.map(|reg| HPETRegister::Timer(&self.timers[timer_id], reg))
|
||||
@@ -859,8 +864,8 @@ qemu_api::declare_properties! {
|
||||
c_str!("timers"),
|
||||
HPETState,
|
||||
num_timers,
|
||||
unsafe { &qdev_prop_usize },
|
||||
usize,
|
||||
unsafe { &qdev_prop_uint8 },
|
||||
u8,
|
||||
default = HPET_MIN_TIMERS
|
||||
),
|
||||
qemu_api::define_property!(
|
||||
|
||||
@@ -383,12 +383,12 @@ fn test_vmstate_macro_array_of_pointer_wrapped() {
|
||||
);
|
||||
assert_eq!(foo_fields[3].offset, (FOO_ARRAY_MAX + 2) * PTR_SIZE);
|
||||
assert_eq!(foo_fields[3].num_offset, 0);
|
||||
assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 });
|
||||
assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_uint8 });
|
||||
assert_eq!(foo_fields[3].version_id, 0);
|
||||
assert_eq!(foo_fields[3].size, PTR_SIZE);
|
||||
assert_eq!(foo_fields[3].num, FOO_ARRAY_MAX as i32);
|
||||
assert_eq!(
|
||||
foo_fields[2].flags.0,
|
||||
foo_fields[3].flags.0,
|
||||
VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0
|
||||
);
|
||||
assert!(foo_fields[3].vmsd.is_null());
|
||||
|
||||
+10
-3
@@ -587,20 +587,27 @@ int scsi_sense_from_errno(int errno_value, SCSISense *sense)
|
||||
return GOOD;
|
||||
case EDOM:
|
||||
return TASK_SET_FULL;
|
||||
#if ENODEV != ENOMEDIUM
|
||||
case ENODEV:
|
||||
/*
|
||||
* Some of the BSDs have ENODEV and ENOMEDIUM as synonyms. For
|
||||
* everyone else, give a more severe sense code for ENODEV.
|
||||
*/
|
||||
#endif
|
||||
#ifdef CONFIG_LINUX
|
||||
/* These errno mapping are specific to Linux. For more information:
|
||||
* - scsi_check_sense and scsi_decide_disposition in drivers/scsi/scsi_error.c
|
||||
* - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c
|
||||
* - blk_errors[] in block/blk-core.c
|
||||
*/
|
||||
case EREMOTEIO:
|
||||
*sense = SENSE_CODE(TARGET_FAILURE);
|
||||
return CHECK_CONDITION;
|
||||
case EBADE:
|
||||
return RESERVATION_CONFLICT;
|
||||
case ENODATA:
|
||||
*sense = SENSE_CODE(READ_ERROR);
|
||||
return CHECK_CONDITION;
|
||||
case EREMOTEIO:
|
||||
*sense = SENSE_CODE(TARGET_FAILURE);
|
||||
return CHECK_CONDITION;
|
||||
#endif
|
||||
case ENOMEDIUM:
|
||||
*sense = SENSE_CODE(NO_MEDIUM);
|
||||
|
||||
@@ -5621,6 +5621,18 @@ static const X86CPUDefinition builtin_x86_defs[] = {
|
||||
.features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Zhaoxin YongFeng Processor",
|
||||
.versions = (X86CPUVersionDefinition[]) {
|
||||
{ .version = 1 },
|
||||
{
|
||||
.version = 2,
|
||||
.note = "with the correct model number",
|
||||
.props = (PropValue[]) {
|
||||
{ "model", "0x5b" },
|
||||
{ /* end of list */ }
|
||||
}
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+29
-4
@@ -1811,10 +1811,10 @@ typedef struct CPUCaches {
|
||||
CPUCacheInfo *l3_cache;
|
||||
} CPUCaches;
|
||||
|
||||
typedef struct HVFX86LazyFlags {
|
||||
typedef struct X86LazyFlags {
|
||||
target_ulong result;
|
||||
target_ulong auxbits;
|
||||
} HVFX86LazyFlags;
|
||||
} X86LazyFlags;
|
||||
|
||||
typedef struct CPUArchState {
|
||||
/* standard registers */
|
||||
@@ -2108,8 +2108,8 @@ typedef struct CPUArchState {
|
||||
QemuMutex xen_timers_lock;
|
||||
#endif
|
||||
#if defined(CONFIG_HVF)
|
||||
HVFX86LazyFlags hvf_lflags;
|
||||
void *hvf_mmio_buf;
|
||||
X86LazyFlags lflags;
|
||||
void *emu_mmio_buf;
|
||||
#endif
|
||||
|
||||
uint64_t mcg_cap;
|
||||
@@ -2843,4 +2843,29 @@ static inline bool ctl_has_irq(CPUX86State *env)
|
||||
# define TARGET_VSYSCALL_PAGE (UINT64_C(-10) << 20)
|
||||
#endif
|
||||
|
||||
/* majority(NOT a, b, c) = (a ^ b) ? b : c */
|
||||
#define MAJ_INV1(a, b, c) ((((a) ^ (b)) & ((b) ^ (c))) ^ (c))
|
||||
|
||||
/*
|
||||
* ADD_COUT_VEC(x, y) = majority((x + y) ^ x ^ y, x, y)
|
||||
*
|
||||
* If two corresponding bits in x and y are the same, that's the carry
|
||||
* independent of the value (x+y)^x^y. Hence x^y can be replaced with
|
||||
* 1 in (x+y)^x^y, resulting in majority(NOT (x+y), x, y)
|
||||
*/
|
||||
#define ADD_COUT_VEC(op1, op2, result) \
|
||||
MAJ_INV1(result, op1, op2)
|
||||
|
||||
/*
|
||||
* SUB_COUT_VEC(x, y) = NOT majority(x, NOT y, (x - y) ^ x ^ NOT y)
|
||||
* = majority(NOT x, y, (x - y) ^ x ^ y)
|
||||
*
|
||||
* Note that the carry out is actually a borrow, i.e. it is inverted.
|
||||
* If two corresponding bits in x and y are different, the value of the
|
||||
* bit in (x-y)^x^y likewise does not matter. Hence, x^y can be replaced
|
||||
* with 0 in (x-y)^x^y, resulting in majority(NOT x, y, x-y)
|
||||
*/
|
||||
#define SUB_COUT_VEC(op1, op2, result) \
|
||||
MAJ_INV1(op1, op2, result)
|
||||
|
||||
#endif /* I386_CPU_H */
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files(
|
||||
'x86_decode.c',
|
||||
'x86_emu.c',
|
||||
'x86_flags.c',
|
||||
))
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Veertu Inc,
|
||||
* Copyright (C) 2017 Google Inc,
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#ifndef X86_EMU_PANIC_H
|
||||
#define X86_EMU_PANIC_H
|
||||
|
||||
#define VM_PANIC(x) {\
|
||||
printf("%s\n", x); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define VM_PANIC_ON(x) {\
|
||||
if (x) { \
|
||||
printf("%s\n", #x); \
|
||||
abort(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define VM_PANIC_EX(...) {\
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define VM_PANIC_ON_EX(x, ...) {\
|
||||
if (x) { \
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -16,8 +16,8 @@
|
||||
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HVF_X86_H
|
||||
#define HVF_X86_H
|
||||
#ifndef X86_EMU_DEFS_H
|
||||
#define X86_EMU_DEFS_H
|
||||
|
||||
typedef struct x86_register {
|
||||
union {
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@
|
||||
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HVF_X86_DECODE_H
|
||||
#define HVF_X86_DECODE_H
|
||||
#ifndef X86_EMU_DECODE_H
|
||||
#define X86_EMU_DECODE_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
@@ -295,8 +295,6 @@ typedef struct x86_decode {
|
||||
struct x86_modrm modrm;
|
||||
struct x86_decode_op op[4];
|
||||
bool is_fpu;
|
||||
uint32_t flags_mask;
|
||||
|
||||
} x86_decode;
|
||||
|
||||
uint64_t sign(uint64_t val, int size);
|
||||
@@ -40,11 +40,7 @@
|
||||
#include "x86_decode.h"
|
||||
#include "x86.h"
|
||||
#include "x86_emu.h"
|
||||
#include "x86_mmu.h"
|
||||
#include "x86_flags.h"
|
||||
#include "vmcs.h"
|
||||
#include "vmx.h"
|
||||
#include "hvf-i386.h"
|
||||
|
||||
#define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \
|
||||
{ \
|
||||
@@ -179,13 +175,13 @@ void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int siz
|
||||
write_val_to_reg(ptr, val, size);
|
||||
return;
|
||||
}
|
||||
vmx_write_mem(env_cpu(env), ptr, &val, size);
|
||||
emul_ops->write_mem(env_cpu(env), &val, ptr, size);
|
||||
}
|
||||
|
||||
uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
|
||||
{
|
||||
vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, ptr, bytes);
|
||||
return env->hvf_mmio_buf;
|
||||
emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
|
||||
return env->emu_mmio_buf;
|
||||
}
|
||||
|
||||
|
||||
@@ -396,18 +392,18 @@ static void exec_out(CPUX86State *env, struct x86_decode *decode)
|
||||
{
|
||||
switch (decode->opcode[0]) {
|
||||
case 0xe6:
|
||||
hvf_handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
|
||||
emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
|
||||
break;
|
||||
case 0xe7:
|
||||
hvf_handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
|
||||
decode->operand_size, 1);
|
||||
emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
|
||||
decode->operand_size, 1);
|
||||
break;
|
||||
case 0xee:
|
||||
hvf_handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
|
||||
emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
|
||||
break;
|
||||
case 0xef:
|
||||
hvf_handle_io(env_cpu(env), DX(env), &RAX(env), 1,
|
||||
decode->operand_size, 1);
|
||||
emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1,
|
||||
decode->operand_size, 1);
|
||||
break;
|
||||
default:
|
||||
VM_PANIC("Bad out opcode\n");
|
||||
@@ -421,10 +417,10 @@ static void exec_in(CPUX86State *env, struct x86_decode *decode)
|
||||
target_ulong val = 0;
|
||||
switch (decode->opcode[0]) {
|
||||
case 0xe4:
|
||||
hvf_handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
|
||||
emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
|
||||
break;
|
||||
case 0xe5:
|
||||
hvf_handle_io(env_cpu(env), decode->op[0].val, &val, 0,
|
||||
emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0,
|
||||
decode->operand_size, 1);
|
||||
if (decode->operand_size == 2) {
|
||||
AX(env) = val;
|
||||
@@ -433,10 +429,11 @@ static void exec_in(CPUX86State *env, struct x86_decode *decode)
|
||||
}
|
||||
break;
|
||||
case 0xec:
|
||||
hvf_handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
|
||||
emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
|
||||
break;
|
||||
case 0xed:
|
||||
hvf_handle_io(env_cpu(env), DX(env), &val, 0, decode->operand_size, 1);
|
||||
emul_ops->handle_io(env_cpu(env), DX(env), &val, 0,
|
||||
decode->operand_size, 1);
|
||||
if (decode->operand_size == 2) {
|
||||
AX(env) = val;
|
||||
} else {
|
||||
@@ -486,10 +483,10 @@ static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
|
||||
target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
|
||||
decode->addressing_size, R_ES);
|
||||
|
||||
hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 0,
|
||||
decode->operand_size, 1);
|
||||
vmx_write_mem(env_cpu(env), addr, env->hvf_mmio_buf,
|
||||
decode->operand_size);
|
||||
emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
|
||||
decode->operand_size, 1);
|
||||
emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
|
||||
decode->operand_size);
|
||||
|
||||
string_increment_reg(env, R_EDI, decode);
|
||||
}
|
||||
@@ -509,10 +506,10 @@ static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
|
||||
{
|
||||
target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
|
||||
|
||||
vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, addr,
|
||||
decode->operand_size);
|
||||
hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 1,
|
||||
decode->operand_size, 1);
|
||||
emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
|
||||
decode->operand_size);
|
||||
emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
|
||||
decode->operand_size, 1);
|
||||
|
||||
string_increment_reg(env, R_ESI, decode);
|
||||
}
|
||||
@@ -595,7 +592,7 @@ static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
|
||||
addr = linear_addr_size(env_cpu(env), RDI(env),
|
||||
decode->addressing_size, R_ES);
|
||||
val = read_reg(env, R_EAX, decode->operand_size);
|
||||
vmx_write_mem(env_cpu(env), addr, &val, decode->operand_size);
|
||||
emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
|
||||
|
||||
string_increment_reg(env, R_EDI, decode);
|
||||
}
|
||||
@@ -619,7 +616,7 @@ static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
|
||||
addr = linear_addr_size(env_cpu(env), RDI(env),
|
||||
decode->addressing_size, R_ES);
|
||||
decode->op[1].type = X86_VAR_IMMEDIATE;
|
||||
vmx_read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
|
||||
emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
|
||||
|
||||
EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
|
||||
string_increment_reg(env, R_EDI, decode);
|
||||
@@ -644,7 +641,7 @@ static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
|
||||
target_ulong val = 0;
|
||||
|
||||
addr = decode_linear_addr(env, decode, RSI(env), R_DS);
|
||||
vmx_read_mem(env_cpu(env), &val, addr, decode->operand_size);
|
||||
emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size);
|
||||
write_reg(env, R_EAX, val, decode->operand_size);
|
||||
|
||||
string_increment_reg(env, R_ESI, decode);
|
||||
@@ -671,13 +668,13 @@ void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_c
|
||||
|
||||
static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
|
||||
{
|
||||
hvf_simulate_rdmsr(env);
|
||||
emul_ops->simulate_rdmsr(env_cpu(env));
|
||||
env->eip += decode->len;
|
||||
}
|
||||
|
||||
static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
|
||||
{
|
||||
hvf_simulate_wrmsr(env);
|
||||
emul_ops->simulate_wrmsr(env_cpu(env));
|
||||
env->eip += decode->len;
|
||||
}
|
||||
|
||||
@@ -1231,6 +1228,8 @@ static struct cmd_handler {
|
||||
|
||||
static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
|
||||
|
||||
const struct x86_emul_ops *emul_ops;
|
||||
|
||||
static void init_cmd_handler(void)
|
||||
{
|
||||
int i;
|
||||
@@ -1253,7 +1252,8 @@ bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_emu(void)
|
||||
void init_emu(const struct x86_emul_ops *o)
|
||||
{
|
||||
emul_ops = o;
|
||||
init_cmd_handler();
|
||||
}
|
||||
@@ -23,7 +23,20 @@
|
||||
#include "x86_decode.h"
|
||||
#include "cpu.h"
|
||||
|
||||
void init_emu(void);
|
||||
struct x86_emul_ops {
|
||||
void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
|
||||
void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
|
||||
void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc,
|
||||
enum X86Seg seg);
|
||||
void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction,
|
||||
int size, int count);
|
||||
void (*simulate_rdmsr)(CPUState *cs);
|
||||
void (*simulate_wrmsr)(CPUState *cs);
|
||||
};
|
||||
|
||||
extern const struct x86_emul_ops *emul_ops;
|
||||
|
||||
void init_emu(const struct x86_emul_ops *ops);
|
||||
bool exec_instruction(CPUX86State *env, struct x86_decode *ins);
|
||||
void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code);
|
||||
|
||||
@@ -45,15 +45,6 @@
|
||||
#define LF_MASK_CF (0x01 << LF_BIT_CF)
|
||||
#define LF_MASK_PO (0x01 << LF_BIT_PO)
|
||||
|
||||
#define ADD_COUT_VEC(op1, op2, result) \
|
||||
(((op1) & (op2)) | (((op1) | (op2)) & (~(result))))
|
||||
|
||||
#define SUB_COUT_VEC(op1, op2, result) \
|
||||
(((~(op1)) & (op2)) | (((~(op1)) ^ (op2)) & (result)))
|
||||
|
||||
#define GET_ADD_OVERFLOW(op1, op2, result, mask) \
|
||||
((((op1) ^ (result)) & ((op2) ^ (result))) & (mask))
|
||||
|
||||
/* ******************* */
|
||||
/* OSZAPC */
|
||||
/* ******************* */
|
||||
@@ -62,7 +53,7 @@
|
||||
#define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \
|
||||
target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
|
||||
(((lf_carries) >> (size - 2)) << LF_BIT_PO); \
|
||||
env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \
|
||||
env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
|
||||
if ((size) == 32) { \
|
||||
temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
|
||||
} else if ((size) == 16) { \
|
||||
@@ -72,7 +63,7 @@
|
||||
} else { \
|
||||
VM_PANIC("unimplemented"); \
|
||||
} \
|
||||
env->hvf_lflags.auxbits = (target_ulong)(uint32_t)temp; \
|
||||
env->lflags.auxbits = (target_ulong)(uint32_t)temp; \
|
||||
}
|
||||
|
||||
/* carries, result */
|
||||
@@ -99,10 +90,10 @@
|
||||
} else { \
|
||||
VM_PANIC("unimplemented"); \
|
||||
} \
|
||||
env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \
|
||||
target_ulong delta_c = (env->hvf_lflags.auxbits ^ temp) & LF_MASK_CF; \
|
||||
env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
|
||||
target_ulong delta_c = (env->lflags.auxbits ^ temp) & LF_MASK_CF; \
|
||||
delta_c ^= (delta_c >> 1); \
|
||||
env->hvf_lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \
|
||||
env->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \
|
||||
}
|
||||
|
||||
/* carries, result */
|
||||
@@ -116,8 +107,8 @@
|
||||
void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf)
|
||||
{
|
||||
uint32_t temp_po = new_of ^ new_cf;
|
||||
env->hvf_lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF);
|
||||
env->hvf_lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF);
|
||||
env->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF);
|
||||
env->lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF);
|
||||
}
|
||||
|
||||
void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
|
||||
@@ -213,27 +204,27 @@ void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2,
|
||||
|
||||
bool get_PF(CPUX86State *env)
|
||||
{
|
||||
uint32_t temp = (255 & env->hvf_lflags.result);
|
||||
temp = temp ^ (255 & (env->hvf_lflags.auxbits >> LF_BIT_PDB));
|
||||
uint32_t temp = (255 & env->lflags.result);
|
||||
temp = temp ^ (255 & (env->lflags.auxbits >> LF_BIT_PDB));
|
||||
temp = (temp ^ (temp >> 4)) & 0x0F;
|
||||
return (0x9669U >> temp) & 1;
|
||||
}
|
||||
|
||||
void set_PF(CPUX86State *env, bool val)
|
||||
{
|
||||
uint32_t temp = (255 & env->hvf_lflags.result) ^ (!val);
|
||||
env->hvf_lflags.auxbits &= ~(LF_MASK_PDB);
|
||||
env->hvf_lflags.auxbits |= (temp << LF_BIT_PDB);
|
||||
uint32_t temp = (255 & env->lflags.result) ^ (!val);
|
||||
env->lflags.auxbits &= ~(LF_MASK_PDB);
|
||||
env->lflags.auxbits |= (temp << LF_BIT_PDB);
|
||||
}
|
||||
|
||||
bool get_OF(CPUX86State *env)
|
||||
{
|
||||
return ((env->hvf_lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1;
|
||||
return ((env->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1;
|
||||
}
|
||||
|
||||
bool get_CF(CPUX86State *env)
|
||||
{
|
||||
return (env->hvf_lflags.auxbits >> LF_BIT_CF) & 1;
|
||||
return (env->lflags.auxbits >> LF_BIT_CF) & 1;
|
||||
}
|
||||
|
||||
void set_OF(CPUX86State *env, bool val)
|
||||
@@ -250,49 +241,50 @@ void set_CF(CPUX86State *env, bool val)
|
||||
|
||||
bool get_AF(CPUX86State *env)
|
||||
{
|
||||
return (env->hvf_lflags.auxbits >> LF_BIT_AF) & 1;
|
||||
return (env->lflags.auxbits >> LF_BIT_AF) & 1;
|
||||
}
|
||||
|
||||
void set_AF(CPUX86State *env, bool val)
|
||||
{
|
||||
env->hvf_lflags.auxbits &= ~(LF_MASK_AF);
|
||||
env->hvf_lflags.auxbits |= val << LF_BIT_AF;
|
||||
env->lflags.auxbits &= ~(LF_MASK_AF);
|
||||
env->lflags.auxbits |= val << LF_BIT_AF;
|
||||
}
|
||||
|
||||
bool get_ZF(CPUX86State *env)
|
||||
{
|
||||
return !env->hvf_lflags.result;
|
||||
return !env->lflags.result;
|
||||
}
|
||||
|
||||
void set_ZF(CPUX86State *env, bool val)
|
||||
{
|
||||
if (val) {
|
||||
env->hvf_lflags.auxbits ^=
|
||||
(((env->hvf_lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD);
|
||||
env->lflags.auxbits ^=
|
||||
(((env->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD);
|
||||
/* merge the parity bits into the Parity Delta Byte */
|
||||
uint32_t temp_pdb = (255 & env->hvf_lflags.result);
|
||||
env->hvf_lflags.auxbits ^= (temp_pdb << LF_BIT_PDB);
|
||||
uint32_t temp_pdb = (255 & env->lflags.result);
|
||||
env->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB);
|
||||
/* now zero the .result value */
|
||||
env->hvf_lflags.result = 0;
|
||||
env->lflags.result = 0;
|
||||
} else {
|
||||
env->hvf_lflags.result |= (1 << 8);
|
||||
env->lflags.result |= (1 << 8);
|
||||
}
|
||||
}
|
||||
|
||||
bool get_SF(CPUX86State *env)
|
||||
{
|
||||
return ((env->hvf_lflags.result >> LF_SIGN_BIT) ^
|
||||
(env->hvf_lflags.auxbits >> LF_BIT_SD)) & 1;
|
||||
return ((env->lflags.result >> LF_SIGN_BIT) ^
|
||||
(env->lflags.auxbits >> LF_BIT_SD)) & 1;
|
||||
}
|
||||
|
||||
void set_SF(CPUX86State *env, bool val)
|
||||
{
|
||||
bool temp_sf = get_SF(env);
|
||||
env->hvf_lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD;
|
||||
env->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD;
|
||||
}
|
||||
|
||||
void lflags_to_rflags(CPUX86State *env)
|
||||
{
|
||||
env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O);
|
||||
env->eflags |= get_CF(env) ? CC_C : 0;
|
||||
env->eflags |= get_PF(env) ? CC_P : 0;
|
||||
env->eflags |= get_AF(env) ? CC_A : 0;
|
||||
@@ -303,7 +295,7 @@ void lflags_to_rflags(CPUX86State *env)
|
||||
|
||||
void rflags_to_lflags(CPUX86State *env)
|
||||
{
|
||||
env->hvf_lflags.auxbits = env->hvf_lflags.result = 0;
|
||||
env->lflags.auxbits = env->lflags.result = 0;
|
||||
set_OF(env, env->eflags & CC_O);
|
||||
set_SF(env, env->eflags & CC_S);
|
||||
set_ZF(env, env->eflags & CC_Z);
|
||||
@@ -21,8 +21,8 @@
|
||||
* x86 eflags functions
|
||||
*/
|
||||
|
||||
#ifndef X86_FLAGS_H
|
||||
#define X86_FLAGS_H
|
||||
#ifndef X86_EMU_FLAGS_H
|
||||
#define X86_EMU_FLAGS_H
|
||||
|
||||
#include "cpu.h"
|
||||
void lflags_to_rflags(CPUX86State *env);
|
||||
@@ -78,4 +78,4 @@ void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2,
|
||||
void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2,
|
||||
uint8_t diff);
|
||||
|
||||
#endif /* X86_FLAGS_H */
|
||||
#endif /* X86_EMU_FLAGS_H */
|
||||
@@ -109,9 +109,13 @@ void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping)
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
|
||||
host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
|
||||
host_cpuid(0x0, 0, NULL, &ebx, &ecx, &edx);
|
||||
x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
|
||||
|
||||
if (!family && !model && !stepping) {
|
||||
return;
|
||||
}
|
||||
|
||||
host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
|
||||
if (family) {
|
||||
*family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
|
||||
@@ -129,11 +133,9 @@ void host_cpu_instance_init(X86CPU *cpu)
|
||||
X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
|
||||
|
||||
if (xcc->model) {
|
||||
uint32_t ebx = 0, ecx = 0, edx = 0;
|
||||
char vendor[CPUID_VENDOR_SZ + 1];
|
||||
|
||||
host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
|
||||
x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
|
||||
host_cpu_vendor_fms(vendor, NULL, NULL, NULL);
|
||||
object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, int reg);
|
||||
|
||||
void hvf_handle_io(CPUState *, uint16_t, void *, int, int, int);
|
||||
void hvf_simulate_rdmsr(CPUX86State *env);
|
||||
void hvf_simulate_wrmsr(CPUX86State *env);
|
||||
void hvf_simulate_rdmsr(CPUState *cpu);
|
||||
void hvf_simulate_wrmsr(CPUState *cpu);
|
||||
|
||||
/* Host specific functions */
|
||||
int hvf_inject_interrupt(CPUArchState *env, int vector);
|
||||
|
||||
+42
-15
@@ -59,12 +59,12 @@
|
||||
#include "hvf-i386.h"
|
||||
#include "vmcs.h"
|
||||
#include "vmx.h"
|
||||
#include "x86.h"
|
||||
#include "emulate/x86.h"
|
||||
#include "x86_descr.h"
|
||||
#include "x86_flags.h"
|
||||
#include "emulate/x86_flags.h"
|
||||
#include "x86_mmu.h"
|
||||
#include "x86_decode.h"
|
||||
#include "x86_emu.h"
|
||||
#include "emulate/x86_decode.h"
|
||||
#include "emulate/x86_emu.h"
|
||||
#include "x86_task.h"
|
||||
#include "x86hvf.h"
|
||||
|
||||
@@ -168,7 +168,7 @@ void hvf_arch_vcpu_destroy(CPUState *cpu)
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
CPUX86State *env = &x86_cpu->env;
|
||||
|
||||
g_free(env->hvf_mmio_buf);
|
||||
g_free(env->emu_mmio_buf);
|
||||
}
|
||||
|
||||
static void init_tsc_freq(CPUX86State *env)
|
||||
@@ -229,6 +229,33 @@ hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range)
|
||||
return hv_vm_create(HV_VM_DEFAULT);
|
||||
}
|
||||
|
||||
static void hvf_read_segment_descriptor(CPUState *s, struct x86_segment_descriptor *desc,
|
||||
X86Seg seg)
|
||||
{
|
||||
struct vmx_segment vmx_segment;
|
||||
vmx_read_segment_descriptor(s, &vmx_segment, seg);
|
||||
vmx_segment_to_x86_descriptor(s, &vmx_segment, desc);
|
||||
}
|
||||
|
||||
static void hvf_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
|
||||
{
|
||||
vmx_read_mem(cpu, data, gva, bytes);
|
||||
}
|
||||
|
||||
static void hvf_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
|
||||
{
|
||||
vmx_write_mem(cpu, gva, data, bytes);
|
||||
}
|
||||
|
||||
static const struct x86_emul_ops hvf_x86_emul_ops = {
|
||||
.read_mem = hvf_read_mem,
|
||||
.write_mem = hvf_write_mem,
|
||||
.read_segment_descriptor = hvf_read_segment_descriptor,
|
||||
.handle_io = hvf_handle_io,
|
||||
.simulate_rdmsr = hvf_simulate_rdmsr,
|
||||
.simulate_wrmsr = hvf_simulate_wrmsr,
|
||||
};
|
||||
|
||||
int hvf_arch_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
X86CPU *x86cpu = X86_CPU(cpu);
|
||||
@@ -237,13 +264,13 @@ int hvf_arch_init_vcpu(CPUState *cpu)
|
||||
int r;
|
||||
uint64_t reqCap;
|
||||
|
||||
init_emu();
|
||||
init_emu(&hvf_x86_emul_ops);
|
||||
init_decoder();
|
||||
|
||||
if (hvf_state->hvf_caps == NULL) {
|
||||
hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
|
||||
}
|
||||
env->hvf_mmio_buf = g_new(char, 4096);
|
||||
env->emu_mmio_buf = g_new(char, 4096);
|
||||
|
||||
if (x86cpu->vmware_cpuid_freq) {
|
||||
init_tsc_freq(env);
|
||||
@@ -481,10 +508,10 @@ void hvf_store_regs(CPUState *cs)
|
||||
macvm_set_rip(cs, env->eip);
|
||||
}
|
||||
|
||||
void hvf_simulate_rdmsr(CPUX86State *env)
|
||||
void hvf_simulate_rdmsr(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = env_archcpu(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
uint32_t msr = ECX(env);
|
||||
uint64_t val = 0;
|
||||
|
||||
@@ -586,10 +613,10 @@ void hvf_simulate_rdmsr(CPUX86State *env)
|
||||
RDX(env) = (uint32_t)(val >> 32);
|
||||
}
|
||||
|
||||
void hvf_simulate_wrmsr(CPUX86State *env)
|
||||
void hvf_simulate_wrmsr(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = env_archcpu(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
uint32_t msr = ECX(env);
|
||||
uint64_t data = ((uint64_t)EDX(env) << 32) | EAX(env);
|
||||
|
||||
@@ -875,9 +902,9 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||
{
|
||||
hvf_load_regs(cpu);
|
||||
if (exit_reason == EXIT_REASON_RDMSR) {
|
||||
hvf_simulate_rdmsr(env);
|
||||
hvf_simulate_rdmsr(cpu);
|
||||
} else {
|
||||
hvf_simulate_wrmsr(env);
|
||||
hvf_simulate_wrmsr(cpu);
|
||||
}
|
||||
env->eip += ins_len;
|
||||
hvf_store_regs(cpu);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user