From patchwork Thu Jun 10 03:31:42 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sheng Yang X-Patchwork-Id: 105269 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o5A3YuDk032369 for ; Thu, 10 Jun 2010 03:34:56 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758610Ab0FJDey (ORCPT ); Wed, 9 Jun 2010 23:34:54 -0400 Received: from mga01.intel.com ([192.55.52.88]:11787 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755525Ab0FJDey (ORCPT ); Wed, 9 Jun 2010 23:34:54 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 09 Jun 2010 20:30:33 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.53,395,1272870000"; d="scan'208";a="806488296" Received: from syang10-desktop.sh.intel.com (HELO syang10-desktop) ([10.239.36.64]) by fmsmga001.fm.intel.com with ESMTP; 09 Jun 2010 20:34:22 -0700 Received: from yasker by syang10-desktop with local (Exim 4.71) (envelope-from ) id 1OMYUa-0007p5-3R; Thu, 10 Jun 2010 11:31:44 +0800 From: Sheng Yang To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org, Sheng Yang Subject: [PATCH 1/2] test: Add IDT framework Date: Thu, 10 Jun 2010 11:31:42 +0800 Message-Id: <1276140703-30046-1-git-send-email-sheng@linux.intel.com> X-Mailer: git-send-email 1.7.0.4 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 10 Jun 2010 03:34:56 +0000 (UTC) diff --git a/kvm/test/config-x86-common.mak b/kvm/test/config-x86-common.mak index c97de52..800b635 100644 --- a/kvm/test/config-x86-common.mak +++ b/kvm/test/config-x86-common.mak @@ -59,6 +59,8 @@ $(TEST_DIR)/realmode.o: bits = 32 $(TEST_DIR)/msr.flat: $(cstart.o) $(TEST_DIR)/msr.o +$(TEST_DIR)/idt_test.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/idt_test.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \ $(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o diff --git a/kvm/test/config-x86_64.mak b/kvm/test/config-x86_64.mak index d8fd2b5..f9cd121 100644 --- a/kvm/test/config-x86_64.mak +++ b/kvm/test/config-x86_64.mak @@ -5,6 +5,6 @@ ldarch = elf64-x86-64 CFLAGS += -D__x86_64__ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ - $(TEST_DIR)/emulator.flat + $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat include config-x86-common.mak diff --git a/kvm/test/lib/x86/idt.h b/kvm/test/lib/x86/idt.h new file mode 100644 index 0000000..f449f01 --- /dev/null +++ b/kvm/test/lib/x86/idt.h @@ -0,0 +1,19 @@ +#ifndef __IDT_TEST__ +#define __IDT_TEST__ + +void setup_idt(void); + +#define EXCEPTION_REGION_BEGIN(r, lb) \ + asm volatile("pushq $"lb"\n\t" \ + "mov $2, %0\n\t" \ + : "=r"(r)) +#define EXCEPTION_REGION_END(r, lb) \ + asm volatile("popq %%rdx\n\t" \ + "mov $0, %0\n\t" \ + lb":\n\t": \ + "=r"(r) :: "%rdx") + +#define UD_VECTOR 6 +#define GP_VECTOR 13 + +#endif diff --git a/kvm/test/x86/idt.c b/kvm/test/x86/idt.c new file mode 100644 index 0000000..e3172cb --- /dev/null +++ b/kvm/test/x86/idt.c @@ -0,0 +1,85 @@ +#include "idt.h" + +typedef struct { + unsigned short offset0; + unsigned short selector; + unsigned short ist : 3; + unsigned short : 5; + unsigned short type : 4; + unsigned short : 1; + unsigned short dpl : 2; + unsigned short p : 1; + unsigned short offset1; + unsigned offset2; + unsigned reserved; +} idt_entry_t; + +static idt_entry_t idt[256]; + +typedef struct { + unsigned short limit; + unsigned long linear_addr; +} __attribute__((packed)) descriptor_table_t; + +void lidt(idt_entry_t *idt, int nentries) +{ + descriptor_table_t dt; + + dt.limit = nentries * sizeof(*idt) - 1; + dt.linear_addr = (unsigned long)idt; + asm volatile ("lidt %0" : : "m"(dt)); +} + +unsigned short read_cs() +{ + unsigned short r; + + asm volatile ("mov %%cs, %0" : "=r"(r)); + return r; +} + +void memset(void *a, unsigned char v, int n) +{ + unsigned char *x = a; + + while (n--) + *x++ = v; +} + +void set_idt_entry(idt_entry_t *e, void *addr, int dpl) +{ + memset(e, 0, sizeof *e); + e->offset0 = (unsigned long)addr; + e->selector = read_cs(); + e->ist = 0; + e->type = 14; + e->dpl = dpl; + e->p = 1; + e->offset1 = (unsigned long)addr >> 16; + e->offset2 = (unsigned long)addr >> 32; +} + +void setup_idt(void) +{ + asm volatile (".section .text.ud \n\t" + "ud_fault: \n\t" + "mov 40(%%rsp), %%rax\n\t" + "mov %%rax, (%%rsp)\n\t" + "mov $6, %%rax\n\t" + "iretq \n\t" + ".section .text":); + + asm volatile (".section .text.gp \n\t" + "gp_fault: \n\t" + "pop %%rax \n\t" + "mov 40(%%rsp), %%rax\n\t" + "mov %%rax, (%%rsp)\n\t" + "mov $13, %%rax\n\t" + "iretq \n\t" + ".section .text":); + extern char ud_fault, gp_fault; + + lidt(idt, 256); + set_idt_entry(&idt[6], &ud_fault, 0); + set_idt_entry(&idt[13], &gp_fault, 0); +} diff --git a/kvm/test/x86/idt_test.c b/kvm/test/x86/idt_test.c new file mode 100644 index 0000000..08f0da8 --- /dev/null +++ b/kvm/test/x86/idt_test.c @@ -0,0 +1,48 @@ +#include "libcflat.h" +#include "idt.h" + +int test_ud2(void) +{ + int r; + EXCEPTION_REGION_BEGIN(r, "fixed_ud"); + asm volatile("ud2;\n\t"); + EXCEPTION_REGION_END(r, "fixed_ud"); + return r; +} + +int test_gp(void) +{ + int r; + EXCEPTION_REGION_BEGIN(r, "fixed_gp"); + asm volatile("mov $0xffffffff, %%rax\n\t" + "mov %%rax, %%cr4\n\t":); + EXCEPTION_REGION_END(r, "fixed_gp"); + return r; +} + +int test(void) +{ + int r; + + setup_idt(); + printf("GP testing: "); + r = test_gp(); + if (r == GP_VECTOR) + printf("Pass!\n"); + else + printf("Fail!\n"); + printf("UD testing: "); + r = test_ud2(); + if (r == UD_VECTOR) + printf("Pass!\n"); + else + printf("Fail!\n"); + return 0; +} + +int main(void) +{ + printf("start testing\n"); + test(); + return 0; +}