Re: [PATCH 2/4] kvm-unit-tests: VMX: Add test cases for CR0/4 shadowing

2013-08-18 Thread Gmail


在 2013-8-18,22:07,Paolo Bonzini  写道:

> Il 15/08/2013 09:59, Arthur Chunqi Li ha scritto:
 volatile u32 stage? And we have barrier() to avoid reordering.
>> Reordering here is not a big deal here, though it is actually needed
>> here. I occurred the following problem:
>> 
>> stage = 1;
>> do something that causes vmexit;
>> stage = 2;
>> 
>> Then the compiler will optimize "stage = 1" and "stage = 2" to one
>> instruction "stage =2", since instructions between them don't use
>> "stage". Can volatile solve this problem?
> 
> I'm not sure if volatile stores are reordered against non-volatile stores.
> 
> Better keep set_stage() but write it as
> 
>barrier();
>stage = s;
>barrier();
Yep. I have done it like this in the 2nd version.

Arthur
> 
> Paolo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] KVM: nVMX: Advertise IA32_PAT in VM exit control

2013-08-05 Thread Gmail


> On Mon, Aug 05, 2013 at 05:10:35PM +0800, Arthur Chunqi Li wrote:
>> Advertise VM_EXIT_SAVE_IA32_PAT and VM_EXIT_LOAD_IA32_PAT.
>> 
>> Signed-off-by: Arthur Chunqi Li 
>> ---
>> arch/x86/kvm/vmx.c |3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>> 
>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>> index 45fd70c..240f0db 100644
>> --- a/arch/x86/kvm/vmx.c
>> +++ b/arch/x86/kvm/vmx.c
>> @@ -2198,7 +2198,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
>> #else
>>nested_vmx_exit_ctls_high = 0;
>> #endif
>> -nested_vmx_exit_ctls_high |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
>> +nested_vmx_exit_ctls_high |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
>> +VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT;
>> 
> You should not set those if host does not support them, otherwise
> GUEST_IA32_PAT may not be available
To Jan,
Is this different from IA32_EFER?

Arthur
> 
> --
>Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] kvm-unit-tests: VMX: Fix confused definition of rflags

2013-08-05 Thread Gmail

在 2013-8-5,17:10,Gleb Natapov  写道:

> On Mon, Aug 05, 2013 at 04:48:47PM +0800, Arthur Chunqi Li wrote:
>> On Mon, Aug 5, 2013 at 4:29 PM, Gleb Natapov  wrote:
>>> On Tue, Jul 30, 2013 at 11:41:00PM +0800, Arthur Chunqi Li wrote:
 Change "rflags" in "struct regs" to "host_rflags". Remove settings
 to GUEST_RFLAGS since GUEST_RFLAGS can be set by vmwrite. Treat
 host_rflags as host rflags before and after vmenter.
>>> I am not sure the change is for the better. Before the change one could
>>> set up rflags for guest environment by setting regs.rflags, no special
>>> init function had to be written. I do not see any problem with correct
>>> code, except that rflags is not correct on a guest entry, but this
>>> should be easy to fix.
>> regs.rflags are designed to set guest rflags, but the current
>> implementation just use it as host_rflags.
> Current implementation uses it to set guest flags at the beginning of
> a test.
> 
>>   For every VM entry, it will
>> load value set by vmcs_write(GUEST_RFLAGS).
> Not for every vmentry, only for the first one. Doing it for every
> vmentry without saving it first with vmcs_read would been incorrect.
> 
>> Set regs.flags as host
>> rflags and then enter VM cannot affect VM's rflags, which is the
>> current implementation.
> It can, on the first launch. It is easy to add code to exit_handler() to
> set current->guest_regs.rflags correctly before calling test's exit handler
> and write GUEST_RFLAGS according to current->guest_regs.rflags after
> exit handler returns, but as you say below test can do it by itself in
> exit handler if it wishes so.
> 
>> Besides, if host want to set/get guest's rflags, it just use
>> vmcs_write/read(GUEST_RFLAGS).
> True, but to do it at the beginning of the test it will require to write
> special init function even if non are needed otherwise. So you are
> removing this functionality without clear benefit.
True, so it seems better to keep it. However, now it is confused with 
host_rflags and not correctly set/get when vmentry/vmexit. I will commit 
another patch to fix both bugs.

