Commit e2815706 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch kvm-arm64/misc-6.10 into kvmarm-master/next



* kvm-arm64/misc-6.10:
  : .
  : Misc fixes and updates targeting 6.10
  :
  : - Improve boot-time diagnostics when the sysreg tables
  :   are not correctly sorted
  :
  : - Allow FFA_MSG_SEND_DIRECT_REQ in the FFA proxy
  :
  : - Fix duplicate XNX field in the ID_AA64MMFR1_EL1
  :   writeable mask
  :
  : - Allocate PPIs and SGIs outside of the vcpu structure, allowing
  :   for smaller EL2 mapping and some flexibility in implementing
  :   more or less than 32 private IRQs.
  :
  : - Use bitmap_gather() instead of its open-coded equivalent
  :
  : - Make protected mode use hVHE if available
  :
  : - Purge stale mpidr_data if a vcpu is created after the MPIDR
  :   map has been created
  : .
  KVM: arm64: Destroy mpidr_data for 'late' vCPU creation
  KVM: arm64: Use hVHE in pKVM by default on CPUs with VHE support
  KVM: arm64: Fix hvhe/nvhe early alias parsing
  KVM: arm64: Convert kvm_mpidr_index() to bitmap_gather()
  KVM: arm64: vgic: Allocate private interrupts on demand
  KVM: arm64: Remove duplicated AA64MMFR1_EL1 XNX
  KVM: arm64: Remove FFA_MSG_SEND_DIRECT_REQ from the denylist
  KVM: arm64: Improve out-of-order sysreg table diagnostics

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 8540bd1b ce5d2448
Loading
Loading
Loading
Loading
+3 −13
Original line number Diff line number Diff line
@@ -221,20 +221,10 @@ struct kvm_mpidr_data {

static inline u16 kvm_mpidr_index(struct kvm_mpidr_data *data, u64 mpidr)
{
	unsigned long mask = data->mpidr_mask;
	u64 aff = mpidr & MPIDR_HWID_BITMASK;
	int nbits, bit, bit_idx = 0;
	u16 index = 0;
	unsigned long index = 0, mask = data->mpidr_mask;
	unsigned long aff = mpidr & MPIDR_HWID_BITMASK;

	/*
	 * If this looks like RISC-V's BEXT or x86's PEXT
	 * instructions, it isn't by accident.
	 */
	nbits = fls(mask);
	for_each_set_bit(bit, &mask, nbits) {
		index |= (aff & BIT(bit)) >> (bit - bit_idx);
		bit_idx++;
	}
	bitmap_gather(&index, &aff, &mask, fls(mask));

	return index;
}
+2 −2
Original line number Diff line number Diff line
@@ -209,8 +209,8 @@ static const struct {
	char	alias[FTR_ALIAS_NAME_LEN];
	char	feature[FTR_ALIAS_OPTION_LEN];
} aliases[] __initconst = {
	{ "kvm_arm.mode=nvhe",		"id_aa64mmfr1.vh=0" },
	{ "kvm_arm.mode=protected",	"id_aa64mmfr1.vh=0" },
	{ "kvm_arm.mode=nvhe",		"arm64_sw.hvhe=0 id_aa64mmfr1.vh=0" },
	{ "kvm_arm.mode=protected",	"arm64_sw.hvhe=1" },
	{ "arm64.nosve",		"id_aa64pfr0.sve=0" },
	{ "arm64.nosme",		"id_aa64pfr1.sme=0" },
	{ "arm64.nobti",		"id_aa64pfr1.bt=0" },
+41 −9
Original line number Diff line number Diff line
@@ -218,6 +218,23 @@ void kvm_arch_create_vm_debugfs(struct kvm *kvm)
	kvm_sys_regs_create_debugfs(kvm);
}

static void kvm_destroy_mpidr_data(struct kvm *kvm)
{
	struct kvm_mpidr_data *data;

	mutex_lock(&kvm->arch.config_lock);

	data = rcu_dereference_protected(kvm->arch.mpidr_data,
					 lockdep_is_held(&kvm->arch.config_lock));
	if (data) {
		rcu_assign_pointer(kvm->arch.mpidr_data, NULL);
		synchronize_rcu();
		kfree(data);
	}

	mutex_unlock(&kvm->arch.config_lock);
}

/**
 * kvm_arch_destroy_vm - destroy the VM data structure
 * @kvm:	pointer to the KVM struct
@@ -232,7 +249,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
	if (is_protected_kvm_enabled())
		pkvm_destroy_hyp_vm(kvm);

	kfree(kvm->arch.mpidr_data);
	kvm_destroy_mpidr_data(kvm);

	kfree(kvm->arch.sysreg_masks);
	kvm_destroy_vcpus(kvm);

@@ -450,6 +468,13 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)

	vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu;

	/*
	 * This vCPU may have been created after mpidr_data was initialized.
	 * Throw out the pre-computed mappings if that is the case which forces
	 * KVM to fall back to iteratively searching the vCPUs.
	 */
	kvm_destroy_mpidr_data(vcpu->kvm);

	err = kvm_vgic_vcpu_init(vcpu);
	if (err)
		return err;
@@ -687,7 +712,8 @@ static void kvm_init_mpidr_data(struct kvm *kvm)

	mutex_lock(&kvm->arch.config_lock);

	if (kvm->arch.mpidr_data || atomic_read(&kvm->online_vcpus) == 1)
	if (rcu_access_pointer(kvm->arch.mpidr_data) ||
	    atomic_read(&kvm->online_vcpus) == 1)
		goto out;

	kvm_for_each_vcpu(c, vcpu, kvm) {
@@ -724,7 +750,7 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
		data->cmpidr_to_idx[index] = c;
	}

	kvm->arch.mpidr_data = data;
	rcu_assign_pointer(kvm->arch.mpidr_data, data);
out:
	mutex_unlock(&kvm->arch.config_lock);
}
@@ -2562,21 +2588,27 @@ static int __init init_hyp_mode(void)

struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vcpu *vcpu = NULL;
	struct kvm_mpidr_data *data;
	unsigned long i;

	mpidr &= MPIDR_HWID_BITMASK;

	if (kvm->arch.mpidr_data) {
		u16 idx = kvm_mpidr_index(kvm->arch.mpidr_data, mpidr);
	rcu_read_lock();
	data = rcu_dereference(kvm->arch.mpidr_data);

		vcpu = kvm_get_vcpu(kvm,
				    kvm->arch.mpidr_data->cmpidr_to_idx[idx]);
	if (data) {
		u16 idx = kvm_mpidr_index(data, mpidr);

		vcpu = kvm_get_vcpu(kvm, data->cmpidr_to_idx[idx]);
		if (mpidr != kvm_vcpu_get_mpidr_aff(vcpu))
			vcpu = NULL;
	}

	rcu_read_unlock();

	if (vcpu)
		return vcpu;
	}

	kvm_for_each_vcpu(i, vcpu, kvm) {
		if (mpidr == kvm_vcpu_get_mpidr_aff(vcpu))
+0 −1
Original line number Diff line number Diff line
@@ -600,7 +600,6 @@ static bool ffa_call_supported(u64 func_id)
	case FFA_MSG_POLL:
	case FFA_MSG_WAIT:
	/* 32-bit variants of 64-bit calls */
	case FFA_MSG_SEND_DIRECT_REQ:
	case FFA_MSG_SEND_DIRECT_RESP:
	case FFA_RXTX_MAP:
	case FFA_MEM_DONATE:
+4 −3
Original line number Diff line number Diff line
@@ -2338,7 +2338,6 @@ static const struct sys_reg_desc sys_reg_descs[] = {
					ID_AA64MMFR0_EL1_TGRAN16_2)),
	ID_WRITABLE(ID_AA64MMFR1_EL1, ~(ID_AA64MMFR1_EL1_RES0 |
					ID_AA64MMFR1_EL1_HCX |
					ID_AA64MMFR1_EL1_XNX |
					ID_AA64MMFR1_EL1_TWED |
					ID_AA64MMFR1_EL1_XNX |
					ID_AA64MMFR1_EL1_VH |
@@ -3069,12 +3068,14 @@ static bool check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,

	for (i = 0; i < n; i++) {
		if (!is_32 && table[i].reg && !table[i].reset) {
			kvm_err("sys_reg table %pS entry %d lacks reset\n", &table[i], i);
			kvm_err("sys_reg table %pS entry %d (%s) lacks reset\n",
				&table[i], i, table[i].name);
			return false;
		}

		if (i && cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
			kvm_err("sys_reg table %pS entry %d out of order\n", &table[i - 1], i - 1);
			kvm_err("sys_reg table %pS entry %d (%s -> %s) out of order\n",
				&table[i], i, table[i - 1].name, table[i].name);
			return false;
		}
	}
Loading