Commit c6a597fc authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'loongarch-fixes-6.8-3' of...

Merge tag 'loongarch-fixes-6.8-3' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson

Pull LoongArch fixes from Huacai Chen:
 "Fix two cpu-hotplug issues, fix the init sequence about FDT system,
  fix the coding style of dts, and fix the wrong CPUCFG ID handling of
  KVM"

* tag 'loongarch-fixes-6.8-3' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
  LoongArch: KVM: Streamline kvm_check_cpucfg() and improve comments
  LoongArch: KVM: Rename _kvm_get_cpucfg() to _kvm_get_cpucfg_mask()
  LoongArch: KVM: Fix input validation of _kvm_get_cpucfg() & kvm_check_cpucfg()
  LoongArch: dts: Minor whitespace cleanup
  LoongArch: Call early_init_fdt_scan_reserved_mem() earlier
  LoongArch: Update cpu_sibling_map when disabling nonboot CPUs
  LoongArch: Disable IRQ before init_fn() for nonboot CPUs
parents 603c04e2 f0f5c489
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -357,6 +357,8 @@ void __init platform_init(void)
	acpi_gbl_use_default_register_widths = false;
	acpi_boot_table_init();
#endif

	early_init_fdt_scan_reserved_mem();
	unflatten_and_copy_device_tree();

#ifdef CONFIG_NUMA
@@ -390,8 +392,6 @@ static void __init arch_mem_init(char **cmdline_p)

	check_kernel_sections_mem();

	early_init_fdt_scan_reserved_mem();

	/*
	 * In order to reduce the possibility of kernel panic when failed to
	 * get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
+69 −53
Original line number Diff line number Diff line
@@ -88,6 +88,73 @@ void show_ipi_list(struct seq_file *p, int prec)
	}
}

static inline void set_cpu_core_map(int cpu)
{
	int i;

	cpumask_set_cpu(cpu, &cpu_core_setup_map);

	for_each_cpu(i, &cpu_core_setup_map) {
		if (cpu_data[cpu].package == cpu_data[i].package) {
			cpumask_set_cpu(i, &cpu_core_map[cpu]);
			cpumask_set_cpu(cpu, &cpu_core_map[i]);
		}
	}
}

static inline void set_cpu_sibling_map(int cpu)
{
	int i;

	cpumask_set_cpu(cpu, &cpu_sibling_setup_map);

	for_each_cpu(i, &cpu_sibling_setup_map) {
		if (cpus_are_siblings(cpu, i)) {
			cpumask_set_cpu(i, &cpu_sibling_map[cpu]);
			cpumask_set_cpu(cpu, &cpu_sibling_map[i]);
		}
	}
}

static inline void clear_cpu_sibling_map(int cpu)
{
	int i;

	for_each_cpu(i, &cpu_sibling_setup_map) {
		if (cpus_are_siblings(cpu, i)) {
			cpumask_clear_cpu(i, &cpu_sibling_map[cpu]);
			cpumask_clear_cpu(cpu, &cpu_sibling_map[i]);
		}
	}

	cpumask_clear_cpu(cpu, &cpu_sibling_setup_map);
}

/*
 * Calculate a new cpu_foreign_map mask whenever a
 * new cpu appears or disappears.
 */
void calculate_cpu_foreign_map(void)
{
	int i, k, core_present;
	cpumask_t temp_foreign_map;

	/* Re-calculate the mask */
	cpumask_clear(&temp_foreign_map);
	for_each_online_cpu(i) {
		core_present = 0;
		for_each_cpu(k, &temp_foreign_map)
			if (cpus_are_siblings(i, k))
				core_present = 1;
		if (!core_present)
			cpumask_set_cpu(i, &temp_foreign_map);
	}

	for_each_online_cpu(i)
		cpumask_andnot(&cpu_foreign_map[i],
			       &temp_foreign_map, &cpu_sibling_map[i]);
}

/* Send mailbox buffer via Mail_Send */
static void csr_mail_send(uint64_t data, int cpu, int mailbox)
{
@@ -303,6 +370,7 @@ int loongson_cpu_disable(void)
	numa_remove_cpu(cpu);
#endif
	set_cpu_online(cpu, false);
	clear_cpu_sibling_map(cpu);
	calculate_cpu_foreign_map();
	local_irq_save(flags);
	irq_migrate_all_off_this_cpu();
@@ -337,6 +405,7 @@ void __noreturn arch_cpu_idle_dead(void)
		addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0);
	} while (addr == 0);

	local_irq_disable();
	init_fn = (void *)TO_CACHE(addr);
	iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR);

@@ -379,59 +448,6 @@ static int __init ipi_pm_init(void)
core_initcall(ipi_pm_init);
#endif

static inline void set_cpu_sibling_map(int cpu)
{
	int i;

	cpumask_set_cpu(cpu, &cpu_sibling_setup_map);

	for_each_cpu(i, &cpu_sibling_setup_map) {
		if (cpus_are_siblings(cpu, i)) {
			cpumask_set_cpu(i, &cpu_sibling_map[cpu]);
			cpumask_set_cpu(cpu, &cpu_sibling_map[i]);
		}
	}
}

static inline void set_cpu_core_map(int cpu)
{
	int i;

	cpumask_set_cpu(cpu, &cpu_core_setup_map);

	for_each_cpu(i, &cpu_core_setup_map) {
		if (cpu_data[cpu].package == cpu_data[i].package) {
			cpumask_set_cpu(i, &cpu_core_map[cpu]);
			cpumask_set_cpu(cpu, &cpu_core_map[i]);
		}
	}
}

