Browse Source

Plan 9 from Bell Labs 2012-04-27

David du Colombier 12 years ago
parent
commit
5e64ba2fa2
5 changed files with 221 additions and 34 deletions
  1. 20 4
      sys/src/9/pc/main.c
  2. 17 17
      sys/src/libmach/9.c
  3. 24 0
      sys/src/libmach/elf.h
  4. 155 10
      sys/src/libmach/executable.c
  5. 5 3
      sys/src/libmach/sym.c

+ 20 - 4
sys/src/9/pc/main.c

@@ -31,7 +31,7 @@ char *confval[MAXCONF];
 int nconf;
 uchar *sp;	/* user stack of init proc */
 int delaylink;
-int always_idle;
+int idle_spin, idle_if_nproc;
 
 static void
 options(void)
@@ -78,11 +78,17 @@ extern void (*i8237alloc)(void);
 void
 main(void)
 {
+	cgapost(0);
 	mach0init();
+cgapost(1);
 	options();
+cgapost(2);
 	ioinit();
+cgapost(3);
 	i8250console();
+cgapost(4);
 	quotefmtinstall();
+cgapost(5);
 	screeninit();
 
 	print("\nPlan 9\n");
@@ -119,11 +125,15 @@ main(void)
 		links();
 	conf.monitor = 1;
 	chandevreset();
+	cgapost(0xcd);
+
 	pageinit();
 	i8253link();
 	swapinit();
 	userinit();
 	active.thunderbirdsarego = 1;
+
+	cgapost(0x99);
 	schedinit();
 }
 
@@ -174,12 +184,14 @@ init0(void)
 
 	up->nerrlab = 0;
 
+cgapost(0x70);
 	spllo();
 
 	/*
 	 * These are o.k. because rootinit is null.
 	 * Then early kproc's will have a root and dot.
 	 */
+cgapost(0x71);
 	up->slash = namec("#/", Atodir, 0, 0);
 	pathclose(up->slash->path);
 	up->slash->path = newpath("/");
@@ -188,6 +200,7 @@ init0(void)
 	chandevinit();
 
 	if(!waserror()){
+cgapost(0x72);
 		snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
 		ksetenv("terminal", buf, 0);
 		ksetenv("cputype", "386", 0);
@@ -202,7 +215,9 @@ init0(void)
 		}
 		poperror();
 	}
+cgapost(0x73);
 	kproc("alarm", alarmkproc, 0);
+	cgapost(0x9);
 	touser(sp);
 }
 
@@ -920,13 +935,14 @@ idlehands(void)
 	/*
 	 * we used to halt only on single-core setups. halting in an smp system 
 	 * can result in a startup latency for processes that become ready.
-	 * if always_idle is zero, we care more about saving energy
+	 * if idle_spin is zero, we care more about saving energy
 	 * than reducing this latency.
 	 *
-	 * the performance loss with always_idle == 0 seems to be slight
+	 * the performance loss with idle_spin == 0 seems to be slight
 	 * and it reduces lock contention (thus system time and real time)
 	 * on many-core systems with large values of NPROC.
 	 */
-	if(conf.nmach == 1 || always_idle == 0)
+	if(conf.nmach == 1 || idle_spin == 0 ||
+	    idle_if_nproc && conf.nmach >= idle_if_nproc)
 		halt();
 }

+ 17 - 17
sys/src/libmach/9.c

