Skip to content

Commit

Permalink
YJIT: Fix page rounding for icache busting
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
XrXr committed Oct 21, 2022
1 parent 8bbcb75 commit 87bb0be
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions yjit/src/asm/mod.rs
Expand Up @@ -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();
}
Expand Down

0 comments on commit 87bb0be

Please sign in to comment.