From eb47d5533a150e2e2729951655f51dd63b9afc6c Mon Sep 17 00:00:00 2001 From: LoGin Date: Fri, 23 Jan 2026 02:03:51 +0800 Subject: [PATCH] =?UTF-8?q?Revert=20"feat(x86=5F64):=20=E6=B7=BB=E5=8A=A0K?= =?UTF-8?q?VM=E6=97=B6=E9=92=9F=E6=BA=90=E6=94=AF=E6=8C=81=20(#1683)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a728b27356ff0e5fdf8f250168e54184aa5c8595. --- kernel/src/arch/x86_64/driver/tsc.rs | 12 - kernel/src/arch/x86_64/init/mod.rs | 6 +- kernel/src/arch/x86_64/kvm_para.rs | 45 ---- kernel/src/arch/x86_64/mod.rs | 2 - kernel/src/arch/x86_64/pvclock.rs | 146 ----------- kernel/src/driver/clocksource/kvm_clock.rs | 276 --------------------- kernel/src/driver/clocksource/mod.rs | 2 - kernel/src/smp/init.rs | 2 - kernel/src/time/clocksource.rs | 13 +- kernel/src/time/timekeeping.rs | 4 - tools/run-qemu.sh | 13 +- 11 files changed, 4 insertions(+), 517 deletions(-) delete mode 100644 kernel/src/arch/x86_64/kvm_para.rs delete mode 100644 kernel/src/arch/x86_64/pvclock.rs delete mode 100644 kernel/src/driver/clocksource/kvm_clock.rs diff --git a/kernel/src/arch/x86_64/driver/tsc.rs b/kernel/src/arch/x86_64/driver/tsc.rs index 7c1db6eef..80dfee194 100644 --- a/kernel/src/arch/x86_64/driver/tsc.rs +++ b/kernel/src/arch/x86_64/driver/tsc.rs @@ -35,10 +35,6 @@ impl TSCManager { return Err(SystemError::ENODEV); } - if Self::cpu_khz() != 0 && Self::tsc_khz() != 0 { - return Ok(()); - } - if unsafe { TSC_KHZ == 0 } { if let Err(e) = Self::determine_cpu_tsc_frequency(false) { error!("Failed to determine CPU TSC frequency: {:?}", e); @@ -389,14 +385,6 @@ impl TSCManager { TSC_KHZ = khz; } } - - pub(crate) fn set_khz_from_kvm(khz: u64) { - if khz == 0 { - return; - } - Self::set_cpu_khz(khz); - Self::set_tsc_khz(khz); - } } /// # 从calibrate_cpu_by_pit_hpet_ptimer 解耦出,减少calibrate_cpu_by_pit_hpet_ptimer的栈帧 diff --git a/kernel/src/arch/x86_64/init/mod.rs b/kernel/src/arch/x86_64/init/mod.rs index c64ef50a1..3562783b5 100644 --- a/kernel/src/arch/x86_64/init/mod.rs +++ b/kernel/src/arch/x86_64/init/mod.rs @@ -9,7 +9,7 @@ use x86::dtables::DescriptorTablePointer; use crate::{ arch::{fpu::FpState, interrupt::trap::arch_trap_init, process::table::TSSManager}, - driver::clocksource::{acpi_pm::init_acpi_pm_clocksource, kvm_clock}, + driver::clocksource::acpi_pm::init_acpi_pm_clocksource, init::init::start_kernel, mm::{MemoryManagementArch, PhysAddr}, }; @@ -109,12 +109,10 @@ pub fn setup_arch() -> Result<(), SystemError> { /// 架构相关的初始化(在IDLE的最后一个阶段) #[inline(never)] pub fn setup_arch_post() -> Result<(), SystemError> { - let kvmclock_ok = kvm_clock::kvmclock_init(); - let ret = hpet_init(); if ret.is_ok() { hpet_instance().hpet_enable().expect("hpet enable failed"); - } else if !kvmclock_ok { + } else { init_acpi_pm_clocksource().expect("acpi_pm_timer inits failed"); } TSCManager::init().expect("tsc init failed"); diff --git a/kernel/src/arch/x86_64/kvm_para.rs b/kernel/src/arch/x86_64/kvm_para.rs deleted file mode 100644 index 425129981..000000000 --- a/kernel/src/arch/x86_64/kvm_para.rs +++ /dev/null @@ -1,45 +0,0 @@ -use x86::cpuid::{cpuid, CpuId, Hypervisor, HypervisorInfo}; - -pub const KVM_CPUID_FEATURES: u32 = 0x4000_0001; - -pub const KVM_FEATURE_CLOCKSOURCE: u32 = 0; -pub const KVM_FEATURE_CLOCKSOURCE2: u32 = 3; -pub const KVM_FEATURE_CLOCKSOURCE_STABLE_BIT: u32 = 24; - -pub const MSR_KVM_WALL_CLOCK: u32 = 0x11; -pub const MSR_KVM_SYSTEM_TIME: u32 = 0x12; -pub const MSR_KVM_WALL_CLOCK_NEW: u32 = 0x4b56_4d00; -pub const MSR_KVM_SYSTEM_TIME_NEW: u32 = 0x4b56_4d01; - -pub fn kvm_para_get_hypervisor_info() -> Option { - let c = CpuId::new().get_hypervisor_info()?; - - if c.identify() != Hypervisor::KVM { - return None; - } - Some(c) -} - -pub fn kvm_para_available() -> bool { - kvm_para_get_hypervisor_info().is_some() -} - -pub fn kvm_para_has_feature(bit: u32) -> bool { - if !kvm_para_available() { - return false; - } - - let res = cpuid!(KVM_CPUID_FEATURES); - (res.eax & (1u32 << bit)) != 0 -} - -pub fn kvm_clock_msrs() -> Option<(u32, u32)> { - if kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE2) { - return Some((MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW)); - } - if kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE) { - return Some((MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK)); - } - - None -} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 9e5e0b588..6378c4295 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -11,13 +11,11 @@ pub mod interrupt; pub mod ipc; pub mod kexec; pub mod kprobe; -pub mod kvm_para; pub mod libs; pub mod mm; pub mod msi; pub mod pci; pub mod process; -pub mod pvclock; pub mod rand; pub mod reboot; pub mod sched; diff --git a/kernel/src/arch/x86_64/pvclock.rs b/kernel/src/arch/x86_64/pvclock.rs deleted file mode 100644 index 5b73a54cf..000000000 --- a/kernel/src/arch/x86_64/pvclock.rs +++ /dev/null @@ -1,146 +0,0 @@ -use core::sync::atomic::{fence, AtomicU64, AtomicU8, Ordering}; -use x86::time::rdtsc; - -pub const PVCLOCK_TSC_STABLE_BIT: u8 = 1 << 0; -#[allow(dead_code)] -pub const PVCLOCK_GUEST_STOPPED: u8 = 1 << 1; - -#[repr(C)] -#[derive(Clone, Copy, Debug)] -pub struct PvclockVcpuTimeInfo { - pub version: u32, - pub pad0: u32, - pub tsc_timestamp: u64, - pub system_time: u64, - pub tsc_to_system_mul: u32, - pub tsc_shift: i8, - pub flags: u8, - pub pad: [u8; 2], -} - -#[allow(dead_code)] -#[repr(C)] -#[derive(Clone, Copy, Debug)] -pub struct PvclockWallClock { - pub version: u32, - pub sec: u32, - pub nsec: u32, -} - -#[repr(C, align(64))] -#[derive(Clone, Copy, Debug)] -pub struct PvclockVsyscallTimeInfo { - pub pvti: PvclockVcpuTimeInfo, -} - -static VALID_FLAGS: AtomicU8 = AtomicU8::new(0); -static LAST_VALUE: AtomicU64 = AtomicU64::new(0); - -pub fn pvclock_set_flags(flags: u8) { - VALID_FLAGS.store(flags, Ordering::Relaxed); -} - -pub fn pvclock_read_begin(src: &PvclockVcpuTimeInfo) -> u32 { - let version = unsafe { core::ptr::read_volatile(&src.version) } & !1; - fence(Ordering::Acquire); - version -} - -pub fn pvclock_read_retry(src: &PvclockVcpuTimeInfo, version: u32) -> bool { - fence(Ordering::Acquire); - let cur = unsafe { core::ptr::read_volatile(&src.version as *const u32) }; - cur != version -} - -#[allow(dead_code)] -pub fn pvclock_read_flags(src: &PvclockVcpuTimeInfo) -> u8 { - let mut flags; - loop { - let version = pvclock_read_begin(src); - flags = unsafe { core::ptr::read_volatile(&src.flags as *const u8) }; - if !pvclock_read_retry(src, version) { - break; - } - } - - flags & VALID_FLAGS.load(Ordering::Relaxed) -} - -pub fn pvclock_scale_delta(mut delta: u64, mul_frac: u32, shift: i8) -> u64 { - if shift < 0 { - delta >>= (-shift) as u32; - } else { - delta <<= shift as u32; - } - - let product = (delta as u128 * mul_frac as u128) >> 32; - product as u64 -} - -pub fn pvclock_read_cycles(src: &PvclockVcpuTimeInfo, tsc: u64) -> u64 { - let tsc_timestamp = unsafe { core::ptr::read_volatile(&src.tsc_timestamp as *const u64) }; - let system_time = unsafe { core::ptr::read_volatile(&src.system_time as *const u64) }; - let tsc_to_system_mul = - unsafe { core::ptr::read_volatile(&src.tsc_to_system_mul as *const u32) }; - let tsc_shift = unsafe { core::ptr::read_volatile(&src.tsc_shift as *const i8) }; - - let delta = tsc.wrapping_sub(tsc_timestamp); - let offset = pvclock_scale_delta(delta, tsc_to_system_mul, tsc_shift); - system_time.wrapping_add(offset) -} - -fn rdtsc_ordered() -> u64 { - fence(Ordering::SeqCst); - unsafe { rdtsc() } -} - -pub fn pvclock_clocksource_read_nowd(src: &PvclockVcpuTimeInfo) -> u64 { - let mut ret; - let mut flags; - - loop { - let version = pvclock_read_begin(src); - ret = pvclock_read_cycles(src, rdtsc_ordered()); - flags = unsafe { core::ptr::read_volatile(&src.flags as *const u8) }; - if !pvclock_read_retry(src, version) { - break; - } - } - - let valid = VALID_FLAGS.load(Ordering::Relaxed); - if (valid & PVCLOCK_TSC_STABLE_BIT) != 0 && (flags & PVCLOCK_TSC_STABLE_BIT) != 0 { - return ret; - } - - loop { - let last = LAST_VALUE.load(Ordering::Relaxed); - if ret <= last { - return last; - } - if LAST_VALUE - .compare_exchange(last, ret, Ordering::AcqRel, Ordering::Relaxed) - .is_ok() - { - return ret; - } - } -} - -pub fn pvclock_tsc_khz(src: &PvclockVcpuTimeInfo) -> u64 { - let tsc_to_system_mul = - unsafe { core::ptr::read_volatile(&src.tsc_to_system_mul as *const u32) } as u64; - let tsc_shift = unsafe { core::ptr::read_volatile(&src.tsc_shift as *const i8) } as i32; - - if tsc_to_system_mul == 0 { - return 0; - } - - let mut pv_tsc_khz = 1_000_000u64 << 32; - pv_tsc_khz /= tsc_to_system_mul; - if tsc_shift < 0 { - pv_tsc_khz <<= (-tsc_shift) as u32; - } else { - pv_tsc_khz >>= tsc_shift as u32; - } - pv_tsc_khz -} diff --git a/kernel/src/driver/clocksource/kvm_clock.rs b/kernel/src/driver/clocksource/kvm_clock.rs deleted file mode 100644 index 0e78e8397..000000000 --- a/kernel/src/driver/clocksource/kvm_clock.rs +++ /dev/null @@ -1,276 +0,0 @@ -use alloc::string::ToString; -use alloc::{sync::Arc, vec::Vec}; -use core::sync::atomic::{AtomicBool, AtomicU32, Ordering}; - -use log::{info, warn}; -use system_error::SystemError; -use x86::msr::wrmsr; - -use crate::{ - arch::{ - kvm_para, - pvclock::{self, PvclockVcpuTimeInfo, PvclockVsyscallTimeInfo, PVCLOCK_TSC_STABLE_BIT}, - MMArch, - }, - libs::spinlock::SpinLock, - mm::{ - allocator::page_frame::FrameAllocator, - percpu::{PerCpu, PerCpuVar}, - MemoryManagementArch, PhysAddr, VirtAddr, - }, - smp::core::smp_get_processor_id, - time::{ - clocksource::{Clocksource, ClocksourceData, ClocksourceFlags, ClocksourceMask, CycleNum}, - NSEC_PER_SEC, - }, -}; - -use crate::arch::driver::tsc::TSCManager; -use crate::process::preempt::PreemptGuard; -use alloc::sync::Weak; - -#[derive(Clone, Copy, Debug)] -struct KvmClockPage { - phys: PhysAddr, - virt: VirtAddr, -} - -impl KvmClockPage { - const fn empty() -> Self { - Self { - phys: PhysAddr::new(0), - virt: VirtAddr::new(0), - } - } - - fn is_valid(&self) -> bool { - self.phys.data() != 0 && self.virt.data() != 0 - } -} - -static mut KVM_CLOCK_PAGES: Option> = None; -static mut CLOCKSOURCE_KVM: Option> = None; - -static MSR_KVM_SYSTEM_TIME: AtomicU32 = AtomicU32::new(0); -static KVM_CLOCK_READY: AtomicBool = AtomicBool::new(false); - -#[derive(Debug)] -pub struct KvmClock(SpinLock); - -#[derive(Debug)] -struct InnerKvmClock { - data: ClocksourceData, - self_ref: Weak, -} - -impl KvmClock { - pub fn new() -> Arc { - let data = ClocksourceData { - name: "kvm-clock".to_string(), - rating: 400, - mask: ClocksourceMask::new(u64::MAX), - mult: 0, - shift: 0, - max_idle_ns: Default::default(), - flags: ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS, - watchdog_last: CycleNum::new(0), - cs_last: CycleNum::new(0), - uncertainty_margin: 0, - maxadj: 0, - cycle_last: CycleNum::new(0), - }; - let kvm = Arc::new(KvmClock(SpinLock::new(InnerKvmClock { - data, - self_ref: Default::default(), - }))); - kvm.0.lock().self_ref = Arc::downgrade(&kvm); - kvm - } -} - -impl Clocksource for KvmClock { - fn read(&self) -> CycleNum { - let now = kvm_clock_read().unwrap_or(0); - CycleNum::new(now) - } - - fn enable(&self) -> Result { - Ok(0) - } - - fn clocksource_data(&self) -> ClocksourceData { - self.0.lock_irqsave().data.clone() - } - - fn clocksource(&self) -> Arc { - self.0.lock_irqsave().self_ref.upgrade().unwrap() - } - - fn update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError> { - let d = &mut self.0.lock_irqsave().data; - d.set_name(data.name); - d.set_rating(data.rating); - d.set_mask(data.mask); - d.set_mult(data.mult); - d.set_shift(data.shift); - d.set_max_idle_ns(data.max_idle_ns); - d.set_flags(data.flags); - d.watchdog_last = data.watchdog_last; - d.cs_last = data.cs_last; - d.set_uncertainty_margin(data.uncertainty_margin); - d.set_maxadj(data.maxadj); - d.cycle_last = data.cycle_last; - Ok(()) - } -} - -fn kvm_clock_pages() -> &'static PerCpuVar { - unsafe { KVM_CLOCK_PAGES.as_ref().unwrap() } -} - -fn ensure_kvm_clock_pages() { - unsafe { - if KVM_CLOCK_PAGES.is_some() { - return; - } - } - - let mut pages = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize); - pages.resize_with(PerCpu::MAX_CPU_NUM as usize, KvmClockPage::empty); - unsafe { - KVM_CLOCK_PAGES = Some(PerCpuVar::new(pages).unwrap()); - } -} - -fn alloc_clock_page() -> Result { - let phys = unsafe { crate::arch::mm::LockedFrameAllocator.allocate_one() } - .ok_or(SystemError::ENOMEM)?; - let virt = unsafe { MMArch::phys_2_virt(phys) }.ok_or(SystemError::EINVAL)?; - - unsafe { - MMArch::write_bytes(virt, 0, MMArch::PAGE_SIZE); - } - - Ok(KvmClockPage { phys, virt }) -} - -fn ensure_clock_page_for_cpu() -> Result { - ensure_kvm_clock_pages(); - let cpu_id = smp_get_processor_id(); - let pages = kvm_clock_pages(); - - let page = unsafe { pages.force_get_mut(cpu_id) }; - if page.is_valid() { - return Ok(*page); - } - - let new_page = alloc_clock_page()?; - *page = new_page; - Ok(new_page) -} - -fn this_cpu_pvti() -> Option<&'static PvclockVcpuTimeInfo> { - let cpu_id = smp_get_processor_id(); - let page = unsafe { kvm_clock_pages().force_get(cpu_id) }; - if !page.is_valid() { - return None; - } - - let ptr = page.virt.data() as *const PvclockVsyscallTimeInfo; - Some(unsafe { &(*ptr).pvti }) -} - -fn write_system_time_msr(phys: PhysAddr) { - let msr = MSR_KVM_SYSTEM_TIME.load(Ordering::SeqCst); - if msr == 0 { - return; - } - - let val = (phys.data() as u64) | 1u64; - unsafe { wrmsr(msr, val) }; -} - -fn kvm_clock_read() -> Option { - let _guard = PreemptGuard::new(); - let pvti = this_cpu_pvti()?; - Some(pvclock::pvclock_clocksource_read_nowd(pvti)) -} - -fn init_msrs() -> bool { - let (system_time, wall_clock) = match kvm_para::kvm_clock_msrs() { - Some(msrs) => msrs, - None => return false, - }; - - MSR_KVM_SYSTEM_TIME.store(system_time, Ordering::SeqCst); - let _ = wall_clock; - true -} - -fn update_tsc_khz_from_pvclock() { - if let Some(pvti) = this_cpu_pvti() { - let khz = pvclock::pvclock_tsc_khz(pvti); - if khz != 0 { - TSCManager::set_khz_from_kvm(khz); - } - } -} - -pub fn kvmclock_init() -> bool { - if KVM_CLOCK_READY.load(Ordering::SeqCst) { - return true; - } - - if !kvm_para::kvm_para_available() { - return false; - } - - if !init_msrs() { - return false; - } - - ensure_kvm_clock_pages(); - let page = match ensure_clock_page_for_cpu() { - Ok(page) => page, - Err(e) => { - warn!("kvm-clock: alloc clock page failed: {:?}", e); - return false; - } - }; - - if kvm_para::kvm_para_has_feature(kvm_para::KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) { - pvclock::pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); - } - - write_system_time_msr(page.phys); - - let kvm_clock = KvmClock::new(); - let clock = kvm_clock.clone() as Arc; - if let Err(e) = clock.register(1, NSEC_PER_SEC) { - warn!("kvm-clock: register failed: {:?}", e); - return false; - } - - unsafe { - CLOCKSOURCE_KVM = Some(kvm_clock); - } - KVM_CLOCK_READY.store(true, Ordering::SeqCst); - - update_tsc_khz_from_pvclock(); - - info!("kvm-clock: registered"); - true -} - -pub fn kvmclock_init_secondary() { - if !KVM_CLOCK_READY.load(Ordering::SeqCst) { - return; - } - - let page = match ensure_clock_page_for_cpu() { - Ok(page) => page, - Err(_) => return, - }; - - write_system_time_msr(page.phys); -} diff --git a/kernel/src/driver/clocksource/mod.rs b/kernel/src/driver/clocksource/mod.rs index 7b5de6ca6..fda0b0864 100644 --- a/kernel/src/driver/clocksource/mod.rs +++ b/kernel/src/driver/clocksource/mod.rs @@ -2,5 +2,3 @@ pub mod timer_riscv; pub mod acpi_pm; -#[cfg(target_arch = "x86_64")] -pub mod kvm_clock; diff --git a/kernel/src/smp/init.rs b/kernel/src/smp/init.rs index 76d860a9d..27d622093 100644 --- a/kernel/src/smp/init.rs +++ b/kernel/src/smp/init.rs @@ -25,7 +25,5 @@ pub fn smp_ap_start_stage2() -> ! { #[inline(never)] fn do_ap_start_stage2() { info!("Successfully started AP {}", smp_get_processor_id().data()); - #[cfg(target_arch = "x86_64")] - crate::driver::clocksource::kvm_clock::kvmclock_init_secondary(); arch_syscall_init().expect("AP core failed to initialize syscall"); } diff --git a/kernel/src/time/clocksource.rs b/kernel/src/time/clocksource.rs index a8021de14..c5cbed2ef 100644 --- a/kernel/src/time/clocksource.rs +++ b/kernel/src/time/clocksource.rs @@ -29,7 +29,6 @@ use crate::{ use super::{ jiffies::clocksource_default_clock, - timekeeping, timer::{clock, Timer, TimerFunction}, NSEC_PER_SEC, NSEC_PER_USEC, }; @@ -1003,17 +1002,11 @@ pub fn clocksource_select() { info!("Switching to the clocksource {:?}\n", best_name); drop(cur_clocksource); CUR_CLOCKSOURCE.lock().replace(best.clone()); - if timekeeping::timekeeping_is_initialized() { - timekeeping::timekeeper().timekeeper_setup_internals(best.clone()); - } // TODO 通知timerkeeping 切换了时间源 } } else { // 当前时钟源为空 CUR_CLOCKSOURCE.lock().replace(best.clone()); - if timekeeping::timekeeping_is_initialized() { - timekeeping::timekeeper().timekeeper_setup_internals(best.clone()); - } } debug!("clocksource_select finish, CUR_CLOCKSOURCE = {best:?}"); } @@ -1021,12 +1014,8 @@ pub fn clocksource_select() { /// # clocksource模块加载完成 pub fn clocksource_boot_finish() { let mut cur_clocksource = CUR_CLOCKSOURCE.lock(); - if cur_clocksource.is_none() { - cur_clocksource.replace(clocksource_default_clock()); - } + cur_clocksource.replace(clocksource_default_clock()); FINISHED_BOOTING.store(true, Ordering::Relaxed); - drop(cur_clocksource); - clocksource_select(); // 清除不稳定的时钟源 __clocksource_watchdog_kthread(); debug!("clocksource_boot_finish"); diff --git a/kernel/src/time/timekeeping.rs b/kernel/src/time/timekeeping.rs index e8b8fad94..13e9bcfe3 100644 --- a/kernel/src/time/timekeeping.rs +++ b/kernel/src/time/timekeeping.rs @@ -296,10 +296,6 @@ pub fn timekeeper() -> &'static Timekeeper { return r; } -pub fn timekeeping_is_initialized() -> bool { - unsafe { __TIMEKEEPER.is_some() } -} - pub fn timekeeper_init() { unsafe { __TIMEKEEPER = Some(Timekeeper::new()) }; } diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh index 2ac20e726..b55478f73 100755 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -179,16 +179,7 @@ if [ -n "${qemu_accel}" ]; then fi if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then - # 根据加速方式设置机器参数 - # 仅在KVM加速时禁用HPET,以使用KVM clock作为时钟源 - # 非KVM加速(如TCG)时保留HPET,因为kvm-clock不可用 - if [ "${qemu_accel}" == "kvm" ]; then - # KVM加速:禁用HPET,使用kvm-clock(性能更好且延迟更低) - QEMU_MACHINE_ARGS=(-machine "q35,hpet=off") - else - # 非KVM加速 - QEMU_MACHINE_ARGS=(-machine q35) - fi + QEMU_MACHINE_ARGS=(-machine q35) # 根据加速方式选择CPU型号:KVM使用host,TCG使用IvyBridge cpu_model=$([ "${qemu_accel}" == "kvm" ] && echo "host" || echo "IvyBridge") if [ -n "${allflags}" ]; then @@ -196,8 +187,6 @@ if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then else QEMU_CPU_ARGS=(-cpu "${cpu_model},apic,x2apic,+fpu,check,+vmx") fi - # RTC配置:clock=host 使guest使用host的时钟源,支持kvm-clock - # base=localtime 设置RTC基准时间为本地时间 QEMU_RTC_ARGS=(-rtc clock=host,base=localtime) if [ ${VIRTIO_BLK_DEVICE} == false ]; then QEMU_DEVICE_DISK_ARGS=(-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0)