runtime: add runtime.cputicks() and seed fastrand with it

This patch adds a function to get the current cpu ticks.  This is
deemed to be 'sufficiently random' to use to seed fastrand to mitigate
the algorithmic complexity attacks on the hash table implementation.

On AMD64 we use the RDTSC instruction.  For 386, this instruction,
while valid, is not recognized by 8a so I've inserted the opcode by
hand.  For ARM, this routine is currently stubbed to return a constant
0 value.

Future work: update 8a to recognize RDTSC.

Fixes #2630.

R=rsc
CC=golang-dev
https://golang.org/cl/5606048
diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s
index 5240063..c242af8 100644
--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -524,6 +524,15 @@
 	MOVL	sp+0(FP), AX
 	RET
 
+// int64 runtime·cputicks(void), so really
+// void runtime·cputicks(int64 *ticks)
+TEXT runtime·cputicks(SB),7,$0
+	BYTE	$0x0F; BYTE $0x31;     // RDTSC; not supported by 8a
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
+	RET
+
 TEXT runtime·ldt0setup(SB),7,$16
 	// set up ldt 7 to point at tls0
 	// ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s
index 308a660..9a660b5 100644
--- a/src/pkg/runtime/asm_amd64.s
+++ b/src/pkg/runtime/asm_amd64.s
@@ -568,4 +568,11 @@
 	MOVQ	sp+0(FP), AX
 	RET
 
+// int64 runtime·cputicks(void)
+TEXT runtime·cputicks(SB),7,$0
+	RDTSC
+	SHLQ	$32, DX
+	ADDQ	DX, AX
+	RET
+
 GLOBL runtime·tls0(SB), $64
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
index 42c7677..58b1862 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/pkg/runtime/asm_arm.s
@@ -265,6 +265,16 @@
 TEXT runtime·emptyfunc(SB),0,$0
 	RET
 
+// int64 runtime·cputicks(), so really
+// void runtime·cputicks(int64 *ticks)
+// stubbed: return int64(0)
+TEXT runtime·cputicks(SB),7,$0
+	MOVW    0(FP), R1
+	MOVW	$0, R0
+	MOVW    R0, 0(R1)
+	MOVW    R0, 4(R1)
+	RET
+
 TEXT runtime·abort(SB),7,$-4
 	MOVW	$0, R0
 	MOVW	(R0), R1
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index cb45a0c..5bb690a 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -332,7 +332,7 @@
 	runtime·atomicstorep(&runtime·allm, m);
 
 	m->id = runtime·sched.mcount++;
-	m->fastrand = 0x49f6428aUL + m->id;
+	m->fastrand = 0x49f6428aUL + m->id + runtime·cputicks();
 	m->stackalloc = runtime·malloc(sizeof(*m->stackalloc));
 	runtime·FixAlloc_Init(m->stackalloc, FixedStack, runtime·SysAlloc, nil, nil);
 
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index df2cd14..6929921 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -566,6 +566,7 @@
 void	runtime·resetcpuprofiler(int32);
 void	runtime·setcpuprofilerate(void(*)(uintptr*, int32), int32);
 void	runtime·usleep(uint32);
+int64	runtime·cputicks(void);
 
 #pragma	varargck	argpos	runtime·printf	1
 #pragma	varargck	type	"d"	int32