| 109 | inline VAddr xa_to_node(VAddr e) { return e & ~3ULL; } |
| 110 | |
| 111 | void walk_pidns_xarray(const Engine& eng, u64 xn_slots_off, |
| 112 | VAddr entry, std::vector<VAddr>& leaves, |
| 113 | std::size_t& budget, int depth = 0) { |
| 114 | if (entry == 0 || depth > 16) return; |
| 115 | if (budget == 0) return; // bound a crafted cyclic/explosive xarray |
| 116 | --budget; |
| 117 | if (xa_is_value(entry)) return; |
| 118 | if (!xa_is_internal(entry)) { leaves.push_back(entry); return; } |
| 119 | VAddr node = xa_to_node(entry); |
| 120 | constexpr u64 kSlots = 64; |
| 121 | std::vector<VAddr> slots(kSlots, 0); |
| 122 | if (!kva_read(eng, node + xn_slots_off, slots.data(), |
| 123 | kSlots * sizeof(VAddr))) return; |
| 124 | for (u64 i = 0; i < kSlots; ++i) |
| 125 | if (slots[i]) walk_pidns_xarray(eng, xn_slots_off, slots[i], leaves, budget, depth + 1); |
| 126 | } |
| 127 | } // anonymous |
| 128 | |
| 129 | ByteBuf format_pidhashtable(const Engine& eng) { |
no test coverage detected