/* SPDX-License-Identifier: GPL-2.0-only */
/*
* tools/testing/selftests/kvm/include/x86_64/processor.h
*
* Copyright (C) 2018, Google LLC.
*/
#ifndef SELFTEST_KVM_PROCESSOR_H
#define SELFTEST_KVM_PROCESSOR_H
#include <assert.h>
#include <stdint.h>
#define X86_EFLAGS_FIXED (1u << 1)
#define X86_CR4_VME (1ul << 0)
#define X86_CR4_PVI (1ul << 1)
#define X86_CR4_TSD (1ul << 2)
#define X86_CR4_DE (1ul << 3)
#define X86_CR4_PSE (1ul << 4)
#define X86_CR4_PAE (1ul << 5)
#define X86_CR4_MCE (1ul << 6)
#define X86_CR4_PGE (1ul << 7)
#define X86_CR4_PCE (1ul << 8)
#define X86_CR4_OSFXSR (1ul << 9)
#define X86_CR4_OSXMMEXCPT (1ul << 10)
#define X86_CR4_UMIP (1ul << 11)
#define X86_CR4_VMXE (1ul << 13)
#define X86_CR4_SMXE (1ul << 14)
#define X86_CR4_FSGSBASE (1ul << 16)
#define X86_CR4_PCIDE (1ul << 17)
#define X86_CR4_OSXSAVE (1ul << 18)
#define X86_CR4_SMEP (1ul << 20)
#define X86_CR4_SMAP (1ul << 21)
#define X86_CR4_PKE (1ul << 22)
/* The enum values match the intruction encoding of each register */
enum x86_register {
RAX = 0,
RCX,
RDX,
RBX,
RSP,
RBP,
RSI,
RDI,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
};
struct desc64 {
uint16_t limit0;
uint16_t base0;
unsigned base1:8, s:1, type:4, dpl:2, p:1;
unsigned limit1:4, avl:1, l:1, db:1, g:1, base2:8;
uint32_t base3;
uint32_t zero1;
} __attribute__((packed));
struct desc_ptr {
uint16_t size;
uint64_t address;
} __attribute__((packed));
static inline uint64_t get_desc64_base(const struct desc64 *desc)
{
return ((uint64_t)desc->base3 << 32) |
(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
}
static inline uint64_t rdtsc(void)
{
uint32_t eax, edx;
/*
* The lfence is to wait (on Intel CPUs) until all previous
* instructions have been executed.
*/
__asm__ __volatile__("lfence; rdtsc" : "=a"(eax), "=d"(edx));
return ((uint64_t)edx) << 32 | eax;
}
static inline uint64_t rdtscp(uint32_t *aux)
{
uint32_t eax, edx;
__asm__ __volatile__("rdtscp" : "=a"(eax), "=d"(edx), "=c"(*aux));
return ((uint64_t)edx) << 32 | eax;
}
static inline uint64_t rdmsr(uint32_t msr)
{
uint32_t a, d;
__asm__ __volatile__("rdmsr" : "=a"(a), "=d"(d) : "c"(msr) : "memory");
return a | ((uint64_t) d << 32);
}
static inline void wrmsr(uint32_t msr, uint64_t value)
{
uint32_t a = value;
uint32_t d = value >> 32;
__asm__ __volatile__("wrmsr" :: "a"(a), "d"(d), "c"(msr) : "memory");
}
static inline uint16_t inw(uint16_t port)
{
uint16_t tmp;
__asm__ __volatile__("in %%dx, %%ax"
: /* output */ "=a" (tmp)
: /* input */ "d" (port));
return tmp;
}
static inline uint16_t get_es(void)
{
uint16_t es;
__asm__ __volatile__("mov %%es, %[es]"
: /* output */ [es]"=rm"(es));
return es;
}
static inline uint16_t get_cs(void)
{
uint16_t cs;
__asm__ __volatile__("mov %%cs, %[cs]"