arch/arm64/kvm/vgic/vgic-its.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/vgic/vgic-its.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/vgic/vgic-its.c
Extension
.c
Size
72030 bytes
Lines
2819
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source 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

struct vgic_its_abi {
	int cte_esz;
	int dte_esz;
	int ite_esz;
	int (*save_tables)(struct vgic_its *its);
	int (*restore_tables)(struct vgic_its *its);
	void (*commit)(struct vgic_its *its);
};

#define ABI_0_ESZ	8
#define ESZ_MAX		ABI_0_ESZ

static const struct vgic_its_abi its_table_abi_versions[] = {
	[0] = {
	 .cte_esz = ABI_0_ESZ,
	 .dte_esz = ABI_0_ESZ,
	 .ite_esz = ABI_0_ESZ,
	 .save_tables = vgic_its_save_tables_v0,
	 .restore_tables = vgic_its_restore_tables_v0,
	 .commit = vgic_its_commit_v0,
	},
};

#define NR_ITS_ABIS	ARRAY_SIZE(its_table_abi_versions)

inline const struct vgic_its_abi *vgic_its_get_abi(struct vgic_its *its)
{
	return &its_table_abi_versions[its->abi_rev];
}

static void vgic_its_set_abi(struct vgic_its *its, u32 rev)
{
	const struct vgic_its_abi *abi;

	its->abi_rev = rev;
	abi = vgic_its_get_abi(its);
	abi->commit(its);
}

/*
 * Find and returns a device in the device table for an ITS.
 * Must be called with the its_lock mutex held.
 */
static struct its_device *find_its_device(struct vgic_its *its, u32 device_id)
{
	struct its_device *device;

	list_for_each_entry(device, &its->device_list, dev_list)
		if (device_id == device->device_id)
			return device;

	return NULL;
}

/*
 * Find and returns an interrupt translation table entry (ITTE) for a given
 * Device ID/Event ID pair on an ITS.
 * Must be called with the its_lock mutex held.
 */
static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
				  u32 event_id)
{
	struct its_device *device;
	struct its_ite *ite;

	device = find_its_device(its, device_id);
	if (device == NULL)
		return NULL;

	list_for_each_entry(ite, &device->itt_head, ite_list)
		if (ite->event_id == event_id)
			return ite;

	return NULL;
}

/* To be used as an iterator this macro misses the enclosing parentheses */
#define for_each_lpi_its(dev, ite, its) \
	list_for_each_entry(dev, &(its)->device_list, dev_list) \
		list_for_each_entry(ite, &(dev)->itt_head, ite_list)

#define GIC_LPI_OFFSET 8192

#define VITS_TYPER_IDBITS		16
#define VITS_MAX_EVENTID		(BIT(VITS_TYPER_IDBITS) - 1)
#define VITS_TYPER_DEVBITS		16
#define VITS_MAX_DEVID			(BIT(VITS_TYPER_DEVBITS) - 1)
#define VITS_DTE_MAX_DEVID_OFFSET	(BIT(14) - 1)
#define VITS_ITE_MAX_EVENTID_OFFSET	(BIT(16) - 1)

Annotation

Implementation Notes