Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Browse files Browse the repository at this point in the history
Pull kvm fixes from Paolo Bonzini:
"RISC-V:

   - Fix a race condition in updating external interrupt for
     trap-n-emulated IMSIC swfile

   - Fix print_reg defaults in get-reg-list selftest

  ARM:

   - Ensure a vCPU's redistributor is unregistered from the MMIO bus if
     vCPU creation fails

   - Fix building KVM selftests for arm64 from the top-level Makefile

  x86:

   - Fix breakage for SEV-ES guests that use XSAVES

  Selftests:

   - Fix bad use of strcat(), by not using strcat() at all"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: SEV: Do not intercept accesses to MSR_IA32_XSS for SEV-ES guests
  KVM: selftests: Fix dynamic generation of configuration names
  RISCV: KVM: update external interrupt atomically for IMSIC swfile
  KVM: riscv: selftests: Fix get-reg-list print_reg defaults
  KVM: selftests: Ensure sysreg-defs.h is generated at the expected path
  KVM: Convert comment into an assertion in kvm_io_bus_register_dev()
  KVM: arm64: vgic: Ensure that slots_lock is held in vgic_register_all_redist_iodevs()
  KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy
  KVM: arm64: vgic: Add a non-locking primitive for kvm_vgic_vcpu_destroy()
  KVM: arm64: vgic: Simplify kvm_vgic_destroy()
  • Loading branch information
Linus Torvalds committed Dec 23, 2023
2 parents c0f65a7 + ef5b283 commit 867583b
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 40 deletions.
2 changes: 1 addition & 1 deletion arch/arm64/kvm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
kvm_timer_vcpu_terminate(vcpu);
kvm_pmu_vcpu_destroy(vcpu);

kvm_vgic_vcpu_destroy(vcpu);
kvm_arm_vcpu_destroy(vcpu);
}

Expand Down
47 changes: 29 additions & 18 deletions arch/arm64/kvm/vgic/vgic-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
vgic_v4_teardown(kvm);
}

void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
static void __kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;

Expand All @@ -379,29 +379,39 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
vgic_flush_pending_lpis(vcpu);

INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
vgic_unregister_redist_iodev(vcpu);
vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
}
}

static void __kvm_vgic_destroy(struct kvm *kvm)
void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;

mutex_lock(&kvm->slots_lock);
__kvm_vgic_vcpu_destroy(vcpu);
mutex_unlock(&kvm->slots_lock);
}

void kvm_vgic_destroy(struct kvm *kvm)
{
struct kvm_vcpu *vcpu;
unsigned long i;

lockdep_assert_held(&kvm->arch.config_lock);
mutex_lock(&kvm->slots_lock);

vgic_debug_destroy(kvm);

kvm_for_each_vcpu(i, vcpu, kvm)
kvm_vgic_vcpu_destroy(vcpu);
__kvm_vgic_vcpu_destroy(vcpu);

mutex_lock(&kvm->arch.config_lock);

kvm_vgic_dist_destroy(kvm);
}

void kvm_vgic_destroy(struct kvm *kvm)
{
mutex_lock(&kvm->arch.config_lock);
__kvm_vgic_destroy(kvm);
mutex_unlock(&kvm->arch.config_lock);
mutex_unlock(&kvm->slots_lock);
}

/**
Expand Down Expand Up @@ -469,25 +479,26 @@ int kvm_vgic_map_resources(struct kvm *kvm)
type = VGIC_V3;
}

if (ret) {
__kvm_vgic_destroy(kvm);
if (ret)
goto out;
}

dist->ready = true;
dist_base = dist->vgic_dist_base;
mutex_unlock(&kvm->arch.config_lock);

ret = vgic_register_dist_iodev(kvm, dist_base, type);
if (ret) {
if (ret)
kvm_err("Unable to register VGIC dist MMIO regions\n");
kvm_vgic_destroy(kvm);
}
mutex_unlock(&kvm->slots_lock);
return ret;

goto out_slots;
out:
mutex_unlock(&kvm->arch.config_lock);
out_slots:
mutex_unlock(&kvm->slots_lock);

if (ret)
kvm_vgic_destroy(kvm);

return ret;
}

Expand Down
4 changes: 3 additions & 1 deletion arch/arm64/kvm/vgic/vgic-mmio-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
return ret;
}

static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
{
struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;

Expand All @@ -833,6 +833,8 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
unsigned long c;
int ret = 0;

lockdep_assert_held(&kvm->slots_lock);

kvm_for_each_vcpu(c, vcpu, kvm) {
ret = vgic_register_redist_iodev(vcpu);
if (ret)
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/kvm/vgic/vgic.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq);
int vgic_v3_save_pending_tables(struct kvm *kvm);
int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count);
int vgic_register_redist_iodev(struct kvm_vcpu *vcpu);
void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu);
bool vgic_v3_check_base(struct kvm *kvm);

void vgic_v3_load(struct kvm_vcpu *vcpu);
Expand Down
13 changes: 13 additions & 0 deletions arch/riscv/kvm/aia_imsic.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct imsic {
/* IMSIC SW-file */
struct imsic_mrif *swfile;
phys_addr_t swfile_pa;
spinlock_t swfile_extirq_lock;
};

