Commit 493804a6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more kvm updates from Paolo Bonzini:
 "This includes the 6.4 changes for RISC-V, and a few bugfix patches for
  other architectures. For x86, this closes a longstanding performance
  issue in the newer and (usually) more scalable page table management
  code.

  RISC-V:
   - ONE_REG interface to enable/disable SBI extensions
   - Zbb extension for Guest/VM
   - AIA CSR virtualization

  x86:
   - Fix a long-standing TDP MMU flaw, where unloading roots on a vCPU
     can result in the root being freed even though the root is
     completely valid and can be reused as-is (with a TLB flush).

  s390:
   - A couple of bugfixes"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: s390: fix race in gmap_make_secure()
  KVM: s390: pv: fix asynchronous teardown for small VMs
  KVM: x86: Preserve TDP MMU roots until they are explicitly invalidated
  RISC-V: KVM: Virtualize per-HART AIA CSRs
  RISC-V: KVM: Use bitmap for irqs_pending and irqs_pending_mask
  RISC-V: KVM: Add ONE_REG interface for AIA CSRs
  RISC-V: KVM: Implement subtype for CSR ONE_REG interface
  RISC-V: KVM: Initial skeletal support for AIA
  RISC-V: KVM: Drop the _MASK suffix from hgatp.VMID mask defines
  RISC-V: Detect AIA CSRs from ISA string
  RISC-V: Add AIA related CSR defines
  RISC-V: KVM: Allow Zbb extension for Guest/VM
  RISC-V: KVM: Add ONE_REG interface to enable/disable SBI extensions
  RISC-V: KVM: Alphabetize selects
  KVM: RISC-V: Retry fault if vma_lookup() results become invalid
parents 7163a211 7a8016d9
Loading
Loading
Loading
Loading
+100 −7
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
#define _ASM_RISCV_CSR_H

#include <asm/asm.h>
#include <linux/const.h>
#include <linux/bits.h>

/* Status register flags */
#define SR_SIE		_AC(0x00000002, UL) /* Supervisor Interrupt Enable */
@@ -72,7 +72,10 @@
#define IRQ_S_EXT		9
#define IRQ_VS_EXT		10
#define IRQ_M_EXT		11
#define IRQ_S_GEXT		12
#define IRQ_PMU_OVF		13
#define IRQ_LOCAL_MAX		(IRQ_PMU_OVF + 1)
#define IRQ_LOCAL_MASK		GENMASK((IRQ_LOCAL_MAX - 1), 0)

/* Exception causes */
#define EXC_INST_MISALIGNED	0
@@ -127,25 +130,25 @@

#define HGATP32_MODE_SHIFT	31
#define HGATP32_VMID_SHIFT	22
#define HGATP32_VMID_MASK	_AC(0x1FC00000, UL)
#define HGATP32_PPN		_AC(0x003FFFFF, UL)
#define HGATP32_VMID		GENMASK(28, 22)
#define HGATP32_PPN		GENMASK(21, 0)

#define HGATP64_MODE_SHIFT	60
#define HGATP64_VMID_SHIFT	44
#define HGATP64_VMID_MASK	_AC(0x03FFF00000000000, UL)
#define HGATP64_PPN		_AC(0x00000FFFFFFFFFFF, UL)
#define HGATP64_VMID		GENMASK(57, 44)
#define HGATP64_PPN		GENMASK(43, 0)

#define HGATP_PAGE_SHIFT	12

#ifdef CONFIG_64BIT
#define HGATP_PPN		HGATP64_PPN
#define HGATP_VMID_SHIFT	HGATP64_VMID_SHIFT
#define HGATP_VMID_MASK		HGATP64_VMID_MASK
#define HGATP_VMID		HGATP64_VMID
#define HGATP_MODE_SHIFT	HGATP64_MODE_SHIFT
#else
#define HGATP_PPN		HGATP32_PPN
#define HGATP_VMID_SHIFT	HGATP32_VMID_SHIFT
#define HGATP_VMID_MASK		HGATP32_VMID_MASK
#define HGATP_VMID		HGATP32_VMID
#define HGATP_MODE_SHIFT	HGATP32_MODE_SHIFT
#endif

