diff options
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/asm_386.s | 37 | ||||
| -rw-r--r-- | src/runtime/asm_amd64.s | 30 | ||||
| -rw-r--r-- | src/runtime/cpuflags.go | 9 | ||||
| -rw-r--r-- | src/runtime/runtime2.go | 1 |
4 files changed, 49 insertions, 28 deletions
diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 571aa28a9e..b711356822 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -137,9 +137,6 @@ has_cpuid: CMPL AX, $0 JE nocpuinfo - // Figure out how to serialize RDTSC. - // On Intel processors LFENCE is enough. AMD requires MFENCE. - // Don't know about the rest, so let's do MFENCE. CMPL BX, $0x756E6547 // "Genu" JNE notintel CMPL DX, $0x49656E69 // "ineI" @@ -147,7 +144,6 @@ has_cpuid: CMPL CX, $0x6C65746E // "ntel" JNE notintel MOVB $1, runtime·isIntel(SB) - MOVB $1, runtime·lfenceBeforeRdtsc(SB) notintel: // Load EAX=1 cpuid flags @@ -838,19 +834,36 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 // func cputicks() int64 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 + // LFENCE/MFENCE instruction support is dependent on SSE2. + // When no SSE2 support is present do not enforce any serialization + // since using CPUID to serialize the instruction stream is + // very costly. CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE done - CMPB runtime·lfenceBeforeRdtsc(SB), $1 - JNE mfence - LFENCE - JMP done -mfence: - MFENCE + JNE rdtsc + CMPB internal∕cpu·X86+const_offsetX86HasRDTSCP(SB), $1 + JNE fences + // Instruction stream serializing RDTSCP is supported. + // RDTSCP is supported by Intel Nehalem (2008) and + // AMD K8 Rev. F (2006) and newer. + RDTSCP done: - RDTSC MOVL AX, ret_lo+0(FP) MOVL DX, ret_hi+4(FP) RET +fences: + // MFENCE is instruction stream serializing and flushes the + // store buffers on AMD. The serialization semantics of LFENCE on AMD + // are dependent on MSR C001_1029 and CPU generation. + // LFENCE on Intel does wait for all previous instructions to have executed. + // Intel recommends MFENCE;LFENCE in its manuals before RDTSC to have all + // previous instructions executed and all previous loads and stores to globally visible. + // Using MFENCE;LFENCE here aligns the serializing properties without + // runtime detection of CPU manufacturer. + MFENCE + LFENCE +rdtsc: + RDTSC + JMP done TEXT ldt0setup<>(SB),NOSPLIT,$16-0 // set up ldt 7 to point at m0.tls diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index a6b321aa42..3ab6060ec0 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -103,9 +103,6 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 CMPL AX, $0 JE nocpuinfo - // Figure out how to serialize RDTSC. - // On Intel processors LFENCE is enough. AMD requires MFENCE. - // Don't know about the rest, so let's do MFENCE. CMPL BX, $0x756E6547 // "Genu" JNE notintel CMPL DX, $0x49656E69 // "ineI" @@ -113,7 +110,6 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 CMPL CX, $0x6C65746E // "ntel" JNE notintel MOVB $1, runtime·isIntel(SB) - MOVB $1, runtime·lfenceBeforeRdtsc(SB) notintel: // Load EAX=1 cpuid flags @@ -928,18 +924,30 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 // func cputicks() int64 TEXT runtime·cputicks(SB),NOSPLIT,$0-0 - CMPB runtime·lfenceBeforeRdtsc(SB), $1 - JNE mfence - LFENCE - JMP done -mfence: - MFENCE + CMPB internal∕cpu·X86+const_offsetX86HasRDTSCP(SB), $1 + JNE fences + // Instruction stream serializing RDTSCP is supported. + // RDTSCP is supported by Intel Nehalem (2008) and + // AMD K8 Rev. F (2006) and newer. + RDTSCP done: - RDTSC SHLQ $32, DX ADDQ DX, AX MOVQ AX, ret+0(FP) RET +fences: + // MFENCE is instruction stream serializing and flushes the + // store buffers on AMD. The serialization semantics of LFENCE on AMD + // are dependent on MSR C001_1029 and CPU generation. + // LFENCE on Intel does wait for all previous instructions to have executed. + // Intel recommends MFENCE;LFENCE in its manuals before RDTSC to have all + // previous instructions executed and all previous loads and stores to globally visible. + // Using MFENCE;LFENCE here aligns the serializing properties without + // runtime detection of CPU manufacturer. + MFENCE + LFENCE + RDTSC + JMP done // func memhash(p unsafe.Pointer, h, s uintptr) uintptr // hash function using AES hardware instructions diff --git a/src/runtime/cpuflags.go b/src/runtime/cpuflags.go index 5104650c5d..c5291ce4ee 100644 --- a/src/runtime/cpuflags.go +++ b/src/runtime/cpuflags.go @@ -11,10 +11,11 @@ import ( // Offsets into internal/cpu records for use in assembly. const ( - offsetX86HasAVX = unsafe.Offsetof(cpu.X86.HasAVX) - offsetX86HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2) - offsetX86HasERMS = unsafe.Offsetof(cpu.X86.HasERMS) - offsetX86HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2) + offsetX86HasAVX = unsafe.Offsetof(cpu.X86.HasAVX) + offsetX86HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2) + offsetX86HasERMS = unsafe.Offsetof(cpu.X86.HasERMS) + offsetX86HasRDTSCP = unsafe.Offsetof(cpu.X86.HasRDTSCP) + offsetX86HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2) offsetARMHasIDIVA = unsafe.Offsetof(cpu.ARM.HasIDIVA) diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index e4e9ee50b8..271d57e5d0 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -1128,7 +1128,6 @@ var ( // Set on startup in asm_{386,amd64}.s processorVersionInfo uint32 isIntel bool - lfenceBeforeRdtsc bool goarm uint8 // set by cmd/link on arm systems ) |