#define imsic_vs_csr_read(__c) \
Expand Down Expand Up @@ -613,12 +614,23 @@ static void imsic_swfile_extirq_update(struct kvm_vcpu *vcpu)
{
struct imsic *imsic = vcpu->arch.aia_context.imsic_state;
struct imsic_mrif *mrif = imsic->swfile;
unsigned long flags;

/*
* The critical section is necessary during external interrupt
* updates to avoid the risk of losing interrupts due to potential
* interruptions between reading topei and updating pending status.
*/

spin_lock_irqsave(&imsic->swfile_extirq_lock, flags);

if (imsic_mrif_atomic_read(mrif, &mrif->eidelivery) &&
imsic_mrif_topei(mrif, imsic->nr_eix, imsic->nr_msis))
kvm_riscv_vcpu_set_interrupt(vcpu, IRQ_VS_EXT);
else
kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_EXT);

spin_unlock_irqrestore(&imsic->swfile_extirq_lock, flags);
}

static void imsic_swfile_read(struct kvm_vcpu *vcpu, bool clear,
Expand Down Expand Up @@ -1039,6 +1051,7 @@ int kvm_riscv_vcpu_aia_imsic_init(struct kvm_vcpu *vcpu)
}
imsic->swfile = page_to_virt(swfile_page);
imsic->swfile_pa = page_to_phys(swfile_page);
spin_lock_init(&imsic->swfile_extirq_lock);

/* Setup IO device */
kvm_iodevice_init(&imsic->iodev, &imsic_iodoev_ops);
Expand Down
19 changes: 19 additions & 0 deletions arch/x86/kvm/svm/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2972,6 +2972,25 @@ static void sev_es_vcpu_after_set_cpuid(struct vcpu_svm *svm)

set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, v_tsc_aux, v_tsc_aux);
}

/*
* For SEV-ES, accesses to MSR_IA32_XSS should not be intercepted if
* the host/guest supports its use.
*
* guest_can_use() checks a number of requirements on the host/guest to
* ensure that MSR_IA32_XSS is available, but it might report true even
* if X86_FEATURE_XSAVES isn't configured in the guest to ensure host
* MSR_IA32_XSS is always properly restored. For SEV-ES, it is better
* to further check that the guest CPUID actually supports
* X86_FEATURE_XSAVES so that accesses to MSR_IA32_XSS by misbehaved
* guests will still get intercepted and caught in the normal
* kvm_emulate_rdmsr()/kvm_emulated_wrmsr() paths.
*/
if (guest_can_use(vcpu, X86_FEATURE_XSAVES) &&
guest_cpuid_has(vcpu, X86_FEATURE_XSAVES))
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_XSS, 1, 1);
else
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_XSS, 0, 0);
}