@@ -155,6 +158,27 @@
				 (_AC(1, UL) << IRQ_S_TIMER) | \
				 (_AC(1, UL) << IRQ_S_EXT))

/* AIA CSR bits */
#define TOPI_IID_SHIFT		16
#define TOPI_IID_MASK		GENMASK(11, 0)
#define TOPI_IPRIO_MASK		GENMASK(7, 0)
#define TOPI_IPRIO_BITS		8

#define TOPEI_ID_SHIFT		16
#define TOPEI_ID_MASK		GENMASK(10, 0)
#define TOPEI_PRIO_MASK		GENMASK(10, 0)

#define ISELECT_IPRIO0		0x30
#define ISELECT_IPRIO15		0x3f
#define ISELECT_MASK		GENMASK(8, 0)

#define HVICTL_VTI		BIT(30)
#define HVICTL_IID		GENMASK(27, 16)
#define HVICTL_IID_SHIFT	16
#define HVICTL_DPR		BIT(9)
#define HVICTL_IPRIOM		BIT(8)
#define HVICTL_IPRIO		GENMASK(7, 0)

/* xENVCFG flags */
#define ENVCFG_STCE			(_AC(1, ULL) << 63)
#define ENVCFG_PBMTE			(_AC(1, ULL) << 62)
@@ -249,6 +273,18 @@
#define CSR_STIMECMP		0x14D
#define CSR_STIMECMPH		0x15D

/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
#define CSR_SISELECT		0x150
#define CSR_SIREG		0x151

/* Supervisor-Level Interrupts (AIA) */
#define CSR_STOPEI		0x15c
#define CSR_STOPI		0xdb0

/* Supervisor-Level High-Half CSRs (AIA) */
#define CSR_SIEH		0x114
#define CSR_SIPH		0x154

#define CSR_VSSTATUS		0x200
#define CSR_VSIE		0x204
#define CSR_VSTVEC		0x205
@@ -278,8 +314,32 @@
#define CSR_HGATP		0x680
#define CSR_HGEIP		0xe12

/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
#define CSR_HVIEN		0x608
#define CSR_HVICTL		0x609
#define CSR_HVIPRIO1		0x646
#define CSR_HVIPRIO2		0x647

/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */
#define CSR_VSISELECT		0x250
#define CSR_VSIREG		0x251

/* VS-Level Interrupts (H-extension with AIA) */
#define CSR_VSTOPEI		0x25c
#define CSR_VSTOPI		0xeb0

/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
#define CSR_HIDELEGH		0x613
#define CSR_HVIENH		0x618
#define CSR_HVIPH		0x655
#define CSR_HVIPRIO1H		0x656
#define CSR_HVIPRIO2H		0x657
#define CSR_VSIEH		0x214
#define CSR_VSIPH		0x254

#define CSR_MSTATUS		0x300
#define CSR_MISA		0x301
#define CSR_MIDELEG		0x303
#define CSR_MIE			0x304
#define CSR_MTVEC		0x305
#define CSR_MENVCFG		0x30a
@@ -296,6 +356,25 @@
#define CSR_MIMPID		0xf13
#define CSR_MHARTID		0xf14

/* Machine-Level Window to Indirectly Accessed Registers (AIA) */
#define CSR_MISELECT		0x350
#define CSR_MIREG		0x351

/* Machine-Level Interrupts (AIA) */
#define CSR_MTOPEI		0x35c
#define CSR_MTOPI		0xfb0

/* Virtual Interrupts for Supervisor Level (AIA) */
#define CSR_MVIEN		0x308
#define CSR_MVIP		0x309

/* Machine-Level High-Half CSRs (AIA) */
#define CSR_MIDELEGH		0x313
#define CSR_MIEH		0x314
#define CSR_MVIENH		0x318
#define CSR_MVIPH		0x319
#define CSR_MIPH		0x354

#ifdef CONFIG_RISCV_M_MODE
# define CSR_STATUS	CSR_MSTATUS
# define CSR_IE		CSR_MIE
@@ -306,6 +385,13 @@
# define CSR_TVAL	CSR_MTVAL
# define CSR_IP		CSR_MIP

