提交 ef3ccaee 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Use the PIT to time the CPU clock, use rdtsc to implement microdelay.

上级 5b532e09
...@@ -23,7 +23,6 @@ ASFLAGS = -m64 -gdwarf-2 ...@@ -23,7 +23,6 @@ ASFLAGS = -m64 -gdwarf-2
LDFLAGS += -m elf_x86_64 LDFLAGS += -m elf_x86_64
OBJS = \ OBJS = \
asm.o \
bio.o \ bio.o \
cga.o \ cga.o \
condvar.o \ condvar.o \
...@@ -33,6 +32,7 @@ OBJS = \ ...@@ -33,6 +32,7 @@ OBJS = \
fs.o \ fs.o \
ioapic.o \ ioapic.o \
lapic.o \ lapic.o \
hz.o \
kalloc.o \ kalloc.o \
kbd.o \ kbd.o \
main.o \ main.o \
......
...@@ -25,12 +25,6 @@ stosb(void *addr, int data, int cnt) ...@@ -25,12 +25,6 @@ stosb(void *addr, int data, int cnt)
"memory", "cc"); "memory", "cc");
} }
static inline void
microdelay(u32 delay)
{
}
static inline u32 static inline u32
xchg32(volatile u32 *addr, u32 newval) xchg32(volatile u32 *addr, u32 newval)
{ {
......
// Intel 8253/8254/82C54 Programmable Interval Timer (PIT).
// http://en.wikipedia.org/wiki/Intel_8253
#include "types.h"
#include "amd64.h"
#define IO_TIMER1 0x040 // 8253 Timer #1
#define TIMER_FREQ 1193182
#define TIMER_CNTR (IO_TIMER1 + 0) // timer counter port
#define TIMER_MODE (IO_TIMER1 + 3) // timer mode port
#define TIMER_SEL0 0x00 // select counter 0
#define TIMER_TCOUNT 0x00 // mode 0, terminal count
#define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first
#define TIMER_STAT 0xe0 // read status mode
#define TIMER_STAT0 (TIMER_STAT | 0x2) // status mode counter 0
u64 cpuhz;
void
microdelay(u64 delay)
{
u64 tscdelay = (cpuhz * delay) / 1000000;
u64 s = rdtsc();
while (rdtsc() - s < tscdelay)
nop_pause();
}
void
inithz(void)
{
// Setup PIT for terminal count starting from 2^16 - 1
u64 ticks = 0x000000000000FFFFull;
outb(TIMER_MODE, TIMER_SEL0 | TIMER_TCOUNT | TIMER_16BIT);
outb(IO_TIMER1, ticks % 256);
outb(IO_TIMER1, ticks / 256);
// Wait until OUT bit of status byte is set
u64 s = rdtsc();
do {
outb(TIMER_MODE, TIMER_STAT0);
} while (!(inb(TIMER_CNTR) & 0x80));
u64 e = rdtsc();
cpuhz = ((e-s)*10000000) / ((ticks*10000000)/TIMER_FREQ);
}
...@@ -81,6 +81,9 @@ int dirlink(struct inode*, char*, u32); ...@@ -81,6 +81,9 @@ int dirlink(struct inode*, char*, u32);
void dir_init(struct inode *dp); void dir_init(struct inode *dp);
void dir_flush(struct inode *dp); void dir_flush(struct inode *dp);
// hz.c
void microdelay(u64);
// ide.c // ide.c
void ideinit(void); void ideinit(void);
void ideintr(void); void ideintr(void);
......
...@@ -22,12 +22,10 @@ extern void initbio(void); ...@@ -22,12 +22,10 @@ extern void initbio(void);
extern void initinode(void); extern void initinode(void);
extern void initdisk(void); extern void initdisk(void);
extern void inituser(void); extern void inituser(void);
extern void inithz(void);
static volatile int bstate; static volatile int bstate;
// Common CPU setup code.
// Bootstrap CPU comes here from mainc().
// Other CPUs jump here from bootother.S.
void void
mpboot(void) mpboot(void)
{ {
...@@ -38,7 +36,6 @@ mpboot(void) ...@@ -38,7 +36,6 @@ mpboot(void)
scheduler(); // start running processes scheduler(); // start running processes
} }
// Start the non-boot processors.
static void static void
bootothers(void) bootothers(void)
{ {
...@@ -77,10 +74,12 @@ void ...@@ -77,10 +74,12 @@ void
cmain(void) cmain(void)
{ {
extern pml4e_t kpml4[]; extern pml4e_t kpml4[];
extern u64 cpuhz;
initpg(); initpg();
initseg(); initseg();
inittls(); inittls(); // thread local storage
inithz(); // CPU Hz, microdelay
initpic(); // interrupt controller initpic(); // interrupt controller
initioapic(); initioapic();
inituart(); inituart();
...@@ -97,7 +96,7 @@ cmain(void) ...@@ -97,7 +96,7 @@ cmain(void)
initinode(); // inode cache initinode(); // inode cache
initdisk(); // disk initdisk(); // disk
cprintf("ncpu %d\n", ncpu); cprintf("ncpu %d %lu MHz\n", ncpu, cpuhz / 1000000);
inituser(); // first user process inituser(); // first user process
bootothers(); // start other processors bootothers(); // start other processors
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论