Document revision date: 30 March 2001

## OpenVMS Alpha Guide to Upgrading Privileged-Code Applications

Previous | Contents | Index

## B.5 EXE_STD$MODIFY, EXE_STD$READ, EXE_STD$WRITE

The routines EXE_STD$MODIFY, EXE_STD$READ, and EXE_STD$WRITE are upper-level FDT routines, so their interfaces remain unchanged:

    int exe_std$modify (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)
    int exe_std$read   (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)
    int exe_std$write  (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)

These routines obtain the address of the caller's buffer from `irp->irp$l_qio_p1` . These routines have been modified to obtain the full 64-bit buffer address from `irp->irp$q_qio_p1` and pass it to EXE_STD$READLOCK or EXE_STD$WRITELOCK. Note, however, that the buffer size remains a longword and is obtained from `irp->irp$l_qio_p2` without checking the upper 32-bits.

## B.6 EXE_STD$MODIFYLOCK, EXE_STD$READLOCK, EXE_STD$WRITELOCK

The routines EXE_STD$MODIFYLOCK, EXE_STD$READLOCK, and EXE_STD$WRITELOCK are FDT support routines that:

- Probe the accessibility of a specified buffer by the mode contained in `irp->irp$b_mode`
- Lock the buffer into memory if the probe succeeds
- Return the address of the first PTE that maps the buffer in `irp->irp$l_svapte`

If an error is encountered, an optional error callback routine is invoked and the I/O request is aborted. If the entire buffer is not resident then the I/O request is backed out and a special status is returned to request a pagefault of the needed page.

In releases prior to OpenVMS Alpha Version 7.0, the interfaces for these routines were:

    int exe_std$modifylock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb,
                            void *buf, int bufsiz, void (*err_rout)(...))
    int exe_std$readlock   (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb,
                            void *buf, int bufsiz, void (*err_rout)(...))
    int exe_std$writelock  (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb,
                            void *buf, int bufsiz, void (*err_rout)(...))

The new interfaces for these routines are:

    int exe_std$modifylock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb,
                            VOID_PQ buf, int bufsiz [, void (*err_rout)(...)] )
    int exe_std$readlock   (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb,
                            VOID_PQ buf, int bufsiz [, void (*err_rout)(...)] )
    int exe_std$writelock  (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb,
                            VOID_PQ buf, int bufsiz [, void (*err_rout)(...)] )

There are two differences in the new OpenVMS Alpha Version 7.0 interfaces:

1. These functions now use the full 64-bits of the buffer address `buf` that is passed by value.
   Previously, the buffer address was a 32-bit value that was sign-extended into a 64-bit parameter value.
2. It is possible to omit the `err_rout` parameter. Currently, one can pass in the value 0 to specify that there is no error routine.
   The new interface supports either method of specifying that there is no error routine. Because many callers do not require an error routine, this allows them to call these routines more efficiently with six parameters.

Both of these interface changes are upwardly compatible.

### B.6.1 CALL_xLOCK and CALL_xLOCK_ERR Macros

There are six MACRO-32 macros that facilitate the use of the routines described in Section B.6 by code that was originally written to use the JSB-interface counterparts for these routines. These macros have implicit register inputs and outputs that correspond to the register inputs and outputs of the JSB-interface routines.

The CALL_MODIFYLOCK, CALL_READLOCK, and CALL_WRITELOCK macros have been modified to pass the full 64-bits of R0 as the buffer address and to omit the optional error routine parameter instead of passing the value 0.

The CALL_MODIFYLOCK_ERR, CALL_READLOCK_ERR, and CALL_WRITELOCK_ERR macros have been modified to pass the full 64-bits of R0 as the buffer address.

This is an upwardly compatible change to the implementation of these macros. This change is transparent to users prior to OpenVMS Alpha Version 7.0, because R0 currently contains the 32-bit buffer address sign-extended to 64-bits.

## B.7 EXE_STD$READCHK and EXE_STD$WRITECHK

The routines EXE_STD$READCHK and EXE_STD$WRITECHK probe the accessibility of a specified buffer by the mode contained in `irp->irp$b_mode` .

In releases prior to OpenVMS Alpha Version 7.0, the interfaces for these routines were:

    int exe_std$readchk  (IRP *irp, PCB *pcb, UCB *ucb, void *buf, int bufsiz)
    int exe_std$writechk (IRP *irp, PCB *pcb, UCB *ucb, void *buf, int bufsiz)

As of OpenVMS Alpha Version 7.0, the new interfaces for these routines are:

    int exe_std$readchk  (IRP *irp, PCB *pcb, UCB *ucb, VOID_PQ buf, int bufsiz)
    int exe_std$writechk (IRP *irp, PCB *pcb, UCB *ucb, VOID_PQ buf, int bufsiz)