Arthur
> 
>> Arthur
>>> 
 Besides, add checks to flags after vmenter.
 
 Signed-off-by: Arthur Chunqi Li 
 ---
 x86/vmx.c |   11 ++-
 x86/vmx.h |2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)
 
 diff --git a/x86/vmx.c b/x86/vmx.c
 index 7467927..082c3bb 100644
 --- a/x86/vmx.c
 +++ b/x86/vmx.c
 @@ -481,6 +481,8 @@ static int vmx_run()
  "vmresume\n\t"
  "2: "
  "setbe %0\n\t"
 + "jbe vmx_return\n\t"
 + "ud2\n\t"
  "vmx_return:\n\t"
  SAVE_GPR_C
  SAVE_RFLAGS
 @@ -505,15 +507,15 @@ static int vmx_run()
  return 0;
  case VMX_TEST_LAUNCH_ERR:
  printf("%s : vmlaunch failed.\n", __func__);
 - if ((!(regs.rflags & X86_EFLAGS_CF) && !(regs.rflags & 
 X86_EFLAGS_ZF))
 - || ((regs.rflags & X86_EFLAGS_CF) && (regs.rflags & 
 X86_EFLAGS_ZF)))
 + if ((!(regs.host_rflags & X86_EFLAGS_CF) && 
 !(regs.host_rflags & X86_EFLAGS_ZF))
 + || ((regs.host_rflags & X86_EFLAGS_CF) && 
 (regs.host_rflags & X86_EFLAGS_ZF)))
  printf("\tvmlaunch set wrong flags\n");
  report("test vmlaunch", 0);
  break;
  case VMX_TEST_RESUME_ERR:
  printf("%s : vmresume failed.\n", __func__);
 - if ((!(regs.rflags & X86_EFLAGS_CF) && !(regs.rflags & 
 X86_EFLAGS_ZF))
 - || ((regs.rflags & X86_EFLAGS_CF) && (regs.rflags & 
 X86_EFLAGS_ZF)))
 + if ((!(regs.host_rflags & X86_EFLAGS_CF) && 
 !(regs.host_rflags & X86_EFLAGS_ZF))
 + || ((regs.host_rflags & X86_EFLAGS_CF) && 
 (regs.host_rflags & X86_EFLAGS_ZF)))
  printf("\tvmresume set wrong flags\n");
  report("test vmresume", 0);
  break;
 @@ -540,7 +542,6 @@ static int test_run(struct vmx_test *test)
  test->exits = 0;
  current = test;
  regs = test->guest_regs;
 - vmcs_write(GUEST_RFLAGS, regs.rflags | 0x2);
  launched = 0;
  printf("\nTest suite : %s\n", test->name);
  vmx_run();
 diff --git a/x86/vmx.h b/x86/vmx.h
 index 1fb9738..d80e000 100644
 --- a/x86/vmx.h
 +++ b/x86/vmx.h
 @@ -27,7 +27,7 @@ struct regs {
  u64 r13;
  u64 r14;
  u64 r15;
 - u64 rflags;
 + u64 host_rflags;
 };
 
 struct vmx_test {
 --
 1.7.9.5
>>> 
>>> --
>>>Gleb.
> 
> --
>Gleb.
--
To un

Re: [PATCH v2] kvm-unit-tests: VMX: Split VMX test suites to separate file

2013-08-04 Thread Gmail
在 2013-8-5,2:08,Jan Kiszka  写道:

> On 2013-08-04 20:04, Arthur Chunqi Li wrote:
>> @@ -432,6 +432,22 @@ enum Ctrl1 {
>> #define HYPERCALL_MASK0xFFF
>> #define HYPERCALL_VMEXIT0x1
>> 
>> +
>> +extern u64 hypercall_field;
>> +extern u32 vpid_cnt;
>> +extern ulong fix_cr0_set, fix_cr0_clr;
>> +extern ulong fix_cr4_set, fix_cr4_clr;
>> +extern struct regs regs;
>> +extern struct vmx_test *current;
>> +extern bool launched;
> 
> You didn't address my question if we need them all to write test cases
> or if some are actually core internal.
You are right. Not all global variants in last version is necessary for test 
cases, so I move some of them to vmx.c internal. The rest ones in this version 
are needed by tests to identify some states.

Arthur.
> 
> The rest looks good.
> 
> Jan
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] kvm-unit-tests : Basic architecture of VMX nested test case

2013-07-25 Thread Gmail

> On 2013-07-25 18:51, Bandan Das wrote:
>> Arthur Chunqi Li  writes:
>> 
>>> This is the first version of VMX nested environment. It contains the
>>> basic VMX instructions test cases, including VMXON/VMXOFF/VMXPTRLD/
>>> VMXPTRST/VMCLEAR/VMLAUNCH/VMRESUME/VMCALL. This patchalso tests the
>>> basic execution routine in VMX nested environment andlet the VM print
>>> "Hello World" to inform its successfully run.
>>> 
>>> The first release also includes a test suite for vmenter (vmlaunch and
>>> vmresume). Besides, hypercall mechanism is included and currently it is
>>> used to invoke VM normal exit.
>> 
>> What's the difference between this and the one you posted earlier :
>> [PATCH] kvm-unit-tests : Basic architecture of VMX nested test case
>> <1374730297-27169-1-git-send-email-yzt...@gmail.com>
>> 
>> Can you please mention what's changed in v2 ?
> 
> True. A changelog can go...
Compared to v1, v2 removes two unused inline functions vmlaunch/vmresume in 
x86/vmx.h, and add host rflags in "struct regs" so that user can get host's 
rflags in exit_handler.
> 
>> 
>> Bandan
>> 
>>> New files added:
>>> x86/vmx.h : contains all VMX related macro declerations
>>> x86/vmx.c : main file for VMX nested test case
>>> 
>>> Signed-off-by: Arthur Chunqi Li 
>>> ---
> 
> ...here, ie. after the --- so that it wont be part of the commit.
> 
> Jan
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] KVM : Fix read/write to IA32_FEATURE_CONTROL MSR in nested virt

