Page MenuHomeFreeBSD

D51256.id158684.diff
No OneTemporary

D51256.id158684.diff

diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -504,6 +504,7 @@
#define SEG_DESC_DEF32(access) (((access) & 0x4000) ? 1 : 0)
#define SEG_DESC_GRANULARITY(access) (((access) & 0x8000) ? 1 : 0)
#define SEG_DESC_UNUSABLE(access) (((access) & 0x10000) ? 1 : 0)
+#define SEG_DESC_CS_D(access) (((access) & 0x20000) ? 1 : 0)
enum vm_cpu_mode {
CPU_MODE_REAL,
diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c
--- a/sys/amd64/vmm/amd/svm.c
+++ b/sys/amd64/vmm/amd/svm.c
@@ -735,10 +735,21 @@
if (in) {
vis->seg_name = VM_REG_GUEST_ES;
- } else {
- /* The segment field has standard encoding */
+ } else if (decode_assist()) {
+ /*
+ * The effective segment number in EXITINFO1[12:10] is populated
+ * only if the processor has the DecodeAssist capability.
+ *
+ * XXX this is not specified explicitly in APMv2 but can be
+ * verified empirically.
+ */
s = (info1 >> 10) & 0x7;
+
+ /* The segment field has standard encoding */
vis->seg_name = vm_segment_name(s);
+ } else {
+ vis->seg_name = VM_REG_LAST;
+ return;
}
error = svm_getdesc(vcpu, vis->seg_name, &vis->seg_desc);
@@ -798,16 +809,6 @@
info1 = ctrl->exitinfo1;
inout_string = info1 & BIT(2) ? 1 : 0;
- /*
- * The effective segment number in EXITINFO1[12:10] is populated
- * only if the processor has the DecodeAssist capability.
- *
- * XXX this is not specified explicitly in APMv2 but can be verified
- * empirically.
- */
- if (inout_string && !decode_assist())
- return (UNHANDLED);
-
vmexit->exitcode = VM_EXITCODE_INOUT;
vmexit->u.inout.in = (info1 & BIT(0)) ? 1 : 0;
vmexit->u.inout.string = inout_string;
diff --git a/sys/amd64/vmm/amd/vmcb.c b/sys/amd64/vmm/amd/vmcb.c
--- a/sys/amd64/vmm/amd/vmcb.c
+++ b/sys/amd64/vmm/amd/vmcb.c
@@ -446,6 +446,9 @@
/* Map seg_desc access to VMCB attribute format */
desc->access = ((seg->attrib & 0xF00) << 4) |
(seg->attrib & 0xFF);
+ if (reg == VM_REG_GUEST_CS)
+ desc->access |= (!!(seg->attrib & VMCB_CS_ATTRIB_D))
+ << 17;
/*
* VT-x uses bit 16 to indicate a segment that has been loaded
diff --git a/sys/amd64/vmm/vmm_ioport.c b/sys/amd64/vmm/vmm_ioport.c
--- a/sys/amd64/vmm/vmm_ioport.c
+++ b/sys/amd64/vmm/vmm_ioport.c
@@ -144,10 +144,61 @@
return (0);
}
+static int
+decode_segment(struct vcpu *vcpu, enum vm_reg_name *segment)
+{
+ struct vm_guest_paging *paging;
+ struct vie vie;
+ struct vm_exit *vme;
+ struct seg_desc cs_desc;
+ uint64_t cs_base;
+ uint32_t cs_d;
+ int err;
+ int fault;
+
+ vme = vm_exitinfo(vcpu);
+ paging = &vme->u.inout_str.paging;
+ err = vm_get_seg_desc(vcpu, VM_REG_GUEST_CS, &cs_desc);
+ if (err)
+ return (err);
+ cs_base = cs_desc.base;
+
+ err = vmm_fetch_instruction(vcpu, paging, vme->rip + cs_base,
+ VIE_INST_SIZE, &vie, &fault);
+ if (err || fault)
+ return (err);
+ cs_d = (paging->cpu_mode == CPU_MODE_PROTECTED ||
+ paging->cpu_mode == CPU_MODE_COMPATIBILITY) ?
+ SEG_DESC_CS_D(cs_desc.access) :
+ 0;
+ /*
+ * Convert the segment override prefix to a 16-bit register number.
+ */
+ err = vmm_decode_instruction(vcpu, VIE_INVALID_GLA, paging->cpu_mode,
+ cs_d, &vie);
+ if (err)
+ return (err);
+ if (vie.segment_override)
+ *segment = vie.segment_register;
+ else
+ *segment = VM_REG_GUEST_DS;
+
+ return (0);
+}
+
static int
emulate_inout_str(struct vcpu *vcpu, struct vm_exit *vmexit, bool *retu)
{
+ int err;
+
*retu = true;
+ if (vmexit->u.inout_str.seg_name == VM_REG_LAST) {
+ err = decode_segment(vcpu, &vmexit->u.inout_str.seg_name);
+ if (err)
+ return (err);
+ return (vm_get_seg_desc(vcpu, vmexit->u.inout_str.seg_name,
+ &vmexit->u.inout_str.seg_desc));
+ }
return (0); /* Return to userspace to finish emulation */
}

File Metadata

Mime Type
text/plain
Expires
Thu, Aug 6, 7:52 AM (10 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36098915
Default Alt Text
D51256.id158684.diff (3 KB)

Event Timeline