blob: c481ac6446ea8286f5fb76290c62498aa25e30cc [file] [log] [blame]
/*
* Copyright 2019 Google LLC
*
* Licensed under both the 3-Clause BSD License and the GPLv2, found in the
* LICENSE and LICENSE.GPL-2.0 files, respectively, in the root directory.
*
* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*/
#include "compiler_specifics.h"
#include "utils.h"
#include <cstddef>
#include <iostream>
#if SAFESIDE_LINUX
#include <sched.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include "hardware_constants.h"
#include "instr.h"
namespace {
// Returns the address of the first byte of the cache line *after* the one on
// which `addr` falls.
const void* StartOfNextCacheLine(const void* addr) {
auto addr_n = reinterpret_cast<uintptr_t>(addr);
// Create an address on the next cache line, then mask it to round it down to
// cache line alignment.
auto next_n = (addr_n + kCacheLineBytes) & ~(kCacheLineBytes - 1);
return reinterpret_cast<const void*>(next_n);
}
} // namespace
void FlushFromDataCache(const void *begin, const void *end) {
for (; begin < end; begin = StartOfNextCacheLine(begin)) {
FlushDataCacheLineNoBarrier(begin);
}
MemoryAndSpeculationBarrier();
}
// This implementation delays the retirement of later instructions by making
// them wait for an uncached read. We arrange the read so it is unlikely to
// interfere with the cache state of other data.
void ExtendSpeculationWindow() {
// Choose an address with at least kPageBytes padding before and after. That
// ensures our memory access will be on its own page and reduces the chance
// it will interfere with caching or prefetching of other data.
//
// A more clever implementation might use 2*kPageBytes + kCacheLineBytes.
static char buffer[3 * kPageBytes] = {0};
const char* read_offset = &buffer[kPageBytes];
FlushFromDataCache(read_offset, read_offset + 1);
ForceRead(read_offset);
}
#if SAFESIDE_LINUX
void PinToTheFirstCore() {
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(0, &set);
int res = sched_setaffinity(getpid(), sizeof(set), &set);
if (res != 0) {
std::cout << "CPU affinity setup failed." << std::endl;
exit(EXIT_FAILURE);
}
}
#endif