2013-07-04 Thread Gmail
在 2013-7-4,15:24,Gleb Natapov  写道:

> On Thu, Jul 04, 2013 at 03:21:15PM +0800, Arthur Chunqi Li wrote:
>> On Thu, Jul 4, 2013 at 3:10 PM, Gleb Natapov  wrote:
>>> On Thu, Jul 04, 2013 at 09:00:09AM +0200, Paolo Bonzini wrote:
 Il 03/07/2013 15:41, Arthur Chunqi Li ha scritto:
> Fix read/write to IA32_FEATURE_CONTROL MSR in nested environment.
> Simply return 0x5 when read and generate #GP(0) when write.
> Delete handling codes in vmx_set_vmx_msr() and generate #GP(0) in
> handle_wrmsr().
> 
> Signed-off-by: Arthur Chunqi Li 
> ---
> arch/x86/kvm/vmx.c |5 +
> 1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 260a919..e125f94 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -2277,7 +2277,7 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, 
> u32 msr_index, u64 *pdata)
> 
>switch (msr_index) {
>case MSR_IA32_FEATURE_CONTROL:
> -   *pdata = 0;
> +   *pdata = 0x5;
>break;
 
 This is not in the MSR_IA32_VMX_BASIC..MSR_IA32_VMX_TRUE_ENTRY_CTLS
 range, so you must check nested_vmx_allowed and return 0 if it is false.
 
>>> Or 1?
>> I think 1 is better here because this may return LOCK message when
>> query and tell OS not to write (if OS does such logical check)
>>> 
 Otherwise looks good.
 
 Paolo
 
>case MSR_IA32_VMX_BASIC:
>/*
> @@ -2356,9 +2356,6 @@ static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, 
> u32 msr_index, u64 data)
>>> Also this function is no longer needed. You can drop it.
>>> 
>>> And what about Nadav's patch Bandan pointed too? It is not entirely
>>> correct, but it is close to real HW.
>> I think Nadav's patch is much closer to the HW scenario. However, I
>> think we don't need make things complex since KVM doen't support SMX
>> now and this MSR is always set to 0x5.
>> 
> Set to 0x5 by BIOS on real HW. This way BIOS can control if VMX is
> exposed to an OS.
I know. So if we don't use solutions like Nadav's patch, some third-party 
BIOSes emulator (if they are) may get error since we simply generate #GP(0) 
when write to this MSR. We can correct SIPI reset in Nadav's patch and add 
initial codes to seabios, then the entire logical can fit real HW.

Arthur
> 
>> Arthur
>>> 
>if (!nested_vmx_allowed(vcpu))
>return 0;
> 
> -   if (msr_index == MSR_IA32_FEATURE_CONTROL)
> -   /* TODO: the right thing. */
> -   return 1;
>/*
> * No need to treat VMX capability MSRs specially: If we don't handle
> * them, handle_wrmsr will #GP(0), which is correct (they are readonly)
> 
>>> 
>>> --
>>>Gleb.
> 
> --
>Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: IA32_FEATURE_CONTROL MSR in nested virt

2013-07-03 Thread Gmail
OK, I will write a patch as what Paolo says. Anything else need to be taken 
into consideration, Paolo?

Arthur Chunqi Li
Department of Computer Science
School of EECS
Peking University
Beijing, China

>From my iPhone

在 2013-7-3,17:14,Gleb Natapov  写道:

> On Wed, Jul 03, 2013 at 04:24:33PM +0800, Arthur Chunqi Li wrote:
>> Hi Gleb and Paolo,
>> When I write test cases for nested virt and found that reading/writing
>> IA32_FEATURE_CONTROL will be simply ignored or return 0 (in
>> arch/x86/kvm/vmx.c) in VM. Checking this MSR will be done by some
>> hypervisors (e.g. NOVA) and may cause error then, so it is necessary
>> to behave right when read/write it in VM.
> NOVA cannot write to it and expect anything but #GP since BIOSes usually
> lock the MSR. So I agree with Paolo about returning 5 on read and #GP on
> write. Later we can implement locking functionality and make BIOS
> enable/disable nested vmx.
> 
>> Are there any difficulties to handle this MSR? I have two solutions.
>> The first one is return the value of physical CPU's and always return
>> true when write. This is simple but may behave as if it is a VM
>> because write to it after VMXON will not return GP exception. This
>> solution can solve most basic problems since this MSR is not commonly
>> used. Another solution is adding a field in VCPU to handle this MSR.
>> This is a complex but better method.
>> 
>> I think I can complete this if needed.
>> 
>> Thanks,
>> Arthur
>> 
>> --
>> Arthur Chunqi Li
>> Department of Computer Science
>> School of EECS
>> Peking University
>> Beijing, China
> 
> --
>Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] kvm-unit-tests: Add a func to run instruction in emulator

2013-06-20 Thread Gmail
ok, I will handle all above in the following commit.

Arthur Chunqi Li
Department of Computer Science
School of EECS
Peking University
Beijing, China

>From my iPhone

在 2013-6-20,16:48,Gleb Natapov  写道:

> On Wed, Jun 19, 2013 at 11:00:56PM +0800, Arthur Chunqi Li wrote:
>> Add a function trap_emulator to run an instruction in emulator.
>> Set inregs first (%rax is invalid because it is used as return
>> address), put instruction codec in alt_insn and call func with
>> alt_insn_length. Get results in outregs.
>> 
>> Signed-off-by: Arthur Chunqi Li 
>> ---
>> x86/emulator.c |  110 
>> 
>> 1 file changed, 110 insertions(+)
>> mode change 100644 => 100755 x86/emulator.c
>> 
>> diff --git a/x86/emulator.c b/x86/emulator.c
>> old mode 100644
>> new mode 100755
>> index 96576e5..48d45c8
>> --- a/x86/emulator.c
>> +++ b/x86/emulator.c
>> @@ -11,6 +11,15 @@ int fails, tests;
>> 
>> static int exceptions;
>> 
>> +struct regs {
>> +u64 rax, rbx, rcx, rdx;
>> +u64 rsi, rdi, rsp, rbp;
>> +u64 r8, r9, r10, r11;
>> +u64 r12, r13, r14, r15;
>> +u64 rip, rflags;
>> +};
>> +struct regs inregs, outregs, save;
>> +
>> void report(const char *name, int result)
>> {
>>++tests;
>> @@ -685,6 +694,107 @@ static void test_shld_shrd(u32 *mem)
>> report("shrd (cl)", *mem == ((0x12345678 >> 3) | (5u << 29)));
>> }
>> 
>> +#define INSN_SAVE\
> No need for all the defines. Put all the code into insn_page, allocate
> alt_insn_page dynamically and copy the code there by memcpy.
> 
>> +"ret\n\t"\
>> +"pushf\n\t"\
>> +"push 136+save \n\t"\
>> +"popf \n\t"\
>> +"xchg %rax, 0+save \n\t"\
>> +"xchg %rbx, 8+save \n\t"\
>> +"xchg %rcx, 16+save \n\t"\
>> +"xchg %rdx, 24+save \n\t"\
>> +"xchg %rsi, 32+save \n\t"\
>> +"xchg %rdi, 40+save \n\t"\
>> +"xchg %rsp, 48+save \n\t"\
>> +"xchg %rbp, 56+save \n\t"\
>> +"xchg %r8, 64+save \n\t"\
>> +"xchg %r9, 72+save \n\t"\
>> +"xchg %r10, 80+save \n\t"\
>> +"xchg %r11, 88+save \n\t"\
>> +"xchg %r12, 96+save \n\t"\
>> +"xchg %r13, 104+save \n\t"\
>> +"xchg %r14, 112+save \n\t"\
>> +"xchg %r15, 120+save \n\t"\
>> +
>> +#define INSN_RESTORE\
>> +"xchg %rax, 0+save \n\t"\
>> +"xchg %rbx, 8+save \n\t"\
>> +"xchg %rcx, 16+save \n\t"\
>> +"xchg %rdx, 24+save \n\t"\
>> +"xchg %rsi, 32+save \n\t"\
>> +"xchg %rdi, 40+save \n\t"\
>> +"xchg %rsp, 48+save \n\t"\
>> +"xchg %rbp, 56+save \n\t"\
>> +"xchg %r8, 64+save \n\t"\
>> +"xchg %r9, 72+save \n\t"\
>> +"xchg %r10, 80+save \n\t"\
>> +"xchg %r11, 88+save \n\t"\
>> +"xchg %r12, 96+save \n\t"\
>> +"xchg %r13, 104+save \n\t"\
>> +"xchg %r14, 112+save \n\t"\
>> +"xchg %r15, 120+save \n\t"\
>> +"pushf \n\t"\
>> +"pop 136+save \n\t"\
>> +"popf \n\t"\
>> +"ret \n\t"\
>> +
>> +#define INSN_TRAP\
>> +"in  (%dx),%al\n\t"\
>> +". = . + 31\n\t"\
> If you will do ".skip 31, 0x90\n\t" instead you can drop loop
> that inserts nops bellow.
> 
>> +
>> +asm(
>> +".align 4096\n\t"
>> +"insn_page:\n\t"
>> +INSN_SAVE
>> +"test_insn:\n\t"
>> +INSN_TRAP
>> +"test_insn_end:\n\t"
>> +INSN_RESTORE
>> +"insn_page_end:\n\t"
>> +".align 4096\n\t"
>> +
>> +"alt_insn_page:\n\t"
>> +INSN_SAVE
>> +"alt_test_insn:\n\t"
>> +INSN_TRAP
>> +"alt_test_insn_end:\n\t"
>> +INSN_RESTORE
>> +"alt_insn_page_end:\n\t"
>> +".align 4096\n\t"
>> +);
>> +
>> +static void trap_emulator(uint64_t *mem, uint8_t* alt_insn, int 
>> alt_insn_length)
>> +{
>> +ulong *cr3 = (ulong *)read_cr3();
>> +void *insn_ram;
>> +int i;
>> +extern u8 insn_page[], test_insn[], test_insn_end[];
>> +extern u8 alt_insn_page[], alt_test_insn[];
>> +
>> +insn_ram = vmap(virt_to_phys(insn_page), 4096);
>> +for (i=1; i> +alt_test_insn[i] = test_insn[i] = 0x90; // nop
>> +for (i=0; i> +alt_test_insn[i] = alt_insn[i];
>> +for(;i> +alt_test_insn[i] = 0x90; // nop
>> +save = inregs;
>> +
>> +// Load the code TLB with insn_page, but point the page tables at
>> +// alt_insn_page (and keep the data TLB clear, for AMD decode assist).
>> +// This will make the CPU trap on the insn_page instruction but the
>> +// hypervisor will see alt_insn_page.
> I prefer all the comments to be changed to /**/ style while we are at it.
> 
>> +install_page(cr3, virt_to_phys(insn_page), insn_ram);
>> +invlpg(insn_ram);
>> +// Load code TLB
>> +asm volatile("

Re: [PATCH 1/2] kvm-unit-tests: Add a func to run instruction in emulator

2013-06-19 Thread Gmail

在 2013-6-20,0:03,Gleb Natapov  写道:

> On Wed, Jun 19, 2013 at 11:07:18PM +0800, 李春奇  wrote:
>> Hi Gleb,
>> This version can set %rsp before trapping into emulator, because
>> insn_page and alt_insn_page is statically defined and their relative
>> position to (save) is fixed during execution.
> The position of the code is not fixed during execution since you execute
> it from a virtual address obtained dynamically by vmap() and the address
> is definitely different from the one the code was compiled for, but if
> you look at the code that compile actually produce you will see that it
> uses absolute address to access "save" and this is why it works. I
> wounder why compiler decided to use absolute address this time, Paolo?
> 
>> In this way, test case of test_mmx_movq_mf needs to pre-define its own
>> stack, this change is in the next patch.
>> 
>> In this version, insn_ram is initially mapped to insn_page and them
>> each call to insn_page/alt_insn_page are all via insn_ram. This trick
>> runs well but I don't know why my previous version causes error.
> Because previous version tried to use install_page() on a large page
> mapped region and the function does not know how to handle that.
I don't quite understand what you mean here. What is the differences between 
large page and 4k page in this test case? Maybe I don't understand the 
differences of install_pte() with 4k page and 2m pages.
> 
>> Arthur.
>> On Wed, Jun 19, 2013 at 11:00 PM, Arthur Chunqi Li  wrote:
>>> Add a function trap_emulator to run an instruction in emulator.
>>> Set inregs first (%rax is invalid because it is used as return
>>> address), put instruction codec in alt_insn and call func with
>>> alt_insn_length. Get results in outregs.
>>> 
>>> Signed-off-by: Arthur Chunqi Li 
>>> ---
>>> x86/emulator.c |  110 
>>> 
>>> 1 file changed, 110 insertions(+)
>>> mode change 100644 => 100755 x86/emulator.c
>>> 
>>> diff --git a/x86/emulator.c b/x86/emulator.c
>>> old mode 100644
>>> new mode 100755
>>> index 96576e5..48d45c8
>>> --- a/x86/emulator.c
>>> +++ b/x86/emulator.c
>>> @@ -11,6 +11,15 @@ int fails, tests;
>>> 
>>> static int exceptions;
>>> 
>>> +struct regs {
>>> +   u64 rax, rbx, rcx, rdx;
>>> +   u64 rsi, rdi, rsp, rbp;
>>> +   u64 r8, r9, r10, r11;
>>> +   u64 r12, r13, r14, r15;
>>> +   u64 rip, rflags;
>>> +};
>>> +struct regs inregs, outregs, save;
>>> +
>>> void report(const char *name, int result)
>>> {
>>>   ++tests;
>>> @@ -685,6 +694,107 @@ static void test_shld_shrd(u32 *mem)
>>>report("shrd (cl)", *mem == ((0x12345678 >> 3) | (5u << 29)));
>>> }
>>> 
>>> +#define INSN_SAVE  \
>>> +   "ret\n\t"   \
>>> +   "pushf\n\t" \
>>> +   "push 136+save \n\t"\
>>> +   "popf \n\t" \
>>> +   "xchg %rax, 0+save \n\t"\
>>> +   "xchg %rbx, 8+save \n\t"\
>>> +   "xchg %rcx, 16+save \n\t"   \
>>> +   "xchg %rdx, 24+save \n\t"   \
>>> +   "xchg %rsi, 32+save \n\t"   \
>>> +   "xchg %rdi, 40+save \n\t"   \
>>> +   "xchg %rsp, 48+save \n\t"   \
>>> +   "xchg %rbp, 56+save \n\t"   \
>>> +   "xchg %r8, 64+save \n\t"\
>>> +   "xchg %r9, 72+save \n\t"\
>>> +   "xchg %r10, 80+save \n\t"   \
>>> +   "xchg %r11, 88+save \n\t"   \
>>> +   "xchg %r12, 96+save \n\t"   \
>>> +   "xchg %r13, 104+save \n\t"  \
>>> +   "xchg %r14, 112+save \n\t"  \
>>> +   "xchg %r15, 120+save \n\t"  \
>>> +
>>> +#define INSN_RESTORE   \
>>> +   "xchg %rax, 0+save \n\t"\
>>> +   "xchg %rbx, 8+save \n\t"\
>>> +   "xchg %rcx, 16+save \n\t"   \
>>> +   "xchg %rdx, 24+save \n\t"   \
>>> +   "xchg %rsi, 32+save \n\t"   \
>>> +   "xchg %rdi, 40+save \n\t"   \
>>> +   "xchg %rsp, 48+save \n\t"   \
>>> +   "xchg %rbp, 56+save \n\t"   \
>>> +   "xchg %r8, 64+save \n\t"\
>>> +   "xchg %r9, 72+save \n\t"\
>>> +   "xchg %r10, 80+save \n\t"   \
>>> +   "xchg %r11, 88+save \n\t"   \
>>> +   "xchg %r12, 96+save \n\t"   \
>>> +   "xchg %r13, 104+save \n\t"  \
>>> +   "xchg %r14, 112+save \n\t"  \
>>> +   "xchg %r15, 120+save \n\t"  \
>>> +   "pushf \n\t"\
>>> +   "pop 136+save \n\t" \
>>> +   "popf \n\t" \
>>> +   "ret \n\t"  \
>>> +
>>> +#define INSN_TRAP  \
>>> +   "in  (%dx),%al\n\t" \
>>> +   ".