# define CSR_IEH		CSR_MIEH
# define CSR_ISELECT	CSR_MISELECT
# define CSR_IREG	CSR_MIREG
# define CSR_IPH		CSR_MIPH
# define CSR_TOPEI	CSR_MTOPEI
# define CSR_TOPI	CSR_MTOPI

# define SR_IE		SR_MIE
# define SR_PIE		SR_MPIE
# define SR_PP		SR_MPP
@@ -323,6 +409,13 @@
# define CSR_TVAL	CSR_STVAL
# define CSR_IP		CSR_SIP

# define CSR_IEH		CSR_SIEH
# define CSR_ISELECT	CSR_SISELECT
# define CSR_IREG	CSR_SIREG
# define CSR_IPH		CSR_SIPH
# define CSR_TOPEI	CSR_STOPEI
# define CSR_TOPI	CSR_STOPI

# define SR_IE		SR_SIE
# define SR_PIE		SR_SPIE
# define SR_PP		SR_SPP
+8 −0
Original line number Diff line number Diff line
@@ -44,10 +44,18 @@
#define RISCV_ISA_EXT_ZIHINTPAUSE	32
#define RISCV_ISA_EXT_SVNAPOT		33
#define RISCV_ISA_EXT_ZICBOZ		34
#define RISCV_ISA_EXT_SMAIA		35
#define RISCV_ISA_EXT_SSAIA		36

#define RISCV_ISA_EXT_MAX		64
#define RISCV_ISA_EXT_NAME_LEN_MAX	32

#ifdef CONFIG_RISCV_M_MODE
#define RISCV_ISA_EXT_SxAIA		RISCV_ISA_EXT_SMAIA
#else
#define RISCV_ISA_EXT_SxAIA		RISCV_ISA_EXT_SSAIA
#endif

#ifndef __ASSEMBLY__

#include <linux/jump_label.h>
+127 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2021 Western Digital Corporation or its affiliates.
 * Copyright (C) 2022 Ventana Micro Systems Inc.
 *
 * Authors:
 *	Anup Patel <apatel@ventanamicro.com>
 */

#ifndef __KVM_RISCV_AIA_H
#define __KVM_RISCV_AIA_H

#include <linux/jump_label.h>
#include <linux/kvm_types.h>
#include <asm/csr.h>

struct kvm_aia {
	/* In-kernel irqchip created */
	bool		in_kernel;

	/* In-kernel irqchip initialized */
	bool		initialized;
};

struct kvm_vcpu_aia_csr {
	unsigned long vsiselect;
	unsigned long hviprio1;
	unsigned long hviprio2;
	unsigned long vsieh;
	unsigned long hviph;
	unsigned long hviprio1h;
	unsigned long hviprio2h;
};

struct kvm_vcpu_aia {
	/* CPU AIA CSR context of Guest VCPU */
	struct kvm_vcpu_aia_csr guest_csr;

	/* CPU AIA CSR context upon Guest VCPU reset */
	struct kvm_vcpu_aia_csr guest_reset_csr;
};

#define kvm_riscv_aia_initialized(k)	((k)->arch.aia.initialized)

#define irqchip_in_kernel(k)		((k)->arch.aia.in_kernel)

DECLARE_STATIC_KEY_FALSE(kvm_riscv_aia_available);
#define kvm_riscv_aia_available() \
	static_branch_unlikely(&kvm_riscv_aia_available)

#define KVM_RISCV_AIA_IMSIC_TOPEI	(ISELECT_MASK + 1)
static inline int kvm_riscv_vcpu_aia_imsic_rmw(struct kvm_vcpu *vcpu,
					       unsigned long isel,
					       unsigned long *val,
					       unsigned long new_val,
					       unsigned long wr_mask)
{
	return 0;
}

#ifdef CONFIG_32BIT
void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu);
#else
static inline void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)
{
}
static inline void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
{
}
#endif
bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask);

