487 lines
7.4 KiB
C
487 lines
7.4 KiB
C
/*
|
|
* Copyright (c) 2013-2018 Ali Mashtizadeh
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#ifndef __AMD64OP_H__
|
|
#define __AMD64OP_H__
|
|
|
|
static INLINE void enable_interrupts()
|
|
{
|
|
__asm__ volatile("sti");
|
|
}
|
|
|
|
static INLINE void disable_interrupts()
|
|
{
|
|
__asm__ volatile("cli");
|
|
}
|
|
|
|
static INLINE void hlt()
|
|
{
|
|
__asm__ volatile("hlt");
|
|
}
|
|
|
|
static INLINE void pause()
|
|
{
|
|
__asm__ volatile("pause");
|
|
}
|
|
|
|
static INLINE void breakpoint()
|
|
{
|
|
__asm__ volatile("int3");
|
|
}
|
|
|
|
static INLINE void icebp()
|
|
{
|
|
__asm__ volatile(".byte 0xf1");
|
|
}
|
|
|
|
static INLINE uint64_t rdtsc()
|
|
{
|
|
uint32_t lo, hi;
|
|
|
|
__asm__ volatile("rdtsc"
|
|
: "=a" (lo), "=d" (hi));
|
|
|
|
return ((uint64_t)hi << 32) | (uint64_t)lo;
|
|
}
|
|
|
|
static INLINE uint64_t rdtscp(uint32_t *procno)
|
|
{
|
|
uint32_t lo, hi, proc;
|
|
|
|
__asm__ volatile("rdtsc"
|
|
: "=a" (lo), "=d" (hi), "=c" (proc));
|
|
|
|
if (procno)
|
|
*procno = proc;
|
|
|
|
return ((uint64_t)hi << 32) | (uint64_t)lo;
|
|
}
|
|
|
|
static INLINE void lidt(PseudoDescriptor *idt)
|
|
{
|
|
__asm__ volatile("lidt (%0)"
|
|
:
|
|
: "r" (idt)
|
|
: "memory");
|
|
}
|
|
|
|
static INLINE void lgdt(PseudoDescriptor *gdt)
|
|
{
|
|
__asm__ volatile("lgdt (%0)"
|
|
:
|
|
: "r" (gdt)
|
|
: "memory");
|
|
}
|
|
|
|
static INLINE void ltr(uint16_t tss)
|
|
{
|
|
__asm__ volatile("ltr %0"
|
|
:
|
|
: "r" (tss));
|
|
}
|
|
|
|
static INLINE void cpuid(uint32_t info, uint32_t *eax, uint32_t *ebx,
|
|
uint32_t *ecx, uint32_t *edx)
|
|
{
|
|
uint32_t a, b, c, d;
|
|
|
|
__asm__ volatile("cpuid"
|
|
: "=a" (a), "=b" (b), "=c" (c), "=d" (d)
|
|
: "a" (info));
|
|
|
|
if (eax)
|
|
*eax = a;
|
|
if (ebx)
|
|
*ebx = b;
|
|
if (ecx)
|
|
*ecx = c;
|
|
if (edx)
|
|
*edx = d;
|
|
}
|
|
|
|
static INLINE void wrmsr(uint32_t addr, uint64_t val)
|
|
{
|
|
uint32_t eax = val & 0xFFFFFFFF;
|
|
uint32_t edx = val >> 32;
|
|
|
|
__asm__ volatile("wrmsr"
|
|
:
|
|
: "a" (eax), "c" (addr), "d" (edx));
|
|
}
|
|
|
|
static INLINE uint64_t rdmsr(uint32_t addr)
|
|
{
|
|
uint64_t eax, edx;
|
|
|
|
__asm__ volatile("rdmsr"
|
|
: "=a" (eax), "=d" (edx)
|
|
: "c" (addr));
|
|
|
|
return edx << 32 | eax;
|
|
}
|
|
|
|
/*
|
|
* Control Registers
|
|
*/
|
|
|
|
static INLINE uint64_t read_cr0()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%cr0, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_cr0(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%cr0"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint64_t read_cr2()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%cr2, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE uint64_t read_cr3()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%cr3, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_cr3(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%cr3"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint64_t read_cr4()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%cr4, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_cr4(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%cr4"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
/*
|
|
* Debug Registers
|
|
*/
|
|
|
|
static INLINE uint64_t read_dr0()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%dr0, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_dr0(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%dr0"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint64_t read_dr1()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%dr1, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_dr1(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%dr1"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint64_t read_dr2()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%dr2, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_dr2(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%dr2"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint64_t read_dr3()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%dr3, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_dr3(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%dr3"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint64_t read_dr6()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%dr6, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_dr6(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%dr6"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint64_t read_dr7()
|
|
{
|
|
uint64_t val;
|
|
|
|
__asm__ volatile("movq %%dr7, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_dr7(uint64_t val)
|
|
{
|
|
__asm__ volatile("movq %0, %%dr7"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
/*
|
|
* Segment Registers
|
|
*/
|
|
|
|
static INLINE uint16_t read_ds()
|
|
{
|
|
uint16_t val;
|
|
|
|
__asm__ volatile("movw %%ds, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_ds(uint16_t val)
|
|
{
|
|
__asm__ volatile("movw %0, %%ds"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint16_t read_es()
|
|
{
|
|
uint16_t val;
|
|
|
|
__asm__ volatile("movw %%es, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_es(uint16_t val)
|
|
{
|
|
__asm__ volatile("movw %0, %%es"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint16_t read_fs()
|
|
{
|
|
uint16_t val;
|
|
|
|
__asm__ volatile("movw %%fs, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_fs(uint16_t val)
|
|
{
|
|
__asm__ volatile("movw %0, %%fs"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
static INLINE uint16_t read_gs()
|
|
{
|
|
uint16_t val;
|
|
|
|
__asm__ volatile("movw %%gs, %0"
|
|
: "=r" (val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static INLINE void write_gs(uint16_t val)
|
|
{
|
|
__asm__ volatile("movw %0, %%gs"
|
|
:
|
|
: "r" (val));
|
|
}
|
|
|
|
/*
|
|
* Floating Point
|
|
*/
|
|
|
|
static INLINE void clts()
|
|
{
|
|
__asm__ volatile("clts");
|
|
}
|
|
|
|
static INLINE void fxsave(struct XSAVEArea *xsa)
|
|
{
|
|
__asm__ volatile("fxsave %0"
|
|
: "=m" (*xsa)
|
|
:
|
|
: "memory");
|
|
}
|
|
|
|
// XXX: Need to fix AMD Bug
|
|
static INLINE void fxrstor(struct XSAVEArea *xsa)
|
|
{
|
|
__asm__ volatile("fxrstor %0"
|
|
:
|
|
: "m" (*xsa)
|
|
: "memory");
|
|
}
|
|
|
|
static INLINE void xsave(struct XSAVEArea *xsa, uint64_t mask)
|
|
{
|
|
uint32_t lo = (uint32_t)mask;
|
|
uint32_t hi = (uint32_t)(mask >> 32);
|
|
|
|
__asm__ volatile("xsave %0"
|
|
: "=m" (*xsa)
|
|
: "a" (lo), "d" (hi)
|
|
: "memory");
|
|
}
|
|
|
|
static INLINE void xsaveopt(struct XSAVEArea *xsa, uint64_t mask)
|
|
{
|
|
uint32_t lo = (uint32_t)mask;
|
|
uint32_t hi = (uint32_t)(mask >> 32);
|
|
|
|
__asm__ volatile("xsaveopt %0"
|
|
: "=m" (*xsa)
|
|
: "a" (lo), "d" (hi)
|
|
: "memory");
|
|
}
|
|
|
|
static INLINE void xrstor(struct XSAVEArea *xsa, uint64_t mask)
|
|
{
|
|
uint32_t lo = (uint32_t)mask;
|
|
uint32_t hi = (uint32_t)(mask >> 32);
|
|
|
|
__asm__ volatile("xrstor %0"
|
|
:
|
|
: "m" (*xsa), "a" (lo), "d" (hi)
|
|
: "memory");
|
|
}
|
|
|
|
/*
|
|
* Port IO
|
|
*/
|
|
|
|
static INLINE void outb(uint16_t port, uint8_t data)
|
|
{
|
|
__asm__ volatile("outb %0, %1"
|
|
:
|
|
: "a" (data), "d" (port));
|
|
}
|
|
|
|
static INLINE void outw(uint16_t port, uint16_t data)
|
|
{
|
|
__asm__ volatile("outw %0, %1"
|
|
:
|
|
: "a" (data), "d" (port));
|
|
}
|
|
|
|
static INLINE void outl(uint16_t port, uint32_t data)
|
|
{
|
|
__asm__ volatile("outl %0, %1"
|
|
:
|
|
: "a" (data), "d" (port));
|
|
}
|
|
|
|
static INLINE uint8_t inb(uint16_t port)
|
|
{
|
|
uint8_t data;
|
|
|
|
__asm__ volatile("inb %1, %0"
|
|
: "=a" (data)
|
|
:"d" (port));
|
|
|
|
return data;
|
|
}
|
|
|
|
static INLINE uint16_t inw(uint16_t port)
|
|
{
|
|
uint16_t data;
|
|
|
|
__asm__ volatile("inw %1, %0"
|
|
: "=a" (data)
|
|
:"d" (port));
|
|
|
|
return data;
|
|
}
|
|
|
|
static INLINE uint32_t inl(uint16_t port)
|
|
{
|
|
uint32_t data;
|
|
|
|
__asm__ volatile("inl %1, %0"
|
|
: "=a" (data)
|
|
:"d" (port));
|
|
|
|
return data;
|
|
}
|
|
|
|
#endif /* __AMD64OP_H__ */
|
|
|