return rc;
}
+static int cf_check
+hvm_emulate_read_segment(enum x86_segment seg,
+ struct segment_register *reg,
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct sh_emulate_ctxt *sh_ctxt =
+ container_of(ctxt, struct sh_emulate_ctxt, ctxt);
+ const struct segment_register *sreg = hvm_get_seg_reg(seg, sh_ctxt);
+
+ if ( IS_ERR(sreg) )
+ return -PTR_ERR(sreg);
+
+ *reg = *sreg;
+
+ return X86EMUL_OKAY;
+}
+
static const struct x86_emulate_ops hvm_shadow_emulator_ops = {
.read = hvm_emulate_read,
.insn_fetch = hvm_emulate_insn_fetch,
.write = hvm_emulate_write,
.cmpxchg = hvm_emulate_cmpxchg,
+ .read_segment = hvm_emulate_read_segment,
};
const struct x86_emulate_ops *shadow_init_emulation(
if ( state->ea.type == OP_MEM )
{
aux.dp = state->ea.mem.off;
- if ( ops->read_segment &&
- ops->read_segment(state->ea.mem.seg, &sreg,
- ctxt) == X86EMUL_OKAY )
+ if ( state->ea.mem.seg == x86_seg_cs )
+ aux.ds = aux.cs;
+ else if ( ops->read_segment &&
+ ops->read_segment(state->ea.mem.seg, &sreg,
+ ctxt) == X86EMUL_OKAY )
aux.ds = sreg.sel;
+#ifdef __XEN__
+ /*
+ * While generally the expectation is that input structures are
+ * fully populated, the selector fields under ctxt->regs normally
+ * aren't set, with the exception of CS and SS for PV domains.
+ * Read the real selector registers for PV, and assert that HVM
+ * invocations always set a properly functioning ->read_segment()
+ * hook.
+ */
+ else if ( is_pv_vcpu(current) )
+ switch ( state->ea.mem.seg )
+ {
+ case x86_seg_ds: aux.ds = read_sreg(ds); break;
+ case x86_seg_es: aux.ds = read_sreg(es); break;
+ case x86_seg_fs: aux.ds = read_sreg(fs); break;
+ case x86_seg_gs: aux.ds = read_sreg(gs); break;
+ case x86_seg_ss: aux.ds = ctxt->regs->ss; break;
+ default: ASSERT_UNREACHABLE(); break;
+ }
+ else
+ ASSERT_UNREACHABLE();
+#else
else
switch ( state->ea.mem.seg )
{
- case x86_seg_cs: aux.ds = ctxt->regs->cs; break;
case x86_seg_ds: aux.ds = ctxt->regs->ds; break;
case x86_seg_es: aux.ds = ctxt->regs->es; break;
case x86_seg_fs: aux.ds = ctxt->regs->fs; break;
case x86_seg_ss: aux.ds = ctxt->regs->ss; break;
default: ASSERT_UNREACHABLE(); break;
}
+#endif
aux.dval = true;
}
ops->put_fpu(ctxt, X86EMUL_FPU_none, &aux);