mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
arm64 mm: asid and tlb support
Some optimizations in this pr: 1, Move ASID from TTBR0 to TTBR1 2, tlb_flush_all Signed-off-by: Bin Lu <bin.lu@arm.com>
This commit is contained in:
@@ -79,7 +79,7 @@ func (c *vCPU) initArchState() error {
|
||||
}
|
||||
|
||||
// tcr_el1
|
||||
data = _TCR_TXSZ_VA48 | _TCR_CACHE_FLAGS | _TCR_SHARED | _TCR_TG_FLAGS | _TCR_ASID16 | _TCR_IPS_40BITS
|
||||
data = _TCR_TXSZ_VA48 | _TCR_CACHE_FLAGS | _TCR_SHARED | _TCR_TG_FLAGS | _TCR_ASID16 | _TCR_IPS_40BITS | _TCR_A1
|
||||
reg.id = _KVM_ARM64_REGS_TCR_EL1
|
||||
if err := c.setOneRegister(®); err != nil {
|
||||
return err
|
||||
@@ -103,7 +103,7 @@ func (c *vCPU) initArchState() error {
|
||||
c.SetTtbr0Kvm(uintptr(data))
|
||||
|
||||
// ttbr1_el1
|
||||
data = c.machine.kernel.PageTables.TTBR1_EL1(false, 0)
|
||||
data = c.machine.kernel.PageTables.TTBR1_EL1(false, 1)
|
||||
|
||||
reg.id = _KVM_ARM64_REGS_TTBR1_EL1
|
||||
if err := c.setOneRegister(®); err != nil {
|
||||
|
||||
@@ -77,6 +77,9 @@ type CPUArchState struct {
|
||||
|
||||
// lazyVFP is the value of cpacr_el1.
|
||||
lazyVFP uintptr
|
||||
|
||||
// appASID is the asid value of guest application.
|
||||
appASID uintptr
|
||||
}
|
||||
|
||||
// ErrorCode returns the last error code.
|
||||
|
||||
@@ -300,17 +300,23 @@
|
||||
|
||||
// SWITCH_TO_APP_PAGETABLE sets a new pagetable for a container application.
|
||||
#define SWITCH_TO_APP_PAGETABLE(from) \
|
||||
MOVD CPU_TTBR0_APP(from), RSV_REG; \
|
||||
WORD $0xd5182012; \ // MSR R18, TTBR0_EL1
|
||||
MRS TTBR1_EL1, R0; \
|
||||
MOVD CPU_APP_ASID(from), R1; \
|
||||
BFI $48, R1, $16, R0; \
|
||||
MSR R0, TTBR1_EL1; \ // set the ASID in TTBR1_EL1 (since TCR.A1 is set)
|
||||
ISB $15; \
|
||||
DSB $15;
|
||||
MOVD CPU_TTBR0_APP(from), RSV_REG; \
|
||||
MSR RSV_REG, TTBR0_EL1;
|
||||
|
||||
// SWITCH_TO_KVM_PAGETABLE sets the kvm pagetable.
|
||||
#define SWITCH_TO_KVM_PAGETABLE(from) \
|
||||
MOVD CPU_TTBR0_KVM(from), RSV_REG; \
|
||||
WORD $0xd5182012; \ // MSR R18, TTBR0_EL1
|
||||
MRS TTBR1_EL1, R0; \
|
||||
MOVD $1, R1; \
|
||||
BFI $48, R1, $16, R0; \
|
||||
MSR R0, TTBR1_EL1; \
|
||||
ISB $15; \
|
||||
DSB $15;
|
||||
MOVD CPU_TTBR0_KVM(from), RSV_REG; \
|
||||
MSR RSV_REG, TTBR0_EL1;
|
||||
|
||||
#define VFP_ENABLE \
|
||||
MOVD $FPEN_ENABLE, R0; \
|
||||
@@ -326,23 +332,20 @@
|
||||
#define KERNEL_ENTRY_FROM_EL0 \
|
||||
SUB $16, RSP, RSP; \ // step1, save r18, r9 into kernel temporary stack.
|
||||
STP (RSV_REG, RSV_REG_APP), 16*0(RSP); \
|
||||
WORD $0xd538d092; \ //MRS TPIDR_EL1, R18, step2, switch user pagetable.
|
||||
SWITCH_TO_KVM_PAGETABLE(RSV_REG); \
|
||||
WORD $0xd538d092; \ //MRS TPIDR_EL1, R18
|
||||
MOVD CPU_APP_ADDR(RSV_REG), RSV_REG_APP; \ // step3, load app context pointer.
|
||||
REGISTERS_SAVE(RSV_REG_APP, 0); \ // step4, save app context.
|
||||
WORD $0xd538d092; \ // MRS TPIDR_EL1, R18
|
||||
MOVD CPU_APP_ADDR(RSV_REG), RSV_REG_APP; \ // step2, load app context pointer.
|
||||
REGISTERS_SAVE(RSV_REG_APP, 0); \ // step3, save app context.
|
||||
MOVD RSV_REG_APP, R20; \
|
||||
LDP 16*0(RSP), (RSV_REG, RSV_REG_APP); \
|
||||
ADD $16, RSP, RSP; \
|
||||
MOVD RSV_REG, PTRACE_R18(R20); \
|
||||
MOVD RSV_REG_APP, PTRACE_R9(R20); \
|
||||
MOVD R20, RSV_REG_APP; \
|
||||
WORD $0xd5384003; \ // MRS SPSR_EL1, R3
|
||||
MOVD R3, PTRACE_PSTATE(RSV_REG_APP); \
|
||||
MOVD R3, PTRACE_PSTATE(R20); \
|
||||
MRS ELR_EL1, R3; \
|
||||
MOVD R3, PTRACE_PC(RSV_REG_APP); \
|
||||
MOVD R3, PTRACE_PC(R20); \
|
||||
WORD $0xd5384103; \ // MRS SP_EL0, R3
|
||||
MOVD R3, PTRACE_SP(RSV_REG_APP);
|
||||
MOVD R3, PTRACE_SP(R20);
|
||||
|
||||
// KERNEL_ENTRY_FROM_EL1 is the entry code of the vcpu from el1 to el1.
|
||||
#define KERNEL_ENTRY_FROM_EL1 \
|
||||
@@ -357,6 +360,13 @@
|
||||
MOVD R4, CPU_REGISTERS+PTRACE_SP(RSV_REG); \
|
||||
LOAD_KERNEL_STACK(RSV_REG); // Load the temporary stack.
|
||||
|
||||
// storeAppASID writes the application's asid value.
|
||||
TEXT ·storeAppASID(SB),NOSPLIT,$0-8
|
||||
MOVD asid+0(FP), R1
|
||||
MRS TPIDR_EL1, RSV_REG
|
||||
MOVD R1, CPU_APP_ASID(RSV_REG)
|
||||
RET
|
||||
|
||||
// Halt halts execution.
|
||||
TEXT ·Halt(SB),NOSPLIT,$0
|
||||
// Clear bluepill.
|
||||
@@ -414,7 +424,7 @@ TEXT ·Current(SB),NOSPLIT,$0-8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
#define STACK_FRAME_SIZE 16
|
||||
#define STACK_FRAME_SIZE 32
|
||||
|
||||
// kernelExitToEl0 is the entrypoint for application in guest_el0.
|
||||
// Prepare the vcpu environment for container application.
|
||||
@@ -458,15 +468,16 @@ TEXT ·kernelExitToEl0(SB),NOSPLIT,$0
|
||||
|
||||
SUB $STACK_FRAME_SIZE, RSP, RSP
|
||||
STP (RSV_REG, RSV_REG_APP), 16*0(RSP)
|
||||
STP (R0, R1), 16*1(RSP)
|
||||
|
||||
WORD $0xd538d092 //MRS TPIDR_EL1, R18
|
||||
|
||||
SWITCH_TO_APP_PAGETABLE(RSV_REG)
|
||||
|
||||
LDP 16*1(RSP), (R0, R1)
|
||||
LDP 16*0(RSP), (RSV_REG, RSV_REG_APP)
|
||||
ADD $STACK_FRAME_SIZE, RSP, RSP
|
||||
|
||||
ISB $15
|
||||
ERET()
|
||||
|
||||
// kernelExitToEl1 is the entrypoint for sentry in guest_el1.
|
||||
@@ -482,6 +493,9 @@ TEXT ·kernelExitToEl1(SB),NOSPLIT,$0
|
||||
MOVD CPU_REGISTERS+PTRACE_SP(RSV_REG), R1
|
||||
MOVD R1, RSP
|
||||
|
||||
SWITCH_TO_KVM_PAGETABLE(RSV_REG)
|
||||
MRS TPIDR_EL1, RSV_REG
|
||||
|
||||
REGISTERS_LOAD(RSV_REG, CPU_REGISTERS)
|
||||
MOVD CPU_REGISTERS+PTRACE_R9(RSV_REG), RSV_REG_APP
|
||||
|
||||
|
||||
@@ -53,6 +53,11 @@ func IsCanonical(addr uint64) bool {
|
||||
|
||||
//go:nosplit
|
||||
func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
|
||||
storeAppASID(uintptr(switchOpts.UserASID))
|
||||
if switchOpts.Flush {
|
||||
FlushTlbAll()
|
||||
}
|
||||
|
||||
regs := switchOpts.Registers
|
||||
|
||||
regs.Pstate &= ^uint64(PsrFlagsClear)
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
|
||||
package ring0
|
||||
|
||||
// storeAppASID writes the application's asid value.
|
||||
func storeAppASID(asid uintptr)
|
||||
|
||||
// LocalFlushTlbAll same as FlushTlbAll, but only applies to the calling CPU.
|
||||
func LocalFlushTlbAll()
|
||||
|
||||
// FlushTlbAll flush all tlb.
|
||||
func FlushTlbAll()
|
||||
|
||||
// CPACREL1 returns the value of the CPACR_EL1 register.
|
||||
func CPACREL1() (value uintptr)
|
||||
|
||||
|
||||
@@ -15,6 +15,20 @@
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·LocalFlushTlbAll(SB),NOSPLIT,$0
|
||||
DSB $6 // dsb(nshst)
|
||||
WORD $0xd508871f // __tlbi(vmalle1)
|
||||
DSB $7 // dsb(nsh)
|
||||
ISB $15
|
||||
RET
|
||||
|
||||
TEXT ·FlushTlbAll(SB),NOSPLIT,$0
|
||||
DSB $10 // dsb(ishst)
|
||||
WORD $0xd508831f // __tlbi(vmalle1is)
|
||||
DSB $11 // dsb(ish)
|
||||
ISB $15
|
||||
RET
|
||||
|
||||
TEXT ·GetTLS(SB),NOSPLIT,$0-8
|
||||
MRS TPIDR_EL0, R1
|
||||
MOVD R1, ret+0(FP)
|
||||
|
||||
@@ -41,6 +41,7 @@ func Emit(w io.Writer) {
|
||||
fmt.Fprintf(w, "#define CPU_VECTOR_CODE 0x%02x\n", reflect.ValueOf(&c.vecCode).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_APP_ADDR 0x%02x\n", reflect.ValueOf(&c.appAddr).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_LAZY_VFP 0x%02x\n", reflect.ValueOf(&c.lazyVFP).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_APP_ASID 0x%02x\n", reflect.ValueOf(&c.appASID).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
|
||||
fmt.Fprintf(w, "\n// Bits.\n")
|
||||
fmt.Fprintf(w, "#define _KERNEL_FLAGS 0x%02x\n", KernelFlagsSet)
|
||||
|
||||
Reference in New Issue
Block a user