archmp.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "mp.h"
  8. _MP_ *_mp_;
  9. static void
  10. mpresetothers(void)
  11. {
  12. /*
  13. * INIT all excluding self.
  14. */
  15. lapicicrw(0, 0x000C0000|ApicINIT);
  16. }
  17. static int identify(void);
  18. PCArch archmp = {
  19. .id= "_MP_",
  20. .ident= identify,
  21. .reset= mpshutdown,
  22. .intrinit= mpinit,
  23. .intrenable= mpintrenable,
  24. .intron= lapicintron,
  25. .introff= lapicintroff,
  26. .fastclock= i8253read,
  27. .timerset= lapictimerset,
  28. .resetothers= mpresetothers,
  29. };
  30. static int
  31. identify(void)
  32. {
  33. char *cp;
  34. PCMP *pcmp;
  35. uchar *p, sum;
  36. ulong length;
  37. if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
  38. return 1;
  39. /*
  40. * Search for an MP configuration table. For now,
  41. * don't accept the default configurations (physaddr == 0).
  42. * Check for correct signature, calculate the checksum and,
  43. * if correct, check the version.
  44. * To do: check extended table checksum.
  45. */
  46. if((_mp_ = sigsearch("_MP_")) == 0 || _mp_->physaddr == 0) {
  47. /*
  48. * we can easily get processor info from acpi, but
  49. * interrupt routing, etc. would require interpreting aml.
  50. */
  51. print("archmp: no mp table found, assuming uniprocessor\n");
  52. return 1;
  53. }
  54. if (0)
  55. iprint("mp physaddr %#lux\n", _mp_->physaddr);
  56. pcmp = KADDR(_mp_->physaddr);
  57. if(memcmp(pcmp, "PCMP", 4) != 0) {
  58. print("archmp: mp table has bad magic");
  59. return 1;
  60. }
  61. length = pcmp->length;
  62. sum = 0;
  63. for(p = (uchar*)pcmp; length; length--)
  64. sum += *p++;
  65. if(sum || (pcmp->version != 1 && pcmp->version != 4))
  66. return 1;
  67. if(cpuserver && m->havetsc)
  68. archmp.fastclock = tscticks;
  69. return 0;
  70. }
  71. Lock mpsynclock;
  72. void
  73. syncclock(void)
  74. {
  75. uvlong x;
  76. if(arch->fastclock != tscticks)
  77. return;
  78. if(m->machno == 0){
  79. wrmsr(0x10, 0);
  80. m->tscticks = 0;
  81. } else {
  82. x = MACHP(0)->tscticks;
  83. while(x == MACHP(0)->tscticks)
  84. ;
  85. wrmsr(0x10, MACHP(0)->tscticks);
  86. cycles(&m->tscticks);
  87. }
  88. }
  89. uvlong
  90. tscticks(uvlong *hz)
  91. {
  92. if(hz != nil)
  93. *hz = m->cpuhz;
  94. cycles(&m->tscticks); /* Uses the rdtsc instruction */
  95. return m->tscticks;
  96. }