xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Ian Campbell <ian.campbell@citrix.com>
To: xen-devel@lists.xen.org
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
	tim@xen.org, stefano.stabelini@citrix.com
Subject: [PATCH 04/21] xen/arm: implement page reference and gnttab functions needed by grant_table.c
Date: Fri, 5 Oct 2012 10:38:10 +0000	[thread overview]
Message-ID: <1349433507-21148-4-git-send-email-ian.campbell@citrix.com> (raw)
In-Reply-To: <1349433418.20946.46.camel@zakaz.uk.xensource.com>

From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

The implementation is strongly "inspired" by their x86 counterparts,
except that we assume paging_mode_external and paging_mode_translate.

TODO: read_only mappings and gnttab_mark_dirty.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/dummy.S |    9 ----
 xen/arch/arm/mm.c    |  115 ++++++++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/p2m.c   |   77 +++++++++++++++++++++++----------
 3 files changed, 168 insertions(+), 33 deletions(-)

diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S
index 5406077..aaf1ff1 100644
--- a/xen/arch/arm/dummy.S
+++ b/xen/arch/arm/dummy.S
@@ -23,18 +23,10 @@ DUMMY(arch_vcpu_reset);
 NOP(update_vcpu_system_time);
 
 /* Page Reference & Type Maintenance */
-DUMMY(get_page);
 DUMMY(get_page_type);
-DUMMY(page_get_owner_and_reference);
-DUMMY(put_page);
 DUMMY(put_page_type);
 
 /* Grant Tables */
-DUMMY(create_grant_host_mapping);
-DUMMY(gnttab_clear_flag);
-DUMMY(gnttab_mark_dirty);
-DUMMY(is_iomem_page);
-DUMMY(replace_grant_host_mapping);
 DUMMY(steal_page);
 
 /* Page Offlining */
@@ -45,7 +37,6 @@ DUMMY(domain_get_maximum_gpfn);
 DUMMY(domain_relinquish_resources);
 DUMMY(domain_set_time_offset);
 DUMMY(dom_cow);
-DUMMY(gmfn_to_mfn);
 DUMMY(send_timer_event);
 DUMMY(share_xen_page_with_privileged_guests);
 DUMMY(wallclock_time);
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index dde304b..8191c90 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -617,6 +617,121 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
 
     return 0;
 }
+
+struct domain *page_get_owner_and_reference(struct page_info *page)
+{
+    unsigned long x, y = page->count_info;
+
+    do {
+        x = y;
+        /*
+         * Count ==  0: Page is not allocated, so we cannot take a reference.
+         * Count == -1: Reference count would wrap, which is invalid.
+         */
+        if ( unlikely(((x + 1) & PGC_count_mask) <= 1) )
+            return NULL;
+    }
+    while ( (y = cmpxchg(&page->count_info, x, x + 1)) != x );
+
+    return page_get_owner(page);
+}
+
+void put_page(struct page_info *page)
+{
+    unsigned long nx, x, y = page->count_info;
+
+    do {
+        ASSERT((y & PGC_count_mask) != 0);
+        x  = y;
+        nx = x - 1;
+    }
+    while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) );
+
+    if ( unlikely((nx & PGC_count_mask) == 0) )
+    {
+        free_domheap_page(page);
+    }
+}
+
+int get_page(struct page_info *page, struct domain *domain)
+{
+    struct domain *owner = page_get_owner_and_reference(page);
+
+    if ( likely(owner == domain) )
+        return 1;
+
+    if ( owner != NULL )
+        put_page(page);
+
+    return 0;
+}
+
+void gnttab_clear_flag(unsigned long nr, uint16_t *addr)
+{
+    /*
+     * Note that this cannot be clear_bit(), as the access must be
+     * confined to the specified 2 bytes.
+     */
+    uint16_t mask = ~(1 << nr), old;
+
+    do {
+        old = *addr;
+    } while (cmpxchg(addr, old, old & mask) != old);
+}
+
+void gnttab_mark_dirty(struct domain *d, unsigned long l)
+{
+    /* XXX: mark dirty */
+    static int warning;
+    if (!warning) {
+        gdprintk(XENLOG_WARNING, "gnttab_mark_dirty not implemented yet\n");
+        warning = 1;
+    }
+}
+
+int create_grant_host_mapping(unsigned long addr, unsigned long frame,
+                              unsigned int flags, unsigned int cache_flags)
+{
+    int rc;
+
+    if ( cache_flags  || (flags & ~GNTMAP_readonly) != GNTMAP_host_map )
+        return GNTST_general_error;
+
+    /* XXX: read only mappings */
+    if ( flags & GNTMAP_readonly )
+    {
+        gdprintk(XENLOG_WARNING, "read only mappings not implemented yet\n");
+        return GNTST_general_error;
+    }
+
+    rc = guest_physmap_add_page(current->domain,
+                                 addr >> PAGE_SHIFT, frame, 0);
+    if ( rc )
+        return GNTST_general_error;
+    else
+        return GNTST_okay;
+}
+
+int replace_grant_host_mapping(unsigned long addr, unsigned long mfn,
+        unsigned long new_addr, unsigned int flags)
+{
+    unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
+    struct domain *d = current->domain;
+
+    if ( new_addr != 0 || (flags & GNTMAP_contains_pte) )
+        return GNTST_general_error;
+
+    guest_physmap_remove_page(d, gfn, mfn, 0);
+
+    return GNTST_okay;
+}
+
+int is_iomem_page(unsigned long mfn)
+{
+    if ( !mfn_valid(mfn) )
+        return 1;
+    return 0;
+}
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 073216b..7c23b7d 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -120,8 +120,14 @@ static int p2m_create_table(struct domain *d,
     return 0;
 }
 
