From: Christoffer Dall <c.dall@virtualopensystems.com>
To: android-virt@lists.cs.columbia.edu, kvm@vger.kernel.org
Cc: Marc.Zyngier@arm.com, catalin.marinas@arm.com,
tech@virtualopensystems.com, avi@redhat.com,
peter.maydell@linaro.org
Subject: [PATCH v5 04/13] ARM: KVM: Memory virtualization setup
Date: Sun, 11 Dec 2011 05:24:42 -0500 [thread overview]
Message-ID: <20111211102442.21693.544.stgit@localhost> (raw)
In-Reply-To: <20111211102403.21693.6887.stgit@localhost>
This commit introduces the framework for guest memory management
through the use of 2nd stage translation. Each VM has a pointer
to a level-1 tabled (the pgd field in struct kvm_arch) which is
used for the 2nd stage translations. Entries are added when handling
guest faults (later patch) and the table itself can be allocated and
freed through the following functions implemented in
arch/arm/kvm/arm_mmu.c:
- kvm_alloc_stage2_pgd(struct kvm *kvm);
- kvm_free_stage2_pgd(struct kvm *kvm);
Further, each entry in TLBs and caches are tagged with a VMID
identifier in addition to ASIDs. The VMIDs are managed using
a bitmap and assigned when creating the VM in kvm_arch_init_vm()
where the 2nd stage pgd is also allocated. The table is freed in
kvm_arch_destroy_vm(). Both functions are called from the main
KVM code.
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
arch/arm/include/asm/kvm_host.h | 4 ++
arch/arm/include/asm/kvm_mmu.h | 5 +++
arch/arm/kvm/arm.c | 59 +++++++++++++++++++++++++++++++--
arch/arm/kvm/mmu.c | 69 +++++++++++++++++++++++++++++++++++++++
4 files changed, 132 insertions(+), 5 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 6a10467..06d1263 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -31,7 +31,9 @@ struct kvm_vcpu;
u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
struct kvm_arch {
- pgd_t *pgd; /* 1-level 2nd stage table */
+ u32 vmid; /* The VMID used for the virt. memory system */
+ pgd_t *pgd; /* 1-level 2nd stage table */
+ u64 vttbr; /* VTTBR value associated with above pgd and vmid */
};
#define EXCEPTION_NONE 0
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 13fd8dc..9d7440c 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -32,4 +32,9 @@ extern pgd_t *kvm_hyp_pgd;
int create_hyp_mappings(pgd_t *hyp_pgd, void *from, void *to);
void free_hyp_pmds(pgd_t *hyp_pgd);
+int kvm_alloc_stage2_pgd(struct kvm *kvm);
+void kvm_free_stage2_pgd(struct kvm *kvm);
+
+int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run);
+
#endif /* __ARM_KVM_MMU_H__ */
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index e6bdf50..89ba18d 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -94,15 +94,62 @@ void kvm_arch_sync_events(struct kvm *kvm)
{
}
+/**
+ * kvm_arch_init_vm - initializes a VM data structure
+ * @kvm: pointer to the KVM struct
+ */
int kvm_arch_init_vm(struct kvm *kvm)
{
- return 0;
+ int ret = 0;
+ phys_addr_t pgd_phys;
+ unsigned long vmid;
+
+ mutex_lock(&kvm_vmids_mutex);
+ vmid = find_first_zero_bit(kvm_vmids, VMID_SIZE);
+ if (vmid >= VMID_SIZE) {
+ mutex_unlock(&kvm_vmids_mutex);
+ return -EBUSY;
+ }
+ __set_bit(vmid, kvm_vmids);
+ kvm->arch.vmid = vmid;
+ mutex_unlock(&kvm_vmids_mutex);
+
+ ret = kvm_alloc_stage2_pgd(kvm);
+ if (ret)
+ goto out_fail_alloc;
+
+ pgd_phys = virt_to_phys(kvm->arch.pgd);
+ kvm->arch.vttbr = pgd_phys & ((1LLU << 40) - 1) & ~((2 << VTTBR_X) - 1);
+ kvm->arch.vttbr |= ((u64)vmid << 48);
+
+ ret = create_hyp_mappings(kvm_hyp_pgd, kvm, kvm + 1);
+ if (ret)
+ goto out_free_stage2_pgd;
+
+ return ret;
+out_free_stage2_pgd:
+ kvm_free_stage2_pgd(kvm);
+out_fail_alloc:
+ clear_bit(vmid, kvm_vmids);
+ return ret;
}
+/**
+ * kvm_arch_destroy_vm - destroy the VM data structure
+ * @kvm: pointer to the KVM struct
+ */
void kvm_arch_destroy_vm(struct kvm *kvm)
{
int i;
+ kvm_free_stage2_pgd(kvm);
+
+ if (kvm->arch.vmid != 0) {
+ mutex_lock(&kvm_vmids_mutex);
+ clear_bit(kvm->arch.vmid, kvm_vmids);
+ mutex_unlock(&kvm_vmids_mutex);
+ }
+
for (i = 0; i < KVM_MAX_VCPUS; ++i) {
if (kvm->vcpus[i]) {
kvm_arch_vcpu_free(kvm->vcpus[i]);
@@ -178,6 +225,10 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
if (err)
goto free_vcpu;
+ err = create_hyp_mappings(kvm_hyp_pgd, vcpu, vcpu + 1);
+ if (err)
+ goto free_vcpu;
+
return vcpu;
free_vcpu:
kmem_cache_free(kvm_vcpu_cache, vcpu);
@@ -187,7 +238,7 @@ out:
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
{
- KVMARM_NOT_IMPLEMENTED();
+ kmem_cache_free(kvm_vcpu_cache, vcpu);
}
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -293,8 +344,8 @@ static int init_hyp_mode(void)
hyp_stack_ptr = (unsigned long)kvm_arm_hyp_stack_page + PAGE_SIZE;
- init_phys_addr = virt_to_phys((void *)&__kvm_hyp_init);
- init_end_phys_addr = virt_to_phys((void *)&__kvm_hyp_init_end);
+ init_phys_addr = virt_to_phys(__kvm_hyp_init);
+ init_end_phys_addr = virt_to_phys(__kvm_hyp_init_end);
/*
* Create identity mapping
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index a298926..f7a7b17 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -160,6 +160,75 @@ int create_hyp_mappings(pgd_t *hyp_pgd, void *from, void *to)
return err;
}
+/**
+ * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation.
+ * @kvm: The KVM struct pointer for the VM.
+ *
+ * Allocates the 1st level table only of size defined by PGD2_ORDER (can
+ * support either full 40-bit input addresses or limited to 32-bit input
+ * addresses). Clears the allocated pages.
+ */
+int kvm_alloc_stage2_pgd(struct kvm *kvm)
+{
+ pgd_t *pgd;
+
+ if (kvm->arch.pgd != NULL) {
+ kvm_err(-EINVAL, "kvm_arch already initialized?\n");
+ return -EINVAL;
+ }
+
+ pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, PGD2_ORDER);
+ if (!pgd)
+ return -ENOMEM;
+
+ memset(pgd, 0, PTRS_PER_PGD2 * sizeof(pgd_t));
+ kvm->arch.pgd = pgd;
+
+ return 0;
+}
+
+/**
+ * kvm_free_stage2_pgd - free all stage-2 tables
+ * @kvm: The KVM struct pointer for the VM.
+ *
+ * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all
+ * underlying level-2 and level-3 tables before freeing the actual level-1 table
+ * and setting the struct pointer to NULL.
+ */
+void kvm_free_stage2_pgd(struct kvm *kvm)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ unsigned long long i, addr;
+
+ if (kvm->arch.pgd == NULL)
+ return;
+
+ /*
+ * We do this slightly different than other places, since we need more
+ * than 32 bits and for instance pgd_addr_end converts to unsigned long.
+ */
+ addr = 0;
+ for (i = 0; i < PTRS_PER_PGD2; i++) {
+ addr = i * (unsigned long long)PGDIR_SIZE;
+ pgd = kvm->arch.pgd + i;
+ pud = pud_offset(pgd, addr);
+
+ if (pud_none(*pud))
+ continue;
+
+ BUG_ON(pud_bad(*pud));
+
+ pmd = pmd_offset(pud, addr);
+ free_ptes(pmd, addr);
+ pmd_free(NULL, pmd);
+ }
+
+ free_pages((unsigned long)kvm->arch.pgd, PGD2_ORDER);
+ kvm->arch.pgd = NULL;
+}
+
int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
KVMARM_NOT_IMPLEMENTED();
next prev parent reply other threads:[~2011-12-11 10:24 UTC|newest]
Thread overview: 105+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-11 10:24 [PATCH v5 00/13] KVM/ARM Implementation Christoffer Dall
2011-12-11 10:24 ` [PATCH v5 01/13] ARM: KVM: Initial skeleton to compile KVM support Christoffer Dall
2011-12-11 10:24 ` [PATCH v5 02/13] ARM: KVM: Hypervisor identity mapping Christoffer Dall
2011-12-11 10:24 ` [PATCH v5 03/13] ARM: KVM: Add hypervisor inititalization Christoffer Dall
2011-12-11 10:24 ` Christoffer Dall [this message]
2011-12-12 14:40 ` [PATCH v5 04/13] ARM: KVM: Memory virtualization setup Avi Kivity
2011-12-12 15:09 ` [Android-virt] " Christoffer Dall
2011-12-12 15:15 ` Avi Kivity
2011-12-12 15:25 ` Peter Maydell
2011-12-12 15:49 ` Avi Kivity
2011-12-12 17:40 ` Christoffer Dall
2011-12-13 17:10 ` Antonios Motakis
2011-12-13 17:13 ` Christoffer Dall
2011-12-11 10:24 ` [PATCH v5 05/13] ARM: KVM: Inject IRQs and FIQs from userspace Christoffer Dall
2011-12-11 15:18 ` Jan Kiszka
2011-12-11 16:03 ` Peter Maydell
2011-12-11 19:30 ` Christoffer Dall
2011-12-11 19:48 ` Peter Maydell
2011-12-11 20:07 ` [Android-virt] " Christoffer Dall
2011-12-11 20:25 ` Peter Maydell
2011-12-11 21:36 ` Christoffer Dall
2011-12-11 22:12 ` Peter Maydell
2011-12-11 22:35 ` Peter Maydell
2011-12-11 22:53 ` Christoffer Dall
2011-12-11 23:01 ` Jan Kiszka
2011-12-12 16:31 ` Peter Maydell
2011-12-12 17:40 ` Avi Kivity
2011-12-29 1:29 ` Christoffer Dall
2012-02-09 1:15 ` Peter Maydell
2011-12-12 11:06 ` Marc Zyngier
2011-12-12 12:54 ` Christoffer Dall
2011-12-12 6:35 ` Alexander Graf
2011-12-11 19:16 ` Christoffer Dall
2011-12-12 13:28 ` Avi Kivity
2011-12-12 14:38 ` [Android-virt] " Christoffer Dall
2011-12-12 14:50 ` Avi Kivity
2011-12-12 15:11 ` Christoffer Dall
2011-12-12 15:16 ` Avi Kivity
2011-12-11 10:24 ` [PATCH v5 06/13] ARM: KVM: World-switch implementation Christoffer Dall
2011-12-11 10:25 ` [PATCH v5 07/13] ARM: KVM: Emulation framework and CP15 emulation Christoffer Dall
2011-12-12 13:44 ` Avi Kivity
2011-12-12 16:17 ` Christoffer Dall
2011-12-11 10:25 ` [PATCH v5 08/13] ARM: KVM: Handle guest faults in KVM Christoffer Dall
2011-12-12 15:05 ` Avi Kivity
2011-12-12 19:53 ` Christoffer Dall
2011-12-13 9:45 ` Avi Kivity
2011-12-13 13:10 ` [Android-virt] " Christoffer Dall
2011-12-13 13:17 ` Marc Zyngier
2011-12-13 13:23 ` Avi Kivity
2011-12-13 13:44 ` Christoffer Dall
2011-12-13 14:27 ` Avi Kivity
2011-12-11 10:25 ` [PATCH v5 09/13] ARM: KVM: Handle I/O aborts Christoffer Dall
2011-12-12 13:54 ` Avi Kivity
2011-12-12 14:56 ` [Android-virt] " Christoffer Dall
2011-12-11 10:25 ` [PATCH v5 10/13] ARM: KVM: Guest wait-for-interrupts (WFI) support Christoffer Dall
2011-12-12 14:12 ` Avi Kivity
2011-12-12 16:20 ` Christoffer Dall
2011-12-12 17:44 ` Avi Kivity
2011-12-12 19:21 ` [Android-virt] " Christoffer Dall
2011-12-13 9:41 ` Avi Kivity
2011-12-11 10:25 ` [PATCH v5 11/13] ARM: KVM: Support SMP hosts Christoffer Dall
2011-12-12 14:30 ` Avi Kivity
2011-12-12 17:37 ` Christoffer Dall
2011-12-12 17:56 ` Avi Kivity
2011-12-12 19:38 ` [Android-virt] " Christoffer Dall
[not found] ` <CAEDV+gJ=zeDpfp0kS2uBvmgRMyCpsV1LitjKR66R4W9Y3VGgWw@mail.gmail.com>
[not found] ` <4EE71CF1.5080705@redhat.com>
2011-12-13 13:36 ` Christoffer Dall
2011-12-13 14:17 ` Avi Kivity
2011-12-13 14:36 ` Christoffer Dall
2011-12-13 14:17 ` Marc Zyngier
2011-12-19 6:15 ` Antonios Motakis
2011-12-19 14:57 ` [Android-virt] " Christoffer Dall
2011-12-19 15:19 ` Marc Zyngier
2011-12-19 15:30 ` Antonios Motakis
2011-12-19 15:37 ` Marc Zyngier
2011-12-19 15:40 ` Christoffer Dall
2011-12-19 15:42 ` Antonios Motakis
2011-12-19 15:45 ` Marc Zyngier
[not found] ` <CAEDV+gL929Hpa=PncVWeHRNAa5fBuorNNYFC=iix=PO+5aO2cg@mail.gmail.com>
2011-12-19 17:19 ` Peter Maydell
2011-12-19 17:24 ` Christoffer Dall
2011-12-19 17:36 ` Peter Maydell
2011-12-19 17:40 ` Christoffer Dall
2011-12-11 10:25 ` [PATCH v5 12/13] ARM: KVM: Fix guest view of MPIDR Christoffer Dall
2011-12-12 14:32 ` Avi Kivity
2011-12-12 17:39 ` Christoffer Dall
2011-12-12 17:44 ` Marc Zyngier
2011-12-12 19:43 ` Christoffer Dall
2011-12-13 9:46 ` Avi Kivity
2011-12-13 13:38 ` Christoffer Dall
2011-12-11 10:25 ` [PATCH v5 13/13] ARM: KVM: Support SMP guests Christoffer Dall
2011-12-11 11:32 ` [PATCH v5 00/13] KVM/ARM Implementation Peter Maydell
2011-12-11 19:23 ` Christoffer Dall
2011-12-11 19:27 ` Peter Maydell
2012-01-11 16:48 ` Peter Maydell
2012-01-12 3:29 ` Christoffer Dall
2012-01-12 8:19 ` Peter Maydell
2012-01-12 16:15 ` [Android-virt] " Christoffer Dall
2012-01-20 2:59 ` Christoffer Dall
2012-01-30 22:46 ` Peter Maydell
2012-01-30 23:02 ` Alexander Graf
2012-01-31 14:39 ` Antonios Motakis
2012-02-01 12:11 ` Marc Zyngier
2012-02-01 12:20 ` Peter Maydell
2012-02-01 13:40 ` Marc Zyngier
2012-02-01 13:57 ` Peter Maydell
2012-02-01 13:59 ` Christoffer Dall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111211102442.21693.544.stgit@localhost \
--to=c.dall@virtualopensystems.com \
--cc=Marc.Zyngier@arm.com \
--cc=android-virt@lists.cs.columbia.edu \
--cc=avi@redhat.com \
--cc=catalin.marinas@arm.com \
--cc=kvm@vger.kernel.org \
--cc=peter.maydell@linaro.org \
--cc=tech@virtualopensystems.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).