From: Jan Kiszka <jan.kis...@siemens.com> Rather than always pulling the four fields of vcpu_execution_state at once, introduce individual accessor functions. This allows to reduce the number of expensive vmcs_read operations on Intel to 2 for typical hypercalls and all MMIO interceptions.
Signed-off-by: Jan Kiszka <jan.kis...@siemens.com> --- hypervisor/arch/x86/apic.c | 5 ++--- hypervisor/arch/x86/include/asm/apic.h | 3 +-- hypervisor/arch/x86/include/asm/mmio.h | 5 ++--- hypervisor/arch/x86/include/asm/vcpu.h | 13 +++++-------- hypervisor/arch/x86/mmio.c | 8 ++++---- hypervisor/arch/x86/svm.c | 22 +++++++++++++--------- hypervisor/arch/x86/vcpu.c | 20 ++++++-------------- hypervisor/arch/x86/vmx.c | 21 +++++++++++++-------- 8 files changed, 46 insertions(+), 51 deletions(-) diff --git a/hypervisor/arch/x86/apic.c b/hypervisor/arch/x86/apic.c index 91a38b23a..3bc31d460 100644 --- a/hypervisor/arch/x86/apic.c +++ b/hypervisor/arch/x86/apic.c @@ -483,8 +483,7 @@ static bool apic_invalid_lvt_delivery_mode(unsigned int reg, u32 val) return true; } -unsigned int apic_mmio_access(unsigned long rip, - const struct guest_paging_structures *pg_structs, +unsigned int apic_mmio_access(const struct guest_paging_structures *pg_structs, unsigned int reg, bool is_write) { struct mmio_instruction inst; @@ -495,7 +494,7 @@ unsigned int apic_mmio_access(unsigned long rip, return 0; } - inst = x86_mmio_parse(rip, pg_structs, is_write); + inst = x86_mmio_parse(pg_structs, is_write); if (inst.inst_len == 0) return 0; if (inst.access_size != 4) { diff --git a/hypervisor/arch/x86/include/asm/apic.h b/hypervisor/arch/x86/include/asm/apic.h index d2cd632a5..41534393e 100644 --- a/hypervisor/arch/x86/include/asm/apic.h +++ b/hypervisor/arch/x86/include/asm/apic.h @@ -162,8 +162,7 @@ void apic_send_irq(struct apic_irq_message irq_msg); void apic_irq_handler(void); -unsigned int apic_mmio_access(unsigned long rip, - const struct guest_paging_structures *pg_structs, +unsigned int apic_mmio_access(const struct guest_paging_structures *pg_structs, unsigned int reg, bool is_write); bool x2apic_handle_write(void); diff --git a/hypervisor/arch/x86/include/asm/mmio.h b/hypervisor/arch/x86/include/asm/mmio.h index 2b66114a9..756c84a88 100644 --- a/hypervisor/arch/x86/include/asm/mmio.h +++ b/hypervisor/arch/x86/include/asm/mmio.h @@ -34,14 +34,13 @@ struct mmio_instruction { /** * Parse instruction causing an intercepted MMIO access on a cell CPU. - * @param pc Program counter of the access instruction. * @param pg_structs Currently active guest (cell) paging structures. * @param is_write True if write access, false for read. * * @return MMIO instruction information. mmio_instruction::inst_len is 0 on * invalid or unsupported access. */ -struct mmio_instruction x86_mmio_parse(unsigned long pc, - const struct guest_paging_structures *pg_structs, bool is_write); +struct mmio_instruction +x86_mmio_parse(const struct guest_paging_structures *pg_structs, bool is_write); /** @} */ diff --git a/hypervisor/arch/x86/include/asm/vcpu.h b/hypervisor/arch/x86/include/asm/vcpu.h index 0782d50d7..429c735e0 100644 --- a/hypervisor/arch/x86/include/asm/vcpu.h +++ b/hypervisor/arch/x86/include/asm/vcpu.h @@ -30,13 +30,6 @@ struct vcpu_io_bitmap { u32 size; }; -struct vcpu_execution_state { - u64 efer; - u64 rflags; - u16 cs; - u64 rip; -}; - struct vcpu_io_intercept { u16 port; unsigned int size; @@ -100,7 +93,11 @@ void vcpu_skip_emulated_instruction(unsigned int inst_len); void vcpu_vendor_get_cell_io_bitmap(struct cell *cell, struct vcpu_io_bitmap *out); -void vcpu_vendor_get_execution_state(struct vcpu_execution_state *x_state); +u64 vcpu_vendor_get_efer(void); +u64 vcpu_vendor_get_rflags(void); +u64 vcpu_vendor_get_rip(void); +u16 vcpu_vendor_get_cs(void); + void vcpu_vendor_get_io_intercept(struct vcpu_io_intercept *io); void vcpu_vendor_get_mmio_intercept(struct vcpu_mmio_intercept *mmio); diff --git a/hypervisor/arch/x86/mmio.c b/hypervisor/arch/x86/mmio.c index d4589d60d..b96fbcf42 100644 --- a/hypervisor/arch/x86/mmio.c +++ b/hypervisor/arch/x86/mmio.c @@ -51,8 +51,7 @@ struct parse_context { const u8 *inst; }; -static bool ctx_update(struct parse_context *ctx, - unsigned long *pc, unsigned int advance, +static bool ctx_update(struct parse_context *ctx, u64 *pc, unsigned int advance, const struct guest_paging_structures *pg) { ctx->inst += advance; @@ -70,13 +69,14 @@ static bool ctx_update(struct parse_context *ctx, return true; } -struct mmio_instruction x86_mmio_parse(unsigned long pc, - const struct guest_paging_structures *pg_structs, bool is_write) +struct mmio_instruction +x86_mmio_parse(const struct guest_paging_structures *pg_structs, bool is_write) { struct parse_context ctx = { .remaining = X86_MAX_INST_LEN, .count = 1 }; union registers *guest_regs = &this_cpu_data()->guest_regs; struct mmio_instruction inst = { .inst_len = 0 }; + u64 pc = vcpu_vendor_get_rip(); unsigned int n, skip_len = 0; bool has_immediate = false; union opcode op[4] = { }; diff --git a/hypervisor/arch/x86/svm.c b/hypervisor/arch/x86/svm.c index ae6860408..f78251eeb 100644 --- a/hypervisor/arch/x86/svm.c +++ b/hypervisor/arch/x86/svm.c @@ -827,8 +827,7 @@ static bool svm_handle_apic_access(struct vmcb *vmcb) vcpu_get_guest_paging_structs(&pg_structs); - inst_len = apic_mmio_access(vmcb->rip, &pg_structs, offset >> 4, - is_write); + inst_len = apic_mmio_access(&pg_structs, offset >> 4, is_write); if (!inst_len) goto out_err; @@ -1034,14 +1033,19 @@ void vcpu_vendor_get_cell_io_bitmap(struct cell *cell, iobm->size = IOPM_PAGES * PAGE_SIZE; } -void vcpu_vendor_get_execution_state(struct vcpu_execution_state *x_state) -{ - struct vmcb *vmcb = &this_cpu_data()->vmcb; +#define VCPU_VENDOR_GET_REGISTER(__reg__) \ +u64 vcpu_vendor_get_##__reg__(void) \ +{ \ + return this_cpu_data()->vmcb.__reg__; \ +} - x_state->efer = vmcb->efer; - x_state->rflags = vmcb->rflags; - x_state->cs = vmcb->cs.selector; - x_state->rip = vmcb->rip; +VCPU_VENDOR_GET_REGISTER(efer); +VCPU_VENDOR_GET_REGISTER(rflags); +VCPU_VENDOR_GET_REGISTER(rip); + +u16 vcpu_vendor_get_cs(void) +{ + return this_cpu_data()->vmcb.cs.selector; } /* GIF must be set for interrupts to be delivered (APMv2, Sect. 15.17) */ diff --git a/hypervisor/arch/x86/vcpu.c b/hypervisor/arch/x86/vcpu.c index 21da05925..48079b9b1 100644 --- a/hypervisor/arch/x86/vcpu.c +++ b/hypervisor/arch/x86/vcpu.c @@ -156,20 +156,14 @@ void vcpu_cell_exit(struct cell *cell) void vcpu_handle_hypercall(void) { union registers *guest_regs = &this_cpu_data()->guest_regs; + bool long_mode = !!(vcpu_vendor_get_efer() & EFER_LMA); + unsigned long arg_mask = long_mode ? (u64)-1 : (u32)-1; unsigned long code = guest_regs->rax; - struct vcpu_execution_state x_state; - unsigned long arg_mask; - bool long_mode; vcpu_skip_emulated_instruction(X86_INST_LEN_HYPERCALL); - vcpu_vendor_get_execution_state(&x_state); - - long_mode = !!(x_state.efer & EFER_LMA); - arg_mask = long_mode ? (u64)-1 : (u32)-1; - - if ((!long_mode && (x_state.rflags & X86_RFLAGS_VM)) || - (x_state.cs & 3) != 0) { + if ((!long_mode && (vcpu_vendor_get_rflags() & X86_RFLAGS_VM)) || + (vcpu_vendor_get_cs() & 3) != 0) { guest_regs->rax = -EPERM; return; } @@ -179,7 +173,7 @@ void vcpu_handle_hypercall(void) if (guest_regs->rax == -ENOSYS) printk("CPU %d: Unknown hypercall %ld, RIP: 0x%016llx\n", this_cpu_id(), code, - x_state.rip - X86_INST_LEN_HYPERCALL); + vcpu_vendor_get_rip() - X86_INST_LEN_HYPERCALL); if (code == JAILHOUSE_HC_DISABLE && guest_regs->rax == 0) vcpu_deactivate_vmm(); @@ -221,15 +215,13 @@ bool vcpu_handle_mmio_access(void) struct guest_paging_structures pg_structs; struct mmio_access mmio = {.size = 0}; struct vcpu_mmio_intercept intercept; - struct vcpu_execution_state x_state; struct mmio_instruction inst; - vcpu_vendor_get_execution_state(&x_state); vcpu_vendor_get_mmio_intercept(&intercept); vcpu_get_guest_paging_structs(&pg_structs); - inst = x86_mmio_parse(x_state.rip, &pg_structs, intercept.is_write); + inst = x86_mmio_parse(&pg_structs, intercept.is_write); if (!inst.inst_len) goto invalid_access; diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c index b69751b8a..bb7f1c7a0 100644 --- a/hypervisor/arch/x86/vmx.c +++ b/hypervisor/arch/x86/vmx.c @@ -1067,9 +1067,7 @@ static bool vmx_handle_apic_access(void) vcpu_get_guest_paging_structs(&pg_structs); - inst_len = apic_mmio_access(vmcs_read64(GUEST_RIP), - &pg_structs, offset >> 4, - is_write); + inst_len = apic_mmio_access(&pg_structs, offset >> 4, is_write); if (!inst_len) break; @@ -1242,12 +1240,19 @@ void vcpu_vendor_get_cell_io_bitmap(struct cell *cell, iobm->size = PIO_BITMAP_PAGES * PAGE_SIZE; } -void vcpu_vendor_get_execution_state(struct vcpu_execution_state *x_state) +#define VCPU_VENDOR_GET_REGISTER(__reg__, __field__) \ +u64 vcpu_vendor_get_##__reg__(void) \ +{ \ + return vmcs_read64(__field__); \ +} + +VCPU_VENDOR_GET_REGISTER(efer, GUEST_IA32_EFER); +VCPU_VENDOR_GET_REGISTER(rflags, GUEST_RFLAGS); +VCPU_VENDOR_GET_REGISTER(rip, GUEST_RIP); + +u16 vcpu_vendor_get_cs(void) { - x_state->efer = vmcs_read64(GUEST_IA32_EFER); - x_state->rflags = vmcs_read64(GUEST_RFLAGS); - x_state->cs = vmcs_read16(GUEST_CS_SELECTOR); - x_state->rip = vmcs_read64(GUEST_RIP); + return vmcs_read16(GUEST_CS_SELECTOR); } void enable_irq(void) -- 2.13.6 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to jailhouse-dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.