Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some improvements. #18

Open
giuseppejaripappalardo opened this issue Nov 10, 2023 · 1 comment
Open

Some improvements. #18

giuseppejaripappalardo opened this issue Nov 10, 2023 · 1 comment

Comments

@giuseppejaripappalardo
Copy link

giuseppejaripappalardo commented Nov 10, 2023

Hello, thanks for your nice work.

I would like to propose some fine tuning, up to you if bring or not:

static int handle_rdtsc(struct kvm_vcpu *vcpu)
{
// Static variables to keep track of the fake and previous TSC values
static u64 rdtsc_fake = 0;
static u64 rdtsc_prev = 0;
// Static variable for the divisor, makes it easy to adjust the TSC rate
static const u64 divisore = 16;

// Retrieve the real TSC value
u64 rdtsc_real = rdtsc();

// Check if this is the first run of the function
if (print_once) {
    printk("[handle_rdtsc] fake rdtsc vmx function is working\n");
    print_once = 0; // Ensure this block runs only once
    rdtsc_fake = rdtsc_real; // Initialize the fake TSC value
}

// Calculate the fake TSC value if not the first run
if (rdtsc_prev != 0 && rdtsc_real > rdtsc_prev) {
    u64 diff = rdtsc_real - rdtsc_prev;
    u64 fake_diff = diff / divisore; // Calculate the difference to be added to the fake TSC
    rdtsc_fake += fake_diff;
} else if (rdtsc_prev == 0) {
    // Handle the initial case where rdtsc_prev is zero
    rdtsc_fake = rdtsc_real;
}

// Prevent the fake TSC from regressing or exceeding the real TSC
if (rdtsc_fake < rdtsc_prev || rdtsc_fake > rdtsc_real) {
    rdtsc_fake = rdtsc_prev + (rdtsc_real - rdtsc_prev) / divisore;
}

// Update the previous TSC value
rdtsc_prev = rdtsc_real;

// Set the fake TSC value to the VM's CPU registers
vcpu->arch.regs[VCPU_REGS_RAX] = rdtsc_fake & -1u;
vcpu->arch.regs[VCPU_REGS_RDX] = (rdtsc_fake >> 32) & -1u;  

// Skip the emulated instruction and return
return skip_emulated_instruction(vcpu);

}

Regards,
Jari

@felikcat
Copy link

This patch makes Windows 10 crash no matter what on 'IPI_WATCHDOG_TIMEOUT' on a i7 12700K.
Screenshot_20240814

The unmodified patch works as intended with no BSOD.

I've done the following to make these patches work on kernel 6.9;
in vmx.c:

        /*
	 * Not used by KVM, but fully supported for nesting, i.e. are allowed in
	 * vmcs12 and propagated to vmcs02 when set in vmcs12.
	 */
	exec_control &= ~(CPU_BASED_USE_IO_BITMAPS |
			  CPU_BASED_MONITOR_TRAP_FLAG |
			  CPU_BASED_PAUSE_EXITING);

	// Ensure handle_rdtsc() is used.
	exec_control |= CPU_BASED_RDTSC_EXITING;

In vmx.h:

#define __KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL			\
	(CPU_BASED_HLT_EXITING |					\
	 CPU_BASED_CR3_LOAD_EXITING |					\
	 CPU_BASED_CR3_STORE_EXITING |					\
	 CPU_BASED_UNCOND_IO_EXITING |					\
	 CPU_BASED_MOV_DR_EXITING |					\
	 CPU_BASED_USE_TSC_OFFSETTING |					\
	 CPU_BASED_MWAIT_EXITING |					\
	 CPU_BASED_MONITOR_EXITING |					\
	 CPU_BASED_INVLPG_EXITING |					\
	 CPU_BASED_RDPMC_EXITING |					\
	 CPU_BASED_RDTSC_EXITING |                                      \
	 CPU_BASED_INTR_WINDOW_EXITING)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants