mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86: allow VCPUOP_register_vcpu_info to work again on PVHVM guests
For details on the hypercall please see commitc58ae69360(VCPUOP_register_vcpu_info) and the c/s 23143 (git commit6b063a4a6f) (x86: move pv-only members of struct vcpu to struct pv_vcpu) that introduced the regression. The current code allows the PVHVM guest to make this hypercall. But for PVHVM guest it always returns -EINVAL (-22) for Xen 4.2 and above. Xen 4.1 and earlier worked. The reason is that the check in map_vcpu_info would fail at: if ( v->arch.vcpu_info_mfn != INVALID_MFN ) The reason is that the vcpu_info_mfn for PVHVM guests ends up by defualt with the value of zero (introduced by c/s 23143). The code in vcpu_initialise which initialized vcpu_info_mfn to a valid value (INVALID_MFN), would never be called for PVHVM: if ( is_hvm_domain(d) ) { rc = hvm_vcpu_initialise(v); goto done; } v->arch.pv_vcpu.vcpu_info_mfn = INVALID_MFN; while previously it would be: v->arch.vcpu_info_mfn = INVALID_MFN; [right at the start of the function in Xen 4.1] This fixes the problem with Linux advertising this error: register_vcpu_info failed: err=-22 Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
This commit is contained in:
1 parent
65a11256f2
commit
63753b3e0d
2 files changed
+10
-9
No files matched your search
@@ -387,13 +387,14 @@ int vcpu_initialise(struct vcpu *v)
|
||||
|
||||
vmce_init_vcpu(v);
|
||||
|
||||
v->arch.vcpu_info_mfn = INVALID_MFN;
|
||||
|
||||
if ( is_hvm_domain(d) )
|
||||
{
|
||||
rc = hvm_vcpu_initialise(v);
|
||||
goto done;
|
||||
}
|
||||
|
||||
v->arch.pv_vcpu.vcpu_info_mfn = INVALID_MFN;
|
||||
|
||||
spin_lock_init(&v->arch.pv_vcpu.shadow_ldt_lock);
|
||||
|
||||
@@ -963,14 +964,14 @@ unmap_vcpu_info(struct vcpu *v)
|
||||
{
|
||||
unsigned long mfn;
|
||||
|
||||
if ( v->arch.pv_vcpu.vcpu_info_mfn == INVALID_MFN )
|
||||
if ( v->arch.vcpu_info_mfn == INVALID_MFN )
|
||||
return;
|
||||
|
||||
mfn = v->arch.pv_vcpu.vcpu_info_mfn;
|
||||
mfn = v->arch.vcpu_info_mfn;
|
||||
unmap_domain_page_global(v->vcpu_info);
|
||||
|
||||
v->vcpu_info = &dummy_vcpu_info;
|
||||
v->arch.pv_vcpu.vcpu_info_mfn = INVALID_MFN;
|
||||
v->arch.vcpu_info_mfn = INVALID_MFN;
|
||||
|
||||
put_page_and_type(mfn_to_page(mfn));
|
||||
}
|
||||
@@ -993,7 +994,7 @@ map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset)
|
||||
if ( offset > (PAGE_SIZE - sizeof(vcpu_info_t)) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( v->arch.pv_vcpu.vcpu_info_mfn != INVALID_MFN )
|
||||
if ( v->arch.vcpu_info_mfn != INVALID_MFN )
|
||||
return -EINVAL;
|
||||
|
||||
/* Run this command on yourself or on other offline VCPUS. */
|
||||
@@ -1030,7 +1031,7 @@ map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset)
|
||||
}
|
||||
|
||||
v->vcpu_info = new_info;
|
||||
v->arch.pv_vcpu.vcpu_info_mfn = page_to_mfn(page);
|
||||
v->arch.vcpu_info_mfn = page_to_mfn(page);
|
||||
|
||||
/* Set new vcpu_info pointer /before/ setting pending flags. */
|
||||
wmb();
|
||||
|
||||
@@ -374,9 +374,6 @@ struct pv_vcpu
|
||||
/* Current LDT details. */
|
||||
unsigned long shadow_ldt_mapcnt;
|
||||
spinlock_t shadow_ldt_lock;
|
||||
|
||||
/* Guest-specified relocation of vcpu_info. */
|
||||
unsigned long vcpu_info_mfn;
|
||||
};
|
||||
|
||||
struct arch_vcpu
|
||||
@@ -438,6 +435,9 @@ struct arch_vcpu
|
||||
|
||||
struct paging_vcpu paging;
|
||||
|
||||
/* Guest-specified relocation of vcpu_info. */
|
||||
unsigned long vcpu_info_mfn;
|
||||
|
||||
uint32_t gdbsx_vcpu_event;
|
||||
|
||||
/* A secondary copy of the vcpu time info. */
|
||||
|
||||