summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/archmp.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/pc/archmp.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/pc/archmp.c')
-rwxr-xr-xsys/src/9/pc/archmp.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/sys/src/9/pc/archmp.c b/sys/src/9/pc/archmp.c
new file mode 100755
index 000000000..b94097cea
--- /dev/null
+++ b/sys/src/9/pc/archmp.c
@@ -0,0 +1,139 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "mp.h"
+
+_MP_ *_mp_;
+
+static _MP_*
+mpscan(uchar *addr, int len)
+{
+ uchar *e, *p, sum;
+ int i;
+
+ e = addr+len;
+ for(p = addr; p < e; p += sizeof(_MP_)){
+ if(memcmp(p, "_MP_", 4))
+ continue;
+ sum = 0;
+ for(i = 0; i < sizeof(_MP_); i++)
+ sum += p[i];
+ if(sum == 0)
+ return (_MP_*)p;
+ }
+ return 0;
+}
+
+static _MP_*
+mpsearch(void)
+{
+ uchar *bda;
+ ulong p;
+ _MP_ *mp;
+
+ /*
+ * Search for the MP Floating Pointer Structure:
+ * 1) in the first KB of the EBDA;
+ * 2) in the last KB of system base memory;
+ * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
+ */
+ bda = KADDR(0x400);
+ if((p = (bda[0x0F]<<8)|bda[0x0E])){
+ if(mp = mpscan(KADDR(p<<4), 1024))
+ return mp;
+ }
+ else{
+ p = ((bda[0x14]<<8)|bda[0x13])*1024;
+ if(mp = mpscan(KADDR(p-1024), 1024))
+ return mp;
+ }
+ return mpscan(KADDR(0xF0000), 0x10000);
+}
+
+static int identify(void);
+
+PCArch archmp = {
+.id= "_MP_",
+.ident= identify,
+.reset= mpshutdown,
+.intrinit= mpinit,
+.intrenable= mpintrenable,
+.intron= lapicintron,
+.introff= lapicintroff,
+.fastclock= i8253read,
+.timerset= lapictimerset,
+};
+
+static int
+identify(void)
+{
+ char *cp;
+ PCMP *pcmp;
+ uchar *p, sum;
+ ulong length;
+
+ if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
+ return 1;
+
+ /*
+ * Search for an MP configuration table. For now,
+ * don't accept the default configurations (physaddr == 0).
+ * Check for correct signature, calculate the checksum and,
+ * if correct, check the version.
+ * To do: check extended table checksum.
+ */
+ if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0)
+ return 1;
+
+ pcmp = KADDR(_mp_->physaddr);
+ if(memcmp(pcmp, "PCMP", 4))
+ return 1;
+
+ length = pcmp->length;
+ sum = 0;
+ for(p = (uchar*)pcmp; length; length--)
+ sum += *p++;
+
+ if(sum || (pcmp->version != 1 && pcmp->version != 4))
+ return 1;
+
+ if(cpuserver && m->havetsc)
+ archmp.fastclock = tscticks;
+ return 0;
+}
+
+Lock mpsynclock;
+
+void
+syncclock(void)
+{
+ uvlong x;
+
+ if(arch->fastclock != tscticks)
+ return;
+
+ if(m->machno == 0){
+ wrmsr(0x10, 0);
+ m->tscticks = 0;
+ } else {
+ x = MACHP(0)->tscticks;
+ while(x == MACHP(0)->tscticks)
+ ;
+ wrmsr(0x10, MACHP(0)->tscticks);
+ cycles(&m->tscticks);
+ }
+}
+
+uvlong
+tscticks(uvlong *hz)
+{
+ if(hz != nil)
+ *hz = m->cpuhz;
+
+ cycles(&m->tscticks); /* Uses the rdtsc instruction */
+ return m->tscticks;
+}