Message ID | 20101104223614.16669.69856.stgit@ginnungagap.bsc.es |
---|---|
State | New |
Headers | show |
On Thu, Nov 04, 2010 at 11:36:15PM +0100, Lluís wrote: > Take the unused CPUID 0x40001xxx range as the backdoor instruction. > In KVM (and it fits the spec nicely) cpuid is defined in terms of tables. There is no callback that is called when particular cpuid is queried, so such backdoor interface will be impossible to implement in KVM. Furthermore any interface that changes/looks at vcpu state in userspace is broken for KVM. Look at vmware backdoor interface for instance. KVM has a hack in emulator code to make it work. > Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> > --- > backdoor/guest.h | 21 +++++++++++++++++++++ > target-i386/cpuid.c | 27 +++++++++++++++++++++++++++ > target-i386/helper.h | 4 ++++ > target-i386/translate.c | 4 ++++ > 4 files changed, 56 insertions(+), 0 deletions(-) > > diff --git a/backdoor/guest.h b/backdoor/guest.h > index 8373762..3edcbc6 100644 > --- a/backdoor/guest.h > +++ b/backdoor/guest.h > @@ -26,8 +26,29 @@ > * - v32: value of 32 bits > */ > > +#include <stdint.h> > + > +#if __i386__ || __i486__ || __x86_64__ > + > +#define _BACKDOOR(t, i8, v32) \ > + ({ \ > + uint32_t eax, ebx, ecx, edx; \ > + uint32_t index = (uint32_t)0x40001000 + (t<<8) + (uint8_t)i8; \ > + uint32_t count = (uint32_t)v32; \ > + asm volatile ("cpuid" \ > + : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) \ > + : "0"(index), "2"(count) \ > + ); \ > + eax; \ > + }) > + > +#define BACKDOOR_i8(i) _BACKDOOR(0, i, 0) > +#define BACKDOOR_i8_v32(i, v) _BACKDOOR(1, i, v) > + > +#else > > #error Undefined instruction-based backdoor interface for guest architecture > > +#endif > > #endif /* BACKDOOR__GUEST_H */ > diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c > index 650a719..03fc973 100644 > --- a/target-i386/cpuid.c > +++ b/target-i386/cpuid.c > @@ -27,6 +27,9 @@ > #include "qemu-option.h" > #include "qemu-config.h" > > +#include "helper.h" > + > + > /* feature flags taken from "Intel Processor Identification and the CPUID > * Instruction" and AMD's "CPUID Specification". In cases of disagreement > * between feature naming conventions, aliases may be added. > @@ -1033,6 +1036,30 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, > uint32_t *eax, uint32_t *ebx, > uint32_t *ecx, uint32_t *edx) > { > +#if defined(CONFIG_BACKDOOR) /* synched with "backdoor/guest.h" */ > + if ((index & ~0xfff) == 0x40001000) { > + int type = (index >> 8) & 0xf; > + uint8_t i8 = index & 0x0ff; > + uint32_t v32 = count; > + switch (type) { > + case 0: > + helper_backdoor_i8(i8); > + break; > + case 1: > + helper_backdoor_i8_v32(i8, v32); > + break; > + default: > + printf("invalid backdoor request\n"); > + abort(); > + } > + *eax = 0; > + *ebx = 0; > + *ecx = 0; > + *edx = 0; > + return; > + } > +#endif > + > /* test if maximum index reached */ > if (index & 0x80000000) { > if (index > env->cpuid_xlevel) > diff --git a/target-i386/helper.h b/target-i386/helper.h > index 6b518ad..979d94e 100644 > --- a/target-i386/helper.h > +++ b/target-i386/helper.h > @@ -217,4 +217,8 @@ DEF_HELPER_2(rclq, tl, tl, tl) > DEF_HELPER_2(rcrq, tl, tl, tl) > #endif > > +#if defined(CONFIG_BACKDOOR) > +#include "backdoor/helper.h" > +#endif > + > #include "def-helper.h" > diff --git a/target-i386/translate.c b/target-i386/translate.c > index 7b6e3c2..dfdc2f0 100644 > --- a/target-i386/translate.c > +++ b/target-i386/translate.c > @@ -6941,6 +6941,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) > gen_op_set_cc_op(s->cc_op); > gen_jmp_im(pc_start - s->cs_base); > gen_helper_cpuid(); > +#if defined(CONFIG_BACKDOOR) > + gen_jmp_im(s->pc); > + gen_eob(s); > +#endif > break; > case 0xf4: /* hlt */ > if (s->cpl != 0) { > -- Gleb.
Gleb Natapov writes: > On Thu, Nov 04, 2010 at 11:36:15PM +0100, Lluís wrote: >> Take the unused CPUID 0x40001xxx range as the backdoor instruction. >> > In KVM (and it fits the spec nicely) cpuid is defined in terms of > tables. There is no callback that is called when particular cpuid is > queried, so such backdoor interface will be impossible to implement > in KVM. Furthermore any interface that changes/looks at vcpu state in > userspace is broken for KVM. Look at vmware backdoor interface for > instance. KVM has a hack in emulator code to make it work. I know. I looked into the KVM implementation and neither CPUID nor VMCALL/VMMCALL (these two are, in fact, obsoleted) are implemented as calls to the hypervisor (although the hardware supports it). The only interfaces exported by KVM to that purpose are through MMIO/PIO, but these are OS-dependant (aka, KVM-dependant). As such, there is currently no generic, OS-independant and low-overhead method for providing a backdoor communication channel from the guest directly into QEMU. As I see this is very tied to my setup, I'll move this patch series down below the tracing series so that it does not interfere with the other patches. Lluis
diff --git a/backdoor/guest.h b/backdoor/guest.h index 8373762..3edcbc6 100644 --- a/backdoor/guest.h +++ b/backdoor/guest.h @@ -26,8 +26,29 @@ * - v32: value of 32 bits */ +#include <stdint.h> + +#if __i386__ || __i486__ || __x86_64__ + +#define _BACKDOOR(t, i8, v32) \ + ({ \ + uint32_t eax, ebx, ecx, edx; \ + uint32_t index = (uint32_t)0x40001000 + (t<<8) + (uint8_t)i8; \ + uint32_t count = (uint32_t)v32; \ + asm volatile ("cpuid" \ + : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) \ + : "0"(index), "2"(count) \ + ); \ + eax; \ + }) + +#define BACKDOOR_i8(i) _BACKDOOR(0, i, 0) +#define BACKDOOR_i8_v32(i, v) _BACKDOOR(1, i, v) + +#else #error Undefined instruction-based backdoor interface for guest architecture +#endif #endif /* BACKDOOR__GUEST_H */ diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 650a719..03fc973 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -27,6 +27,9 @@ #include "qemu-option.h" #include "qemu-config.h" +#include "helper.h" + + /* feature flags taken from "Intel Processor Identification and the CPUID * Instruction" and AMD's "CPUID Specification". In cases of disagreement * between feature naming conventions, aliases may be added. @@ -1033,6 +1036,30 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { +#if defined(CONFIG_BACKDOOR) /* synched with "backdoor/guest.h" */ + if ((index & ~0xfff) == 0x40001000) { + int type = (index >> 8) & 0xf; + uint8_t i8 = index & 0x0ff; + uint32_t v32 = count; + switch (type) { + case 0: + helper_backdoor_i8(i8); + break; + case 1: + helper_backdoor_i8_v32(i8, v32); + break; + default: + printf("invalid backdoor request\n"); + abort(); + } + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + return; + } +#endif + /* test if maximum index reached */ if (index & 0x80000000) { if (index > env->cpuid_xlevel) diff --git a/target-i386/helper.h b/target-i386/helper.h index 6b518ad..979d94e 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -217,4 +217,8 @@ DEF_HELPER_2(rclq, tl, tl, tl) DEF_HELPER_2(rcrq, tl, tl, tl) #endif +#if defined(CONFIG_BACKDOOR) +#include "backdoor/helper.h" +#endif + #include "def-helper.h" diff --git a/target-i386/translate.c b/target-i386/translate.c index 7b6e3c2..dfdc2f0 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6941,6 +6941,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); gen_helper_cpuid(); +#if defined(CONFIG_BACKDOOR) + gen_jmp_im(s->pc); + gen_eob(s); +#endif break; case 0xf4: /* hlt */ if (s->cpl != 0) {
Take the unused CPUID 0x40001xxx range as the backdoor instruction. Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- backdoor/guest.h | 21 +++++++++++++++++++++ target-i386/cpuid.c | 27 +++++++++++++++++++++++++++ target-i386/helper.h | 4 ++++ target-i386/translate.c | 4 ++++ 4 files changed, 56 insertions(+), 0 deletions(-)