From cfea17a5a8b27a97a7a2b3a622c80394a5995330 Mon Sep 17 00:00:00 2001 From: marcus Date: Wed, 27 Oct 2004 20:14:51 +0000 Subject: 2004-10-27 Marcus Brinkmann * l4/gnu/space.h (l4_fpage_xspan): New function. --- libl4/ChangeLog | 4 ++++ libl4/l4/gnu/space.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) (limited to 'libl4') 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 + + * l4/gnu/space.h (l4_fpage_xspan): New function. + 2004-10-23 Marcus Brinkmann * 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; +} -- cgit v1.2.3