17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "io.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier #include "mp.h"
97dd7cddfSDavid du Colombier
107dd7cddfSDavid du Colombier _MP_ *_mp_;
117dd7cddfSDavid du Colombier
121206f3fcSDavid du Colombier static void
mpresetothers(void)131206f3fcSDavid du Colombier mpresetothers(void)
141206f3fcSDavid du Colombier {
151206f3fcSDavid du Colombier /*
161206f3fcSDavid du Colombier * INIT all excluding self.
171206f3fcSDavid du Colombier */
181206f3fcSDavid du Colombier lapicicrw(0, 0x000C0000|ApicINIT);
191206f3fcSDavid du Colombier }
201206f3fcSDavid du Colombier
21e288d156SDavid du Colombier static int identify(void);
22e288d156SDavid du Colombier
23e288d156SDavid du Colombier PCArch archmp = {
24e288d156SDavid du Colombier .id= "_MP_",
25e288d156SDavid du Colombier .ident= identify,
26e288d156SDavid du Colombier .reset= mpshutdown,
27e288d156SDavid du Colombier .intrinit= mpinit,
28e288d156SDavid du Colombier .intrenable= mpintrenable,
294de34a7eSDavid du Colombier .intron= lapicintron,
304de34a7eSDavid du Colombier .introff= lapicintroff,
31e288d156SDavid du Colombier .fastclock= i8253read,
32e288d156SDavid du Colombier .timerset= lapictimerset,
331206f3fcSDavid du Colombier .resetothers= mpresetothers,
34e288d156SDavid du Colombier };
35e288d156SDavid du Colombier
367dd7cddfSDavid du Colombier static int
identify(void)377dd7cddfSDavid du Colombier identify(void)
387dd7cddfSDavid du Colombier {
39901484c1SDavid du Colombier char *cp;
407dd7cddfSDavid du Colombier PCMP *pcmp;
417dd7cddfSDavid du Colombier uchar *p, sum;
427dd7cddfSDavid du Colombier ulong length;
437dd7cddfSDavid du Colombier
44901484c1SDavid du Colombier if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
457dd7cddfSDavid du Colombier return 1;
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier /*
487dd7cddfSDavid du Colombier * Search for an MP configuration table. For now,
497dd7cddfSDavid du Colombier * don't accept the default configurations (physaddr == 0).
507dd7cddfSDavid du Colombier * Check for correct signature, calculate the checksum and,
517dd7cddfSDavid du Colombier * if correct, check the version.
527dd7cddfSDavid du Colombier * To do: check extended table checksum.
537dd7cddfSDavid du Colombier */
54*00a4193cSDavid du Colombier if((_mp_ = sigsearch("_MP_")) == 0 || _mp_->physaddr == 0) {
55e360d427SDavid du Colombier /*
56e360d427SDavid du Colombier * we can easily get processor info from acpi, but
57e360d427SDavid du Colombier * interrupt routing, etc. would require interpreting aml.
58e360d427SDavid du Colombier */
59e360d427SDavid du Colombier print("archmp: no mp table found, assuming uniprocessor\n");
607dd7cddfSDavid du Colombier return 1;
61e360d427SDavid du Colombier }
627dd7cddfSDavid du Colombier
63*00a4193cSDavid du Colombier if (0)
64*00a4193cSDavid du Colombier iprint("mp physaddr %#lux\n", _mp_->physaddr);
657dd7cddfSDavid du Colombier pcmp = KADDR(_mp_->physaddr);
66e360d427SDavid du Colombier if(memcmp(pcmp, "PCMP", 4) != 0) {
67e360d427SDavid du Colombier print("archmp: mp table has bad magic");
687dd7cddfSDavid du Colombier return 1;
69e360d427SDavid du Colombier }
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier length = pcmp->length;
727dd7cddfSDavid du Colombier sum = 0;
737dd7cddfSDavid du Colombier for(p = (uchar*)pcmp; length; length--)
747dd7cddfSDavid du Colombier sum += *p++;
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier if(sum || (pcmp->version != 1 && pcmp->version != 4))
777dd7cddfSDavid du Colombier return 1;
787dd7cddfSDavid du Colombier
79e288d156SDavid du Colombier if(cpuserver && m->havetsc)
80e288d156SDavid du Colombier archmp.fastclock = tscticks;
817dd7cddfSDavid du Colombier return 0;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier
849a747e4fSDavid du Colombier Lock mpsynclock;
859a747e4fSDavid du Colombier
869a747e4fSDavid du Colombier void
syncclock(void)879a747e4fSDavid du Colombier syncclock(void)
889a747e4fSDavid du Colombier {
899a747e4fSDavid du Colombier uvlong x;
909a747e4fSDavid du Colombier
91dc5a79c1SDavid du Colombier if(arch->fastclock != tscticks)
92dc5a79c1SDavid du Colombier return;
93dc5a79c1SDavid du Colombier
949a747e4fSDavid du Colombier if(m->machno == 0){
959a747e4fSDavid du Colombier wrmsr(0x10, 0);
969a747e4fSDavid du Colombier m->tscticks = 0;
979a747e4fSDavid du Colombier } else {
989a747e4fSDavid du Colombier x = MACHP(0)->tscticks;
999a747e4fSDavid du Colombier while(x == MACHP(0)->tscticks)
1009a747e4fSDavid du Colombier ;
101e288d156SDavid du Colombier wrmsr(0x10, MACHP(0)->tscticks);
102da51d93aSDavid du Colombier cycles(&m->tscticks);
1039a747e4fSDavid du Colombier }
1049a747e4fSDavid du Colombier }
1059a747e4fSDavid du Colombier
1069a747e4fSDavid du Colombier uvlong
tscticks(uvlong * hz)1079a747e4fSDavid du Colombier tscticks(uvlong *hz)
1089a747e4fSDavid du Colombier {
1099a747e4fSDavid du Colombier if(hz != nil)
1109a747e4fSDavid du Colombier *hz = m->cpuhz;
1119a747e4fSDavid du Colombier
112e288d156SDavid du Colombier cycles(&m->tscticks); /* Uses the rdtsc instruction */
113e288d156SDavid du Colombier return m->tscticks;
1149a747e4fSDavid du Colombier }
115