mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/vmx: refactor cache disable mode data
The Cache Disable mode data is used only by VMX code, so move it from common HVM structures into VMX specific structures: - move "uc_lock", "is_in_uc_mode" fields from struct hvm_domain to struct vmx_domain; - move "cache_mode" field from struct hvm_vcpu to struct vmx_vcpu. Hence, the "in_uc_mode" field is used directly in mm/shadow/multi.c _sh_propagate(), introduce the hvm_is_in_uc_mode() macro to avoid direct access to this field and account for INTEL_VMX configuration. While here: - rename "is_in_uc_mode" to "in_uc_mode" - s/NORMAL_CACHE_MODE/CACHE_MODE_NORMAL - s/NO_FILL_CACHE_MODE/CACHE_MODE_NO_FILL Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
0545f53aa9
commit
9569b05e9b
8 files changed
+33
-28
No files matched your search
@@ -608,7 +608,6 @@ int hvm_domain_initialise(struct domain *d,
|
||||
}
|
||||
|
||||
spin_lock_init(&d->arch.hvm.irq_lock);
|
||||
spin_lock_init(&d->arch.hvm.uc_lock);
|
||||
spin_lock_init(&d->arch.hvm.write_map.lock);
|
||||
rwlock_init(&d->arch.hvm.mmcfg_lock);
|
||||
INIT_LIST_HEAD(&d->arch.hvm.write_map.list);
|
||||
|
||||
+16
-14
@@ -590,6 +590,8 @@ static int cf_check vmx_domain_initialise(struct domain *d)
|
||||
*/
|
||||
d->arch.hvm.vmx.exec_sp = is_hardware_domain(d) || opt_ept_exec_sp;
|
||||
|
||||
spin_lock_init(&d->arch.hvm.vmx.uc_lock);
|
||||
|
||||
if ( (rc = vmx_alloc_vlapic_mapping(d)) != 0 )
|
||||
return rc;
|
||||
|
||||
@@ -1425,7 +1427,7 @@ static void cf_check vmx_set_segment_register(
|
||||
static int cf_check vmx_set_guest_pat(struct vcpu *v, u64 gpat)
|
||||
{
|
||||
if ( !paging_mode_hap(v->domain) ||
|
||||
unlikely(v->arch.hvm.cache_mode == NO_FILL_CACHE_MODE) )
|
||||
unlikely(v->arch.hvm.vmx.cache_mode == CACHE_MODE_NO_FILL) )
|
||||
return 0;
|
||||
|
||||
vmx_vmcs_enter(v);
|
||||
@@ -1437,7 +1439,7 @@ static int cf_check vmx_set_guest_pat(struct vcpu *v, u64 gpat)
|
||||
static int cf_check vmx_get_guest_pat(struct vcpu *v, u64 *gpat)
|
||||
{
|
||||
if ( !paging_mode_hap(v->domain) ||
|
||||
unlikely(v->arch.hvm.cache_mode == NO_FILL_CACHE_MODE) )
|
||||
unlikely(v->arch.hvm.vmx.cache_mode == CACHE_MODE_NO_FILL) )
|
||||
return 0;
|
||||
|
||||
vmx_vmcs_enter(v);
|
||||
@@ -1456,7 +1458,7 @@ static bool domain_exit_uc_mode(const struct vcpu *v)
|
||||
{
|
||||
if ( (vs == v) || !vs->is_initialised )
|
||||
continue;
|
||||
if ( (vs->arch.hvm.cache_mode == NO_FILL_CACHE_MODE) ||
|
||||
if ( (vs->arch.hvm.vmx.cache_mode == CACHE_MODE_NO_FILL) ||
|
||||
mtrr_pat_not_equal(vs, v) )
|
||||
return false;
|
||||
}
|
||||
@@ -1466,7 +1468,7 @@ static bool domain_exit_uc_mode(const struct vcpu *v)
|
||||
|
||||
static void set_uc_mode(struct domain *d, bool is_in_uc_mode)
|
||||
{
|
||||
d->arch.hvm.is_in_uc_mode = is_in_uc_mode;
|
||||
d->arch.hvm.vmx.in_uc_mode = is_in_uc_mode;
|
||||
shadow_blow_tables_per_domain(d);
|
||||
}
|
||||
|
||||
@@ -1477,10 +1479,10 @@ static void shadow_handle_cd(struct vcpu *v, unsigned long value)
|
||||
if ( value & X86_CR0_CD )
|
||||
{
|
||||
/* Entering no fill cache mode. */
|
||||
spin_lock(&d->arch.hvm.uc_lock);
|
||||
v->arch.hvm.cache_mode = NO_FILL_CACHE_MODE;
|
||||
spin_lock(&d->arch.hvm.vmx.uc_lock);
|
||||
v->arch.hvm.vmx.cache_mode = CACHE_MODE_NO_FILL;
|
||||
|
||||
if ( !d->arch.hvm.is_in_uc_mode )
|
||||
if ( !d->arch.hvm.vmx.in_uc_mode )
|
||||
{
|
||||
domain_pause_nosync(d);
|
||||
|
||||
@@ -1490,19 +1492,19 @@ static void shadow_handle_cd(struct vcpu *v, unsigned long value)
|
||||
|
||||
domain_unpause(d);
|
||||
}
|
||||
spin_unlock(&d->arch.hvm.uc_lock);
|
||||
spin_unlock(&d->arch.hvm.vmx.uc_lock);
|
||||
}
|
||||
else if ( !(value & X86_CR0_CD) &&
|
||||
(v->arch.hvm.cache_mode == NO_FILL_CACHE_MODE) )
|
||||
(v->arch.hvm.vmx.cache_mode == CACHE_MODE_NO_FILL) )
|
||||
{
|
||||
/* Exit from no fill cache mode. */
|
||||
spin_lock(&d->arch.hvm.uc_lock);
|
||||
v->arch.hvm.cache_mode = NORMAL_CACHE_MODE;
|
||||
spin_lock(&d->arch.hvm.vmx.uc_lock);
|
||||
v->arch.hvm.vmx.cache_mode = CACHE_MODE_NORMAL;
|
||||
|
||||
if ( domain_exit_uc_mode(v) )
|
||||
set_uc_mode(d, false);
|
||||
|
||||
spin_unlock(&d->arch.hvm.uc_lock);
|
||||
spin_unlock(&d->arch.hvm.vmx.uc_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1543,11 +1545,11 @@ static void cf_check vmx_handle_cd(struct vcpu *v, unsigned long value)
|
||||
|
||||
wbinvd(); /* flush possibly polluted cache */
|
||||
hvm_asid_flush_vcpu(v); /* invalidate memory type cached in TLB */
|
||||
v->arch.hvm.cache_mode = NO_FILL_CACHE_MODE;
|
||||
v->arch.hvm.vmx.cache_mode = CACHE_MODE_NO_FILL;
|
||||
}
|
||||
else
|
||||
{
|
||||
v->arch.hvm.cache_mode = NORMAL_CACHE_MODE;
|
||||
v->arch.hvm.vmx.cache_mode = CACHE_MODE_NORMAL;
|
||||
vmx_set_guest_pat(v, *pat);
|
||||
if ( !is_iommu_enabled(v->domain) || iommu_snoop )
|
||||
vmx_clear_msr_intercept(v, MSR_IA32_CR_PAT, VMX_MSR_RW);
|
||||
|
||||
@@ -97,12 +97,6 @@ struct hvm_domain {
|
||||
/* VRAM dirty support. Protect with the domain paging lock. */
|
||||
struct sh_dirty_vram *dirty_vram;
|
||||
|
||||
/* If one of vcpus of this domain is in no_fill_mode or
|
||||
* mtrr/pat between vcpus is not the same, set is_in_uc_mode
|
||||
*/
|
||||
spinlock_t uc_lock;
|
||||
bool is_in_uc_mode;
|
||||
|
||||
bool is_s3_suspended;
|
||||
|
||||
/* Compatibility setting for a bug in x2APIC LDR */
|
||||
|
||||
@@ -392,6 +392,9 @@ static inline bool using_svm(void)
|
||||
return IS_ENABLED(CONFIG_AMD_SVM) && cpu_has_svm;
|
||||
}
|
||||
|
||||
#define hvm_is_in_uc_mode(d) \
|
||||
(using_vmx() && (d)->arch.hvm.vmx.in_uc_mode)
|
||||
|
||||
#ifdef CONFIG_HVM
|
||||
|
||||
#define hvm_get_guest_tsc(v) hvm_get_guest_tsc_fixed(v, 0)
|
||||
|
||||
@@ -168,9 +168,6 @@ struct hvm_vcpu {
|
||||
|
||||
u8 evtchn_upcall_vector;
|
||||
|
||||
/* Which cache mode is this VCPU in (CR0:CD/NW)? */
|
||||
u8 cache_mode;
|
||||
|
||||
struct hvm_vcpu_io hvm_io;
|
||||
|
||||
/* Pending hw/sw interrupt (.vector = -1 means nothing pending). */
|
||||
|
||||
@@ -46,6 +46,7 @@ struct ept_data {
|
||||
|
||||
#define _VMX_DOMAIN_PML_ENABLED 0
|
||||
#define VMX_DOMAIN_PML_ENABLED (1ul << _VMX_DOMAIN_PML_ENABLED)
|
||||
|
||||
struct vmx_domain {
|
||||
mfn_t apic_access_mfn;
|
||||
/* VMX_DOMAIN_* */
|
||||
@@ -56,6 +57,13 @@ struct vmx_domain {
|
||||
* around CVE-2018-12207 as appropriate.
|
||||
*/
|
||||
bool exec_sp;
|
||||
/*
|
||||
* If one of vcpus of this domain is in no_fill_mode or
|
||||
* mtrr/pat between vcpus is not the same, set in_uc_mode.
|
||||
* Protected by uc_lock.
|
||||
*/
|
||||
bool in_uc_mode;
|
||||
spinlock_t uc_lock;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -156,6 +164,11 @@ struct vmx_vcpu {
|
||||
|
||||
uint8_t lbr_flags;
|
||||
|
||||
/* Which cache mode is this VCPU in (CR0:CD/NW)? */
|
||||
uint8_t cache_mode;
|
||||
#define CACHE_MODE_NORMAL 0
|
||||
#define CACHE_MODE_NO_FILL 2
|
||||
|
||||
/* Bitmask of segments that we can't safely use in virtual 8086 mode */
|
||||
uint16_t vm86_segment_mask;
|
||||
/* Shadow CS, SS, DS, ES, FS, GS, TR while in virtual 8086 mode */
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
#define MEMORY_NUM_TYPES MTRR_NUM_TYPES
|
||||
#define NO_HARDCODE_MEM_TYPE MTRR_NUM_TYPES
|
||||
|
||||
#define NORMAL_CACHE_MODE 0
|
||||
#define NO_FILL_CACHE_MODE 2
|
||||
|
||||
#define INVALID_MEM_TYPE X86_NUM_MT
|
||||
|
||||
/* In the Intel processor's MTRR interface, the MTRR type is always held in
|
||||
|
||||
@@ -559,7 +559,7 @@ _sh_propagate(struct vcpu *v,
|
||||
if ( !mmio_mfn &&
|
||||
(type = hvm_get_mem_pinned_cacheattr(d, target_gfn, 0)) >= 0 )
|
||||
sflags |= pat_type_2_pte_flags(type);
|
||||
else if ( d->arch.hvm.is_in_uc_mode )
|
||||
else if ( hvm_is_in_uc_mode(d) )
|
||||
sflags |= pat_type_2_pte_flags(X86_MT_UC);
|
||||
else
|
||||
if ( iomem_access_permitted(d, mfn_x(target_mfn), mfn_x(target_mfn)) )
|
||||
|
||||