@@ -479,6 +479,7 @@ typedef void (*on_lock_fn_t)(struct kvm *kvm, unsigned long start,
struct kvm_useraddr_range {
unsigned long start;
unsigned long end;
+ struct inode *inode;
pte_t pte;
gfn_handler_t handler;
on_lock_fn_t on_lock;
@@ -519,9 +520,19 @@ static __always_inline int __kvm_handle_useraddr_range(struct kvm *kvm,
slots = __kvm_memslots(kvm, i);
kvm_for_each_memslot(slot, slots) {
unsigned long useraddr_start, useraddr_end;
+ unsigned long useraddr_base;
- useraddr_start = max(range->start, slot->userspace_addr);
- useraddr_end = min(range->end, slot->userspace_addr +
+ if (range->inode) {
+ if (!slot->file ||
+ slot->file->f_inode != range->inode)
+ continue;
+ useraddr_base = slot->file_ofs;
+ } else
+ useraddr_base = slot->userspace_addr;
+
+
+ useraddr_start = max(range->start, useraddr_base);
+ useraddr_end = min(range->end, useraddr_base +
(slot->npages << PAGE_SHIFT));
if (useraddr_start >= useraddr_end)
continue;
@@ -540,10 +551,10 @@ static __always_inline int __kvm_handle_useraddr_range(struct kvm *kvm,
* {gfn_start, gfn_start+1, ..., gfn_end-1}.
*/
gfn_range.start = useraddr_to_gfn_memslot(useraddr_start,
- slot, true);
+ slot, !range->inode);
gfn_range.end = useraddr_to_gfn_memslot(
useraddr_end + PAGE_SIZE - 1,
- slot, true);
+ slot, !range->inode);
gfn_range.slot = slot;
if (!locked) {
@@ -585,6 +596,7 @@ static __always_inline int kvm_handle_hva_range(struct mmu_notifier *mn,
.on_lock = (void *)kvm_null_fn,
.flush_on_ret = true,
.may_block = false,
+ .inode = NULL,
};
return __kvm_handle_useraddr_range(kvm, &range);
@@ -604,6 +616,7 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
.on_lock = (void *)kvm_null_fn,
.flush_on_ret = false,
.may_block = false,
+ .inode = NULL,
};
return __kvm_handle_useraddr_range(kvm, &range);
@@ -672,6 +685,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
.on_lock = kvm_inc_notifier_count,
.flush_on_ret = true,
.may_block = mmu_notifier_range_blockable(range),
+ .inode = NULL,
};
trace_kvm_unmap_hva_range(range->start, range->end);
@@ -723,6 +737,7 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
.on_lock = kvm_dec_notifier_count,
.flush_on_ret = false,
.may_block = mmu_notifier_range_blockable(range),
+ .inode = NULL,
};
bool wake;