mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
Merge 4118bd1834 ("KVM: x86/mmu: Ensure that kvm_release_pfn_clean() takes exact pfn from kvm_faultin_pfn()") into android14-6.1-lts
Steps on the way to 6.1.121 Resolves merge conflicts in: arch/arm64/kvm/vgic/vgic-its.c arch/arm64/kvm/vgic/vgic.h Change-Id: I0841e064555bb23ffab537b15b4425a7ab4b8efc Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -855,6 +855,9 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
|
|||||||
|
|
||||||
ite = find_ite(its, device_id, event_id);
|
ite = find_ite(its, device_id, event_id);
|
||||||
if (ite && its_is_collection_mapped(ite->collection)) {
|
if (ite && its_is_collection_mapped(ite->collection)) {
|
||||||
|
struct its_device *device = find_its_device(its, device_id);
|
||||||
|
int ite_esz = vgic_its_get_abi(its)->ite_esz;
|
||||||
|
gpa_t gpa = device->itt_addr + ite->event_id * ite_esz;
|
||||||
/*
|
/*
|
||||||
* Though the spec talks about removing the pending state, we
|
* Though the spec talks about removing the pending state, we
|
||||||
* don't bother here since we clear the ITTE anyway and the
|
* don't bother here since we clear the ITTE anyway and the
|
||||||
@@ -863,7 +866,8 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
|
|||||||
vgic_its_invalidate_cache(kvm);
|
vgic_its_invalidate_cache(kvm);
|
||||||
|
|
||||||
its_free_ite(kvm, ite);
|
its_free_ite(kvm, ite);
|
||||||
return 0;
|
|
||||||
|
return vgic_its_write_entry_lock(its, gpa, 0, ite_esz);
|
||||||
}
|
}
|
||||||
|
|
||||||
return E_ITS_DISCARD_UNMAPPED_INTERRUPT;
|
return E_ITS_DISCARD_UNMAPPED_INTERRUPT;
|
||||||
@@ -1211,9 +1215,11 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
|
|||||||
bool valid = its_cmd_get_validbit(its_cmd);
|
bool valid = its_cmd_get_validbit(its_cmd);
|
||||||
u8 num_eventid_bits = its_cmd_get_size(its_cmd);
|
u8 num_eventid_bits = its_cmd_get_size(its_cmd);
|
||||||
gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd);
|
gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd);
|
||||||
|
int dte_esz = vgic_its_get_abi(its)->dte_esz;
|
||||||
struct its_device *device;
|
struct its_device *device;
|
||||||
|
gpa_t gpa;
|
||||||
|
|
||||||
if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL))
|
if (!vgic_its_check_id(its, its->baser_device_table, device_id, &gpa))
|
||||||
return E_ITS_MAPD_DEVICE_OOR;
|
return E_ITS_MAPD_DEVICE_OOR;
|
||||||
|
|
||||||
if (valid && num_eventid_bits > VITS_TYPER_IDBITS)
|
if (valid && num_eventid_bits > VITS_TYPER_IDBITS)
|
||||||
@@ -1234,7 +1240,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
|
|||||||
* is an error, so we are done in any case.
|
* is an error, so we are done in any case.
|
||||||
*/
|
*/
|
||||||
if (!valid)
|
if (!valid)
|
||||||
return 0;
|
return vgic_its_write_entry_lock(its, gpa, 0, dte_esz);
|
||||||
|
|
||||||
device = vgic_its_alloc_device(its, device_id, itt_addr,
|
device = vgic_its_alloc_device(its, device_id, itt_addr,
|
||||||
num_eventid_bits);
|
num_eventid_bits);
|
||||||
@@ -2207,7 +2213,6 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
|
|||||||
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
||||||
struct its_ite *ite, gpa_t gpa, int ite_esz)
|
struct its_ite *ite, gpa_t gpa, int ite_esz)
|
||||||
{
|
{
|
||||||
struct kvm *kvm = its->dev->kvm;
|
|
||||||
u32 next_offset;
|
u32 next_offset;
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
@@ -2216,7 +2221,8 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
|||||||
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
|
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
|
||||||
ite->collection->collection_id;
|
ite->collection->collection_id;
|
||||||
val = cpu_to_le64(val);
|
val = cpu_to_le64(val);
|
||||||
return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
|
|
||||||
|
return vgic_its_write_entry_lock(its, gpa, val, ite_esz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2357,7 +2363,6 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
|
|||||||
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
||||||
gpa_t ptr, int dte_esz)
|
gpa_t ptr, int dte_esz)
|
||||||
{
|
{
|
||||||
struct kvm *kvm = its->dev->kvm;
|
|
||||||
u64 val, itt_addr_field;
|
u64 val, itt_addr_field;
|
||||||
u32 next_offset;
|
u32 next_offset;
|
||||||
|
|
||||||
@@ -2368,7 +2373,8 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
|||||||
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
|
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
|
||||||
(dev->num_eventid_bits - 1));
|
(dev->num_eventid_bits - 1));
|
||||||
val = cpu_to_le64(val);
|
val = cpu_to_le64(val);
|
||||||
return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
|
|
||||||
|
return vgic_its_write_entry_lock(its, ptr, val, dte_esz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2555,7 +2561,8 @@ static int vgic_its_save_cte(struct vgic_its *its,
|
|||||||
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
|
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
|
||||||
collection->collection_id);
|
collection->collection_id);
|
||||||
val = cpu_to_le64(val);
|
val = cpu_to_le64(val);
|
||||||
return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
|
|
||||||
|
return vgic_its_write_entry_lock(its, gpa, val, esz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2571,8 +2578,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
|
|||||||
u64 val;
|
u64 val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
BUG_ON(esz > sizeof(val));
|
ret = vgic_its_read_entry_lock(its, gpa, &val, esz);
|
||||||
ret = kvm_read_guest_lock(kvm, gpa, &val, esz);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
val = le64_to_cpu(val);
|
val = le64_to_cpu(val);
|
||||||
@@ -2610,7 +2616,6 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
|
|||||||
u64 baser = its->baser_coll_table;
|
u64 baser = its->baser_coll_table;
|
||||||
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
|
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
|
||||||
struct its_collection *collection;
|
struct its_collection *collection;
|
||||||
u64 val;
|
|
||||||
size_t max_size, filled = 0;
|
size_t max_size, filled = 0;
|
||||||
int ret, cte_esz = abi->cte_esz;
|
int ret, cte_esz = abi->cte_esz;
|
||||||
|
|
||||||
@@ -2634,10 +2639,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
|
|||||||
* table is not fully filled, add a last dummy element
|
* table is not fully filled, add a last dummy element
|
||||||
* with valid bit unset
|
* with valid bit unset
|
||||||
*/
|
*/
|
||||||
val = 0;
|
return vgic_its_write_entry_lock(its, gpa, 0, cte_esz);
|
||||||
BUG_ON(cte_esz > sizeof(val));
|
|
||||||
ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -132,14 +132,27 @@ static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq)
|
|||||||
return vgic_irq_get_lr_count(irq) > 1;
|
return vgic_irq_get_lr_count(irq) > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa,
|
static inline int vgic_its_read_entry_lock(struct vgic_its *its, gpa_t eaddr,
|
||||||
const void *data, unsigned long len)
|
u64 *eval, unsigned long esize)
|
||||||
{
|
{
|
||||||
int ret;
|
struct kvm *kvm = its->dev->kvm;
|
||||||
|
|
||||||
ret = kvm_write_guest_lock(kvm, gpa, data, len);
|
if (KVM_BUG_ON(esize != sizeof(*eval), kvm))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
return ret;
|
return kvm_read_guest_lock(kvm, eaddr, eval, esize);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int vgic_its_write_entry_lock(struct vgic_its *its, gpa_t eaddr,
|
||||||
|
u64 eval, unsigned long esize)
|
||||||
|
{
|
||||||
|
struct kvm *kvm = its->dev->kvm;
|
||||||
|
|
||||||
|
if (KVM_BUG_ON(esize != sizeof(eval), kvm))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return kvm_write_guest_lock(kvm, eaddr, &eval, esize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -4245,6 +4245,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
|
|||||||
bool is_tdp_mmu_fault = is_tdp_mmu(vcpu->arch.mmu);
|
bool is_tdp_mmu_fault = is_tdp_mmu(vcpu->arch.mmu);
|
||||||
|
|
||||||
unsigned long mmu_seq;
|
unsigned long mmu_seq;
|
||||||
|
kvm_pfn_t orig_pfn;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
fault->gfn = fault->addr >> PAGE_SHIFT;
|
fault->gfn = fault->addr >> PAGE_SHIFT;
|
||||||
@@ -4272,6 +4273,8 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
|
|||||||
if (r != RET_PF_CONTINUE)
|
if (r != RET_PF_CONTINUE)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
orig_pfn = fault->pfn;
|
||||||
|
|
||||||
r = RET_PF_RETRY;
|
r = RET_PF_RETRY;
|
||||||
|
|
||||||
if (is_tdp_mmu_fault)
|
if (is_tdp_mmu_fault)
|
||||||
@@ -4296,7 +4299,7 @@ out_unlock:
|
|||||||
read_unlock(&vcpu->kvm->mmu_lock);
|
read_unlock(&vcpu->kvm->mmu_lock);
|
||||||
else
|
else
|
||||||
write_unlock(&vcpu->kvm->mmu_lock);
|
write_unlock(&vcpu->kvm->mmu_lock);
|
||||||
kvm_release_pfn_clean(fault->pfn);
|
kvm_release_pfn_clean(orig_pfn);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -790,6 +790,7 @@ FNAME(is_self_change_mapping)(struct kvm_vcpu *vcpu,
|
|||||||
static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
||||||
{
|
{
|
||||||
struct guest_walker walker;
|
struct guest_walker walker;
|
||||||
|
kvm_pfn_t orig_pfn;
|
||||||
int r;
|
int r;
|
||||||
unsigned long mmu_seq;
|
unsigned long mmu_seq;
|
||||||
bool is_self_change_mapping;
|
bool is_self_change_mapping;
|
||||||
@@ -868,6 +869,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
|
|||||||
walker.pte_access &= ~ACC_EXEC_MASK;
|
walker.pte_access &= ~ACC_EXEC_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
orig_pfn = fault->pfn;
|
||||||
|
|
||||||
r = RET_PF_RETRY;
|
r = RET_PF_RETRY;
|
||||||
write_lock(&vcpu->kvm->mmu_lock);
|
write_lock(&vcpu->kvm->mmu_lock);
|
||||||
|
|
||||||
@@ -881,7 +884,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
|
|||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
write_unlock(&vcpu->kvm->mmu_lock);
|
write_unlock(&vcpu->kvm->mmu_lock);
|
||||||
kvm_release_pfn_clean(fault->pfn);
|
kvm_release_pfn_clean(orig_pfn);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user