arch/powerpc/kvm/book3s_hv_uvmem.c

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

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kvm/book3s_hv_uvmem.c
Extension
.c
Size
34291 bytes
Lines
1224
Domain
Architecture Layer
Bucket
arch/powerpc
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 kvmppc_uvmem_slot {
	struct list_head list;
	unsigned long nr_pfns;
	unsigned long base_pfn;
	unsigned long *pfns;
};
struct kvmppc_uvmem_page_pvt {
	struct kvm *kvm;
	unsigned long gpa;
	bool skip_page_out;
	bool remove_gfn;
};

bool kvmppc_uvmem_available(void)
{
	/*
	 * If kvmppc_uvmem_bitmap != NULL, then there is an ultravisor
	 * and our data structures have been initialized successfully.
	 */
	return !!kvmppc_uvmem_bitmap;
}

int kvmppc_uvmem_slot_init(struct kvm *kvm, const struct kvm_memory_slot *slot)
{
	struct kvmppc_uvmem_slot *p;

	p = kzalloc_obj(*p);
	if (!p)
		return -ENOMEM;
	p->pfns = vcalloc(slot->npages, sizeof(*p->pfns));
	if (!p->pfns) {
		kfree(p);
		return -ENOMEM;
	}
	p->nr_pfns = slot->npages;
	p->base_pfn = slot->base_gfn;

	mutex_lock(&kvm->arch.uvmem_lock);
	list_add(&p->list, &kvm->arch.uvmem_pfns);
	mutex_unlock(&kvm->arch.uvmem_lock);

	return 0;
}

/*
 * All device PFNs are already released by the time we come here.
 */
void kvmppc_uvmem_slot_free(struct kvm *kvm, const struct kvm_memory_slot *slot)
{
	struct kvmppc_uvmem_slot *p, *next;

	mutex_lock(&kvm->arch.uvmem_lock);
	list_for_each_entry_safe(p, next, &kvm->arch.uvmem_pfns, list) {
		if (p->base_pfn == slot->base_gfn) {
			vfree(p->pfns);
			list_del(&p->list);
			kfree(p);
			break;
		}
	}
	mutex_unlock(&kvm->arch.uvmem_lock);
}

static void kvmppc_mark_gfn(unsigned long gfn, struct kvm *kvm,
			unsigned long flag, unsigned long uvmem_pfn)
{
	struct kvmppc_uvmem_slot *p;

	list_for_each_entry(p, &kvm->arch.uvmem_pfns, list) {
		if (gfn >= p->base_pfn && gfn < p->base_pfn + p->nr_pfns) {
			unsigned long index = gfn - p->base_pfn;

			if (flag == KVMPPC_GFN_UVMEM_PFN)
				p->pfns[index] = uvmem_pfn | flag;
			else
				p->pfns[index] = flag;
			return;
		}
	}
}

/* mark the GFN as secure-GFN associated with @uvmem pfn device-PFN. */
static void kvmppc_gfn_secure_uvmem_pfn(unsigned long gfn,
			unsigned long uvmem_pfn, struct kvm *kvm)
{
	kvmppc_mark_gfn(gfn, kvm, KVMPPC_GFN_UVMEM_PFN, uvmem_pfn);
}

/* mark the GFN as secure-GFN associated with a memory-PFN. */
static void kvmppc_gfn_secure_mem_pfn(unsigned long gfn, struct kvm *kvm)

Annotation

Implementation Notes