segments.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*P:600 The x86 architecture has segments, which involve a table of descriptors
  2. * which can be used to do funky things with virtual address interpretation.
  3. * We originally used to use segments so the Guest couldn't alter the
  4. * Guest<->Host Switcher, and then we had to trim Guest segments, and restore
  5. * for userspace per-thread segments, but trim again for on userspace->kernel
  6. * transitions... This nightmarish creation was contained within this file,
  7. * where we knew not to tread without heavy armament and a change of underwear.
  8. *
  9. * In these modern times, the segment handling code consists of simple sanity
  10. * checks, and the worst you'll experience reading this code is butterfly-rash
  11. * from frolicking through its parklike serenity. :*/
  12. #include "lg.h"
  13. static int desc_ok(const struct desc_struct *gdt)
  14. {
  15. /* MBZ=0, P=1, DT=1 */
  16. return ((gdt->b & 0x00209000) == 0x00009000);
  17. }
  18. static int segment_present(const struct desc_struct *gdt)
  19. {
  20. return gdt->b & 0x8000;
  21. }
  22. static int ignored_gdt(unsigned int num)
  23. {
  24. return (num == GDT_ENTRY_TSS
  25. || num == GDT_ENTRY_LGUEST_CS
  26. || num == GDT_ENTRY_LGUEST_DS
  27. || num == GDT_ENTRY_DOUBLEFAULT_TSS);
  28. }
  29. /* We don't allow removal of CS, DS or SS; it doesn't make sense. */
  30. static void check_segment_use(struct lguest *lg, unsigned int desc)
  31. {
  32. if (lg->regs->gs / 8 == desc)
  33. lg->regs->gs = 0;
  34. if (lg->regs->fs / 8 == desc)
  35. lg->regs->fs = 0;
  36. if (lg->regs->es / 8 == desc)
  37. lg->regs->es = 0;
  38. if (lg->regs->ds / 8 == desc
  39. || lg->regs->cs / 8 == desc
  40. || lg->regs->ss / 8 == desc)
  41. kill_guest(lg, "Removed live GDT entry %u", desc);
  42. }
  43. static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end)
  44. {
  45. unsigned int i;
  46. for (i = start; i < end; i++) {
  47. /* We never copy these ones to real gdt */
  48. if (ignored_gdt(i))
  49. continue;
  50. /* We could fault in switch_to_guest if they are using
  51. * a removed segment. */
  52. if (!segment_present(&lg->gdt[i])) {
  53. check_segment_use(lg, i);
  54. continue;
  55. }
  56. if (!desc_ok(&lg->gdt[i]))
  57. kill_guest(lg, "Bad GDT descriptor %i", i);
  58. /* DPL 0 presumably means "for use by guest". */
  59. if ((lg->gdt[i].b & 0x00006000) == 0)
  60. lg->gdt[i].b |= (GUEST_PL << 13);
  61. /* Set accessed bit, since gdt isn't writable. */
  62. lg->gdt[i].b |= 0x00000100;
  63. }
  64. }
  65. void setup_default_gdt_entries(struct lguest_ro_state *state)
  66. {
  67. struct desc_struct *gdt = state->guest_gdt;
  68. unsigned long tss = (unsigned long)&state->guest_tss;
  69. /* Hypervisor segments. */
  70. gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
  71. gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
  72. /* This is the one which we *cannot* copy from guest, since tss
  73. is depended on this lguest_ro_state, ie. this cpu. */
  74. gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16);
  75. gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000)
  76. | ((tss >> 16) & 0x000000FF);
  77. }
  78. void setup_guest_gdt(struct lguest *lg)
  79. {
  80. lg->gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
  81. lg->gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
  82. lg->gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
  83. lg->gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
  84. }
  85. /* This is a fast version for the common case where only the three TLS entries
  86. * have changed. */
  87. void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt)
  88. {
  89. unsigned int i;
  90. for (i = GDT_ENTRY_TLS_MIN; i <= GDT_ENTRY_TLS_MAX; i++)
  91. gdt[i] = lg->gdt[i];
  92. }
  93. void copy_gdt(const struct lguest *lg, struct desc_struct *gdt)
  94. {
  95. unsigned int i;
  96. for (i = 0; i < GDT_ENTRIES; i++)
  97. if (!ignored_gdt(i))
  98. gdt[i] = lg->gdt[i];
  99. }
  100. void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num)
  101. {
  102. if (num > ARRAY_SIZE(lg->gdt))
  103. kill_guest(lg, "too many gdt entries %i", num);
  104. lgread(lg, lg->gdt, table, num * sizeof(lg->gdt[0]));
  105. fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->gdt));
  106. lg->changed |= CHANGED_GDT;
  107. }
  108. void guest_load_tls(struct lguest *lg, unsigned long gtls)
  109. {
  110. struct desc_struct *tls = &lg->gdt[GDT_ENTRY_TLS_MIN];
  111. lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
  112. fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1);
  113. lg->changed |= CHANGED_GDT_TLS;
  114. }