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
next prev 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).