Skip to contentSkip to conversation

arch/arm64/kvm/vgic/vgic-v5-tables.c:456:31: sparse: sparse: incorrect type in assignment (different address spaces)

PATCH kernel test robot 1 participant 1 message Sep 18

lore
Share & tools
lore

kernel test robot

author build bot
#0 lore raw
tree:   https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
head:   3f2425f5b5bbbdd991ca9cdfd5502e68d8895998
commit: f45438c015291f26e99f7fe355c4c191b5750f8d [5531/8449] KVM: arm64: gic-v5: Create and manage VM and VPE tables
config: arm64-randconfig-r1307-20260918 (https://download.01.org/0day-ci/archive/20260919/[email protected]/config)
compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project 7252edd9aa82ef1c570ff6694ef7f4763a8a5d2f)
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260919/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

sparse warnings: (new ones prefixed by >>)

>> arch/arm64/kvm/vgic/vgic-v5-tables.c:456:31: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected void [noderef] __iomem *vmd_base @@     got void *[assigned] vmd @@
   arch/arm64/kvm/vgic/vgic-v5-tables.c:456:31: sparse:     expected void [noderef] __iomem *vmd_base
   arch/arm64/kvm/vgic/vgic-v5-tables.c:456:31: sparse:     got void *[assigned] vmd
>> arch/arm64/kvm/vgic/vgic-v5-tables.c:497:24: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected restricted __le64 [noderef] [usertype] __iomem *vpet_base @@     got restricted __le64 [usertype] *[assigned] vpet @@
   arch/arm64/kvm/vgic/vgic-v5-tables.c:497:24: sparse:     expected restricted __le64 [noderef] [usertype] __iomem *vpet_base
   arch/arm64/kvm/vgic/vgic-v5-tables.c:497:24: sparse:     got restricted __le64 [usertype] *[assigned] vpet
>> arch/arm64/kvm/vgic/vgic-v5-tables.c:585:18: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const *objp @@     got restricted __le64 [noderef] [usertype] __iomem *vpet_base @@
   arch/arm64/kvm/vgic/vgic-v5-tables.c:585:18: sparse:     expected void const *objp
   arch/arm64/kvm/vgic/vgic-v5-tables.c:585:18: sparse:     got restricted __le64 [noderef] [usertype] __iomem *vpet_base
>> arch/arm64/kvm/vgic/vgic-v5-tables.c:586:18: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const *objp @@     got void [noderef] __iomem *vmd_base @@
   arch/arm64/kvm/vgic/vgic-v5-tables.c:586:18: sparse:     expected void const *objp
   arch/arm64/kvm/vgic/vgic-v5-tables.c:586:18: sparse:     got void [noderef] __iomem *vmd_base
>> arch/arm64/kvm/vgic/vgic-v5-tables.c:626:19: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected restricted __le64 [usertype] *vpet_base @@     got restricted __le64 [noderef] [usertype] __iomem *vpet_base @@
   arch/arm64/kvm/vgic/vgic-v5-tables.c:626:19: sparse:     expected restricted __le64 [usertype] *vpet_base
   arch/arm64/kvm/vgic/vgic-v5-tables.c:626:19: sparse:     got restricted __le64 [noderef] [usertype] __iomem *vpet_base
>> arch/arm64/kvm/vgic/vgic-v5-tables.c:638:13: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le64 [usertype] tmp @@     got unsigned long long @@
   arch/arm64/kvm/vgic/vgic-v5-tables.c:638:13: sparse:     expected restricted __le64 [usertype] tmp
   arch/arm64/kvm/vgic/vgic-v5-tables.c:638:13: sparse:     got unsigned long long
>> arch/arm64/kvm/vgic/vgic-v5-tables.c:641:17: sparse: sparse: cast from restricted __le64

