This document specifies the application of Open Firmware to an ARM Processor, including requirements and practices to support unique firmware specific to an ARM Processor. The core requirements and practices specified by Open Firmware must be augmented by processor-specific requirements to form a complete specification for the firmware implementation for a ARM Processor. This document establishes such additional requirements pertaining to the processor and the support required by Open Firmware.
The following terms, denoted by a registration symbol (®) or trademark symbol() on the first occurrence in this publication, are registered trademarks or trademarks of the companies as shown in the list below:
3. Data Formats and Representations 1
4.1 Open Firmware's Use of Memory 2
4.1.2.2 Client Program Rules 2
5.1.1 Physical Address Formats and Representations 3
5.1.1.1 Numerical Representation 3
5.1.1.3 Unit Address Representation 3
5.1.2 "/cpus" node Properties 3
5.2.1 "/cpus/cpu" Node Properties 4
5.2.1.2 Internal (L1) Cache Properties 5
5.2.2 "/cpus/cpu" Node Methods 5
5.4.1 Memory Management Unit Properties 6
5.4.2 Memory Management Unit Methods 6
5.5 Ancillary (L2, L3 ....) Cache Node Properties 6
6. Client Interface Requirements 7
6.2.1 Initial Register Values 9
6.2.3 Client Interface Calling Convention 9
6.2.4 Client Program Arguments 10
6.2.6 Virtual address space and memory allocation 11
6.3 Additional Client Interface Services 12
6.4.1 Virtual Address Translation Assist Callbacks 13
6.4.2 Claim and Release Callbacks 14
7. User Interface Requirements 17
7.1 Machine Register Access 17
7.1.2 Floating-Point Registers 18
7.3 Configuration Variables 18
This document specifies the application of IEEE Std 1275-1994 Standard for Boot (Initialization, Configuration) Firmware, Core Practices and Requirements to computer systems that use the Advance RISC Machine (ARM) Instruction Set Architecture, including instruction-set-specific requirements and practices for debugging, client program interface and data formats. An implementation of Open Firmware for ARM shall implement the core requirements as defined in [1] and the ARM-specific extensions described in this binding.
This standard shall be used in conjunction with the following publications. When the following standards are superseded by an approved revision, the revision shall apply.
This standard uses technical terms as they are defined in the documents cited in Section 2.1 , plus the following terms:
core specification: Synonym for IEEE Std 1275-1994 Standard for Boot (Initialization, Configuration) Firmware, Core Practices and Requirements (i.e. the standard that specifies the system-independent and bus-independent requirements for Open Firmware).
Open Firmware: The firmware architecture defined by IEEE Std 1275-1994 and its applicable supplements or, when used as an adjective, a software component compliant with such an architecture.
virtual address: The address that a program uses to access a memory location or memory-mapped device register. Depending on the presence or absence of memory mapping hardware in the system, and whether or not that mapping hardware is enabled, a virtual address may or may not be the same as the physical address that appears on an external bus. Unless otherwise noted, all addresses mentioned in this document are virtual addresses.
The cell size shall be 32 bits. Number ranges for n, u, and other cell-sized items are consistent with 32-bit, two's-complement number representation.
The required alignment for items accessed with a-addr addresses shall be four-byte aligned (i.e. a multiple of 4).
Each operation involving a qaddr address shall be performed with a single 32-bit access to the addressed location; similarly, each waddr access shall be performed with a single 16-bit access. This implies four-byte alignment for qaddrs and two-byte alignment for waddrs.
Open Firmware shall use the memory resources within the virtual space beginning at 0xF700.000 whose size is 0x0100.0000.
Open Firmware shall operate with the memory management unit enabled so that Open Firmware and its client share a single virtual address space. This binding provides interfaces to allow Open Firmware and its client to ensure that this single virtual address model can be maintained.
Client interface services are invoked essentially as "subroutine" calls to Open Firmware. Hence, the client interface executes in the environment of its client, including any translations that the OS has established (i.e. addresses passed in to the client interface are assumed to be valid virtual addresses within the scope of the OS).
In addition to using existing translations, the Client Interface might require the establishment of new translations (e.g. due to map-in calls during open time), or the removal of old translations (e.g. during map-out calls during close time). Since this requires altering the client's translation resources (e.g. page tables), Open Firmware cannot know how to perform these updates.
The following rules let clients (i.e. target operating systems) know where Open Firmware lives in the address space.
This section describes the processor-related nodes of the device tree of an ARM Open Firmware implementation.
There shall be a node named "cpus" which is a direct child of the root node.
The purpose of this node is to contain other "cpu" nodes and to define an address space by which individual "cpu" nodes can be distinguished from one another. This anticipates the possibility of multi-processor ARM systems in the future.
The numerical representation of a child's address shall be a single binary integer in the range 0 ... N-1, where N is the maximum number of CPUs supported by the system architecture.
The text representation of a child's address shall be the ASCII hexadecimal number corresponding to the numerical representation of the address.
Conversion of the hexadecimal number from text representation to numeric representation shall be case insensitive, and leading zeros shall be permitted but not required.
Conversion from numeric representation to text representation shall use the lower case forms of the hexadecimal digits in the range a...f , suppressing leading zeros.
A processor's "unit-address" (i.e. the first component of its "reg" value) is the interprocessor interrupt destination identifier used by the platform. For a uni-processor platform, the "unit-address" shall be zero.
The following properties shall be created within the "cpus" node.
Standard prop-name to define the number of cells required to represent the physical addresses for the "cpu" nodes (i.e. the children of the "cpus" node).
Each CPU in the system shall have a node describing it as follows.
Standard prop-name to specify the node's addressable resources.
prop-encoded-array: an integer encoded as with encode-int.
The value of this property shall be a one-cell integer representing the interrupt dispatch number that is used to direct inter-processor interrupts to this CPU.
Since the ARM architecture defines the MMU as being part of the processor, the properties defined by Section 3.6.5 of [1] and the following MMU-related properties shall be presented under "cpu" nodes.
Standard property, encoded as with encode-int , that represents the total number of TLB entries in decimal (e.g. 32).
The ARM architecture defines a Harvard-style cache architecture. All of the ARM cache instructions act upon a cache "block" (also referred to as a cache "line"). The internal (also referred to as "L1") caches of ARM processors are represented in the Open Firmware device tree by the following properties contained under "cpu" nodes.
Standard property, encoded as with encode-int , that represents the maximum number of bytes in the write buffer (e.g. 16).
Standard property, encoded as with encode-int , that represents the size of the internal data cache in bytes (e.g. 16384).
Standard property, encoded as with encode-int , that represents the size of a data cache block size, in bytes (e.g. 32).
Standard property, encoded as with encode-int , that represents the number of data cache sets.
d-cache-sets * number-of-ways * d-cache-block-size = d-cache-size
For a fully-associative data cache, d-cache-sets = 1.
For a direct-mapped data cache, d-cache-sets = d-cache-size / d-cache-block-size
Standard property, encoded as with encode-int , that represents the size of the instruction cache in bytes (e.g. 16384).
Standard property, encoded as with encode-int , that represents the size of an instruction cache block in bytes (e.g. 32).
Standard property, encoded as with encode-int , that represents number of instruction cache sets.
i-cache-sets * number-of-ways * i-cache-block-size = i-cache-size
For a fully-associative instruction cache, i-cache-sets = 1.
For a direct-mapped data cache, i-cache-sets = i-cache-size / i-cache-block-size
TBD: Do we need to report which kinds of flush and clean instructions are supported?
In addition to the standard properties defined for this node by [1] , this binding defines the following property.
To aid a client in "taking over" the translation mechanism while still enabling interaction with Open Firmware (via the client interface), the client needs to know the granularity of the virtual address space and what translations have been established by Open Firmware. In addition to the standard properties listed in Section 3.6.5 of [1] , the following standard properties shall exist within the package to which the "mmu" property of the /chosen package refers.
There are no additional methods required beyond those specified in Section 3.6.5 of [1] .
Some systems might include secondary (L2) or tertiary (L3), etc. cache(s). They can be implemented as either Harvard-style or unified. Unlike the L1 properties, that are contained within the "cpu" nodes, the properties of ancillary caches are contained within other device tree nodes.
The following properties define the characteristics of such ancillary caches. These properties shall be contained as a child node of one of the CPU nodes; this is to allow path-name access to the node. All "cpu" nodes that share the same ancillary cache (including the cpu node under which the ancillary cache node is contained) shall contain an "l2-cache" property whose value is the phandle of that ancillary cache node.
Open Firmware Standard property; the device_type of ancillary cache nodes shall be "cache" .
This property, if present, indicates that the cache at this node has a unified organization. Absence of this property indicates that the caches at this node are implemented as separate instruction and data caches.
Standard property, encoded as with encode-int , that represents the total size (in bytes) of the instruction cache at this node.
Standard property, encoded as with encode-int , that represents number of associativity sets of the instruction cache at this node. A value of 1 signifies that the instruction cache is fully associative.
Standard property, encoded as with encode-int , that represents the total size (in bytes) of the data cache at this node.
Standard property, encoded as with encode-int , that represents number of associativity sets of the instruction cache at this node. A value of 1 signifies that the instruction cache is fully associative.
Standard property, encoded as with encode-int , that represents the next level of cache in the memory hierarchy.
Absence of this property indicates that no further levels of cache are present. If present, its value is the phandle of the device node that represents the cache at the next level.
An ARM Open Firmware implementation shall implement a client interface (as defined in Chapter 6 of [1] ) according to the specifications contained within this section.
The default load address is 0xF0000000, the value of load-base . Client programs are assumed to be designed to be loaded at 0xF0000000.
Prior to the first execution of load , the firmware shall allocate and map at least 6 MB of physical memory at this address, unless the hardware configuration of the system makes this impossible. In that case, the firmware shall map as much memory as practical.
An Open Firmware implementation shall recognize the sequence of eight quadlets described below as a valid client program header (as used by the load User Interface command in the core specification) if the a_midmag quadlet contains the specified values. The offsets given below are from the beginning of the loaded image.
The length in bytes of the header plus the text segment in both the file and the execution image. |
|||
The length in bytes of the data segment in both the file and the execution image |
|||
The length in bytes of the bss segment in the execution image. The bss segment is not stored in the file, because its initial contents are always zero. |
|||
The length in bytes of the symbols "section" of the file. (The symbol table in the execution image consists of two "sections", one for the symbols and a second for the strings.1 ) |
|||
The size of the text relocation table. Used only for object files. Contains 0 for executable files. |
|||
The size of the data relocation table. Used only for object files. Contains 0 for executable files. |
The program image immediately follows the header. After recognizing this header, load shall :
If the a_midmag quadlet does not contain the specified value, the behavior of the Open Firmware load command with respect to client program recognition is as follows:
This section defines the "initial program state", the execution environment that exists when the first machine instruction of a client program begins execution. Many aspects of the "initial program state" are established by init-program , which sets the saved-program-state so that subsequent execution of go will begin execution of the client program with the specified environment.
Upon entry to the client program, the following registers shall contain the following values:
pc |
|
psr |
|
|
|
|
F = enabled (if and only if the firmware is using fast interrupts) |
|
|
|
|
sp |
|
r0 |
|
r1,r2 |
|
r2 |
|
r3 |
|
r4 |
|
Client programs shall be invoked with a valid stack pointer ( sp ) with at least 4K bytes of memory available for stack growth. The stack pointer shall be 4-byte aligned.
To invoke a client interface service, a client program:
A typical way of accomplishing this is:
\ First set r1 to Client Interface Handler entry point address, then:
mov r14, pc \ Establish return address pointer
mov pc, r1 \ Load pc with CIF Handler entry point
The client interface handler shall use various CPU registers as described in the following table. The term "preserved" below means that the register shall have the same value when returning as it did when the client interface service was invoked.
The calling program may pass to the client an array of bytes of arbitrary content; if this array is present, its address and length shall be passed in registers r1 and r2 , respectively. For programs booted directly by Open Firmware, the length of this array is zero. Secondary boot programs may use this argument array to pass information to the programs that they boot.
In this section, save-state-and-interact means to save the CPU state to the extent possible, display (if possible) a message indicating that a trap occurred, and return control to the Open Firmware user interface if it is present.
A client program that installs its own trap table entries but wishes to continue using Open Firmware debugging services should preserve the Open Firmware trap table entries for any traps that the client program does not explicitly need to handle.
Open Firmware shall use the following format for its trap table.
0 |
ldr pc, [pc, #56] |
4 |
ldr pc, [pc, #56] |
8 |
|
12 |
|
... |
|
64 |
|
68 |
Typical Open Firmware trap responses are as follows:
save-state-and-interact (Typically Open Firmware runs with these other interrupts disabled.) |
|
save-state-and-interact (but may perform other functions needed for a specific hardware design). |
|
When a client program begins execution, an Open Firmware implementation's use of any virtual address space outside of the ranges 0x0000.0000-0x0000.1000 and 0xF700.0000-0xF7FF.FFFF shall have ceased, except for the virtual address space and associated memory where the client program is loaded (see Section 6.1.2 ). Subsequently, the Open Firmware implementation shall not allocate virtual address space outside those ranges, except as explicitly requested by a client program.
The caches of the processor shall be enabled when the client program is invoked. (As specified by Section 6.1.2 , the I-cache must be consistent with the D-cache for all memory areas occupied by the client program.)
This section describes techniques for handling interrupts when client programs are making active use of Open Firmware client services and device drivers.
Typically, Open Firmware implementations attempt to minimize their use of interrupts, for simplicity and robustness. On many systems, the only Open Firmware feature that demands the use of interrupts is alarm . On some systems, the implementation of get-msecs and sometimes ms also depend upon interrupts. (For the Digital Network Architecture, interrupts are required for all three of those functions, although ms can be implemented reasonably well without interrupts, at least for short durations.)
The only interrupt that is needed for these functions is a periodic timer tick. Relatively few high-level firmware functions depend upon those low-level interrupt-dependent functions. Typically, alarm is used to poll the console input device (usually a keyboard or a serial port) periodically to check for a "break" sequence indicating the user's desire to interrupt the current firmware activity. If the firmware is not receiving a periodic timer tick interrupt, alarm handlers will not be called. The typical result is that the user will be unable to interrupt arbitrary firmware activity from the console input device, but the firmware will be otherwise functional.
The most common uses for get-msecs are network protocol time-outs and device driver time-outs to prevent indefinite "hangs" when waiting for a device to respond. In many cases, when the network is responsive and devices are working correctly, a get-msecs failure (usually caused by the firmware not receiving a periodic timer tick interrupt such that get-msecs always returns the same value) may not have any noticeable effect on overall firmware operation.
Nevertheless, even though most device drivers make scarce use of alarm and get-msecs , it cannot be guaranteed that a particular driver will not require them for a critical function. Therefore, it is prudent for client programs that use Open Firmware services, particularly those that involve I/O, to preserve the delivery of timer tick interrupts to the firmware.
In addition to the list of client interface methods defined in Section 6.3.2 of [1] , the /openprom/client-services node shall contain the following methods.
Resets the system (as with the command reset-all ) in such a way that the firmware, during its subsequent startup sequence, will execute command instead of performing the automatic default boot process. command is a string containing a sequence of user interface commands.
The permissible length of command may depend upon the availability of system resources such as free space in the NVRAM that the firmware uses for storing configuration variables. In the absense of the exhaustion of such resources for other uses, the firmware shall be able to accept command strings of at least 80 characters.
IN: [string] method, phandle, stack-arg1, ..., stack-argP
OUT: catch-result, stack-result1, ..., stack-resultQ
call-method invokes the static device method named method in the package identified by phandle . The N_args -2 arguments associated with method , stack-arg1, ..., stack-argP , are pushed onto the Forth data stack, with stack-arg1 on top of the stack, and method is executed as with the User Interface method $call-method , guarded by catch .
The result returned by catch is returned in catch-result . If catch-result is non-zero (meaning that an error occurred during the execution of method ), the depth of the Forth data stack is restored to its depth prior to the execution of call-method . The values of the elements of the returned values portion of the argument array are undefined.
If catch-result is zero, call-method pops up to K_returns -1 items from the Forth data stack into the returned values portion of the argument array, with stack_result1 corresponding to the top of the stack.
N_args and K_returns are stored in the argument array, and may be different for different calls to call-method . If the number of items J left on the Forth data stack as a result of the execution of method is less than K_returns -1, only stack_result1 ... stack_resultJ are modified; other elements of the returned values portion of the argument array are unaffected. If J is greater than K_returns -1, ( J - Q ) additional items are popped from the Forth data stack after setting stack_result1 ... stack_resultQ , so that, in all cases, the execution of call-method results in no net change to the depth of the Forth data stack.
A compliant Open Firmware implementation must allow at least six stack_arg and six stack_result items.
The behavior of call-static-method is undefined if method is not a static method.
If a client program takes control of timer interrupts or memory management, but needs to continue using Open Firmware client services thereafter, the client program must register a callback routine that supplies services that the firmware can use to perform the functions that the client program has subsumed.
The following subsections define those callback services.
The callback mechanism must operate in accordance with the specifications for callback , $callback , and set-callback in [1]. In particular, the callback mechanism operates in a fashion very similar to the client interface handler, except in the other direction (the firmware calls the client, instead of the client calling the firmware). The client program first invokes the set-callback client service to inform the firmware of the address of the callback handler routine. Subsequently, the firmware constructs an "argument array" and calls the callback handler routine, passing the address of the argument array as an argument (in r0 for the ARM processor).
Several of the callback services defined below refer to the system-dependent MMU page size. For the ARM processor, that page size is 4096 bytes. Under some circumstances, the ARM MMU can deal with finer granularity than one page; specifically, it can apply a different protection to each of the four 1K sub-pages of a page. The MMU-related callback services defined below do not support sub-page granularity; all operations are performed in units of one page.
IN: [address] phys, [address] virt, size, mode
This callback service creates an address translation associating the region of virtual address space of size size beginning at the virtual address virt with the region of physical address of the same size beginning at the physical address phys .
mode specifies the values for the "AP" fields and the "C" and "B" bits of a page table entry. A page table entry is encoded as follows:
0000.0000.0000.0000.0000.AP0d.ddd0.CB00
The fields and bits shown above are in accordance with the ARM Memory Management Unit Architecture definition in [2] .
The indicated access permissions apply to the entire range specified by the arguments to map , which implies that the implementation of map must propagate the AP bits into each of the AP[0-3] sub-page access permission fields of any second-level descriptors that are used to accomplish the translation.
The firmware must specify domain 0 for any mode arguments that it generates internally, and must preserve the domain field unchanged for any mode value that it receives as the return value from an invocation of the translate callback and subsequently passes as an argument to the map callback.
The implementation of map may use any combination of first-level and second-level descriptors to accomplish its function, subject to the restriction that it must faithfully establish the requested translation without changing any other extant translations that are outside the requested range.
The virt , phys , and size arguments that the caller passes to this service must be multiples of the system-dependent MMU page size.
The return value error shall be zero if the operation succeeded, or a system-specific non-zero error code otherwise.
This callback service removes any address translation currently associated with the region of virtual address space of size size beginning at the virtual address virt . Typically, this involves setting the address translation for that virtual region to a system-specific "invalid" or "not mapped" state.
The virt and size arguments that the caller passes to this service must be multiples of the system-dependent MMU page size.
OUT: throw-code, error, [address] phys, mode
This callback service returns information about the address translation currently associated with the virtual address virt . If there is currently no valid translation for that virtual address, the error return value shall be a system-specific non-zero error code and the number of return values (as indicated by the N_returns cell of the argument array) shall be two. Otherwise, error shall be zero, the number of return values shall be four, phys shall be the physical address to which virt is translated, and mode shall specify the values for the "AP" fields and the "C" and "B" bits of a page table entry as described above under map .
The value returned in the mode result shall reflect the domain signified by the first-level descriptor and the access permissions signified by either the section descriptor (if the virtual address is mapped by a section descriptor) or the first sub-page (AP0) (if the virtual address is mapped by a second-level descriptor).
The firmware must specify domain 0 for any mode arguments that it generates internally, and must preserve the domain field unchanged for any mode value that it receives as the return value from an invocation of the translate callback and subsequently passes as an argument to the map callback.
The virt argument that the caller passes to this service must be a multiple of the system-dependent MMU page size.
IN: [address] min_addr, [address] max_addr, size, align
OUT: throw-code, error, [address] phys_addr
This callback service allocates consecutive pages of physical RAM subject to the following constraints:
The beginning address of the first page shall be (using unsigned comparison) greater than or equal to min_addr and less than or equal to max_addr .
The beginning address of the first page shall be a multiple of the value of align . The value of align passed to this callback must be a multiple of the system-dependent MMU page size.
The size of the region shall be size bytes. The value of size passed to this callback must be a multiple of the system-dependent MMU page size.
The pages shall be at consecutive addresses.
The region shall not span the boundary between the maximum unsigned number and zero.
If the allocation fails, the error return value shall be a system-dependent non-zero error code and the number of return values (as indicated by the N_returns cell of the argument array) shall be two. Otherwise, error shall be zero, the number of return values shall be three, and phys_addr shall be the physical address of the beginning of the first allocated page.
There are three general possibilities for the min_addr and max_addr arguments:
min_addr = 0, max_addr = <maximum unsigned integer>
In this case, the firmware places no constraints on the address range of the return value; it is willing to accept any physical memory that meets the alignment constraints. (This is the usual case.)
In this case, the firmware is requesting the allocation of a specific range of physical memory. This case is rarely used; typically, when the firmware needs to use a specific page or pages of RAM, it claims that RAM prior to the time that the client program takes control of memory allocation. This callback is used to implement the firmware "/memory" node claim method, and it is possible that a user or program might attempt to claim a specific physical page, so this case is defined. It is of course possible that it may not be possible to satisfy such a request, in which case the callback would return an error code.
If min_addr = max_addr , they must be multiples of align , otherwise it would not be possible to simultaneously satisfy both the alignment and range constraints.
If min_addr and max_addr differ, but min_addr is not zero or max_addr is not the maximum unsigned integer, then the firmware is requesting the allocation of physical memory somewhere within a particular address range. The most common use of this case is for DMA-based I/O devices that cannot access arbitrary addresses. For example, in systems with bus-mastering ISA devices, there is often no way for those devices to supply DMA addresses outside the range 0 to 16 MBytes. Typically, the firmware uses this form of constrained physical allocation only for such cases.
Since the definition of this callback service specifies that the constraint applies only to the beginning address of the first page of allocated memory, if the entire allocated range must fall within a certain region, the firmware must be careful to supply a value for max_addr such that the value of max_addr + size does not extend beyond the end of the desired region.
Free consecutive pages of physical RAM, making it available for later use. The size of the region to be freed is given by size . The phys_addr and size arguments passed to this callback must be multiples of the system-dependent MMU page size. The physical RAM within the region to be freed must either have been previously allocated by claim-phys or have already been "owned" by the firmware at the time that the client program took control of physical memory allocation.
IN: [address] min_addr, [address] max_addr, size, align
OUT: throw-code, error, [address] virt_addr
This callback service allocates consecutive page frames of virtual address space subject to the following constraints:
The beginning address of the first page frame shall be (using unsigned comparison) greater than or equal to min_addr and less than or equal to max_addr .
The beginning address of the first page frame shall be a multiple of the value of align . The value of align passed to this callback must be a multiple of the system-dependent MMU page size.
The size of the region shall be size bytes. The value of size passed to this callback must be a multiple of the system-dependent MMU page size.
The pages frames shall be at consecutive addresses.
The region shall not span the boundary between the maximum unsigned number and zero.
If the allocation fails, the error return value shall be a system-dependent non-zero error code and the number of return values (as indicated by the N_returns cell of the argument array) shall be two. Otherwise, error shall be zero, the number of return values shall be three, and virt_addr shall be the virtual address of the beginning of the first allocated page frame.
There are three general possibilities for the min_addr and max_addr arguments:
min_addr = 0, max_addr = <maximum unsigned integer>
In this case, the firmware places no constraints on the address range of the return value; it is willing to accept any physical address that meets the alignment constraints. (This is the usual case.)
In this case, the firmware is requesting the allocation of a specific virtual address. This case is rarely used; typically, when the firmware needs to use to a specific virtual address, it claims that virtual address prior to the time that the client program takes control of address allocation. This callback is used to implement the firmware "/mmu" node claim method, and it is possible that a user or program might attempt to claim a specific virtual address, so this case is defined. It is of course possible that it may not be possible to satisfy such a request, in which case the callback would return an error code.
If min_addr = max_addr , they must be multiples of align , otherwise it would not be possible to simultaneously satisfy both the alignment and range constraints.
If min_addr and max_addr differ, but min_addr is not zero or max_addr is not the maximum unsigned integer, then the firmware is requesting the allocation of virtual address space somewhere within a particular address range. The most common use of this case is for DMA-based I/O devices that cannot access arbitrary addresses when used on a system with virtually-addressed DMA. For example, some DMA devices drive some number of high-order address lines to fixed values, so on a virtual-DMA system, the DMA addresses for those devices must be taken from a specific region. Typically, the firmware uses this form of constrained physical allocation only for such cases.
Since the definition of this callback service specifies that the constraint applies only to the beginning address of the first page of allocated memory, if the entire allocated range must fall within a certain region, the firmware must be careful to supply a value for max_addr such that the value of max_addr + size does not extend beyond the end of the desired region.
Free consecutive page frames of virtual address space, making it available for later use. The size of the region to be freed is given by size . The values virt_addr and size passed to this callback must be multiples of the system-dependent MMU page size.
The virtual address space within the region to be freed must either have been previously allocated by claim-virt or have already been "owned" by the firmware at the time that the client program took control of virtual address space allocation.
This callback service notifies the client program each time that the firmware handles a timer tick interrupt, giving the client program a chance to schedule or perform periodic operations based upon that tick.
If the client program has registered a callback handler, the firmware shall attempt to invoke the tick callback as part of the process of handling a timer tick interrupt. (Open Firmware typically uses timer tick interrupts to implement the alarm and get-msecs features). If the client program does not implement the tick callback, the throw-code result will be non-zero (according to the usual semantics of client callbacks), in which case the firmware shall proceed with the rest of its timer tick handling process as though the callback had not been attempted.
The firmware shall invoke the tick callback in IRQ mode with interrupts disabled.
intsave is the address of a 260-byte array of memory that is used to pass to and from the client program the values of certain processor registers as they existed just prior to the occurrence of the tick interrupt. The firmware shall set the contents of the array as follows, prior to invoking the tick callback. Each array entry is a 32-bit little-endian integer representing the saved value of an ARM CPU register.
0 |
|
4 |
|
8 |
|
12 |
|
16 |
|
... |
|
56 |
|
60 |
|
64 |
For "banked" registers (registers for which the ARM processor has multiple copies for different modes), the saved register values shall be for the register set corresponding to the mode indicated in the saved PSR value.
After the tick callback returns, the firmware shall proceed with the rest of its timer tick handling process, and upon completion shall restore the state of the CPU registers to the values contained in the intsave array. The client program's tick callback handler may alter the contents of intsave in order to cause the firmware to restore the register state to a state that differs from the state that existed when the timer tick occurred.
The client program's tick callback handler must not enable interrupts during its execution, but may, by modifying the PSR value in the intsave array, cause a delayed change in the interrupt enabled/disabled state that will take effect upon completion of the firmware's timer tick handler.
The client program's tick callback handler must not invoke any Open Firmware client services during its execution. If Open Firmware client services need to be invoked as a result of timer ticks, the appropriate way to do so is for the client program to use the tick callback handler to schedule those activities for execution after the firmware's tick handler completes (typically by modifying the intsave array).
An implementation of Open Firmware for ARM shall conform to the core requirements as specified in [1] and the following ARM-specific extensions.
The following user interface commands represent ARM registers within the saved program state. Executing the command returns the saved value of the corresponding register. The saved value may be set by preceding the command with to; the actual registers are restored to the saved values when go is executed.
The following command displays the ARM CPU's saved program state.