void kvm_riscv_vcpu_aia_update_hvip(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_aia_load(struct kvm_vcpu *vcpu, int cpu);
void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu);
int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
			       unsigned long reg_num,
			       unsigned long *out_val);
int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
			       unsigned long reg_num,
			       unsigned long val);

int kvm_riscv_vcpu_aia_rmw_topei(struct kvm_vcpu *vcpu,
				 unsigned int csr_num,
				 unsigned long *val,
				 unsigned long new_val,
				 unsigned long wr_mask);
int kvm_riscv_vcpu_aia_rmw_ireg(struct kvm_vcpu *vcpu, unsigned int csr_num,
				unsigned long *val, unsigned long new_val,
				unsigned long wr_mask);
#define KVM_RISCV_VCPU_AIA_CSR_FUNCS \
{ .base = CSR_SIREG,      .count = 1, .func = kvm_riscv_vcpu_aia_rmw_ireg }, \
{ .base = CSR_STOPEI,     .count = 1, .func = kvm_riscv_vcpu_aia_rmw_topei },

static inline int kvm_riscv_vcpu_aia_update(struct kvm_vcpu *vcpu)
{
	return 1;
}

static inline void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu)
{
}

static inline int kvm_riscv_vcpu_aia_init(struct kvm_vcpu *vcpu)
{
	return 0;
}

static inline void kvm_riscv_vcpu_aia_deinit(struct kvm_vcpu *vcpu)
{
}

static inline void kvm_riscv_aia_init_vm(struct kvm *kvm)
{
}

static inline void kvm_riscv_aia_destroy_vm(struct kvm *kvm)
{
}

void kvm_riscv_aia_enable(void);
void kvm_riscv_aia_disable(void);
int kvm_riscv_aia_init(void);
void kvm_riscv_aia_exit(void);

#endif
+11 −3
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/kvm_types.h>
#include <linux/spinlock.h>
#include <asm/hwcap.h>
#include <asm/kvm_aia.h>
#include <asm/kvm_vcpu_fp.h>
#include <asm/kvm_vcpu_insn.h>
#include <asm/kvm_vcpu_sbi.h>
@@ -94,6 +95,9 @@ struct kvm_arch {

	/* Guest Timer */
	struct kvm_guest_timer timer;

	/* AIA Guest/VM context */
	struct kvm_aia aia;
};

struct kvm_cpu_trap {
@@ -200,8 +204,9 @@ struct kvm_vcpu_arch {
	 * in irqs_pending. Our approach is modeled around multiple producer
	 * and single consumer problem where the consumer is the VCPU itself.
	 */
	unsigned long irqs_pending;
	unsigned long irqs_pending_mask;
#define KVM_RISCV_VCPU_NR_IRQS	64
	DECLARE_BITMAP(irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
	DECLARE_BITMAP(irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);

	/* VCPU Timer */
	struct kvm_vcpu_timer timer;
@@ -221,6 +226,9 @@ struct kvm_vcpu_arch {
	/* SBI context */
	struct kvm_vcpu_sbi_context sbi_context;

	/* AIA VCPU context */
	struct kvm_vcpu_aia aia_context;

	/* Cache pages needed to program page tables with spinlock held */
	struct kvm_mmu_memory_cache mmu_page_cache;

@@ -327,7 +335,7 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq);
int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq);
void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu);
bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, unsigned long mask);
bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, u64 mask);
void kvm_riscv_vcpu_power_off(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_power_on(struct kvm_vcpu *vcpu);

+7 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

struct kvm_vcpu_sbi_context {
	int return_handled;
	bool extension_disabled[KVM_RISCV_SBI_EXT_MAX];
};

struct kvm_vcpu_sbi_return {
@@ -45,7 +46,12 @@ void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
				     struct kvm_run *run,
				     u32 type, u64 flags);
int kvm_riscv_vcpu_sbi_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(unsigned long extid);
int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
				   const struct kvm_one_reg *reg);
int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
				   const struct kvm_one_reg *reg);
const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
				struct kvm_vcpu *vcpu, unsigned long extid);
int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);

#ifdef CONFIG_RISCV_SBI_V01
Loading