1670 lines · 44.0 KB · C
RawDownload
				   "device driver tries to free an "				   "invalid DMA memory address\n");		} else {			err_printk(ref->dev, NULL,				   "device driver tries to free DMA "				   "memory it has not allocated [device "				   "address=0x%016llx] [size=%llu bytes]\n",				   ref->dev_addr, ref->size);		}		return;	} 	if (ref->size != entry->size) {		err_printk(ref->dev, entry, "device driver frees "			   "DMA memory with different size "			   "[device address=0x%016llx] [map size=%llu bytes] "			   "[unmap size=%llu bytes]\n",			   ref->dev_addr, entry->size, ref->size);	} 	if (ref->type != entry->type) {		err_printk(ref->dev, entry, "device driver frees "			   "DMA memory with wrong function "			   "[device address=0x%016llx] [size=%llu bytes] "			   "[mapped as %s] [unmapped as %s]\n",			   ref->dev_addr, ref->size,			   type2name[entry->type], type2name[ref->type]);	} else if ((entry->type == dma_debug_coherent ||		    entry->type == dma_debug_noncoherent) &&		   ref->paddr != entry->paddr) {		err_printk(ref->dev, entry, "device driver frees "			   "DMA memory with different CPU address "			   "[device address=0x%016llx] [size=%llu bytes] "			   "[cpu alloc address=0x%pa] "			   "[cpu free address=0x%pa]",			   ref->dev_addr, ref->size,			   &entry->paddr,			   &ref->paddr);	} 	if (ref->sg_call_ents && ref->type == dma_debug_sg &&	    ref->sg_call_ents != entry->sg_call_ents) {		err_printk(ref->dev, entry, "device driver frees "			   "DMA sg list with different entry count "			   "[map count=%d] [unmap count=%d]\n",			   entry->sg_call_ents, ref->sg_call_ents);	} 	/*	 * This may be no bug in reality - but most implementations of the	 * DMA API don't handle this properly, so check for it here	 */	if (ref->direction != entry->direction) {		err_printk(ref->dev, entry, "device driver frees "			   "DMA memory with different direction "			   "[device address=0x%016llx] [size=%llu bytes] "			   "[mapped with %s] [unmapped with %s]\n",			   ref->dev_addr, ref->size,			   dir2name[entry->direction],			   dir2name[ref->direction]);	} 	/*	 * Drivers should use dma_mapping_error() to check the returned	 * addresses of dma_map_single() and dma_map_page().	 * If not, print this warning message. See Documentation/core-api/dma-api.rst.	 */	if (entry->map_err_type == MAP_ERR_NOT_CHECKED) {		err_printk(ref->dev, entry,			   "device driver failed to check map error"			   "[device address=0x%016llx] [size=%llu bytes] "			   "[mapped as %s]",			   ref->dev_addr, ref->size,			   type2name[entry->type]);	} 	/*	 * This may be no bug in reality - but DMA API still expects	 * that entry is unmapped with same attributes as it was mapped.	 *	 * DMA_ATTR_UNMAP_VALID lists the attributes that must be identical	 * between map and unmap. Any attribute outside this set (e.g.	 * DMA_ATTR_NO_WARN, DMA_ATTR_SKIP_CPU_SYNC) is allowed to differ.	 */#define DMA_ATTR_UNMAP_VALID                                               \	(DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_FORCE_CONTIGUOUS |          \	 DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT | DMA_ATTR_PRIVILEGED | \	 DMA_ATTR_CC_SHARED)	if ((ref->attrs & DMA_ATTR_UNMAP_VALID) !=	    (entry->attrs & DMA_ATTR_UNMAP_VALID)) {		err_printk(ref->dev, entry,			   "device driver frees "			   "DMA memory with different attributes "			   "[device address=0x%016llx] [size=%llu bytes] "			   "[mapped with 0x%lx] [unmapped with 0x%lx]\n",			   ref->dev_addr, ref->size, entry->attrs, ref->attrs);	}#undef DMA_ATTR_UNMAP_VALID 	hash_bucket_del(entry);	put_hash_bucket(bucket, flags); 	/*	 * Free the entry outside of bucket_lock to avoid ABBA deadlocks	 * between that and radix_lock.	 */	dma_entry_free(entry);} static void check_for_stack(struct device *dev, phys_addr_t phys){	void *addr;	struct vm_struct *stack_vm_area = task_stack_vm_area(current); 	if (!stack_vm_area) {		/* Stack is direct-mapped. */		if (PhysHighMem(phys))			return;		addr = phys_to_virt(phys);		if (object_is_on_stack(addr))			err_printk(dev, NULL, "device driver maps memory from stack [addr=%p]\n", addr);	} else {		/* Stack is vmalloced. */		int i; 		for (i = 0; i < stack_vm_area->nr_pages; i++) {			if (__phys_to_pfn(phys) !=			    page_to_pfn(stack_vm_area->pages[i]))				continue; 			addr = (u8 *)current->stack + i * PAGE_SIZE +			       (phys % PAGE_SIZE);			err_printk(dev, NULL, "device driver maps memory from stack [probable addr=%p]\n", addr);			break;		}	}} static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len){	if (memory_intersects(_stext, _etext, addr, len) ||	    memory_intersects(__start_rodata, __end_rodata, addr, len))		err_printk(dev, NULL, "device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len);} static void check_sync(struct device *dev,		       struct dma_debug_entry *ref,		       bool to_cpu){	struct dma_debug_entry *entry;	struct hash_bucket *bucket;	unsigned long flags; 	bucket = get_hash_bucket(ref, &flags); 	entry = bucket_find_contain(&bucket, ref, &flags); 	if (!entry) {		err_printk(dev, NULL, "device driver tries "				"to sync DMA memory it has not allocated "				"[device address=0x%016llx] [size=%llu bytes]\n",				(unsigned long long)ref->dev_addr, ref->size);		goto out;	} 	if (ref->size > entry->size) {		err_printk(dev, entry, "device driver syncs"				" DMA memory outside allocated range "				"[device address=0x%016llx] "				"[allocation size=%llu bytes] "				"[sync offset+size=%llu]\n",				entry->dev_addr, entry->size,				ref->size);	} 	if (entry->direction == DMA_BIDIRECTIONAL)		goto out; 	if (ref->direction != entry->direction) {		err_printk(dev, entry, "device driver syncs "				"DMA memory with different direction "				"[device address=0x%016llx] [size=%llu bytes] "				"[mapped with %s] [synced with %s]\n",				(unsigned long long)ref->dev_addr, entry->size,				dir2name[entry->direction],				dir2name[ref->direction]);	} 	if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) &&		      !(ref->direction == DMA_TO_DEVICE))		err_printk(dev, entry, "device driver syncs "				"device read-only DMA memory for cpu "				"[device address=0x%016llx] [size=%llu bytes] "				"[mapped with %s] [synced with %s]\n",				(unsigned long long)ref->dev_addr, entry->size,				dir2name[entry->direction],				dir2name[ref->direction]); 	if (!to_cpu && !(entry->direction == DMA_TO_DEVICE) &&		       !(ref->direction == DMA_FROM_DEVICE))		err_printk(dev, entry, "device driver syncs "				"device write-only DMA memory to device "				"[device address=0x%016llx] [size=%llu bytes] "				"[mapped with %s] [synced with %s]\n",				(unsigned long long)ref->dev_addr, entry->size,				dir2name[entry->direction],				dir2name[ref->direction]); 	if (ref->sg_call_ents && ref->type == dma_debug_sg &&	    ref->sg_call_ents != entry->sg_call_ents) {		err_printk(ref->dev, entry, "device driver syncs "			   "DMA sg list with different entry count "			   "[map count=%d] [sync count=%d]\n",			   entry->sg_call_ents, ref->sg_call_ents);	} out:	put_hash_bucket(bucket, flags);} static void check_sg_segment(struct device *dev, struct scatterlist *sg){	unsigned int max_seg = dma_get_max_seg_size(dev);	u64 start, end, boundary = dma_get_seg_boundary(dev); 	/*	 * Either the driver forgot to set dma_parms appropriately, or	 * whoever generated the list forgot to check them.	 */	if (sg->length > max_seg)		err_printk(dev, NULL, "mapping sg segment longer than device claims to support [len=%u] [max=%u]\n",			   sg->length, max_seg);	/*	 * In some cases this could potentially be the DMA API	 * implementation's fault, but it would usually imply that	 * the scatterlist was built inappropriately to begin with.	 */	start = sg_dma_address(sg);	end = start + sg_dma_len(sg) - 1;	if ((start ^ end) & ~boundary)		err_printk(dev, NULL, "mapping sg segment across boundary [start=0x%016llx] [end=0x%016llx] [boundary=0x%016llx]\n",			   start, end, boundary);} void debug_dma_map_single(struct device *dev, const void *addr,			    unsigned long len){	if (unlikely(dma_debug_disabled()))		return; 	if (!virt_addr_valid(addr))		err_printk(dev, NULL, "device driver maps memory from invalid area [addr=%p] [len=%lu]\n",			   addr, len); 	if (is_vmalloc_addr(addr))		err_printk(dev, NULL, "device driver maps memory from vmalloc area [addr=%p] [len=%lu]\n",			   addr, len);}EXPORT_SYMBOL(debug_dma_map_single); void debug_dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,		int direction, dma_addr_t dma_addr, unsigned long attrs){	struct dma_debug_entry *entry; 	if (unlikely(dma_debug_disabled()))		return; 	if (dma_mapping_error(dev, dma_addr))		return; 	entry = dma_entry_alloc();	if (!entry)		return; 	entry->dev       = dev;	entry->type      = dma_debug_phy;	entry->paddr	 = phys;	entry->dev_addr  = dma_addr;	entry->size      = size;	entry->direction = direction;	entry->map_err_type = MAP_ERR_NOT_CHECKED;	entry->attrs     = attrs; 	if (attrs & DMA_ATTR_MMIO) {		unsigned long pfn = PHYS_PFN(phys); 		if (pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))			err_printk(dev, entry,				   "dma_map_resource called for RAM address %pa\n",				   &phys);	} else {		check_for_stack(dev, phys); 		if (!PhysHighMem(phys))			check_for_illegal_area(dev, phys_to_virt(phys), size);	} 	add_dma_entry(entry);} void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr){	struct dma_debug_entry ref;	struct dma_debug_entry *entry;	struct hash_bucket *bucket;	unsigned long flags; 	if (unlikely(dma_debug_disabled()))		return; 	ref.dev = dev;	ref.dev_addr = dma_addr;	bucket = get_hash_bucket(&ref, &flags); 	list_for_each_entry(entry, &bucket->list, list) {		if (!exact_match(&ref, entry))			continue; 		/*		 * The same physical address can be mapped multiple		 * times. Without a hardware IOMMU this results in the		 * same device addresses being put into the dma-debug		 * hash multiple times too. This can result in false		 * positives being reported. Therefore we implement a		 * best-fit algorithm here which updates the first entry		 * from the hash which fits the reference value and is		 * not currently listed as being checked.		 */		if (entry->map_err_type == MAP_ERR_NOT_CHECKED) {			entry->map_err_type = MAP_ERR_CHECKED;			break;		}	} 	put_hash_bucket(bucket, flags);}EXPORT_SYMBOL(debug_dma_mapping_error); void debug_dma_unmap_phys(struct device *dev, dma_addr_t dma_addr, size_t size,			  int direction, unsigned long attrs){	struct dma_debug_entry ref = {		.type           = dma_debug_phy,		.dev            = dev,		.dev_addr       = dma_addr,		.size           = size,		.direction      = direction,		.attrs          = attrs,	}; 	if (unlikely(dma_debug_disabled()))		return;	check_unmap(&ref);} void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,		      int nents, int mapped_ents, int direction,		      unsigned long attrs){	struct dma_debug_entry *entry;	struct scatterlist *s;	int i; 	if (unlikely(dma_debug_disabled()))		return; 	for_each_sg(sg, s, nents, i) {		check_for_stack(dev, sg_phys(s));		if (!PageHighMem(sg_page(s)))			check_for_illegal_area(dev, sg_virt(s), s->length);	} 	for_each_sg(sg, s, mapped_ents, i) {		entry = dma_entry_alloc();		if (!entry)			return; 		entry->type           = dma_debug_sg;		entry->dev            = dev;		entry->paddr	      = sg_phys(s);		entry->size           = sg_dma_len(s);		entry->dev_addr       = sg_dma_address(s);		entry->direction      = direction;		entry->sg_call_ents   = nents;		entry->sg_mapped_ents = mapped_ents;		entry->attrs          = attrs; 		check_sg_segment(dev, s); 		add_dma_entry(entry);	}} static int get_nr_mapped_entries(struct device *dev,				 struct dma_debug_entry *ref){	struct dma_debug_entry *entry;	struct hash_bucket *bucket;	unsigned long flags;	int mapped_ents; 	bucket       = get_hash_bucket(ref, &flags);	entry        = bucket_find_exact(bucket, ref);	mapped_ents  = 0; 	if (entry)		mapped_ents = entry->sg_mapped_ents;	put_hash_bucket(bucket, flags); 	return mapped_ents;} void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,			int nelems, int dir, unsigned long attrs){	struct scatterlist *s;	int mapped_ents = 0, i; 	if (unlikely(dma_debug_disabled()))		return; 	for_each_sg(sglist, s, nelems, i) { 		struct dma_debug_entry ref = {			.type           = dma_debug_sg,			.dev            = dev,			.paddr		= sg_phys(s),			.dev_addr       = sg_dma_address(s),			.size           = sg_dma_len(s),			.direction      = dir,			.sg_call_ents   = nelems,			.attrs          = attrs,		}; 		if (mapped_ents && i >= mapped_ents)			break; 		if (!i)			mapped_ents = get_nr_mapped_entries(dev, &ref); 		check_unmap(&ref);	}} static phys_addr_t virt_to_paddr(void *virt){	struct page *page; 	if (is_vmalloc_addr(virt))		page = vmalloc_to_page(virt);	else		page = virt_to_page(virt); 	return page_to_phys(page) + offset_in_page(virt);} void debug_dma_alloc_coherent(struct device *dev, size_t size,			      dma_addr_t dma_addr, void *virt,			      unsigned long attrs){	struct dma_debug_entry *entry; 	if (unlikely(dma_debug_disabled()))		return; 	if (unlikely(virt == NULL))		return; 	/* handle vmalloc and linear addresses */	if (!is_vmalloc_addr(virt) && !virt_addr_valid(virt))		return; 	entry = dma_entry_alloc();	if (!entry)		return; 	entry->type      = dma_debug_coherent;	entry->dev       = dev;	entry->paddr	 = virt_to_paddr(virt);	entry->size      = size;	entry->dev_addr  = dma_addr;	entry->direction = DMA_BIDIRECTIONAL;	entry->attrs     = attrs; 	add_dma_entry(entry);} void debug_dma_free_coherent(struct device *dev, size_t size, void *virt,			     dma_addr_t dma_addr, unsigned long attrs){	struct dma_debug_entry ref = {		.type           = dma_debug_coherent,		.dev            = dev,		.dev_addr       = dma_addr,		.size           = size,		.direction      = DMA_BIDIRECTIONAL,		.attrs          = attrs,	}; 

Lines 1001–1500 of 1670. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t