void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm)
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kvm/svm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ static const struct svm_direct_access_msrs {
{ .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
{ .index = MSR_IA32_LASTINTFROMIP, .always = false },
{ .index = MSR_IA32_LASTINTTOIP, .always = false },
{ .index = MSR_IA32_XSS, .always = false },
{ .index = MSR_EFER, .always = false },
{ .index = MSR_IA32_CR_PAT, .always = false },
{ .index = MSR_AMD64_SEV_ES_GHCB, .always = true },
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kvm/svm/svm.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#define IOPM_SIZE PAGE_SIZE * 3
#define MSRPM_SIZE PAGE_SIZE * 2

#define MAX_DIRECT_ACCESS_MSRS 46
#define MAX_DIRECT_ACCESS_MSRS 47
#define MSRPM_OFFSETS 32
extern u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
extern bool npt_enabled;
Expand Down
26 changes: 16 additions & 10 deletions tools/testing/selftests/kvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,6 @@ else
ARCH_DIR := $(ARCH)
endif

ifeq ($(ARCH),arm64)
tools_dir := $(top_srcdir)/tools
arm64_tools_dir := $(tools_dir)/arch/arm64/tools/
GEN_HDRS := $(top_srcdir)/tools/arch/arm64/include/generated/
CFLAGS += -I$(GEN_HDRS)

$(GEN_HDRS): $(wildcard $(arm64_tools_dir)/*)
$(MAKE) -C $(arm64_tools_dir) O=$(tools_dir)
endif

LIBKVM += lib/assert.c
LIBKVM += lib/elf.c
LIBKVM += lib/guest_modes.c
Expand Down Expand Up @@ -234,6 +224,22 @@ CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
ifeq ($(ARCH),s390)
CFLAGS += -march=z10
endif
ifeq ($(ARCH),arm64)
tools_dir := $(top_srcdir)/tools
arm64_tools_dir := $(tools_dir)/arch/arm64/tools/

ifneq ($(abs_objdir),)
arm64_hdr_outdir := $(abs_objdir)/tools/
else
arm64_hdr_outdir := $(tools_dir)/
endif

GEN_HDRS := $(arm64_hdr_outdir)arch/arm64/include/generated/
CFLAGS += -I$(GEN_HDRS)

$(GEN_HDRS): $(wildcard $(arm64_tools_dir)/*)
$(MAKE) -C $(arm64_tools_dir) OUTPUT=$(arm64_hdr_outdir)
endif

no-pie-option := $(call try-run, echo 'int main(void) { return 0; }' | \
$(CC) -Werror $(CFLAGS) -no-pie -x c - -o "$$TMP", -no-pie)
Expand Down
9 changes: 5 additions & 4 deletions tools/testing/selftests/kvm/get-reg-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ static const char *config_name(struct vcpu_reg_list *c)
for_each_sublist(c, s) {
if (!strcmp(s->name, "base"))
continue;
strcat(c->name + len, s->name);
len += strlen(s->name) + 1;
c->name[len - 1] = '+';
if (len)
c->name[len++] = '+';
strcpy(c->name + len, s->name);
len += strlen(s->name);
}
c->name[len - 1] = '\0';
c->name[len] = '\0';

return c->name;
}
Expand Down
10 changes: 6 additions & 4 deletions tools/testing/selftests/kvm/riscv/get-reg-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,9 @@ void print_reg(const char *prefix, __u64 id)
reg_size = "KVM_REG_SIZE_U128";
break;
default:
printf("\tKVM_REG_RISCV | (%lld << KVM_REG_SIZE_SHIFT) | 0x%llx /* UNKNOWN */,",
(id & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT, id & REG_MASK);
printf("\tKVM_REG_RISCV | (%lld << KVM_REG_SIZE_SHIFT) | 0x%llx /* UNKNOWN */,\n",
(id & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT, id & ~REG_MASK);
return;
}

switch (id & KVM_REG_RISCV_TYPE_MASK) {
Expand Down Expand Up @@ -496,8 +497,9 @@ void print_reg(const char *prefix, __u64 id)
reg_size, sbi_ext_id_to_str(prefix, id));
break;
default:
printf("\tKVM_REG_RISCV | %s | 0x%llx /* UNKNOWN */,",
reg_size, id & REG_MASK);
printf("\tKVM_REG_RISCV | %s | 0x%llx /* UNKNOWN */,\n",
reg_size, id & ~REG_MASK);
return;
}
}

Expand Down
3 changes: 2 additions & 1 deletion virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5540,14 +5540,15 @@ int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
return r < 0 ? r : 0;
}

/* Caller must hold slots_lock. */
int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
int len, struct kvm_io_device *dev)
{
int i;
struct kvm_io_bus *new_bus, *bus;
struct kvm_io_range range;

lockdep_assert_held(&kvm->slots_lock);

bus = kvm_get_bus(kvm, bus_idx);
if (!bus)
return -ENOMEM;
Expand Down

0 comments on commit 867583b

Please sign in to comment.