Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
219
include/x86.h
Normal file
219
include/x86.h
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
#pragma once
|
||||
|
||||
struct dtr {
|
||||
ushort limit;
|
||||
uint64 base;
|
||||
} __attribute__((packed));
|
||||
|
||||
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; rep insl" :
|
||||
"=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 uint
|
||||
inl(ushort port)
|
||||
{
|
||||
uint data;
|
||||
asm volatile("inl %1,%0" : "=a" (data) : "d" (port));
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline void
|
||||
outw(ushort port, ushort data)
|
||||
{
|
||||
asm volatile("out %0,%1" : : "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
// PCI configuration space is reached through a pair of 32-bit ports, so this
|
||||
// is not optional decoration -- see kernel/dev/pci.c.
|
||||
static inline void
|
||||
outl(ushort port, uint data)
|
||||
{
|
||||
asm volatile("outl %0,%1" : : "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
static inline void
|
||||
outsl(int port, const void *addr, int cnt)
|
||||
{
|
||||
asm volatile("cld; rep outsl" :
|
||||
"=S" (addr), "=c" (cnt) :
|
||||
"d" (port), "0" (addr), "1" (cnt) :
|
||||
"cc");
|
||||
}
|
||||
|
||||
static inline void
|
||||
stosb(void *addr, int data, int cnt)
|
||||
{
|
||||
asm volatile("cld; rep stosb" :
|
||||
"=D" (addr), "=c" (cnt) :
|
||||
"0" (addr), "1" (cnt), "a" (data) :
|
||||
"memory", "cc");
|
||||
}
|
||||
|
||||
// 64-bit-only helpers. `rep stosq` and `xchgq` do not exist in 32-bit mode, so
|
||||
// these must not even be parsed by the -m32 bootloader build -- they compiled
|
||||
// there before only because uint64 was accidentally 32 bits wide, which is the
|
||||
// bug include/types.h now asserts against.
|
||||
#ifdef __x86_64__
|
||||
static inline void
|
||||
stosq(void *addr, uint64 data, int cnt)
|
||||
{
|
||||
asm volatile("cld; rep stosq" :
|
||||
"=D" (addr), "=c" (cnt) :
|
||||
"0" (addr), "1" (cnt), "a" (data) :
|
||||
"memory", "cc");
|
||||
}
|
||||
|
||||
struct segdesc;
|
||||
|
||||
static inline void
|
||||
lgdt(struct segdesc *p, int size)
|
||||
{
|
||||
struct dtr d;
|
||||
d.limit = size - 1;
|
||||
d.base = (uint64)p;
|
||||
asm volatile("lgdt (%0)" : : "r" (&d));
|
||||
}
|
||||
|
||||
struct gatedesc;
|
||||
|
||||
static inline void
|
||||
lidt(struct gatedesc *p, int size)
|
||||
{
|
||||
struct dtr d;
|
||||
d.limit = size - 1;
|
||||
d.base = (uint64)p;
|
||||
asm volatile("lidt (%0)" : : "r" (&d));
|
||||
}
|
||||
|
||||
static inline void
|
||||
ltr(ushort sel)
|
||||
{
|
||||
asm volatile("ltr %0" : : "r" (sel));
|
||||
}
|
||||
|
||||
static inline uint64
|
||||
readeflags(void)
|
||||
{
|
||||
uint64 flags;
|
||||
asm volatile("pushfq; pop %0" : "=r" (flags));
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cli(void)
|
||||
{
|
||||
asm volatile("cli");
|
||||
}
|
||||
|
||||
static inline void
|
||||
sti(void)
|
||||
{
|
||||
asm volatile("sti");
|
||||
}
|
||||
|
||||
static inline void
|
||||
hlt(void)
|
||||
{
|
||||
asm volatile("hlt");
|
||||
}
|
||||
|
||||
static inline uint64
|
||||
xchg(volatile uint64 *addr, uint64 newval)
|
||||
{
|
||||
uint64 result;
|
||||
asm volatile("lock; xchgq %0, %1" :
|
||||
"+m" (*addr), "=a" (result) :
|
||||
"1" (newval) :
|
||||
"cc");
|
||||
return result;
|
||||
}
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
static inline uint64
|
||||
rcr2(void)
|
||||
{
|
||||
uint64 val;
|
||||
asm volatile("mov %%cr2,%0" : "=r" (val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
lcr3(uint64 val)
|
||||
{
|
||||
asm volatile("mov %0,%%cr3" : : "r" (val));
|
||||
}
|
||||
|
||||
// Invalidate the TLB entry for one page. Needed any time a PTE is changed
|
||||
// or cleared for an address space that may still be the active CR3 —
|
||||
// otherwise the CPU can keep translating through the stale entry until the
|
||||
// next full CR3 reload (context switch), silently reading/writing the
|
||||
// wrong physical page.
|
||||
static inline void
|
||||
invlpg(void *va)
|
||||
{
|
||||
asm volatile("invlpg (%0)" : : "r" (va) : "memory");
|
||||
}
|
||||
|
||||
static inline void
|
||||
wrmsr(uint32 msr, uint64 val)
|
||||
{
|
||||
uint32 low = (uint32)val;
|
||||
uint32 high = (uint32)(val >> 32);
|
||||
asm volatile("wrmsr" : : "c" (msr), "a" (low), "d" (high));
|
||||
}
|
||||
|
||||
static inline uint64
|
||||
rdmsr(uint32 msr)
|
||||
{
|
||||
uint32 low, high;
|
||||
asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
|
||||
return ((uint64)high << 32) | low;
|
||||
}
|
||||
|
||||
static inline uint64
|
||||
readcs(void)
|
||||
{
|
||||
uint64 val;
|
||||
asm volatile("mov %%cs, %0" : "=r" (val));
|
||||
return val;
|
||||
}
|
||||
|
||||
// CPUID. `leaf` in EAX, results in EAX/EBX/ECX/EDX.
|
||||
//
|
||||
// %rbx is callee-saved *and* the PIC base register on some builds, so it is
|
||||
// exchanged out rather than named as an operand -- naming it directly is the
|
||||
// classic way to get "inline asm clobbers reserved register" or, worse, silent
|
||||
// corruption in the caller.
|
||||
static inline void
|
||||
cpuid_leaf(uint32 leaf, uint32 *a, uint32 *b, uint32 *c, uint32 *d)
|
||||
{
|
||||
uint32 ra, rb, rc, rd;
|
||||
asm volatile("xchgq %%rbx, %q1\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchgq %%rbx, %q1"
|
||||
: "=a"(ra), "=&r"(rb), "=c"(rc), "=d"(rd)
|
||||
: "0"(leaf), "2"(0));
|
||||
if (a) *a = ra;
|
||||
if (b) *b = rb;
|
||||
if (c) *c = rc;
|
||||
if (d) *d = rd;
|
||||
}
|
||||
Loading…
Reference in a new issue