The only difference in the new interface is that these functions now use the full 64-bits of the buffer address `buf` that is passed by value. Previously, the buffer address was a 32-bit value sign-extended into a 64-bit parameter value. Thus, this is an upward compatible change to the interface.

### B.7.1 CALL_xCHK and CALL_xCHKR Macros

The CALL_READCHK, CALL_READCHKR, CALL_WRITECHK, and CALL_WRITECHKR MACRO-32 macros have been modified to pass the full 64-bits of the buffer address in a similar fashion as described in Section B.6.1.

## B.8 EXE_STD$SETCHAR and EXE_STD$SETMODE

The routines EXE_STD$SETCHAR and EXE_STD$SETMODE are upper-level FDT routines, thus their interfaces remain unchanged:

    int exe_std$setchar (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)
    int exe_std$setmode (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)

Both of these routines use the local routine CHECK_SET to obtain and validate a pointer to the caller's buffer from `irp->irp$l_qio_p1` . The routine CHECK_SET has been modified to obtain the full 64-bit buffer address from `irp->irp$q_qio_p1` . Routines EXE_STD$SETCHAR and EXE_STD$SETMODE has been modified to use the 64-bit pointer returned by CHECK_SET when loading the UCB characteristics from the caller's buffer.

## B.9 IOC_STD$CREATE_DIOBM

Routine IOC_STD$CREATE_DIOBM is a new routine that is used to derive a 32-bit system virtual address for a specific number of PTEs that are pointed to by a 64-bit process virtual address. This routine allocates a "primary" DIOBM structure of sufficient size for its needs and returns a pointer to it. When the derived 32-bit system virtual address is no longer required the DIOBM must be released by calling the IOC_STD$RELEASE_DIOBM routine.

The algorithm used by this routine is very similar to the one used by IOC_STD$FILL_DIOBM as described in Section B.10. The significant difference is that IOC_STD$CREATE_DIOBM allocates a sufficiently sized primary DIOBM structure for its needs and does not depend on a preallocated fixed-size DIOBM. This routine is designed for previous users of the MMG$IOLOCK routine that do not have an embedded DIOBM to work with, but can maintain a single pointer to the external DIOBM structure that is returned by IOC_STD$CREATE_DIOBM.

The interface for IOC_STD$CREATE_DIOBM is:

    int ioc_std$create_diobm (const PTE_PQ va_pte, const uint32 pte_count,
                              const uint32 flags,
                              PTE **svapte_p, DIOBM **diobm_p)

Table B-7 summarizes the use of the arguments.

Table B-7 IOC_STD$CREATE_DIOBM Arguments
Argument | Type | Access | Description
--- | --- | --- | ---
va_pte | PTE_PQ | Input | A 64-bit pointer to the first PTE that maps the user buffer.
pte_count | uint32 | Input | Number of PTEs that are required to map the entire buffer.
svapte_p | PTE ** | Output | Pointer to a 32-bit PTE address that is returned. The returned address is always a 32-bit system virtual address.
flags | uint32 | Input | Option flags. The following bit mask values can be set: DIOBM$M_NORESWAIT - Disable resource wait. All other option bits must be zero.
diobm_p | DIOBM ** | Output | Pointer to DIOBM address that is returned.

This routine requires system resources, nonpaged pool and possibly SPTEs. If there are insufficient resources, this routine will, by default, place the process (kernel thread) in a kernel mode wait state for nonpaged pool and try again until it succeeds. In this case, the return value of this routine is always SS$_NORMAL because it will not return until it can do so successfully.

However, the caller can inhibit this resource wait by setting the DIOBM$M_NORESWAIT option in the flags parameter. When this is done an error status is returned to the caller if there are insufficient system resources. This capability is intended to be used in contexts where either a resource wait in kernel mode is not acceptable or the caller can readily put the process into a wait state in the requestor's mode.

This routine must be called in process context and assumes that it was called at IPL 2, or minimally, that it can lower IPL to 2.

The use of the DIOBM structure by this routine is described in detail in Appendix A.

This routine is coded in C and is contained in the new DIOBM.C module.

## B.10 IOC_STD$FILL_DIOBM

Routine IOC_STD$FILL_DIOBM is a new routine that is used to derive a 32-bit system virtual address for a specific number of PTEs that are pointed to by a 64-bit process virtual address. This routine employs a previously allocated or embedded "primary" DIOBM structure that must be supplied as one of its inputs. When the derived 32-bit system virtual address is no longer required, the DIOBM must be released by calling the IOC_STD$RELEASE_DIOBM routine.

