Print this page
9600 LDT still not happy under KPTI
*** 176,187 ****
/*
* Routines for loading segment descriptors in format the hardware
* can understand.
*/
- #if defined(__amd64)
-
/*
* In long mode we have the new L or long mode attribute bit
* for code segments. Only the conforming bit in type is used along
* with descriptor priority and present bits. Default operand size must
* be zero when in long mode. In 32-bit compatibility mode all fields
--- 176,185 ----
*** 191,200 ****
--- 189,200 ----
void
set_usegd(user_desc_t *dp, uint_t lmode, void *base, size_t size,
uint_t type, uint_t dpl, uint_t gran, uint_t defopsz)
{
ASSERT(lmode == SDP_SHORT || lmode == SDP_LONG);
+ /* This should never be a "system" segment. */
+ ASSERT3U(type & SDT_S, !=, 0);
/*
* 64-bit long mode.
*/
if (lmode == SDP_LONG)
*** 203,212 ****
--- 203,220 ----
/*
* 32-bit compatibility mode.
*/
dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32-bit ops */
+ /*
+ * We should always set the "accessed" bit (SDT_A), otherwise the CPU
+ * will write to the GDT whenever we change segment registers around.
+ * With KPTI on, the GDT is read-only in the user page table, which
+ * causes crashes if we don't set this.
+ */
+ ASSERT3U(type & SDT_A, !=, 0);
+
dp->usd_long = lmode; /* 64-bit mode */
dp->usd_type = type;
dp->usd_dpl = dpl;
dp->usd_p = 1;
dp->usd_gran = gran; /* 0 = bytes, 1 = pages */
*** 216,256 ****
dp->usd_hibase = (uintptr_t)base >> (16 + 8);
dp->usd_lolimit = size;
dp->usd_hilimit = (uintptr_t)size >> 16;
}
- #elif defined(__i386)
-
/*
- * Install user segment descriptor for code and data.
- */
- void
- set_usegd(user_desc_t *dp, void *base, size_t size, uint_t type,
- uint_t dpl, uint_t gran, uint_t defopsz)
- {
- dp->usd_lolimit = size;
- dp->usd_hilimit = (uintptr_t)size >> 16;
-
- dp->usd_lobase = (uintptr_t)base;
- dp->usd_midbase = (uintptr_t)base >> 16;
- dp->usd_hibase = (uintptr_t)base >> (16 + 8);
-
- dp->usd_type = type;
- dp->usd_dpl = dpl;
- dp->usd_p = 1;
- dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32 bit operands */
- dp->usd_gran = gran; /* 0 = bytes, 1 = pages */
- }
-
- #endif /* __i386 */
-
- /*
* Install system segment descriptor for LDT and TSS segments.
*/
- #if defined(__amd64)
-
void
set_syssegd(system_desc_t *dp, void *base, size_t size, uint_t type,
uint_t dpl)
{
dp->ssd_lolimit = size;
--- 224,237 ----
*** 279,321 ****
(uintptr_t)dp->ssd_hibase << (16 + 8) |
(uintptr_t)dp->ssd_hi64base << (16 + 8 + 8);
return ((void *)base);
}
- #elif defined(__i386)
-
- void
- set_syssegd(system_desc_t *dp, void *base, size_t size, uint_t type,
- uint_t dpl)
- {
- dp->ssd_lolimit = size;
- dp->ssd_hilimit = (uintptr_t)size >> 16;
-
- dp->ssd_lobase = (uintptr_t)base;
- dp->ssd_midbase = (uintptr_t)base >> 16;
- dp->ssd_hibase = (uintptr_t)base >> (16 + 8);
-
- dp->ssd_type = type;
- dp->ssd_zero = 0; /* must be zero */
- dp->ssd_dpl = dpl;
- dp->ssd_p = 1;
- dp->ssd_gran = 0; /* force byte units */
- }
-
- void *
- get_ssd_base(system_desc_t *dp)
- {
- uintptr_t base;
-
- base = (uintptr_t)dp->ssd_lobase |
- (uintptr_t)dp->ssd_midbase << 16 |
- (uintptr_t)dp->ssd_hibase << (16 + 8);
- return ((void *)base);
- }
-
- #endif /* __i386 */
-
/*
* Install gate segment descriptor for interrupt, trap, call and task gates.
*
* For 64 bit native if we have KPTI enabled, we use the IST stack mechanism on
* all interrupts. We have different ISTs for each class of exceptions that are
--- 260,269 ----
*** 389,409 ****
*/
void
gdt_update_usegd(uint_t sidx, user_desc_t *udp)
{
! #if defined(__xpv)
uint64_t dpa = CPU->cpu_m.mcpu_gdtpa + sizeof (*udp) * sidx;
if (HYPERVISOR_update_descriptor(pa_to_ma(dpa), *(uint64_t *)udp))
panic("gdt_update_usegd: HYPERVISOR_update_descriptor");
#else /* __xpv */
-
CPU->cpu_gdt[sidx] = *udp;
-
#endif /* __xpv */
}
/*
* Writes single descriptor pointed to by udp into a processes
--- 337,370 ----
*/
void
gdt_update_usegd(uint_t sidx, user_desc_t *udp)
{
! #if defined(DEBUG)
! /* This should never be a "system" segment, but it might be null. */
! if (udp->usd_p != 0 || udp->usd_type != 0) {
! ASSERT3U(udp->usd_type & SDT_S, !=, 0);
! }
! /*
! * We should always set the "accessed" bit (SDT_A), otherwise the CPU
! * will write to the GDT whenever we change segment registers around.
! * With KPTI on, the GDT is read-only in the user page table, which
! * causes crashes if we don't set this.
! */
! if (udp->usd_p != 0 || udp->usd_type != 0) {
! ASSERT3U(udp->usd_type & SDT_A, !=, 0);
! }
! #endif
+ #if defined(__xpv)
uint64_t dpa = CPU->cpu_m.mcpu_gdtpa + sizeof (*udp) * sidx;
if (HYPERVISOR_update_descriptor(pa_to_ma(dpa), *(uint64_t *)udp))
panic("gdt_update_usegd: HYPERVISOR_update_descriptor");
#else /* __xpv */
CPU->cpu_gdt[sidx] = *udp;
#endif /* __xpv */
}
/*
* Writes single descriptor pointed to by udp into a processes
*** 410,421 ****
* LDT entry pointed to by ldp.
*/
int
ldt_update_segd(user_desc_t *ldp, user_desc_t *udp)
{
! #if defined(__xpv)
uint64_t dpa;
dpa = mmu_ptob(hat_getpfnum(kas.a_hat, (caddr_t)ldp)) |
((uintptr_t)ldp & PAGEOFFSET);
--- 371,397 ----
* LDT entry pointed to by ldp.
*/
int
ldt_update_segd(user_desc_t *ldp, user_desc_t *udp)
{
! #if defined(DEBUG)
! /* This should never be a "system" segment, but it might be null. */
! if (udp->usd_p != 0 || udp->usd_type != 0) {
! ASSERT3U(udp->usd_type & SDT_S, !=, 0);
! }
! /*
! * We should always set the "accessed" bit (SDT_A), otherwise the CPU
! * will write to the LDT whenever we change segment registers around.
! * With KPTI on, the LDT is read-only in the user page table, which
! * causes crashes if we don't set this.
! */
! if (udp->usd_p != 0 || udp->usd_type != 0) {
! ASSERT3U(udp->usd_type & SDT_A, !=, 0);
! }
! #endif
+ #if defined(__xpv)
uint64_t dpa;
dpa = mmu_ptob(hat_getpfnum(kas.a_hat, (caddr_t)ldp)) |
((uintptr_t)ldp & PAGEOFFSET);
*** 425,435 ****
*/
if (HYPERVISOR_update_descriptor(pa_to_ma(dpa), *(uint64_t *)udp) != 0)
return (EINVAL);
#else /* __xpv */
-
*ldp = *udp;
#endif /* __xpv */
return (0);
}
--- 401,410 ----