[PATCH v7 03/23] KVM: Allow KVM implementations to switch off MMIO independent of Kconfig
Marc Zyngier
maz at kernel.org
Wed Sep 2 01:30:17 PDT 2026
On Wed, 02 Sep 2026 01:38:53 +0100,
Sean Christopherson <seanjc at google.com> wrote:
>
> On Mon, Aug 31, 2026, Steffen Eiden wrote:
> > Only defining KVM_MMIO is not flexible enough for multi-KVM systems
> > where one KVM implements MMIO but others do not. Solve this by
> > additionally testing for the non-existence of KVM_NO_MMIO before
> > including MMIO code to KVM.
>
> Ewwwww. IIUC, s390 ends up with two KVM modules, i.e. there really are two different
> KVMs being built. Rather than have a KVM_MMIO and NO_KVM_MMIO, I vote very
> strongly to drop CONFIG_KVM_MMIO entirely and replace it with __KVM_HAVE_ARCH_MMIO,
> a la __KVM_HAVE_ARCH_VM_FREE and others. Tracking two separate macros is going
> to be annoying to maintain, and will definitely be confusing for non-s390 people.
>
> It'll mean linking in an emtpy coalesced_mmio.o on s390 when building without arm64
> support, but I'm guessing that won't be at all common for s390 builds.
>
I ended-up doing something very similar locally, because I couldn't
really make head or tail of the logic while being in holiday mode
(which doesn't help). However, I kept the negative logic, so that we
don't need to add anything to any architecture but S390 (they are the
odd one out here).
Untested hack follows.
M.
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 449154f9a4852..dd138b730217e 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -22,7 +22,6 @@ menuconfig KVM
select KVM_COMMON
select KVM_GENERIC_HARDWARE_ENABLING
select HAVE_KVM_CPU_RELAX_INTERCEPT
- select KVM_MMIO
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select VIRT_XFER_TO_GUEST_WORK
select KVM_VFIO
diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig
index 15da2d88c0c10..f03872ba0ba8c 100644
--- a/arch/loongarch/kvm/Kconfig
+++ b/arch/loongarch/kvm/Kconfig
@@ -28,7 +28,6 @@ config KVM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
- select KVM_MMIO
select VIRT_XFER_TO_GUEST_WORK
select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS
diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig
index b1b9a1d677581..c65596fdf54f4 100644
--- a/arch/mips/kvm/Kconfig
+++ b/arch/mips/kvm/Kconfig
@@ -22,7 +22,6 @@ config KVM
select EXPORT_UASM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
- select KVM_MMIO
select KVM_GENERIC_HARDWARE_ENABLING
select HAVE_KVM_READONLY_MEM
help
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index b6bc2fc86dca6..c5565d6fb27e4 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -30,7 +30,6 @@ config KVM_BOOK3S_HANDLER
config KVM_BOOK3S_32_HANDLER
bool
select KVM_BOOK3S_HANDLER
- select KVM_MMIO
config KVM_BOOK3S_64_HANDLER
bool
@@ -38,7 +37,6 @@ config KVM_BOOK3S_64_HANDLER
config KVM_BOOK3S_PR_POSSIBLE
bool
- select KVM_MMIO
config KVM_BOOK3S_HV_POSSIBLE
bool
@@ -201,7 +199,6 @@ config KVM_E500V2
depends on PPC_E500 && !PPC_E500MC
depends on !CONTEXT_TRACKING_USER
select KVM
- select KVM_MMIO
help
Support running unmodified E500 guest kernels in virtual machines on
E500v2 host processors.
@@ -216,7 +213,6 @@ config KVM_E500MC
depends on PPC_E500MC
depends on !CONTEXT_TRACKING_USER
select KVM
- select KVM_MMIO
select KVM_BOOKE_HV
help
Support running unmodified E500MC/E5500/E6500 guest kernels in
diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig
index ec2cee0a39e01..3aea8d4939d2e 100644
--- a/arch/riscv/kvm/Kconfig
+++ b/arch/riscv/kvm/Kconfig
@@ -28,7 +28,6 @@ config KVM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
- select KVM_MMIO
select VIRT_XFER_TO_GUEST_WORK
select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS
diff --git a/arch/s390/include/asm/kvm_host_s390.h b/arch/s390/include/asm/kvm_host_s390.h
index cd692f8fb7643..3c65c52d6682b 100644
--- a/arch/s390/include/asm/kvm_host_s390.h
+++ b/arch/s390/include/asm/kvm_host_s390.h
@@ -34,6 +34,8 @@
#define KVM_S390_MANAGES_S390_GUEST 1
+#define __KVM_NO_MMIO
+
/*
* These seem to be used for allocating ->chip in the routing table, which we
* don't use. 1 is as small as we can get to reduce the needed memory. If we
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 538ed1e803326..48ca567b0a846 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -32,7 +32,6 @@ config KVM_X86
select VHOST_TASK
select KVM_ASYNC_PF
select USER_RETURN_NOTIFIER
- select KVM_MMIO
select SCHED_INFO
select PERF_EVENTS
select GUEST_PERF_EVENTS
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 03bfc92864b6e..dc9b68793f0d7 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -833,7 +833,7 @@ struct kvm {
struct kvm_vm_stat stat;
struct kvm_arch arch;
refcount_t users_count;
-#ifdef CONFIG_KVM_MMIO
+#ifndef __KVM_NO_MMIO
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
spinlock_t ring_lock;
struct list_head coalesced_zones;
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index c3c0ee253fc77..c012f30127e38 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -40,9 +40,6 @@ config NEED_KVM_DIRTY_RING_WITH_BITMAP
bool
depends on HAVE_KVM_DIRTY_RING
-config KVM_MMIO
- bool
-
config KVM_ASYNC_PF
bool
diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
index d047d4cf58c9f..c4fb1e01d0c89 100644
--- a/virt/kvm/Makefile.kvm
+++ b/virt/kvm/Makefile.kvm
@@ -5,9 +5,8 @@
KVM ?= ../../../virt/kvm
-kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/binary_stats.o
+kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/coalesced_mmio.o $(KVM)/binary_stats.o
kvm-$(CONFIG_KVM_VFIO) += $(KVM)/vfio.o
-kvm-$(CONFIG_KVM_MMIO) += $(KVM)/coalesced_mmio.o
kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
kvm-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o
kvm-$(CONFIG_HAVE_KVM_DIRTY_RING) += $(KVM)/dirty_ring.o
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 6b1d901610998..6bd4157b3ef41 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -15,6 +15,8 @@
#include <linux/slab.h>
#include <linux/kvm.h>
+#ifndef __KVM_NO_MMIO
+
#include "coalesced_mmio.h"
static inline struct kvm_coalesced_mmio_dev *to_mmio(struct kvm_io_device *dev)
@@ -188,3 +190,4 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,
*/
return 0;
}
+#endif
diff --git a/virt/kvm/coalesced_mmio.h b/virt/kvm/coalesced_mmio.h
index 36f84264ed257..77b811dee27c2 100644
--- a/virt/kvm/coalesced_mmio.h
+++ b/virt/kvm/coalesced_mmio.h
@@ -11,7 +11,7 @@
*
*/
-#ifdef CONFIG_KVM_MMIO
+#ifndef __KVM_NO_MMIO
#include <linux/list.h>
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 65eb26a0520d8..2f25b75dbfd44 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4059,7 +4059,7 @@ static vm_fault_t kvm_vcpu_fault(struct vm_fault *vmf)
else if (vmf->pgoff == KVM_PIO_PAGE_OFFSET)
page = virt_to_page(vcpu->arch.pio_data);
#endif
-#ifdef CONFIG_KVM_MMIO
+#ifndef __KVM_NO_MMIO
else if (vmf->pgoff == KVM_COALESCED_MMIO_PAGE_OFFSET)
page = virt_to_page(vcpu->kvm->coalesced_mmio_ring);
#endif
@@ -4900,7 +4900,7 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
case KVM_CAP_ENABLE_CAP_VM:
case KVM_CAP_HALT_POLL:
return 1;
-#ifdef CONFIG_KVM_MMIO
+#ifndef __KVM_NO_MMIO
case KVM_CAP_COALESCED_MMIO:
return KVM_COALESCED_MMIO_PAGE_OFFSET;
case KVM_CAP_COALESCED_PIO:
@@ -5241,7 +5241,7 @@ static long kvm_vm_ioctl(struct file *filp,
break;
}
#endif
-#ifdef CONFIG_KVM_MMIO
+#ifndef __KVM_NO_MMIO
case KVM_REGISTER_COALESCED_MMIO: {
struct kvm_coalesced_mmio_zone zone;
@@ -5563,7 +5563,7 @@ static long kvm_dev_ioctl(struct file *filp,
#ifdef CONFIG_X86
r += PAGE_SIZE; /* pio data page */
#endif
-#ifdef CONFIG_KVM_MMIO
+#ifndef __KVM_NO_MMIO
r += PAGE_SIZE; /* coalesced mmio ring page */
#endif
break;
--
Jazz isn't dead. It just smells funny.
More information about the linux-arm-kernel
mailing list