Comment

Comment by pavehawk2007

I don't think it's as cut and dry as "execute sfence.vma every time you write to SATP" as you say for the following reasons.

1. The sfence.vma is much like a TLB flush. Just like a normal fence, it ensures that orderings are done properly. The privileged spec says this in section 4.2.1. In fact, a parenthetical tells us that "The SFENCE.VMA is used to flush any local hardware caches related to address translation."

2. The sfence.vma has three formats. sfence.vma x0, x0, sfence.vma x? (!= 0), x0, and sfence.vma x0, x? (!= 0). This allows us to flush certain addresses from the translation lookaside buffer (TLB) so that the newly updated page tables are updated in this buffer.

3. You don't have to call sfence.vma every time you write to the SATP. This would thrash the TLB every time you context switch. Please see page 66 of the privileged spec (20190608 and more recent versions).

4. If you see the original tutorial this blog post is based on, you can see that I use sfence.vma with the ASID which is the process ID. That way there, the address space and process ID are equivalent so that when I transfer the process to another hart, I can execute sfence.vma x? where x? contains the ASID. If I add a mapping, such as sbrk or mmap, then I can call sfence.vma x0, x? where x? contains the specific page I want updated.

5. If we use PMP (physical memory protection), the specification tells us to use sfence.vma x0, x0 to update in case the hart speculates before we use those particular addresses (see section 3.6.2 in the privileged SPEC).

6. The code I show updating the SATP is the same code we used in the original tutorial: https://osblog.stephenmarz.com. In this case, I use sfence.vma when I update a mapping, transfer a process to another hart, or when I create a new process.

Maybe I'm wrong, but my reading of the SFENCE.VMA instruction combined with the fact that we have multiple versions and the ability to TLB shootdown an entire address space or a single page tells me that it isn't "execute sfence.vma every time SATP is written."

In conclusion, I don't use sfence.vma every time I write to SATP. Instead, I use it when there is a memory ordering issue, such as starting a new process, updating a mapping, or transferring a process to another hart. In this case, we wouldn't do this in the code that switches us to a userspace process, since this is invoked every time we do a context switch.

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton