Bus error

Last updated

In computing, a bus error is a fault raised by hardware, notifying an operating system (OS) that a process is trying to access memory that the CPU cannot physically address: an invalid address for the address bus, hence the name. In modern use on most architectures these are much rarer than segmentation faults, which occur primarily due to memory access violations: problems in the logical address or permissions.

Contents

On POSIX-compliant platforms, bus errors usually result in the SIGBUS signal being sent to the process that caused the error. SIGBUS can also be caused by any general device fault that the computer detects, though a bus error rarely means that the computer hardware is physically broken—it is normally caused by a bug in software.[ citation needed ] Bus errors may also be raised for certain other paging errors; see below.

Causes

There are at least three main causes of bus errors:

Non-existent address

Software instructs the CPU to read or write a specific physical memory address. Accordingly, the CPU sets this physical address on its address bus and requests all other hardware connected to the CPU to respond with the results, if they answer for this specific address. If no other hardware responds, the CPU raises an exception, stating that the requested physical address is unrecognized by the whole computer system. Note that this only covers physical memory addresses. Trying to access an undefined virtual memory address is generally considered to be a segmentation fault rather than a bus error, though if the MMU is separate, the processor cannot tell the difference.

Unaligned access

Most CPUs are byte-addressable, where each unique memory address refers to an 8-bit byte. Most CPUs can access individual bytes from each memory address, but they generally cannot access larger units (16 bits, 32 bits, 64 bits and so on) without these units being "aligned" to a specific boundary (the x86 platform being a notable exception).

For example, if multi-byte accesses must be 16 bit-aligned, addresses (given in bytes) at 0, 2, 4, 6, and so on would be considered aligned and therefore accessible, while addresses 1, 3, 5, and so on would be considered unaligned. Similarly, if multi-byte accesses must be 32-bit aligned, addresses 0, 4, 8, 12, and so on would be considered aligned and therefore accessible, and all addresses in between would be considered unaligned. Attempting to access a unit larger than a byte at an unaligned address can cause a bus error.

Some systems may have a hybrid of these depending on the architecture being used. For example, for hardware based on the IBM System/360 mainframe, including the IBM System z, Fujitsu B8000, RCA Spectra, and UNIVAC Series 90, instructions must be on a 16-bit boundary, that is, execution addresses must start on an even byte. Attempts to branch to an odd address results in a specification exception. [1] Data, however, may be retrieved from any address in memory, and may be one byte or longer depending on the instruction.

CPUs generally access data at the full width of their data bus at all times. To address bytes, they access memory at the full width of their data bus, then mask and shift to address the individual byte. Systems tolerate this inefficient algorithm, as it is an essential feature for most software, especially string processing. Unlike bytes, larger units can span two aligned addresses and would thus require more than one fetch on the data bus. It is possible for CPUs to support this, but this functionality is rarely required directly at the machine code level, thus CPU designers normally avoid implementing it and instead issue bus errors for unaligned memory access.

Paging errors

FreeBSD, Linux and Solaris can signal a bus error when virtual memory pages cannot be paged in, e.g. because it has disappeared (e.g. accessing a memory-mapped file or executing a binary image which has been truncated while the program was running), [2] [ unreliable source? ] or because a just-created memory-mapped file cannot be physically allocated, because the disk is full.

Non-present segment (x86)

On x86 exists an older memory management mechanism known as segmentation. If the application loads segment register with the selector of non-present segment (which under POSIX-compliant OSes can only be done with an assembly language), the exception is generated. Some OSes used that for swapping, but under Linux this generates SIGBUS.

Example

This is an example of unaligned memory access, written in the C programming language with AT&T assembly syntax.

#include<stdlib.h>intmain(intargc,char**argv){int*iptr;char*cptr;#if defined(__GNUC__)# if defined(__i386__)/* Enable Alignment Checking on x86 */__asm__("pushf\norl $0x40000,(%esp)\npopf");# elif defined(__x86_64__) /* Enable Alignment Checking on x86_64 */__asm__("pushf\norl $0x40000,(%rsp)\npopf");# endif#endif/* malloc() always provides memory which is aligned for all fundamental types */cptr=malloc(sizeof(int)+1);/* Increment the pointer by one, making it misaligned */iptr=(int*)++cptr;/* Dereference it as an int pointer, causing an unaligned access */*iptr=42;/*       Following accesses will also result in sigbus error.       short *sptr;       int    i;       sptr = (short *)&i;       // For all odd value increments, it will result in sigbus.       sptr = (short *)(((char *)sptr) + 1);       *sptr = 100;    */return0;}

