From patchwork Tue Oct 9 10:50:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peng Hao X-Patchwork-Id: 10631781 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 60EF613AA for ; Tue, 9 Oct 2018 02:38:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5431829B45 for ; Tue, 9 Oct 2018 02:38:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4713729B4F; Tue, 9 Oct 2018 02:38:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7FC8B29B45 for ; Tue, 9 Oct 2018 02:38:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726666AbeJIJxV (ORCPT ); Tue, 9 Oct 2018 05:53:21 -0400 Received: from out1.zte.com.cn ([202.103.147.172]:44244 "EHLO mxct.zte.com.cn" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726646AbeJIJxV (ORCPT ); Tue, 9 Oct 2018 05:53:21 -0400 Received: from mse01.zte.com.cn (unknown [10.30.3.20]) by Forcepoint Email with ESMTPS id 208F9E4551F24B2FC0A1; Tue, 9 Oct 2018 10:38:39 +0800 (CST) Received: from notes_smtp.zte.com.cn ([10.30.1.239]) by mse01.zte.com.cn with ESMTP id w992cOo8007728; Tue, 9 Oct 2018 10:38:24 +0800 (GMT-8) (envelope-from peng.hao2@zte.com.cn) Received: from localhost.localdomain.localdomain ([10.74.120.59]) by szsmtp06.zte.com.cn (Lotus Domino Release 8.5.3FP6) with ESMTP id 2018100910383653-3313687 ; Tue, 9 Oct 2018 10:38:36 +0800 From: Peng Hao To: pbonzini@redhat.com, rkrcmar@redhat.com Cc: kvm@vger.kernel.org, Peng Hao Subject: [PATCH v2] kvm-unit-test: add a fetch insn test case Date: Tue, 9 Oct 2018 18:50:25 +0800 Message-Id: <1539082225-73191-1-git-send-email-peng.hao2@zte.com.cn> X-Mailer: git-send-email 1.8.3.1 X-MIMETrack: Itemize by SMTP Server on SZSMTP06/server/zte_ltd(Release 8.5.3FP6|November 21, 2013) at 2018-10-09 10:38:36, Serialize by Router on notes_smtp/zte_ltd(Release 9.0.1FP7|August 17, 2016) at 2018-10-09 10:38:20, Serialize complete at 2018-10-09 10:38:20 X-MAIL: mse01.zte.com.cn w992cOo8007728 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP the test case is for "kvm/x86: fix a fetch fault emulation" . KVM internal error. Suberror: 1 emulation failure RAX=0000000000463fe8 RBX=ffffffffffffd000 RCX=000000000000000c RDX=0000000000464006 RSI=0000000000000001 RDI=0000000000463000 RBP=0000000000452ce0 RSP=0000000000452c78 R8 =0000000000000000 R9 =0000000000410d7f R10=0000000000000000 R11=0000000000000000 R12=ffffffffffffe000 R13=1111111111111111 R14=3333333333333333 R15=00000000a06d39e8 RIP=ffffffffffffd000 RFL=00010002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =0010 0000000000000000 ffffffff 00c09300 DPL=0 DS [-WA] CS =0008 0000000000000000 ffffffff 00a09b00 DPL=0 CS64 [-RA] SS =0010 0000000000000000 ffffffff 00c09300 DPL=0 DS [-WA] v1 --> v2: simply some functions. Signed-off-by: Peng Hao --- lib/vmalloc.c | 18 ++++++++++++++---- lib/vmalloc.h | 9 +++++++-- lib/x86/io.c | 2 +- lib/x86/vm.c | 5 +++++ x86/emulator.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 76 insertions(+), 10 deletions(-) diff --git a/lib/vmalloc.c b/lib/vmalloc.c index b583786..31c1fe0 100644 --- a/lib/vmalloc.c +++ b/lib/vmalloc.c @@ -36,18 +36,28 @@ void init_alloc_vpage(void *top) vfree_top = top; } -void *vmap(phys_addr_t phys, size_t size) +/* + * op: VMAP_MAP + * VMAP_UNMAP + * VMAP_REMAP + */ +void *vmap(phys_addr_t phys, void *vmem, size_t size, int op) { void *mem, *p; unsigned pages; size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); pages = size / PAGE_SIZE; - mem = p = alloc_vpages(pages); - + if (op == VMAP_MAP) + mem = p = alloc_vpages(pages); + else + mem = p = vmem; phys &= ~(unsigned long long)(PAGE_SIZE - 1); while (pages--) { - install_page(page_root, phys, p); + if (op == VMAP_UNMAP) + install_page(page_root, phys, p); + else + uninstall_page(page_root, phys, p); phys += PAGE_SIZE; p += PAGE_SIZE; } diff --git a/lib/vmalloc.h b/lib/vmalloc.h index 3658b80..579e1e8 100644 --- a/lib/vmalloc.h +++ b/lib/vmalloc.h @@ -3,6 +3,11 @@ #include +/* vmap op type */ +#define VMAP_MAP 0 +#define VMAP_UNMAP 1 +#define VMAP_REMAP 2 + extern void *alloc_vpages(ulong nr); extern void *alloc_vpage(void); extern void init_alloc_vpage(void *top); @@ -11,7 +16,7 @@ extern void setup_vm(void); extern void *setup_mmu(phys_addr_t top); extern phys_addr_t virt_to_pte_phys(pgd_t *pgtable, void *virt); extern pteval_t *install_page(pgd_t *pgtable, phys_addr_t phys, void *virt); - -void *vmap(phys_addr_t phys, size_t size); +extern pteval_t *uninstall_page(pgd_t *pgtable, phys_addr_t phys, void *virt); +void *vmap(phys_addr_t phys, void * vmem, size_t size, int op); #endif diff --git a/lib/x86/io.c b/lib/x86/io.c index 7e64877..266b132 100644 --- a/lib/x86/io.c +++ b/lib/x86/io.c @@ -116,5 +116,5 @@ void __iomem *ioremap(phys_addr_t phys_addr, size_t size) * mappings would be uncached - and may help us find bugs when we * properly map that way. */ - return vmap(phys_addr, size) + offset; + return vmap(phys_addr, NULL, size, VMAP_MAP) + offset; } diff --git a/lib/x86/vm.c b/lib/x86/vm.c index 73d9be4..cf77eb8 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -100,6 +100,11 @@ pteval_t *install_page(pgd_t *cr3, phys_addr_t phys, void *virt) return install_pte(cr3, 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK, 0); } +pteval_t *uninstall_page(pgd_t *cr3, phys_addr_t phys, void *virt) +{ + return install_pte(cr3, 1, virt, phys | PT_WRITABLE_MASK | PT_USER_MASK, 0); +} + void install_pages(pgd_t *cr3, phys_addr_t phys, size_t len, void *virt) { phys_addr_t max = (u64)len + (u64)phys; diff --git a/x86/emulator.c b/x86/emulator.c index c856db4..cfc9057 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -11,6 +11,8 @@ #define TESTDEV_IO_PORT 0xe0 static int exceptions; +static void *insn_page; +static void *insn_ram; /* Forced emulation prefix, used to invoke the emulator unconditionally. */ #define KVM_FEP "ud2; .byte 'k', 'v', 'm';" @@ -33,6 +35,49 @@ struct insn_desc { static char st1[] = "abcdefghijklmnop"; +void do_pf_tss(void); +void do_pf_tss(void) +{ + printf("PF running\n"); + vmap(virt_to_phys(insn_page), insn_ram, 4096, VMAP_REMAP); + invlpg(insn_ram); +} + +extern void pf_tss(void); + +asm ("pf_tss: \n\t" +#ifdef __x86_64__ + // no task on x86_64, save/restore caller-save regs + "push %rax; push %rcx; push %rdx; push %rsi; push %rdi\n" + "push %r8; push %r9; push %r10; push %r11\n" +#endif + "call do_pf_tss \n\t" +#ifdef __x86_64__ + "pop %r11; pop %r10; pop %r9; pop %r8\n" + "pop %rdi; pop %rsi; pop %rdx; pop %rcx; pop %rax\n" +#endif + "add $"S", %"R "sp\n\t" // discard error code + "iret"W" \n\t" + "jmp pf_tss\n\t" + ); + +static void test_fetch_insn(unsigned *mem,unsigned long phys, char *insn_ram) +{ + /* movb $1, mem+2(%rip) */ + insn_ram[0] = 0xc6; + insn_ram[1] = 0x05; + *(unsigned *)&insn_ram[2] = 2 + (char *)mem - (insn_ram + 7); + insn_ram[6] = 0x01; + /* ret */ + insn_ram[7] = 0xc3; + + vmap(phys, insn_ram, 4096, VMAP_UNMAP); + + *mem = 0; + asm("callq *%1" : "+m"(*mem) : "r"(insn_ram)); + report("fetch ", *mem == 0x10000); +} + static void test_stringio(void) { unsigned char r = 0; @@ -1018,12 +1063,11 @@ static void record_no_fep(struct ex_regs *regs) int main(void) { void *mem; - void *insn_page; - void *insn_ram; unsigned long t1, t2; setup_vm(); setup_idt(); + setup_alt_stack(); handle_exception(UD_VECTOR, record_no_fep); asm(KVM_FEP "nop"); handle_exception(UD_VECTOR, 0); @@ -1033,7 +1077,7 @@ int main(void) // install the page twice to test cross-page mmio install_page((void *)read_cr3(), IORAM_BASE_PHYS, mem + 4096); insn_page = alloc_page(); - insn_ram = vmap(virt_to_phys(insn_page), 4096); + insn_ram = vmap(virt_to_phys(insn_page), NULL, 4096, VMAP_MAP); // test mov reg, r/m and mov r/m, reg t1 = 0x123456789abcdef; @@ -1068,6 +1112,8 @@ int main(void) test_sse(mem); test_mmx(mem); test_rip_relative(mem, insn_ram); + set_intr_alt_stack(14, pf_tss); + test_fetch_insn(mem, virt_to_phys(insn_page), insn_ram); test_shld_shrd(mem); //test_lgdt_lidt(mem); test_sreg(mem);