+enum p2m_operation {
+    INSERT,
+    ALLOCATE,
+    REMOVE
+};
+
 static int create_p2m_entries(struct domain *d,
-                     int alloc,
+                     enum p2m_operation op,
                      paddr_t start_gpaddr,
                      paddr_t end_gpaddr,
                      paddr_t maddr,
@@ -191,25 +197,39 @@ static int create_p2m_entries(struct domain *d,
         }
 
         /* Allocate a new RAM page and attach */
-        if (alloc)
-        {
-            struct page_info *page;
-            lpae_t pte;
-
-            rc = -ENOMEM;
-            page = alloc_domheap_page(d, 0);
-            if ( page == NULL ) {
-                printk("p2m_populate_ram: failed to allocate page\n");
-                goto out;
-            }
-
-            pte = mfn_to_p2m_entry(page_to_mfn(page), mattr);
-
-            write_pte(&third[third_table_offset(addr)], pte);
-        } else {
-            lpae_t pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT, mattr);
-            write_pte(&third[third_table_offset(addr)], pte);
-            maddr += PAGE_SIZE;
+        switch (op) {
+            case ALLOCATE:
+                {
+                    struct page_info *page;
+                    lpae_t pte;
+
+                    rc = -ENOMEM;
+                    page = alloc_domheap_page(d, 0);
+                    if ( page == NULL ) {
+                        printk("p2m_populate_ram: failed to allocate page\n");
+                        goto out;
+                    }
+
+                    pte = mfn_to_p2m_entry(page_to_mfn(page), mattr);
+
+                    write_pte(&third[third_table_offset(addr)], pte);
+                }
+                break;
+            case INSERT:
+                {
+                    lpae_t pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT, mattr);
+                    write_pte(&third[third_table_offset(addr)], pte);
+                    maddr += PAGE_SIZE;
+                }
+                break;
+            case REMOVE:
+                {
+                    lpae_t pte;
+                    memset(&pte, 0x00, sizeof(pte));
+                    write_pte(&third[third_table_offset(addr)], pte);
+                    maddr += PAGE_SIZE;
+                }
+                break;
         }
     }
 