Compiling and running the example on a POSIX compliant OS on x86 demonstrates the error:

$ gcc -ansi sigbus.c -o sigbus $ ./sigbus  Bus error$ gdb ./sigbus (gdb)rProgram received signal SIGBUS, Bus error.0x080483ba in main ()(gdb)x/i $pc0x80483ba <main+54>:    mov    DWORD PTR [eax],0x2a(gdb)p/x $eax$1= 0x804a009 (gdb)p/t $eax & (sizeof(int) - 1)$2=1

The GDB debugger shows that the immediate value 0x2a is being stored at the location stored in the EAX register, using X86 assembly language. This is an example of register indirect addressing.

Printing the low order bits of the address shows that it is not aligned to a word boundary ("dword" using x86 terminology).

Related Research Articles

Intel 8086 16-bit microprocessor

The 8086 is a 16-bit microprocessor chip designed by Intel between early 1976 and June 8, 1978, when it was released. The Intel 8088, released July 1, 1979, is a slightly modified chip with an external 8-bit data bus, and is notable as the processor used in the original IBM PC design.

Motorola 68020

The Motorola 68020 is a 32-bit microprocessor from Motorola, released in 1984. A lower cost version was also made available, known as the 68EC020. In keeping with naming practices common to Motorola designs, the 68020 is usually referred to as the "020", pronounced "oh-two-oh" or "oh-twenty".

In computing, a segmentation fault or access violation is a fault, or failure condition, raised by hardware with memory protection, notifying an operating system (OS) the software has attempted to access a restricted area of memory. On standard x86 computers, this is a form of general protection fault. The operating system kernel will, in response, usually perform some corrective action, generally passing the fault on to the offending process by sending the process a signal. Processes can in some cases install a custom signal handler, allowing them to recover on their own, but otherwise the OS default signal handler is used, generally causing abnormal termination of the process, and sometimes a core dump.

x86 Family of instruction set architectures

x86 is a family of instruction set architectures initially developed by Intel based on the Intel 8086 microprocessor and its 8088 variant. The 8086 was introduced in 1978 as a fully 16-bit extension of Intel's 8-bit 8080 microprocessor, with memory segmentation as a solution for addressing more memory than can be covered by a plain 16-bit address. The term "x86" came into being because the names of several successors to Intel's 8086 processor end in "86", including the 80186, 80286, 80386 and 80486 processors.

In computing, endianness is the order or sequence of bytes of a word of digital data in computer memory. Endianness is primarily expressed as big-endian (BE) or little-endian (LE). A big-endian system stores the most significant byte of a word at the smallest memory address and the least significant byte at the largest. A little-endian system, in contrast, stores the least-significant byte at the smallest address. Bi-endianness is a feature supported by numerous computer architectures that feature switchable endianness in data fetches and stores or for instruction fetches. Other orderings are generically called middle-endian or mixed-endian.

x86 memory segmentation refers to the implementation of memory segmentation in the Intel x86 computer instruction set architecture. Segmentation was introduced on the Intel 8086 in 1978 as a way to allow programs to address more than 64 KB (65,536 bytes) of memory. The Intel 80286 introduced a second version of segmentation in 1982 that added support for virtual memory and memory protection. At this point the original model was renamed real mode, and the new version was named protected mode. The x86-64 architecture, introduced in 2003, has largely dropped support for segmentation in 64-bit mode.

In computing, protected mode, also called protected virtual address mode, is an operational mode of x86-compatible central processing units (CPUs). It allows system software to use features such as virtual memory, paging and safe multi-tasking designed to increase an operating system's control over application software.

Memory management unit Hardware translating virtual addresses to physical address

A memory management unit (MMU), sometimes called paged memory management unit (PMMU), is a computer hardware unit having all memory references passed through itself, primarily performing the translation of virtual memory addresses to physical addresses.

x86 assembly language is a family of backward-compatible assembly languages, which provide some level of compatibility all the way back to the Intel 8008 introduced in April 1972. x86 assembly languages are used to produce object code for the x86 class of processors. Like all assembly languages, it uses short mnemonics to represent the fundamental instructions that the CPU in a computer can understand and follow. Compilers sometimes produce assembly code as an intermediate step when translating a high level program into machine code. Regarded as a programming language, assembly coding is machine-specific and low level. Assembly languages are more typically used for detailed and time critical applications such as small real-time embedded systems or operating system kernels and device drivers.

