archmp.c 2.4 KB

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