xv6-cs450/x86.h

161 lines
3 KiB
C
Raw Normal View History

2006-09-07 16:12:30 +02:00
// Special assembly routines to access x86-specific
// hardware instructions.
2006-07-20 11:07:53 +02:00
static __inline uchar
2006-06-12 17:22:12 +02:00
inb(int port)
{
uchar data;
__asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
return data;
2006-06-12 17:22:12 +02:00
}
static __inline void
insl(int port, void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\tinsl" :
"=D" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"memory", "cc");
2006-06-12 17:22:12 +02:00
}
static __inline void
2006-07-20 11:07:53 +02:00
outb(int port, uchar data)
2006-06-12 17:22:12 +02:00
{
__asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
2006-06-12 17:22:12 +02:00
}
static __inline void
2006-07-20 11:07:53 +02:00
outw(int port, ushort data)
2006-06-12 17:22:12 +02:00
{
__asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
2006-06-12 17:22:12 +02:00
}
static __inline void
outsl(int port, const void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\toutsl" :
"=S" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"cc");
2006-06-12 17:22:12 +02:00
}
struct segdesc;
2006-06-12 17:22:12 +02:00
static __inline void
lgdt(struct segdesc *p, int size)
2006-06-12 17:22:12 +02:00
{
volatile ushort pd[3];
2006-09-06 19:27:19 +02:00
pd[0] = size-1;
pd[1] = (uint)p;
pd[2] = (uint)p >> 16;
asm volatile("lgdt (%0)" : : "g" (pd));
}
struct gatedesc;
static __inline void
lidt(struct gatedesc *p, int size)
{
volatile ushort pd[3];
2006-09-06 19:27:19 +02:00
pd[0] = size-1;
pd[1] = (uint)p;
pd[2] = (uint)p >> 16;
2006-09-06 19:27:19 +02:00
asm volatile("lidt (%0)" : : "g" (pd));
2006-06-12 17:22:12 +02:00
}
static __inline void
2006-07-20 11:07:53 +02:00
ltr(ushort sel)
2006-06-12 17:22:12 +02:00
{
__asm __volatile("ltr %0" : : "r" (sel));
2006-06-12 17:22:12 +02:00
}
2006-07-20 11:07:53 +02:00
static __inline uint
2006-06-12 17:22:12 +02:00
read_eflags(void)
{
uint eflags;
__asm __volatile("pushfl; popl %0" : "=r" (eflags));
return eflags;
2006-06-12 17:22:12 +02:00
}
static __inline void
2006-07-20 11:07:53 +02:00
write_eflags(uint eflags)
2006-06-12 17:22:12 +02:00
{
__asm __volatile("pushl %0; popfl" : : "r" (eflags));
2006-06-12 17:22:12 +02:00
}
static __inline void
2006-07-20 11:07:53 +02:00
cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp)
2006-06-12 17:22:12 +02:00
{
uint eax, ebx, ecx, edx;
asm volatile("cpuid" :
"=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) :
"a" (info));
2006-09-06 19:27:19 +02:00
if(eaxp)
*eaxp = eax;
2006-09-06 19:27:19 +02:00
if(ebxp)
*ebxp = ebx;
2006-09-06 19:27:19 +02:00
if(ecxp)
*ecxp = ecx;
2006-09-06 19:27:19 +02:00
if(edxp)
*edxp = edx;
2006-06-12 17:22:12 +02:00
}
2006-07-20 11:07:53 +02:00
static __inline uint
cmpxchg(uint oldval, uint newval, volatile uint* lock_addr)
{
2006-07-20 11:07:53 +02:00
uint result;
__asm__ __volatile__("lock; cmpxchgl %2, %0" :
"+m" (*lock_addr), "=a" (result) :
"r"(newval), "1"(oldval) :
"cc");
return result;
}
static __inline void
cli(void)
{
__asm__ volatile("cli");
}
static __inline void
sti(void)
{
__asm__ volatile("sti");
}
2006-09-07 16:12:30 +02:00
// Layout of the trap frame on the stack upon entry to trap.
struct trapframe {
2006-09-06 19:50:20 +02:00
// registers as pushed by pusha
uint edi;
uint esi;
uint ebp;
2006-09-06 19:50:20 +02:00
uint oesp; // useless & ignored
uint ebx;
uint edx;
uint ecx;
uint eax;
2006-09-06 19:50:20 +02:00
// rest of trap frame
ushort es;
ushort padding1;
ushort ds;
ushort padding2;
uint trapno;
2006-09-06 19:50:20 +02:00
// below here defined by x86 hardware
uint err;
uint eip;
ushort cs;
ushort padding3;
uint eflags;
2006-09-06 19:50:20 +02:00
// below here only when crossing rings, such as from user to kernel
uint esp;
ushort ss;
ushort padding4;
2006-06-12 17:22:12 +02:00
};