arch/powerpc/kvm/book3s_rtas.c

Source file repositories/reference/linux-study-clean/arch/powerpc/kvm/book3s_rtas.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kvm/book3s_rtas.c
Extension
.c
Size
6984 bytes
Lines
308
Domain
Architecture Layer
Bucket
arch/powerpc
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

struct rtas_handler {
	void (*handler)(struct kvm_vcpu *vcpu, struct rtas_args *args);
	char *name;
};

static struct rtas_handler rtas_handlers[] = {
#ifdef CONFIG_KVM_XICS
	{ .name = "ibm,set-xive", .handler = kvm_rtas_set_xive },
	{ .name = "ibm,get-xive", .handler = kvm_rtas_get_xive },
	{ .name = "ibm,int-off",  .handler = kvm_rtas_int_off },
	{ .name = "ibm,int-on",   .handler = kvm_rtas_int_on },
#endif
};

struct rtas_token_definition {
	struct list_head list;
	struct rtas_handler *handler;
	u64 token;
};

static int rtas_name_matches(char *s1, char *s2)
{
	struct kvm_rtas_token_args args;
	return !strncmp(s1, s2, sizeof(args.name));
}

static int rtas_token_undefine(struct kvm *kvm, char *name)
{
	struct rtas_token_definition *d, *tmp;

	lockdep_assert_held(&kvm->arch.rtas_token_lock);

	list_for_each_entry_safe(d, tmp, &kvm->arch.rtas_tokens, list) {
		if (rtas_name_matches(d->handler->name, name)) {
			list_del(&d->list);
			kfree(d);
			return 0;
		}
	}

	/* It's not an error to undefine an undefined token */
	return 0;
}

static int rtas_token_define(struct kvm *kvm, char *name, u64 token)
{
	struct rtas_token_definition *d;
	struct rtas_handler *h = NULL;
	bool found;
	int i;

	lockdep_assert_held(&kvm->arch.rtas_token_lock);

	list_for_each_entry(d, &kvm->arch.rtas_tokens, list) {
		if (d->token == token)
			return -EEXIST;
	}

	found = false;
	for (i = 0; i < ARRAY_SIZE(rtas_handlers); i++) {
		h = &rtas_handlers[i];
		if (rtas_name_matches(h->name, name)) {
			found = true;
			break;
		}
	}

	if (!found)
		return -ENOENT;

	d = kzalloc_obj(*d);
	if (!d)
		return -ENOMEM;

	d->handler = h;
	d->token = token;

	list_add_tail(&d->list, &kvm->arch.rtas_tokens);

	return 0;
}

int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp)
{
	struct kvm_rtas_token_args args;
	int rc;

	if (copy_from_user(&args, argp, sizeof(args)))
		return -EFAULT;

Annotation

Implementation Notes