This routine derives a 32-bit system virtual address for the PTEs using one of the following methods:

1. If the PTEs are in the region of the page table space that maps S0/S1 space, a 32-bit PTE address using the SPT window is returned.
2. If less than or equal to DIOBM$K_PTECNT_FIX PTEs are required, the PTEs are copied into the PTE vector in the DIOBM and the 32-bit system virtual address of the PTE vector in the DIOBM is returned.
3. If more than DIOBM$K_PTECNT_FIX and less than or equal to `ioc$gl_diobm_ptecnt_max` PTEs are required, a secondary DIOBM is allocated, the PTEs are copied into the PTE vector in the secondary DIOBM, and the 32-bit system virtual address of the PTE vector in the secondary DIOBM is returned.
4. If more than `ioc$gl_diobm_ptecnt_max` PTEs are required, a temporary PTE window in S0/S1 space is created that maps the neccessary process level-3 page table pages. These level-3 page table pages are locked into memory and the 32-bit S0/S1 address of the PTEs through the PTE window is returned.

The interface for IOC_STD$FILL_DIOBM is:

    int ioc_std$fill_diobm (DIOBM *const diobm, const PTE_PQ va_pte,
                            const uint32 pte_count, const uint32 flags,
                            PTE **svapte_p)

Table B-8 summarizes the use of the arguments.

Table B-8 IOC_STD$FILL_DIOBM Arguments
Argument | Type | Access | Description
--- | --- | --- | ---
diobm | DIOBM * | Input | Pointer to a previously allocated but unused or uninitialized DIOBM structure.
va_pte | PTE_PQ | Input | A 64-bit pointer to the first PTE that maps the user buffer.
pte_count | uint32 | Input | Number of PTEs that are required to map the entire buffer.
flags | uint32 | Input | Option flags. The following bit mask values can be set: DIOBM$M_NORESWAIT - Disable resource wait. All other option bits must be zero.
svapte_p | PTE ** | Output | Pointer to a 32-bit PTE address that is returned. The returned address is always a 32-bit system virtual address.

This routine may require system resources, either nonpaged pool or SPTEs, depending on the number of PTEs that are required to map the buffer. If there are insufficient resources this routine will, by default, place the process (kernel thread) in a kernel mode wait state for nonpaged pool and try again until it succeeds. In this case, the return value of this routine is always SS$_NORMAL because it will not return until it can do so successfully.

However, the caller can inhibit this resource wait by setting the DIOBM$M_NORESWAIT option in the flags parameter. When this is done, an error status is returned to the caller if there are insufficient system resources. This capability is intended to be used in contexts where either a resource wait in kernel mode is not acceptable or the caller can readily put the process into a wait state in the requestor's mode.

This routine must be called in process context and assumes that it was called at IPL 2, or minimally that it can lower IPL to 2.

The use of the DIOBM structure by this routine is described in detail in Appendix A. The normal version of the IOC_STD$FILL_DIOBM routine makes no assumptions about the contents of the input DIOBM structure. In contrast, the full checking version of this routine in the IO_ROUTINES_MON.EXE execlet performs some initial validation and declares an INCONSTATE bugcheck should this check fail.

## B.11 IOC_STD$PTETOPFN

The routine IOC_STD$PTETOPFN allows drivers or other components to obtain the PFN for a page that has been previously locked into memory but the valid bit in its PTE is currently clear. This routine handles transition PTEs and PTEs that have reverted into GPTX format.

In releases prior to OpenVMS Alpha Version 7.0, the interface for this routine was:

    int ioc_std$ptetopfn (PTE *pte);

The new interface for this routine is:

    int ioc_std$ptetopfn (PTE_PQ pte);

The first interface difference is that IOC_STD$PTETOPFN uses the full 64-bits of the caller's PTE address that is passed by value. The second interface difference is not apparent from the above function prototype. The IOC_STD$PTETOPFN routine has been enhanced to handle the case where the `pte$v_valid` bit is set in the PTE. Therefore, drivers can use this routine without first checking the valid bit.

Both of these are upwardly compatible changes to the interface.

## B.12 IOC_STD$RELEASE_DIOBM

Routine IOC_STD$RELEASE_DIOBM is a new routine that is used to release the PTE mapping resources that were set up by a prior call to either the IOC_STD$CREATE_DIOBM or IOC_STD$FILL_DIOBM routines.

The interface for IOC_STD$RELEASE_DIOBM is:

    int ioc_std$release_diobm (DIOBM *const diobm)

Table B-9 summarizes the use of the arguments.

Table B-9 IOC_STD$RELEASE_DIOBM Arguments
Argument | Type | Access | Description
--- | --- | --- | ---
diobm | DIOBM * | Input | Pointer to an active primary DIOBM.

