Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: s390: Use guest address to mark guest page dirty

Stop using the userspace address to mark the guest page dirty.
mark_page_dirty() expects a guest frame number, but was being passed a
host virtual frame number. When slot == NULL, mark_page_dirty_in_slot()
does nothing and does not complain.

This means that in some circumstances the dirtiness of the guest page
might have been lost.

Fix by adding two fields in struct kvm_s390_adapter_int to keep the
guest addressses, and use those for mark_page_dirty().

Fixes: f65470661f36 ("KVM: s390/interrupt: do not pin adapter interrupt pages")
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

+6 -2
+4 -2
arch/s390/kvm/interrupt.c
··· 2768 2768 bit = get_ind_bit(adapter_int->ind_addr, 2769 2769 adapter_int->ind_offset, adapter->swap); 2770 2770 set_bit(bit, map); 2771 - mark_page_dirty(kvm, adapter_int->ind_addr >> PAGE_SHIFT); 2771 + mark_page_dirty(kvm, adapter_int->ind_gaddr >> PAGE_SHIFT); 2772 2772 set_page_dirty_lock(ind_page); 2773 2773 map = page_address(summary_page); 2774 2774 bit = get_ind_bit(adapter_int->summary_addr, 2775 2775 adapter_int->summary_offset, adapter->swap); 2776 2776 summary_set = test_and_set_bit(bit, map); 2777 - mark_page_dirty(kvm, adapter_int->summary_addr >> PAGE_SHIFT); 2777 + mark_page_dirty(kvm, adapter_int->summary_gaddr >> PAGE_SHIFT); 2778 2778 set_page_dirty_lock(summary_page); 2779 2779 srcu_read_unlock(&kvm->srcu, idx); 2780 2780 ··· 2870 2870 if (kvm_is_error_hva(uaddr_s) || kvm_is_error_hva(uaddr_i)) 2871 2871 return -EFAULT; 2872 2872 e->adapter.summary_addr = uaddr_s; 2873 + e->adapter.summary_gaddr = ue->u.adapter.summary_addr; 2873 2874 e->adapter.ind_addr = uaddr_i; 2875 + e->adapter.ind_gaddr = ue->u.adapter.ind_addr; 2874 2876 e->adapter.summary_offset = ue->u.adapter.summary_offset; 2875 2877 e->adapter.ind_offset = ue->u.adapter.ind_offset; 2876 2878 e->adapter.adapter_id = ue->u.adapter.adapter_id;
+2
include/linux/kvm_host.h
··· 645 645 646 646 struct kvm_s390_adapter_int { 647 647 u64 ind_addr; 648 + u64 ind_gaddr; 648 649 u64 summary_addr; 650 + u64 summary_gaddr; 649 651 u64 ind_offset; 650 652 u32 summary_offset; 651 653 u32 adapter_id;