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