Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d8b81ab authored by Xiao Guangrong's avatar Xiao Guangrong Committed by Avi Kivity
Browse files

KVM: introduce readonly memslot



In current code, if we map a readonly memory space from host to guest
and the page is not currently mapped in the host, we will get a fault
pfn and async is not allowed, then the vm will crash

We introduce readonly memory region to map ROM/ROMD to the guest, read access
is happy for readonly memslot, write access on readonly memslot will cause
KVM_EXIT_MMIO exit

Signed-off-by: default avatarXiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 7068d097
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -857,7 +857,8 @@ struct kvm_userspace_memory_region {
};

/* for kvm_memory_region::flags */
#define KVM_MEM_LOG_DIRTY_PAGES  1UL
#define KVM_MEM_LOG_DIRTY_PAGES	(1UL << 0)
#define KVM_MEM_READONLY	(1UL << 1)

This ioctl allows the user to create or modify a guest physical memory
slot.  When changing an existing slot, it may be moved in the guest
@@ -873,9 +874,12 @@ It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
be identical.  This allows large pages in the guest to be backed by large
pages in the host.

The flags field supports just one flag, KVM_MEM_LOG_DIRTY_PAGES, which
The flags field supports two flag, KVM_MEM_LOG_DIRTY_PAGES, which
instructs kvm to keep track of writes to memory within the slot.  See
the KVM_GET_DIRTY_LOG ioctl.
the KVM_GET_DIRTY_LOG ioctl. Another flag is KVM_MEM_READONLY when the
KVM_CAP_READONLY_MEM capability, it indicates the guest memory is read-only,
that means, guest is only allowed to read it. Writes will be posted to
userspace as KVM_EXIT_MMIO exits.

When the KVM_CAP_SYNC_MMU capability, changes in the backing of the memory
region are automatically reflected into the guest.  For example, an mmap()
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#define __KVM_HAVE_DEBUGREGS
#define __KVM_HAVE_XSAVE
#define __KVM_HAVE_XCRS
#define __KVM_HAVE_READONLY_MEM

/* Architectural interrupt line count. */
#define KVM_NR_INTERRUPTS 256
+9 −0
Original line number Diff line number Diff line
@@ -2647,6 +2647,15 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *

static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, pfn_t pfn)
{
	/*
	 * Do not cache the mmio info caused by writing the readonly gfn
	 * into the spte otherwise read access on readonly gfn also can
	 * caused mmio page fault and treat it as mmio access.
	 * Return 1 to tell kvm to emulate it.
	 */
	if (pfn == KVM_PFN_ERR_RO_FAULT)
		return 1;

	if (pfn == KVM_PFN_ERR_HWPOISON) {
		kvm_send_hwpoison_signal(gfn_to_hva(vcpu->kvm, gfn), current);
		return 0;
+1 −0
Original line number Diff line number Diff line
@@ -2175,6 +2175,7 @@ int kvm_dev_ioctl_check_extension(long ext)
	case KVM_CAP_GET_TSC_KHZ:
	case KVM_CAP_PCI_2_3:
	case KVM_CAP_KVMCLOCK_CTRL:
	case KVM_CAP_READONLY_MEM:
		r = 1;
		break;
	case KVM_CAP_COALESCED_MMIO:
+5 −1
Original line number Diff line number Diff line
@@ -106,7 +106,8 @@ struct kvm_userspace_memory_region {
 * other bits are reserved for kvm internal use which are defined in
 * include/linux/kvm_host.h.
 */
#define KVM_MEM_LOG_DIRTY_PAGES  1UL
#define KVM_MEM_LOG_DIRTY_PAGES	(1UL << 0)
#define KVM_MEM_READONLY	(1UL << 1)

/* for KVM_IRQ_LINE */
struct kvm_irq_level {
@@ -621,6 +622,9 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_PPC_GET_SMMU_INFO 78
#define KVM_CAP_S390_COW 79
#define KVM_CAP_PPC_ALLOC_HTAB 80
#ifdef __KVM_HAVE_READONLY_MEM
#define KVM_CAP_READONLY_MEM 81
#endif

#ifdef KVM_CAP_IRQ_ROUTING

Loading