archmp.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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 _MP_*
  10. mpscan(uchar *addr, int len)
  11. {
  12. uchar *e, *p, sum;
  13. int i;
  14. e = addr+len;
  15. for(p = addr; p < e; p += sizeof(_MP_)){
  16. if(memcmp(p, "_MP_", 4))
  17. continue;
  18. sum = 0;
  19. for(i = 0; i < sizeof(_MP_); i++)
  20. sum += p[i];
  21. if(sum == 0)
  22. return (_MP_*)p;
  23. }
  24. return 0;
  25. }
  26. static _MP_*
  27. mpsearch(void)
  28. {
  29. uchar *bda;
  30. ulong p;
  31. _MP_ *mp;
  32. /*
  33. * Search for the MP Floating Pointer Structure:
  34. * 1) in the first KB of the EBDA;
  35. * 2) in the last KB of system base memory;
  36. * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
  37. */
  38. bda = KADDR(0x400);
  39. if((p = (bda[0x0F]<<8)|bda[0x0E])){
  40. if(mp = mpscan(KADDR(p<<4), 1024))
  41. return mp;
  42. }
  43. else{
  44. p = ((bda[0x14]<<8)|bda[0x13])*1024;
  45. if(p != 0 && (mp = mpscan(KADDR(p-1024), 1024)) != nil)
  46. return mp;
  47. }
  48. return mpscan(KADDR(0xF0000), 0x10000);
  49. }
  50. static void
  51. mpresetothers(void)
  52. {
  53. /*
  54. * INIT all excluding self.
  55. */
  56. lapicicrw(0, 0x000C0000|ApicINIT);
  57. }
  58. static int identify(void);
  59. PCArch archmp = {
  60. .id= "_MP_",
  61. .ident= identify,
  62. .reset= mpshutdown,
  63. .intrinit= mpinit,
  64. .intrenable= mpintrenable,
  65. .intron= lapicintron,
  66. .introff= lapicintroff,
  67. .fastclock= i8253read,
  68. .timerset= lapictimerset,
  69. .resetothers= mpresetothers,
  70. };
  71. static int
  72. identify(void)
  73. {
  74. char *cp;
  75. PCMP *pcmp;
  76. uchar *p, sum;
  77. ulong length;
  78. if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
  79. return 1;
  80. /*
  81. * Search for an MP configuration table. For now,
  82. * don't accept the default configurations (physaddr == 0).
  83. * Check for correct signature, calculate the checksum and,
  84. * if correct, check the version.
  85. * To do: check extended table checksum.
  86. */
  87. if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0) {
  88. /*
  89. * we can easily get processor info from acpi, but
  90. * interrupt routing, etc. would require interpreting aml.
  91. */
  92. print("archmp: no mp table found, assuming uniprocessor\n");
  93. return 1;
  94. }
  95. pcmp = KADDR(_mp_->physaddr);
  96. if(memcmp(pcmp, "PCMP", 4) != 0) {
  97. print("archmp: mp table has bad magic");
  98. return 1;
  99. }
  100. length = pcmp->length;
  101. sum = 0;
  102. for(p = (uchar*)pcmp; length; length--)
  103. sum += *p++;
  104. if(sum || (pcmp->version != 1 && pcmp->version != 4))
  105. return 1;
  106. if(cpuserver && m->havetsc)
  107. archmp.fastclock = tscticks;
  108. return 0;
  109. }
  110. Lock mpsynclock;
  111. void
  112. syncclock(void)
  113. {
  114. uvlong x;
  115. if(arch->fastclock != tscticks)
  116. return;
  117. if(m->machno == 0){
  118. wrmsr(0x10, 0);
  119. m->tscticks = 0;
  120. } else {
  121. x = MACHP(0)->tscticks;
  122. while(x == MACHP(0)->tscticks)
  123. ;
  124. wrmsr(0x10, MACHP(0)->tscticks);
  125. cycles(&m->tscticks);
  126. }
  127. }
  128. uvlong
  129. tscticks(uvlong *hz)
  130. {
  131. if(hz != nil)
  132. *hz = m->cpuhz;
  133. cycles(&m->tscticks); /* Uses the rdtsc instruction */
  134. return m->tscticks;
  135. }