I noticed anamoly in my code the way IOPL is set. For vcpu 0, its done via set_iopl.iopl = 1; rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); in xen_start_kernel() in enlighten.c. But, for non boot vcpus, its done via eflags in cpu_initialize_context(): ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ Since I am running in HVM container, IO ops cause vmexit. I can just check eflags at that point for guest IOPL. So I am thinking of just using eflags and not doing the hcall. It will also reduce the need for another field in the struct pv_vcpu for me. (JFYI: EXIT_REASON_IO_INSTRUCTION cause emulate_privileged_op() to be called). What do you guys think? thanks, mukesh
On Wed, 19 Sep 2012 12:29:07 -0700 Mukesh Rathor <mukesh.rathor@oracle.com> wrote:> > I noticed anamoly in my code the way IOPL is set. For vcpu 0, its done > via > > set_iopl.iopl = 1; > rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); > > in xen_start_kernel() in enlighten.c. But, for non boot vcpus, its > done via eflags in cpu_initialize_context(): > ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ > > Since I am running in HVM container, IO ops cause vmexit. I can just > check eflags at that point for guest IOPL. So I am thinking of just > using eflags and not doing the hcall. It will also reduce the need > for another field in the struct pv_vcpu for me. > > (JFYI: EXIT_REASON_IO_INSTRUCTION cause emulate_privileged_op() to be > called).So, I got rid of calling hcall to set iopl. The guest just manages via eflags. Then upon vmexit: { int curr_lvl; int requested = (regs->rflags >> 12) & 3; read_vmcs_selectors(regs); curr_lvl = regs->cs & 3; if (requested >= curr_lvl && emulate_privileged_op(regs)) return success; hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code); } I tested it out, and seems fine. thanks, Mukesh
>>> On 20.09.12 at 00:13, Mukesh Rathor <mukesh.rathor@oracle.com> wrote: > On Wed, 19 Sep 2012 12:29:07 -0700 > Mukesh Rathor <mukesh.rathor@oracle.com> wrote: > >> >> I noticed anamoly in my code the way IOPL is set. For vcpu 0, its done >> via >> >> set_iopl.iopl = 1; >> rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); >> >> in xen_start_kernel() in enlighten.c. But, for non boot vcpus, its >> done via eflags in cpu_initialize_context(): >> ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ >> >> Since I am running in HVM container, IO ops cause vmexit. I can just >> check eflags at that point for guest IOPL. So I am thinking of just >> using eflags and not doing the hcall. It will also reduce the need >> for another field in the struct pv_vcpu for me. >> >> (JFYI: EXIT_REASON_IO_INSTRUCTION cause emulate_privileged_op() to be >> called). > > So, I got rid of calling hcall to set iopl. The guest just manages > via eflags. Then upon vmexit: > > { > int curr_lvl; > int requested = (regs->rflags >> 12) & 3; > read_vmcs_selectors(regs); > curr_lvl = regs->cs & 3; > > if (requested >= curr_lvl && emulate_privileged_op(regs)) > return success; > > hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code); > } > > I tested it out, and seems fine.And that''s also how I would expect it to be. Even more - just like the ring not needing to be 1, you shouldn''t need to fiddle artificially with IOPL. Just leave it at zero for the kernel, and adjust between 0 and 3 for user mode based on the respective syscalls). Jan