return 0;
}
- if ( seg != x86_seg_tr && !reg->attr.fields.s )
+ if ( seg == x86_seg_tr )
{
- gprintk(XENLOG_ERR,
- "System segment provided for a code or data segment\n");
- return -EINVAL;
- }
+ if ( reg->attr.fields.s )
+ {
+ gprintk(XENLOG_ERR, "Code or data segment provided for TR\n");
+ return -EINVAL;
+ }
- if ( seg == x86_seg_tr && reg->attr.fields.s )
+ if ( reg->attr.fields.type != SYS_DESC_tss_busy )
+ {
+ gprintk(XENLOG_ERR, "Non-32-bit-TSS segment provided for TR\n");
+ return -EINVAL;
+ }
+ }
+ else if ( !reg->attr.fields.s )
{
- gprintk(XENLOG_ERR, "Code or data segment provided for TR\n");
+ gprintk(XENLOG_ERR,
+ "System segment provided for a code or data segment\n");
return -EINVAL;
}
#define SEG(s, r) ({ \
s = (struct segment_register){ .base = (r)->s ## _base, \
.limit = (r)->s ## _limit, \
- .attr.bytes = (r)->s ## _ar }; \
+ .attr.bytes = (r)->s ## _ar | \
+ (x86_seg_##s != x86_seg_tr ? 1 : 2) }; \
check_segment(&s, x86_seg_ ## s); })
rc = SEG(cs, regs);
case x86_seg_cs:
ASSERT(reg->attr.fields.p); /* Usable. */
ASSERT(reg->attr.fields.s); /* User segment. */
+ ASSERT(reg->attr.fields.type & 0x1); /* Accessed. */
ASSERT((reg->base >> 32) == 0); /* Upper bits clear. */
break;
ASSERT(reg->attr.fields.s); /* User segment. */
ASSERT(!(reg->attr.fields.type & 0x8)); /* Data segment. */
ASSERT(reg->attr.fields.type & 0x2); /* Writeable. */
+ ASSERT(reg->attr.fields.type & 0x1); /* Accessed. */
ASSERT((reg->base >> 32) == 0); /* Upper bits clear. */
}
break;
if ( reg->attr.fields.type & 0x8 )
ASSERT(reg->attr.fields.type & 0x2); /* Readable. */
+ ASSERT(reg->attr.fields.type & 0x1); /* Accessed. */
+
if ( seg == x86_seg_fs || seg == x86_seg_gs )
ASSERT(is_canonical_address(reg->base));
else