mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
x86/vmx: Fold VMCS logic in vmx_{get,set}_segment_register()
Xen's segment enumeration almost matches the VMCS encoding order, while the VMCS encoding order has the system segments immediately following the user segments for all relevant attributes. Use a sneaky xor to hide the difference in encoding order to fold the switch statements, dropping 10 __vmread() and 10 __vmwrite() calls. Bloat-o-meter reports: add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-433 (-433) Function old new delta vmx_set_segment_register 804 593 -211 vmx_get_segment_register 778 556 -222 showing that these wrappers aren't trivial. In addition, 20 BUGs worth of metadata are dropped. No functional change. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
0bdc43c8de
commit
b4c669fd7e
1 file changed
+36
-45
+36
-45
@@ -986,6 +986,7 @@ static void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg,
|
||||
struct segment_register *reg)
|
||||
{
|
||||
unsigned long attr = 0, sel = 0, limit;
|
||||
unsigned int tmp_seg;
|
||||
|
||||
/*
|
||||
* We may get here in the context of dump_execstate(), which may have
|
||||
@@ -1009,34 +1010,34 @@ static void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg,
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( seg )
|
||||
/*
|
||||
* Xen's x86_seg_* enumeration *almost* matches the VMCS encoding order.
|
||||
*
|
||||
* tr and ldtr are reversed, and other areas of code rely on this, so we
|
||||
* can't just re-enumerate.
|
||||
*/
|
||||
BUILD_BUG_ON(x86_seg_tr != 6);
|
||||
BUILD_BUG_ON(x86_seg_ldtr != 7);
|
||||
BUILD_BUG_ON(x86_seg_gdtr != 8);
|
||||
BUILD_BUG_ON(x86_seg_idtr != 9);
|
||||
switch ( tmp_seg = seg )
|
||||
{
|
||||
case x86_seg_es ... x86_seg_gs:
|
||||
__vmread(GUEST_SEG_SELECTOR(seg), &sel);
|
||||
__vmread(GUEST_SEG_LIMIT(seg), &limit);
|
||||
__vmread(GUEST_SEG_BASE(seg), ®->base);
|
||||
__vmread(GUEST_SEG_AR_BYTES(seg), &attr);
|
||||
break;
|
||||
case x86_seg_tr:
|
||||
__vmread(GUEST_TR_SELECTOR, &sel);
|
||||
__vmread(GUEST_TR_LIMIT, &limit);
|
||||
__vmread(GUEST_TR_BASE, ®->base);
|
||||
__vmread(GUEST_TR_AR_BYTES, &attr);
|
||||
break;
|
||||
case x86_seg_gdtr:
|
||||
__vmread(GUEST_GDTR_LIMIT, &limit);
|
||||
__vmread(GUEST_GDTR_BASE, ®->base);
|
||||
break;
|
||||
case x86_seg_idtr:
|
||||
__vmread(GUEST_IDTR_LIMIT, &limit);
|
||||
__vmread(GUEST_IDTR_BASE, ®->base);
|
||||
break;
|
||||
case x86_seg_ldtr:
|
||||
__vmread(GUEST_LDTR_SELECTOR, &sel);
|
||||
__vmread(GUEST_LDTR_LIMIT, &limit);
|
||||
__vmread(GUEST_LDTR_BASE, ®->base);
|
||||
__vmread(GUEST_LDTR_AR_BYTES, &attr);
|
||||
tmp_seg ^= 1; /* Flip tr and ldtr so GUEST_SEG_*() works. */
|
||||
fallthrough;
|
||||
|
||||
case x86_seg_es ... x86_seg_gs:
|
||||
__vmread(GUEST_SEG_SELECTOR(tmp_seg), &sel);
|
||||
__vmread(GUEST_SEG_AR_BYTES(tmp_seg), &attr);
|
||||
fallthrough;
|
||||
|
||||
case x86_seg_gdtr:
|
||||
case x86_seg_idtr:
|
||||
__vmread(GUEST_SEG_LIMIT(tmp_seg), &limit);
|
||||
__vmread(GUEST_SEG_BASE(tmp_seg), ®->base);
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
return;
|
||||
@@ -1150,32 +1151,22 @@ static void vmx_set_segment_register(struct vcpu *v, enum x86_segment seg,
|
||||
|
||||
switch ( seg )
|
||||
{
|
||||
case x86_seg_tr:
|
||||
case x86_seg_ldtr:
|
||||
seg ^= 1; /* Flip tr and ldtr so GUEST_SEG_*() works. */
|
||||
fallthrough;
|
||||
|
||||
case x86_seg_es ... x86_seg_gs:
|
||||
__vmwrite(GUEST_SEG_SELECTOR(seg), sel);
|
||||
__vmwrite(GUEST_SEG_AR_BYTES(seg), attr);
|
||||
fallthrough;
|
||||
|
||||
case x86_seg_gdtr:
|
||||
case x86_seg_idtr:
|
||||
__vmwrite(GUEST_SEG_LIMIT(seg), limit);
|
||||
__vmwrite(GUEST_SEG_BASE(seg), base);
|
||||
__vmwrite(GUEST_SEG_AR_BYTES(seg), attr);
|
||||
break;
|
||||
case x86_seg_tr:
|
||||
__vmwrite(GUEST_TR_SELECTOR, sel);
|
||||
__vmwrite(GUEST_TR_LIMIT, limit);
|
||||
__vmwrite(GUEST_TR_BASE, base);
|
||||
__vmwrite(GUEST_TR_AR_BYTES, attr);
|
||||
break;
|
||||
case x86_seg_gdtr:
|
||||
__vmwrite(GUEST_GDTR_LIMIT, limit);
|
||||
__vmwrite(GUEST_GDTR_BASE, base);
|
||||
break;
|
||||
case x86_seg_idtr:
|
||||
__vmwrite(GUEST_IDTR_LIMIT, limit);
|
||||
__vmwrite(GUEST_IDTR_BASE, base);
|
||||
break;
|
||||
case x86_seg_ldtr:
|
||||
__vmwrite(GUEST_LDTR_SELECTOR, sel);
|
||||
__vmwrite(GUEST_LDTR_LIMIT, limit);
|
||||
__vmwrite(GUEST_LDTR_BASE, base);
|
||||
__vmwrite(GUEST_LDTR_AR_BYTES, attr);
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||