@@ -101,21 +101,21 @@ Mach mpower64 =
 {
 	"power64",
 	MPOWER64,		/* machine type */
-	power64reglist,	/* register set */
-	REGSIZE,	/* number of bytes in register set */
-	FPREGSIZE,	/* number of bytes in FP register set */
-	"PC",		/* name of PC */
-	"SP",		/* name of SP */
-	"LR",		/* name of link register */
-	"setSB",	/* static base register name */
-	0,		/* value */
-	0x1000,		/* page size */
-	0x80000000ULL,	/* kernel base */
-	0,		/* kernel text mask */
-	0x7FFFFFFFULL,	/* user stack top */
-	4,		/* quantization of pc */
-	8,		/* szaddr */
-	8,		/* szreg */
-	4,		/* szfloat */
-	8,		/* szdouble */
+	power64reglist,		/* register set */
+	REGSIZE,		/* number of bytes in register set */
+	FPREGSIZE,		/* number of bytes in FP register set */
+	"PC",			/* name of PC */
+	"SP",			/* name of SP */
+	"LR",			/* name of link register */
+	"setSB",		/* static base register name */
+	0,			/* value */
+	0x100000,		/* page size (TODO, too many choices) */
+	0xffffffff80000000ull,	/* kernel base (TODO, likely incorrect) */
+	0xf000000000000000ull,	/* kernel text mask (TODO, likely incorrect) */
+	0x00007ffffff00000ull,	/* user stack top (TODO, likely incorrect) */
+	4,			/* quantization of pc */
+	8,			/* szaddr */
+	8,			/* szreg */
+	4,			/* szfloat */
+	8,			/* szdouble */
 };

+ 24 - 0
sys/src/libmach/elf.h

@@ -46,6 +46,17 @@ typedef struct {
 	int	align;		/* memory/file alignment */
 } Phdr;
 
