summaryrefslogtreecommitdiff
path: root/libl4
diff options
context:
space:
mode:
authormarcus <marcus>2004-10-27 20:14:51 +0000
committermarcus <marcus>2004-10-27 20:14:51 +0000
commitcfea17a5a8b27a97a7a2b3a622c80394a5995330 (patch)
tree4216c725ba5a914028805d0efbd9aacb96a18739 /libl4
parent3454bf5c17ce27245859596c9a62c260ba060924 (diff)
2004-10-27 Marcus Brinkmann <marcus@gnu.org>
* l4/gnu/space.h (l4_fpage_xspan): New function.
Diffstat (limited to 'libl4')
-rw-r--r--libl4/ChangeLog4
-rw-r--r--libl4/l4/gnu/space.h62
2 files changed, 66 insertions, 0 deletions
diff --git a/libl4/ChangeLog b/libl4/ChangeLog
index c466bf4..ac7e267 100644
--- a/libl4/ChangeLog
+++ b/libl4/ChangeLog
@@ -1,3 +1,7 @@
+2004-10-27 Marcus Brinkmann <marcus@gnu.org>
+
+ * l4/gnu/space.h (l4_fpage_xspan): New function.
+
2004-10-23 Marcus Brinkmann <marcus@gnu.org>
* l4/gnu/ipc.h (l4_ipc, l4_lipc): New functions.
diff --git a/libl4/l4/gnu/space.h b/libl4/l4/gnu/space.h
index 9ae560e..a09b1ba 100644
--- a/libl4/l4/gnu/space.h
+++ b/libl4/l4/gnu/space.h
@@ -288,3 +288,65 @@ l4_fpage_span (l4_word_t start, l4_word_t end, l4_fpage_t *fpages)
return nr_fpages;
}
+
+
+/* Determine the fpages covering the (page aligned) virtual address
+ space from START to END (inclusive) under the conditions that it is
+ going to be mapped (or granted) to the virtual address DEST. START
+ and DEST must be page aligned, while END must be the address of the
+ last byte in the area. MAX_FPAGES is the count of available fpages
+ that can be stored at FPAGES. The actual number required can be
+ very large (thousands and tens of thousands) due to bad alignment.
+ The function returns the number of fpages returned in FPAGES. The
+ generated fpages are fully accessible. */
+static inline unsigned int
+l4_fpage_xspan (l4_word_t start, l4_word_t end, l4_word_t dest,
+ l4_fpage_t *fpages, l4_word_t max_fpages)
+{
+ l4_word_t min_page_size = l4_min_page_size ();
+ unsigned int nr_fpages = 0;
+
+ if (start > end)
+ return 0;
+
+ /* Round START and DEST down to a multiple of the minimum page size. */
+ start &= ~(min_page_size - 1);
+ dest &= ~(min_page_size - 1);
+
+ /* Round END up to one less than a multiple of the minimum page size. */
+ end = (end & ~(min_page_size - 1)) + min_page_size - 1;
+
+ end = ((end + min_page_size) & ~(min_page_size - 1)) - 1;
+
+ /* END is now at least MIN_PAGE_SIZE - 1 larger than START. */
+ do
+ {
+ unsigned int addr_align;
+ unsigned int dest_align;
+ unsigned int size_align;
+
+ /* Each fpage must be self-aligned. */
+ addr_align = start ? l4_lsb (start) - 1 : (_L4_MAX_PAGE_SIZE_LOG2 - 1);
+ dest_align = dest ? l4_lsb (dest) - 1 : (_L4_MAX_PAGE_SIZE_LOG2 - 1);
+ size_align = (end + 1 - start) ? l4_msb (end + 1 - start) - 1
+ : (_L4_MAX_PAGE_SIZE_LOG2 - 1);
+
+ if (addr_align < size_align)
+ size_align = addr_align;
+ if (dest_align < size_align)
+ size_align = dest_align;
+
+ fpages[nr_fpages]
+ = l4_fpage_add_rights (l4_fpage_log2 (start, size_align),
+ L4_FPAGE_FULLY_ACCESSIBLE);
+
+ /* This may overflow and result in zero. In that case, the
+ while loop will terminate. */
+ start += l4_size (fpages[nr_fpages]);
+ dest += l4_size (fpages[nr_fpages]);
+ nr_fpages++;
+ }
+ while (start && start < end && nr_fpages < max_fpages);
+
+ return nr_fpages;
+}