This routine deallocates any secondary DIOBM that is connected to the primary DIOBM. If this primary DIOBM has a PTE window, the resources used for the window are deallocated. If the primary DIOBM was allocated by IOC_STD$CREATE_DIOBM, the primary DIOBM is deallocated as well. The use of the DIOBM structure by this routine is described in detail in Appendix A.

The returned value of this routine is always SS$_NORMAL.

This routine does not depend on process context. However, the IPL and spinlocks of the caller must allow this routine to acquire and restore the MMG spinlock.

This routine is coded in C and is contained in the new DIOBM.C module.

## B.13 IOC_STD$SIMREQCOM, IOC$SIMREQCOM

The routine IOC_STD$SIMREQCOM allows drivers or other components to complete an I/O that does not have a normal IRP associated with it. Because this routine does not have an IRP, the necessary information to signal an I/O completion is passed directly in separate parameters. For example, the user's IOSB address, the event flag value, a pointer to an ACB, and the caller's access mode are among the parameters.

In releases prior to OpenVMS Alpha Version 7.0, the interface for this routine was:

    int ioc_std$simreqcom (int32 iosb[2], int pri, int efn, int32 iost[2],
                           ACB *acb, int acmode);

The new interface for this routine is:

    int ioc_std$simreqcom (VOID_PQ iosb_p, int pri, int efn, int32 iost[2],
                           ACB *acb, int acmode);

The first interface difference is that IOC_STD$SIMREQCOM uses the full 64-bits of the caller's IOSB address `iosb_p` that is passed by value. The second interface difference is not apparent from the above function prototype. The IOC_STD$SIMREQCOM routine has been enhanced to accept either a pointer to an ACB64 or an ACB structure.

Both of these are upwardly compatible changes to the interface.

### B.13.1 CALL_SIMREQCOM Macro

The CALL_SIMREQCOM MACRO-32 macro facilitates the use of the IOC_STD$SIMREQCOM routine by code that was originally written to use the JSB-interface counterpart IOC$SIMREQCOM. The CALL_SIMREQCOM macro has implicit register inputs that correspond to the register inputs of the JSB-interface for the IOC$SIMREQCOM routine.

Because this macro uses registers for its inputs, it can be altered to use the full 64-bit value of the caller's IOSB address which is passed in register R1.

### B.13.2 IOC$SIMREQCOM

The IOC$SIMREQCOM routine is simply a JSB-to-CALL jacket routine around IOC_STD$SIMREQCOM. Because it is implemented through the use of the CALL_SIMREQCOM macro, IOC$SIMREQCOM transparently supports a 64-bit caller's IOSB address in the R1 parameter. Similarly, this routine allows R5 to point to either an ACB or an ACB64 structure.

## B.14 IOC_STD$SVAPTE_IN_BUF

Routine IOC_STD$SVAPTE_IN_BUF is a new routine that is used to calculate a 32-bit PTE address for a virtual address within a buffer that has been previously locked for this IRP and for which a 32-bit PTE address has been derived.

It is the caller's responsibility to ensure that the virtual address is a legal address within a buffer that has been locked into memory prior to calling this routine and that a 32-bit PTE address has been derived for this buffer. The IOC_STD$SVAPTE_IN_BUF routine may declare a bugcheck if either of these conditions have not been met.

The interface for IOC_STD$SVAPTE_IN_BUF is:

    int ioc_std$svapte_in_buf (IRP *irp, VOID_PQ va, PTE **svapte_p)

Table B-10 summarizes the use of the arguments.

Table B-10 IOC_STD$SVAPTE_IN_BUF Arguments
Argument | Type | Access | Description
--- | --- | --- | ---
irp | IRP * | Input | Pointer to the current IRP.
va | VOID_PQ | Input | Virtual address within the buffer that was locked for this IRP.
svapte_p | PTE ** | Output | Pointer to a 32-bit PTE address that is returned. The returned address is a 32-bit system virtual address that is derived based on the values in irp$l_svapte and irp$q_qio_p1.

Table B-11 lists all the implicit inputs that are used by this routine.

Table B-11 IOC_STD$SVAPTE_IN_BUF Implicit Inputs
Field | Use
--- | ---
irp$q_qio_p1 | Virtual address of the start of the buffer that has been previously locked into memory for this IRP.
irp$l_svapte | 32-bit PTE address for the PTEs that map the buffer.

The returned value of this routine is always SS$_NORMAL.

This routine is coded in C and is contained in the new SVAPTE2.C module.

Previous | Next | Contents | Index

| privacy and legal statement |
6466PRO_009.HTML