Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Oct 2016 22:04:23 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r306738 - stable/11/sys/boot/efi/loader/arch/amd64
Message-ID:  <201610052204.u95M4Nvn038008@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Oct  5 22:04:22 2016
New Revision: 306738
URL: https://svnweb.freebsd.org/changeset/base/306738

Log:
  MFC r306090:
  Simple post-mortem reporter for amd64 loader.efi.

Added:
  stable/11/sys/boot/efi/loader/arch/amd64/exc.S
     - copied unchanged from r306090, head/sys/boot/efi/loader/arch/amd64/exc.S
  stable/11/sys/boot/efi/loader/arch/amd64/trap.c
     - copied unchanged from r306090, head/sys/boot/efi/loader/arch/amd64/trap.c
Modified:
  stable/11/sys/boot/efi/loader/arch/amd64/Makefile.inc
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/boot/efi/loader/arch/amd64/Makefile.inc
==============================================================================
--- stable/11/sys/boot/efi/loader/arch/amd64/Makefile.inc	Wed Oct  5 22:02:36 2016	(r306737)
+++ stable/11/sys/boot/efi/loader/arch/amd64/Makefile.inc	Wed Oct  5 22:04:22 2016	(r306738)
@@ -3,7 +3,9 @@
 SRCS+=	amd64_tramp.S \
 	start.S \
 	framebuffer.c \
-	elf64_freebsd.c
+	elf64_freebsd.c \
+	trap.c \
+	exc.S
 
 .PATH:	${.CURDIR}/../../i386/libi386
 SRCS+=	nullconsole.c \

Copied: stable/11/sys/boot/efi/loader/arch/amd64/exc.S (from r306090, head/sys/boot/efi/loader/arch/amd64/exc.S)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/11/sys/boot/efi/loader/arch/amd64/exc.S	Wed Oct  5 22:04:22 2016	(r306738, copy of r306090, head/sys/boot/efi/loader/arch/amd64/exc.S)
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Konstantin Belousov under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+	.macro	EH	N, err=1
+	.align	8
+	.globl	EXC\N\()_handler
+EXC\N\()_handler:
+	.if	\err != 1
+	pushq	$0
+	.endif
+	pushq	%rax
+	pushq	%rdx
+	pushq	%rcx
+	movl	$\N,%ecx
+	jmp	all_handlers
+	.endm
+
+	.text
+	EH	0,0
+	EH	1,0
+	EH	2,0
+	EH	3,0
+	EH	4,0
+	EH	5,0
+	EH	6,0
+	EH	7,0
+	EH	8
+	EH	9,0
+	EH	10
+	EH	11
+	EH	12
+	EH	13
+	EH	14
+	EH	16,0
+	EH	17
+	EH	18,0
+	EH	19,0
+	EH	20,0
+
+	.globl	exc_rsp
+all_handlers:
+	cmpq	%rsp,exc_rsp(%rip)
+	je	exception
+
+	/*
+	 * Interrupt, not exception.
+	 * First, copy the hardware interrupt frame to the previous stack.
+	 * Our handler always has private IST stack.
+	 */
+	movq	(6*8)(%rsp),%rax	/* saved %rsp value, AKA old stack */
+	subq	(5*8),%rax
+	movq	(3*8)(%rsp),%rdx	/* copy %rip to old stack */
+	movq	%rdx,(%rax)
+	movq	(4*8)(%rsp),%rdx	/* copy %cs */
+	movq	%rdx,(1*8)(%rax)
+	movq	(5*8)(%rsp),%rdx	/* copy %rflags */
+	movq	%rdx,(2*8)(%rax)
+	movq	(6*8)(%rsp),%rdx	/* copy %rsp */
+	movq	%rdx,(3*8)(%rax)
+	movq	(7*8)(%rsp),%rdx	/* copy %ss */
+	movq	%rdx,(4*8)(%rax)
+
+	/*
+	 * Now simulate invocation of the original interrupt handler
+	 * with retq.  We switch stacks and execute retq from the old
+	 * stack since there is no free registers at the last moment.
+	 */
+	subq	$16,%rax
+	leaq	fw_intr_handlers(%rip),%rdx
+	movq	(%rdx,%rcx,8),%rdx /* push intr handler address on old stack */
+	movq	%rdx,8(%rax)
+	movq	(2*8)(%rsp),%rcx   /* saved %rax is put on top of old stack */
+	movq	%rcx,(%rax)
+	movq	(%rsp),%rcx
+	movq	8(%rsp),%rdx
+
+	movq	32(%rsp),%rsp	/* switch to old stack */
+	popq	%rax
+	retq
+
+exception:
+	/*
+	 * Form the struct trapframe on our IST stack.
+	 * Skip three words, which are currently busy with temporal
+	 * saves.
+	 */
+	pushq	%r15
+	pushq	%r14
+	pushq	%r13
+	pushq	%r12
+	pushq	%r11
+	pushq	%r10
+	pushq	%rbp
+	pushq	%rbx
+	pushq	$0	/* %rax	*/
+	pushq	%r9
+	pushq	%r8
+	pushq	$0	/* %rcx */
+	pushq	$0	/* %rdx	*/
+	pushq	%rsi
+	pushq	%rdi
+
+	/*
+	 * Move %rax, %rdx, %rcx values into the final location,
+	 * from the three words which were skipped above.
+	 */
+	movq	0x88(%rsp),%rax
+	movq	%rax,0x30(%rsp)	/* tf_rax */
+	movq	0x78(%rsp),%rax
+	movq	%rax,0x18(%rsp)	/* tf_rcx */
+	movq	0x80(%rsp),%rax
+	movq	%rax,0x10(%rsp)	/* tf_rdx */
+
+	/*
+	 * And fill the three words themself.
+	 */
+	movq	%cr2,%rax
+	movq	%rax,0x80(%rsp)	/* tf_addr */
+	movl	%ecx,0x78(%rsp)	/* tf_trapno */
+	movw	%ds,0x8e(%rsp)
+	movw	%es,0x8c(%rsp)
+	movw	%fs,0x7c(%rsp)
+	movw	%gs,0x7e(%rsp)
+	movw	$0,0x88(%rsp)	/* tf_flags */
+
+	/*
+	 * Call dump routine.
+	 */
+	movq	%rsp,%rdi
+	callq	report_exc
+
+	/*
+	 * Hang after reporting. Interrupts are already disabled.
+	 */
+1:
+	hlt
+	jmp	1b

