From patchwork Mon Apr 28 15:22:49 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 4079381 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 912AABFF02 for ; Mon, 28 Apr 2014 15:24:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4C27E201EF for ; Mon, 28 Apr 2014 15:24:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3C7CB20219 for ; Mon, 28 Apr 2014 15:24:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756632AbaD1PYe (ORCPT ); Mon, 28 Apr 2014 11:24:34 -0400 Received: from mail-ee0-f54.google.com ([74.125.83.54]:42318 "EHLO mail-ee0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932684AbaD1PXV (ORCPT ); Mon, 28 Apr 2014 11:23:21 -0400 Received: by mail-ee0-f54.google.com with SMTP id d49so4984208eek.41 for ; Mon, 28 Apr 2014 08:23:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=q/2Aotsm0rSzx67eSOLFoYk7Zl/LHnD4oHM4d8sQK/8=; b=FJdET9j18+kDNPFr0tJ1QWL1bSHS1NSGqod7IKG7tTaEEkiRWzFVl8GBOk2L14DX5D o41uOAGe2aS3YHBXMsy63ygZ3tCPIC3H/touubc9q2XnuMZCf6FrxssO/2eQjHjO5gcz PqOt2f/tBH7ZdTKd8u8GdoSbRCBkOxQ9P2bWa15i9foL8PeJzibsMvNZXFlGo8e/DEnm KIe90V7J0dSEGkFoOLPeVATTdmla9Vf3SwD+Isk+0tfeKhJQgHcdslJ06vNHi6943nzs xpBAH6Tt2lXkq5Nd1ZwyZlVJdj0/3GrL1222aa6ehX7zelnoiQ10pxdo/eg/hPOAZFPa cryA== X-Received: by 10.14.4.201 with SMTP id 49mr34050582eej.13.1398698599806; Mon, 28 Apr 2014 08:23:19 -0700 (PDT) Received: from playground.lan (net-37-117-141-58.cust.vodafonedsl.it. [37.117.141.58]) by mx.google.com with ESMTPSA id 44sm51183201eek.30.2014.04.28.08.23.17 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Apr 2014 08:23:18 -0700 (PDT) From: Paolo Bonzini To: kvm@vger.kernel.org Cc: jan.kiszka@siemens.com, drjones@redhat.com Subject: [PATCH kvm-unit-tests 06/18] x86: taskswitch: use desc library Date: Mon, 28 Apr 2014 17:22:49 +0200 Message-Id: <1398698581-17302-7-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1398698581-17302-1-git-send-email-pbonzini@redhat.com> References: <1398698581-17302-1-git-send-email-pbonzini@redhat.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The APIs in desc.c make it much simpler to understand what the test is doing. Signed-off-by: Paolo Bonzini --- lib/x86/desc.c | 7 ++- lib/x86/desc.h | 2 + x86/taskswitch.c | 134 +++++-------------------------------------------------- 3 files changed, 18 insertions(+), 125 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index 812295c..442c9a1 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -217,6 +217,11 @@ void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran) gdt32[num].access = access; } +void set_gdt_task_gate(u16 sel, u16 tss_sel) +{ + set_gdt_entry(sel, tss_sel, 0, 0x85, 0); // task, present +} + void set_idt_task_gate(int vec, u16 sel) { idt_entry_t *e = &boot_idt[vec]; @@ -235,7 +240,7 @@ void set_idt_task_gate(int vec, u16 sel) * 1 - interrupt task */ -static tss32_t tss_intr; +tss32_t tss_intr; static char tss_stack[4096]; void setup_tss32(void) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index e0af335..4689474 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -106,6 +106,7 @@ extern idt_entry_t boot_idt[256]; #ifndef __x86_64__ extern gdt_entry_t gdt32[]; extern tss32_t tss; +extern tss32_t tss_intr; #endif unsigned exception_vector(void); @@ -113,6 +114,7 @@ unsigned exception_error_code(void); void set_idt_entry(int vec, void *addr, int dpl); void set_idt_sel(int vec, u16 sel); void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran); +void set_gdt_task_gate(u16 tss_sel, u16 sel); void set_idt_task_gate(int vec, u16 sel); void set_intr_task_gate(int e, void *fn); void print_current_tss_info(void); diff --git a/x86/taskswitch.c b/x86/taskswitch.c index 8ed8a93..423f51e 100644 --- a/x86/taskswitch.c +++ b/x86/taskswitch.c @@ -6,152 +6,38 @@ */ #include "libcflat.h" +#include "lib/x86/desc.h" -#define FIRST_SPARE_SEL 0x18 - -struct exception_frame { - unsigned long error_code; - unsigned long ip; - unsigned long cs; - unsigned long flags; -}; - -struct tss32 { - unsigned short prev; - unsigned short res1; - unsigned long esp0; - unsigned short ss0; - unsigned short res2; - unsigned long esp1; - unsigned short ss1; - unsigned short res3; - unsigned long esp2; - unsigned short ss2; - unsigned short res4; - unsigned long cr3; - unsigned long eip; - unsigned long eflags; - unsigned long eax, ecx, edx, ebx, esp, ebp, esi, edi; - unsigned short es; - unsigned short res5; - unsigned short cs; - unsigned short res6; - unsigned short ss; - unsigned short res7; - unsigned short ds; - unsigned short res8; - unsigned short fs; - unsigned short res9; - unsigned short gs; - unsigned short res10; - unsigned short ldt; - unsigned short res11; - unsigned short t:1; - unsigned short res12:15; - unsigned short iomap_base; -}; - -static char main_stack[4096]; -static char fault_stack[4096]; -static struct tss32 main_tss; -static struct tss32 fault_tss; - -static unsigned long long gdt[] __attribute__((aligned(16))) = { - 0, - 0x00cf9b000000ffffull, - 0x00cf93000000ffffull, - 0, 0, /* TSS segments */ - 0, /* task return gate */ -}; - -static unsigned long long gdtr; +#define TSS_RETURN (FIRST_SPARE_SEL) void fault_entry(void); static __attribute__((used, regparm(1))) void fault_handler(unsigned long error_code) { - unsigned short *desc; - - printf("fault at %x:%x, prev task %x, error code %x\n", - main_tss.cs, main_tss.eip, fault_tss.prev, error_code); + print_current_tss_info(); + printf("error code %x\n", error_code); - main_tss.eip += 2; + tss.eip += 2; - desc = (unsigned short *)&gdt[3]; - desc[2] &= ~0x0200; + gdt32[TSS_MAIN / 8].access &= ~2; - desc = (unsigned short *)&gdt[5]; - desc[0] = 0; - desc[1] = fault_tss.prev; - desc[2] = 0x8500; - desc[3] = 0; + set_gdt_task_gate(TSS_RETURN, tss_intr.prev); } asm ( "fault_entry:\n" " mov (%esp),%eax\n" " call fault_handler\n" - " jmp $0x28, $0\n" + " jmp $" xstr(TSS_RETURN) ", $0\n" ); -static void setup_tss(struct tss32 *tss, void *entry, - void *stack_base, unsigned long stack_size) -{ - unsigned long cr3; - unsigned short cs, ds; - - asm ("mov %%cr3,%0" : "=r" (cr3)); - asm ("mov %%cs,%0" : "=r" (cs)); - asm ("mov %%ds,%0" : "=r" (ds)); - - tss->ss0 = tss->ss1 = tss->ss2 = tss->ss = ds; - tss->esp0 = tss->esp1 = tss->esp2 = tss->esp = - (unsigned long)stack_base + stack_size; - tss->ds = tss->es = tss->fs = tss->gs = ds; - tss->cs = cs; - tss->eip = (unsigned long)entry; - tss->cr3 = cr3; -} - -static void setup_tss_desc(unsigned short tss_sel, struct tss32 *tss) -{ - unsigned long addr = (unsigned long)tss; - unsigned short *desc; - - desc = (unsigned short *)&gdt[tss_sel/8]; - desc[0] = sizeof(*tss) - 1; - desc[1] = addr; - desc[2] = 0x8900 | ((addr & 0x00ff0000) >> 16); - desc[3] = (addr & 0xff000000) >> 16; -} - -static void set_intr_task(unsigned short tss_sel, int intr, struct tss32 *tss) -{ - unsigned short *desc = (void *)(intr* sizeof(long) * 2); - - setup_tss_desc(tss_sel, tss); - - desc[0] = 0; - desc[1] = tss_sel; - desc[2] = 0x8500; - desc[3] = 0; -} - int main(int ac, char **av) { const long invalid_segment = 0x1234; - gdtr = ((unsigned long long)(unsigned long)&gdt << 16) | - (sizeof(gdt) - 1); - asm ("lgdt %0" : : "m" (gdtr)); - - setup_tss(&main_tss, 0, main_stack, sizeof(main_stack)); - setup_tss_desc(FIRST_SPARE_SEL, &main_tss); - asm ("ltr %0" : : "r" ((unsigned short)FIRST_SPARE_SEL)); - - setup_tss(&fault_tss, fault_entry, fault_stack, sizeof(fault_stack)); - set_intr_task(FIRST_SPARE_SEL+8, 13, &fault_tss); + setup_tss32(); + set_intr_task_gate(13, fault_entry); asm ( "mov %0,%%es\n"