Page MenuHomeFreeBSD

Set the address of translation table for thread0.
ClosedPublic

Authored by br on Dec 18 2017, 11:00 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Nov 19, 9:30 PM
Unknown Object (File)
Fri, Nov 15, 7:22 AM
Unknown Object (File)
Fri, Nov 15, 7:22 AM
Unknown Object (File)
Sat, Nov 9, 12:32 PM
Unknown Object (File)
Tue, Nov 5, 1:01 AM
Unknown Object (File)
Sun, Nov 3, 1:25 PM
Unknown Object (File)
Oct 21 2024, 4:18 AM
Unknown Object (File)
Oct 2 2024, 9:03 PM
Subscribers

Details

Summary

We need a correct value of ttbr0 to operate. I am not sure why it is zero in my case.

When scheduler returns us back to thread0 we need to have correct ttbr0 value so hardware page walker can translate addresses.
This value will be loaded to ttbr0 register in cpu_switch() function called by scheduler.

This is similar to RISC-V where we already do this.

This is a fix for Qualcomm Snapdragon 410E (Cortex A-53) SoC used in DragonBoard 410c.
Without this fix the Qualcomm board goes to reboot on any access to VA space.

UPDATE:
My comment is wrong, we don't need ttbr0 for address translation in kernel, because ttbr0 is user page table base register.
However it looks like Qualcomm (And Nvidia?) proceed a sanity check, and writing 0 to this register leads to reboot on Qualcomm.
So based on this and similar to other kernel threads, do install the value of kernel pmap L0 directory to TTBR0.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

I can confirm same issue on Cortex-A72. Loading zero to TTBR0_EL1 causes immediate exception (in sched_switch+0x3a0).

@meloun-miracle-cz that is, this fix works for you as well?

yes, but the fix looks incorrect for me.
I think that we can have same problem with secondary cores(idle threads). Imho, cpu_startup() is more appropriate place for this and we should derive TTBR0 value from kernel_pmap[1]. See arm version of cpu_startup() and call to pmap_set_pcb_pagedir(kernel_pmap, pcb); .

[1] Yes I know that these kernel_pmap is initialized with abp->kern_l0pt - but my proposal is more readable/consistent fir new kernel thread creation.

Read the TTBR0 register instead of calculating the value.
Suggested by andrew@.

Nice, this looks OK for me
But,it seems that there are some related problems:

  • the PCB for proc0/thread0 is allocated on top of stack, from dirty memory, but not all fields are not initialized - this is probably a root cause why this bug is not visible on all boards.
  • we leaks initial low memory mappings in kernel_pmap. This can results to double mappings with different attributes which is undefined behavior. Imho, we should clear all mappings in low memory region.
In D13536#283757, @meloun-miracle-cz wrote:

Nice, this looks OK for me
But,it seems that there are some related problems:

  • the PCB for proc0/thread0 is allocated on top of stack, from dirty memory, but not all fields are not initialized - this is probably a root cause why this bug is not visible on all boards.
  • we leaks initial low memory mappings in kernel_pmap. This can results to double mappings with different attributes which is undefined behavior. Imho, we should clear all mappings in low memory region.

These should be fixed, but in a separate patch.

sys/arm64/arm64/machdep.c
720–721 ↗(On Diff #36814)

This can use the READ_SPECIALREG macro to read the value.

This revision is now accepted and ready to land.Jan 18 2018, 3:49 PM
This revision was automatically updated to reflect the committed changes.