arch/sparc/kernel/adi_64.c

Source file repositories/reference/linux-study-clean/arch/sparc/kernel/adi_64.c

File Facts

System
Linux kernel
Corpus path
arch/sparc/kernel/adi_64.c
Extension
.c
Size
11253 bytes
Lines
397
Domain
Architecture Layer
Bucket
arch/sparc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!strcmp(prop, "adp")) {
			adi_state.enabled = true;
			break;
		}

		plen = strlen(prop) + 1;
		prop += plen;
		len -= plen;
	}

	if (!adi_state.enabled)
		goto adi_not_found;

	/* Find the ADI properties in "platform" node. If all ADI
	 * properties are not found, ADI support is incomplete and
	 * do not enable ADI in the kernel.
	 */
	pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
	if (pn == MDESC_NODE_NULL)
		goto adi_not_found;

	val = (u64 *) mdesc_get_property(hp, pn, "adp-blksz", &len);
	if (!val)
		goto adi_not_found;
	adi_state.caps.blksz = *val;

	val = (u64 *) mdesc_get_property(hp, pn, "adp-nbits", &len);
	if (!val)
		goto adi_not_found;
	adi_state.caps.nbits = *val;

	val = (u64 *) mdesc_get_property(hp, pn, "ue-on-adp", &len);
	if (!val)
		goto adi_not_found;
	adi_state.caps.ue_on_adi = *val;

	/* Some of the code to support swapping ADI tags is written
	 * assumption that two ADI tags can fit inside one byte. If
	 * this assumption is broken by a future architecture change,
	 * that code will have to be revisited. If that were to happen,
	 * disable ADI support so we do not get unpredictable results
	 * with programs trying to use ADI and their pages getting
	 * swapped out
	 */
	if (adi_state.caps.nbits > 4) {
		pr_warn("WARNING: ADI tag size >4 on this platform. Disabling AADI support\n");
		adi_state.enabled = false;
	}

	mdesc_release(hp);
	return;

adi_not_found:
	adi_state.enabled = false;
	adi_state.caps.blksz = 0;
	adi_state.caps.nbits = 0;
	if (hp)
		mdesc_release(hp);
}

static tag_storage_desc_t *find_tag_store(struct mm_struct *mm,
					  struct vm_area_struct *vma,
					  unsigned long addr)
{
	tag_storage_desc_t *tag_desc = NULL;
	unsigned long i, max_desc, flags;

	/* Check if this vma already has tag storage descriptor
	 * allocated for it.
	 */
	max_desc = PAGE_SIZE/sizeof(tag_storage_desc_t);
	if (mm->context.tag_store) {
		tag_desc = mm->context.tag_store;
		spin_lock_irqsave(&mm->context.tag_lock, flags);
		for (i = 0; i < max_desc; i++) {
			if ((addr >= tag_desc->start) &&
			    ((addr + PAGE_SIZE - 1) <= tag_desc->end))
				break;
			tag_desc++;
		}
		spin_unlock_irqrestore(&mm->context.tag_lock, flags);

		/* If no matching entries were found, this must be a
		 * freshly allocated page
		 */
		if (i >= max_desc)
			tag_desc = NULL;
	}

	return tag_desc;

Annotation

Implementation Notes