CPL initialization fix
PATCH 1/1 CPL initialization fix
CPL should be determined by code segment's DPL, not data segment's.
This solves a problem migrating a QEMU guest without PV-on-HVM drivers
xen/arch/x86/hvm/svm/svm.c +1 -1
@@ -557,7 +557,7 @@ static void svm_set_segment_register(strbreak ;case x86_seg_ss:memcpy (&vmcb->ss, reg,sizeof (*reg)); - vmcb->cpl = vmcb->ss.attr.fields.dpl; + vmcb->cpl = vmcb->cs.attr.fields.dpl;break ;case x86_seg_tr:memcpy (&vmcb->tr, reg,sizeof (*reg));
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
CPL is architecturally SS.DPL in almost all cases. It's certainly not CS.DPL. What do you mean by 'migrate a QEMU guest'?
-- Keir
Quoted 22 lines · Ben Guthro
CPL should be determined by code segment's DPL, not data segment's.
This solves a problem migrating a QEMU guest without PV-on-HVM drivers
Signed-off-by Robert Plillips <[email protected]>Signed-off-by Ben Guthro <[email protected]>diff -r
f76f151a7431xen/arch/x86/hvm/svm/svm.cxen/arch/x86/hvm/svm/svm.c +1
-1@@ -557,7 +557,7 @@ static void svm_set_segment_register(strbreak ;case x86_seg_ss:memcpy (&vmcb->ss, reg,sizeof (*reg)); - vmcb->cpl = vmcb->ss.attr.fields.dpl; + vmcb->cpl = vmcb->cs.attr.fields.dpl;break ;case x86_seg_tr:memcpy (&vmcb->tr, reg,sizeof (*reg));_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
For reference, from AMD's manual, Vol.2:
"The processor reads the current privilege level from the CPL field in the VMCB, not from SS.DPL. However, SS.DPL should match the CPL field."
And from Intel's manual, Vol.3B:
"Note that the value of the DPL field for SS is always equal to the logical processor¹s current privilege level (CPL)."
-- Keir
Quoted 36 lines · Keir Fraser
CPL is architecturally SS.DPL in almost all cases. It's certainly not CS.DPL. What do you mean by 'migrate a QEMU guest'?
-- Keir
Quoted 18 lines · Ben Guthro
CPL should be determined by code segment's DPL, not data segment's.
This solves a problem migrating a QEMU guest without PV-on-HVM drivers
Signed-off-by Robert Plillips <[email protected]>Signed-off-by Ben Guthro <[email protected]>diff -r
f76f151a7431xen/arch/x86/hvm/svm/svm.cxen/arch/x86/hvm/svm/svm.c +1
-1@@ -557,7 +557,7 @@ static void svm_set_segment_register(strbreak ;case x86_seg_ss:memcpy (&vmcb->ss, reg,sizeof (*reg)); - vmcb->cpl = vmcb->ss.attr.fields.dpl; + vmcb->cpl = vmcb->cs.attr.fields.dpl;break ;case x86_seg_tr:memcpy (&vmcb->tr, reg,sizeof (*reg));Quoted 4 lines
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Neither of the sections that you quote specify that it is correct to set the CPL from the SS DPL. They say (a) the SS DPL is set from the CPL and (b) the SS DPL is (always mysteriously) equal to the CPL
I found the AMD (and Intel) manuals to be inconsistent.
AMD's manual, Vol.2:
4.9.2 Privilege-Level Types
Current Privilege-Level. The current privilege-level (CPL) is the privilege level at which the processor is currently executing. The CPL is stored in an internal processor register that is invisible to software. Software changes the CPL by performing a control transfer to a different code segment with a new privilege level.
So the processor switches CPL by changing code segments, and the CPL is taken from the code segment's DPL.
And what, one might ask, if the stack segment and code segment have different DPLs? The AMD manual doesn't say. It simply asserts that they will be equal.
In our experience this is not true.
When we perform a live migrate from a HVM VS without PV drivers [what Ben Guthro referred to as a QEMU-only virtual server], we simply pause the guest in whatever state we find it. We found that when the guest happened to be in user-mode code (CPL == 3), the migrate failed because, on the receiving node, the CPL would be restored to 0. The zero came from SS.DPL. However the value in CS.DPL was 3.
SS.DPL was not equal to CS.DPL.
When we changed the code (per this patch), the CPL would be restored from CS.DPL. That value was correct in all cases.
-- rsp
Quoted 60 lines · Keir Fraser
For reference, from AMD's manual, Vol.2:
"The processor reads the current privilege level from the CPL field in the VMCB, not from SS.DPL. However, SS.DPL should match the CPL field."And from Intel's manual, Vol.3B:
"Note that the value of the DPL field for SS is always equal to the logical
processor¹s current privilege level (CPL)."-- Keir
Quoted 28 lines · Keir Fraser
CPL is architecturally SS.DPL in almost all cases. It's certainly not CS.DPL. What do you mean by 'migrate a QEMU guest'?
-- Keir
Quoted 21 lines · Ben Guthro
CPL should be determined by code segment's DPL, not data segment's.
This solves a problem migrating a QEMU guest without PV-on-HVM drivers
Signed-off-by Robert Plillips <[email protected]>Signed-off-by Ben Guthro <[email protected]>diff -r
f76f151a7431xen/arch/x86/hvm/svm/svm.cxen/arch/x86/hvm/svm/svm.c +1
-1@@ -557,7 +557,7 @@ static void svm_set_segment_register(strbreak ;case x86_seg_ss:memcpy (&vmcb->ss, reg,sizeof (*reg)); - vmcb->cpl = vmcb->ss.attr.fields.dpl; + vmcb->cpl = vmcb->cs.attr.fields.dpl;break ;case x86_seg_tr:memcpy (&vmcb->tr, reg,sizeof (*reg));_______________________________________________
Xen-devel mailing list
[email protected]Quoted 8 lines
Quoted 1 line
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Signature · 5 lines
-------------------------------------------------------------------- Robert S. Phillips Virtual Iron Software [email protected] Tower 1, Floor 2 978-849-1220 900 Chelmsford Street Lowell, MA 01851
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
The statement that CPL is directly related to CS.DPL is not true. Conforming code segments break this relationship, for example. This is despite the fact that the AMD manual does baldly state at one point that ³When a new selector is loaded into the CS register, the current-privilege level (CPL) of the processor is set to that of the CS-segment descriptor-privilege level (DPL).² Conforming code segments clearly break this, unless AMD differ from Intel and nobble CS.DPL in this case, but if they do it's not mentioned in the manuals.
It looks to me as though AMD maintains CPL separately from SS.DPL because they explicitly define that SYSRET doesn¹t modify SS.DPL (even though SYSCALL explicitly does clear SS.DPL).
The assumption that CPL=SS.DPL is used elsewhere in the HVM code. I think our best bet is to modify hvm_get_segment_register(ss) to force the returned dpl to vmcb->cpl. Then get/set are symmetric, other ss.dpl checks in hvm code will work, and save/restore also is fixed.
I've cc'ed Tom Woller in case he can clarify further.
-- Keir
Quoted 25 lines · Robert Phillips
AMD's manual, Vol.2:
4.9.2 Privilege-Level Types
Current Privilege-Level. The current privilege-level (CPL) is the privilege level at which the processor is currently executing. The CPL is stored in an internal processor register that is invisible to software. Software changes the CPL by performing a control transfer to a different code segment with a new privilege level.So the processor switches CPL by changing code segments, and the CPL is taken from the code segment's DPL.
And what, one might ask, if the stack segment and code segment have different DPLs? The AMD manual doesn't say. It simply asserts that they will be equal.
In our experience this is not true.
When we perform a live migrate from a HVM VS without PV drivers [what Ben Guthro referred to as a QEMU-only virtual server], we simply pause the guest in whatever state we find it. We found that when the guest happened to be in user-mode code (CPL == 3), the migrate failed because, on the receiving node, the CPL would be restored to 0. The zero came from SS.DPL. However the value in CS.DPL was 3.
SS.DPL was not equal to CS.DPL.
When we changed the code (per this patch), the CPL would be restored from CS.DPL. That value was correct in all cases.