+typedef struct {
+	u32int	type;		/* entry type */
+	u32int	flags;		/* entry flags */
+	u64int	offset;		/* file offset */
+	u64int	vaddr;		/* virtual address */
+	u64int	paddr;		/* physical address */
+	u64int	filesz;		/* file size */
+	u64int	memsz;		/* memory size */
+	u64int	align;		/* memory/file alignment */
+} P64hdr;
+
 typedef struct {
 	ulong	name;		/* section name */
 	ulong	type;		/* SHT_... */
@@ -59,6 +70,19 @@ typedef struct {
 	ulong	entsize;	/* entry size if table */
 } Shdr;
 
+typedef struct {
+	u32int	name;		/* section name */
+	u32int	type;		/* SHT_... */
+	u64int	flags;		/* SHF_... */
+	u64int	addr;		/* virtual address */
+	u64int	offset;		/* file offset */
+	u64int	size;		/* section size */
+	u32int	link;		/* misc info */
+	u32int	info;		/* misc info */
+	u64int	addralign;	/* memory alignment */
+	u64int	entsize;	/* entry size if table */
+} S64hdr;
+
 enum {
 	/* Ehdr codes */
 	MAG0 = 0,		/* ident[] indexes */

+ 155 - 10
sys/src/libmach/executable.c

@@ -17,6 +17,7 @@ typedef struct {
 			uvlong hdr[1];
 		};
 		Ehdr;			/* elf.h */
+		E64hdr;
 		struct mipsexec;	/* bootexec.h */
 		struct mips4kexec;	/* bootexec.h */
 		struct sparcexec;	/* bootexec.h */
@@ -206,7 +207,7 @@ ExecTable exectab[] =
 		sizeof(Exec)+8,
 		nil,
 		commonllp64 },
-	{ ELF_MAG,			/* any elf32 */
+	{ ELF_MAG,			/* any ELF */
 		"elf executable",
 		nil,
 		FNONE,
@@ -411,6 +412,12 @@ commonboot(Fhdr *fp)
 		fp->name = "amd64 plan 9 boot image";
 		fp->dataddr = _round(fp->txtaddr+fp->txtsz, 4096);
 		break;
+	case FPOWER64:
+		fp->type = FPOWER64B;
+		fp->txtaddr = fp->entry;
+		fp->name = "power64 plan 9 boot image";
+		fp->dataddr = fp->txtaddr+fp->txtsz;
+		break;
 	default:
 		return;
 	}
@@ -562,12 +569,124 @@ nextboot(int fd, Fhdr *fp, ExecHdr *hp)
 }
 
 /*
- * Elf32 binaries.
+ * ELF64 binaries.
  */
 static int
-elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
+elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
 {
+	E64hdr *ep;
+	P64hdr *ph;
+	ushort (*swab)(ushort);
+	ulong (*swal)(ulong);
+	uvlong (*swav)(uvlong);
+	int i, it, id, is, phsz;
+	uvlong uvl;
+
+	ep = &hp->e;
+	if(ep->ident[DATA] == ELFDATA2LSB) {
+		swab = leswab;
+		swal = leswal;
+		swav = leswav;
+	} else if(ep->ident[DATA] == ELFDATA2MSB) {
+		swab = beswab;
+		swal = beswal;
+		swav = beswav;
+	} else {
+		werrstr("bad ELF64 encoding - not big or little endian");
+		return 0;
+	}
+
+	ep->type = swab(ep->type);
+	ep->machine = swab(ep->machine);
+	ep->version = swal(ep->version);
+	if(ep->type != EXEC || ep->version != CURRENT)
+		return 0;
+	ep->elfentry = swav(ep->elfentry);
+	ep->phoff = swav(ep->phoff);
+	ep->shoff = swav(ep->shoff);
+	ep->flags = swal(ep->flags);
+	ep->ehsize = swab(ep->ehsize);
+	ep->phentsize = swab(ep->phentsize);
+	ep->phnum = swab(ep->phnum);
+	ep->shentsize = swab(ep->shentsize);
+	ep->shnum = swab(ep->shnum);
+	ep->shstrndx = swab(ep->shstrndx);
 
+	fp->magic = ELF_MAG;
+	fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
+	switch(ep->machine) {
+	default:
+		return 0;
+	case AMD64:
+		mach = &mamd64;
+		fp->type = FAMD64;
+		fp->name = "amd64 ELF64 executable";
+		break;
+	case POWER64:
+		mach = &mpower64;
+		fp->type = FPOWER64;
+		fp->name = "power64 ELF64 executable";
+		break;
+	}
+
+	if(ep->phentsize != sizeof(P64hdr)) {
+		werrstr("bad ELF64 header size");
+		return 0;
+	}
+	phsz = sizeof(P64hdr)*ep->phnum;
+	ph = malloc(phsz);
+	if(!ph)
+		return 0;
+	seek(fd, ep->phoff, 0);
+	if(read(fd, ph, phsz) < 0) {
+		free(ph);
+		return 0;
+	}
+	for(i = 0; i < ep->phnum; i++) {
+		ph[i].type = swal(ph[i].type);
+		ph[i].flags = swal(ph[i].flags);
+		ph[i].offset = swav(ph[i].offset);
+		ph[i].vaddr = swav(ph[i].vaddr);
+		ph[i].paddr = swav(ph[i].paddr);
+		ph[i].filesz = swav(ph[i].filesz);
+		ph[i].memsz = swav(ph[i].memsz);
+		ph[i].align = swav(ph[i].align);
+	}
+
+	/* find text, data and symbols and install them */
+	it = id = is = -1;
+	for(i = 0; i < ep->phnum; i++) {
+		if(ph[i].type == LOAD
+		&& (ph[i].flags & (R|X)) == (R|X) && it == -1)
+			it = i;
+		else if(ph[i].type == LOAD
+		&& (ph[i].flags & (R|W)) == (R|W) && id == -1)
+			id = i;
+		else if(ph[i].type == NOPTYPE && is == -1)
+			is = i;
+	}
+	if(it == -1 || id == -1) {
+		werrstr("No ELF64 TEXT or DATA sections");
+		free(ph);
+		return 0;
+	}
+
+	settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
+	/* 8c: out of fixed registers */
+	uvl = ph[id].memsz - ph[id].filesz;
+	setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl);
+	if(is != -1)
+		setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset);
+	free(ph);
+	return 1;
+}
+
+/*
+ * ELF32 binaries.
+ */
+static int
+elf32dotout(int fd, Fhdr *fp, ExecHdr *hp)
+{
 	ulong (*swal)(ulong);
 	ushort (*swab)(ushort);
 	Ehdr *ep;
@@ -576,10 +695,6 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
 
 	/* bitswap the header according to the DATA format */
 	ep = &hp->e;
-	if(ep->ident[CLASS] != ELFCLASS32) {
-		werrstr("bad ELF class - not 32 bit");
-		return 0;
-	}
 	if(ep->ident[DATA] == ELFDATA2LSB) {
 		swab = leswab;
 		swal = leswal;
@@ -587,7 +702,7 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
 		swab = beswab;
 		swal = beswal;
 	} else {
-		werrstr("bad ELF encoding - not big or little endian");
+		werrstr("bad ELF32 encoding - not big or little endian");
 		return 0;
 	}
 
@@ -614,33 +729,44 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
 	case I386:
 		mach = &mi386;
 		fp->type = FI386;
+		fp->name = "386 ELF32 executable";
 		break;
 	case MIPS:
 		mach = &mmips;
 		fp->type = FMIPS;
+		fp->name = "mips ELF32 executable";
 		break;
 	case SPARC64:
 		mach = &msparc64;
 		fp->type = FSPARC64;
+		fp->name = "sparc64 ELF32 executable";
 		break;
 	case POWER:
 		mach = &mpower;
 		fp->type = FPOWER;
+		fp->name = "power ELF32 executable";
+		break;
+	case POWER64:
+		mach = &mpower64;
+		fp->type = FPOWER64;
+		fp->name = "power64 ELF32 executable";
 		break;
 	case AMD64:
 		mach = &mamd64;
 		fp->type = FAMD64;
+		fp->name = "amd64 ELF32 executable";
 		break;
 	case ARM:
 		mach = &marm;
 		fp->type = FARM;
+		fp->name = "arm ELF32 executable";
 		break;
 	default:
 		return 0;
 	}
 
 	if(ep->phentsize != sizeof(Phdr)) {
-		werrstr("bad ELF header size");
+		werrstr("bad ELF32 header size");
 		return 0;
 	}
 	phsz = sizeof(Phdr)*ep->phnum;