Copied: stable/11/sys/boot/efi/loader/arch/amd64/trap.c (from r306090, head/sys/boot/efi/loader/arch/amd64/trap.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/11/sys/boot/efi/loader/arch/amd64/trap.c	Wed Oct  5 22:04:22 2016	(r306738, copy of r306090, head/sys/boot/efi/loader/arch/amd64/trap.c)
@@ -0,0 +1,398 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Konstantin Belousov under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <string.h>
+#include <sys/param.h>
+#include <machine/cpufunc.h>
+#include <machine/psl.h>
+#include <machine/segments.h>
+#include <machine/frame.h>
+#include <machine/tss.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+#include "loader_efi.h"
+
+#define	NUM_IST	8
+#define	NUM_EXC	32
+
+/*
+ * This code catches exceptions but forwards hardware interrupts to
+ * handlers installed by firmware.  It differentiates exceptions
+ * vs. interrupts by presence of the error code on the stack, which
+ * causes different stack pointer value on trap handler entry.
+ *
+ * Use kernel layout for the trapframe just to not be original.
+ *
+ * Use free IST slot in existing TSS, or create our own TSS if
+ * firmware did not configured any, to have stack switched to
+ * IST-specified one, e.g. to handle #SS.  If hand-off cannot find
+ * unused IST slot, or create a new descriptor in GDT, we bail out.
+ */
+
+static struct region_descriptor fw_idt;	/* Descriptor for pristine fw IDT */
+static struct region_descriptor loader_idt;/* Descriptor for loader
+					   shadow IDT */
+static EFI_PHYSICAL_ADDRESS lidt_pa;	/* Address of loader shadow IDT */
+static EFI_PHYSICAL_ADDRESS tss_pa;	/* Address of TSS */
+static EFI_PHYSICAL_ADDRESS exc_stack_pa;/* Address of IST stack for loader */
+EFI_PHYSICAL_ADDRESS exc_rsp;	/* %rsp value on our IST stack when
+				   exception happens */
+EFI_PHYSICAL_ADDRESS fw_intr_handlers[NUM_EXC]; /* fw handlers for < 32 IDT
+						   vectors */
+static int intercepted[NUM_EXC];
+static int ist;				/* IST for exception handlers */
+static uint32_t tss_fw_seg;		/* Fw TSS segment */
+static uint32_t loader_tss;		/* Loader TSS segment */
+static struct region_descriptor fw_gdt;	/* Descriptor of pristine GDT */
+static EFI_PHYSICAL_ADDRESS loader_gdt_pa; /* Address of loader shadow GDT */
+
+void report_exc(struct trapframe *tf);
+void
+report_exc(struct trapframe *tf)
+{
+
+	/* XXX using printf */
+	printf("===================================================="
+	    "============================\n");
+	printf("Exception %u\n", tf->tf_trapno);
+	printf("ss 0x%04hx cs 0x%04hx ds 0x%04hx es 0x%04hx fs 0x%04hx "
+	    "gs 0x%04hx\n",
+	    (uint16_t)tf->tf_ss, (uint16_t)tf->tf_cs, (uint16_t)tf->tf_ds,
+	    (uint16_t)tf->tf_es, (uint16_t)tf->tf_fs, (uint16_t)tf->tf_gs);
+	printf("err 0x%08x rfl 0x%08x addr 0x%016lx\n"
+	    "rsp 0x%016lx rip 0x%016lx\n",
+	    (uint32_t)tf->tf_err, (uint32_t)tf->tf_rflags, tf->tf_addr,
+	    tf->tf_rsp, tf->tf_rip);
+	printf(
+	    "rdi 0x%016lx rsi 0x%016lx rdx 0x%016lx\n"
+	    "rcx 0x%016lx r8  0x%016lx r9  0x%016lx\n"
+	    "rax 0x%016lx rbx 0x%016lx rbp 0x%016lx\n"
+	    "r10 0x%016lx r11 0x%016lx r12 0x%016lx\n"
+	    "r13 0x%016lx r14 0x%016lx r15 0x%016lx\n",
+	    tf->tf_rdi, tf->tf_rsi, tf->tf_rdx, tf->tf_rcx, tf->tf_r8,
+	    tf->tf_r9, tf->tf_rax, tf->tf_rbx, tf->tf_rbp, tf->tf_r10,
+	    tf->tf_r11, tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15);
+	printf("Machine stopped.\n");
+}
+
+static void
+prepare_exception(unsigned idx, uint64_t my_handler,
+    int ist_use_table[static NUM_IST])
+{
+	struct gate_descriptor *fw_idt_e, *loader_idt_e;
+
+	fw_idt_e = &((struct gate_descriptor *)fw_idt.rd_base)[idx];
+	loader_idt_e = &((struct gate_descriptor *)loader_idt.rd_base)[idx];
+	fw_intr_handlers[idx] = fw_idt_e->gd_looffset +
+	    (fw_idt_e->gd_hioffset << 16);
+	intercepted[idx] = 1;
+	ist_use_table[fw_idt_e->gd_ist]++;
+	loader_idt_e->gd_looffset = my_handler;
+	loader_idt_e->gd_hioffset = my_handler >> 16;
+	loader_idt_e->gd_selector = fw_idt_e->gd_selector; /* XXX */
+	loader_idt_e->gd_ist = 0;
+	loader_idt_e->gd_type = SDT_SYSIGT;
+	loader_idt_e->gd_dpl = 0;
+	loader_idt_e->gd_p = 1;
+	loader_idt_e->gd_xx = 0;
+	loader_idt_e->sd_xx1 = 0;
+}
+#define	PREPARE_EXCEPTION(N)						\
+    extern char EXC##N##_handler[];					\
+    prepare_exception(N, (uintptr_t)EXC##N##_handler, ist_use_table);
+
+static void
+free_tables(void)
+{
+
+	if (lidt_pa != 0) {
+		BS->FreePages(lidt_pa, EFI_SIZE_TO_PAGES(fw_idt.rd_limit));
+		lidt_pa = 0;
+	}
+	if (exc_stack_pa != 0) {
+		BS->FreePages(exc_stack_pa, 1);
+		exc_stack_pa = 0;
+	}
+	if (tss_pa != 0 && tss_fw_seg == 0) {
+		BS->FreePages(tss_pa, EFI_SIZE_TO_PAGES(sizeof(struct
+		    amd64tss)));
+		tss_pa = 0;
+	}
+	if (loader_gdt_pa != 0) {
+		BS->FreePages(tss_pa, 2);
+		loader_gdt_pa = 0;
+	}
+	ist = 0;
+	loader_tss = 0;
+}
+
+static int
+efi_setup_tss(struct region_descriptor *gdt, uint32_t loader_tss_idx,
+    struct amd64tss **tss)
+{
+	EFI_STATUS status;
+	struct system_segment_descriptor *tss_desc;
+
+	tss_desc = (struct system_segment_descriptor *)(gdt->rd_base +
+	    (loader_tss_idx << 3));
+	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+	    EFI_SIZE_TO_PAGES(sizeof(struct amd64tss)), &tss_pa);
+	if (EFI_ERROR(status)) {
+		printf("efi_setup_tss: AllocatePages tss error %lu\n",
+		    EFI_ERROR_CODE(status));
+		return (0);
+	}
+	*tss = (struct amd64tss *)tss_pa;
+	bzero(*tss, sizeof(**tss));
+	tss_desc->sd_lolimit = sizeof(struct amd64tss);
+	tss_desc->sd_lobase = tss_pa;
+	tss_desc->sd_type = SDT_SYSTSS;
+	tss_desc->sd_dpl = 0;
+	tss_desc->sd_p = 1;
+	tss_desc->sd_hilimit = sizeof(struct amd64tss) >> 16;
+	tss_desc->sd_gran = 0;
+	tss_desc->sd_hibase = tss_pa >> 24;
+	tss_desc->sd_xx0 = 0;
+	tss_desc->sd_xx1 = 0;
+	tss_desc->sd_mbz = 0;
+	tss_desc->sd_xx2 = 0;
+	return (1);
+}
+
+static int
+efi_redirect_exceptions(void)
+{
+	int ist_use_table[NUM_IST];
+	struct gate_descriptor *loader_idt_e;
+	struct system_segment_descriptor *tss_desc, *gdt_desc;
+	struct amd64tss *tss;
+	struct region_descriptor *gdt_rd, loader_gdt;
+	uint32_t i;
+	EFI_STATUS status;
+	register_t rfl;
+
+	sidt(&fw_idt);
+	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+	    EFI_SIZE_TO_PAGES(fw_idt.rd_limit), &lidt_pa);
+	if (EFI_ERROR(status)) {
+		printf("efi_redirect_exceptions: AllocatePages IDT error %lu\n",
+		    EFI_ERROR_CODE(status));
+		lidt_pa = 0;
+		return (0);
+	}
+	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, 1,
+	    &exc_stack_pa);
+	if (EFI_ERROR(status)) {
+		printf("efi_redirect_exceptions: AllocatePages stk error %lu\n",
+		    EFI_ERROR_CODE(status));
+		exc_stack_pa = 0;
+		free_tables();
+		return (0);
+	}
+	loader_idt.rd_limit = fw_idt.rd_limit;
+	bcopy((void *)fw_idt.rd_base, (void *)loader_idt.rd_base,
+	    loader_idt.rd_limit);
+	bzero(ist_use_table, sizeof(ist_use_table));
+	bzero(fw_intr_handlers, sizeof(fw_intr_handlers));
+	bzero(intercepted, sizeof(intercepted));
+
+	sgdt(&fw_gdt);
+	tss_fw_seg = read_tr();
+	gdt_rd = NULL;
+	if (tss_fw_seg == 0) {
+		for (i = 2; (i << 3) + sizeof(*gdt_desc) <= fw_gdt.rd_limit;
+		    i += 2) {
+			gdt_desc = (struct system_segment_descriptor *)(
+			    fw_gdt.rd_base + (i << 3));
+			if (gdt_desc->sd_type == 0 && gdt_desc->sd_mbz == 0) {
+				gdt_rd = &fw_gdt;
+				break;
+			}
+		}
+		if (gdt_rd == NULL) {
+			if (i >= 8190) {
+				printf("efi_redirect_exceptions: all slots "
+				    "in gdt are used\n");
+				free_tables();
+				return (0);
+			}
+			loader_gdt.rd_limit = roundup2(fw_gdt.rd_limit +
+			    sizeof(struct system_segment_descriptor),
+			    sizeof(struct system_segment_descriptor)) - 1;
+			i = (loader_gdt.rd_limit + 1 -
+			    sizeof(struct system_segment_descriptor)) /
+			    sizeof(struct system_segment_descriptor) * 2;
+			status = BS->AllocatePages(AllocateAnyPages,
+			    EfiLoaderData,
+			    EFI_SIZE_TO_PAGES(loader_gdt.rd_limit),
+			    &loader_gdt_pa);
+			if (EFI_ERROR(status)) {
+				printf("efi_setup_tss: AllocatePages gdt error "
+				    "%lu\n",  EFI_ERROR_CODE(status));
+				loader_gdt_pa = 0;
+				free_tables();
+				return (0);
+			}
+			loader_gdt.rd_base = loader_gdt_pa;
+			bzero((void *)loader_gdt.rd_base, loader_gdt.rd_limit);
+			bcopy((void *)fw_gdt.rd_base,
+			    (void *)loader_gdt.rd_base, fw_gdt.rd_limit);
+			gdt_rd = &loader_gdt;
+		}
+		loader_tss = i << 3;
+		if (!efi_setup_tss(gdt_rd, i, &tss)) {
+			tss_pa = 0;
+			free_tables();
+			return (0);
+		}
+	} else {
+		tss_desc = (struct system_segment_descriptor *)((char *)
+		    fw_gdt.rd_base + tss_fw_seg);
+		if (tss_desc->sd_type != SDT_SYSTSS &&
+		    tss_desc->sd_type != SDT_SYSBSY) {
+			printf("LTR points to non-TSS descriptor\n");
+			free_tables();
+			return (0);
+		}
+		tss_pa = tss_desc->sd_lobase + (tss_desc->sd_hibase << 16);
+		tss = (struct amd64tss *)tss_pa;
+		tss_desc->sd_type = SDT_SYSTSS; /* unbusy */
+	}
+
+	PREPARE_EXCEPTION(0);
+	PREPARE_EXCEPTION(1);
+	PREPARE_EXCEPTION(2);
+	PREPARE_EXCEPTION(3);
+	PREPARE_EXCEPTION(4);
+	PREPARE_EXCEPTION(5);
+	PREPARE_EXCEPTION(6);
+	PREPARE_EXCEPTION(7);
+	PREPARE_EXCEPTION(8);
+	PREPARE_EXCEPTION(9);
+	PREPARE_EXCEPTION(10);
+	PREPARE_EXCEPTION(11);
+	PREPARE_EXCEPTION(12);
+	PREPARE_EXCEPTION(13);
+	PREPARE_EXCEPTION(14);
+	PREPARE_EXCEPTION(16);
+	PREPARE_EXCEPTION(17);
+	PREPARE_EXCEPTION(18);
+	PREPARE_EXCEPTION(19);
+	PREPARE_EXCEPTION(20);
+
+	exc_rsp = exc_stack_pa + PAGE_SIZE -
+	    (6 /* hw exception frame */ + 3 /* scratch regs */) * 8;
+
+	/* Find free IST and use it */
+	for (ist = 1; ist < NUM_IST; ist++) {
+		if (ist_use_table[ist] == 0)
+			break;
+	}
+	if (ist == NUM_IST) {
+		printf("efi_redirect_exceptions: all ISTs used\n");
+		free_tables();
+		lidt_pa = 0;
+		return (0);
+	}
+	for (i = 0; i < NUM_EXC; i++) {
+		loader_idt_e = &((struct gate_descriptor *)loader_idt.
+		    rd_base)[i];
+		if (intercepted[i])
+			loader_idt_e->gd_ist = ist;
+	}
+	(&(tss->tss_ist1))[ist - 1] = exc_stack_pa + PAGE_SIZE;
+
+	/* Switch to new IDT */
+	rfl = intr_disable();
+	if (loader_gdt_pa != 0)
+		bare_lgdt(&loader_gdt);
+	if (loader_tss != 0)
+		ltr(loader_tss);
+	lidt(&loader_idt);
+	intr_restore(rfl);
+	return (1);
+}
+
+static void
+efi_unredirect_exceptions(void)
+{
+	register_t rfl;
+
+	if (lidt_pa == 0)
+		return;
+
+	rfl = intr_disable();
+	if (ist != 0)
+		(&(((struct amd64tss *)tss_pa)->tss_ist1))[ist - 1] = 0;
+	if (loader_gdt_pa != 0)
+		bare_lgdt(&fw_gdt);
+	if (loader_tss != 0)
+		ltr(tss_fw_seg);
+	lidt(&fw_idt);
+	intr_restore(rfl);
+	free_tables();
+}
+
+static int
+command_grab_faults(int argc, char *argv[])
+{
+	int res;
+
+	res = efi_redirect_exceptions();
+	if (!res)
+		printf("failed\n");
+	return (CMD_OK);
+}
+COMMAND_SET(grap_faults, "grab_faults", "grab faults", command_grab_faults);
+
+static int
+command_ungrab_faults(int argc, char *argv[])
+{
+
+	efi_unredirect_exceptions();
+	return (CMD_OK);
+}
+COMMAND_SET(ungrab_faults, "ungrab_faults", "ungrab faults",
+    command_ungrab_faults);
+
+static int
+command_fault(int argc, char *argv[])
+{
+
+	__asm("ud2");
+	return (CMD_OK);
+}
+COMMAND_SET(fault, "fault", "generate fault", command_fault);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610052204.u95M4Nvn038008>