Skip to content

Commit

Permalink
s390x: fix virtual address translation on Linux >= 6.10
Browse files Browse the repository at this point in the history
Since Linux kernel commit c98d2ecae08f ("s390/mm: Uncouple physical vs
virtual address spaces") (in v6.10), kernel virtual addresses in the
direct mapping are no longer equal to physical addresses on s390x. This
broke our s390x page table iterator, which still assumes that they are
equal. The fix is easy: treat the top-level page table address as
virtual like we do for every other architecture.

Fixes #433.

Suggested-by: Sven Schnelle <[email protected]>
Signed-off-by: Omar Sandoval <[email protected]>
  • Loading branch information
osandov committed Oct 4, 2024
1 parent 0fa4f53 commit 92c133e
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/support_matrix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ of this support is:
* - s390x
- ✓
- ✓
- ✓ (`currently broken on Linux ≥ 6.10 <https://github.com/osandov/drgn/issues/433>`_)
- ✓
* - ppc64
- ✓
- ✓
Expand Down
7 changes: 5 additions & 2 deletions libdrgn/arch_s390x.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ linux_kernel_pgtable_iterator_next_s390x(struct drgn_program *prog,
container_of(_it, struct pgtable_iterator_s390x, it);
const uint64_t va = it->it.virt_addr;
uint64_t table = _it->pgtable & ~UINT64_C(0xfff);
bool table_physical = false;
int level, length = 2048, offset = 0;
uint64_t entry;

Expand All @@ -403,7 +404,7 @@ linux_kernel_pgtable_iterator_next_s390x(struct drgn_program *prog,
* the linux kernel does: read the first level entry, and deduct the
* number of levels from the TT bits.
*/
struct drgn_error *err = drgn_program_read_u64(prog, table, true,
struct drgn_error *err = drgn_program_read_u64(prog, table, false,
&entry);
if (err)
return err;
Expand All @@ -430,7 +431,8 @@ linux_kernel_pgtable_iterator_next_s390x(struct drgn_program *prog,
*/
err = drgn_program_read_memory(prog,
it->pagetable[level].entries,
table, length * 8, true);
table, length * 8,
table_physical);
if (err)
return err;

Expand All @@ -452,6 +454,7 @@ linux_kernel_pgtable_iterator_next_s390x(struct drgn_program *prog,

bool is_large;
table = get_table_address(entry, level, &is_large);
table_physical = true;

if (level == 0 || is_large) {
uint64_t mask = get_level_mask(level);
Expand Down

0 comments on commit 92c133e

Please sign in to comment.