xv6-cs450/x86.h
rsc 9fd9f80431 Re: why cpuid() in locking code?
rtm wrote:
> Why does acquire() call cpuid()? Why does release() call cpuid()?

The cpuid in acquire is redundant with the cmpxchg, as you said.
I have removed the cpuid from acquire.

The cpuid in release is actually doing something important,
but not on the hardware.  It keeps gcc from reordering the
lock->locked assignment above the other two during optimization.
(Not that current gcc -O2 would choose to do that, but it is allowed to.)
I have replaced the cpuid in release with a "gcc barrier" that
keeps gcc from moving things around but has no hardware effect.

On a related note, I don't think the cpuid in mpmain is necessary,
for the same reason that the cpuid wasn't needed in release.

As to the question of whether

  acquire();
  x = protected;
  release();

might read protected after release(), I still haven't convinced
myself whether it can.  I'll put the cpuid back into release if
we determine that it can.

Russ
2007-09-30 14:30:04 +00:00

175 lines
3.1 KiB
C

// Routines to let C code use special x86 instructions.
static inline uchar
inb(ushort port)
{
uchar data;
asm volatile("in %1,%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(ushort port, uchar data)
{
asm volatile("out %0,%1" : : "a" (data), "d" (port));
}
static inline void
outw(ushort port, ushort data)
{
asm volatile("out %0,%1" : : "a" (data), "d" (port));
}
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 uint
read_ebp(void)
{
uint ebp;
asm volatile("movl %%ebp, %0" : "=a" (ebp));
return ebp;
}
struct segdesc;
static inline void
lgdt(struct segdesc *p, int size)
{
volatile ushort pd[3];
pd[0] = size-1;
pd[1] = (uint)p;
pd[2] = (uint)p >> 16;
asm volatile("lgdt (%0)" : : "r" (pd));
}
struct gatedesc;
static inline void
lidt(struct gatedesc *p, int size)
{
volatile ushort pd[3];
pd[0] = size-1;
pd[1] = (uint)p;
pd[2] = (uint)p >> 16;
asm volatile("lidt (%0)" : : "r" (pd));
}
static inline void
ltr(ushort sel)
{
asm volatile("ltr %0" : : "r" (sel));
}
static inline uint
read_eflags(void)
{
uint eflags;
asm volatile("pushfl; popl %0" : "=r" (eflags));
return eflags;
}
static inline void
write_eflags(uint eflags)
{
asm volatile("pushl %0; popfl" : : "r" (eflags));
}
// XXX: Kill this if not used.
static inline void
cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp)
{
uint 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 uint
cmpxchg(uint oldval, uint newval, volatile uint* lock_addr)
{
uint result;
// The + in "+m" denotes a read-modify-write operand.
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");
}
// Layout of the trap frame built on the stack by the
// hardware and by trapasm.S, and passed to trap().
struct trapframe {
// registers as pushed by pusha
uint edi;
uint esi;
uint ebp;
uint oesp; // useless & ignored
uint ebx;
uint edx;
uint ecx;
uint eax;
// rest of trap frame
ushort es;
ushort padding1;
ushort ds;
ushort padding2;
uint trapno;
// below here defined by x86 hardware
uint err;
uint eip;
ushort cs;
ushort padding3;
uint eflags;
// below here only when crossing rings, such as from user to kernel
uint esp;
ushort ss;
ushort padding4;
};