aboutsummaryrefslogtreecommitdiffstats
path: root/yjit/src/asm
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2022-10-21 17:06:34 -0400
committerGitHub <noreply@github.com>2022-10-21 17:06:34 -0400
commit87bb0bee6b9843ea32ca6bb48f9e03b1876b7c48 (patch)
tree91d9e8f18c1f7b12c2a606f7cc4b0207ee404269 /yjit/src/asm
parent8bbcb75377fed4e4e7f2a5848e1a21f4dc0efa8c (diff)
downloadruby-87bb0bee6b9843ea32ca6bb48f9e03b1876b7c48.tar.gz
YJIT: Fix page rounding for icache busting
Previously, we found the current page by rounding the current pointer to the closest smaller page size. This is incorrect because pages are relative to the start of the address we reserve. For example, if the starting address is 12KiB modulo the 16KiB page size, once we have more than 4KiB of code, calculating with the address would incorrectly give us page 1 when we're actually still on page 0. Previously, I can reproduce crashes with: make btest RUN_OPTS=--yjit-code-page-size=32 on ARM64 macOS, where system page sizes are 16KiB.
Diffstat (limited to 'yjit/src/asm')
-rw-r--r--yjit/src/asm/mod.rs12
1 files changed, 7 insertions, 5 deletions
diff --git a/yjit/src/asm/mod.rs b/yjit/src/asm/mod.rs
index 61c1523aab..ab7c4d6aba 100644
--- a/yjit/src/asm/mod.rs
+++ b/yjit/src/asm/mod.rs
@@ -217,12 +217,14 @@ impl CodeBlock {
#[cfg(any(feature = "disasm", target_arch = "aarch64"))]
pub fn writable_addrs(&self, start_ptr: CodePtr, end_ptr: CodePtr) -> Vec<(usize, usize)> {
let mut addrs = vec![];
- let mut start = start_ptr.raw_ptr() as usize;
- let codeblock_end = self.get_ptr(self.get_mem_size()).raw_ptr() as usize;
- let end = std::cmp::min(end_ptr.raw_ptr() as usize, codeblock_end);
+ let mut start = start_ptr.into_usize();
+ let region_start = self.get_ptr(0).into_usize();
+ let region_end = self.get_ptr(self.get_mem_size()).into_usize();
+ let end = std::cmp::min(end_ptr.into_usize(), region_end);
while start < end {
- let current_page = start / self.page_size * self.page_size;
- let page_end = std::cmp::min(end, current_page + self.page_end()) as usize;
+ let current_page = region_start +
+ (start.saturating_sub(region_start) / self.page_size * self.page_size);
+ let page_end = std::cmp::min(end, current_page + self.page_end());
addrs.push((start, page_end));
start = current_page + self.page_size + self.page_start();
}