- 论坛徽章:
- 9
|
kernel interrupt 0 - interrupt 45 测试程序
- /*
- * Test code for Interrupt table
- * Maintainer: Buddy <buddy.zhang@aliyun.com>
- *
- * Copyright (C) 2017 BiscuitOS
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
- #include <linux/kernel.h>
- #ifdef CONFIG_TESTCODE
- /*
- * Test interrupt 0 - divide zero
- * The processor generates a type 0 interrupt whenever executing a divide
- * instruction—either 'div' (divide) or 'idiv' (integer divide)—results in
- * a quotient that is larger than the destination specified. The default
- * interrupt handler on Linux displays a Floating point exception message
- * and terminates the program.
- */
- void test_interrupt0_divide_error(void)
- {
- #ifndef CONFIG_SOFT_INTERRUPT
- #ifdef CONFIG_DIVIDE_ERROR0
- int a;
- int b = 0;
- #else
- unsigned short _rax = 0xFFF;
- unsigned short _res;
- #endif
-
- #ifdef CONFIG_DIVIDE_ERROR0
- /* case 0 */
- /* divide error -> interrupt0 */
- a = 3 / b;
- b = a;
- #else
- /* case 1 */
- /*
- * EAX or AX can't store a rightful result-value
- * eg, _rax / 0x01 = 0xFFF, and "AL" can't store result '0xFFF'.
- */
- __asm__("mov %1, %%ax\n\t"
- "movb $0x1, %%bl\n\t"
- "div %%bl\n\t"
- "movb %%al, %0"
- : "=m" (_res) : "m" (_rax));
- printk("The result %#x\n", _res);
- #endif /* CONFIG_DIVIDE_ERROR0 */
- #else
- __asm__("int $0");
- #endif /* CONFIG_SOFT_INTERRUPT */
- }
- /*
- * Test interrupt 1 - debug
- * Single-Step Interrupt Single-stepping is a useful debugging tool to
- * observe the behavior of a program instruction by instruction. To start
- * single-stepping, the trap flag (TF) bit in the flags register should
- * be set (i.e., TF = 1). When TF is set, the CPU automatically generates
- * a type 1 interrupt after executing each instruction. Some exceptions
- * do exist, but we do not worry about them here.
- * The interrupt handler for the type 1 interrupt can be used to display
- * relevant information about the state of the program. For example,
- * the contents of all registers could be displayed.
- * To end single stepping, the TF should be cleared. The instruction set,
- * however, does not have instructions to directly manipulate the TF bit.
- * Instead, we have to resort to an indirect means. You have to push flags
- * register using pushf and manipulate the TF bit and use popf to store this
- * value back in the flags register. Here is an example code fragment that
- * sets the trap flag.
- */
- void test_interrupt1_debug(void)
- {
- #ifndef CONFIG_SOFT_INTERRUPT
- /* case 0 */
- /*
- * Set TF on EFLAGS will invoke interrupt 1 (debug).
- */
- __asm__("pushl %%eax\n\t"
- "pushf\n\t"
- "movl %%esp, %%eax\n\t"
- "orl $0x0100, (%%eax)\n\t" // set TF bit.
- "popf\n\t"
- "popl %%eax"
- ::);
- #else
- __asm__("int $1");
- #endif
- }
- /*
- * Test Interrupt 3 - NMI
- * In computing, a non-maskable interrupt (NMI) is a hardware interrupt
- * that standard interrupt-masking techniques in the system cannot ignore.
- * It typically occurs to signal attention for non-recoverable hardware
- * errors. (Some NMIs may be masked, but only by using proprietary methods
- * specific to the particular NMI.)
- * An NMI is often used when response time is critical or when an interrupt
- * should never be disabled during normal system operation. Such uses
- * include reporting non-recoverable hardware errors, system debugging
- * and profiling, and handling of special cases like system resets.
- */
- void test_interrupt2_nmi(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $2");
- #endif
- }
- /*
- * Test Interrupt 3 - int3
- * Breakpoint Interrupt If you have used a debugger, which you should
- * have by now, you already know the usefulness of inserting breakpoints
- * while debugging a program. The type 3 interrupt is dedicated to the
- * breakpoint processing. This type of interrupt can be generated by
- * using the special single-byte form of 'int3' (opcode CCH). Using the
- * 'int3' instruction automatically causes the assembler to encode the
- * instruction into the single-byte version. Note that the standard encoding
- * for the 'int' instruction is two bytes long.
- * Inserting a breakpoint in a program involves replacing the program
- * code byte by CCH while saving the program byte for later restoration
- * to remove the breakpoint. The standard 2-byte version of 'int3' can
- * cause problems in certain situations, as there are instructions that
- * require only a single byte to encode.
- */
- void test_interrupt3_int3(void)
- {
- #ifndef CONFIG_SOFT_INTERRUPT
- /* general interrupt entry */
- __asm__("pushl %%eax\n\t"
- "pushf\n\t"
- "movl %%esp, %%eax\n\t"
- "orl $0x0100, (%%eax)\n\t"
- "popf\n\t"
- "popl %%eax"
- ::);
- #else
- __asm__("int $3");
- #endif
- }
- /*
- * Test Interrupt 4 - overflow error
- * The type 4 interrupt is dedicated to handle overflow conditions.
- * There are two ways by which a type 4 interrupt can be generated:
- * either by 'int4' or by 'into' . Like the breakpoint interrupt,
- * 'into' requires only one byte to encode, as it does not require
- * the specification of the interrupt type number as part of the
- * instruction. Unlike 'int4', which unconditionally generates a
- * type 4 interrupt, 'into' generates a type 4 interrupt only if the
- * overflow flag is set. We do not normally use 'into' , as the
- * overflow condition is usually detected and processed by using
- * the conditional jump instructions 'jo' and 'jno'.
- */
- void test_interrupt4_overflow(void)
- {
- #ifndef CONFIG_SOFT_INTERRUPT
- /* case 0 */
- /*
- * 'OF' set and call 'into'
- */
- __asm__("pushl %%ebx\n\t"
- "movb $0x7f, %%bl\n\t"
- "addb $10, %%bl\n\t"
- "into\n\t"
- "popl %%ebx"
- ::);
- #else
- /* case 1 */
- __asm__("int $4");
- #endif
- }
- /*
- * Test Interrupt 5 - Bound error
- * Determines if the first operand (array index) is within the bounds of
- * an array specified the second operand (bounds operand). The array
- * index is a signed integer located in a register. The bounds operand
- * is a memory location that contains a pair of signed doubleword-integers
- * (when the operand-size attribute is 32) or a pair of signed word-integers
- * (when the operand-size attribute is 16). The first doubleword (or word)
- * is the lower bound of the array and the second doubleword (or word)
- * is the upper bound of the array. The array index must be greater than
- * or equal to the lower bound and less than or equal to the upper bound
- * plus the operand size in bytes.
- * If the index is not within bounds, a BOUND range exceeded exception
- * (#BR) is signaled. When this exception is generated, the saved return
- * instruction pointer points to the BOUND instruction.
- * The bounds limit data structure (two words or doublewords containing
- * the lower and upper limits of the array) is usually placed just before
- * the array itself, making the limits addressable via a constant offset
- * from the beginning of the array. Because the address of the array already
- * will be present in a register, this practice avoids extra bus cycles
- * to obtain the effective address of the array bounds.
- */
- void test_interrupt5_bound(void)
- {
- #ifndef CONFIG_SOFT_INTERRUPT
- int buffer[2] = { 0, 6 };
- int index = 7; /* safe value: 0, 1, 2, 3, 4, 5, 6 */
- /* case 0 */
- /*
- * Upper = buffer[1]
- * lower = buffer[0]
- * if index < lower || index > upper
- * Invoke Bound interrupt.
- */
- __asm__("lea %0, %%edx\n\t"
- "movl %1, %%eax\n\t"
- "boundl %%eax, (%%edx)"
- :: "m" (buffer), "m" (index));
- #else
- __asm__("int $5");
- #endif
- }
- /*
- * Test Interrupt 6 - Invalid operand
- */
- void test_interrupt6_invalid_op(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $6");
- #endif
- }
- /*
- * Test Interrupt 7 - device not available.
- * Not used - 20170603
- */
- void test_interrupt7_device_not_available(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $7");
- #endif
- }
- /*
- * Test Interrupt 8 - double fault
- * On the x86 architecture, a double fault exception occurs if the
- * processor encounters a problem while trying to service a pending
- * interrupt or exception. An example situation when a double fault
- * would occur is when an interrupt is triggered but the segment in
- * which the interrupt handler resides is invalid. If the processor
- * encounters a problem when calling the double fault handler, a triple
- * fault is generated and the processor shuts down.
- * As double faults can only happen due to kernel bugs, they are rarely
- * caused by user space programs in a modern protected mode operating
- * system, unless the program somehow gains kernel access (some viruses
- * and also some low-level DOS programs). Other processors like PowerPC
- * or SPARC generally save state to predefined and reserved machine
- * registers. A double fault will then be a situation where another
- * exception happens while the processor is still using the contents of
- * these registers to process the exception. SPARC processors have four
- * levels of such registers, i.e. they have a 4-window register system.
- */
- void test_interrupt8_double_fault(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $8");
- #endif
- }
- /*
- * Test Interrupt 9 - Coprocessor segment overrun
- */
- void test_interrupt9_coprocessor_segment_overrun(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $9");
- #endif
- }
- /*
- * Test Interrupt 10 - invalid TSS segment
- */
- void test_interrupt10_invalid_TSS(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $10");
- #endif
- }
- /*
- * Test Interrupt 11 - Segment not present.
- */
- void test_interrupt11_segment_not_present(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $11");
- #endif
- }
- /*
- * Test Interrupt 12 - Stack segment
- */
- void test_interrupt12_task_segment(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $12");
- #endif
- }
- /*
- * Test Interrupt 13 - General protection
- */
- void test_interrupt13_general_protection(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $13");
- #endif
- }
- /*
- * Test Interrupt 14 - page fault
- * Cannot use
- */
- void test_interrupt14_page_fault(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $14");
- #endif
- }
- /*
- * Test Interrupt 15 - Intel reserved
- */
- void test_interrupt15_intel_reserved(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $15");
- #endif
- }
- /*
- * Test Interrupt 16 - Coprocessor error
- * Cannot use
- */
- void test_interrupt16_coprocessor_error(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $16");
- #endif
- }
- /*
- * Test Interrupt 17-48 - Intel Reserved
- */
- void test_interrupt17_47_Reserved(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- //__asm__("int $17");
- __asm__("int $47");
- #endif
- }
- /*
- * Test Interrupt 39 - parallel interrupt
- */
- void test_interrupt39_parallel_interrupt(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $39");
- #endif
- }
- /*
- * Test Interrupt 45 - irq13
- * Cannot use
- */
- void test_interrupt45_irq13(void)
- {
- #ifdef CONFIG_SOFT_INTERRUPT
- __asm__("int $45");
- #endif
- }
- #endif
复制代码 |
|