* [PATCH v3 12/12] KVM: x86: First attempt at converting nested virtual APIC page to gpc
From: David Woodhouse @ 2021-11-17 17:40 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
This is what evolved during the discussion at
https://lore.kernel.org/kvm/960E233F-EC0B-4FB5-BA2E-C8D2CCB38B12@infradead.org/T/#m11d75fcfe2da357ec1dabba0d0e3abb91fd13665
As discussed, an alternative approach might be to augment
kvm_arch_memslots_updated() to raise KVM_REQ_GET_NESTED_STATE_PAGES to
each vCPU (and make that req only do anything on a given vCPU if that
vCPU is actually in L2 guest mode).
That would mean the reload gets actively triggered even on memslot
changes rather than only on MMU notifiers as is the case now. It could
*potentially* mean we can drop the new 'check_guest_maps' function.
The 'check_guest_maps' function could be a lot simpler than it is,
though. It only really needs to get kvm->memslots->generation, then
check each gpc->generation against that, and each gpc->valid.
Also I suspect we *shouldn't* destroy the virtual_apic_cache in
nested_vmx_vmexit(). We can just leave it there for next time the
vCPU enters guest mode. If it happens to get invalidated in the
meantime, that's fine and we'll refresh it on the way back in.
We probably *would* want to actively do something on memslot changes
in that case though, to ensure that even if the vCPU isn't in guest
mode any more, we *release* the cached page.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/vmx/nested.c | 50 ++++++++++++++++++++++++++++-----
arch/x86/kvm/vmx/vmx.c | 12 +++++---
arch/x86/kvm/vmx/vmx.h | 2 +-
arch/x86/kvm/x86.c | 10 +++++++
5 files changed, 63 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6ea2446ab851..24f6f3e2de47 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1511,6 +1511,7 @@ struct kvm_x86_nested_ops {
int (*enable_evmcs)(struct kvm_vcpu *vcpu,
uint16_t *vmcs_version);
uint16_t (*get_evmcs_version)(struct kvm_vcpu *vcpu);
+ void (*check_guest_maps)(struct kvm_vcpu *vcpu);
};
struct kvm_x86_init_ops {
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 1e2f66951566..794aa6021188 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -309,7 +309,7 @@ static void free_nested(struct kvm_vcpu *vcpu)
kvm_release_page_clean(vmx->nested.apic_access_page);
vmx->nested.apic_access_page = NULL;
}
- kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);
+ kvm_gfn_to_pfn_cache_destroy(vcpu->kvm, &vmx->nested.virtual_apic_cache);
kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map, true);
vmx->nested.pi_desc = NULL;
@@ -3179,10 +3179,12 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
}
if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
- map = &vmx->nested.virtual_apic_map;
+ struct gfn_to_pfn_cache *gpc = &vmx->nested.virtual_apic_cache;
- if (!kvm_vcpu_map(vcpu, gpa_to_gfn(vmcs12->virtual_apic_page_addr), map)) {
- vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, pfn_to_hpa(map->pfn));
+ if (!kvm_gfn_to_pfn_cache_init(vcpu->kvm, gpc, vcpu, true, true,
+ vmcs12->virtual_apic_page_addr,
+ PAGE_SIZE, true)) {
+ vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, pfn_to_hpa(gpc->pfn));
} else if (nested_cpu_has(vmcs12, CPU_BASED_CR8_LOAD_EXITING) &&
nested_cpu_has(vmcs12, CPU_BASED_CR8_STORE_EXITING) &&
!nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
@@ -3207,6 +3209,9 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
if (nested_cpu_has_posted_intr(vmcs12)) {
map = &vmx->nested.pi_desc_map;
+ if (kvm_vcpu_mapped(map))
+ kvm_vcpu_unmap(vcpu, map, true);
+
if (!kvm_vcpu_map(vcpu, gpa_to_gfn(vmcs12->posted_intr_desc_addr), map)) {
vmx->nested.pi_desc =
(struct pi_desc *)(((void *)map->hva) +
@@ -3251,6 +3256,29 @@ static bool vmx_get_nested_state_pages(struct kvm_vcpu *vcpu)
return true;
}
+static void nested_vmx_check_guest_maps(struct kvm_vcpu *vcpu)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct gfn_to_pfn_cache *gpc;
+
+ int valid;
+
+ if (nested_cpu_has_posted_intr(vmcs12)) {
+ gpc = &vmx->nested.virtual_apic_cache;
+
+ read_lock(&gpc->lock);
+ valid = kvm_gfn_to_pfn_cache_check(vcpu->kvm, gpc,
+ vmcs12->virtual_apic_page_addr,
+ PAGE_SIZE);
+ read_unlock(&gpc->lock);
+ if (!valid) {
+ kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
+ return;
+ }
+ }
+}
+
static int nested_vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
{
struct vmcs12 *vmcs12;
@@ -3749,9 +3777,15 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256);
if (max_irr != 256) {
- vapic_page = vmx->nested.virtual_apic_map.hva;
- if (!vapic_page)
+ struct gfn_to_pfn_cache *gpc = &vmx->nested.virtual_apic_cache;
+
+ read_lock(&gpc->lock);
+ if (!kvm_gfn_to_pfn_cache_check(vcpu->kvm, gpc, gpc->gpa, PAGE_SIZE)) {
+ read_unlock(&gpc->lock);
goto mmio_needed;
+ }
+
+ vapic_page = gpc->khva;
__kvm_apic_update_irr(vmx->nested.pi_desc->pir,
vapic_page, &max_irr);
@@ -3761,6 +3795,7 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
status |= (u8)max_irr;
vmcs_write16(GUEST_INTR_STATUS, status);
}
+ read_unlock(&gpc->lock);
}
nested_mark_vmcs12_pages_dirty(vcpu);
@@ -4581,7 +4616,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
kvm_release_page_clean(vmx->nested.apic_access_page);
vmx->nested.apic_access_page = NULL;
}
- kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);
+ kvm_gfn_to_pfn_cache_destroy(vcpu->kvm, &vmx->nested.virtual_apic_cache);
kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map, true);
vmx->nested.pi_desc = NULL;
@@ -6756,4 +6791,5 @@ struct kvm_x86_nested_ops vmx_nested_ops = {
.write_log_dirty = nested_vmx_write_pml_buffer,
.enable_evmcs = nested_enable_evmcs,
.get_evmcs_version = nested_get_evmcs_version,
+ .check_guest_maps = nested_vmx_check_guest_maps,
};
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index ba66c171d951..6c61faef86d3 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -3839,19 +3839,23 @@ void pt_update_intercept_for_msr(struct kvm_vcpu *vcpu)
static bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- void *vapic_page;
+ struct gfn_to_pfn_cache *gpc = &vmx->nested.virtual_apic_cache;
u32 vppr;
int rvi;
if (WARN_ON_ONCE(!is_guest_mode(vcpu)) ||
!nested_cpu_has_vid(get_vmcs12(vcpu)) ||
- WARN_ON_ONCE(!vmx->nested.virtual_apic_map.gfn))
+ WARN_ON_ONCE(gpc->gpa == GPA_INVALID))
return false;
rvi = vmx_get_rvi();
- vapic_page = vmx->nested.virtual_apic_map.hva;
- vppr = *((u32 *)(vapic_page + APIC_PROCPRI));
+ read_lock(&gpc->lock);
+ if (!kvm_gfn_to_pfn_cache_check(vcpu->kvm, gpc, gpc->gpa, PAGE_SIZE))
+ vppr = *((u32 *)(gpc->khva + APIC_PROCPRI));
+ else
+ vppr = 0xff;
+ read_unlock(&gpc->lock);
return ((rvi & 0xf0) > (vppr & 0xf0));
}
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 4df2ac24ffc1..8364e7fc92a0 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -195,7 +195,7 @@ struct nested_vmx {
* pointers, so we must keep them pinned while L2 runs.
*/
struct page *apic_access_page;
- struct kvm_host_map virtual_apic_map;
+ struct gfn_to_pfn_cache virtual_apic_cache;
struct kvm_host_map pi_desc_map;
struct kvm_host_map msr_bitmap_map;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6f7669c94c79..caf35aa85ae3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9739,6 +9739,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
if (kvm_check_request(KVM_REQ_UPDATE_CPU_DIRTY_LOGGING, vcpu))
static_call(kvm_x86_update_cpu_dirty_logging)(vcpu);
+ if (kvm_check_request(KVM_REQ_GPC_INVALIDATE, vcpu))
+ ; /* Nothing to do. It just wanted to wake us */
}
if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win ||
@@ -9785,6 +9787,14 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
local_irq_disable();
vcpu->mode = IN_GUEST_MODE;
+ /*
+ * If the guest requires direct access to mapped L1 pages, check
+ * the caches are valid. Will raise KVM_REQ_GET_NESTED_STATE_PAGES
+ * to go and revalidate them, if necessary.
+ */
+ if (is_guest_mode(vcpu) && kvm_x86_ops.nested_ops->check_guest_maps)
+ kvm_x86_ops.nested_ops->check_guest_maps(vcpu);
+
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
/*
--
2.31.1
^ permalink raw reply related
* [PATCH v3 06/12] KVM: powerpc: Use Makefile.kvm for common files
From: David Woodhouse @ 2021-11-17 17:39 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
It's all fairly baroque but in the end, I don't think there's any reason
for $(KVM)/irqchip.o to have been handled differently, as they all end
up in $(kvm-y) in the end anyway, regardless of whether they get there
via $(common-objs-y) and the CPU-specific object lists.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/powerpc/kvm/Makefile | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 583c14ef596e..245f59118413 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -4,11 +4,8 @@
#
ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
-KVM := ../../../virt/kvm
-common-objs-y = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/binary_stats.o
-common-objs-$(CONFIG_KVM_VFIO) += $(KVM)/vfio.o
-common-objs-$(CONFIG_KVM_MMIO) += $(KVM)/coalesced_mmio.o
+include $(srctree)/virt/kvm/Makefile.kvm
common-objs-y += powerpc.o emulate_loadstore.o
obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o
@@ -125,7 +122,6 @@ kvm-book3s_32-objs := \
kvm-objs-$(CONFIG_KVM_BOOK3S_32) := $(kvm-book3s_32-objs)
kvm-objs-$(CONFIG_KVM_MPIC) += mpic.o
-kvm-objs-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o
kvm-objs := $(kvm-objs-m) $(kvm-objs-y)
--
2.31.1
^ permalink raw reply related
* [PATCH v3 02/12] KVM: Add Makefile.kvm for common files, use it for x86
From: David Woodhouse @ 2021-11-17 17:39 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Splitting kvm_main.c out into smaller and better-organized files is
slightly non-trivial when it involves editing a bunch of per-arch
KVM makefiles. Provide virt/kvm/Makefile.kvm for them to include.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/Makefile | 7 +------
virt/kvm/Makefile.kvm | 13 +++++++++++++
2 files changed, 14 insertions(+), 6 deletions(-)
create mode 100644 virt/kvm/Makefile.kvm
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 75dfd27b6e8a..30f244b64523 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -7,12 +7,7 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
OBJECT_FILES_NON_STANDARD_vmenter.o := y
endif
-KVM := ../../../virt/kvm
-
-kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
- $(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o \
- $(KVM)/dirty_ring.o $(KVM)/binary_stats.o
-kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
+include $(srctree)/virt/kvm/Makefile.kvm
kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
new file mode 100644
index 000000000000..ffdcad3cc97a
--- /dev/null
+++ b/virt/kvm/Makefile.kvm
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Kernel-based Virtual Machine module
+#
+
+KVM ?= ../../../virt/kvm
+
+kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.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
--
2.31.1
^ permalink raw reply related
* [PATCH v3 03/12] KVM: s390: Use Makefile.kvm for common files
From: David Woodhouse @ 2021-11-17 17:39 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
arch/s390/kvm/Makefile | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index b3aaadc60ead..e4f50453cf7f 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -3,13 +3,11 @@
#
# Copyright IBM Corp. 2008
-KVM := ../../../virt/kvm
-common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o \
- $(KVM)/irqchip.o $(KVM)/vfio.o $(KVM)/binary_stats.o
+include $(srctree)/virt/kvm/Makefile.kvm
ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
-kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o
+kvm-objs := kvm-s390.o intercept.o interrupt.o priv.o sigp.o
kvm-objs += diag.o gaccess.o guestdbg.o vsie.o pv.o
obj-$(CONFIG_KVM) += kvm.o
--
2.31.1
^ permalink raw reply related
* [PATCH v3 08/12] KVM: Propagate vcpu explicitly to mark_page_dirty_in_slot()
From: David Woodhouse @ 2021-11-17 17:39 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
The kvm_dirty_ring_get() function uses kvm_get_running_vcpu() to work out
which dirty ring to use, but there are some use cases where that doesn't
work.
There's one in setting the Xen shared info page, introduced in commit
629b5348841a ("KVM: x86/xen: update wallclock region") and reported by
"butt3rflyh4ck" <butterflyhuangxx@gmail.com> in
https://lore.kernel.org/kvm/CAFcO6XOmoS7EacN_n6v4Txk7xL7iqRa2gABg3F7E3Naf5uG94g@mail.gmail.com/
There's also about to be another one when the newly-reintroduced
gfn_to_pfn_cache needs to mark a page as dirty from the MMU notifier
which invalidates the mapping. In that case, we will *know* the vcpu
that can be 'blamed' for dirtying the page, and we just need to be
able to pass it in as an explicit argument when doing so.
This patch preemptively resolves the second issue, and paves the way
for resolving the first. A complete fix for the first issue will need
us to switch the Xen shinfo to be owned by a particular vCPU, which
will happen in a separate patch.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/arm64/kvm/mmu.c | 2 +-
arch/x86/kvm/mmu/mmu.c | 2 +-
arch/x86/kvm/mmu/spte.c | 2 +-
arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
arch/x86/kvm/x86.c | 4 ++--
include/linux/kvm_dirty_ring.h | 6 ++++--
include/linux/kvm_host.h | 3 ++-
virt/kvm/dirty_ring.c | 8 ++++++--
virt/kvm/kvm_main.c | 18 +++++++++---------
9 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 326cdfec74a1..d8411ce4db4b 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1143,7 +1143,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
/* Mark the page dirty only if the fault is handled successfully */
if (writable && !ret) {
kvm_set_pfn_dirty(pfn);
- mark_page_dirty_in_slot(kvm, memslot, gfn);
+ mark_page_dirty_in_slot(kvm, vcpu, memslot, gfn);
}
out_unlock:
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 3be9beea838d..cedeab55b0d8 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -3090,7 +3090,7 @@ fast_pf_fix_direct_spte(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault,
return false;
if (is_writable_pte(new_spte) && !is_writable_pte(old_spte))
- mark_page_dirty_in_slot(vcpu->kvm, fault->slot, fault->gfn);
+ mark_page_dirty_in_slot(vcpu->kvm, vcpu, fault->slot, fault->gfn);
return true;
}
diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c
index 0c76c45fdb68..0598515f3ae2 100644
--- a/arch/x86/kvm/mmu/spte.c
+++ b/arch/x86/kvm/mmu/spte.c
@@ -184,7 +184,7 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
if ((spte & PT_WRITABLE_MASK) && kvm_slot_dirty_track_enabled(slot)) {
/* Enforced by kvm_mmu_hugepage_adjust. */
WARN_ON(level > PG_LEVEL_4K);
- mark_page_dirty_in_slot(vcpu->kvm, slot, gfn);
+ mark_page_dirty_in_slot(vcpu->kvm, vcpu, slot, gfn);
}
*new_spte = spte;
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index a54c3491af42..c5669c9918a4 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -247,7 +247,7 @@ static void handle_changed_spte_dirty_log(struct kvm *kvm, int as_id, gfn_t gfn,
if ((!is_writable_pte(old_spte) || pfn_changed) &&
is_writable_pte(new_spte)) {
slot = __gfn_to_memslot(__kvm_memslots(kvm, as_id), gfn);
- mark_page_dirty_in_slot(kvm, slot, gfn);
+ mark_page_dirty_in_slot(kvm, NULL, slot, gfn);
}
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5a403d92833f..5af88f9e7fd1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3353,7 +3353,7 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
out:
user_access_end();
dirty:
- mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa));
+ mark_page_dirty_in_slot(vcpu->kvm, vcpu, ghc->memslot, gpa_to_gfn(ghc->gpa));
}
int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
@@ -4420,7 +4420,7 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
if (!copy_to_user_nofault(&st->preempted, &preempted, sizeof(preempted)))
vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED;
- mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa));
+ mark_page_dirty_in_slot(vcpu->kvm, vcpu, ghc->memslot, gpa_to_gfn(ghc->gpa));
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
diff --git a/include/linux/kvm_dirty_ring.h b/include/linux/kvm_dirty_ring.h
index 4da8d4a4140b..f3be974f9c5a 100644
--- a/include/linux/kvm_dirty_ring.h
+++ b/include/linux/kvm_dirty_ring.h
@@ -43,7 +43,8 @@ static inline int kvm_dirty_ring_alloc(struct kvm_dirty_ring *ring,
return 0;
}
-static inline struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm)
+static inline struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm,
+ struct kvm_vcpu *vcpu)
{
return NULL;
}
@@ -78,7 +79,8 @@ static inline bool kvm_dirty_ring_soft_full(struct kvm_dirty_ring *ring)
u32 kvm_dirty_ring_get_rsvd_entries(void);
int kvm_dirty_ring_alloc(struct kvm_dirty_ring *ring, int index, u32 size);
-struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm);
+struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm,
+ struct kvm_vcpu *vcpu);
/*
* called with kvm->slots_lock held, returns the number of
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c310648cc8f1..1628c32e4464 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -942,7 +942,8 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn);
bool kvm_vcpu_is_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
unsigned long kvm_host_page_size(struct kvm_vcpu *vcpu, gfn_t gfn);
-void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot, gfn_t gfn);
+void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_vcpu *vcpu,
+ struct kvm_memory_slot *memslot, gfn_t gfn);
void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
struct kvm_memslots *kvm_vcpu_memslots(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/dirty_ring.c b/virt/kvm/dirty_ring.c
index 88f4683198ea..61c94fc4d7f0 100644
--- a/virt/kvm/dirty_ring.c
+++ b/virt/kvm/dirty_ring.c
@@ -36,12 +36,16 @@ static bool kvm_dirty_ring_full(struct kvm_dirty_ring *ring)
return kvm_dirty_ring_used(ring) >= ring->size;
}
-struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm)
+struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm, struct kvm_vcpu *vcpu)
{
- struct kvm_vcpu *vcpu = kvm_get_running_vcpu();
+ struct kvm_vcpu *running_vcpu = kvm_get_running_vcpu();
+ WARN_ON_ONCE(vcpu && vcpu != running_vcpu);
WARN_ON_ONCE(vcpu->kvm != kvm);
+ if (!vcpu)
+ vcpu = running_vcpu;
+
return &vcpu->dirty_ring;
}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 356d636e037d..7137995cab41 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2781,7 +2781,7 @@ int kvm_vcpu_read_guest_atomic(struct kvm_vcpu *vcpu, gpa_t gpa,
}
EXPORT_SYMBOL_GPL(kvm_vcpu_read_guest_atomic);
-static int __kvm_write_guest_page(struct kvm *kvm,
+static int __kvm_write_guest_page(struct kvm *kvm, struct kvm_vcpu *vcpu,
struct kvm_memory_slot *memslot, gfn_t gfn,
const void *data, int offset, int len)
{
@@ -2794,7 +2794,7 @@ static int __kvm_write_guest_page(struct kvm *kvm,
r = __copy_to_user((void __user *)addr + offset, data, len);
if (r)
return -EFAULT;
- mark_page_dirty_in_slot(kvm, memslot, gfn);
+ mark_page_dirty_in_slot(kvm, vcpu, memslot, gfn);
return 0;
}
@@ -2803,7 +2803,7 @@ int kvm_write_guest_page(struct kvm *kvm, gfn_t gfn,
{
struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
- return __kvm_write_guest_page(kvm, slot, gfn, data, offset, len);
+ return __kvm_write_guest_page(kvm, NULL, slot, gfn, data, offset, len);
}
EXPORT_SYMBOL_GPL(kvm_write_guest_page);
@@ -2812,7 +2812,7 @@ int kvm_vcpu_write_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn,
{
struct kvm_memory_slot *slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
- return __kvm_write_guest_page(vcpu->kvm, slot, gfn, data, offset, len);
+ return __kvm_write_guest_page(vcpu->kvm, vcpu, slot, gfn, data, offset, len);
}
EXPORT_SYMBOL_GPL(kvm_vcpu_write_guest_page);
@@ -2931,7 +2931,7 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
r = __copy_to_user((void __user *)ghc->hva + offset, data, len);
if (r)
return -EFAULT;
- mark_page_dirty_in_slot(kvm, ghc->memslot, gpa >> PAGE_SHIFT);
+ mark_page_dirty_in_slot(kvm, NULL, ghc->memslot, gpa >> PAGE_SHIFT);
return 0;
}
@@ -3000,7 +3000,7 @@ int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len)
}
EXPORT_SYMBOL_GPL(kvm_clear_guest);
-void mark_page_dirty_in_slot(struct kvm *kvm,
+void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_vcpu *vcpu,
struct kvm_memory_slot *memslot,
gfn_t gfn)
{
@@ -3009,7 +3009,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm,
u32 slot = (memslot->as_id << 16) | memslot->id;
if (kvm->dirty_ring_size)
- kvm_dirty_ring_push(kvm_dirty_ring_get(kvm),
+ kvm_dirty_ring_push(kvm_dirty_ring_get(kvm, vcpu),
slot, rel_gfn);
else
set_bit_le(rel_gfn, memslot->dirty_bitmap);
@@ -3022,7 +3022,7 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
struct kvm_memory_slot *memslot;
memslot = gfn_to_memslot(kvm, gfn);
- mark_page_dirty_in_slot(kvm, memslot, gfn);
+ mark_page_dirty_in_slot(kvm, NULL, memslot, gfn);
}
EXPORT_SYMBOL_GPL(mark_page_dirty);
@@ -3031,7 +3031,7 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn)
struct kvm_memory_slot *memslot;
memslot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
- mark_page_dirty_in_slot(vcpu->kvm, memslot, gfn);
+ mark_page_dirty_in_slot(vcpu->kvm, vcpu, memslot, gfn);
}
EXPORT_SYMBOL_GPL(kvm_vcpu_mark_page_dirty);
--
2.31.1
^ permalink raw reply related
* [PATCH v3 04/12] KVM: mips: Use Makefile.kvm for common files
From: David Woodhouse @ 2021-11-17 17:39 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/mips/kvm/Makefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/mips/kvm/Makefile b/arch/mips/kvm/Makefile
index d3710959da55..21ff75bcdbc4 100644
--- a/arch/mips/kvm/Makefile
+++ b/arch/mips/kvm/Makefile
@@ -2,9 +2,10 @@
# Makefile for KVM support for MIPS
#
+include $(srctree)/virt/kvm/Makefile.kvm
+
ccflags-y += -Ivirt/kvm -Iarch/mips/kvm
-kvm-y := $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o eventfd.o binary_stats.o)
kvm-$(CONFIG_CPU_HAS_MSA) += msa.o
kvm-y += mips.o emulate.o entry.o \
--
2.31.1
^ permalink raw reply related
* [PATCH v3 07/12] KVM: arm64: Use Makefile.kvm for common files
From: David Woodhouse @ 2021-11-17 17:39 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/arm64/kvm/Makefile | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 989bb5dad2c8..04a53f71a6b6 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -5,14 +5,12 @@
ccflags-y += -I $(srctree)/$(src)
-KVM=../../../virt/kvm
+include $(srctree)/virt/kvm/Makefile.kvm
obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_KVM) += hyp/
-kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
- $(KVM)/vfio.o $(KVM)/irqchip.o $(KVM)/binary_stats.o \
- arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
+kvm-y += arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
inject_fault.o va_layout.o handle_exit.o \
guest.o debug.o reset.o sys_regs.o \
vgic-sys-reg-v3.o fpsimd.o pmu.o \
--
2.31.1
^ permalink raw reply related
* [PATCH v3 00/12] KVM: x86/xen: Add in-kernel Xen event channel delivery
From: David Woodhouse @ 2021-11-17 17:39 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
Event channels, yeah. That really is where I started.
It was all so simple in Joao and Ankur's original version at
https://www.spinics.net/lists/kvm/msg182556.html — just a handful
of simple test_and_set_bit() calls on the mapped page.
When I posted v1 I didn't quite understand how steal time and nesting
were safely using the kvm_map_gfn() function, and I posted the Xen
part declaring that I had "reduced it to a previously solved problem".
Then I frowned at kvm_map_gfn() for a bit longer, concluded it was
basically impossible to use it safely on its own because the page it
maps might belong to another guest by the time it even returns to its
caller, and posted a v2 in which I did something safer for myself by
hooking into the MMU notifiers.
I then fixed the steal time reporting, and killed gfn_to_pfn_cache,
under separate cover.
In v3 of this series I re-introduce a saner gfn_to_pfn_cache with MMU
notifier support to give it proper invalidation semantics. This can now
be used for the Xen event channel support and should also be usable for
fixing the various use-after-free races in the nesting code too — the
last patch in this series being an untested proof of concept attempt at
fixing one such.
Since adding a C file in virt/kvm/ was somewhat more painful than it
really should have been, there is a small detour into all the arch
specific Makefiles to make them include a common one.
Intended for merging up to patch 11. Patch 12 is for illustration.
David Woodhouse (12):
KVM: Introduce CONFIG_HAVE_KVM_DIRTY_RING
KVM: Add Makefile.kvm for common files, use it for x86
KVM: s390: Use Makefile.kvm for common files
KVM: mips: Use Makefile.kvm for common files
KVM: RISC-V: Use Makefile.kvm for common files
KVM: powerpc: Use Makefile.kvm for common files
KVM: arm64: Use Makefile.kvm for common files
KVM: Propagate vcpu explicitly to mark_page_dirty_in_slot()
KVM: Reinstate gfn_to_pfn_cache with invalidation support
KVM: x86/xen: Maintain valid mapping of Xen shared_info page
KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery
KVM: x86: First attempt at converting nested virtual APIC page to gpc
Documentation/virt/kvm/api.rst | 21 ++
arch/arm64/kvm/Makefile | 6 +-
arch/arm64/kvm/mmu.c | 2 +-
arch/mips/kvm/Makefile | 3 +-
arch/powerpc/kvm/Makefile | 6 +-
arch/riscv/kvm/Makefile | 6 +-
arch/s390/kvm/Makefile | 6 +-
arch/x86/include/asm/kvm_host.h | 4 +-
arch/x86/kvm/Kconfig | 2 +
arch/x86/kvm/Makefile | 7 +-
arch/x86/kvm/irq_comm.c | 12 +
arch/x86/kvm/mmu/mmu.c | 2 +-
arch/x86/kvm/mmu/spte.c | 2 +-
arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
arch/x86/kvm/vmx/nested.c | 50 +++-
arch/x86/kvm/vmx/vmx.c | 12 +-
arch/x86/kvm/vmx/vmx.h | 2 +-
arch/x86/kvm/x86.c | 17 +-
arch/x86/kvm/xen.c | 287 +++++++++++++++++++--
arch/x86/kvm/xen.h | 9 +
include/linux/kvm_dirty_ring.h | 14 +-
include/linux/kvm_host.h | 100 ++++++-
include/linux/kvm_types.h | 18 ++
include/uapi/linux/kvm.h | 11 +
.../testing/selftests/kvm/x86_64/xen_shinfo_test.c | 112 +++++++-
virt/kvm/Kconfig | 6 +
virt/kvm/Makefile.kvm | 14 +
virt/kvm/dirty_ring.c | 10 +-
virt/kvm/kvm_main.c | 34 ++-
virt/kvm/{mmu_lock.h => kvm_mm.h} | 23 +-
virt/kvm/pfncache.c | 281 ++++++++++++++++++++
31 files changed, 992 insertions(+), 89 deletions(-)
^ permalink raw reply
* [PATCH v3 09/12] KVM: Reinstate gfn_to_pfn_cache with invalidation support
From: David Woodhouse @ 2021-11-17 17:40 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
This can be used in two modes. There is an atomic mode where the cached
mapping is accessed while holding the rwlock, and a mode where the
physical address is used by a vCPU in guest mode.
For the latter case, an invalidation will wake the vCPU with the new
KVM_REQ_GPC_INVALIDATE, and the architecture will need to refresh any
caches it still needs to access before entering guest mode again.
Only one vCPU can be targeted by the wake requests; it's simple enough
to make it wake all vCPUs or even a mask but I don't see a use case for
that additional complexity right now.
Invalidation happens from the invalidate_range_start MMU notifier, which
needs to be able to sleep in order to wake the vCPU and wait for it.
This means that revalidation potentially needs to "wait" for the MMU
operation to complete and the invalidate_range_end notifier to be
invoked. Like the vCPU when it takes a page fault in that period, we
just spin — fixing that in a future patch by implementing an actual
*wait* may be another part of shaving this particularly hirsute yak.
As noted in the comments in the function itself, the only case where
the invalidate_range_start notifier is expected to be called *without*
being able to sleep is when the OOM reaper is killing the process. In
that case, we expect the vCPU threads already to have exited, and thus
there will be nothing to wake, and no reason to wait. So we clear the
KVM_REQUEST_WAIT bit and send the request anyway, then complain loudly
if there actually *was* anything to wake up.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kvm/Kconfig | 1 +
include/linux/kvm_host.h | 90 ++++++++++
include/linux/kvm_types.h | 18 ++
virt/kvm/Kconfig | 3 +
virt/kvm/Makefile.kvm | 1 +
virt/kvm/dirty_ring.c | 2 +-
virt/kvm/kvm_main.c | 12 +-
virt/kvm/{mmu_lock.h => kvm_mm.h} | 23 ++-
virt/kvm/pfncache.c | 281 ++++++++++++++++++++++++++++++
9 files changed, 424 insertions(+), 7 deletions(-)
rename virt/kvm/{mmu_lock.h => kvm_mm.h} (55%)
create mode 100644 virt/kvm/pfncache.c
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index d7fa0a42ac25..af351107d47f 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -26,6 +26,7 @@ config KVM
select PREEMPT_NOTIFIERS
select MMU_NOTIFIER
select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_PFNCACHE
select HAVE_KVM_IRQFD
select HAVE_KVM_DIRTY_RING
select IRQ_BYPASS_MANAGER
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 1628c32e4464..c35e207c2c1f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -151,6 +151,7 @@ static inline bool is_error_page(struct page *page)
#define KVM_REQ_UNBLOCK 2
#define KVM_REQ_UNHALT 3
#define KVM_REQ_VM_DEAD (4 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
+#define KVM_REQ_GPC_INVALIDATE (5 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
#define KVM_REQUEST_ARCH_BASE 8
#define KVM_ARCH_REQ_FLAGS(nr, flags) ({ \
@@ -559,6 +560,10 @@ struct kvm {
unsigned long mn_active_invalidate_count;
struct rcuwait mn_memslots_update_rcuwait;
+ /* For management / invalidation of gfn_to_pfn_caches */
+ spinlock_t gpc_lock;
+ struct list_head gpc_list;
+
/*
* created_vcpus is protected by kvm->lock, and is incremented
* at the beginning of KVM_CREATE_VCPU. online_vcpus is only
@@ -967,6 +972,91 @@ int kvm_vcpu_write_guest(struct kvm_vcpu *vcpu, gpa_t gpa, const void *data,
unsigned long len);
void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn);
+/**
+ * kvm_gfn_to_pfn_cache_init - prepare a cached kernel mapping and HPA for a
+ * given guest physical address.
+ *
+ * @kvm: pointer to kvm instance.
+ * @gpc: struct gfn_to_pfn_cache object.
+ * @vcpu: vCPU to be used for marking pages dirty and to be woken on
+ * invalidation.
+ * @guest_uses_pa: indicates that the resulting host physical PFN is used while
+ * @vcpu is IN_GUEST_MODE so invalidations should wake it.
+ * @kernel_map: requests a kernel virtual mapping (kmap / memremap).
+ * @gpa: guest physical address to map.
+ * @len: sanity check; the range being access must fit a single page.
+ * @dirty: mark the cache dirty immediately.
+ *
+ * @return: 0 for success.
+ * -EINVAL for a mapping which would cross a page boundary.
+ * -EFAULT for an untranslatable guest physical address.
+ *
+ * This primes a gfn_to_pfn_cache and links it into the @kvm's list for
+ * invalidations to be processed. Invalidation callbacks to @vcpu using
+ * %KVM_REQ_GPC_INVALIDATE will occur only for MMU notifiers, not for KVM
+ * memslot changes. Callers are required to use kvm_gfn_to_pfn_cache_check()
+ * to ensure that the cache is valid before accessing the target page.
+ */
+int kvm_gfn_to_pfn_cache_init(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ struct kvm_vcpu *vcpu, bool guest_uses_pa,
+ bool kernel_map, gpa_t gpa, unsigned long len,
+ bool dirty);
+
+/**
+ * kvm_gfn_to_pfn_cache_check - check validity of a gfn_to_pfn_cache.
+ *
+ * @kvm: pointer to kvm instance.
+ * @gpc: struct gfn_to_pfn_cache object.
+ * @gpa: current guest physical address to map.
+ * @len: sanity check; the range being access must fit a single page.
+ * @dirty: mark the cache dirty immediately.
+ *
+ * @return: %true if the cache is still valid and the address matches.
+ * %false if the cache is not valid.
+ *
+ * Callers outside IN_GUEST_MODE context should hold a read lock on @gpc->lock
+ * while calling this function, and then continue to hold the lock until the
+ * access is complete.
+ *
+ * Callers in IN_GUEST_MODE may do so without locking, although they should
+ * still hold a read lock on kvm->scru for the memslot checks.
+ */
+bool kvm_gfn_to_pfn_cache_check(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ gpa_t gpa, unsigned long len);
+
+/**
+ * kvm_gfn_to_pfn_cache_refresh - update a previously initialized cache.
+ *
+ * @kvm: pointer to kvm instance.
+ * @gpc: struct gfn_to_pfn_cache object.
+ * @gpa: updated guest physical address to map.
+ * @len: sanity check; the range being access must fit a single page.
+ * @dirty: mark the cache dirty immediately.
+ *
+ * @return: 0 for success.
+ * -EINVAL for a mapping which would cross a page boundary.
+ * -EFAULT for an untranslatable guest physical address.
+ *
+ * This will attempt to refresh a gfn_to_pfn_cache. Note that a successful
+ * returm from this function does not mean the page can be immediately
+ * accessed because it may have raced with an invalidation. Callers must
+ * still lock and check the cache status, as this function does not return
+ * with the lock still held to permit access.
+ */
+int kvm_gfn_to_pfn_cache_refresh(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ gpa_t gpa, unsigned long len, bool dirty);
+
+/**
+ * kvm_gfn_to_pfn_cache_check - destroy and unlink a gfn_to_pfn_cache.
+ *
+ * @kvm: pointer to kvm instance.
+ * @gpc: struct gfn_to_pfn_cache object.
+ *
+ * This removes a cache from the @kvm's list to be processed on MMU notifier
+ * invocation.
+ */
+void kvm_gfn_to_pfn_cache_destroy(struct kvm *kvm, struct gfn_to_pfn_cache *gpc);
+
void kvm_sigset_activate(struct kvm_vcpu *vcpu);
void kvm_sigset_deactivate(struct kvm_vcpu *vcpu);
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index 234eab059839..22a52ef12b4d 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -19,6 +19,7 @@ struct kvm_memslots;
enum kvm_mr_change;
#include <linux/types.h>
+#include <linux/spinlock_types.h>
#include <asm/kvm_types.h>
@@ -53,6 +54,23 @@ struct gfn_to_hva_cache {
struct kvm_memory_slot *memslot;
};
+struct gfn_to_pfn_cache {
+ u64 generation;
+ gpa_t gpa;
+ unsigned long uhva;
+ struct kvm_memory_slot *memslot;
+ struct kvm_vcpu *vcpu;
+ struct list_head list;
+ rwlock_t lock;
+ void *khva;
+ kvm_pfn_t pfn;
+ bool active;
+ bool valid;
+ bool dirty;
+ bool kernel_map;
+ bool guest_uses_pa;
+};
+
#ifdef KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE
/*
* Memory caches are used to preallocate memory ahead of various MMU flows,
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index 97cf5413ac25..f4834c20e4a6 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -4,6 +4,9 @@
config HAVE_KVM
bool
+config HAVE_KVM_PFNCACHE
+ bool
+
config HAVE_KVM_IRQCHIP
bool
diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
index ffdcad3cc97a..2c27d5d0c367 100644
--- a/virt/kvm/Makefile.kvm
+++ b/virt/kvm/Makefile.kvm
@@ -11,3 +11,4 @@ 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
+kvm-$(CONFIG_HAVE_KVM_PFNCACHE) += $(KVM)/pfncache.o
diff --git a/virt/kvm/dirty_ring.c b/virt/kvm/dirty_ring.c
index 61c94fc4d7f0..879d454eef71 100644
--- a/virt/kvm/dirty_ring.c
+++ b/virt/kvm/dirty_ring.c
@@ -9,7 +9,7 @@
#include <linux/vmalloc.h>
#include <linux/kvm_dirty_ring.h>
#include <trace/events/kvm.h>
-#include "mmu_lock.h"
+#include "kvm_mm.h"
int __weak kvm_cpu_dirty_log_size(void)
{
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 7137995cab41..24f300e5fa96 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -59,7 +59,7 @@
#include "coalesced_mmio.h"
#include "async_pf.h"
-#include "mmu_lock.h"
+#include "kvm_mm.h"
#include "vfio.h"
#define CREATE_TRACE_POINTS
@@ -684,6 +684,9 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
kvm->mn_active_invalidate_count++;
spin_unlock(&kvm->mn_invalidate_lock);
+ gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end,
+ hva_range.may_block);
+
__kvm_handle_hva_range(kvm, &hva_range);
return 0;
@@ -1051,6 +1054,9 @@ static struct kvm *kvm_create_vm(unsigned long type)
spin_lock_init(&kvm->mn_invalidate_lock);
rcuwait_init(&kvm->mn_memslots_update_rcuwait);
+ INIT_LIST_HEAD(&kvm->gpc_list);
+ spin_lock_init(&kvm->gpc_lock);
+
INIT_LIST_HEAD(&kvm->devices);
BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX);
@@ -2390,8 +2396,8 @@ static int hva_to_pfn_remapped(struct vm_area_struct *vma,
* 2): @write_fault = false && @writable, @writable will tell the caller
* whether the mapping is writable.
*/
-static kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async,
- bool write_fault, bool *writable)
+kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async,
+ bool write_fault, bool *writable)
{
struct vm_area_struct *vma;
kvm_pfn_t pfn = 0;
diff --git a/virt/kvm/mmu_lock.h b/virt/kvm/kvm_mm.h
similarity index 55%
rename from virt/kvm/mmu_lock.h
rename to virt/kvm/kvm_mm.h
index 9e1308f9734c..b976e4b07e88 100644
--- a/virt/kvm/mmu_lock.h
+++ b/virt/kvm/kvm_mm.h
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
-#ifndef KVM_MMU_LOCK_H
-#define KVM_MMU_LOCK_H 1
+#ifndef __KVM_MM_H__
+#define __KVM_MM_H__ 1
/*
* Architectures can choose whether to use an rwlock or spinlock
@@ -20,4 +20,21 @@
#define KVM_MMU_UNLOCK(kvm) spin_unlock(&(kvm)->mmu_lock)
#endif /* KVM_HAVE_MMU_RWLOCK */
-#endif
+kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async,
+ bool write_fault, bool *writable);
+
+#ifdef CONFIG_HAVE_KVM_PFNCACHE
+void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm,
+ unsigned long start,
+ unsigned long end,
+ bool may_block);
+#else
+static inline void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm,
+ unsigned long start,
+ unsigned long end,
+ bool may_block)
+{
+}
+#endif /* HAVE_KVM_PFNCACHE */
+
+#endif /* __KVM_MM_H__ */
diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c
new file mode 100644
index 000000000000..06a6bb6c74ef
--- /dev/null
+++ b/virt/kvm/pfncache.c
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables kernel and guest-mode vCPU access to guest physical
+ * memory with suitable invalidation mechanisms.
+ *
+ * Copyright © 2021 Amazon.com, Inc. or its affiliates.
+ *
+ * Authors:
+ * David Woodhouse <dwmw2@infradead.org>
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include "kvm_mm.h"
+
+/*
+ * MMU notifier 'invalidate_range_start' hook.
+ */
+void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start,
+ unsigned long end, bool may_block)
+{
+ DECLARE_BITMAP(vcpu_bitmap, KVM_MAX_VCPUS);
+ struct gfn_to_pfn_cache *gpc;
+ bool wake_vcpus = false;
+
+ spin_lock(&kvm->gpc_lock);
+ list_for_each_entry(gpc, &kvm->gpc_list, list) {
+ write_lock_irq(&gpc->lock);
+
+ /* Only a single page so no need to care about length */
+ if (gpc->valid && !is_error_noslot_pfn(gpc->pfn) &&
+ gpc->uhva >= start && gpc->uhva < end) {
+ gpc->valid = false;
+
+ if (gpc->dirty) {
+ int idx = srcu_read_lock(&kvm->srcu);
+ if (gpc->vcpu)
+ kvm_vcpu_mark_page_dirty(gpc->vcpu, gpa_to_gfn(gpc->gpa));
+ else
+ mark_page_dirty(kvm, gpa_to_gfn(gpc->gpa));
+ srcu_read_unlock(&kvm->srcu, idx);
+
+ kvm_set_pfn_dirty(gpc->pfn);
+ gpc->dirty = false;
+ }
+
+ /*
+ * If a guest vCPU could be using the physical address,
+ * it needs to be woken.
+ */
+ if (gpc->guest_uses_pa) {
+ if (!wake_vcpus) {
+ wake_vcpus = true;
+ bitmap_zero(vcpu_bitmap, KVM_MAX_VCPUS);
+ }
+ __set_bit(gpc->vcpu->vcpu_idx, vcpu_bitmap);
+ }
+ }
+ write_unlock_irq(&gpc->lock);
+ }
+ spin_unlock(&kvm->gpc_lock);
+
+ if (wake_vcpus) {
+ unsigned int req = KVM_REQ_GPC_INVALIDATE;
+ bool called;
+
+ /*
+ * If the OOM reaper is active, then all vCPUs should have
+ * been stopped already, so perform the request without
+ * KVM_REQUEST_WAIT and be sad if any needed to be woken.
+ */
+ if (!may_block)
+ req &= ~KVM_REQUEST_WAIT;
+
+ called = kvm_make_vcpus_request_mask(kvm, req, vcpu_bitmap);
+
+ WARN_ON_ONCE(called && !may_block);
+ }
+}
+
+bool kvm_gfn_to_pfn_cache_check(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ gpa_t gpa, unsigned long len)
+{
+ struct kvm_memslots *slots = kvm_memslots(kvm);
+
+ if ((gpa & ~PAGE_MASK) + len > PAGE_SIZE)
+ return false;
+
+ if (gpc->gpa != gpa || gpc->generation != slots->generation ||
+ kvm_is_error_hva(gpc->uhva))
+ return false;
+
+ if (!gpc->valid)
+ return false;
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(kvm_gfn_to_pfn_cache_check);
+
+int kvm_gfn_to_pfn_cache_refresh(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ gpa_t gpa, unsigned long len, bool dirty)
+{
+ struct kvm_memslots *slots = kvm_memslots(kvm);
+ unsigned long page_offset = gpa & ~PAGE_MASK;
+ kvm_pfn_t old_pfn, new_pfn;
+ unsigned long old_uhva;
+ gpa_t old_gpa;
+ void *old_khva;
+ bool old_valid, old_dirty;
+ int ret = 0;
+
+ /*
+ * If must fit within a single page. The 'len' argument is
+ * only to enforce that.
+ */
+ if (page_offset + len > PAGE_SIZE)
+ return -EINVAL;
+
+ write_lock_irq(&gpc->lock);
+
+ old_gpa = gpc->gpa;
+ old_pfn = gpc->pfn;
+ old_khva = gpc->khva;
+ old_uhva = gpc->uhva;
+ old_valid = gpc->valid;
+ old_dirty = gpc->dirty;
+
+ /* If the userspace HVA is invalid, refresh that first */
+ if (gpc->gpa != gpa || gpc->generation != slots->generation ||
+ kvm_is_error_hva(gpc->uhva)) {
+ gfn_t gfn = gpa_to_gfn(gpa);
+
+ gpc->dirty = false;
+ gpc->gpa = gpa;
+ gpc->generation = slots->generation;
+ gpc->memslot = __gfn_to_memslot(slots, gfn);
+ gpc->uhva = gfn_to_hva_memslot(gpc->memslot, gfn);
+
+ if (kvm_is_error_hva(gpc->uhva)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ gpc->uhva += page_offset;
+ }
+
+ /*
+ * If the userspace HVA changed or the PFN was already invalid,
+ * drop the lock and do the HVA to PFN lookup again.
+ */
+ if (!old_valid || old_uhva != gpc->uhva) {
+ unsigned long uhva = gpc->uhva;
+ void *new_khva = NULL;
+ unsigned long mmu_seq;
+ int retry;
+
+ /* Placeholders for "hva is valid but not yet mapped" */
+ gpc->pfn = KVM_PFN_ERR_FAULT;
+ gpc->khva = NULL;
+ gpc->valid = true;
+
+ write_unlock_irq(&gpc->lock);
+
+ retry_map:
+ mmu_seq = kvm->mmu_notifier_seq;
+ smp_rmb();
+
+ /* We always request a writeable mapping */
+ new_pfn = hva_to_pfn(uhva, false, NULL, true, NULL);
+ if (is_error_noslot_pfn(new_pfn)) {
+ ret = -EFAULT;
+ goto map_done;
+ }
+
+ read_lock(&kvm->mmu_lock);
+ retry = mmu_notifier_retry_hva(kvm, mmu_seq, uhva);
+ read_unlock(&kvm->mmu_lock);
+ if (retry) {
+ cond_resched();
+ goto retry_map;
+ }
+
+ if (gpc->kernel_map) {
+ if (new_pfn == old_pfn) {
+ new_khva = (void *)((unsigned long)old_khva - page_offset);
+ old_pfn = KVM_PFN_ERR_FAULT;
+ old_khva = NULL;
+ } else if (pfn_valid(new_pfn)) {
+ new_khva = kmap(pfn_to_page(new_pfn));
+#ifdef CONFIG_HAS_IOMEM
+ } else {
+ new_khva = memremap(pfn_to_hpa(new_pfn), PAGE_SIZE, MEMREMAP_WB);
+#endif
+ }
+ if (!new_khva)
+ ret = -EFAULT;
+ }
+
+ map_done:
+ write_lock_irq(&gpc->lock);
+ if (ret) {
+ gpc->valid = false;
+ gpc->pfn = KVM_PFN_ERR_FAULT;
+ gpc->khva = NULL;
+ } else {
+ /* At this point, gpc->valid may already have been cleared */
+ gpc->pfn = new_pfn;
+ gpc->khva = new_khva + page_offset;
+ }
+ }
+
+ out:
+ if (ret)
+ gpc->dirty = false;
+ else
+ gpc->dirty = dirty;
+
+ write_unlock_irq(&gpc->lock);
+
+ /* Unmap the old page if it was mapped before */
+ if (!is_error_noslot_pfn(old_pfn)) {
+ if (pfn_valid(old_pfn)) {
+ kunmap(pfn_to_page(old_pfn));
+#ifdef CONFIG_HAS_IOMEM
+ } else {
+ memunmap(old_khva);
+#endif
+ }
+ kvm_release_pfn(old_pfn, old_dirty);
+ if (old_dirty)
+ mark_page_dirty(kvm, old_gpa);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(kvm_gfn_to_pfn_cache_refresh);
+
+int kvm_gfn_to_pfn_cache_init(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ struct kvm_vcpu *vcpu, bool guest_uses_pa,
+ bool kernel_map, gpa_t gpa, unsigned long len,
+ bool dirty)
+{
+ if (!gpc->active) {
+ rwlock_init(&gpc->lock);
+
+ gpc->khva = NULL;
+ gpc->pfn = KVM_PFN_ERR_FAULT;
+ gpc->uhva = KVM_HVA_ERR_BAD;
+ gpc->vcpu = vcpu;
+ gpc->kernel_map = kernel_map;
+ gpc->guest_uses_pa = guest_uses_pa;
+ gpc->valid = false;
+ gpc->active = true;
+
+ spin_lock(&kvm->gpc_lock);
+ list_add(&gpc->list, &kvm->gpc_list);
+ spin_unlock(&kvm->gpc_lock);
+ }
+ return kvm_gfn_to_pfn_cache_refresh(kvm, gpc, gpa, len, dirty);
+}
+EXPORT_SYMBOL_GPL(kvm_gfn_to_pfn_cache_init);
+
+void kvm_gfn_to_pfn_cache_destroy(struct kvm *kvm, struct gfn_to_pfn_cache *gpc)
+{
+ if (gpc->active) {
+ spin_lock(&kvm->gpc_lock);
+ list_del(&gpc->list);
+ spin_unlock(&kvm->gpc_lock);
+
+ /* In failing, it will tear down any existing mapping */
+ (void)kvm_gfn_to_pfn_cache_refresh(kvm, gpc, GPA_INVALID, 0, false);
+ gpc->active = false;
+ }
+}
+EXPORT_SYMBOL_GPL(kvm_gfn_to_pfn_cache_destroy);
--
2.31.1
^ permalink raw reply related
* [PATCH v3 11/12] KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery
From: David Woodhouse @ 2021-11-17 17:40 UTC (permalink / raw)
To: Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
This adds basic support for delivering 2 level event channels to a guest.
Initially, it only supports delivery via the IRQ routing table, triggered
by an eventfd. In order to do so, it has a kvm_xen_set_evtchn_fast()
function which will use the pre-mapped shared_info page if it already
exists and is still valid, while the slow path through the irqfd_inject
workqueue will remap the shared_info page if necessary.
It sets the bits in the shared_info page but not the vcpu_info; that is
deferred to __kvm_xen_has_interrupt() which raises the vector to the
appropriate vCPU.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
Documentation/virt/kvm/api.rst | 21 ++
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/irq_comm.c | 12 +
arch/x86/kvm/x86.c | 3 +-
arch/x86/kvm/xen.c | 262 +++++++++++++++++-
arch/x86/kvm/xen.h | 9 +
include/linux/kvm_host.h | 7 +
include/uapi/linux/kvm.h | 11 +
.../selftests/kvm/x86_64/xen_shinfo_test.c | 112 +++++++-
9 files changed, 431 insertions(+), 7 deletions(-)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index aeeb071c7688..2a24098f9f95 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -1796,6 +1796,7 @@ No flags are specified so far, the corresponding field must be set to zero.
struct kvm_irq_routing_msi msi;
struct kvm_irq_routing_s390_adapter adapter;
struct kvm_irq_routing_hv_sint hv_sint;
+ struct kvm_irq_routing_xen_evtchn xen_evtchn;
__u32 pad[8];
} u;
};
@@ -1805,6 +1806,7 @@ No flags are specified so far, the corresponding field must be set to zero.
#define KVM_IRQ_ROUTING_MSI 2
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
#define KVM_IRQ_ROUTING_HV_SINT 4
+ #define KVM_IRQ_ROUTING_XEN_EVTCHN 5
flags:
@@ -1856,6 +1858,20 @@ address_hi must be zero.
__u32 sint;
};
+ struct kvm_irq_routing_xen_evtchn {
+ __u32 port;
+ __u32 vcpu;
+ __u32 priority;
+ };
+
+
+When KVM_CAP_XEN_HVM includes the KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL bit
+in its indication of supported features, routing to Xen event channels
+is supported. Although the priority field is present, only the value
+KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL is supported, which means delivery by
+2 level event channels. FIFO event channel support may be added in
+the future.
+
4.55 KVM_SET_TSC_KHZ
--------------------
@@ -7401,6 +7417,7 @@ PVHVM guests. Valid flags are::
#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1)
#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2)
#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 2)
+ #define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 3)
The KVM_XEN_HVM_CONFIG_HYPERCALL_MSR flag indicates that the KVM_XEN_HVM_CONFIG
ioctl is available, for the guest to set its hypercall page.
@@ -7420,6 +7437,10 @@ The KVM_XEN_HVM_CONFIG_RUNSTATE flag indicates that the runstate-related
features KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR/_CURRENT/_DATA/_ADJUST are
supported by the KVM_XEN_VCPU_SET_ATTR/KVM_XEN_VCPU_GET_ATTR ioctls.
+The KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL flag indicates that IRQ routing entries
+of the type KVM_IRQ_ROUTING_XEN_EVTCHN are supported, with the priority
+field set to indicate 2 level event channel delivery.
+
8.31 KVM_CAP_PPC_MULTITCE
-------------------------
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4b2b4ecf3b46..6ea2446ab851 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -604,6 +604,7 @@ struct kvm_vcpu_xen {
u64 last_steal;
u64 runstate_entry_time;
u64 runstate_times[4];
+ unsigned long evtchn_pending_sel;
};
struct kvm_vcpu_arch {
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index d5b72a08e566..afd2de84be60 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -24,6 +24,7 @@
#include "hyperv.h"
#include "x86.h"
+#include "xen.h"
static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int irq_source_id, int level,
@@ -175,6 +176,13 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
return r;
break;
+#ifdef CONFIG_KVM_XEN
+ case KVM_IRQ_ROUTING_XEN_EVTCHN:
+ if (!level)
+ return -1;
+
+ return kvm_xen_set_evtchn_fast(e, kvm);
+#endif
default:
break;
}
@@ -310,6 +318,10 @@ int kvm_set_routing_entry(struct kvm *kvm,
e->hv_sint.vcpu = ue->u.hv_sint.vcpu;
e->hv_sint.sint = ue->u.hv_sint.sint;
break;
+#ifdef CONFIG_KVM_XEN
+ case KVM_IRQ_ROUTING_XEN_EVTCHN:
+ return kvm_xen_setup_evtchn(kvm, e, ue);
+#endif
default:
return -EINVAL;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5af88f9e7fd1..6f7669c94c79 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4147,7 +4147,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_XEN_HVM:
r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL |
- KVM_XEN_HVM_CONFIG_SHARED_INFO;
+ KVM_XEN_HVM_CONFIG_SHARED_INFO |
+ KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL;
if (sched_info_on())
r |= KVM_XEN_HVM_CONFIG_RUNSTATE;
break;
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 32a915a4fe20..6fdb7afa8344 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -16,6 +16,7 @@
#include <trace/events/kvm.h>
#include <xen/interface/xen.h>
#include <xen/interface/vcpu.h>
+#include <xen/interface/event_channel.h>
#include "trace.h"
@@ -195,6 +196,8 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
{
+ unsigned long evtchn_pending_sel = READ_ONCE(v->arch.xen.evtchn_pending_sel);
+ bool atomic = in_atomic() || !task_is_running(current);
int err;
u8 rc = 0;
@@ -204,6 +207,9 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
*/
struct gfn_to_hva_cache *ghc = &v->arch.xen.vcpu_info_cache;
struct kvm_memslots *slots = kvm_memslots(v->kvm);
+ bool ghc_valid = slots->generation == ghc->generation &&
+ !kvm_is_error_hva(ghc->hva) && ghc->memslot;
+
unsigned int offset = offsetof(struct vcpu_info, evtchn_upcall_pending);
/* No need for compat handling here */
@@ -219,8 +225,7 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
* cache in kvm_read_guest_offset_cached(), but just uses
* __get_user() instead. And falls back to the slow path.
*/
- if (likely(slots->generation == ghc->generation &&
- !kvm_is_error_hva(ghc->hva) && ghc->memslot)) {
+ if (!evtchn_pending_sel && ghc_valid) {
/* Fast path */
pagefault_disable();
err = __get_user(rc, (u8 __user *)ghc->hva + offset);
@@ -239,11 +244,82 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
* and we'll end up getting called again from a context where we *can*
* fault in the page and wait for it.
*/
- if (in_atomic() || !task_is_running(current))
+ if (atomic)
return 1;
- kvm_read_guest_offset_cached(v->kvm, ghc, &rc, offset,
- sizeof(rc));
+ if (!ghc_valid) {
+ err = kvm_gfn_to_hva_cache_init(v->kvm, ghc, ghc->gpa, ghc->len);
+ if (err || !ghc->memslot) {
+ /*
+ * If this failed, userspace has screwed up the
+ * vcpu_info mapping. No interrupts for you.
+ */
+ return 0;
+ }
+ }
+
+ /*
+ * Now we have a valid (protected by srcu) userspace HVA in
+ * ghc->hva which points to the struct vcpu_info. If there
+ * are any bits in the in-kernel evtchn_pending_sel then
+ * we need to write those to the guest vcpu_info and set
+ * its evtchn_upcall_pending flag. If there aren't any bits
+ * to add, we only want to *check* evtchn_upcall_pending.
+ */
+ if (evtchn_pending_sel) {
+ bool long_mode = v->kvm->arch.xen.long_mode;
+
+ if (!user_access_begin((void *)ghc->hva, sizeof(struct vcpu_info)))
+ return 0;
+
+ if (IS_ENABLED(CONFIG_64BIT) && long_mode) {
+ struct vcpu_info __user *vi = (void *)ghc->hva;
+
+ /* Attempt to set the evtchn_pending_sel bits in the
+ * guest, and if that succeeds then clear the same
+ * bits in the in-kernel version. */
+ asm volatile("1:\t" LOCK_PREFIX "orq %0, %1\n"
+ "\tnotq %0\n"
+ "\t" LOCK_PREFIX "andq %0, %2\n"
+ "2:\n"
+ "\t.section .fixup,\"ax\"\n"
+ "3:\tjmp\t2b\n"
+ "\t.previous\n"
+ _ASM_EXTABLE_UA(1b, 3b)
+ : "=r" (evtchn_pending_sel),
+ "+m" (vi->evtchn_pending_sel),
+ "+m" (v->arch.xen.evtchn_pending_sel)
+ : "0" (evtchn_pending_sel));
+ } else {
+ struct compat_vcpu_info __user *vi = (void *)ghc->hva;
+ u32 evtchn_pending_sel32 = evtchn_pending_sel;
+
+ /* Attempt to set the evtchn_pending_sel bits in the
+ * guest, and if that succeeds then clear the same
+ * bits in the in-kernel version. */
+ asm volatile("1:\t" LOCK_PREFIX "orl %0, %1\n"
+ "\tnotl %0\n"
+ "\t" LOCK_PREFIX "andl %0, %2\n"
+ "2:\n"
+ "\t.section .fixup,\"ax\"\n"
+ "3:\tjmp\t2b\n"
+ "\t.previous\n"
+ _ASM_EXTABLE_UA(1b, 3b)
+ : "=r" (evtchn_pending_sel32),
+ "+m" (vi->evtchn_pending_sel),
+ "+m" (v->arch.xen.evtchn_pending_sel)
+ : "0" (evtchn_pending_sel32));
+ }
+ rc = 1;
+ unsafe_put_user(rc, (u8 __user *)ghc->hva + offset, err);
+
+ err:
+ user_access_end();
+
+ mark_page_dirty_in_slot(v->kvm, v, ghc->memslot, ghc->gpa >> PAGE_SHIFT);
+ } else {
+ __get_user(rc, (u8 __user *)ghc->hva + offset);
+ }
return rc;
}
@@ -740,3 +816,179 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
return 0;
}
+
+static inline int max_evtchn_port(struct kvm *kvm)
+{
+ if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode)
+ return EVTCHN_2L_NR_CHANNELS;
+ else
+ return COMPAT_EVTCHN_2L_NR_CHANNELS;
+}
+
+/*
+ * This follows the kvm_set_irq() API, so it returns:
+ * < 0 Interrupt was ignored (masked or not delivered for other reasons)
+ * = 0 Interrupt was coalesced (previous irq is still pending)
+ * > 0 Number of CPUs interrupt was delivered to
+ */
+int kvm_xen_set_evtchn_fast(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm)
+{
+ struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
+ struct kvm_vcpu *vcpu;
+ unsigned long *pending_bits, *mask_bits;
+ unsigned long flags;
+ int port_word_bit;
+ bool kick_vcpu = false;
+ int idx;
+ int rc;
+
+ vcpu = kvm_get_vcpu_by_id(kvm, e->xen_evtchn.vcpu);
+ if (!vcpu)
+ return -1;
+
+ if (!vcpu->arch.xen.vcpu_info_set)
+ return -1;
+
+ if (e->xen_evtchn.port >= max_evtchn_port(kvm))
+ return -1;
+
+ rc = -EWOULDBLOCK;
+ read_lock_irqsave(&gpc->lock, flags);
+
+ idx = srcu_read_lock(&kvm->srcu);
+ if (!kvm_gfn_to_pfn_cache_check(kvm, gpc, gpc->gpa, PAGE_SIZE))
+ goto out_rcu;
+
+ if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
+ struct shared_info *shinfo = gpc->khva;
+ pending_bits = (unsigned long *)&shinfo->evtchn_pending;
+ mask_bits = (unsigned long *)&shinfo->evtchn_mask;
+ port_word_bit = e->xen_evtchn.port / 64;
+ } else {
+ struct compat_shared_info *shinfo = gpc->khva;
+ pending_bits = (unsigned long *)&shinfo->evtchn_pending;
+ mask_bits = (unsigned long *)&shinfo->evtchn_mask;
+ port_word_bit = e->xen_evtchn.port / 32;
+ }
+
+ /*
+ * If this port wasn't already set, and if it isn't masked, then
+ * we try to set the corresponding bit in the in-kernel shadow of
+ * evtchn_pending_sel for the target vCPU. And if *that* wasn't
+ * already set, then we kick the vCPU in question to write to the
+ * *real* evtchn_pending_sel in its own guest vcpu_info struct.
+ */
+ if (test_and_set_bit(e->xen_evtchn.port, pending_bits)) {
+ rc = 0; /* It was already raised */
+ } else if (test_bit(e->xen_evtchn.port, mask_bits)) {
+ rc = -1; /* Masked */
+ } else {
+ rc = 1; /* Delivered. But was the vCPU waking already? */
+ if (!test_and_set_bit(port_word_bit, &vcpu->arch.xen.evtchn_pending_sel))
+ kick_vcpu = true;
+ }
+
+ out_rcu:
+ srcu_read_unlock(&kvm->srcu, idx);
+ read_unlock_irqrestore(&gpc->lock, flags);
+
+ if (kick_vcpu) {
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+ kvm_vcpu_kick(vcpu);
+ }
+
+ return rc;
+}
+
+/* This is the version called from kvm_set_irq() as the .set function */
+static int evtchn_set_fn(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
+ int irq_source_id, int level, bool line_status)
+{
+ bool mm_borrowed = false;
+ int rc;
+
+ if (!level)
+ return -1;
+
+ rc = kvm_xen_set_evtchn_fast(e, kvm);
+ if (rc != -EWOULDBLOCK)
+ return rc;
+
+ if (current->mm != kvm->mm) {
+ /*
+ * If not on a thread which already belongs to this KVM,
+ * we'd better be in the irqfd workqueue.
+ */
+ if (WARN_ON_ONCE(current->mm))
+ return -EINVAL;
+
+ kthread_use_mm(kvm->mm);
+ mm_borrowed = true;
+ }
+
+ /*
+ * For the irqfd workqueue, using the main kvm->lock mutex is
+ * fine since this function is invoked from kvm_set_irq() with
+ * no other lock held, no srcu. In future if it will be called
+ * directly from a vCPU thread (e.g. on hypercall for an IPI)
+ * then it may need to switch to using a leaf-node mutex for
+ * serializing the shared_info mapping.
+ */
+ mutex_lock(&kvm->lock);
+
+ /*
+ * It is theoretically possible for the page to be unmapped
+ * and the MMU notifier to invalidate the shared_info before
+ * we even get to use it. In that case, this looks like an
+ * infinite loop. It was tempting to do it via the userspace
+ * HVA instead... but that just *hides* the fact that it's
+ * an infinite loop, because if a fault occurs and it waits
+ * for the page to come back, it can *still* immediately
+ * fault and have to wait again, repeatedly.
+ *
+ * Conversely, the page could also have been reinstated by
+ * another thread before we even obtain the mutex above, so
+ * check again *first* before remapping it.
+ */
+ do {
+ struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
+ int idx;
+
+ rc = kvm_xen_set_evtchn_fast(e, kvm);
+ if (rc != -EWOULDBLOCK)
+ break;
+
+ idx = srcu_read_lock(&kvm->srcu);
+ rc = kvm_gfn_to_pfn_cache_refresh(kvm, gpc, gpc->gpa,
+ PAGE_SIZE, true);
+ srcu_read_unlock(&kvm->srcu, idx);
+ } while(!rc);
+
+ mutex_unlock(&kvm->lock);
+
+ if (mm_borrowed)
+ kthread_unuse_mm(kvm->mm);
+
+ return rc;
+}
+
+int kvm_xen_setup_evtchn(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
+
+{
+ if (ue->u.xen_evtchn.port >= max_evtchn_port(kvm))
+ return -EINVAL;
+
+ /* We only support 2 level event channels for now */
+ if (ue->u.xen_evtchn.priority != KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL)
+ return -EINVAL;
+
+ e->xen_evtchn.port = ue->u.xen_evtchn.port;
+ e->xen_evtchn.vcpu = ue->u.xen_evtchn.vcpu;
+ e->xen_evtchn.priority = ue->u.xen_evtchn.priority;
+ e->set = evtchn_set_fn;
+
+ return 0;
+}
diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h
index cc0cf5f37450..adbcc9ed59db 100644
--- a/arch/x86/kvm/xen.h
+++ b/arch/x86/kvm/xen.h
@@ -24,6 +24,12 @@ int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc);
void kvm_xen_init_vm(struct kvm *kvm);
void kvm_xen_destroy_vm(struct kvm *kvm);
+int kvm_xen_set_evtchn_fast(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm);
+int kvm_xen_setup_evtchn(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue);
+
static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
{
return static_branch_unlikely(&kvm_xen_enabled.key) &&
@@ -134,6 +140,9 @@ struct compat_shared_info {
struct compat_arch_shared_info arch;
};
+#define COMPAT_EVTCHN_2L_NR_CHANNELS (8 * \
+ sizeof_field(struct compat_shared_info, \
+ evtchn_pending))
struct compat_vcpu_runstate_info {
int state;
uint64_t state_entry_time;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c35e207c2c1f..8a169ed43026 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -470,6 +470,12 @@ struct kvm_hv_sint {
u32 sint;
};
+struct kvm_xen_evtchn {
+ u32 port;
+ u32 vcpu;
+ u32 priority;
+};
+
struct kvm_kernel_irq_routing_entry {
u32 gsi;
u32 type;
@@ -490,6 +496,7 @@ struct kvm_kernel_irq_routing_entry {
} msi;
struct kvm_s390_adapter_int adapter;
struct kvm_hv_sint hv_sint;
+ struct kvm_xen_evtchn xen_evtchn;
};
struct hlist_node link;
};
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 1daa45268de2..12421e76adcb 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1162,11 +1162,20 @@ struct kvm_irq_routing_hv_sint {
__u32 sint;
};
+struct kvm_irq_routing_xen_evtchn {
+ __u32 port;
+ __u32 vcpu;
+ __u32 priority;
+};
+
+#define KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL ((__u32)(-1))
+
/* gsi routing entry types */
#define KVM_IRQ_ROUTING_IRQCHIP 1
#define KVM_IRQ_ROUTING_MSI 2
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
#define KVM_IRQ_ROUTING_HV_SINT 4
+#define KVM_IRQ_ROUTING_XEN_EVTCHN 5
struct kvm_irq_routing_entry {
__u32 gsi;
@@ -1178,6 +1187,7 @@ struct kvm_irq_routing_entry {
struct kvm_irq_routing_msi msi;
struct kvm_irq_routing_s390_adapter adapter;
struct kvm_irq_routing_hv_sint hv_sint;
+ struct kvm_irq_routing_xen_evtchn xen_evtchn;
__u32 pad[8];
} u;
};
@@ -1208,6 +1218,7 @@ struct kvm_x86_mce {
#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1)
#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2)
#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4)
struct kvm_xen_hvm_config {
__u32 flags;
diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
index a0699f00b3d6..a865e60a042c 100644
--- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
+++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
@@ -14,6 +14,9 @@
#include <stdint.h>
#include <time.h>
#include <sched.h>
+#include <signal.h>
+
+#include <sys/eventfd.h>
#define VCPU_ID 5
@@ -22,10 +25,12 @@
#define SHINFO_REGION_SLOT 10
#define PAGE_SIZE 4096
+#define SHINFO_ADDR (SHINFO_REGION_GPA)
#define PVTIME_ADDR (SHINFO_REGION_GPA + PAGE_SIZE)
#define RUNSTATE_ADDR (SHINFO_REGION_GPA + PAGE_SIZE + 0x20)
#define VCPU_INFO_ADDR (SHINFO_REGION_GPA + 0x40)
+#define SHINFO_VADDR (SHINFO_REGION_GVA)
#define RUNSTATE_VADDR (SHINFO_REGION_GVA + PAGE_SIZE + 0x20)
#define VCPU_INFO_VADDR (SHINFO_REGION_GVA + 0x40)
@@ -73,15 +78,30 @@ struct vcpu_info {
struct pvclock_vcpu_time_info time;
}; /* 64 bytes (x86) */
+struct shared_info {
+ struct vcpu_info vcpu_info[32];
+ unsigned long evtchn_pending[64];
+ unsigned long evtchn_mask[64];
+ struct pvclock_wall_clock wc;
+ uint32_t wc_sec_hi;
+ /* arch_shared_info here */
+};
+
#define RUNSTATE_running 0
#define RUNSTATE_runnable 1
#define RUNSTATE_blocked 2
#define RUNSTATE_offline 3
+struct {
+ struct kvm_irq_routing info;
+ struct kvm_irq_routing_entry entries[2];
+} irq_routes;
+
static void evtchn_handler(struct ex_regs *regs)
{
struct vcpu_info *vi = (void *)VCPU_INFO_VADDR;
vi->evtchn_upcall_pending = 0;
+ vi->evtchn_pending_sel = 0;
GUEST_SYNC(0x20);
}
@@ -127,7 +147,19 @@ static void guest_code(void)
GUEST_SYNC(6);
GUEST_ASSERT(rs->time[RUNSTATE_runnable] >= MIN_STEAL_TIME);
- GUEST_DONE();
+ /* Attempt to deliver a *masked* interrupt */
+ GUEST_SYNC(7);
+
+ /* Wait until we see the bit set */
+ struct shared_info *si = (void *)SHINFO_VADDR;
+ while (!si->evtchn_pending[0])
+ __asm__ __volatile__ ("rep nop" : : : "memory");
+
+ /* Now deliver an *unmasked* interrupt */
+ GUEST_SYNC(8);
+
+ for (;;)
+ __asm__ __volatile__ ("rep nop" : : : "memory");
}
static int cmp_timespec(struct timespec *a, struct timespec *b)
@@ -144,6 +176,11 @@ static int cmp_timespec(struct timespec *a, struct timespec *b)
return 0;
}
+static void handle_alrm(int sig)
+{
+ TEST_FAIL("IRQ delivery timed out");
+}
+
int main(int argc, char *argv[])
{
struct timespec min_ts, max_ts, vm_ts;
@@ -155,6 +192,7 @@ int main(int argc, char *argv[])
}
bool do_runstate_tests = !!(xen_caps & KVM_XEN_HVM_CONFIG_RUNSTATE);
+ bool do_eventfd_tests = !!(xen_caps & KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL);
clock_gettime(CLOCK_REALTIME, &min_ts);
@@ -166,6 +204,11 @@ int main(int argc, char *argv[])
SHINFO_REGION_GPA, SHINFO_REGION_SLOT, 2, 0);
virt_map(vm, SHINFO_REGION_GVA, SHINFO_REGION_GPA, 2);
+ struct shared_info *shinfo = addr_gpa2hva(vm, SHINFO_VADDR);
+
+ int zero_fd = open("/dev/zero", O_RDONLY);
+ TEST_ASSERT(zero_fd != -1, "Failed to open /dev/zero");
+
struct kvm_xen_hvm_config hvmc = {
.flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,
.msr = XEN_HYPERCALL_MSR,
@@ -184,6 +227,16 @@ int main(int argc, char *argv[])
};
vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &ha);
+ /*
+ * Test what happens when the HVA of the shinfo page is remapped after
+ * the kernel has a reference to it. But make sure we copy the clock
+ * info over since that's only set at setup time, and we test it later.
+ */
+ struct pvclock_wall_clock wc_copy = shinfo->wc;
+ void *m = mmap(shinfo, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, zero_fd, 0);
+ TEST_ASSERT(m == shinfo, "Failed to map /dev/zero over shared info");
+ shinfo->wc = wc_copy;
+
struct kvm_xen_vcpu_attr vi = {
.type = KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
.u.gpa = VCPU_INFO_ADDR,
@@ -214,6 +267,49 @@ int main(int argc, char *argv[])
vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &st);
}
+ int irq_fd[2] = { -1, -1 };
+
+ if (do_eventfd_tests) {
+ irq_fd[0] = eventfd(0, 0);
+ irq_fd[1] = eventfd(0, 0);
+
+ /* Unexpected, but not a KVM failure */
+ if (irq_fd[0] == -1 || irq_fd[1] == -1)
+ do_eventfd_tests = false;
+ }
+
+ if (do_eventfd_tests) {
+ irq_routes.info.nr = 2;
+
+ irq_routes.entries[0].gsi = 32;
+ irq_routes.entries[0].type = KVM_IRQ_ROUTING_XEN_EVTCHN;
+ irq_routes.entries[0].u.xen_evtchn.port = 15;
+ irq_routes.entries[0].u.xen_evtchn.vcpu = VCPU_ID;
+ irq_routes.entries[0].u.xen_evtchn.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
+
+ irq_routes.entries[1].gsi = 33;
+ irq_routes.entries[1].type = KVM_IRQ_ROUTING_XEN_EVTCHN;
+ irq_routes.entries[1].u.xen_evtchn.port = 66;
+ irq_routes.entries[1].u.xen_evtchn.vcpu = VCPU_ID;
+ irq_routes.entries[1].u.xen_evtchn.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
+
+ vm_ioctl(vm, KVM_SET_GSI_ROUTING, &irq_routes);
+
+ struct kvm_irqfd ifd = { };
+
+ ifd.fd = irq_fd[0];
+ ifd.gsi = 32;
+ vm_ioctl(vm, KVM_IRQFD, &ifd);
+
+ ifd.fd = irq_fd[1];
+ ifd.gsi = 33;
+ vm_ioctl(vm, KVM_IRQFD, &ifd);
+
+ struct sigaction sa = { };
+ sa.sa_handler = handle_alrm;
+ sigaction(SIGALRM, &sa, NULL);
+ }
+
struct vcpu_info *vinfo = addr_gpa2hva(vm, VCPU_INFO_VADDR);
vinfo->evtchn_upcall_pending = 0;
@@ -289,9 +385,23 @@ int main(int argc, char *argv[])
sched_yield();
} while (get_run_delay() < rundelay);
break;
+ case 7:
+ if (!do_eventfd_tests)
+ goto done;
+ shinfo->evtchn_mask[0] = 0x8000;
+ eventfd_write(irq_fd[0], 1UL);
+ alarm(1);
+ break;
+ case 8:
+ eventfd_write(irq_fd[1], 1UL);
+ evtchn_irq_expected = true;
+ break;
+
case 0x20:
TEST_ASSERT(evtchn_irq_expected, "Unexpected event channel IRQ");
evtchn_irq_expected = false;
+ if (shinfo->evtchn_pending[1])
+ goto done;
break;
}
break;
--
2.31.1
^ permalink raw reply related
* Re: [PATCH v3 07/12] KVM: arm64: Use Makefile.kvm for common files
From: Marc Zyngier @ 2021-11-17 18:11 UTC (permalink / raw)
To: David Woodhouse
Cc: Anup Patel, wanpengli @ tencent . com, kvm, Joao Martins,
Will Deacon, kvmarm, linux-s390, joro @ 8bytes . org, Huacai Chen,
Christian Borntraeger, Aleksandar Markovic, karahmed,
Catalin Marinas, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Paolo Bonzini, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-8-dwmw2@infradead.org>
On Wed, 17 Nov 2021 17:39:58 +0000,
David Woodhouse <dwmw2@infradead.org> wrote:
>
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/arm64/kvm/Makefile | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index 989bb5dad2c8..04a53f71a6b6 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -5,14 +5,12 @@
>
> ccflags-y += -I $(srctree)/$(src)
>
> -KVM=../../../virt/kvm
> +include $(srctree)/virt/kvm/Makefile.kvm
>
> obj-$(CONFIG_KVM) += kvm.o
> obj-$(CONFIG_KVM) += hyp/
>
> -kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
> - $(KVM)/vfio.o $(KVM)/irqchip.o $(KVM)/binary_stats.o \
> - arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
> +kvm-y += arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
> inject_fault.o va_layout.o handle_exit.o \
> guest.o debug.o reset.o sys_regs.o \
> vgic-sys-reg-v3.o fpsimd.o pmu.o \
Acked-by: Marc Zyngier <maz@kernel.org>
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v3 02/12] KVM: Add Makefile.kvm for common files, use it for x86
From: Marc Zyngier @ 2021-11-17 18:11 UTC (permalink / raw)
To: David Woodhouse
Cc: Anup Patel, wanpengli @ tencent . com, kvm, Joao Martins,
Will Deacon, kvmarm, linux-s390, joro @ 8bytes . org, Huacai Chen,
Christian Borntraeger, Aleksandar Markovic, karahmed,
Catalin Marinas, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Paolo Bonzini, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-3-dwmw2@infradead.org>
On Wed, 17 Nov 2021 17:39:53 +0000,
David Woodhouse <dwmw2@infradead.org> wrote:
>
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Splitting kvm_main.c out into smaller and better-organized files is
> slightly non-trivial when it involves editing a bunch of per-arch
> KVM makefiles. Provide virt/kvm/Makefile.kvm for them to include.
>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/x86/kvm/Makefile | 7 +------
> virt/kvm/Makefile.kvm | 13 +++++++++++++
> 2 files changed, 14 insertions(+), 6 deletions(-)
> create mode 100644 virt/kvm/Makefile.kvm
>
> diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
> index 75dfd27b6e8a..30f244b64523 100644
> --- a/arch/x86/kvm/Makefile
> +++ b/arch/x86/kvm/Makefile
> @@ -7,12 +7,7 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
> OBJECT_FILES_NON_STANDARD_vmenter.o := y
> endif
>
> -KVM := ../../../virt/kvm
> -
> -kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
> - $(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o \
> - $(KVM)/dirty_ring.o $(KVM)/binary_stats.o
> -kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
> +include $(srctree)/virt/kvm/Makefile.kvm
>
> kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
> i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
> diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
> new file mode 100644
> index 000000000000..ffdcad3cc97a
> --- /dev/null
> +++ b/virt/kvm/Makefile.kvm
> @@ -0,0 +1,13 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Makefile for Kernel-based Virtual Machine module
> +#
> +
> +KVM ?= ../../../virt/kvm
> +
> +kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.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
Acked-by: Marc Zyngier <maz@kernel.org>
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v3 08/12] KVM: Propagate vcpu explicitly to mark_page_dirty_in_slot()
From: Marc Zyngier @ 2021-11-17 18:13 UTC (permalink / raw)
To: David Woodhouse
Cc: Anup Patel, wanpengli @ tencent . com, kvm, Joao Martins,
Will Deacon, kvmarm, linux-s390, joro @ 8bytes . org, Huacai Chen,
Christian Borntraeger, Aleksandar Markovic, karahmed,
Catalin Marinas, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Paolo Bonzini, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <20211117174003.297096-9-dwmw2@infradead.org>
On Wed, 17 Nov 2021 17:39:59 +0000,
David Woodhouse <dwmw2@infradead.org> wrote:
>
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> The kvm_dirty_ring_get() function uses kvm_get_running_vcpu() to work out
> which dirty ring to use, but there are some use cases where that doesn't
> work.
>
> There's one in setting the Xen shared info page, introduced in commit
> 629b5348841a ("KVM: x86/xen: update wallclock region") and reported by
> "butt3rflyh4ck" <butterflyhuangxx@gmail.com> in
> https://lore.kernel.org/kvm/CAFcO6XOmoS7EacN_n6v4Txk7xL7iqRa2gABg3F7E3Naf5uG94g@mail.gmail.com/
>
> There's also about to be another one when the newly-reintroduced
> gfn_to_pfn_cache needs to mark a page as dirty from the MMU notifier
> which invalidates the mapping. In that case, we will *know* the vcpu
> that can be 'blamed' for dirtying the page, and we just need to be
> able to pass it in as an explicit argument when doing so.
>
> This patch preemptively resolves the second issue, and paves the way
> for resolving the first. A complete fix for the first issue will need
> us to switch the Xen shinfo to be owned by a particular vCPU, which
> will happen in a separate patch.
>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/arm64/kvm/mmu.c | 2 +-
> arch/x86/kvm/mmu/mmu.c | 2 +-
> arch/x86/kvm/mmu/spte.c | 2 +-
> arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
> arch/x86/kvm/x86.c | 4 ++--
> include/linux/kvm_dirty_ring.h | 6 ++++--
> include/linux/kvm_host.h | 3 ++-
> virt/kvm/dirty_ring.c | 8 ++++++--
> virt/kvm/kvm_main.c | 18 +++++++++---------
> 9 files changed, 27 insertions(+), 20 deletions(-)
What's the base for this series? This patch fails to compile for me
(at least on arm64), and the following patch doesn't apply on -rc1.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v3 08/12] KVM: Propagate vcpu explicitly to mark_page_dirty_in_slot()
From: David Woodhouse @ 2021-11-17 18:31 UTC (permalink / raw)
To: Marc Zyngier
Cc: Anup Patel, wanpengli @ tencent . com, kvm, Joao Martins,
Will Deacon, kvmarm, linux-s390, joro @ 8bytes . org, Huacai Chen,
Christian Borntraeger, Aleksandar Markovic, karahmed,
Catalin Marinas, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Paolo Bonzini, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <87pmqy7ir2.wl-maz@kernel.org>
On 17 November 2021 18:13:37 GMT, Marc Zyngier <maz@kernel.org> wrote:
>On Wed, 17 Nov 2021 17:39:59 +0000,
>David Woodhouse <dwmw2@infradead.org> wrote:
>>
>> From: David Woodhouse <dwmw@amazon.co.uk>
>>
>> The kvm_dirty_ring_get() function uses kvm_get_running_vcpu() to work out
>> which dirty ring to use, but there are some use cases where that doesn't
>> work.
>>
>> There's one in setting the Xen shared info page, introduced in commit
>> 629b5348841a ("KVM: x86/xen: update wallclock region") and reported by
>> "butt3rflyh4ck" <butterflyhuangxx@gmail.com> in
>> https://lore.kernel.org/kvm/CAFcO6XOmoS7EacN_n6v4Txk7xL7iqRa2gABg3F7E3Naf5uG94g@mail.gmail.com/
>>
>> There's also about to be another one when the newly-reintroduced
>> gfn_to_pfn_cache needs to mark a page as dirty from the MMU notifier
>> which invalidates the mapping. In that case, we will *know* the vcpu
>> that can be 'blamed' for dirtying the page, and we just need to be
>> able to pass it in as an explicit argument when doing so.
>>
>> This patch preemptively resolves the second issue, and paves the way
>> for resolving the first. A complete fix for the first issue will need
>> us to switch the Xen shinfo to be owned by a particular vCPU, which
>> will happen in a separate patch.
>>
>> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
>> ---
>> arch/arm64/kvm/mmu.c | 2 +-
>> arch/x86/kvm/mmu/mmu.c | 2 +-
>> arch/x86/kvm/mmu/spte.c | 2 +-
>> arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
>> arch/x86/kvm/x86.c | 4 ++--
>> include/linux/kvm_dirty_ring.h | 6 ++++--
>> include/linux/kvm_host.h | 3 ++-
>> virt/kvm/dirty_ring.c | 8 ++++++--
>> virt/kvm/kvm_main.c | 18 +++++++++---------
>> 9 files changed, 27 insertions(+), 20 deletions(-)
>
>What's the base for this series? This patch fails to compile for me
>(at least on arm64), and the following patch doesn't apply on -rc1.
kvm/master
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
^ permalink raw reply
* Re: [PATCH v3 08/12] KVM: Propagate vcpu explicitly to mark_page_dirty_in_slot()
From: David Woodhouse @ 2021-11-17 19:30 UTC (permalink / raw)
To: Marc Zyngier
Cc: Anup Patel, wanpengli @ tencent . com, kvm, Joao Martins,
Will Deacon, kvmarm, linux-s390, joro @ 8bytes . org, Huacai Chen,
Christian Borntraeger, Aleksandar Markovic, karahmed,
Catalin Marinas, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Paolo Bonzini, vkuznets @ redhat . com,
linuxppc-dev
In-Reply-To: <87pmqy7ir2.wl-maz@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 394 bytes --]
On Wed, 2021-11-17 at 18:13 +0000, Marc Zyngier wrote:
> What's the base for this series? This patch fails to compile for me
> (at least on arm64), and the following patch doesn't apply on -rc1.
It's on top of kvm/master, and it's also at
https://git.infradead.org/users/dwmw2/linux.git/shortlog/refs/heads/xen-evtchn
git pull git://git.infradead.org/users/dwmw2/linux.git xen-evtchn
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5174 bytes --]
^ permalink raw reply
* Re: Build regressions/improvements in v5.16-rc1
From: Nick Terrell @ 2021-11-17 19:39 UTC (permalink / raw)
To: Helge Deller
Cc: Hector Martin, Peter Zijlstra, linux-pci, DRI Development,
open list:BROADCOM NVRAM DRIVER, James E.J. Bottomley,
Andrey Ryabinin, Stan Skowronek, Herbert Xu, kasan-dev,
Sergio Paracuellos, Geert Uytterhoeven, Anton Altaparmakov,
linux-arm-msm, open list:GPIO SUBSYSTEM, Joey Gouly,
André Almeida, Linux ARM, Thomas Bogendoerfer, Parisc List,
linux-ntfs-dev@lists.sourceforge.net, Randy Dunlap,
Linux Kernel Mailing List, Rob Clark, Linux Crypto Mailing List,
linuxppc-dev
In-Reply-To: <525f9914-04bd-2d8a-0bbf-daf2d0d2053d@gmx.de>
> On Nov 17, 2021, at 3:22 AM, Helge Deller <deller@gmx.de> wrote:
>
> On 11/17/21 03:19, Nick Terrell wrote:
>>
>>
>>> On Nov 16, 2021, at 6:05 PM, Randy Dunlap <rdunlap@infradead.org> wrote:
>>>
>>> On 11/16/21 5:59 PM, Nick Terrell wrote:
>>>>> On Nov 15, 2021, at 8:44 AM, Helge Deller <deller@gmx.de> wrote:
>>>>>
>>>>> On 11/15/21 17:12, Geert Uytterhoeven wrote:
>>>>>> On Mon, Nov 15, 2021 at 4:54 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>>>>>>> Below is the list of build error/warning regressions/improvements in
>>>>>>> v5.16-rc1[1] compared to v5.15[2].
>>>>>>>
>>>>>>> Summarized:
>>>>>>> - build errors: +20/-13
>>>>>>> - build warnings: +3/-28
>>>>>>>
>>>>>>> Happy fixing! ;-)
>>>>>>>
>>>>>>> Thanks to the linux-next team for providing the build service.
>>>>>>>
>>>>>>> [1] http://kisskb.ellerman.id.au/kisskb/branch/linus/head/fa55b7dcdc43c1aa1ba12bca9d2dd4318c2a0dbf/ (all 90 configs)
>>>>>>> [2] http://kisskb.ellerman.id.au/kisskb/branch/linus/head/8bb7eca972ad531c9b149c0a51ab43a417385813/ (all 90 configs)
>>>>>>>
>>>>>>>
>>>>>>> *** ERRORS ***
>>>>>>>
>>>>>>> 20 error regressions:
>>>>>>> + /kisskb/src/arch/parisc/include/asm/jump_label.h: error: expected ':' before '__stringify': => 33:4, 18:4
>>>>>>> + /kisskb/src/arch/parisc/include/asm/jump_label.h: error: label 'l_yes' defined but not used [-Werror=unused-label]: => 38:1, 23:1
>>>>>>
>>>>>> due to static_branch_likely() in crypto/api.c
>>>>>>
>>>>>> parisc-allmodconfig
>>>>>
>>>>> fixed now in the parisc for-next git tree.
>>>>>
>>>>>
>>>>>>> + /kisskb/src/drivers/gpu/drm/msm/msm_drv.h: error: "COND" redefined [-Werror]: => 531
>>>>>>> + /kisskb/src/lib/zstd/compress/zstd_double_fast.c: error: the frame size of 3252 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]: => 47:1
>>>>>>> + /kisskb/src/lib/zstd/compress/zstd_double_fast.c: error: the frame size of 3360 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]: => 499:1
>>>>>>> + /kisskb/src/lib/zstd/compress/zstd_double_fast.c: error: the frame size of 5344 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]: => 334:1
>>>>>>> + /kisskb/src/lib/zstd/compress/zstd_double_fast.c: error: the frame size of 5380 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]: => 354:1
>>>>>>> + /kisskb/src/lib/zstd/compress/zstd_fast.c: error: the frame size of 1824 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]: => 372:1
>>>>>>> + /kisskb/src/lib/zstd/compress/zstd_fast.c: error: the frame size of 2224 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]: => 204:1
>>>>>>> + /kisskb/src/lib/zstd/compress/zstd_fast.c: error: the frame size of 3800 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]: => 476:1
>>>>>>
>>>>>> parisc-allmodconfig
>>>>>
>>>>> parisc needs much bigger frame sizes, so I'm not astonished here.
>>>>> During the v5.15 cycl I increased it to 1536 (from 1280), so I'm simply tempted to
>>>>> increase it this time to 4096, unless someone has a better idea....
>>>> This patch set should fix the zstd stack size warnings [0]. I’ve
>>>> verified the fix using the same tooling: gcc-8-hppa-linux-gnu.
>>>> I’ll send the PR to Linus tomorrow. I’ve been informed that it
>>>> isn't strictly necessary to send the patches to the mailing list
>>>> for bug fixes, but its already done, so I’ll wait and see if there
>>>> is any feedback.
>>>
>>> IMO several (or many more) people would disagree with that.
>>>
>>> "strictly?" OK, it's probably possible that almost any patch
>>> could be merged without being on a mailing list, but it's not
>>> desirable (except in the case of "security" patches).
>>
>> Good to know! Thanks for the advice, I wasn’t really sure what
>> the best practice is for sending patches to your own tree, as I
>> didn't see anything about it in the maintainer guide.
>
> Nick, thanks a lot for your efforts to get the frame size usage down!
>
> I've applied your patch series to the parisc for-next tree [1], so that it
> gets some testing in the upstream for-next tree.
> My tests so far are good, although I'm only using gcc-11.
>
> If you don't mind, and if it doesn't generate issues for other
> platforms & architectures I could submit them upstream to Linus when
> I send the next pull request.
Sure, I’m fine with that. The only other major goal of this patch series
is to reduce code size bloat. But, that isn’t blocking development of
anyone.
I do have an update to make for patch 1 though, after some comments
from Linus. So I’ll send out a V2 shortly.
Best,
Nick Terrell
> Helge
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git/log/?h=for-next
^ permalink raw reply
* Re: [PATCH v3 08/12] KVM: Propagate vcpu explicitly to mark_page_dirty_in_slot()
From: David Woodhouse @ 2021-11-17 21:09 UTC (permalink / raw)
To: David Woodhouse
Cc: Anup Patel, wanpengli @ tencent . com, kvm, Joao Martins,
Will Deacon, kvmarm, linux-s390, joro @ 8bytes . org, Huacai Chen,
Christian Borntraeger, Aleksandar Markovic, karahmed,
Catalin Marinas, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, Marc Zyngier, Paolo Bonzini,
vkuznets @ redhat . com, linuxppc-dev
In-Reply-To: <20211117174003.297096-9-dwmw2@infradead.org>
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> The kvm_dirty_ring_get() function uses kvm_get_running_vcpu() to work out
> which dirty ring to use, but there are some use cases where that doesn't
> work.
>
> There's one in setting the Xen shared info page, introduced in commit
> 629b5348841a ("KVM: x86/xen: update wallclock region") and reported by
> "butt3rflyh4ck" <butterflyhuangxx@gmail.com> in
> https://lore.kernel.org/kvm/CAFcO6XOmoS7EacN_n6v4Txk7xL7iqRa2gABg3F7E3Naf5uG94g@mail.gmail.com/
>
> There's also about to be another one when the newly-reintroduced
> gfn_to_pfn_cache needs to mark a page as dirty from the MMU notifier
> which invalidates the mapping. In that case, we will *know* the vcpu
> that can be 'blamed' for dirtying the page, and we just need to be
> able to pass it in as an explicit argument when doing so.
>
> This patch preemptively resolves the second issue, and paves the way
> for resolving the first. A complete fix for the first issue will need
> us to switch the Xen shinfo to be owned by a particular vCPU, which
> will happen in a separate patch.
>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> --- a/virt/kvm/dirty_ring.c
> +++ b/virt/kvm/dirty_ring.c
> @@ -36,12 +36,16 @@ static bool kvm_dirty_ring_full(struct kvm_dirty_ring
> *ring)
> return kvm_dirty_ring_used(ring) >= ring->size;
> }
>
> -struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm)
> +struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm, struct
> kvm_vcpu *vcpu)
> {
> - struct kvm_vcpu *vcpu = kvm_get_running_vcpu();
> + struct kvm_vcpu *running_vcpu = kvm_get_running_vcpu();
>
> + WARN_ON_ONCE(vcpu && vcpu != running_vcpu);
> WARN_ON_ONCE(vcpu->kvm != kvm);
Ah, that one needs to be changed to check running_vcpu instead. Or this
needs to go first:
I think I prefer making the vCPU a required argument. If anyone's going to
pull a vCPU pointer out of their posterior, let the caller do it.
> + if (!vcpu)
> + vcpu = running_vcpu;
> +
> return &vcpu->dirty_ring;
> }
>
--
dwmw2
^ permalink raw reply
* Re: [PATCH v3 06/12] KVM: powerpc: Use Makefile.kvm for common files
From: Michael Ellerman @ 2021-11-17 23:50 UTC (permalink / raw)
To: David Woodhouse, Paolo Bonzini, kvm
Cc: Anup Patel, wanpengli @ tencent . com, Catalin Marinas,
Joao Martins, Will Deacon, kvmarm, linux-s390, Marc Zyngier,
joro @ 8bytes . org, Huacai Chen, Christian Borntraeger,
Aleksandar Markovic, karahmed, Suzuki K Poulose, Boris Ostrovsky,
Alexandru Elisei, linux-arm-kernel, jmattson @ google . com,
seanjc @ google . com, mtosatti @ redhat . com, linux-mips,
James Morse, kvm-riscv, vkuznets @ redhat . com, linuxppc-dev
In-Reply-To: <20211117174003.297096-7-dwmw2@infradead.org>
David Woodhouse <dwmw2@infradead.org> writes:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> It's all fairly baroque but in the end, I don't think there's any reason
> for $(KVM)/irqchip.o to have been handled differently, as they all end
> up in $(kvm-y) in the end anyway, regardless of whether they get there
> via $(common-objs-y) and the CPU-specific object lists.
>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> arch/powerpc/kvm/Makefile | 6 +-----
> 1 file changed, 1 insertion(+), 5 deletions(-)
>
> diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
> index 583c14ef596e..245f59118413 100644
> --- a/arch/powerpc/kvm/Makefile
> +++ b/arch/powerpc/kvm/Makefile
> @@ -4,11 +4,8 @@
> #
>
> ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
> -KVM := ../../../virt/kvm
>
> -common-objs-y = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/binary_stats.o
> -common-objs-$(CONFIG_KVM_VFIO) += $(KVM)/vfio.o
> -common-objs-$(CONFIG_KVM_MMIO) += $(KVM)/coalesced_mmio.o
> +include $(srctree)/virt/kvm/Makefile.kvm
>
> common-objs-y += powerpc.o emulate_loadstore.o
> obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o
> @@ -125,7 +122,6 @@ kvm-book3s_32-objs := \
> kvm-objs-$(CONFIG_KVM_BOOK3S_32) := $(kvm-book3s_32-objs)
>
> kvm-objs-$(CONFIG_KVM_MPIC) += mpic.o
> -kvm-objs-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o
>
> kvm-objs := $(kvm-objs-m) $(kvm-objs-y)
Looks OK to me. The extra objects built in Makefile.kvm are all behind
CONFIG symbols we don't enable.
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
cheers
^ permalink raw reply
* Re: [PATCH v3 01/25] PCI: Add PCI_ERROR_RESPONSE and it's related definitions
From: Bjorn Helgaas @ 2021-11-17 23:58 UTC (permalink / raw)
To: Naveen Naidu
Cc: Krzysztof Wilczyński, linux-hyperv, Heiko Stuebner,
linux-pci, Shawn Lin, Binghui Wang, Kuppuswamy Sathyanarayanan,
Ryder Lee, Oliver O'Halloran, Thomas Petazzoni, Toan Le,
K. Y. Srinivasan, Nirmal Patel, Marek Vasut, Rob Herring, Wei Liu,
Lorenzo Pieralisi, Stephen Hemminger, Krzysztof Kozlowski,
Marc Zyngier, Dexuan Cui, Jianjun Wang, linux-rockchip,
maintainer:BROADCOM IPROC ARM ARCHITECTURE, Jonathan Derrick,
Xiaowei Song, linux-kernel-mentees, Matthias Brugger,
Robert Richter, Sean V Kelley, Ray Jui, Haiyang Zhang,
linux-samsung-soc, linux-mediatek, bhelgaas, linux-arm-kernel,
Qiuxu Zhuo, Pali Rohár, Scott Branden, Jingoo Han,
Yoshihiro Shimoda, linux-kernel, linux-renesas-soc, Lukas Wunner,
Joyce Ooi, Shawn Guo, linuxppc-dev
In-Reply-To: <f7960a4dee0e417eedd7d2e031d04ac9016c6686.1634825082.git.naveennaidu479@gmail.com>
On Thu, Oct 21, 2021 at 08:37:26PM +0530, Naveen Naidu wrote:
> An MMIO read from a PCI device that doesn't exist or doesn't respond
> causes a PCI error. There's no real data to return to satisfy the
> CPU read, so most hardware fabricates ~0 data.
>
> Add a PCI_ERROR_RESPONSE definition for that and use it where
> appropriate to make these checks consistent and easier to find.
>
> Also add helper definitions SET_PCI_ERROR_RESPONSE and
> RESPONSE_IS_PCI_ERROR to make the code more readable.
>
> Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
> Signed-off-by: Naveen Naidu <naveennaidu479@gmail.com>
> ---
> include/linux/pci.h | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index cd8aa6fce204..689c8277c584 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -154,6 +154,15 @@ enum pci_interrupt_pin {
> /* The number of legacy PCI INTx interrupts */
> #define PCI_NUM_INTX 4
>
> +/*
> + * Reading from a device that doesn't respond typically returns ~0. A
> + * successful read from a device may also return ~0, so you need additional
> + * information to reliably identify errors.
> + */
> +#define PCI_ERROR_RESPONSE (~0ULL)
> +#define SET_PCI_ERROR_RESPONSE(val) (*(val) = ((typeof(*(val))) PCI_ERROR_RESPONSE))
> +#define RESPONSE_IS_PCI_ERROR(val) ((val) == ((typeof(val)) PCI_ERROR_RESPONSE))
Beautiful! I really like this.
I would prefer the macros to start with "PCI_", e.g.,
PCI_SET_ERROR_RESPONSE().
I think "RESPONSE_IS_PCI_ERROR()" is too strong because (as the
comment says), ~0 *may* indicate an error. Or it may be a successful
read of a register that happens to contain ~0.
Possibilities to convey the idea that this isn't definitive:
PCI_POSSIBLE_ERROR_RESPONSE(val) # a little long
PCI_LIKELY_ERROR(val) # we really have no idea whether
PCI_PROBABLE_ERROR(val) # likely or probable
PCI_POSSIBLE_ERROR(val) # promising?
Can you rebase to my "main" branch (v5.16-rc1), tweak the above, and
collect up the acks/reviews?
We should also browse drivers outside drivers/pci for places we could
use these. Not necessarily as part of this series, although if
authors there object, it would be good to learn that earlier than
later.
Drivers that implement pci_error_handlers might be a fruitful place to
start. But you've done a great job finding users of ~0 and 0xffff...
in drivers/pci/, too.
> +
> /*
> * pci_power_t values must match the bits in the Capabilities PME_Support
> * and Control/Status PowerState fields in the Power Management capability.
> --
> 2.25.1
>
> _______________________________________________
> Linux-kernel-mentees mailing list
> Linux-kernel-mentees@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees
^ permalink raw reply
* Re: [PATCH] powerpc/pseries: delete scanlog
From: Michael Ellerman @ 2021-11-18 0:26 UTC (permalink / raw)
To: Nathan Lynch, linuxppc-dev; +Cc: tyreld
In-Reply-To: <87mtm2j0tz.fsf@linux.ibm.com>
Nathan Lynch <nathanl@linux.ibm.com> writes:
> Michael Ellerman <mpe@ellerman.id.au> writes:
>> Nathan Lynch <nathanl@linux.ibm.com> writes:
>>> Nathan Lynch <nathanl@linux.ibm.com> writes:
>>>> Remove the pseries scanlog driver.
>>>>
>>>> This code supports functions from Power4-era servers that are not present
>>>> on targets currently supported by arch/powerpc. System manuals from this
>>>> time have this description:
>>>>
>>>> Scan Dump data is a set of chip data that the service processor gathers
>>>> after a system malfunction. It consists of chip scan rings, chip trace
>>>> arrays, and Scan COM (SCOM) registers. This data is stored in the
>>>> scan-log partition of the system’s Nonvolatile Random Access
>>>> Memory (NVRAM).
>>>>
>>>> PowerVM partition firmware development doesn't recognize the associated
>>>> function call or property, and they don't see any references to them in
>>>> their codebase. It seems to have been specific to non-virtualized
>>>> pseries.
>>>
>>> Just bumping this to see if there are any objections.
>>
>> Not an objection, I like nothing better than dropping old unused cruft,
>> but are we sure it's safe to remove the proc file?
>>
>> I see that rtas_errd still looks for it, have you checked that it will
>> handle the absence of the file gracefully and continue doing whatever
>> else it does?
>
> Uhh. I will stop forgetting to check ppc64_diag when making such
> changes. Thanks for pointing this out.
No worries.
>> On further inspection it looks like the code that looks for it in
>> rtas_errd is #if 0'ed out (??), so maybe it's dead.
>
> Yes it seems so. From rtas_errd's main():
>
> #if 0
> /*
> * Check to see if a new scanlog dump is available; if so, copy it to
> * the filesystem and associate the dump with the first error processed.
> */
> check_scanlog_dump();
> #endif
>
> And that's the only entry point into the code that collects the scanlog
> data. And that dead code appears to deal with the absence of
> /proc/ppc64/scan-log-dump gracefully. It has been like that since
> initial git import in 2013.
OK, I guess it came from sourceforge before that. But I'm not going to
start digging there, that's long enough ago that it shouldn't matter.
>> Anyway if you can test that rtas_errd still works that'd be good.
>
> I've verified that it starts normally and logs EPOW events associated
> with partition migration.
Awesome.
>> Presumably there's no other code that cares about the proc file.
>
> AFAIK this is right. powerpc-utils and librtas do not use it. librtas
> has a wrapper for the calling the associated RTAS function directly, but
> that's fine.
>
> I tried using GitHub's search to find instances of "scan-log-dump" that
> weren't from Linux or ppc64_diag (need to be logged in I think):
>
> https://github.com/search?q=%22scan-log-dump%22+-path%3Aarch%2Fpowerpc+-filename%3Ascanlog.c+-extension%3Apatch&type=Code&ref=advsearch&l=&l=
>
> This hasn't yielded any unexpected users. There may be better search
> terms but that's what a few minutes of fiddling with it got me.
I had a look on sourcegraph too, same story, nothing interesting:
https://sourcegraph.com/search?q=context:global+scan-log-dump+NOT+file:arch/powerpc/platforms/pseries/scanlog.c+NOT+file:arch/powerpc/kernel/rtas.c+NOT+file:arch/ppc64/kernel/scanlog.c+fork:yes+archived:yes&patternType=literal
So that seems OK to me, I'll pick this up.
cheers
^ permalink raw reply
* [powerpc:fixes-test] BUILD SUCCESS 8e80a73fa9a7747e3e8255cb149c543aabf65a24
From: kernel test robot @ 2021-11-18 0:34 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git fixes-test
branch HEAD: 8e80a73fa9a7747e3e8255cb149c543aabf65a24 powerpc/xive: Change IRQ domain to a tree domain
elapsed time: 727m
configs tested: 188
configs skipped: 85
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
i386 randconfig-c001-20211117
powerpc randconfig-c003-20211117
sh ecovec24-romimage_defconfig
m68k multi_defconfig
powerpc mpc85xx_cds_defconfig
arm jornada720_defconfig
sh rsk7269_defconfig
riscv alldefconfig
alpha defconfig
powerpc stx_gp3_defconfig
arc nsimosci_hs_defconfig
powerpc mpc5200_defconfig
powerpc amigaone_defconfig
powerpc adder875_defconfig
arm iop32x_defconfig
m68k mac_defconfig
sh se7343_defconfig
powerpc pasemi_defconfig
mips jazz_defconfig
mips malta_qemu_32r6_defconfig
sparc sparc64_defconfig
i386 defconfig
ia64 defconfig
sh apsh4a3a_defconfig
arm ep93xx_defconfig
mips ath79_defconfig
sh ecovec24_defconfig
i386 alldefconfig
mips capcella_defconfig
powerpc tqm8555_defconfig
arm ezx_defconfig
powerpc mpc885_ads_defconfig
powerpc ge_imp3a_defconfig
um x86_64_defconfig
sh secureedge5410_defconfig
s390 allmodconfig
mips loongson3_defconfig
sh sh7724_generic_defconfig
mips malta_kvm_defconfig
powerpc mpc832x_mds_defconfig
h8300 h8300h-sim_defconfig
m68k sun3_defconfig
sh lboxre2_defconfig
xtensa allyesconfig
arm moxart_defconfig
arm keystone_defconfig
mips bcm47xx_defconfig
alpha alldefconfig
xtensa common_defconfig
mips ci20_defconfig
arm sunxi_defconfig
mips sb1250_swarm_defconfig
powerpc akebono_defconfig
powerpc chrp32_defconfig
powerpc mpc7448_hpc2_defconfig
sh ul2_defconfig
powerpc socrates_defconfig
m68k atari_defconfig
mips bmips_stb_defconfig
sh se7724_defconfig
arm mmp2_defconfig
powerpc wii_defconfig
arm lpc32xx_defconfig
powerpc cm5200_defconfig
arm mvebu_v7_defconfig
arm exynos_defconfig
mips fuloong2e_defconfig
ia64 tiger_defconfig
csky alldefconfig
csky defconfig
sh espt_defconfig
arm lubbock_defconfig
arm simpad_defconfig
sh kfr2r09-romimage_defconfig
x86_64 defconfig
riscv nommu_k210_sdcard_defconfig
powerpc cell_defconfig
powerpc holly_defconfig
xtensa defconfig
arm mps2_defconfig
arm collie_defconfig
sh edosk7705_defconfig
um i386_defconfig
arm aspeed_g5_defconfig
m68k amcore_defconfig
ia64 allyesconfig
sh sh03_defconfig
mips loongson1c_defconfig
powerpc currituck_defconfig
powerpc ksi8560_defconfig
xtensa nommu_kc705_defconfig
powerpc tqm8xx_defconfig
powerpc mpc866_ads_defconfig
arm s3c6400_defconfig
powerpc ppc6xx_defconfig
powerpc tqm8560_defconfig
mips decstation_defconfig
mips db1xxx_defconfig
sh sh7763rdp_defconfig
arm pxa910_defconfig
mips mtx1_defconfig
parisc generic-64bit_defconfig
powerpc asp8347_defconfig
arm stm32_defconfig
arm magician_defconfig
arm assabet_defconfig
h8300 alldefconfig
mips tb0287_defconfig
powerpc64 defconfig
powerpc acadia_defconfig
arm versatile_defconfig
arm dove_defconfig
arm randconfig-c002-20211117
ia64 allmodconfig
m68k allmodconfig
m68k defconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
nds32 defconfig
nios2 allyesconfig
alpha allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
s390 allyesconfig
parisc allyesconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
sparc defconfig
i386 debian-10.3
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
powerpc allnoconfig
x86_64 randconfig-a005-20211117
x86_64 randconfig-a003-20211117
x86_64 randconfig-a002-20211117
x86_64 randconfig-a001-20211117
x86_64 randconfig-a006-20211117
x86_64 randconfig-a004-20211117
i386 randconfig-a006-20211117
i386 randconfig-a003-20211117
i386 randconfig-a005-20211117
i386 randconfig-a001-20211117
i386 randconfig-a004-20211117
i386 randconfig-a002-20211117
riscv nommu_k210_defconfig
riscv allyesconfig
riscv nommu_virt_defconfig
riscv allnoconfig
riscv defconfig
riscv rv32_defconfig
riscv allmodconfig
x86_64 rhel-8.3-kselftests
x86_64 allyesconfig
x86_64 rhel-8.3
x86_64 rhel-8.3-func
x86_64 kexec
clang tested configs:
x86_64 randconfig-c007-20211117
i386 randconfig-c001-20211117
arm randconfig-c002-20211117
riscv randconfig-c006-20211117
powerpc randconfig-c003-20211117
s390 randconfig-c005-20211117
mips randconfig-c004-20211117
x86_64 randconfig-a015-20211117
x86_64 randconfig-a013-20211117
x86_64 randconfig-a011-20211117
x86_64 randconfig-a012-20211117
x86_64 randconfig-a016-20211117
x86_64 randconfig-a014-20211117
i386 randconfig-a014-20211117
i386 randconfig-a016-20211117
i386 randconfig-a012-20211117
i386 randconfig-a013-20211117
i386 randconfig-a011-20211117
i386 randconfig-a015-20211117
hexagon randconfig-r045-20211117
hexagon randconfig-r041-20211117
s390 randconfig-r044-20211117
riscv randconfig-r042-20211117
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* [powerpc:next-test] BUILD SUCCESS 5d12a44d97850aacfc86a4817ca304fc33876476
From: kernel test robot @ 2021-11-18 0:34 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next-test
branch HEAD: 5d12a44d97850aacfc86a4817ca304fc33876476 powerpc/rtas: rtas_busy_delay_time() kernel-doc
elapsed time: 726m
configs tested: 189
configs skipped: 3
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
i386 randconfig-c001-20211117
powerpc randconfig-c003-20211117
sh ecovec24-romimage_defconfig
m68k multi_defconfig
powerpc mpc85xx_cds_defconfig
arm jornada720_defconfig
sh rsk7269_defconfig
riscv alldefconfig
alpha defconfig
powerpc stx_gp3_defconfig
arc nsimosci_hs_defconfig
powerpc mpc5200_defconfig
powerpc amigaone_defconfig
powerpc adder875_defconfig
arm iop32x_defconfig
m68k mac_defconfig
sh se7343_defconfig
powerpc pasemi_defconfig
mips jazz_defconfig
mips malta_qemu_32r6_defconfig
sparc sparc64_defconfig
i386 defconfig
ia64 defconfig
sh apsh4a3a_defconfig
arm ep93xx_defconfig
mips ath79_defconfig
sh ecovec24_defconfig
i386 alldefconfig
mips capcella_defconfig
powerpc tqm8555_defconfig
arm ezx_defconfig
powerpc mpc885_ads_defconfig
powerpc ge_imp3a_defconfig
um x86_64_defconfig
sh secureedge5410_defconfig
s390 allmodconfig
mips loongson3_defconfig
sh sh7724_generic_defconfig
mips malta_kvm_defconfig
powerpc mpc832x_mds_defconfig
h8300 h8300h-sim_defconfig
m68k sun3_defconfig
sh lboxre2_defconfig
xtensa allyesconfig
arm moxart_defconfig
arm keystone_defconfig
mips bcm47xx_defconfig
alpha alldefconfig
xtensa common_defconfig
mips ci20_defconfig
arm sunxi_defconfig
mips sb1250_swarm_defconfig
powerpc akebono_defconfig
powerpc chrp32_defconfig
powerpc mpc7448_hpc2_defconfig
sh ul2_defconfig
powerpc socrates_defconfig
m68k atari_defconfig
mips bmips_stb_defconfig
sh se7724_defconfig
arm mmp2_defconfig
powerpc wii_defconfig
arm lpc32xx_defconfig
powerpc cm5200_defconfig
arm mvebu_v7_defconfig
arm exynos_defconfig
mips fuloong2e_defconfig
ia64 tiger_defconfig
csky alldefconfig
csky defconfig
sh espt_defconfig
arm lubbock_defconfig
arm simpad_defconfig
sh kfr2r09-romimage_defconfig
x86_64 defconfig
riscv nommu_k210_sdcard_defconfig
powerpc cell_defconfig
powerpc holly_defconfig
xtensa defconfig
arm mps2_defconfig
arm collie_defconfig
sh edosk7705_defconfig
um i386_defconfig
arm aspeed_g5_defconfig
m68k amcore_defconfig
ia64 allyesconfig
sh sh03_defconfig
mips loongson1c_defconfig
powerpc currituck_defconfig
powerpc ksi8560_defconfig
xtensa nommu_kc705_defconfig
powerpc tqm8xx_defconfig
powerpc mpc866_ads_defconfig
arm s3c6400_defconfig
powerpc ppc6xx_defconfig
powerpc tqm8560_defconfig
mips decstation_defconfig
mips db1xxx_defconfig
sh sh7763rdp_defconfig
arm pxa910_defconfig
mips mtx1_defconfig
parisc generic-64bit_defconfig
powerpc asp8347_defconfig
arm stm32_defconfig
arm magician_defconfig
arm assabet_defconfig
h8300 alldefconfig
mips tb0287_defconfig
powerpc64 defconfig
powerpc acadia_defconfig
arm versatile_defconfig
arm dove_defconfig
arm randconfig-c002-20211117
ia64 allmodconfig
m68k allmodconfig
m68k defconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
nds32 defconfig
nios2 allyesconfig
alpha allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
s390 allyesconfig
parisc allyesconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
sparc defconfig
i386 debian-10.3
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
powerpc allnoconfig
x86_64 randconfig-a005-20211117
x86_64 randconfig-a003-20211117
x86_64 randconfig-a002-20211117
x86_64 randconfig-a001-20211117
x86_64 randconfig-a006-20211117
x86_64 randconfig-a004-20211117
i386 randconfig-a006-20211117
i386 randconfig-a003-20211117
i386 randconfig-a005-20211117
i386 randconfig-a001-20211117
i386 randconfig-a004-20211117
i386 randconfig-a002-20211117
arc randconfig-r043-20211117
riscv nommu_k210_defconfig
riscv allyesconfig
riscv nommu_virt_defconfig
riscv allnoconfig
riscv defconfig
riscv rv32_defconfig
riscv allmodconfig
x86_64 rhel-8.3-kselftests
x86_64 allyesconfig
x86_64 rhel-8.3
x86_64 rhel-8.3-func
x86_64 kexec
clang tested configs:
x86_64 randconfig-c007-20211117
i386 randconfig-c001-20211117
arm randconfig-c002-20211117
riscv randconfig-c006-20211117
powerpc randconfig-c003-20211117
s390 randconfig-c005-20211117
mips randconfig-c004-20211117
x86_64 randconfig-a015-20211117
x86_64 randconfig-a013-20211117
x86_64 randconfig-a011-20211117
x86_64 randconfig-a012-20211117
x86_64 randconfig-a016-20211117
x86_64 randconfig-a014-20211117
i386 randconfig-a014-20211117
i386 randconfig-a016-20211117
i386 randconfig-a012-20211117
i386 randconfig-a013-20211117
i386 randconfig-a011-20211117
i386 randconfig-a015-20211117
hexagon randconfig-r045-20211117
hexagon randconfig-r041-20211117
s390 randconfig-r044-20211117
riscv randconfig-r042-20211117
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* [PATCH] powerpc/microwatt: Make microwatt_get_random_darn() static
From: Michael Ellerman @ 2021-11-18 0:44 UTC (permalink / raw)
To: linuxppc-dev
Make microwatt_get_random_darn() static, because it can be.
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/platforms/microwatt/rng.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Report: https://lore.kernel.org/lkml/202111120545.dtEw8pTr-lkp@intel.com/
diff --git a/arch/powerpc/platforms/microwatt/rng.c b/arch/powerpc/platforms/microwatt/rng.c
index 3d8ee6eb7dad..7bc4d1cbfaf0 100644
--- a/arch/powerpc/platforms/microwatt/rng.c
+++ b/arch/powerpc/platforms/microwatt/rng.c
@@ -14,7 +14,7 @@
#define DARN_ERR 0xFFFFFFFFFFFFFFFFul
-int microwatt_get_random_darn(unsigned long *v)
+static int microwatt_get_random_darn(unsigned long *v)
{
unsigned long val;
--
2.31.1
^ permalink raw reply related
* Re: [RESEND PATCH v2 1/3] fixup mmu_features immediately after getting cpu pa features.
From: Sourabh Jain @ 2021-11-18 6:12 UTC (permalink / raw)
To: linuxppc-dev, Michael Ellerman
In-Reply-To: <20211018084434.217772-2-sourabhjain@linux.ibm.com>
Hi MPE,
Any comments or suggestion on list patch series?
Thanks,
Sourabh Jain
On 18/10/21 14:14, Sourabh Jain wrote:
> From: Mahesh Salgaonkar <mahesh@linux.ibm.com>
>
> On system with radix support available, early_radix_enabled() starts
> returning true for a small window (until mmu_early_init_devtree() is
> called) even when radix mode disabled on kernel command line. This causes
> ppc64_bolted_size() to return ULONG_MAX in HPT mode instead of supported
> segment size, during boot cpu paca allocation.
>
> Withi kernel command line = "... disable_radix":
>
> early_init_devtree: <- early_radix_enabled() = false
> early_init_dt_scan_cpus: <- early_radix_enabled() = false
> ...
> check_cpu_pa_features: <- early_radix_enabled() = false
> ... ^ <- early_radix_enabled() = TRUE
> allocate_paca: | <- early_radix_enabled() = TRUE
> ... |
> ppc64_bolted_size: | <- early_radix_enabled() = TRUE
> if (early_radix_enabled())| <- early_radix_enabled() = TRUE
> return ULONG_MAX; |
> ... |
> ... | <- early_radix_enabled() = TRUE
> ... | <- early_radix_enabled() = TRUE
> mmu_early_init_devtree() V
> ... <- early_radix_enabled() = false
>
> So far we have not seen any issue because allocate_paca() takes minimum of
> ppc64_bolted_size and rma_size while allocating paca. However it is better
> to close this window by fixing up the mmu features as early as possible.
> This fixes early_radix_enabled() and ppc64_bolted_size() to return valid
> values in radix disable mode. This patch will help subsequent patch to
> depend on early_radix_enabled() check while detecting supported segment
> size in HPT mode.
>
> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> Reported-and-tested-by: Abdul haleem <abdhalee@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/book3s/64/mmu.h | 1 +
> arch/powerpc/include/asm/mmu.h | 1 +
> arch/powerpc/kernel/prom.c | 2 ++
> arch/powerpc/mm/init_64.c | 5 ++++-
> 4 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
> index c02f42d1031e..d60be5051d60 100644
> --- a/arch/powerpc/include/asm/book3s/64/mmu.h
> +++ b/arch/powerpc/include/asm/book3s/64/mmu.h
> @@ -197,6 +197,7 @@ extern int mmu_vmemmap_psize;
> extern int mmu_io_psize;
>
> /* MMU initialization */
> +void update_cpu_features(void);
> void mmu_early_init_devtree(void);
> void hash__early_init_devtree(void);
> void radix__early_init_devtree(void);
> diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
> index 8abe8e42e045..5eb494ea85d7 100644
> --- a/arch/powerpc/include/asm/mmu.h
> +++ b/arch/powerpc/include/asm/mmu.h
> @@ -401,6 +401,7 @@ extern void early_init_mmu(void);
> extern void early_init_mmu_secondary(void);
> extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
> phys_addr_t first_memblock_size);
> +static inline void update_cpu_features(void) { }
> static inline void mmu_early_init_devtree(void) { }
>
> static inline void pkey_early_init_devtree(void) {}
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 2e67588f6f6e..889c909e4ed4 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -380,6 +380,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
> check_cpu_pa_features(node);
> }
>
> + /* Update cpu features based on kernel command line */
> + update_cpu_features();
> identical_pvr_fixup(node);
> init_mmu_slb_size(node);
>
> diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
> index 386be136026e..19680b42898f 100644
> --- a/arch/powerpc/mm/init_64.c
> +++ b/arch/powerpc/mm/init_64.c
> @@ -437,12 +437,15 @@ static void __init early_check_vec5(void)
> }
> }
>
> -void __init mmu_early_init_devtree(void)
> +void __init update_cpu_features(void)
> {
> /* Disable radix mode based on kernel command line. */
> if (disable_radix)
> cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX;
> +}
>
> +void __init mmu_early_init_devtree(void)
> +{
> /*
> * Check /chosen/ibm,architecture-vec-5 if running as a guest.
> * When running bare-metal, we can use radix if we like
^ permalink raw reply
* Re: [PATCH 04/11] powerpc/xive: Introduce xive_core_debugfs_create()
From: Michael Ellerman @ 2021-11-18 9:21 UTC (permalink / raw)
To: Cédric Le Goater, linuxppc-dev; +Cc: Cédric Le Goater
In-Reply-To: <20211105102636.1016378-5-clg@kaod.org>
Cédric Le Goater <clg@kaod.org> writes:
> and fix some compile issues when !CONFIG_DEBUG_FS.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
> arch/powerpc/sysdev/xive/common.c | 17 ++++++++++++++---
> 1 file changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
> index 3d558cad1f19..b71cc1020296 100644
> --- a/arch/powerpc/sysdev/xive/common.c
> +++ b/arch/powerpc/sysdev/xive/common.c
...
> @@ -1779,10 +1782,18 @@ static int xive_core_debug_show(struct seq_file *m, void *private)
> }
> DEFINE_SHOW_ATTRIBUTE(xive_core_debug);
>
> +static void xive_core_debugfs_create(void)
> +{
> + debugfs_create_file("xive", 0400, arch_debugfs_dir,
> + NULL, &xive_core_debug_fops);
> +}
> +
> +#endif /* CONFIG_DEBUG_FS */
> +
> int xive_core_debug_init(void)
> {
> - if (xive_enabled())
> - debugfs_create_file("xive", 0400, arch_debugfs_dir,
> - NULL, &xive_core_debug_fops);
> + if (xive_enabled() && IS_ENABLED(CONFIG_DEBUG_FS))
> + xive_core_debugfs_create();
> +
> return 0;
> }
For skiroot_defconfig this gives me:
arch/powerpc/sysdev/xive/common.c: In function ‘xive_core_init’:
arch/powerpc/sysdev/xive/common.c:1676:2: error: implicit declaration of function ‘xive_core_debugfs_create’; did you mean ‘xive_core_debug_init’? [-Werror=implicit-function-declaration]
1676 | xive_core_debugfs_create();
| ^~~~~~~~~~~~~~~~~~~~~~~~
| xive_core_debug_init
cc1: all warnings being treated as errors
We need an empty inline stub of xive_core_debugfs_create() for the
CONFIG_DEBUG_FS=n case.
I'm wondering though why do we have xive_core_debug_init() at all, why
don't we just initialise the debugfs files in xive_core_init()?
cheers
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox