1// Copyright 2016 The Fuchsia Authors 2// Copyright (c) 2009 Corey Tabaka 3// 4// Use of this source code is governed by a MIT-style 5// license that can be found in the LICENSE file or at 6// https://opensource.org/licenses/MIT 7 8#include <arch/ops.h> 9#include <arch/x86.h> 10#include <arch/x86/feature.h> 11 12uint32_t arch_dcache_line_size(void) { 13 return x86_get_clflush_line_size(); 14} 15 16uint32_t arch_icache_line_size(void) { 17 return x86_get_clflush_line_size(); 18} 19 20void arch_sync_cache_range(addr_t start, size_t len) { 21 // Invoke cpuid to act as a serializing instruction. This will ensure we 22 // see modifications to future parts of the instruction stream. See 23 // Intel Volume 3, 8.1.3 "Handling Self- and Cross-Modifying Code". cpuid 24 // is the more conservative approach suggested in this section. 25 uint32_t v; 26 cpuid(0, &v, &v, &v, &v); 27} 28 29void arch_invalidate_cache_range(addr_t start, size_t len) { 30} 31 32void arch_clean_cache_range(addr_t start, size_t len) { 33 // TODO: consider wiring up clwb if present 34 arch_clean_invalidate_cache_range(start, len); 35} 36 37void arch_clean_invalidate_cache_range(addr_t start, size_t len) { 38 if (unlikely(!x86_feature_test(X86_FEATURE_CLFLUSH))) { 39 __asm__ volatile("wbinvd"); 40 return; 41 } 42 43 // clflush/clflushopt is present 44 const vaddr_t clsize = x86_get_clflush_line_size(); 45 addr_t end = start + len; 46 addr_t ptr = ROUNDDOWN(start, clsize); 47 48 // TODO: use run time patching to merge these two paths 49 if (likely(x86_feature_test(X86_FEATURE_CLFLUSHOPT))) { 50 while (ptr < end) { 51 __asm__ volatile("clflushopt %0" ::"m"(*(char*)ptr)); 52 ptr += clsize; 53 } 54 } else { 55 while (ptr < end) { 56 __asm__ volatile("clflush %0" ::"m"(*(char*)ptr)); 57 ptr += clsize; 58 } 59 } 60 61 __asm__ volatile("mfence"); 62} 63