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.

Reply via email to