use super::reader::GuestMem;
use super::symbols::kva_to_pa;
pub(crate) const XA_CHUNK_SIZE: u64 = 64;
pub(crate) fn translate_any_kva(
mem: &GuestMem,
cr3_pa: u64,
page_offset: u64,
kva: u64,
l5: bool,
) -> Option<u64> {
let direct_pa = kva_to_pa(kva, page_offset);
if direct_pa < mem.size() {
return Some(direct_pa);
}
mem.translate_kva(cr3_pa, kva, l5)
}
pub(crate) fn xa_load(
mem: &GuestMem,
page_offset: u64,
xa_head: u64,
index: u64,
slots_off: usize,
shift_off: usize,
) -> Option<u64> {
if xa_head == 0 {
return Some(0);
}
if xa_head & 2 == 0 {
return if index == 0 { Some(xa_head) } else { Some(0) };
}
let mut node_kva = xa_head & !3u64;
let mut shift = xa_node_shift(mem, page_offset, node_kva, shift_off);
loop {
let slot_idx = (index >> shift) & (XA_CHUNK_SIZE - 1);
let slot_pa = kva_to_pa(node_kva + slots_off as u64 + slot_idx * 8, page_offset);
let entry = mem.read_u64(slot_pa, 0);
if entry == 0 {
return Some(0);
}
if entry & 2 == 0 {
return Some(entry);
}
node_kva = entry & !3u64;
if shift < 6 {
return Some(0);
}
shift -= 6; }
}
pub(crate) fn xa_node_shift(
mem: &GuestMem,
page_offset: u64,
node_kva: u64,
shift_off: usize,
) -> u64 {
let pa = kva_to_pa(node_kva, page_offset);
mem.read_u8(pa, shift_off) as u64
}