@@ -690,7 +816,7 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
 			return 1;
 		}
 
-		werrstr("No TEXT or DATA sections");
+		werrstr("No ELF32 TEXT or DATA sections");
 		free(ph);
 		return 0;
 	}
@@ -703,6 +829,25 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
 	return 1;
 }
 
+/*
+ * Elf binaries.
+ */
+static int
+elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
+{
+	Ehdr *ep;
+
+	/* bitswap the header according to the DATA format */
+	ep = &hp->e;
+	if(ep->ident[CLASS] == ELFCLASS32)
+		return elf32dotout(fd, fp, hp);
+	else if(ep->ident[CLASS] == ELFCLASS64)
+		return elf64dotout(fd, fp, hp);
+
+	werrstr("bad ELF class - not 32 bit");
+	return 0;
+}
+
 /*
  * (Free|Net)BSD ARM header.
  */

+ 5 - 3
sys/src/libmach/sym.c

@@ -102,15 +102,17 @@ syminit(int fd, Fhdr *fp)
 	Bseek(&b, fp->symoff, 0);
 	nsym = 0;
 	size = 0;
+	if((fp->_magic && (fp->magic & HDR_MAGIC)) || mach->szaddr == 8)
+		svalsz = 8;
+	else
+		svalsz = 4;
 	for(p = symbols; size < fp->symsz; p++, nsym++) {
-		if(fp->_magic && (fp->magic & HDR_MAGIC)){
-			svalsz = 8;
+		if(svalsz == 8){
 			if(Bread(&b, &vl, 8) != 8)
 				return symerrmsg(8, "symbol");
 			p->value = beswav(vl);
 		}
 		else{
-			svalsz = 4;
 			if(Bread(&b, &l, 4) != 4)
 				return symerrmsg(4, "symbol");
 			p->value = (u32int)beswal(l);