On 01.07.19 09:29, Pratyush Yadav wrote:
Right now, page_alloc_aligned() can fail to give aligned pages when more
than one page is being allocated. This is because the aligned_start
calculation is flawed.
Taking an example from a test case, let's say 8 pages need to be
allocated. This means an alignment of 15 bits. The mask here is 0x7. If
the page pool's base address is 0xffffc021f000, this gives us
aligned_start = 0x7. This start is clearly not aligned at a 15 bits
boundary (3 bits after shifting by PAGE_SHIFT). It is exactly the
opposite. It will never be aligned except when the page pool start also
happens to be aligned at that boundary.
In the above example, the address of the pointer returned was
0xffffc026e000 which is clearly not 15-bit aligned.
This change fixes this problem. Add align_mask to pool_start, and then
zero out the bottom mask bits. Adding align_mask ensures that
aligned_start is always greater than pool_start.
Signed-off-by: Pratyush Yadav <[email protected]>
---
v2:
As suggested by Jan, simplify aligned_start calculation.
hypervisor/paging.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/hypervisor/paging.c b/hypervisor/paging.c
index 16687a89..4a24c1f6 100644
--- a/hypervisor/paging.c
+++ b/hypervisor/paging.c
@@ -105,13 +105,15 @@ static unsigned long find_next_free_page(struct page_pool
*pool,
static void *page_alloc_internal(struct page_pool *pool, unsigned int num,
unsigned long align_mask)
{
- /* The pool itself might not be aligned as required. */
- unsigned long aligned_start =
- ((unsigned long)pool->base_address >> PAGE_SHIFT) & align_mask;
- unsigned long next = aligned_start;
- unsigned long start, last;
+ unsigned long aligned_start, pool_start, next, start, last;
unsigned int allocated;
+ pool_start = (unsigned long)pool->base_address >> PAGE_SHIFT;
+
+ /* The pool itself might not be aligned as required. */
+ aligned_start = ((pool_start + align_mask) & ~align_mask) - pool_start;
+ next = aligned_start;
+
restart:
/* Forward the search start to the next aligned page. */
if ((next - aligned_start) & align_mask)
Thanks, applied. This should finally close the merge window for the release.
Jan
--
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux
--
You received this message because you are subscribed to the Google Groups
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/jailhouse-dev/ca30179b-8ffc-b273-89e7-568d2d4fb541%40siemens.com.
For more options, visit https://groups.google.com/d/optout.