Page MenuHomeFreeBSD

Add support to switch the arm64 EL2 vector after boot
Needs ReviewPublic

Authored by andrew on Aug 17 2020, 1:04 PM.

Details

Summary

When loading a hypervisor into EL2 we need to switch the exception
vector base address to one provide by the hypervisor. Allow for this
by providing a way to do this via a hypervisor call instruction.

Obtained from: https://github.com/FreeBSD-UPB/freebsd (earlier version)

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 36678
Build 33567: arc lint + arc unit

Event Timeline

I'm interested in reviewing the patch, I'll try to set aside some time for it.

@andrew, for bhyve on arm64 patches, would you mind adding me as a reviewer with my alexandru.elisei@arm email address from now on?

sys/arm64/arm64/hyp_stub.S
3

@alexandru.elisei_arm.com Are you happy for me to remove All rights reserved? We've been removing them recently as they are no longer needed.

sys/arm64/arm64/hyp_stub.S
52

The argument seems to be unused.

59

Typo, haandler

sys/arm64/arm64/hyp_stub.S
3

Sure, please feel free to remove it, from this file, and from any other files where I'm one of the authors.

  • Remove "All rights reserved"
  • Fix spelling
  • Use the argument to vector_tail
sys/arm64/arm64/hyp_stub.S
52

The argument is still there.

sys/arm64/arm64/hyp_stub.S
52

It's used in vector_el1h_sync

sys/arm64/arm64/locore.S
233

I'm not sure about the purpose of this instruction. I remember copying it from where we disable the MMU from EL1 (after drop_to_el1 returns), but now I can't figure out why this is used. If the MMU is off, it doesn't do anything because data accesses are to Device-nGnRnE memory according to ARM DDI 0487F.b, page D5-2586 (the PE reads and writes directly to main memory).

If the MMU is on, I believe this still has no effect because:

  1. Before this point, the kernel hasn't performed any explicit memory accesses, so why do a DSB?
  2. I'm speculating, but if this is done as a cheap dcache clean, The PE can speculate data reads and instruction fetches (both are cached in clean cache lines) after the instruction terminates and before we disable the MMU.
  3. I'm not 100% sure of this, but the definition of DSB from ARM DDI 0487F.b, page B2-138, only talks about data accesses that come in program order before the barrier, it doesn't say anything about reordering the instruction itself. I think the DSB can be reordered at any point in the program as long as it allowed by the barrier definition.
236

I haven't been reading the code, but I haven't found where the dcache is invalidated before the MMU is turned on at EL1. Where is that done?

298

According to the definition of a context synchronization event from ARM DDI 0487F.b, page Glossary-8112, the isb and eret instructions are equivalent. I believe this isb is redundant.

sys/arm64/arm64/locore.S
236

In the normal boot process we expect the bootloader to have invalidated the dcache

sys/arm64/arm64/locore.S
236

The patch itself looks alright to me, but I haven't tested it.

As for why I think FreeBSD should do dcache invalidation before turning the MMU back on, wall of text below.

I've been reading the Arm ARM ARM DDI 0487F.b trying to find out exactly what a CPU is allowed to speculate, and I've only found what is *not* able to speculate (section B2.3.6 "Restrictions on the effects of speculation"). From that I assume the CPU is able to speculate *any* loads regardless of the program order, and modify the dcache as a result. This gets somewhat confirmed by the definition of the SB (Speculation Barrier) instruction (page C6-1188):

"In particular, any instruction that appears later in the program order than the barrier cannot cause a speculative allocation into any caching structure where the allocation of that entry could be
indicative of any data value present in memory or in the registers."

My interpretation of that statement is that without the barrier, the PE is allowed to modify the dcache as a result of speculation.

This is the definition of Device memory from page B2-117:

"The Arm architecture forbids Speculative reads of any type of Device memory. This means Device memory types are suitable attributes for read-sensitive Locations."

When address translation is disabled, data accesses are to Device-nGnRnE memory type (page D5-2586).

The point I am trying to make is that as long as the MMU is enabled (SCTLR_ELx.M == 1), the PE is allowed to speculate any loads and modify the dcache. This is something that FreeBSD allows the bootloader to do.

The other side of the story is that even if FreeBSD starts execution with the MMU disabled, if it's running under a hypervisor, the dcaches might have been populated while the host was running on the same PE (either intentionally or as a result of speculation). As a result, dcache invalidation must be performed right before the MMU is turned on (after the last load in program order, to be more precise), so any speculative reads on the host side will populate the dcache with the latest values that the guest wrote to memory.

I hope what I wrote above makes sense.

Rebase after locore.S changes

sys/arm64/arm64/locore.S
236

Which memory do you think needs d-cache management? As far as I can tell we should invalidate the d-cache for the page tables as there may be data for them in the cache, however we create them with the cache disabled.

Remove an unneeded instruction