xv6/x86.h
rtm 8148b6ee53 i think my cmpxchg use was wrong in acquire
nesting cli/sti: release shouldn't always enable interrupts
separate setup of lapic from starting of other cpus, so cpu() works earlier
flag to disable locking in console output
make locks work even when curproc==0
(still crashes in clock interrupt)
2006-07-12 11:15:38 +00:00

344 lines
8.2 KiB
C

static __inline void breakpoint(void) __attribute__((always_inline));
static __inline uint8_t inb(int port) __attribute__((always_inline));
static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline));
static __inline uint16_t inw(int port) __attribute__((always_inline));
static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline));
static __inline uint32_t inl(int port) __attribute__((always_inline));
static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline));
static __inline void outb(int port, uint8_t data) __attribute__((always_inline));
static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline));
static __inline void outw(int port, uint16_t data) __attribute__((always_inline));
static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline));
static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline));
static __inline void outl(int port, uint32_t data) __attribute__((always_inline));
static __inline void invlpg(void *addr) __attribute__((always_inline));
static __inline void lidt(void *p) __attribute__((always_inline));
static __inline void lldt(uint16_t sel) __attribute__((always_inline));
static __inline void ltr(uint16_t sel) __attribute__((always_inline));
static __inline void lcr0(uint32_t val) __attribute__((always_inline));
static __inline uint32_t rcr0(void) __attribute__((always_inline));
static __inline uint32_t rcr2(void) __attribute__((always_inline));
static __inline void lcr3(uint32_t val) __attribute__((always_inline));
static __inline uint32_t rcr3(void) __attribute__((always_inline));
static __inline void lcr4(uint32_t val) __attribute__((always_inline));
static __inline uint32_t rcr4(void) __attribute__((always_inline));
static __inline void tlbflush(void) __attribute__((always_inline));
static __inline uint32_t read_eflags(void) __attribute__((always_inline));
static __inline void write_eflags(uint32_t eflags) __attribute__((always_inline));
static __inline uint32_t read_ebp(void) __attribute__((always_inline));
static __inline uint32_t read_esp(void) __attribute__((always_inline));
static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp);
static __inline uint64_t read_tsc(void) __attribute__((always_inline));
static __inline void
breakpoint(void)
{
__asm __volatile("int3");
}
static __inline uint8_t
inb(int port)
{
uint8_t data;
__asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
return data;
}
static __inline void
insb(int port, void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\tinsb" :
"=D" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"memory", "cc");
}
static __inline uint16_t
inw(int port)
{
uint16_t data;
__asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
return data;
}
static __inline void
insw(int port, void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\tinsw" :
"=D" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"memory", "cc");
}
static __inline uint32_t
inl(int port)
{
uint32_t data;
__asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
return data;
}
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");
}
static __inline void
outb(int port, uint8_t data)
{
__asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
}
static __inline void
outsb(int port, const void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\toutsb" :
"=S" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"cc");
}
static __inline void
outw(int port, uint16_t data)
{
__asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
}
static __inline void
outsw(int port, const void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\toutsw" :
"=S" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"cc");
}
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");
}
static __inline void
outl(int port, uint32_t data)
{
__asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
}
static __inline void
invlpg(void *addr)
{
__asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
}
static __inline void
lidt(void *p)
{
__asm __volatile("lidt (%0)" : : "r" (p));
}
static __inline void
lldt(uint16_t sel)
{
__asm __volatile("lldt %0" : : "r" (sel));
}
static __inline void
ltr(uint16_t sel)
{
__asm __volatile("ltr %0" : : "r" (sel));
}
static __inline void
lcr0(uint32_t val)
{
__asm __volatile("movl %0,%%cr0" : : "r" (val));
}
static __inline uint32_t
rcr0(void)
{
uint32_t val;
__asm __volatile("movl %%cr0,%0" : "=r" (val));
return val;
}
static __inline uint32_t
rcr2(void)
{
uint32_t val;
__asm __volatile("movl %%cr2,%0" : "=r" (val));
return val;
}
static __inline void
lcr3(uint32_t val)
{
__asm __volatile("movl %0,%%cr3" : : "r" (val));
}
static __inline uint32_t
rcr3(void)
{
uint32_t val;
__asm __volatile("movl %%cr3,%0" : "=r" (val));
return val;
}
static __inline void
lcr4(uint32_t val)
{
__asm __volatile("movl %0,%%cr4" : : "r" (val));
}
static __inline uint32_t
rcr4(void)
{
uint32_t cr4;
__asm __volatile("movl %%cr4,%0" : "=r" (cr4));
return cr4;
}
static __inline void
tlbflush(void)
{
uint32_t cr3;
__asm __volatile("movl %%cr3,%0" : "=r" (cr3));
__asm __volatile("movl %0,%%cr3" : : "r" (cr3));
}
static __inline uint32_t
read_eflags(void)
{
uint32_t eflags;
__asm __volatile("pushfl; popl %0" : "=r" (eflags));
return eflags;
}
static __inline void
write_eflags(uint32_t eflags)
{
__asm __volatile("pushl %0; popfl" : : "r" (eflags));
}
static __inline uint32_t
read_ebp(void)
{
uint32_t ebp;
__asm __volatile("movl %%ebp,%0" : "=r" (ebp));
return ebp;
}
static __inline uint32_t
read_esp(void)
{
uint32_t esp;
__asm __volatile("movl %%esp,%0" : "=r" (esp));
return esp;
}
static __inline uint32_t
read_esi(void)
{
uint32_t esi;
__asm __volatile("movl %%esi,%0" : "=r" (esi));
return esi;
}
static __inline uint32_t
read_edi(void)
{
uint32_t edi;
__asm __volatile("movl %%edi,%0" : "=r" (edi));
return edi;
}
static __inline uint32_t
read_ebx(void)
{
uint32_t ebx;
__asm __volatile("movl %%ebx,%0" : "=r" (ebx));
return ebx;
}
static __inline void
cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
{
uint32_t eax, ebx, ecx, edx;
asm volatile("cpuid"
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
: "a" (info));
if (eaxp)
*eaxp = eax;
if (ebxp)
*ebxp = ebx;
if (ecxp)
*ecxp = ecx;
if (edxp)
*edxp = edx;
}
static __inline uint32_t
cmpxchg(uint32_t oldval, uint32_t newval, volatile uint32_t* lock_addr)
{
uint32_t result;
__asm__ __volatile__(
"lock; cmpxchgl %2, %0"
:"+m" (*lock_addr), "=a" (result) : "r"(newval), "1"(oldval) : "cc"
);
return result;
}
static __inline uint64_t
read_tsc(void)
{
uint64_t tsc;
__asm __volatile("rdtsc" : "=A" (tsc));
return tsc;
}
struct PushRegs {
/* registers as pushed by pusha */
uint32_t reg_edi;
uint32_t reg_esi;
uint32_t reg_ebp;
uint32_t reg_oesp; /* Useless */
uint32_t reg_ebx;
uint32_t reg_edx;
uint32_t reg_ecx;
uint32_t reg_eax;
};
struct Trapframe {
struct PushRegs tf_regs;
uint16_t tf_es;
uint16_t tf_padding1;
uint16_t tf_ds;
uint16_t tf_padding2;
uint32_t tf_trapno;
/* below here defined by x86 hardware */
uint32_t tf_err;
uintptr_t tf_eip;
uint16_t tf_cs;
uint16_t tf_padding3;
uint32_t tf_eflags;
/* below here only when crossing rings, such as from user to kernel */
uintptr_t tf_esp;
uint16_t tf_ss;
uint16_t tf_padding4;
};
#define MAX_IRQS 16 // Number of IRQs
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
#define IRQ_IDE 14
#define IRQ_ERROR 19
#define IRQ_SPURIOUS 31