/*
 * Calculate a new cpu_foreign_map mask whenever a
 * new cpu appears or disappears.
 */
void calculate_cpu_foreign_map(void)
{
	int i, k, core_present;
	cpumask_t temp_foreign_map;

	/* Re-calculate the mask */
	cpumask_clear(&temp_foreign_map);
	for_each_online_cpu(i) {
		core_present = 0;
		for_each_cpu(k, &temp_foreign_map)
			if (cpus_are_siblings(i, k))
				core_present = 1;
		if (!core_present)
			cpumask_set_cpu(i, &temp_foreign_map);
	}

	for_each_online_cpu(i)
		cpumask_andnot(&cpu_foreign_map[i],
			       &temp_foreign_map, &cpu_sibling_map[i]);
}

/* Preload SMP state for boot cpu */
void smp_prepare_boot_cpu(void)
{
+40 −41
Original line number Diff line number Diff line
@@ -298,74 +298,73 @@ static int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 val)
	return ret;
}

static int _kvm_get_cpucfg(int id, u64 *v)
static int _kvm_get_cpucfg_mask(int id, u64 *v)
{
	int ret = 0;

	if (id < 0 && id >= KVM_MAX_CPUCFG_REGS)
	if (id < 0 || id >= KVM_MAX_CPUCFG_REGS)
		return -EINVAL;

	switch (id) {
	case 2:
		/* Return CPUCFG2 features which have been supported by KVM */
		/* CPUCFG2 features unconditionally supported by KVM */
		*v = CPUCFG2_FP     | CPUCFG2_FPSP  | CPUCFG2_FPDP     |
		     CPUCFG2_FPVERS | CPUCFG2_LLFTP | CPUCFG2_LLFTPREV |
		     CPUCFG2_LAM;
		/*
		 * If LSX is supported by CPU, it is also supported by KVM,
		 * as we implement it.
		 * For the ISA extensions listed below, if one is supported
		 * by the host, then it is also supported by KVM.
		 */
		if (cpu_has_lsx)
			*v |= CPUCFG2_LSX;
		/*
		 * if LASX is supported by CPU, it is also supported by KVM,
		 * as we implement it.
		 */
		if (cpu_has_lasx)
			*v |= CPUCFG2_LASX;

		break;
		return 0;
	default:
		ret = -EINVAL;
		break;
		/*
		 * No restrictions on other valid CPUCFG IDs' values, but
		 * CPUCFG data is limited to 32 bits as the LoongArch ISA
		 * manual says (Volume 1, Section 2.2.10.5 "CPUCFG").
		 */
		*v = U32_MAX;
		return 0;
	}
	return ret;
}

static int kvm_check_cpucfg(int id, u64 val)
{
	u64 mask;
	int ret = 0;

	if (id < 0 && id >= KVM_MAX_CPUCFG_REGS)
		return -EINVAL;
	int ret;
	u64 mask = 0;

	if (_kvm_get_cpucfg(id, &mask))
	ret = _kvm_get_cpucfg_mask(id, &mask);
	if (ret)
		return ret;

	if (val & ~mask)
		/* Unsupported features and/or the higher 32 bits should not be set */
		return -EINVAL;

	switch (id) {
	case 2:
		/* CPUCFG2 features checking */
		if (val & ~mask)
			/* The unsupported features should not be set */
			ret = -EINVAL;
		else if (!(val & CPUCFG2_LLFTP))
			/* The LLFTP must be set, as guest must has a constant timer */
			ret = -EINVAL;
		else if ((val & CPUCFG2_FP) && (!(val & CPUCFG2_FPSP) || !(val & CPUCFG2_FPDP)))
			/* Single and double float point must both be set when enable FP */
			ret = -EINVAL;
		else if ((val & CPUCFG2_LSX) && !(val & CPUCFG2_FP))
			/* FP should be set when enable LSX */
			ret = -EINVAL;
		else if ((val & CPUCFG2_LASX) && !(val & CPUCFG2_LSX))
			/* LSX, FP should be set when enable LASX, and FP has been checked before. */
			ret = -EINVAL;
		break;
		if (!(val & CPUCFG2_LLFTP))
			/* Guests must have a constant timer */
			return -EINVAL;
		if ((val & CPUCFG2_FP) && (!(val & CPUCFG2_FPSP) || !(val & CPUCFG2_FPDP)))
			/* Single and double float point must both be set when FP is enabled */
			return -EINVAL;
		if ((val & CPUCFG2_LSX) && !(val & CPUCFG2_FP))
			/* LSX architecturally implies FP but val does not satisfy that */
			return -EINVAL;
		if ((val & CPUCFG2_LASX) && !(val & CPUCFG2_LSX))
			/* LASX architecturally implies LSX and FP but val does not satisfy that */
			return -EINVAL;
		return 0;
	default:
		break;
		/*
		 * Values for the other CPUCFG IDs are not being further validated
		 * besides the mask check above.
		 */
		return 0;
	}
	return ret;
}

static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
@@ -566,7 +565,7 @@ static int kvm_loongarch_get_cpucfg_attr(struct kvm_vcpu *vcpu,
	uint64_t val;
	uint64_t __user *uaddr = (uint64_t __user *)attr->addr;

	ret = _kvm_get_cpucfg(attr->attr, &val);
	ret = _kvm_get_cpucfg_mask(attr->attr, &val);
	if (ret)
		return ret;

+1 −1

File changed.

Contains only whitespace changes.

+1 −1

File changed.

Contains only whitespace changes.