From cf2c5550aab71e0e1e4eb10692fe9e769ab11534 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Tue, 5 Dec 2017 19:22:29 +0000 Subject: [PATCH] Fix sign extension bug in `next_table_address` (#372) Fixes #362 Fix an issue where the left shift of the old table address would overwrite the sign extension, making the address non-canonical and leading to #GPs. This calculates the correct sign extension for the new table address. --- src/memory/paging/table.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/memory/paging/table.rs b/src/memory/paging/table.rs index ec370894..f94afc42 100644 --- a/src/memory/paging/table.rs +++ b/src/memory/paging/table.rs @@ -31,6 +31,15 @@ where } } +/* + * Addresses are expected to be canonical (bits 48-63 must be the same as bit 47), otherwise the + * CPU will #GP when we ask it to translate it. + */ +fn make_address_canonical(address : usize) -> usize { + let sign_extension = 0o177777_000_000_000_000_0000 * ((address >> 47) & 0b1); + (address & ((1 << 48) - 1)) | sign_extension +} + impl Table where L: HierarchicalLevel, @@ -39,7 +48,7 @@ where let entry_flags = self[index].flags(); if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) { let table_address = self as *const _ as usize; - Some((table_address << 9) | (index << 12)) + Some(make_address_canonical((table_address << 9) | (index << 12))) } else { None }