whpx: Fixed incorrect CR8/TPR synchronization
This fixes the following error triggered when stopping and resuming a 64-bit Linux kernel via gdb: qemu-system-x86_64.exe: WHPX: Failed to set virtual processor context, hr=c0350005 The previous logic for synchronizing the values did not take into account that the lower 4 bits of the CR8 register, containing the priority level, mapped to bits 7:4 of the APIC.TPR register (see section 10.8.6.1 of Volume 3 of Intel 64 and IA-32 Architectures Software Developer's Manual). The caused WHvSetVirtualProcessorRegisters() to fail with an error, effectively preventing GDB from changing the guest context. Signed-off-by: Ivan Shcherbakov <ivan@sysprogs.com> Message-Id: <010b01d82874$bb4ef160$31ecd420$@sysprogs.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
e561890841
commit
5ad93fd351
@ -256,6 +256,21 @@ static int whpx_set_tsc(CPUState *cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The CR8 register in the CPU is mapped to the TPR register of the APIC,
|
||||
* however, they use a slightly different encoding. Specifically:
|
||||
*
|
||||
* APIC.TPR[bits 7:4] = CR8[bits 3:0]
|
||||
*
|
||||
* This mechanism is described in section 10.8.6.1 of Volume 3 of Intel 64
|
||||
* and IA-32 Architectures Software Developer's Manual.
|
||||
*/
|
||||
|
||||
static uint64_t whpx_apic_tpr_to_cr8(uint64_t tpr)
|
||||
{
|
||||
return tpr >> 4;
|
||||
}
|
||||
|
||||
static void whpx_set_registers(CPUState *cpu, int level)
|
||||
{
|
||||
struct whpx_state *whpx = &whpx_global;
|
||||
@ -284,7 +299,7 @@ static void whpx_set_registers(CPUState *cpu, int level)
|
||||
v86 = (env->eflags & VM_MASK);
|
||||
r86 = !(env->cr[0] & CR0_PE_MASK);
|
||||
|
||||
vcpu->tpr = cpu_get_apic_tpr(x86_cpu->apic_state);
|
||||
vcpu->tpr = whpx_apic_tpr_to_cr8(cpu_get_apic_tpr(x86_cpu->apic_state));
|
||||
vcpu->apic_base = cpu_get_apic_base(x86_cpu->apic_state);
|
||||
|
||||
idx = 0;
|
||||
@ -475,6 +490,17 @@ static void whpx_get_registers(CPUState *cpu)
|
||||
hr);
|
||||
}
|
||||
|
||||
if (whpx_apic_in_platform()) {
|
||||
/*
|
||||
* Fetch the TPR value from the emulated APIC. It may get overwritten
|
||||
* below with the value from CR8 returned by
|
||||
* WHvGetVirtualProcessorRegisters().
|
||||
*/
|
||||
whpx_apic_get(x86_cpu->apic_state);
|
||||
vcpu->tpr = whpx_apic_tpr_to_cr8(
|
||||
cpu_get_apic_tpr(x86_cpu->apic_state));
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
|
||||
/* Indexes for first 16 registers match between HV and QEMU definitions */
|
||||
|
Loading…
Reference in New Issue
Block a user