archmp.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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), 1024))
  41. return mp;
  42. }
  43. else{
  44. p = ((bda[0x14]<<8)|bda[0x13])*1024;
  45. if(mp = mpscan(KADDR(p-1024), 1024))
  46. return mp;
  47. }
  48. return mpscan(KADDR(0xF0000), 0x10000);
  49. }
  50. static int identify(void);
  51. PCArch archmp = {
  52. .id= "_MP_",
  53. .ident= identify,
  54. .reset= mpshutdown,
  55. .intrinit= mpinit,
  56. .intrenable= mpintrenable,
  57. .intron= lapicintron,
  58. .introff= lapicintroff,
  59. .fastclock= i8253read,
  60. .timerset= lapictimerset,
  61. };
  62. static int
  63. identify(void)
  64. {
  65. PCMP *pcmp;
  66. uchar *p, sum;
  67. ulong length;
  68. if(getconf("*nomp"))
  69. return 1;
  70. /*
  71. * Search for an MP configuration table. For now,
  72. * don't accept the default configurations (physaddr == 0).
  73. * Check for correct signature, calculate the checksum and,
  74. * if correct, check the version.
  75. * To do: check extended table checksum.
  76. */
  77. if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0)
  78. return 1;
  79. pcmp = KADDR(_mp_->physaddr);
  80. if(memcmp(pcmp, "PCMP", 4))
  81. return 1;
  82. length = pcmp->length;
  83. sum = 0;
  84. for(p = (uchar*)pcmp; length; length--)
  85. sum += *p++;
  86. if(sum || (pcmp->version != 1 && pcmp->version != 4))
  87. return 1;
  88. if(cpuserver && m->havetsc)
  89. archmp.fastclock = tscticks;
  90. return 0;
  91. }
  92. Lock mpsynclock;
  93. void
  94. syncclock(void)
  95. {
  96. uvlong x;
  97. if(arch->fastclock != tscticks)
  98. return;
  99. if(m->machno == 0){
  100. wrmsr(0x10, 0);
  101. m->tscticks = 0;
  102. } else {
  103. x = MACHP(0)->tscticks;
  104. while(x == MACHP(0)->tscticks)
  105. ;
  106. wrmsr(0x10, MACHP(0)->tscticks);
  107. cycles(&m->tscticks);
  108. }
  109. }
  110. uvlong
  111. tscticks(uvlong *hz)
  112. {
  113. if(hz != nil)
  114. *hz = m->cpuhz;
  115. cycles(&m->tscticks); /* Uses the rdtsc instruction */
  116. return m->tscticks;
  117. }