* [Qemu-devel] [RFC PATCH 1/3] KVM: promote KVM_MEMSLOT_INCOHERENT to uapi
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Andrew Jones
@ 2015-03-18 19:10 ` Andrew Jones
2015-04-20 15:26 ` Christoffer Dall
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 2/3] arm/arm64: KVM: decouple READONLY and UNCACHED Andrew Jones
` (3 subsequent siblings)
4 siblings, 1 reply; 18+ messages in thread
From: Andrew Jones @ 2015-03-18 19:10 UTC (permalink / raw)
To: kvmarm, qemu-devel, ard.biesheuvel, christoffer.dall,
marc.zyngier, peter.maydell, pbonzini
Cc: catalin.marinas, lersek, agraf, m.smarduch
Also rename to KVM_MEM_UNCACHED.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
Documentation/virtual/kvm/api.txt | 16 ++++++++++------
arch/arm/include/uapi/asm/kvm.h | 1 +
arch/arm/kvm/arm.c | 1 +
arch/arm/kvm/mmu.c | 4 ++--
arch/arm64/include/uapi/asm/kvm.h | 1 +
include/linux/kvm_host.h | 1 -
include/uapi/linux/kvm.h | 2 ++
virt/kvm/kvm_main.c | 7 ++++++-
8 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 0007fef4ed814..a5a51403a7937 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -902,6 +902,7 @@ struct kvm_userspace_memory_region {
/* for kvm_memory_region::flags */
#define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0)
#define KVM_MEM_READONLY (1UL << 1)
+#define KVM_MEM_UNCACHED (1UL << 2)
This ioctl allows the user to create or modify a guest physical memory
slot. When changing an existing slot, it may be moved in the guest
@@ -917,12 +918,15 @@ It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
be identical. This allows large pages in the guest to be backed by large
pages in the host.
-The flags field supports two flags: KVM_MEM_LOG_DIRTY_PAGES and
-KVM_MEM_READONLY. The former can be set to instruct KVM to keep track of
-writes to memory within the slot. See KVM_GET_DIRTY_LOG ioctl to know how to
-use it. The latter can be set, if KVM_CAP_READONLY_MEM capability allows it,
-to make a new slot read-only. In this case, writes to this memory will be
-posted to userspace as KVM_EXIT_MMIO exits.
+The flags field supports three flags: KVM_MEM_LOG_DIRTY_PAGES,
+KVM_MEM_READONLY, and KVM_MEM_UNCACHED. The first can be set to instruct
+KVM to keep track of writes to memory within the slot. See KVM_GET_DIRTY_LOG
+ioctl to know how to use it. The second can be set, if KVM_CAP_READONLY_MEM
+capability allows it, to make a new slot read-only. In this case, writes to
+this memory will be posted to userspace as KVM_EXIT_MMIO exits. The third can
+be set, if the KVM_CAP_UNCACHED_MEM capability allows it. This remaps the
+memory as uncached, i.e. userspace will always directly read/write RAM for
+this memory region.
When the KVM_CAP_SYNC_MMU capability is available, changes in the backing of
the memory region are automatically reflected into the guest. For example, an
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 09ee408c1a676..9d6fc19acf8a2 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -26,6 +26,7 @@
#define __KVM_HAVE_GUEST_DEBUG
#define __KVM_HAVE_IRQ_LINE
#define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_UNCACHED_MEM
#define KVM_REG_SIZE(id) \
(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index c9e6ef1f7403a..8d4c08f238cf0 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -180,6 +180,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_ARM_PSCI:
case KVM_CAP_ARM_PSCI_0_2:
case KVM_CAP_READONLY_MEM:
+ case KVM_CAP_UNCACHED_MEM:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index bcc1b3ad2adce..719931e83c468 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1260,7 +1260,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
if (!hugetlb && !force_pte)
hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa);
- fault_ipa_uncached = memslot->flags & KVM_MEMSLOT_INCOHERENT;
+ fault_ipa_uncached = memslot->flags & KVM_MEM_UNCACHED;
if (hugetlb) {
pmd_t new_pmd = pfn_pmd(pfn, mem_type);
@@ -1792,7 +1792,7 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
* regions as incoherent.
*/
if (slot->flags & KVM_MEM_READONLY)
- slot->flags |= KVM_MEMSLOT_INCOHERENT;
+ slot->flags |= KVM_MEM_UNCACHED;
return 0;
}
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 8e38878c87c61..5553d112e405b 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -38,6 +38,7 @@
#define __KVM_HAVE_GUEST_DEBUG
#define __KVM_HAVE_IRQ_LINE
#define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_UNCACHED_MEM
#define KVM_REG_SIZE(id) \
(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 3b934cc94cc83..9dfb519c51e5b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -43,7 +43,6 @@
* include/linux/kvm_h.
*/
#define KVM_MEMSLOT_INVALID (1UL << 16)
-#define KVM_MEMSLOT_INCOHERENT (1UL << 17)
/* Two fragments for cross MMIO pages. */
#define KVM_MAX_MMIO_FRAGMENTS 2
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index a37fd1224f363..4781fc00cd746 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -108,6 +108,7 @@ struct kvm_userspace_memory_region {
*/
#define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0)
#define KVM_MEM_READONLY (1UL << 1)
+#define KVM_MEM_UNCACHED (1UL << 2)
/* for KVM_IRQ_LINE */
struct kvm_irq_level {
@@ -753,6 +754,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_PPC_FIXUP_HCALL 103
#define KVM_CAP_PPC_ENABLE_HCALL 104
#define KVM_CAP_CHECK_EXTENSION_VM 105
+#define KVM_CAP_UNCACHED_MEM 107
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 59bc56e577b2d..6d63ceb6324d9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -723,6 +723,10 @@ static int check_memory_region_flags(struct kvm_userspace_memory_region *mem)
valid_flags |= KVM_MEM_READONLY;
#endif
+#ifdef __KVM_HAVE_UNCACHED_MEM
+ valid_flags |= KVM_MEM_UNCACHED;
+#endif
+
if (mem->flags & ~valid_flags)
return -EINVAL;
@@ -820,7 +824,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
else { /* Modify an existing slot. */
if ((mem->userspace_addr != old.userspace_addr) ||
(npages != old.npages) ||
- ((new.flags ^ old.flags) & KVM_MEM_READONLY))
+ ((new.flags ^ old.flags) &
+ (KVM_MEM_READONLY | KVM_MEM_UNCACHED)))
goto out;
if (base_gfn != old.base_gfn)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH 1/3] KVM: promote KVM_MEMSLOT_INCOHERENT to uapi
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 1/3] KVM: promote KVM_MEMSLOT_INCOHERENT to uapi Andrew Jones
@ 2015-04-20 15:26 ` Christoffer Dall
0 siblings, 0 replies; 18+ messages in thread
From: Christoffer Dall @ 2015-04-20 15:26 UTC (permalink / raw)
To: Andrew Jones
Cc: peter.maydell, ard.biesheuvel, marc.zyngier, catalin.marinas,
qemu-devel, agraf, pbonzini, lersek, kvmarm, m.smarduch
On Wed, Mar 18, 2015 at 03:10:31PM -0400, Andrew Jones wrote:
> Also rename to KVM_MEM_UNCACHED.
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> Documentation/virtual/kvm/api.txt | 16 ++++++++++------
> arch/arm/include/uapi/asm/kvm.h | 1 +
> arch/arm/kvm/arm.c | 1 +
> arch/arm/kvm/mmu.c | 4 ++--
> arch/arm64/include/uapi/asm/kvm.h | 1 +
> include/linux/kvm_host.h | 1 -
> include/uapi/linux/kvm.h | 2 ++
> virt/kvm/kvm_main.c | 7 ++++++-
> 8 files changed, 23 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 0007fef4ed814..a5a51403a7937 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -902,6 +902,7 @@ struct kvm_userspace_memory_region {
> /* for kvm_memory_region::flags */
> #define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0)
> #define KVM_MEM_READONLY (1UL << 1)
> +#define KVM_MEM_UNCACHED (1UL << 2)
>
> This ioctl allows the user to create or modify a guest physical memory
> slot. When changing an existing slot, it may be moved in the guest
> @@ -917,12 +918,15 @@ It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
> be identical. This allows large pages in the guest to be backed by large
> pages in the host.
>
> -The flags field supports two flags: KVM_MEM_LOG_DIRTY_PAGES and
> -KVM_MEM_READONLY. The former can be set to instruct KVM to keep track of
> -writes to memory within the slot. See KVM_GET_DIRTY_LOG ioctl to know how to
> -use it. The latter can be set, if KVM_CAP_READONLY_MEM capability allows it,
> -to make a new slot read-only. In this case, writes to this memory will be
> -posted to userspace as KVM_EXIT_MMIO exits.
> +The flags field supports three flags: KVM_MEM_LOG_DIRTY_PAGES,
> +KVM_MEM_READONLY, and KVM_MEM_UNCACHED. The first can be set to instruct
> +KVM to keep track of writes to memory within the slot. See KVM_GET_DIRTY_LOG
> +ioctl to know how to use it. The second can be set, if KVM_CAP_READONLY_MEM
> +capability allows it, to make a new slot read-only. In this case, writes to
> +this memory will be posted to userspace as KVM_EXIT_MMIO exits. The third can
> +be set, if the KVM_CAP_UNCACHED_MEM capability allows it. This remaps the
> +memory as uncached, i.e. userspace will always directly read/write RAM for
> +this memory region.
I would repeat the definition of the flag in the text here instead of
referring to the 'first', 'second', and 'third' here; it's too hard to
follow.
Also, which combination of these flags are allowed? Can they all be set
in combination or are they mutually exclusive or a bit of everything?
Thanks,
-Christoffer
^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH 2/3] arm/arm64: KVM: decouple READONLY and UNCACHED
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Andrew Jones
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 1/3] KVM: promote KVM_MEMSLOT_INCOHERENT to uapi Andrew Jones
@ 2015-03-18 19:10 ` Andrew Jones
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 3/3] arm/arm64: KVM: implement KVM_MEM_UNCACHED Andrew Jones
` (2 subsequent siblings)
4 siblings, 0 replies; 18+ messages in thread
From: Andrew Jones @ 2015-03-18 19:10 UTC (permalink / raw)
To: kvmarm, qemu-devel, ard.biesheuvel, christoffer.dall,
marc.zyngier, peter.maydell, pbonzini
Cc: catalin.marinas, lersek, agraf, m.smarduch
KVM_MEM_UNCACHED memory will no longer need caches to be flushed
for memory as it's faulted in. Just use READONLY directly, in that
case, now.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
arch/arm/kvm/mmu.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 719931e83c468..59af5ad779eb6 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1260,7 +1260,15 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
if (!hugetlb && !force_pte)
hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa);
- fault_ipa_uncached = memslot->flags & KVM_MEM_UNCACHED;
+ /*
+ * Readonly memslots are not incoherent with the caches by definition,
+ * but in practice, they are used mostly to emulate ROMs or NOR flashes
+ * that the guest may consider devices and hence map as uncached.
+ * To prevent incoherency issues in these cases, force dcache flushes
+ * for all pages in the region as they're faulted in.
+ */
+ fault_ipa_uncached = (memslot->flags & KVM_MEM_READONLY) &&
+ !(memslot->flags & KVM_MEM_UNCACHED);
if (hugetlb) {
pmd_t new_pmd = pfn_pmd(pfn, mem_type);
@@ -1784,15 +1792,6 @@ void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
unsigned long npages)
{
- /*
- * Readonly memslots are not incoherent with the caches by definition,
- * but in practice, they are used mostly to emulate ROMs or NOR flashes
- * that the guest may consider devices and hence map as uncached.
- * To prevent incoherency issues in these cases, tag all readonly
- * regions as incoherent.
- */
- if (slot->flags & KVM_MEM_READONLY)
- slot->flags |= KVM_MEM_UNCACHED;
return 0;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH 3/3] arm/arm64: KVM: implement KVM_MEM_UNCACHED
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Andrew Jones
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 1/3] KVM: promote KVM_MEMSLOT_INCOHERENT to uapi Andrew Jones
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 2/3] arm/arm64: KVM: decouple READONLY and UNCACHED Andrew Jones
@ 2015-03-18 19:10 ` Andrew Jones
2015-03-19 16:56 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Paolo Bonzini
2015-04-29 9:03 ` Alexander Graf
4 siblings, 0 replies; 18+ messages in thread
From: Andrew Jones @ 2015-03-18 19:10 UTC (permalink / raw)
To: kvmarm, qemu-devel, ard.biesheuvel, christoffer.dall,
marc.zyngier, peter.maydell, pbonzini
Cc: catalin.marinas, lersek, agraf, m.smarduch
When userspace tells us a memory region is uncached, then we
need to pin all its pages and set them all to be uncached.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
arch/arm/include/asm/kvm_mmu.h | 9 +++++
arch/arm/include/uapi/asm/kvm.h | 1 +
arch/arm/kvm/mmu.c | 71 +++++++++++++++++++++++++++++++++++++++
arch/arm64/include/asm/kvm_mmu.h | 9 +++++
arch/arm64/include/uapi/asm/kvm.h | 1 +
5 files changed, 91 insertions(+)
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 37ca2a4c6f094..6802f6adc12bf 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -265,6 +265,15 @@ static inline void __kvm_flush_dcache_pud(pud_t pud)
{
}
+static inline void __set_page_uncached(pte_t *ptep)
+{
+ pte_t pte = *ptep;
+
+ pte = clear_pte_bit(pte, L_PTE_MT_MASK);
+ pte = set_pte_bit(pte, L_PTE_MT_UNCACHED);
+ set_pte_ext(ptep, pte, 0);
+}
+
#define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x))
void kvm_set_way_flush(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 9d6fc19acf8a2..cdd456f591882 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -109,6 +109,7 @@ struct kvm_sync_regs {
};
struct kvm_arch_memory_slot {
+ struct page **pages;
};
/* If you need to interpret the index values, here is the key: */
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 59af5ad779eb6..d4e47572d3a5d 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1697,6 +1697,54 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
kvm_mmu_wp_memory_region(kvm, mem->slot);
}
+static int set_page_uncached(pte_t *ptep, pgtable_t token,
+ unsigned long addr, void *data)
+{
+ __set_page_uncached(ptep);
+ kvm_flush_dcache_pte(*ptep);
+ return 0;
+}
+
+static int vma_range_pin_and_set_uncached(struct vm_area_struct *vma,
+ hva_t start, long nr_pages,
+ struct page **pages)
+{
+ unsigned long size = nr_pages * PAGE_SIZE;
+ int ret;
+
+ down_read(&vma->vm_mm->mmap_sem);
+ ret = get_user_pages(NULL, vma->vm_mm, start, nr_pages,
+ true, true, pages, NULL);
+ up_read(&vma->vm_mm->mmap_sem);
+
+ if (ret < 0)
+ return ret;
+
+ if (ret == nr_pages) {
+ ret = apply_to_page_range(vma->vm_mm, start, size,
+ set_page_uncached, NULL);
+ flush_tlb_kernel_range(start, start + size);
+ return ret;
+ }
+
+ return -EFAULT;
+}
+
+static void unpin_pages(struct kvm_memory_slot *memslot)
+{
+ int i;
+
+ if (!memslot->arch.pages)
+ return;
+
+ for (i = 0; i < memslot->npages; ++i) {
+ if (memslot->arch.pages[i])
+ put_page(memslot->arch.pages[i]);
+ }
+ kfree(memslot->arch.pages);
+ memslot->arch.pages = NULL;
+}
+
int kvm_arch_prepare_memory_region(struct kvm *kvm,
struct kvm_memory_slot *memslot,
struct kvm_userspace_memory_region *mem,
@@ -1705,6 +1753,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
hva_t hva = mem->userspace_addr;
hva_t reg_end = hva + mem->memory_size;
bool writable = !(mem->flags & KVM_MEM_READONLY);
+ struct page **pages = memslot->arch.pages;
int ret = 0;
if (change != KVM_MR_CREATE && change != KVM_MR_MOVE &&
@@ -1768,6 +1817,26 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
writable);
if (ret)
break;
+ } else if ((change != KVM_MR_FLAGS_ONLY)
+ && (memslot->flags & KVM_MEM_UNCACHED)) {
+
+ long nr_pages = (vm_end - vm_start)/PAGE_SIZE;
+
+ if (!pages) {
+ pages = kzalloc(memslot->npages *
+ sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+ memslot->arch.pages = pages;
+ }
+
+ ret = vma_range_pin_and_set_uncached(vma, vm_start,
+ nr_pages, pages);
+ if (ret) {
+ unpin_pages(memslot);
+ break;
+ }
+ pages += nr_pages;
}
hva = vm_end;
} while (hva < reg_end);
@@ -1787,6 +1856,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
struct kvm_memory_slot *dont)
{
+ if (free->flags & KVM_MEM_UNCACHED)
+ unpin_pages(free);
}
int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6458b53731421..f4c3c56587a9f 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -300,6 +300,15 @@ static inline void __kvm_flush_dcache_pud(pud_t pud)
kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
}
+static inline void __set_page_uncached(pte_t *ptep)
+{
+ pte_t pte = *ptep;
+
+ pte = clear_pte_bit(pte, PTE_ATTRINDX_MASK);
+ pte = set_pte_bit(pte, PTE_ATTRINDX(MT_DEVICE_nGnRnE));
+ set_pte(ptep, pte);
+}
+
#define kvm_virt_to_phys(x) __virt_to_phys((unsigned long)(x))
void kvm_set_way_flush(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 5553d112e405b..22b4e4a6da950 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -104,6 +104,7 @@ struct kvm_sync_regs {
};
struct kvm_arch_memory_slot {
+ struct page **pages;
};
/* If you need to interpret the index values, here is the key: */
--
1.8.3.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Andrew Jones
` (2 preceding siblings ...)
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 3/3] arm/arm64: KVM: implement KVM_MEM_UNCACHED Andrew Jones
@ 2015-03-19 16:56 ` Paolo Bonzini
2015-03-19 17:24 ` Andrew Jones
2015-04-29 9:03 ` Alexander Graf
4 siblings, 1 reply; 18+ messages in thread
From: Paolo Bonzini @ 2015-03-19 16:56 UTC (permalink / raw)
To: Andrew Jones, kvmarm, qemu-devel, ard.biesheuvel,
christoffer.dall, marc.zyngier, peter.maydell
Cc: catalin.marinas, lersek, agraf, m.smarduch
On 18/03/2015 20:10, Andrew Jones wrote:
> Introduce a new memory region flag, KVM_MEM_UNCACHED, which
> is needed by ARM. This flag informs KVM that the given memory
> region is typically mapped by the guest as uncached. KVM for
> ARM then maps that region as uncached for userspace as well,
> in order to keep coherency.
>
> Andrew Jones (3):
> KVM: promote KVM_MEMSLOT_INCOHERENT to uapi
> arm/arm64: KVM: decouple READONLY and UNCACHED
> arm/arm64: KVM: implement KVM_MEM_UNCACHED
>
> Documentation/virtual/kvm/api.txt | 16 ++++---
> arch/arm/include/asm/kvm_mmu.h | 9 ++++
> arch/arm/include/uapi/asm/kvm.h | 2 +
> arch/arm/kvm/arm.c | 1 +
> arch/arm/kvm/mmu.c | 90 ++++++++++++++++++++++++++++++++++-----
> arch/arm64/include/asm/kvm_mmu.h | 9 ++++
> arch/arm64/include/uapi/asm/kvm.h | 2 +
> include/linux/kvm_host.h | 1 -
> include/uapi/linux/kvm.h | 2 +
> virt/kvm/kvm_main.c | 7 ++-
> 10 files changed, 121 insertions(+), 18 deletions(-)
>
I think the pinning breaks running KVM as non-root (the default ulimit
-l is just 64 KiB). Can you do something about it with the MMU
notifiers instead?
It looks very clean.
The fly in the ointment is that some kind of quirk is probably needed in
the future for ivshmem---it's definitely not acceptable performance-wise
to mark it uncached, neither in the guests not in the host. On the
other hand that quirk would be necessary only in the guest, not in the
firmware, so we can live with a mixture of the two approaches.
Paolo
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED
2015-03-19 16:56 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Paolo Bonzini
@ 2015-03-19 17:24 ` Andrew Jones
0 siblings, 0 replies; 18+ messages in thread
From: Andrew Jones @ 2015-03-19 17:24 UTC (permalink / raw)
To: Paolo Bonzini
Cc: peter.maydell, ard.biesheuvel, marc.zyngier, catalin.marinas,
qemu-devel, agraf, lersek, kvmarm, christoffer.dall, m.smarduch
On Thu, Mar 19, 2015 at 05:56:20PM +0100, Paolo Bonzini wrote:
>
>
> On 18/03/2015 20:10, Andrew Jones wrote:
> > Introduce a new memory region flag, KVM_MEM_UNCACHED, which
> > is needed by ARM. This flag informs KVM that the given memory
> > region is typically mapped by the guest as uncached. KVM for
> > ARM then maps that region as uncached for userspace as well,
> > in order to keep coherency.
> >
> > Andrew Jones (3):
> > KVM: promote KVM_MEMSLOT_INCOHERENT to uapi
> > arm/arm64: KVM: decouple READONLY and UNCACHED
> > arm/arm64: KVM: implement KVM_MEM_UNCACHED
> >
> > Documentation/virtual/kvm/api.txt | 16 ++++---
> > arch/arm/include/asm/kvm_mmu.h | 9 ++++
> > arch/arm/include/uapi/asm/kvm.h | 2 +
> > arch/arm/kvm/arm.c | 1 +
> > arch/arm/kvm/mmu.c | 90 ++++++++++++++++++++++++++++++++++-----
> > arch/arm64/include/asm/kvm_mmu.h | 9 ++++
> > arch/arm64/include/uapi/asm/kvm.h | 2 +
> > include/linux/kvm_host.h | 1 -
> > include/uapi/linux/kvm.h | 2 +
> > virt/kvm/kvm_main.c | 7 ++-
> > 10 files changed, 121 insertions(+), 18 deletions(-)
> >
Hi Paolo,
Thanks for the comments!
>
> I think the pinning breaks running KVM as non-root (the default ulimit
> -l is just 64 KiB). Can you do something about it with the MMU
> notifiers instead?
I'll look into this as soon as possible. I'm headed out 25 minutes ago
for some vacation time though, so it'll be week or so before I can.
>
> It looks very clean.
>
> The fly in the ointment is that some kind of quirk is probably needed in
> the future for ivshmem---it's definitely not acceptable performance-wise
> to mark it uncached, neither in the guests not in the host. On the
> other hand that quirk would be necessary only in the guest, not in the
> firmware, so we can live with a mixture of the two approaches.
Yes, quirking ivshmem makes sense. ivshmem users (guest drivers) should
ensure they map the memory as cached, as they know it's normal memory
on the host.
drew
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED
2015-03-18 19:10 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Andrew Jones
` (3 preceding siblings ...)
2015-03-19 16:56 ` [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED Paolo Bonzini
@ 2015-04-29 9:03 ` Alexander Graf
2015-04-29 9:19 ` Peter Maydell
4 siblings, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2015-04-29 9:03 UTC (permalink / raw)
To: Andrew Jones, kvmarm, qemu-devel, ard.biesheuvel,
christoffer.dall, marc.zyngier, peter.maydell, pbonzini
Cc: catalin.marinas, lersek, m.smarduch
On 18.03.15 20:10, Andrew Jones wrote:
> Introduce a new memory region flag, KVM_MEM_UNCACHED, which
> is needed by ARM. This flag informs KVM that the given memory
> region is typically mapped by the guest as uncached. KVM for
> ARM then maps that region as uncached for userspace as well,
> in order to keep coherency.
I finally managed to give this a spin and immediately ran into an
unaligned access trap:
[ 116.509976] Unhandled fault: alignment fault (0x92000061) at
0x000003ffb1300000
Program received signal SIGBUS, Bus error.
[Switching to Thread 0x3ffb317ecb0 (LWP 1956)]
0x000003ffb685ed68 in memset () from /lib64/libc.so.6
(gdb) bt
#0 0x000003ffb685ed68 in memset () from /lib64/libc.so.6
#1 0x000002aaaac013ec in memset (__len=<optimized out>, __ch=0,
__dest=<optimized out>) at /usr/include/bits/string3.h:90
#2 vbe_ioport_write_data (opaque=0x2aaabbd3600, addr=<optimized out>,
val=65) at /usr/src/debug/qemu-2.3.0-rc4/hw/display/vga.c:739
#3 0x000002aaaabe07dc in memory_region_write_accessor (mr=<optimized
out>, addr=<optimized out>, value=<optimized out>, size=<optimized out>,
shift=<optimized out>, mask=<optimized out>) at
/usr/src/debug/qemu-2.3.0-rc4/memory.c:430
[...]
So maybe forcing the guest to see VRAM as cached is the safer choice
after all?
Alex
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED
2015-04-29 9:03 ` Alexander Graf
@ 2015-04-29 9:19 ` Peter Maydell
2015-04-29 11:19 ` Andrew Jones
0 siblings, 1 reply; 18+ messages in thread
From: Peter Maydell @ 2015-04-29 9:19 UTC (permalink / raw)
To: Alexander Graf
Cc: Andrew Jones, Ard Biesheuvel, Marc Zyngier, Catalin Marinas,
QEMU Developers, Paolo Bonzini, Laszlo Ersek,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Mario Smarduch
On 29 April 2015 at 10:03, Alexander Graf <agraf@suse.de> wrote:
>
>
> On 18.03.15 20:10, Andrew Jones wrote:
>> Introduce a new memory region flag, KVM_MEM_UNCACHED, which
>> is needed by ARM. This flag informs KVM that the given memory
>> region is typically mapped by the guest as uncached. KVM for
>> ARM then maps that region as uncached for userspace as well,
>> in order to keep coherency.
>
> I finally managed to give this a spin and immediately ran into an
> unaligned access trap:
>
> [ 116.509976] Unhandled fault: alignment fault (0x92000061) at
> 0x000003ffb1300000
>
> Program received signal SIGBUS, Bus error.
> [Switching to Thread 0x3ffb317ecb0 (LWP 1956)]
> 0x000003ffb685ed68 in memset () from /lib64/libc.so.6
> (gdb) bt
> #0 0x000003ffb685ed68 in memset () from /lib64/libc.so.6
> #1 0x000002aaaac013ec in memset (__len=<optimized out>, __ch=0,
> __dest=<optimized out>) at /usr/include/bits/string3.h:90
> #2 vbe_ioport_write_data (opaque=0x2aaabbd3600, addr=<optimized out>,
> val=65) at /usr/src/debug/qemu-2.3.0-rc4/hw/display/vga.c:739
> #3 0x000002aaaabe07dc in memory_region_write_accessor (mr=<optimized
> out>, addr=<optimized out>, value=<optimized out>, size=<optimized out>,
> shift=<optimized out>, mask=<optimized out>) at
> /usr/src/debug/qemu-2.3.0-rc4/memory.c:430
> [...]
This appears to be because the KVM_MEM_UNCACHED flag
confusingly isn't marking the memory as Normal-Noncacheable
but as Device-nGnRnE (aka Strongly Ordered). You can't unalignedly
access Device memory (and so you can't use the usual userspace
memcpy, memset, etc).
Did we really want Device-nGnRnE memory here? If we did can
we have a less confusing name for the flag?
[for the non-ARM folk, nGnRnE == no gathering of accesses,
no reordering, no early-write-acknowledgement.]
thanks
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH 0/3] KVM: Introduce KVM_MEM_UNCACHED
2015-04-29 9:19 ` Peter Maydell
@ 2015-04-29 11:19 ` Andrew Jones
0 siblings, 0 replies; 18+ messages in thread
From: Andrew Jones @ 2015-04-29 11:19 UTC (permalink / raw)
To: Peter Maydell
Cc: Ard Biesheuvel, Marc Zyngier, Catalin Marinas, QEMU Developers,
Alexander Graf, Paolo Bonzini, Laszlo Ersek,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Mario Smarduch
On Wed, Apr 29, 2015 at 10:19:55AM +0100, Peter Maydell wrote:
> On 29 April 2015 at 10:03, Alexander Graf <agraf@suse.de> wrote:
> >
> >
> > On 18.03.15 20:10, Andrew Jones wrote:
> >> Introduce a new memory region flag, KVM_MEM_UNCACHED, which
> >> is needed by ARM. This flag informs KVM that the given memory
> >> region is typically mapped by the guest as uncached. KVM for
> >> ARM then maps that region as uncached for userspace as well,
> >> in order to keep coherency.
> >
> > I finally managed to give this a spin and immediately ran into an
> > unaligned access trap:
Thanks! And err.. sorry it broke.
> >
> > [ 116.509976] Unhandled fault: alignment fault (0x92000061) at
> > 0x000003ffb1300000
> >
> > Program received signal SIGBUS, Bus error.
> > [Switching to Thread 0x3ffb317ecb0 (LWP 1956)]
> > 0x000003ffb685ed68 in memset () from /lib64/libc.so.6
> > (gdb) bt
> > #0 0x000003ffb685ed68 in memset () from /lib64/libc.so.6
> > #1 0x000002aaaac013ec in memset (__len=<optimized out>, __ch=0,
> > __dest=<optimized out>) at /usr/include/bits/string3.h:90
> > #2 vbe_ioport_write_data (opaque=0x2aaabbd3600, addr=<optimized out>,
> > val=65) at /usr/src/debug/qemu-2.3.0-rc4/hw/display/vga.c:739
> > #3 0x000002aaaabe07dc in memory_region_write_accessor (mr=<optimized
> > out>, addr=<optimized out>, value=<optimized out>, size=<optimized out>,
> > shift=<optimized out>, mask=<optimized out>) at
> > /usr/src/debug/qemu-2.3.0-rc4/memory.c:430
> > [...]
>
> This appears to be because the KVM_MEM_UNCACHED flag
> confusingly isn't marking the memory as Normal-Noncacheable
> but as Device-nGnRnE (aka Strongly Ordered). You can't unalignedly
> access Device memory (and so you can't use the usual userspace
> memcpy, memset, etc).
>
> Did we really want Device-nGnRnE memory here? If we did can
> we have a less confusing name for the flag?
I hadn't considered the other side-effects of going with device
vs. normal memory. I'll change patch 3/3 with
31c31
< + pte = set_pte_bit(pte, L_PTE_MT_UNCACHED);
---
> + pte = set_pte_bit(pte, L_PTE_MT_WRITEBACK);
166c166
< + pte = set_pte_bit(pte, PTE_ATTRINDX(MT_DEVICE_nGnRnE));
---
> + pte = set_pte_bit(pte, PTE_ATTRINDX(MT_NORMAL_NC));
I've left this on the backburner too long, but I can pick it back
up on Monday. I still haven't looked at Paolo's mmu notifier
suggestion yet either. I'll start looking at that as well.
Thanks,
drew
>
> [for the non-ARM folk, nGnRnE == no gathering of accesses,
> no reordering, no early-write-acknowledgement.]
>
> thanks
> -- PMM
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread