Skip to content

Commit

Permalink
RISCV64: Use va_kernel_pa_offset in VTOP()
Browse files Browse the repository at this point in the history
Since RISC-V Linux v6.4, the commit 3335068f8721 ("riscv: Use
PUD/P4D/PGD pages for the linear mapping") changes phys_ram_base from
the physical start of the kernel to the actual start of the DRAM.

The Crash's VTOP() still uses phys_ram_base and kernel_map.virt_addr
to translate kernel virtual address, that made Crash boot failed with
Linux v6.4 and later version.

Let Linux export kernel_map.va_kernel_pa_offset in v6.5 and backported
v6.4.0 stable, so Crash can use "va_kernel_pa_offset" to translate the
kernel virtual address in VTOP() correctly.

Signed-off-by: Song Shuai <suagrfillet@gmail.com>
  • Loading branch information
Song Shuai authored and k-hagio committed Aug 16, 2023
1 parent 69f38d7 commit ff963b7
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
4 changes: 2 additions & 2 deletions defs.h
Expand Up @@ -3663,8 +3663,7 @@ typedef signed int s32;
ulong _X = X; \
(THIS_KERNEL_VERSION >= LINUX(5,13,0) && \
(_X) >= machdep->machspec->kernel_link_addr) ? \
(((unsigned long)(_X)-(machdep->machspec->kernel_link_addr)) + \
machdep->machspec->phys_base): \
((unsigned long)(_X)-(machdep->machspec->va_kernel_pa_offset)): \
(((unsigned long)(_X)-(machdep->kvbase)) + \
machdep->machspec->phys_base); \
})
Expand Down Expand Up @@ -7022,6 +7021,7 @@ struct machine_specific {
ulong modules_vaddr;
ulong modules_end;
ulong kernel_link_addr;
ulong va_kernel_pa_offset;

ulong _page_present;
ulong _page_read;
Expand Down
23 changes: 23 additions & 0 deletions riscv64.c
Expand Up @@ -418,6 +418,28 @@ static void riscv64_get_va_range(struct machine_specific *ms)
error(FATAL, "cannot get vm layout\n");
}

static void
riscv64_get_va_kernel_pa_offset(struct machine_specific *ms)
{
unsigned long kernel_version = riscv64_get_kernel_version();

/*
* Since Linux v6.4 phys_base is not the physical start of the kernel,
* trying to use "va_kernel_pa_offset" to determine the offset between
* kernel virtual and physical addresses.
*/
if (kernel_version >= LINUX(6,4,0)) {
char *string;
if ((string = pc->read_vmcoreinfo("NUMBER(va_kernel_pa_offset)"))) {
ms->va_kernel_pa_offset = htol(string, QUIET, NULL);
free(string);
} else
error(FATAL, "cannot read va_kernel_pa_offset\n");
}
else
ms->va_kernel_pa_offset = ms->kernel_link_addr - ms->phys_base;
}

static int
riscv64_is_kvaddr(ulong vaddr)
{
Expand Down Expand Up @@ -1352,6 +1374,7 @@ riscv64_init(int when)
riscv64_get_struct_page_size(machdep->machspec);
riscv64_get_va_bits(machdep->machspec);
riscv64_get_va_range(machdep->machspec);
riscv64_get_va_kernel_pa_offset(machdep->machspec);

pt_level_alloc(&machdep->pgd, "cannot malloc pgd space.");
pt_level_alloc(&machdep->machspec->p4d, "cannot malloc p4d space.");
Expand Down

0 comments on commit ff963b7

Please sign in to comment.