@@ -229,7 +249,7 @@ int p2m_populate_ram(struct domain *d,
                      paddr_t start,
                      paddr_t end)
 {
-    return create_p2m_entries(d, 1, start, end, 0, MATTR_MEM);
+    return create_p2m_entries(d, ALLOCATE, start, end, 0, MATTR_MEM);
 }
 
 int map_mmio_regions(struct domain *d,
@@ -237,7 +257,7 @@ int map_mmio_regions(struct domain *d,
                      paddr_t end_gaddr,
                      paddr_t maddr)
 {
-    return create_p2m_entries(d, 0, start_gaddr, end_gaddr, maddr, MATTR_DEV);
+    return create_p2m_entries(d, INSERT, start_gaddr, end_gaddr, maddr, MATTR_DEV);
 }
 
 int guest_physmap_add_page(struct domain *d,
@@ -245,7 +265,7 @@ int guest_physmap_add_page(struct domain *d,
                            unsigned long mfn,
                            unsigned int page_order)
 {
-    return create_p2m_entries(d, 0, gpfn << PAGE_SHIFT,
+    return create_p2m_entries(d, INSERT, gpfn << PAGE_SHIFT,
                               (gpfn + (1<<page_order)) << PAGE_SHIFT,
                               mfn << PAGE_SHIFT, MATTR_MEM);
 }
@@ -254,7 +274,9 @@ void guest_physmap_remove_page(struct domain *d,
                                unsigned long gpfn,
                                unsigned long mfn, unsigned int page_order)
 {
-    ASSERT(0);
+    create_p2m_entries(d, REMOVE, gpfn << PAGE_SHIFT,
+                       (gpfn + (1<<page_order)) << PAGE_SHIFT,
+                       mfn << PAGE_SHIFT, MATTR_MEM);
 }
 
 int p2m_alloc_table(struct domain *d)
@@ -318,6 +340,13 @@ int p2m_init(struct domain *d)
 
     return 0;
 }
+
+unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn)
+{
+    paddr_t p = p2m_lookup(d, gpfn << PAGE_SHIFT);
+    return p >> PAGE_SHIFT;
+}
+
 /*
  * Local variables:
  * mode: C
-- 
1.7.9.1

  parent reply	other threads:[~2012-10-05 10:38 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-05 10:36 [PATCH 00/21] Sweep through arm-for-4.3 branch + a bit extra Ian Campbell
2012-10-05 10:38 ` [PATCH 01/21] xen: arm: implement XENMEM_add_to_physmap_range Ian Campbell
2012-10-08 13:42   ` Ian Campbell
2012-10-05 10:38 ` [PATCH 02/21] libxc: add ARM support to xc_dom (PV domain building) Ian Campbell
2012-10-05 10:38 ` [PATCH 03/21] arm: implement VGCF_online Ian Campbell
2012-10-05 10:38 ` Ian Campbell [this message]
2012-10-05 10:38 ` [PATCH 05/21] xen/arm: implement get/put_page_type Ian Campbell
2012-10-05 10:38 ` [PATCH 06/21] xen/arm: create_p2m_entries should not call free_domheap_page Ian Campbell
2012-10-05 10:38 ` [PATCH 07/21] xen/arm: grant table Ian Campbell
2012-10-05 10:38 ` [PATCH 08/21] arm: kill a guest which uses hvc with an immediate operand != XEN_HYPERCALL_TAG Ian Campbell
2012-10-05 10:38 ` [PATCH 09/21] libxc/arm: allocate xenstore and console pages Ian Campbell
2012-10-05 10:38 ` [PATCH 10/21] arm: disable distributor delivery on boot CPU only Ian Campbell
2012-10-05 10:38 ` [PATCH 11/21] xen/arm: protect LR registers and lr_mask changes with spin_lock_irq Ian Campbell
2012-10-05 10:38 ` [PATCH 12/21] xen/arm: introduce __lshrdi3 and __aeabi_llsr Ian Campbell
2012-10-05 10:38 ` [PATCH 13/21] arm: don't bother setting up vtimer, vgic etc on idle CPUs Ian Campbell
2012-10-05 10:38 ` [PATCH 14/21] arm/vtimer: convert result to ticks when reading CNTPCT register Ian Campbell
2012-10-05 10:38 ` [PATCH 15/21] arm: Use per-CPU irq_desc for PPIs and SGIs Ian Campbell
2012-10-05 10:38 ` [PATCH 16/21] arm: tools: add arm to foreign structs checking Ian Campbell
2012-10-05 10:38 ` [PATCH 17/21] xen: xen_ulong_t substitution Ian Campbell
2012-10-05 11:00   ` Jan Beulich
2012-10-05 11:03     ` Ian Campbell
2012-10-05 14:13     ` Stefano Stabellini
2012-10-08 13:45       ` Ian Campbell
2012-10-05 16:08   ` Ian Campbell
2012-10-09 12:39     ` Stefano Stabellini
2012-10-09 12:49       ` Ian Campbell
2012-10-09 12:51         ` Stefano Stabellini
2012-10-09 13:05           ` Ian Campbell
2012-10-05 10:38 ` [PATCH 18/21] xen: change the limit of nr_extents to UINT_MAX >> MEMOP_EXTENT_SHIFT Ian Campbell
2012-10-05 11:02   ` Jan Beulich
2012-10-05 11:05     ` Ian Campbell
2012-10-05 10:38 ` [PATCH 19/21] xen: introduce XEN_GUEST_HANDLE_PARAM Ian Campbell
2012-10-05 11:05   ` Jan Beulich
2012-10-05 11:09     ` Ian Campbell
2012-10-05 11:20       ` Jan Beulich
2012-10-05 11:24         ` Ian Campbell
2012-10-05 10:38 ` [PATCH 20/21] xen: replace XEN_GUEST_HANDLE with XEN_GUEST_HANDLE_PARAM when appropriate Ian Campbell
2012-10-05 11:06   ` Jan Beulich
2012-10-05 14:15     ` Stefano Stabellini
2012-10-05 11:30   ` Ian Campbell
2012-10-05 11:43     ` Jan Beulich
2012-10-05 12:12       ` Ian Campbell
2012-10-05 12:28         ` Jan Beulich
2012-10-05 10:38 ` [PATCH 21/21] xen: more substitutions Ian Campbell
2012-10-05 11:09   ` Jan Beulich
2012-10-05 11:14     ` Ian Campbell
2012-10-05 11:33       ` Jan Beulich
2012-10-05 11:40         ` Ian Campbell
2012-10-05 11:52           ` Jan Beulich
2012-10-05 11:29   ` Jan Beulich
2012-10-05 14:51     ` Stefano Stabellini
2012-10-09 14:06 ` [PATCH 00/21] Sweep through arm-for-4.3 branch + a bit extra Ian Campbell

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=1349433507-21148-4-git-send-email-ian.campbell@citrix.com \
    --to=ian.campbell@citrix.com \
    --cc=stefano.stabelini@citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=tim@xen.org \
    --cc=xen-devel@lists.xen.org \
    /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).