From patchwork Wed Dec 22 15:06:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 427961 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oBMF7VsV014364 for ; Wed, 22 Dec 2010 15:07:32 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753571Ab0LVPHG (ORCPT ); Wed, 22 Dec 2010 10:07:06 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48025 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753352Ab0LVPGc (ORCPT ); Wed, 22 Dec 2010 10:06:32 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oBMF6WPM026622 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 22 Dec 2010 10:06:32 -0500 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oBMF6VYw022605; Wed, 22 Dec 2010 10:06:32 -0500 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 13519) id CD46B18D3FB; Wed, 22 Dec 2010 17:06:29 +0200 (IST) From: Gleb Natapov To: avi@redhat.com, mtosatti@redhat.com Cc: kvm@vger.kernel.org Subject: [PATCH unit-tests 14/16] Add handle_exception() interface. Date: Wed, 22 Dec 2010 17:06:27 +0200 Message-Id: <1293030389-1143-15-git-send-email-gleb@redhat.com> In-Reply-To: <1293030389-1143-1-git-send-email-gleb@redhat.com> References: <1293030389-1143-1-git-send-email-gleb@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 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 (demeter1.kernel.org [140.211.167.41]); Wed, 22 Dec 2010 15:07:32 +0000 (UTC) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index aa0b4f4..0da8989 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -90,19 +90,6 @@ void set_idt_entry(int vec, void *addr, int dpl) #endif } -struct ex_regs { - unsigned long rax, rcx, rdx, rbx; - unsigned long dummy, rbp, rsi, rdi; -#ifdef __x86_64__ - unsigned long r8, r9, r10, r11; - unsigned long r12, r13, r14, r15; -#endif - unsigned long vector; - unsigned long error_code; - unsigned long rip; - unsigned long cs; - unsigned long rflags; -}; struct ex_record { unsigned long rip; @@ -111,10 +98,7 @@ struct ex_record { extern struct ex_record exception_table_start, exception_table_end; -#ifndef __x86_64__ -__attribute__((regparm(1))) -#endif -void do_handle_exception(struct ex_regs *regs) +static void check_exception_table(struct ex_regs *regs) { struct ex_record *ex; unsigned ex_val; @@ -129,10 +113,34 @@ void do_handle_exception(struct ex_regs *regs) return; } } - printf("unhandled excecption\n"); + printf("unhandled excecption %d\n", regs->vector); exit(7); } +static void (*exception_handlers[32])(struct ex_regs *regs); + + +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)) +{ + if (v < 32) + exception_handlers[v] = func; +} + +#ifndef __x86_64__ +__attribute__((regparm(1))) +#endif +void do_handle_exception(struct ex_regs *regs) +{ + if (regs->vector < 32 && exception_handlers[regs->vector]) { + exception_handlers[regs->vector](regs); + return; + } + printf("unhandled cpu excecption %d\n", regs->vector); + if (regs->vector == 14) + printf("PF at %p addr %p\n", regs->rip, read_cr2()); + exit(7); +} + #ifdef __x86_64__ # define R "r" # define W "q" @@ -143,22 +151,42 @@ void do_handle_exception(struct ex_regs *regs) # define S "4" #endif -asm (".pushsection .text \n\t" - "ud_fault: \n\t" - "push"W" $0 \n\t" - "push"W" $6 \n\t" - "jmp handle_exception \n\t" - - "gp_fault: \n\t" - "push"W" $13 \n\t" - "jmp handle_exception \n\t" - - "de_fault: \n\t" - "push"W" $0 \n\t" - "push"W" $0 \n\t" - "jmp handle_exception \n\t" +#define EX(NAME, N) extern char NAME##_fault; \ + asm (".pushsection .text \n\t" \ + #NAME"_fault: \n\t" \ + "push"W" $0 \n\t" \ + "push"W" $"#N" \n\t" \ + "jmp __handle_exception \n\t" \ + ".popsection") + +#define EX_E(NAME, N) extern char NAME##_fault; \ + asm (".pushsection .text \n\t" \ + #NAME"_fault: \n\t" \ + "push"W" $"#N" \n\t" \ + "jmp __handle_exception \n\t" \ + ".popsection") + +EX(de, 0); +EX(db, 1); +EX(nmi, 2); +EX(bp, 3); +EX(of, 4); +EX(br, 5); +EX(ud, 6); +EX(nm, 7); +EX_E(df, 8); +EX_E(ts, 10); +EX_E(np, 11); +EX_E(ss, 12); +EX_E(gp, 13); +EX_E(pf, 14); +EX(mf, 16); +EX_E(ac, 17); +EX(mc, 18); +EX(xm, 19); - "handle_exception: \n\t" +asm (".pushsection .text \n\t" + "__handle_exception: \n\t" #ifdef __x86_64__ "push %r15; push %r14; push %r13; push %r12 \n\t" "push %r11; push %r10; push %r9; push %r8 \n\t" @@ -182,15 +210,37 @@ asm (".pushsection .text \n\t" "iret"W" \n\t" ".popsection"); +static void *idt_handlers[32] = { + [0] = &de_fault, + [1] = &db_fault, + [2] = &nmi_fault, + [3] = &bp_fault, + [4] = &of_fault, + [5] = &br_fault, + [6] = &ud_fault, + [7] = &nm_fault, + [8] = &df_fault, + [10] = &ts_fault, + [11] = &np_fault, + [12] = &ss_fault, + [13] = &gp_fault, + [14] = &pf_fault, + [16] = &mf_fault, + [17] = &ac_fault, + [18] = &mc_fault, + [19] = &xm_fault, +}; void setup_idt(void) { - extern char ud_fault, gp_fault, de_fault; - + int i; load_lidt(idt, 256); - set_idt_entry(0, &de_fault, 0); - set_idt_entry(6, &ud_fault, 0); - set_idt_entry(13, &gp_fault, 0); + for (i = 0; i < 32; i++) + if (idt_handlers[i]) + set_idt_entry(i, idt_handlers[i], 0); + handle_exception(0, check_exception_table); + handle_exception(6, check_exception_table); + handle_exception(13, check_exception_table); } unsigned exception_vector(void) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index 2c9db5b..073878d 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -10,6 +10,20 @@ static inline void setup_gdt(void){} static inline void setup_tss32(void){} #endif +struct ex_regs { + unsigned long rax, rcx, rdx, rbx; + unsigned long dummy, rbp, rsi, rdi; +#ifdef __x86_64__ + unsigned long r8, r9, r10, r11; + unsigned long r12, r13, r14, r15; +#endif + unsigned long vector; + unsigned long error_code; + unsigned long rip; + unsigned long cs; + unsigned long rflags; +}; + #define ASM_TRY(catch) \ "movl $0, %%gs:4 \n\t" \ ".pushsection .data.ex \n\t" \ @@ -29,5 +43,6 @@ void set_idt_entry(int vec, void *addr, int dpl); void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); void set_intr_task_gate(int e, void *fn); void print_current_tss_info(void); +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); #endif