aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-04-17 11:35:38 +0200
committerJan Beulich <jbeulich@suse.com>2013-04-17 11:35:38 +0200
commit63753b3e0dc56efb1acf94fa46f3fee7bc59281c (patch)
tree5ac1e9d1e192c546bafb3ec7dc1b83cf2412706f
parent65a11256f294882d6bd1af4af51e42dbbead650d (diff)
downloadxen-63753b3e0dc56efb1acf94fa46f3fee7bc59281c.tar.gz
xen-63753b3e0dc56efb1acf94fa46f3fee7bc59281c.tar.bz2
xen-63753b3e0dc56efb1acf94fa46f3fee7bc59281c.zip
x86: allow VCPUOP_register_vcpu_info to work again on PVHVM guests
For details on the hypercall please see commit c58ae69360ccf2495a19bf4ca107e21cf873c75b (VCPUOP_register_vcpu_info) and the c/s 23143 (git commit 6b063a4a6f44245a727aa04ef76408b2e00af9c7) (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>
-rw-r--r--xen/arch/x86/domain.c13
-rw-r--r--xen/include/asm-x86/domain.h6
2 files changed, 10 insertions, 9 deletions
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 6f9cbed7cb..14b6d13d88 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -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();
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 6f9744a58f..bdaf714ef6 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -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. */