Memory-mapped I/O (MMIO) and port-mapped I/O (PMIO) are two complementary methods of performing input/output (I/O) between the central processing unit (CPU) and peripheral devices in a computer. An alternative approach is using dedicated I/O processors, commonly known as channels on mainframe computers, which execute their own instructions.

C dynamic memory allocation refers to performing manual memory management for dynamic memory allocation in the C programming language via a group of functions in the C standard library, namely malloc, realloc, calloc and free.

Pointer (computer programming) Object which stores memory addresses in a computer program

In computer science, a pointer is an object in many programming languages that stores a memory address. This can be that of another value located in computer memory, or in some cases, that of memory-mapped computer hardware. A pointer references a location in memory, and obtaining the value stored at that location is known as dereferencing the pointer. As an analogy, a page number in a book's index could be considered a pointer to the corresponding page; dereferencing such a pointer would be done by flipping to the page with the given page number and reading the text found on that page. The actual format and content of a pointer variable is dependent on the underlying computer architecture.

General protection fault

A general protection fault (GPF) in the x86 instruction set architectures (ISAs) is a fault initiated by ISA-defined protection mechanisms in response to an access violation caused by some running code, either in the kernel or a user program. The mechanism is first described in Intel manuals and datasheets for the Intel 80286 CPU, which was introduced in 1983; it is also described in section 9.8.13 in the Intel 80386 programmer's reference manual from 1986. A general protection fault is implemented as an interrupt. Some operating systems may also classify some exceptions not related to access violations, such as illegal opcode exceptions, as general protection faults, even though they have nothing to do with memory protection. If a CPU detects a protection violation, it stops executing the code and sends a GPF interrupt. In most cases, the operating system removes the failing process from the execution queue, signals the user, and continues executing other processes. If, however, the operating system fails to catch the general protection fault, i.e. another protection violation occurs before the operating system returns from the previous GPF interrupt, the CPU signals a double fault, stopping the operating system. If yet another failure occurs, the CPU is unable to recover; since 80286, the CPU enters a special halt state called "Shutdown", which can only be exited through a hardware reset. The IBM PC AT, the first PC-compatible system to contain an 80286, has hardware that detects the Shutdown state and automatically resets the CPU when it occurs. All descendants of the PC AT do the same, so in a PC, a triple fault causes an immediate system reset.

Addressing modes are an aspect of the instruction set architecture in most central processing unit (CPU) designs. The various addressing modes that are defined in a given instruction set architecture define how the machine language instructions in that architecture identify the operand(s) of each instruction. An addressing mode specifies how to calculate the effective memory address of an operand by using information held in registers and/or constants contained within a machine instruction or elsewhere.

Memory segmentation is an operating system memory management technique of division of a computer's primary memory into segments or sections. In a computer system using segmentation, a reference to a memory location includes a value that identifies a segment and an offset within that segment. Segments or sections are also used in object files of compiled programs when they are linked together into a program image and when the image is loaded into memory.

Data structure alignment is the way data is arranged and accessed in computer memory. It consists of three separate but related issues: data alignment, data structure padding, and packing.

INT 13h is shorthand for BIOS interrupt call 13hex, the 20th interrupt vector in an x86-based computer system. The BIOS typically sets up a real mode interrupt handler at this vector that provides sector-based hard disk and floppy disk read and write services using cylinder-head-sector (CHS) addressing. Modern PC BIOSes also include INT 13h extension functions, originated by IBM and Microsoft in 1992, that provide those same disk access services using 64-bit LBA addressing; with minor additions, these were quasi-standardized by Phoenix Technologies and others as the EDD BIOS extensions.

In the x86 architecture, the CPUID instruction is a processor supplementary instruction allowing software to discover details of the processor. It was introduced by Intel in 1993 with the launch of the Pentium and SL-enhanced 486 processors.

The task state segment (TSS) is a structure on x86-based computers which holds information about a task. It is used by the operating system kernel for task management. Specifically, the following information is stored in the TSS:

This article describes the calling conventions used when programming x86 architecture microprocessors.

References

  1. z/Architecture Principles of Operation, SA22-7832-04, Page 6-6, Fifth Edition (September, 2005) IBM Corporation, Poukeepsie, NY, Retrievable from http://publibfp.dhe.ibm.com/epubs/pdf/a2278324.pdf (Retrieved December 31, 2015)
  2. "What is SIGBUS - Object specific hardware error?".