[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] x86/vmx: Fold VMCS logic in vmx_{get,set}_segment_register()
commit b4c669fd7eabfdba93aa96a3a3b62829a67a60d5 Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Fri Jan 21 11:00:09 2022 +0000 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Thu Jan 27 17:38:15 2022 +0000 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@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> --- xen/arch/x86/hvm/vmx/vmx.c | 77 ++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index c44cf8f5d4..9765cfd90a 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -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_ldtr: + 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: - __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); + __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_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; + fallthrough; + 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); + __vmwrite(GUEST_SEG_LIMIT(seg), limit); + __vmwrite(GUEST_SEG_BASE(seg), base); break; + default: BUG(); } -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |