tools/testing/selftests/kvm/arm64/vgic_irq.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/arm64/vgic_irq.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/arm64/vgic_irq.c
Extension
.c
Size
27216 bytes
Lines
1086
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct test_args {
	u32 nr_irqs; /* number of KVM supported IRQs. */
	bool eoi_split; /* 1 is eoir+dir, 0 is eoir only */
	bool level_sensitive; /* 1 is level, 0 is edge */
	int kvm_max_routes; /* output of KVM_CAP_IRQ_ROUTING */
	bool kvm_supports_irqfd; /* output of KVM_CAP_IRQFD */
	u32 shared_data;
};

/*
 * KVM implements 32 priority levels:
 * 0x00 (highest priority) - 0xF8 (lowest priority), in steps of 8
 *
 * Note that these macros will still be correct in the case that KVM implements
 * more priority levels. Also note that 32 is the minimum for GICv3 and GICv2.
 */
#define KVM_NUM_PRIOS		32
#define KVM_PRIO_SHIFT		3 /* steps of 8 = 1 << 3 */
#define KVM_PRIO_STEPS		(1 << KVM_PRIO_SHIFT) /* 8 */
#define LOWEST_PRIO		(KVM_NUM_PRIOS - 1)
#define CPU_PRIO_MASK		(LOWEST_PRIO << KVM_PRIO_SHIFT)	/* 0xf8 */
#define IRQ_DEFAULT_PRIO	(LOWEST_PRIO - 1)
#define IRQ_DEFAULT_PRIO_REG	(IRQ_DEFAULT_PRIO << KVM_PRIO_SHIFT) /* 0xf0 */

/*
 * The kvm_inject_* utilities are used by the guest to ask the host to inject
 * interrupts (e.g., using the KVM_IRQ_LINE ioctl).
 */

typedef enum {
	KVM_INJECT_EDGE_IRQ_LINE = 1,
	KVM_SET_IRQ_LINE,
	KVM_SET_IRQ_LINE_HIGH,
	KVM_SET_LEVEL_INFO_HIGH,
	KVM_INJECT_IRQFD,
	KVM_WRITE_ISPENDR,
	KVM_WRITE_ISACTIVER,
} kvm_inject_cmd;

struct kvm_inject_args {
	kvm_inject_cmd cmd;
	u32 first_intid;
	u32 num;
	int level;
	bool expect_failure;
};

/* Used on the guest side to perform the hypercall. */
static void kvm_inject_call(kvm_inject_cmd cmd, u32 first_intid,
			    u32 num, int level, bool expect_failure);

/* Used on the host side to get the hypercall info. */
static void kvm_inject_get_call(struct kvm_vm *vm, struct ucall *uc,
		struct kvm_inject_args *args);

#define _KVM_INJECT_MULTI(cmd, intid, num, expect_failure)			\
	kvm_inject_call(cmd, intid, num, -1 /* not used */, expect_failure)

#define KVM_INJECT_MULTI(cmd, intid, num)					\
	_KVM_INJECT_MULTI(cmd, intid, num, false)

#define _KVM_INJECT(cmd, intid, expect_failure)					\
	_KVM_INJECT_MULTI(cmd, intid, 1, expect_failure)

#define KVM_INJECT(cmd, intid)							\
	_KVM_INJECT_MULTI(cmd, intid, 1, false)

#define KVM_ACTIVATE(cmd, intid)						\
	kvm_inject_call(cmd, intid, 1, 1, false);

struct kvm_inject_desc {
	kvm_inject_cmd cmd;
	/* can inject PPIs, PPIs, and/or SPIs. */
	bool sgi, ppi, spi;
};

static struct kvm_inject_desc inject_edge_fns[] = {
	/*                                      sgi    ppi    spi */
	{ KVM_INJECT_EDGE_IRQ_LINE,		false, false, true },
	{ KVM_INJECT_IRQFD,			false, false, true },
	{ KVM_WRITE_ISPENDR,			true,  false, true },
	{ 0, },
};

static struct kvm_inject_desc inject_level_fns[] = {
	/*                                      sgi    ppi    spi */
	{ KVM_SET_IRQ_LINE_HIGH,		false, true,  true },
	{ KVM_SET_LEVEL_INFO_HIGH,		false, true,  true },
	{ KVM_INJECT_IRQFD,			false, false, true },
	{ KVM_WRITE_ISPENDR,			false, true,  true },

Annotation

Implementation Notes