arch/arm64/kvm/vgic/vgic-v5-tables.c:674:19: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected restricted __le64 [usertype] *vpet_base @@ got restricted __le64 [noderef] [usertype] __iomem *vpet_base @@
arch/arm64/kvm/vgic/vgic-v5-tables.c:674:19: sparse: expected restricted __le64 [usertype] *vpet_base
arch/arm64/kvm/vgic/vgic-v5-tables.c:674:19: sparse: got restricted __le64 [noderef] [usertype] __iomem *vpet_base

vim +456 arch/arm64/kvm/vgic/vgic-v5-tables.c

385
386 /*
387 * Initialise an entry in the VMT based on the index of the VM.
388 *
389 * Note: We don't mark the VMTE as valid as this needs to be done by
390 * the hardware.
391 */
392 int vgic_v5_vmte_init(struct kvm *kvm)
393 {
394 size_t vmd_alloc_size, vpet_alloc_size, vped_alloc_size;
395 void *vped_base = NULL, *vmd = NULL;
396 struct vgic_v5_vm_info *vmi = NULL;
397 u64 tmp, vmte_val0 = 0, vmte_val1;
398 u32 vm_id = vgic_v5_vm_id(kvm);
399 int ret, nr_cpus, nr_vcpus;
400 bool vmi_inserted = false;
401 struct vmtl2_entry *vmte;
402 vpe_entry *vpet = NULL;
403 struct kvm_vcpu *vcpu;
404 u16 max_vpe_id = 0;
405 unsigned long i;
406
407 nr_vcpus = atomic_read(&kvm->online_vcpus);
408 if (nr_vcpus > vmt_info->max_vpes)
409 return -E2BIG;
410
411 /*
412 * If we're using two-level VMTs, L2 is allocated on demand. For linear
413 * VMTs, this is a NOP.
414 */
415 ret = vgic_v5_alloc_l2_vmt(kvm);
416 if (ret)
417 return ret;
418
419 vmte = vgic_v5_get_l2_vmte(vm_id);
420 if (IS_ERR(vmte))
421 return PTR_ERR(vmte);
422
423 /* If the entry is already valid, something went wrong */
424 scoped_guard(raw_spinlock_irqsave, &vgic_v5_irs_lock) {
425 vgic_v5_clean_inval(vmte, sizeof(*vmte));
426 if (le64_to_cpu(READ_ONCE(vmte->val[0])) & GICV5_VMTEL2E_VALID)
427 return -EINVAL;
428 }
429
430 ret = vgic_v5_reset_vmte(kvm);
431 if (ret)
432 return ret;
433
434 vmi = kzalloc_obj(*vmi);
435 if (!vmi) {
436 ret = -ENOMEM;
437 goto out_fail;
438 }
439
440 ret = xa_insert(&vm_info, vm_id, vmi, GFP_KERNEL);
441 if (ret)
442 goto out_fail;
443 vmi_inserted = true;
444
445 /* Allocate and assign the VM Descriptor, if required. */
446 if (vmt_info->vmd_size != 0) {
447 vmd_alloc_size = round_up(vmt_info->vmd_size,
448 dma_get_cache_alignment());
449 vmd = kzalloc(vmd_alloc_size, GFP_KERNEL);
450 if (!vmd) {
451 ret = -ENOMEM;
452 goto out_fail;
453 }
454
455 /* Stash the VA so we can free it later */

 > 456			vmi->vmd_base = vmd;
   457	
   458			tmp = FIELD_PREP(GICV5_VMTEL2E_VMD_ADDR,
   459					 virt_to_phys(vmd) >> GICV5_VMTEL2E_VMD_ADDR_SHIFT);
   460			vmte_val0 = tmp;
   461		}
   462	
   463		/*
   464		 * Allocate and assign the VPE Table.
   465		 *
   466		 * First of all, iterate over all vcpus to find the highest VPE ID we
   467		 * require - we need to ensure that we have enough storage for all
   468		 * vcpu_id values that userspace has picked and not just the total
   469		 * number of vcpus. This gives us the number of VPEs required for the
   470		 * VM.
   471		 *
   472		 * Round up the number of VPEs to a whole power of two as we cannot
   473		 * describe non-powers-of-two in the VMTE field as it conveys the number
   474		 * of ID bits used and not the number of vPEs. IRS_IDR1.IAFFID_BITS is
   475		 * encoded as N - 1, so expose at least one VPE ID bit even for a
   476		 * single-vCPU VM to keep the views consistent.
   477		 */
   478		kvm_for_each_vcpu(i, vcpu, kvm) {
   479			u16 vpe_id = vgic_v5_vpe_id(vcpu);
   480	
   481			if (vpe_id > max_vpe_id)
   482				max_vpe_id = vpe_id;
   483		}
   484	
   485		nr_cpus = max(2UL, roundup_pow_of_two(max_vpe_id + 1));
   486		vmi->vpe_id_bits = fls(nr_cpus) - 1;
   487	
   488		vpet_alloc_size = round_up((size_t)nr_cpus * sizeof(*vpet),
   489					   dma_get_cache_alignment());
   490		vpet = kzalloc(vpet_alloc_size, GFP_KERNEL);
   491		if (!vpet) {
   492			ret = -ENOMEM;
   493			goto out_fail;
   494		}
   495	
   496		/* Stash the VA so we can free it later */
 > 497		vmi->vpet_base = vpet;
   498	
   499		tmp = FIELD_PREP(GICV5_VMTEL2E_VPET_ADDR,
   500				 virt_to_phys(vpet) >> GICV5_VMTEL2E_VPET_ADDR_SHIFT);
   501		tmp |= FIELD_PREP(GICV5_VMTEL2E_VPE_ID_BITS, vmi->vpe_id_bits);
   502		vmte_val1 = tmp;
   503	
   504		/*
   505		 * Allocate a dense VPED array indexed by vcpu_idx. The VPET is indexed
   506		 * by the potentially sparse vcpu_id, but using that ID here would waste
   507		 * memory. Given that this is not userspace visible, we can cheat a bit
   508		 * and use the dense index instead. This is the ONLY place that we do
   509		 * this.
   510		 *
   511		 * Round the requested size up to a whole cacheline. kzalloc() gurantees
   512		 * natural alignment, so we ensure that the cachelines cannot be shared
   513		 * with unrelated slab objects. VPED and cacheline sizes are powers of
   514		 * two, so this also preserves the required VPED alignment when a VPED
   515		 * is larger than a cacheline.
   516		 */
   517		vped_alloc_size = round_up((size_t)nr_vcpus * vmt_info->vped_size,
   518					   dma_get_cache_alignment());
   519		vped_base = kzalloc(vped_alloc_size, GFP_KERNEL);
   520		if (!vped_base) {
   521			ret = -ENOMEM;
   522			goto out_fail;
   523		}
   524		vmi->vped_base = vped_base;
   525	
   526		if (vmd)
   527			vgic_v5_clean_inval(vmd, vmd_alloc_size);
   528		vgic_v5_clean_inval(vpet, vpet_alloc_size);
   529		vgic_v5_clean_inval(vped_base, vped_alloc_size);
   530	
   531		/* Publish the VMTE while serialising access to the shared VMT. */
   532		scoped_guard(raw_spinlock_irqsave, &vgic_v5_irs_lock) {
   533			WRITE_ONCE(vmte->val[0], cpu_to_le64(vmte_val0));
   534			WRITE_ONCE(vmte->val[1], cpu_to_le64(vmte_val1));
   535			vgic_v5_clean_inval(vmte, sizeof(*vmte));
   536		}
   537	
   538		kvm->arch.vgic.gicv5_vm.vmte_allocated = true;
   539	
   540		return 0;
   541	
   542	out_fail:
   543		/* kfree(NULL) is safe so we can just kfree() at leisure */
   544		kfree(vmd);
   545		kfree(vpet);
   546		kfree(vped_base);
   547		if (vmi_inserted)
   548			xa_erase(&vm_info, vm_id);
   549		kfree(vmi);
   550	
   551		vgic_v5_reset_vmte(kvm);
   552	
   553		return ret;
   554	}
   555	
   556	/*
   557	 * Release the VMT Entry, freeing up any allocated data structures before
   558	 * zeroing the VMTE.
   559	 *
   560	 * The VMTE must be marked as invalid before it is released.
   561	 */
   562	int vgic_v5_vmte_release(struct kvm *kvm)
   563	{
   564		u32 vm_id = vgic_v5_vm_id(kvm);
   565		struct vgic_v5_vm_info *vmi;
   566		struct vmtl2_entry *vmte;
   567		int ret;
   568	
   569		vmte = vgic_v5_get_l2_vmte(vm_id);
   570		if (IS_ERR(vmte))
   571			return PTR_ERR(vmte);
   572	
   573		/* Reject if the VMTE has not been marked as invalid! */
   574		scoped_guard(raw_spinlock_irqsave, &vgic_v5_irs_lock) {
   575			vgic_v5_clean_inval(vmte, sizeof(*vmte));
   576			if (le64_to_cpu(READ_ONCE(vmte->val[0])) & GICV5_VMTEL2E_VALID)
   577				return -EINVAL;
   578		}
   579	
   580		vmi = xa_load(&vm_info, vm_id);
   581		if (!vmi)
   582			goto no_vmi;
   583	
   584		kfree(vmi->vped_base);
 > 585		kfree(vmi->vpet_base);
 > 586		kfree(vmi->vmd_base);
   587	
   588		xa_erase(&vm_info, vm_id);
   589		kfree(vmi);
   590	
   591	no_vmi:
   592		/*
   593		 * If we didn't get far enough into allocating a VMTE to create the VM
   594		 * info structure, then we just zero the VMTE and move on. There's
   595		 * nothing else we can realistically do here.
   596		 */
   597		ret = vgic_v5_reset_vmte(kvm);
   598		if (ret)
   599			return ret;
   600	
   601		kvm->arch.vgic.gicv5_vm.vmte_allocated = false;
   602	
   603		return 0;
   604	}
   605	
   606	/* Provide the preallocated VPE descriptor to the hardware via the VPE Table. */
   607	int vgic_v5_vmte_alloc_vpe(struct kvm_vcpu *vcpu)
   608	{
   609		u32 vm_id = vgic_v5_vm_id(vcpu->kvm);
   610		u16 vpe_id = vgic_v5_vpe_id(vcpu);
   611		struct vgic_v5_vm_info *vmi;
   612		vpe_entry tmp, *vpet_base;
   613		void *vped;
   614	
   615		/* Make sure we're not over what the hardware supports */
   616		if (vpe_id >= vmt_info->max_vpes)
   617			return -E2BIG;
   618	
   619		vmi = xa_load(&vm_info, vm_id);
   620		if (!vmi)
   621			return -EINVAL;
   622	
   623		if (vpe_id >= 1 << vmi->vpe_id_bits)
   624			return -E2BIG;
   625	
 > 626		vpet_base = vmi->vpet_base;
   627	
   628		/* If the VPETE for this CPU is already valid we've gone wrong */
   629		scoped_guard(raw_spinlock_irqsave, &vgic_v5_irs_lock) {
   630			vgic_v5_clean_inval(&vpet_base[vpe_id], sizeof(*vpet_base));
   631			if (le64_to_cpu(READ_ONCE(vpet_base[vpe_id])) & GICV5_VPE_VALID)
   632				return -EBUSY;
   633		}
   634	
   635		vped = (u8 *)vmi->vped_base +
   636			(size_t)vcpu->vcpu_idx * vmt_info->vped_size;
   637	
 > 638		tmp = FIELD_PREP(GICV5_VPED_ADDR, virt_to_phys(vped) >> GICV5_VPED_ADDR_SHIFT);
   639	
   640		scoped_guard(raw_spinlock_irqsave, &vgic_v5_irs_lock) {
 > 641			WRITE_ONCE(vpet_base[vpe_id], cpu_to_le64(tmp));

642 vgic_v5_clean_inval(vpet_base + vpe_id, sizeof(vpe_entry));
643 }
644
645 return 0;
646 }
647

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki