⛏️ index : haiku.git

/*
 * Copyright 2018, JΓ©rΓ΄me Duval, jerome.duval@gmail.com.
 * Copyright 2002-2009, Axel DΓΆrfler, axeld@pinc-software.de.
 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
 * Distributed under the terms of the MIT License.
 *
 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
 * Distributed under the terms of the NewOS License.
 */
#ifndef _KERNEL_ARCH_x86_CPUASM_H
#define _KERNEL_ARCH_x86_CPUASM_H


#define nop() __asm__ ("nop"::)

static inline uint64_t
x86_read_msr(uint32_t msr)
{
	uint32_t high, low;
	asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
	return (((uint64_t) high) << 32) | low;
}

static inline void
x86_write_msr(uint32_t msr, uint64_t value)
{
	asm volatile("wrmsr" : : "a" ((uint32_t)value) , "d" ((uint32_t)(value >> 32)), "c" (msr));
}

#define x86_read_cr0() ({ \
	size_t _v; \
	__asm__("mov    %%cr0,%0" : "=r" (_v)); \
	_v; \
})

#define x86_write_cr0(value) \
	__asm__("mov    %0,%%cr0" : : "r" (value))

#define x86_read_cr2() ({ \
	size_t _v; \
	__asm__("mov    %%cr2,%0" : "=r" (_v)); \
	_v; \
})

#define x86_read_cr3() ({ \
	size_t _v; \
	__asm__("mov    %%cr3,%0" : "=r" (_v)); \
	_v; \
})

static inline void
x86_write_cr3(size_t value)
{
	__asm__("mov %0,%%cr3" : : "r" (value) : "memory");
}

#define x86_read_cr4() ({ \
	size_t _v; \
	__asm__("mov    %%cr4,%0" : "=r" (_v)); \
	_v; \
})

#define x86_write_cr4(value) \
	__asm__("mov    %0,%%cr4" : : "r" (value))

#define x86_read_dr3() ({ \
	size_t _v; \
	__asm__("mov    %%dr3,%0" : "=r" (_v)); \
	_v; \
})

#define x86_write_dr3(value) \
	__asm__("mov    %0,%%dr3" : : "r" (value))

#define invalidate_TLB(va) \
	__asm__("invlpg (%0)" : : "r" (va))

#define wbinvd() \
	__asm__ volatile ("wbinvd" : : : "memory")

#define arch_cpu_enable_user_access() \
	__asm__ volatile (ASM_STAC : : : "memory")

#define arch_cpu_disable_user_access() \
	__asm__ volatile (ASM_CLAC : : : "memory")

#define xgetbv(reg) ({ \
	uint32 low, high; \
	__asm__ volatile ("xgetbv" : "=a" (low), "=d" (high), "c" (reg)); \
	(low | (uint64)high << 32); \
})

#define xsetbv(reg, value) { \
	uint32 low = value; uint32 high = value >> 32; \
	__asm__ volatile ("xsetbv" : : "a" (low), "d" (high), "c" (reg)); }

#define out8(value,port) \
	__asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port))

#define out16(value,port) \
	__asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port))

#define out32(value,port) \
	__asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port))

#define in8(port) ({ \
	uint8 _v; \
	__asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \
	_v; \
})

#define in16(port) ({ \
	uint16 _v; \
	__asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \
	_v; \
})

#define in32(port) ({ \
	uint32 _v; \
	__asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \
	_v; \
})

#define out8_p(value,port) \
	__asm__ ("outb %%al,%%dx\n" \
			"\tjmp 1f\n" \
			"1:\tjmp 1f\n" \
			"1:" : : "a" (value), "d" (port))

#define in8_p(port) ({ \
	uint8 _v; \
	__asm__ volatile ("inb %%dx,%%al\n" \
			"\tjmp 1f\n" \
			"1:\tjmp 1f\n" \
			"1:" : "=a" (_v) : "d" (port)); \
	_v; \
})


#endif /* _KERNEL_ARCH_x86_CPUASM_H */