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

Start of mp.c, console.c, and spinlock.c 64-bitification.

上级 0f218772
......@@ -3,7 +3,10 @@
OBJS = \
asm.o \
cga.o \
console.o \
main.o \
mp.o \
spinlock.o \
string.o \
uart.o \
trap.o
......@@ -15,7 +18,7 @@ TOOLPREFIX ?= x86_64-jos-elf-
QEMU = qemu-system-x86_64
NM = $(TOOLPREFIX)nm
CC = $(TOOLPREFIX)clang
CC = $(TOOLPREFIX)gcc
AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
......@@ -50,4 +53,4 @@ endif
QEMUOPTS = -smp $(CPUS) -m 512
qemu: kernel
$(QEMU) $(QEMUOPTS) -kernel kernel
$(QEMU) $(QEMUOPTS) -kernel kernel -nographic
// Rflags register
#define FL_CF 0x00000001 // Carry Flag
#define FL_PF 0x00000004 // Parity Flag
#define FL_AF 0x00000010 // Auxiliary carry Flag
#define FL_ZF 0x00000040 // Zero Flag
#define FL_SF 0x00000080 // Sign Flag
#define FL_TF 0x00000100 // Trap Flag
#define FL_IF 0x00000200 // Interrupt Enable
#define FL_DF 0x00000400 // Direction Flag
#define FL_OF 0x00000800 // Overflow Flag
#define FL_IOPL_MASK 0x00003000 // I/O Privilege Level bitmask
#define FL_IOPL_0 0x00000000 // IOPL == 0
#define FL_IOPL_1 0x00001000 // IOPL == 1
#define FL_IOPL_2 0x00002000 // IOPL == 2
#define FL_IOPL_3 0x00003000 // IOPL == 3
#define FL_NT 0x00004000 // Nested Task
#define FL_RF 0x00010000 // Resume Flag
#define FL_VM 0x00020000 // Virtual 8086 mode
#define FL_AC 0x00040000 // Alignment Check
#define FL_VIF 0x00080000 // Virtual Interrupt Flag
#define FL_VIP 0x00100000 // Virtual Interrupt Pending
#define FL_ID 0x00200000 // ID flag
......@@ -8,45 +8,35 @@ static int cursor;
extern void setcursor(int);
void
putsn(const char *s, int n)
static void
cgaputs(const char *s)
{
int i;
uint8 *p, *ep;
p = (uint8*)s;
ep = p+n;
for(; p < ep; p++) {
if(*p == '\n') {
cursor += 80 - cursor%80;
} else {
screen[cursor] = color | *p;
cursor++;
}
if(cursor == 25*80) {
memmove((void*)screen+80*2, (void*)screen+80*3, 80*(25-3)*2);
for(i=0; i<80; i++)
screen[(24*80+i)] = color | ' ' & 0xff;
cursor -= 80;
}
}
}
ep = p+strlen(s);
static void
cgaputs(const char *s)
{
putsn(s, strlen(s));
for (; p < ep; p++)
cgaputc(*p);
}
void
panic(const char *s)
cgaputc(char c)
{
cgaputs("panic: ");
cgaputs(s);
cgaputs("\n");
setcursor(cursor);
for(;;)
screen[0] = screen[0];
int i;
if(c == '\n') {
cursor += 80 - cursor%80;
} else {
screen[cursor] = color | c;
cursor++;
}
if(cursor == 25*80) {
memmove((void*)screen+80*2, (void*)screen+80*3, 80*(25-3)*2);
for(i=0; i<80; i++)
screen[(24*80+i)] = color | (' ' & 0xff);
cursor -= 80;
}
}
void
......@@ -57,6 +47,6 @@ initcga(void)
cursor = 2*80;
setcursor(cursor);
cgaputs("booting...\n");
cgaputs("cga...\n");
setcursor(cursor);
}
......@@ -2,26 +2,14 @@
// Input is from the keyboard or serial port.
// Output is written to the screen and serial port.
#include "types.h"
#include "defs.h"
#include "param.h"
#include "traps.h"
#include "types.h"
#include "cpu.h"
#include "kernel.h"
#include "spinlock.h"
#include "condvar.h"
#include "fs.h"
#include "file.h"
#include "memlayout.h"
#include "mmu.h"
#include "queue.h"
#include "proc.h"
#include "x86.h"
#include <stdarg.h>
static void consputc(int);
static int panicked = 0;
static struct {
struct spinlock lock;
int locking;
......@@ -34,7 +22,7 @@ printint(void (*putch) (void*, char), void *putarg,
static char digits[] = "0123456789abcdef";
char buf[16];
int i;
uint x;
u32 x;
if(sign && (sign = xx < 0))
x = -xx;
......@@ -53,11 +41,18 @@ printint(void (*putch) (void*, char), void *putarg,
putch(putarg, buf[i]);
}
//PAGEBREAK: 50
// Only understands %d, %x, %p, %s.
// Print to the console.
static void
writecons(void *arg, char c)
{
uartputc(c);
cgaputc(c);
}
// Only understands %d, %x, %s.
void
vprintfmt(void (*putch) (void*, char), void *putarg,
char *fmt, va_list ap)
const char *fmt, va_list ap)
{
char *s;
int c, i, state;
......@@ -73,9 +68,9 @@ vprintfmt(void (*putch) (void*, char), void *putarg,
}
} else if(state == '%'){
if(c == 'd'){
printint(putch, putarg, va_arg(ap, uint), 10, 1);
} else if(c == 'x' || c == 'p'){
printint(putch, putarg, va_arg(ap, uint), 16, 0);
printint(putch, putarg, va_arg(ap, u32), 10, 1);
} else if(c == 'x') {
printint(putch, putarg, va_arg(ap, u32), 16, 0);
} else if(c == 's'){
s = (char*) va_arg(ap, char*);
if(s == 0)
......@@ -85,7 +80,7 @@ vprintfmt(void (*putch) (void*, char), void *putarg,
s++;
}
} else if(c == 'c'){
putch(putarg, va_arg(ap, uint));
putch(putarg, va_arg(ap, u32));
} else if(c == '%'){
putch(putarg, c);
} else {
......@@ -98,15 +93,8 @@ vprintfmt(void (*putch) (void*, char), void *putarg,
}
}
// Print to the console.
static void
writecons(void *arg, char c)
{
consputc(c);
}
void
cprintf(char *fmt, ...)
cprintf(const char *fmt, ...)
{
va_list ap;
......@@ -122,233 +110,33 @@ cprintf(char *fmt, ...)
release(&cons.lock);
}
// Print to a buffer.
struct bufstate {
char *p;
char *e;
};
static void
writebuf(void *arg, char c)
{
struct bufstate *bs = arg;
if (bs->p < bs->e) {
bs->p[0] = c;
bs->p++;
}
}
void
vsnprintf(char *buf, uint n, char *fmt, va_list ap)
{
struct bufstate bs = { buf, buf+n-1 };
vprintfmt(writebuf, (void*) &bs, fmt, ap);
bs.p[0] = '\0';
}
void
snprintf(char *buf, uint n, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, n, fmt, ap);
va_end(ap);
}
void
panic(char *s)
{
int i;
uint pcs[10];
cli();
cons.locking = 0;
cprintf("cpu%d: panic: ", cpu->id);
cprintf(s);
cprintf("\n");
getcallerpcs(&s, pcs);
for(i=0; i<10; i++)
cprintf(" %p", pcs[i]);
cprintf("\n");
panicked = 1; // freeze other CPU
extern void sys_halt();
sys_halt();
for(;;)
;
}
//PAGEBREAK: 50
#define BACKSPACE 0x100
#define CRTPORT 0x3d4
static ushort *crt = (ushort*)P2V(0xb8000); // CGA memory
static void
cgaputc(int c)
{
int pos;
// Cursor position: col + 80*row.
outb(CRTPORT, 14);
pos = inb(CRTPORT+1) << 8;
outb(CRTPORT, 15);
pos |= inb(CRTPORT+1);
if(c == '\n')
pos += 80 - pos%80;
else if(c == BACKSPACE){
if(pos > 0) --pos;
} else
crt[pos++] = (c&0xff) | 0x0700; // black on white
if((pos/80) >= 24){ // Scroll up.
memmove(crt, crt+80, sizeof(crt[0])*23*80);
pos -= 80;
memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
}
outb(CRTPORT, 14);
outb(CRTPORT+1, pos>>8);
outb(CRTPORT, 15);
outb(CRTPORT+1, pos);
crt[pos] = ' ' | 0x0700;
}
void
consputc(int c)
{
if(panicked){
cli();
for(;;)
;
}
if(c == BACKSPACE){
uartputc('\b'); uartputc(' '); uartputc('\b');
} else
uartputc(c);
cgaputc(c);
}
#define INPUT_BUF 128
struct {
struct spinlock lock;
struct condvar cv;
char buf[INPUT_BUF];
uint r; // Read index
uint w; // Write index
uint e; // Edit index
} input;
#define C(x) ((x)-'@') // Control-x
void
consoleintr(int (*getc)(void))
puts(const char *s)
{
int c;
uint8 *p, *ep;
acquire(&input.lock);
while((c = getc()) >= 0){
switch(c){
case C('P'): // Process listing.
procdumpall();
break;
case C('U'): // Kill line.
while(input.e != input.w &&
input.buf[(input.e-1) % INPUT_BUF] != '\n'){
input.e--;
consputc(BACKSPACE);
}
break;
case C('H'): case '\x7f': // Backspace
if(input.e != input.w){
input.e--;
consputc(BACKSPACE);
}
break;
default:
if(c != 0 && input.e-input.r < INPUT_BUF){
c = (c == '\r') ? '\n' : c;
input.buf[input.e++ % INPUT_BUF] = c;
consputc(c);
if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
input.w = input.e;
cv_wakeup(&input.cv);
}
}
break;
}
}
release(&input.lock);
}
p = (uint8*)s;
ep = p+strlen(s);
int
consoleread(struct inode *ip, char *dst, int n)
{
uint target;
int c;
iunlock(ip);
target = n;
acquire(&input.lock);
while(n > 0){
while(input.r == input.w){
if(proc->killed){
release(&input.lock);
ilock(ip, 1);
return -1;
}
cv_sleep(&input.cv, &input.lock);
}
c = input.buf[input.r++ % INPUT_BUF];
if(c == C('D')){ // EOF
if(n < target){
// Save ^D for next time, to make sure
// caller gets a 0-byte result.
input.r--;
}
break;
}
*dst++ = c;
--n;
if(c == '\n')
break;
}
release(&input.lock);
ilock(ip, 1);
for (; p < ep; p++)
writecons(NULL, *p);
return target - n;
}
int
consolewrite(struct inode *ip, char *buf, int n)
void __attribute__((noreturn))
panic(const char *s)
{
int i;
puts("panic: ");
puts(s);
puts("\n");
iunlock(ip);
acquire(&cons.lock);
for(i = 0; i < n; i++)
consputc(buf[i] & 0xff);
release(&cons.lock);
ilock(ip, 1);
return n;
for (;;);
}
void
consoleinit(void)
initconsole(void)
{
initlock(&cons.lock, "console");
initlock(&input.lock, "input");
initcondvar(&input.cv, "input");
devsw[CONSOLE].write = consolewrite;
devsw[CONSOLE].read = consoleread;
cons.locking = 1;
picenable(IRQ_KBD);
ioapicenable(IRQ_KBD, 0);
// XXX(sbw) enable once we setup %gs
cons.locking = 0;
}
// Per-CPU state
struct cpu {
u8 id; // Local APIC ID; index into cpus[] below
int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli?
#if 0
struct context *scheduler; // swtch() here to enter scheduler
struct taskstate ts; // Used by x86 to find stack for interrupt
struct segdesc gdt[NSEGS]; // x86 global descriptor table
volatile uint booted; // Has the CPU started?
int last_rcu_gc_ticks;
// Cpu-local storage variables; see below
struct cpu *cpu;
struct proc *proc; // The currently-running process.
struct kmem *kmem; // The per-core memory table
#endif
} __mpalign__;
// Per-CPU variables, holding pointers to the
// current cpu and to the current process.
// The asm suffix tells gcc to use "%gs:0" to refer to cpu
// and "%gs:4" to refer to proc. seginit sets up the
// %gs segment register so that %gs refers to the memory
// holding those two variables in the local cpu's struct cpu.
// This is similar to how thread-local variables are implemented
// in thread libraries such as Linux pthreads.
extern struct cpu *cpu __asm("%gs:0"); // &cpus[cpunum()].cpu
extern struct proc *proc __asm("%gs:8"); // cpus[cpunum()].proc
extern struct kmem *kmem __asm("%gs:16"); // &cpu[cpunum()].kmem
#include "types.h"
#define KBASE 0xFFFFFFFF80000000ull
#define KADDR(x) ((void*)(KBASE+(uintptr)(x)))
#define PADDR(x) ((uintptr)(x) - KBASE)
#define PGSIZE (2*1024*1024ull)
#define KCSEG (2<<3) /* kernel code segment */
#define KDSEG (3<<3) /* kernel data segment */
#define nil ((void*)0)
#define NULL ((void *)0)
static inline uptr v2p(void *a) { return (uptr) a - KBASE; }
static inline void *p2v(uptr a) { return (void *) a + KBASE; }
struct spinlock;
// console.c
void cprintf(const char*, ...);
void panic(const char*) __attribute__((noreturn));
// string.c
int memcmp(const void*, const void*, u32);
void* memmove(void*, const void*, u32);
void* memset(void*, int, u32);
char* safestrcpy(char*, const char*, int);
int strlen(const char*);
int strncmp(const char*, const char*, u32);
char* strncpy(char*, const char*, int);
int strcmp(const char *p, const char *q);
// spinlock.c
void acquire(struct spinlock*);
void getcallerpcs(void*, uptr*);
int holding(struct spinlock*);
void initlock(struct spinlock*, char*);
void release(struct spinlock*);
void pushcli(void);
void popcli(void);
// cga.c
void cgaputc(char c);
// uart.c
void uartputc(char c);
void memmove(void *dst, void *src, int64 n);
int strlen(const char*);
#include "types.h"
#include "multiboot.h"
#include "kernel.h"
extern void inituart(void);
extern void initcga(void);
extern void initconsole(void);
extern void initmp(void);
extern void inittrap(void);
void
cmain(void)
{
inituart();
initcga();
initconsole();
#if 0
initmp();
inittrap();
#endif
panic("end");
}
......@@ -3,22 +3,17 @@
// http://developer.intel.com/design/pentium/datashts/24201606.pdf
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mp.h"
#include "x86.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "queue.h"
#include "proc.h"
#include "mp.h"
#include "kernel.h"
#include "cpu.h"
struct cpu cpus[NCPU];
static struct cpu *bcpu __attribute__((aligned (CACHELINE)));
int ismp __attribute__((aligned (CACHELINE)));
int ncpu __attribute__((aligned (CACHELINE)));
uchar ioapicid __attribute__((aligned (CACHELINE)));
static struct cpu *bcpu __mpalign__;
int ismp __mpalign__;
int ncpu __mpalign__;
u8 ioapicid __mpalign__;
int
mpbcpu(void)
......@@ -26,8 +21,8 @@ mpbcpu(void)
return bcpu-cpus;
}
static uchar
sum(uchar *addr, int len)
static u8
sum(u8 *addr, int len)
{
int i, sum;
......@@ -39,11 +34,11 @@ sum(uchar *addr, int len)
// Look for an MP structure in the len bytes at addr.
static struct mp*
mpsearch1(uchar *addr, int len)
mpsearch1(u8 *addr, int len)
{
uchar *e, *p;
u8 *e, *p;
addr = p2v((uint) addr);
addr = p2v((uptr) addr);
e = addr+len;
for(p = addr; p < e; p += sizeof(struct mp))
if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
......@@ -59,20 +54,20 @@ mpsearch1(uchar *addr, int len)
static struct mp*
mpsearch(void)
{
uchar *bda;
uint p;
u8 *bda;
paddr p;
struct mp *mp;
bda = (uchar*)0x400;
bda = (u8*)0x400;
if((p = ((bda[0x0F]<<8)|bda[0x0E]) << 4)){
if((mp = mpsearch1((uchar*)p, 1024)))
if((mp = mpsearch1((u8*)p, 1024)))
return mp;
} else {
p = ((bda[0x14]<<8)|bda[0x13])*1024;
if((mp = mpsearch1((uchar*)p-1024, 1024)))
if((mp = mpsearch1((u8*)p-1024, 1024)))
return mp;
}
return mpsearch1((uchar*)0xF0000, 0x10000);
return mpsearch1((u8*)0xF0000, 0x10000);
}
// Search for an MP configuration table. For now,
......@@ -88,21 +83,21 @@ mpconfig(struct mp **pmp)
if((mp = mpsearch()) == 0 || mp->physaddr == 0)
return 0;
conf = (struct mpconf*) p2v((uint) mp->physaddr);
conf = (struct mpconf*) p2v((uptr) mp->physaddr);
if(memcmp(conf, "PCMP", 4) != 0)
return 0;
if(conf->version != 1 && conf->version != 4)
return 0;
if(sum((uchar*)conf, conf->length) != 0)
if(sum((u8*)conf, conf->length) != 0)
return 0;
*pmp = mp;
return conf;
}
void
mpinit(void)
initmp(void)
{
uchar *p, *e;
u8 *p, *e;
struct mp *mp;
struct mpconf *conf;
struct mpproc *proc;
......@@ -112,8 +107,8 @@ mpinit(void)
if((conf = mpconfig(&mp)) == 0)
return;
ismp = 1;
lapic = (uint*)conf->lapicaddr;
for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; p<e; ){
for(p=(u8*)(conf+1), e=(u8*)conf+conf->length; p<e; ){
switch(*p){
case MPPROC:
proc = (struct mpproc*)p;
......@@ -145,7 +140,6 @@ mpinit(void)
if(!ismp){
// Didn't like what we found; fall back to no MP.
ncpu = 1;
lapic = 0;
ioapicid = 0;
return;
}
......
// See MultiProcessor Specification Version 1.[14]
struct mp { // floating pointer
uchar signature[4]; // "_MP_"
void *physaddr; // phys addr of MP config table
uchar length; // 1
uchar specrev; // [14]
uchar checksum; // all bytes must add up to 0
uchar type; // MP system config type
uchar imcrp;
uchar reserved[3];
u8 signature[4]; // "_MP_"
u32 physaddr; // phys addr of MP config table
u8 length; // 1
u8 specrev; // [14]
u8 checksum; // all bytes must add up to 0
u8 type; // MP system config type
u8 imcrp;
u8 reserved[3];
};
struct mpconf { // configuration table header
uchar signature[4]; // "PCMP"
ushort length; // total table length
uchar version; // [14]
uchar checksum; // all bytes must add up to 0
uchar product[20]; // product id
uint *oemtable; // OEM table pointer
ushort oemlength; // OEM table length
ushort entry; // entry count
uint *lapicaddr; // address of local APIC
ushort xlength; // extended table length
uchar xchecksum; // extended table checksum
uchar reserved;
u8 signature[4]; // "PCMP"
u16 length; // total table length
u8 version; // [14]
u8 checksum; // all bytes must add up to 0
u8 product[20]; // product id
u32 oemtable; // OEM table pointer
u16 oemlength; // OEM table length
u16 entry; // entry count
u32 lapicaddr; // address of local APIC
u16 xlength; // extended table length
u8 xchecksum; // extended table checksum
u8 reserved;
};
struct mpproc { // processor table entry
uchar type; // entry type (0)
uchar apicid; // local APIC id
uchar version; // local APIC verison
uchar flags; // CPU flags
u8 type; // entry type (0)
u8 apicid; // local APIC id
u8 version; // local APIC verison
u8 flags; // CPU flags
#define MPBOOT 0x02 // This proc is the bootstrap processor.
uchar signature[4]; // CPU signature
uint feature; // feature flags from CPUID instruction
uchar reserved[8];
u8 signature[4]; // CPU signature
u32 feature; // feature flags from CPUID instruction
u8 reserved[8];
};
struct mpioapic { // I/O APIC table entry
uchar type; // entry type (2)
uchar apicno; // I/O APIC id
uchar version; // I/O APIC version
uchar flags; // I/O APIC flags
uint *addr; // I/O APIC address
u8 type; // entry type (2)
u8 apicno; // I/O APIC id
u8 version; // I/O APIC version
u8 flags; // I/O APIC flags
u32 addr; // I/O APIC address
};
// Table entry types
......
......@@ -10,5 +10,6 @@
#define MAXARG 32 // max exec arguments
#define MAXNAME 16 // max string names
#define MINCYCTHRESH 1000000 // min cycles a proc executes on a core before allowed to be stolen
#define INF 0xFFFFFFFF
#define INF (~0UL)
#define CACHELINE 64 // cache line size
#define MTRACE 0
// Mutual exclusion spin locks.
#include "types.h"
#include "defs.h"
#include "kernel.h"
#include "param.h"
#include "x86.h"
#include "memlayout.h"
#include "mmu.h"
#include "cpu.h"
#include "bits.h"
#include "spinlock.h"
#include "condvar.h"
#include "queue.h"
#include "proc.h"
#include "xv6-mtrace.h"
void
......@@ -49,7 +46,7 @@ acquire(struct spinlock *lk)
// The xchg is atomic.
// It also serializes, so that reads after acquire are not
// reordered before it.
while(xchg(&lk->locked, 1) != 0)
while(xchg32(&lk->locked, 1) != 0)
;
mtrace_lock_register(RET_EIP(),
......@@ -104,24 +101,24 @@ release(struct spinlock *lk)
// after a store. So lock->locked = 0 would work here.
// The xchg being asm volatile ensures gcc emits it after
// the above assignments (and after the critical section).
xchg(&lk->locked, 0);
xchg32(&lk->locked, 0);
popcli();
}
// Record the current call stack in pcs[] by following the %ebp chain.
void
getcallerpcs(void *v, uint pcs[])
getcallerpcs(void *v, uptr pcs[])
{
uint *ebp;
uptr *rbp;
int i;
ebp = (uint*)v - 2;
rbp = (uptr*)v - 2;
for(i = 0; i < 10; i++){
if(ebp == 0 || ebp < (uint*)KERNBASE || ebp == (uint*)0xffffffff)
if(rbp == 0 || rbp < (uptr*)KBASE || rbp == (uptr*)(~0UL))
break;
pcs[i] = ebp[1]; // saved %eip
ebp = (uint*)ebp[0]; // saved %ebp
pcs[i] = rbp[1]; // saved %rip
rbp = (uptr*)rbp[0]; // saved %rbp
}
for(; i < 10; i++)
pcs[i] = 0;
......@@ -144,22 +141,21 @@ holding(struct spinlock *lock)
void
pushcli(void)
{
int eflags;
u64 rflags;
eflags = readeflags();
rflags = readrflags();
cli();
if(cpu->ncli++ == 0)
cpu->intena = eflags & FL_IF;
cpu->intena = rflags & FL_IF;
}
void
popcli(void)
{
if(readeflags()&FL_IF)
if(readrflags()&FL_IF)
panic("popcli - interruptible");
if(--cpu->ncli < 0)
panic("popcli");
if(cpu->ncli == 0 && cpu->intena)
sti();
}
......@@ -4,13 +4,13 @@
// Mutual exclusion lock.
struct spinlock {
uint locked; // Is the lock held?
u32 locked; // Is the lock held?
#if SPINLOCK_DEBUG
// For debugging:
char *name; // Name of lock.
struct cpu *cpu; // The cpu holding the lock.
uint pcs[10]; // The call stack (an array of program counters)
uptr pcs[10]; // The call stack (an array of program counters)
// that locked the lock.
#endif
};
......
......@@ -3,11 +3,61 @@
extern Segdesc bootgdt[NUMSEG];
void
inittrap(void)
{
}
// Bootstrap GDT. Used by boot.S but defined in C
// so we can use the data structure macros in amd64.h.
Segdesc bootgdt[NUMSEG] = {
SEGDESC(0, 0, 0), // null
SEGDESC(0, 0xfffff, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G), // 32-bit kernel code
SEGDESC(0, 0, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_L|SEG_G), // 64-bit kernel code
SEGDESC(0, 0xfffff, SEG_W|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G), // kernel data
SEGDESC(0, 0, 0), // null
SEGDESC(0, 0xfffff, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G), // 32-bit kernel code
SEGDESC(0, 0, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_L|SEG_G), // 64-bit kernel code
SEGDESC(0, 0xfffff, SEG_W|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G), // kernel data
};
#if 0
Intdesc idt[256];
Segdesc gdt[NUMSEG];
extern Segdesc bootgdt[NUMSEG];
extern uint64 trapentry[];
static Taskseg ts;
static char istack[8192];
void
inittrap(void)
{
int i;
uint32 bits;
uint64 base, entry;
bits = INT_P | SEG_INTR64; // present, interrupt gate
for(i=0; i<256; i++) {
entry = trapentry[i];
idt[i] = INTDESC(KCSEG, entry, bits);
}
memmove(gdt, bootgdt, sizeof gdt);
base = (uintptr)&ts;
gdt[TSSSEG>>3] = SEGDESC(base, (sizeof ts-1), SEG_P|SEG_TSS64A);
gdt[(TSSSEG>>3)+1] = SEGDESCHI(base);
ts.rsp0 = (uintptr)istack+sizeof istack;
lidt(idt, sizeof idt);
lgdt(gdt, sizeof gdt);
ltr(TSSSEG);
}
void
trap(void)
{
panic("trap");
}
#endif
......@@ -10,3 +10,7 @@ typedef uint16 u16;
typedef uint32 u32;
typedef int64 s64;
typedef uint64 u64;
typedef uint64 uptr;
typedef uptr paddr;
#define __mpalign__ __attribute__((aligned(CACHELINE)))
// Intel 8250 serial port (UART).
#include "types.h"
#include "kernel.h"
#include "x86.h"
......@@ -7,7 +8,7 @@
static int uart; // is there a uart?
void
uartputc(int c)
uartputc(char c)
{
int i;
......@@ -45,6 +46,6 @@ inituart(void)
inb(COM1+0);
// Announce that we're here.
for(p="xv6...\n"; *p; p++)
for(p="uart...\n"; *p; p++)
uartputc(*p);
}
......@@ -30,3 +30,36 @@ microdelay(u32 delay)
{
}
static inline u32
xchg32(volatile u32 *addr, u32 newval)
{
u32 result;
// The + in "+m" denotes a read-modify-write operand.
__asm volatile("lock; xchgl %0, %1" :
"+m" (*addr), "=a" (result) :
"1" (newval) :
"cc");
return result;
}
static inline u64
readrflags(void)
{
u64 rflags;
__asm volatile("pushfq; popq %0" : "=r" (rflags));
return rflags;
}
static inline void
cli(void)
{
__asm volatile("cli");
}
static inline void
sti(void)
{
__asm volatile("sti");
}
#if MTRACE
typedef __signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
......@@ -10,9 +11,12 @@ typedef unsigned long long uint64_t;
typedef __PTRDIFF_TYPE__ intptr_t;
typedef unsigned __PTRDIFF_TYPE__ uintptr_t;
void* memcpy(void *dst, const void *src, uint n);
void* memcpy(void *dst, const void *src, u32 n);
char* strncpy(char *s, const char *t, int n);
#define RET_EIP() ((unsigned long)__builtin_return_address(0))
#include "mtrace-magic.h"
#else
#define mtrace_lock_register(ip, x, name, op, y)
#endif
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论