|  | /* 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); | 
|  | } |