blob: 7684e4952847f55becc6f864f8455a53b71c85f3 [file] [log] [blame]
/* Copyright (c) 2016 Google Inc.
* Barret Rhoden <brho@cs.berkeley.edu>
* See LICENSE for details.
*
* Getters and setters for FS Base and GS base. */
#pragma once
#include <cpu_feat.h>
#include <arch/x86.h>
static inline uintptr_t read_fsbase(void)
{
uintptr_t base;
if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE))
return read_msr(MSR_FS_BASE);
asm volatile ("rdfsbase %0" : "=r"(base));
return base;
}
static inline void write_fsbase(uintptr_t base)
{
if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE)) {
write_msr(MSR_FS_BASE, base);
return;
}
asm volatile ("wrfsbase %0" : : "r"(base));
}
static inline uintptr_t read_gsbase(void)
{
uintptr_t base;
if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE))
return read_msr(MSR_GS_BASE);
asm volatile ("rdgsbase %0" : "=r"(base));
return base;
}
static inline void write_gsbase(uintptr_t base)
{
if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE)) {
write_msr(MSR_GS_BASE, base);
return;
}
asm volatile ("wrgsbase %0" : : "r"(base));
}
/* If we have fast FS/GS access, we can use swapgs to quickly access
* kern_gsbase. */
static inline uintptr_t read_kern_gsbase(void)
{
uintptr_t base;
int8_t irq_state = 0;
if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE))
return read_msr(MSR_KERNEL_GS_BASE);
disable_irqsave(&irq_state);
swap_gs();
base = read_gsbase();
swap_gs();
enable_irqsave(&irq_state);
return base;
}
static inline void write_kern_gsbase(uintptr_t base)
{
int8_t irq_state = 0;
if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE)) {
write_msr(MSR_KERNEL_GS_BASE, base);
return;
}
disable_irqsave(&irq_state);
swap_gs();
write_gsbase(base);
swap_gs();
enable_irqsave(&irq_state);
}