archmp.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. .fastclock= i8253read,
  58. .timerset= lapictimerset,
  59. };
  60. static int
  61. identify(void)
  62. {
  63. PCMP *pcmp;
  64. uchar *p, sum;
  65. ulong length;
  66. if(getconf("*nomp"))
  67. return 1;
  68. /*
  69. * Search for an MP configuration table. For now,
  70. * don't accept the default configurations (physaddr == 0).
  71. * Check for correct signature, calculate the checksum and,
  72. * if correct, check the version.
  73. * To do: check extended table checksum.
  74. */
  75. if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0)
  76. return 1;
  77. pcmp = KADDR(_mp_->physaddr);
  78. if(memcmp(pcmp, "PCMP", 4))
  79. return 1;
  80. length = pcmp->length;
  81. sum = 0;
  82. for(p = (uchar*)pcmp; length; length--)
  83. sum += *p++;
  84. if(sum || (pcmp->version != 1 && pcmp->version != 4))
  85. return 1;
  86. if(cpuserver && m->havetsc)
  87. archmp.fastclock = tscticks;
  88. return 0;
  89. }
  90. Lock mpsynclock;
  91. void
  92. syncclock(void)
  93. {
  94. uvlong x;
  95. if(arch->fastclock != tscticks)
  96. return;
  97. if(m->machno == 0){
  98. wrmsr(0x10, 0);
  99. m->tscticks = 0;
  100. } else {
  101. x = MACHP(0)->tscticks;
  102. while(x == MACHP(0)->tscticks)
  103. ;
  104. wrmsr(0x10, MACHP(0)->tscticks);
  105. m->tscticks = MACHP(0)->tscticks;
  106. }
  107. }
  108. uvlong
  109. tscticks(uvlong *hz)
  110. {
  111. if(hz != nil)
  112. *hz = m->cpuhz;
  113. cycles(&m->tscticks); /* Uses the rdtsc instruction */
  114. return m->tscticks;
  115. }