swtch saves callee-saved registers
swtch idles on per-CPU stack, not on calling process's stack fix pipe bugs usertest.c tests pipes, fork, exit, close
This commit is contained in:
parent
f7cea12b38
commit
8b4e2a08fe
14 changed files with 220 additions and 63 deletions
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ CC = i386-jos-elf-gcc
|
||||||
LD = i386-jos-elf-ld
|
LD = i386-jos-elf-ld
|
||||||
OBJCOPY = i386-jos-elf-objcopy
|
OBJCOPY = i386-jos-elf-objcopy
|
||||||
OBJDUMP = i386-jos-elf-objdump
|
OBJDUMP = i386-jos-elf-objdump
|
||||||
CFLAGS = -nostdinc -I. -O -Wall -MD
|
CFLAGS = -nostdinc -I. -O2 -Wall -MD
|
||||||
|
|
||||||
xv6.img : bootblock kernel
|
xv6.img : bootblock kernel
|
||||||
dd if=/dev/zero of=xv6.img count=10000
|
dd if=/dev/zero of=xv6.img count=10000
|
||||||
|
|
30
fd.c
30
fd.c
|
@ -37,19 +37,6 @@ fd_alloc()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
fd_close(struct fd *fd)
|
|
||||||
{
|
|
||||||
if(fd->type == FD_CLOSED || fd->count <= 0)
|
|
||||||
panic("fd_close");
|
|
||||||
fd->count -= 1;
|
|
||||||
if(fd->count == 0){
|
|
||||||
if(fd->type == FD_PIPE)
|
|
||||||
pipe_close(fd->pipe, fd->writeable);
|
|
||||||
fd->type = FD_CLOSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* addr is a kernel address, pointing into some process's p->mem.
|
* addr is a kernel address, pointing into some process's p->mem.
|
||||||
*/
|
*/
|
||||||
|
@ -78,3 +65,20 @@ fd_read(struct fd *fd, char *addr, int n)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fd_close(struct fd *fd)
|
||||||
|
{
|
||||||
|
if(fd->count < 1 || fd->type == FD_CLOSED)
|
||||||
|
panic("fd_close");
|
||||||
|
fd->count -= 1;
|
||||||
|
|
||||||
|
if(fd->count == 0){
|
||||||
|
if(fd->type == FD_PIPE){
|
||||||
|
pipe_close(fd->pipe, fd->writeable);
|
||||||
|
} else {
|
||||||
|
panic("fd_close");
|
||||||
|
}
|
||||||
|
fd->type = FD_CLOSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
5
kalloc.c
5
kalloc.c
|
@ -45,10 +45,15 @@ kfree(char *cp, int len)
|
||||||
struct run **rr;
|
struct run **rr;
|
||||||
struct run *p = (struct run *) cp;
|
struct run *p = (struct run *) cp;
|
||||||
struct run *pend = (struct run *) (cp + len);
|
struct run *pend = (struct run *) (cp + len);
|
||||||
|
int i;
|
||||||
|
|
||||||
if(len % PAGE)
|
if(len % PAGE)
|
||||||
panic("kfree");
|
panic("kfree");
|
||||||
|
|
||||||
|
// XXX fill with junk to help debug
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
cp[i] = 1;
|
||||||
|
|
||||||
rr = &freelist;
|
rr = &freelist;
|
||||||
while(*rr){
|
while(*rr){
|
||||||
struct run *rend = (struct run *) ((char *)(*rr) + (*rr)->len);
|
struct run *rend = (struct run *) ((char *)(*rr) + (*rr)->len);
|
||||||
|
|
2
main.c
2
main.c
|
@ -46,7 +46,7 @@ main()
|
||||||
p = &proc[0];
|
p = &proc[0];
|
||||||
curproc[cpu()] = p;
|
curproc[cpu()] = p;
|
||||||
p->state = WAITING;
|
p->state = WAITING;
|
||||||
p->sz = PAGE;
|
p->sz = 4 * PAGE;
|
||||||
p->mem = kalloc(p->sz);
|
p->mem = kalloc(p->sz);
|
||||||
memset(p->mem, 0, p->sz);
|
memset(p->mem, 0, p->sz);
|
||||||
p->kstack = kalloc(KSTACKSIZE);
|
p->kstack = kalloc(KSTACKSIZE);
|
||||||
|
|
12
mp.c
12
mp.c
|
@ -6,6 +6,7 @@
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "traps.h"
|
#include "traps.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
|
#include "proc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Credit: Plan 9 sources, Intel MP spec, and Cliff Frey
|
* Credit: Plan 9 sources, Intel MP spec, and Cliff Frey
|
||||||
|
@ -92,16 +93,11 @@ enum { /* LAPIC_TDCR */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define APBOOTCODE 0x7000 // XXX hack
|
#define APBOOTCODE 0x7000 // XXX hack
|
||||||
#define MPSTACK 512
|
|
||||||
|
|
||||||
static struct MP* mp; // The MP floating point structure
|
static struct MP* mp; // The MP floating point structure
|
||||||
static uint32_t *lapicaddr;
|
static uint32_t *lapicaddr;
|
||||||
static struct cpu {
|
struct cpu cpus[NCPU];
|
||||||
uint8_t apicid; // Local APIC ID
|
int ncpu;
|
||||||
int lintr[2]; // Local APIC
|
|
||||||
char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
|
|
||||||
} cpus[NCPU];
|
|
||||||
static int ncpu;
|
|
||||||
static struct cpu *bcpu;
|
static struct cpu *bcpu;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -130,7 +126,7 @@ lapic_timerinit()
|
||||||
void
|
void
|
||||||
lapic_timerintr()
|
lapic_timerintr()
|
||||||
{
|
{
|
||||||
cprintf("%d: timer interrupt!\n", cpu());
|
// cprintf("%d: timer interrupt!\n", cpu());
|
||||||
lapic_write (LAPIC_EOI, 0);
|
lapic_write (LAPIC_EOI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
pipe.c
14
pipe.c
|
@ -28,6 +28,10 @@ pipe_alloc(struct fd **fd1, struct fd **fd2)
|
||||||
goto oops;
|
goto oops;
|
||||||
if((p = (struct pipe *) kalloc(PAGE)) == 0)
|
if((p = (struct pipe *) kalloc(PAGE)) == 0)
|
||||||
goto oops;
|
goto oops;
|
||||||
|
p->readopen = 1;
|
||||||
|
p->writeopen = 1;
|
||||||
|
p->writep = 0;
|
||||||
|
p->readp = 0;
|
||||||
(*fd1)->type = FD_PIPE;
|
(*fd1)->type = FD_PIPE;
|
||||||
(*fd1)->readable = 1;
|
(*fd1)->readable = 1;
|
||||||
(*fd1)->writeable = 0;
|
(*fd1)->writeable = 0;
|
||||||
|
@ -54,10 +58,13 @@ pipe_alloc(struct fd **fd1, struct fd **fd2)
|
||||||
void
|
void
|
||||||
pipe_close(struct pipe *p, int writeable)
|
pipe_close(struct pipe *p, int writeable)
|
||||||
{
|
{
|
||||||
if(writeable)
|
if(writeable){
|
||||||
p->writeopen = 0;
|
p->writeopen = 0;
|
||||||
else
|
wakeup(&p->readp);
|
||||||
|
} else {
|
||||||
p->readopen = 0;
|
p->readopen = 0;
|
||||||
|
wakeup(&p->writep);
|
||||||
|
}
|
||||||
if(p->readopen == 0 && p->writeopen == 0)
|
if(p->readopen == 0 && p->writeopen == 0)
|
||||||
kfree((char *) p, PAGE);
|
kfree((char *) p, PAGE);
|
||||||
}
|
}
|
||||||
|
@ -71,11 +78,13 @@ pipe_write(struct pipe *p, char *addr, int n)
|
||||||
while(((p->writep + 1) % PIPESIZE) == p->readp){
|
while(((p->writep + 1) % PIPESIZE) == p->readp){
|
||||||
if(p->readopen == 0)
|
if(p->readopen == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
wakeup(&p->readp);
|
||||||
sleep(&p->writep);
|
sleep(&p->writep);
|
||||||
}
|
}
|
||||||
p->data[p->writep] = addr[i];
|
p->data[p->writep] = addr[i];
|
||||||
p->writep = (p->writep + 1) % PIPESIZE;
|
p->writep = (p->writep + 1) % PIPESIZE;
|
||||||
}
|
}
|
||||||
|
wakeup(&p->readp);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,5 +105,6 @@ pipe_read(struct pipe *p, char *addr, int n)
|
||||||
addr[i] = p->data[p->readp];
|
addr[i] = p->data[p->readp];
|
||||||
p->readp = (p->readp + 1) % PIPESIZE;
|
p->readp = (p->readp + 1) % PIPESIZE;
|
||||||
}
|
}
|
||||||
|
wakeup(&p->writep);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
58
proc.c
58
proc.c
|
@ -104,37 +104,47 @@ swtch()
|
||||||
{
|
{
|
||||||
struct proc *np;
|
struct proc *np;
|
||||||
struct proc *op = curproc[cpu()];
|
struct proc *op = curproc[cpu()];
|
||||||
|
unsigned sp;
|
||||||
while(1){
|
int i;
|
||||||
np = op + 1;
|
|
||||||
while(np != op){
|
// force push of callee-saved registers
|
||||||
if(np->state == RUNNABLE)
|
asm volatile("nop" : : : "%edi", "%esi", "%ebx");
|
||||||
break;
|
|
||||||
np++;
|
// save calling process's stack pointers
|
||||||
if(np == &proc[NPROC])
|
|
||||||
np = &proc[0];
|
|
||||||
}
|
|
||||||
if(np->state == RUNNABLE)
|
|
||||||
break;
|
|
||||||
// cprintf("swtch: nothing to run\n");
|
|
||||||
release_spinlock(&kernel_lock);
|
|
||||||
acquire_spinlock(&kernel_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX this may be too late, should probably save on the way
|
|
||||||
// in, in case some other CPU decided to run curproc
|
|
||||||
// before we got here. in fact setting state=WAITING and
|
|
||||||
// setting these variables had better be atomic w.r.t. other CPUs.
|
|
||||||
op->ebp = read_ebp();
|
op->ebp = read_ebp();
|
||||||
op->esp = read_esp();
|
op->esp = read_esp();
|
||||||
|
|
||||||
cprintf("cpu %d swtch %x -> %x\n", cpu(), op, np);
|
// don't execute on calling process's stack
|
||||||
|
sp = (unsigned) cpus[cpu()].mpstack + MPSTACK - 32;
|
||||||
|
asm volatile("movl %0, %%esp" : : "g" (sp));
|
||||||
|
asm volatile("movl %0, %%ebp" : : "g" (sp));
|
||||||
|
|
||||||
|
// gcc might store op on the stack
|
||||||
|
np = curproc[cpu()];
|
||||||
|
np = np + 1;
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
for(i = 0; i < NPROC; i++){
|
||||||
|
if(np >= &proc[NPROC])
|
||||||
|
np = &proc[0];
|
||||||
|
if(np->state == RUNNABLE)
|
||||||
|
break;
|
||||||
|
np++;
|
||||||
|
}
|
||||||
|
if(i < NPROC)
|
||||||
|
break;
|
||||||
|
// cprintf("swtch %d: nothing to run %d %d\n",
|
||||||
|
// cpu(), proc[1].state, proc[2].state);
|
||||||
|
release_spinlock(&kernel_lock);
|
||||||
|
acquire_spinlock(&kernel_lock);
|
||||||
|
np = &proc[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
cprintf("cpu %d swtch %x -> %x\n", cpu(), curproc[cpu()], np);
|
||||||
|
|
||||||
curproc[cpu()] = np;
|
curproc[cpu()] = np;
|
||||||
np->state = RUNNING;
|
np->state = RUNNING;
|
||||||
|
|
||||||
// XXX callee-saved registers?
|
|
||||||
|
|
||||||
// h/w sets busy bit in TSS descriptor sometimes, and faults
|
// h/w sets busy bit in TSS descriptor sometimes, and faults
|
||||||
// if it's set in LTR. so clear tss descriptor busy bit.
|
// if it's set in LTR. so clear tss descriptor busy bit.
|
||||||
np->gdt[SEG_TSS].sd_type = STS_T32A;
|
np->gdt[SEG_TSS].sd_type = STS_T32A;
|
||||||
|
|
11
proc.h
11
proc.h
|
@ -37,3 +37,14 @@ struct proc{
|
||||||
|
|
||||||
extern struct proc proc[];
|
extern struct proc proc[];
|
||||||
extern struct proc *curproc[NCPU];
|
extern struct proc *curproc[NCPU];
|
||||||
|
|
||||||
|
#define MPSTACK 512
|
||||||
|
|
||||||
|
struct cpu {
|
||||||
|
uint8_t apicid; // Local APIC ID
|
||||||
|
int lintr[2]; // Local APIC
|
||||||
|
char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct cpu cpus[NCPU];
|
||||||
|
extern int ncpu;
|
||||||
|
|
38
syscall.c
38
syscall.c
|
@ -91,7 +91,7 @@ sys_pipe()
|
||||||
int
|
int
|
||||||
sys_write()
|
sys_write()
|
||||||
{
|
{
|
||||||
int fd, n;
|
int fd, n, ret;
|
||||||
unsigned addr;
|
unsigned addr;
|
||||||
struct proc *p = curproc[cpu()];
|
struct proc *p = curproc[cpu()];
|
||||||
|
|
||||||
|
@ -103,13 +103,14 @@ sys_write()
|
||||||
return -1;
|
return -1;
|
||||||
if(addr + n > p->sz)
|
if(addr + n > p->sz)
|
||||||
return -1;
|
return -1;
|
||||||
return fd_write(p->fds[fd], p->mem + addr, n);
|
ret = fd_write(p->fds[fd], p->mem + addr, n);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sys_read()
|
sys_read()
|
||||||
{
|
{
|
||||||
int fd, n;
|
int fd, n, ret;
|
||||||
unsigned addr;
|
unsigned addr;
|
||||||
struct proc *p = curproc[cpu()];
|
struct proc *p = curproc[cpu()];
|
||||||
|
|
||||||
|
@ -121,7 +122,25 @@ sys_read()
|
||||||
return -1;
|
return -1;
|
||||||
if(addr + n > p->sz)
|
if(addr + n > p->sz)
|
||||||
return -1;
|
return -1;
|
||||||
return fd_read(p->fds[fd], p->mem + addr, n);
|
ret = fd_read(p->fds[fd], p->mem + addr, n);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sys_close()
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct proc *p = curproc[cpu()];
|
||||||
|
|
||||||
|
if(fetcharg(0, &fd) < 0)
|
||||||
|
return -1;
|
||||||
|
if(fd < 0 || fd >= NOFILE)
|
||||||
|
return -1;
|
||||||
|
if(p->fds[fd] == 0)
|
||||||
|
return -1;
|
||||||
|
fd_close(p->fds[fd]);
|
||||||
|
p->fds[fd] = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -138,6 +157,14 @@ sys_exit()
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
struct proc *cp = curproc[cpu()];
|
struct proc *cp = curproc[cpu()];
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
for(fd = 0; fd < NOFILE; fd++){
|
||||||
|
if(cp->fds[fd]){
|
||||||
|
fd_close(cp->fds[fd]);
|
||||||
|
cp->fds[fd] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cp->state = ZOMBIE;
|
cp->state = ZOMBIE;
|
||||||
|
|
||||||
|
@ -227,6 +254,9 @@ syscall()
|
||||||
case SYS_read:
|
case SYS_read:
|
||||||
ret = sys_read();
|
ret = sys_read();
|
||||||
break;
|
break;
|
||||||
|
case SYS_close:
|
||||||
|
ret = sys_close();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cprintf("unknown sys call %d\n", num);
|
cprintf("unknown sys call %d\n", num);
|
||||||
// XXX fault
|
// XXX fault
|
||||||
|
|
|
@ -5,3 +5,4 @@
|
||||||
#define SYS_pipe 5
|
#define SYS_pipe 5
|
||||||
#define SYS_write 6
|
#define SYS_write 6
|
||||||
#define SYS_read 7
|
#define SYS_read 7
|
||||||
|
#define SYS_close 8
|
||||||
|
|
16
trap.c
16
trap.c
|
@ -35,16 +35,28 @@ trap(struct Trapframe *tf)
|
||||||
{
|
{
|
||||||
int v = tf->tf_trapno;
|
int v = tf->tf_trapno;
|
||||||
|
|
||||||
|
if(tf->tf_cs == 0x8 && kernel_lock == cpu())
|
||||||
|
cprintf("cpu %d: trap from %x:%x with lock=%d\n",
|
||||||
|
cpu(), tf->tf_cs, tf->tf_eip, kernel_lock);
|
||||||
|
|
||||||
acquire_spinlock(&kernel_lock); // released in trapret in trapasm.S
|
acquire_spinlock(&kernel_lock); // released in trapret in trapasm.S
|
||||||
|
|
||||||
if(v == T_SYSCALL){
|
if(v == T_SYSCALL){
|
||||||
curproc[cpu()]->tf = tf;
|
struct proc *cp = curproc[cpu()];
|
||||||
|
cp->tf = tf;
|
||||||
syscall();
|
syscall();
|
||||||
|
if(cp != curproc[cpu()])
|
||||||
|
panic("trap ret wrong curproc");
|
||||||
|
if(cp->state != RUNNING)
|
||||||
|
panic("trap ret but not RUNNING");
|
||||||
|
if(tf != cp->tf)
|
||||||
|
panic("trap ret wrong tf");
|
||||||
|
if(read_esp() < cp->kstack || read_esp() >= cp->kstack + KSTACKSIZE)
|
||||||
|
panic("trap ret esp wrong");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(v == (IRQ_OFFSET + IRQ_TIMER)){
|
if(v == (IRQ_OFFSET + IRQ_TIMER)){
|
||||||
curproc[cpu()]->tf = tf;
|
|
||||||
lapic_timerintr();
|
lapic_timerintr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
14
ulib.c
14
ulib.c
|
@ -5,6 +5,13 @@ fork()
|
||||||
asm("int $48");
|
asm("int $48");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
exit()
|
||||||
|
{
|
||||||
|
asm("mov $2, %eax");
|
||||||
|
asm("int $48");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cons_putc(int c)
|
cons_putc(int c)
|
||||||
{
|
{
|
||||||
|
@ -42,3 +49,10 @@ write(int fd, char *buf, int n)
|
||||||
asm("mov $6, %eax");
|
asm("mov $6, %eax");
|
||||||
asm("int $48");
|
asm("int $48");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
close(int fd)
|
||||||
|
{
|
||||||
|
asm("mov $8, %eax");
|
||||||
|
asm("int $48");
|
||||||
|
}
|
||||||
|
|
42
usertests.c
42
usertests.c
|
@ -1,22 +1,48 @@
|
||||||
// simple fork and pipe read/write
|
// simple fork and pipe read/write
|
||||||
|
|
||||||
char buf[32];
|
char buf[2048];
|
||||||
|
|
||||||
void
|
void
|
||||||
pipe1()
|
pipe1()
|
||||||
{
|
{
|
||||||
int fds[2], pid;
|
int fds[2], pid;
|
||||||
|
int seq = 0, i, n, cc, total;
|
||||||
|
|
||||||
pipe(fds);
|
pipe(fds);
|
||||||
pid = pipe();
|
pid = fork();
|
||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
write(fds[1], "xyz", 4);
|
close(fds[0]);
|
||||||
} else {
|
for(n = 0; n < 5; n++){
|
||||||
read(fds[0], buf, sizeof(buf));
|
for(i = 0; i < 1033; i++)
|
||||||
if(buf[0] != 'x' || buf[1] != 'y'){
|
buf[i] = seq++;
|
||||||
puts("pipe1 oops\n");
|
if(write(fds[1], buf, 1033) != 1033){
|
||||||
return;
|
puts("pipe1 oops 1\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
close(fds[1]);
|
||||||
|
total = 0;
|
||||||
|
cc = 1;
|
||||||
|
while(1){
|
||||||
|
n = read(fds[0], buf, cc);
|
||||||
|
if(n < 1)
|
||||||
|
break;
|
||||||
|
for(i = 0; i < n; i++){
|
||||||
|
if((buf[i] & 0xff) != (seq++ & 0xff)){
|
||||||
|
puts("pipe1 oops 2\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += n;
|
||||||
|
cc = cc * 2;
|
||||||
|
if(cc > sizeof(buf))
|
||||||
|
cc = sizeof(buf);
|
||||||
|
}
|
||||||
|
if(total != 5 * 1033)
|
||||||
|
puts("pipe1 oops 3\n");
|
||||||
|
close(fds[0]);
|
||||||
}
|
}
|
||||||
puts("pipe1 ok\n");
|
puts("pipe1 ok\n");
|
||||||
}
|
}
|
||||||
|
|
38
x86.h
38
x86.h
|
@ -244,6 +244,30 @@ read_esp(void)
|
||||||
return 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
|
static __inline void
|
||||||
cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
|
cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
|
||||||
{
|
{
|
||||||
|
@ -280,6 +304,20 @@ read_tsc(void)
|
||||||
return tsc;
|
return tsc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// disable interrupts
|
||||||
|
static __inline void
|
||||||
|
cli(void)
|
||||||
|
{
|
||||||
|
__asm __volatile("cli");
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable interrupts
|
||||||
|
static __inline void
|
||||||
|
sti(void)
|
||||||
|
{
|
||||||
|
__asm __volatile("sti");
|
||||||
|
}
|
||||||
|
|
||||||
struct PushRegs {
|
struct PushRegs {
|
||||||
/* registers as pushed by pusha */
|
/* registers as pushed by pusha */
|
||||||
uint32_t reg_edi;
|
uint32_t reg_edi;
|
||||||
|
|
Loading…
Reference in a new issue