VirtualBox

Changeset 80306 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Aug 15, 2019 6:45:06 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132764
Message:

Storage/DevVirtioSCSI.cpp: Implemented interrupt handling and check/improved nuanced spec'd handling of EVENT_IDX mode, notification, device reset, added client/framework interface and other cleanup (see bugref:9440 Comment 51)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r80240 r80306  
    4444#include "VBoxDD.h"
    4545
    46 #define VIRTIOSCSI_MAX_TARGETS                      1            /**< Can probably determined from higher layers     */
    4746
    4847/**
     
    6261 */
    6362#define VIRTIOSCSI_REQ_QUEUE_CNT                    1            /**< Number of req queues exposed by dev.            */
     63#define VIRTIOSCSI_MAX_TARGETS                      1           /**< Can probably determined from higher layers      */
     64#define VIRTIOSCSI_MAX_LUN                          16383        /* < VirtIO specification, section 5.6.4             */
     65#define VIRTIOSCSI_MAX_COMMANDS_PER_LUN             64           /* < T.B.D. What is a good value for this?           */
     66#define VIRTIOSCSI_MAX_SEG_COUNT                    1024         /* < T.B.D. What is a good value for this?           */
     67#define VIRTIOSCSI_MAX_SECTORS_HINT                 0x10000      /* < VirtIO specification, section 5.6.4             */
     68#define VIRTIOSCSI_MAX_CHANNEL_HINT                 0            /* < VirtIO specification, section 5.6.4             */
    6469#define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01         /**< SSM version #                                   */
     70
    6571#define PCI_DEVICE_ID_VIRTIOSCSI_HOST               0x1048       /**< Informs guest driver of type of VirtIO device   */
    6672#define PCI_CLASS_BASE_MASS_STORAGE                 0x01         /**< PCI Mass Storage device class                   */
     
    106112typedef struct virtio_scsi_ctrl
    107113{
    108     uint32_t type;                                              /**< type                                             */
    109     uint8_t  response;                                          /**< response                                         */
     114    uint32_t type;                                               /**< type                                            */
     115    uint8_t  response;                                           /**< response                                        */
    110116} VIRTIO_SCSI_CTRL_T, *PVIRTIO_SCSI_CTRL_T;
    111117
     
    113119 * @name VirtIO 1.0 SCSI Host Device device specific control types
    114120 * @{  */
    115 #define VIRTIOSCSI_T_NO_EVENT                   0
    116 #define VIRTIOSCSI_T_TRANSPORT_RESET            1
    117 #define VIRTIOSCSI_T_ASYNC_NOTIFY               2              /**< Asynchronous notification                         */
    118 #define VIRTIOSCSI_T_PARAM_CHANGE               3
     121#define VIRTIOSCSI_T_NO_EVENT                       0
     122#define VIRTIOSCSI_T_TRANSPORT_RESET                1
     123#define VIRTIOSCSI_T_ASYNC_NOTIFY                   2           /**< Asynchronous notification                       */
     124#define VIRTIOSCSI_T_PARAM_CHANGE                   3
    119125/** @} */
    120126
     
    125131typedef struct virtio_scsi_event {
    126132    // Device-writable part
    127     uint32_t uEvent;                                           /**< event:                                           */
    128     uint8_t  uLUN[8];                                          /**< lun                                              */
    129     uint32_t uReason;                                          /**< reason                                           */
     133    uint32_t uEvent;                                            /**< event:                                          */
     134    uint8_t  uLUN[8];                                           /**< lun                                             */
     135    uint32_t uReason;                                           /**< reason                                          */
    130136} VIRTIO_SCSI_EVENT_T, *PVIRTIO_SCSI_EVENT_T;
    131137
     
    133139 * @name VirtIO 1.0 SCSI Host Device device specific event types
    134140 * @{  */
    135 #define VIRTIOSCSI_EVT_RESET_HARD               0              /**<                                                  */
    136 #define VIRTIOSCSI_EVT_RESET_RESCAN             1              /**<                                                  */
    137 #define VIRTIOSCSI_EVT_RESET_REMOVED            2              /**<                                                  */
     141#define VIRTIOSCSI_EVT_RESET_HARD                   0           /**<                                                 */
     142#define VIRTIOSCSI_EVT_RESET_RESCAN                 1           /**<                                                 */
     143#define VIRTIOSCSI_EVT_RESET_REMOVED                2           /**<                                                 */
    138144/** @} */
    139145
     
    143149 * The following struct is described in VirtIO 1.0 Specification, section 5.6.6.1
    144150 */
    145 #define CDB_SIZE                                 32             /**< Mandated by VirtIO 1.0 spec section 5.6.6.1     */
    146 #define SENSE_SIZE                               96             /**< See section VirtIO 1.0, section 5.6.4           */
    147 #define PI_BYTES_IN                              1              /**< Value TBD (see section 5.6.6.1)                 */
    148 #define PI_BYTES_OUT                             1              /**< Value TBD (see section 5.6.6.1)                 */
    149 #define DATA_OUT                                512             /**< Value TBD (see section 5.6.6.1)                 */
     151#define VIRTIOSCSI_SENSE_SIZE_DEFAULT               96          /**< VirtIO 1.0: 96 on reset, guest can change       */
     152#define VIRTIOSCSI_CDB_SIZE_DEFAULT                 32          /**< VirtIO 1.0: 32 on reset, guest can change       */
     153#define VIRTIOSCSI_PI_BYTES_IN                      1           /**< Value TBD (see section 5.6.6.1)                 */
     154#define VIRTIOSCSI_PI_BYTES_OUT                     1           /**< Value TBD (see section 5.6.6.1)                 */
     155#define VIRTIOSCSI_DATA_OUT                         512         /**< Value TBD (see section 5.6.6.1)                 */
    150156
    151157typedef struct virtio_scsi_req_cmd
     
    157163    uint8_t  uPrio;                                             /**< prio                                            */
    158164    uint8_t  uCrn;                                              /**< crn                                             */
    159     uint8_t  uCdb[CDB_SIZE];                                    /**< cdb              VirtIO 1.0 mandates 32-bytes   */
     165    uint8_t  uCdb[VIRTIOSCSI_CDB_SIZE_DEFAULT];                 /**< cdb              VirtIO 1.0 mandates 32-bytes   */
    160166
    161167    /** Following three fields only present if VIRTIOSCSI_F_T10_PI negotiated */
     
    163169    uint32_t uPiBytesOut;                                       /**< pi_bytesout                                     */
    164170    uint32_t uPiBytesIn;                                        /**< pi_bytesin                                      */
    165     uint8_t  uPiOut[PI_BYTES_OUT];                              /**< pi_out[]        TBD                             */
    166 
    167     uint8_t  uDataOut[DATA_OUT];                                /**< dataout                                         */
     171    uint8_t  uPiOut[VIRTIOSCSI_PI_BYTES_OUT];                   /**< pi_out[]        TBD                             */
     172
     173    uint8_t  uDataOut[VIRTIOSCSI_DATA_OUT];                     /**< dataout                                         */
    168174
    169175    /* Device-writable part */
     
    173179    uint8_t  uStatus;                                           /**< status                                          */
    174180    uint8_t  uResponse;                                         /**< response                                        */
    175     uint8_t  uSense[SENSE_SIZE];                                /**< sense                                           */
     181    uint8_t  uSense[VIRTIOSCSI_SENSE_SIZE_DEFAULT];             /**< sense                                           */
    176182
    177183    /** Following two fields only present if VIRTIOSCSI_F_T10_PI negotiated */
    178     uint8_t  uPiIn[PI_BYTES_IN];                                /**< pi_in[]                                         */
     184    uint8_t  uPiIn[VIRTIOSCSI_PI_BYTES_IN];                     /**< pi_in[]                                         */
    179185    uint8_t  uDataIn[];                                         /**< detain;                                         */
    180186} VIRTIO_SCSI_REQ_CMD_T, *PVIRTIO_SCSI_REQ_CMD_T;
     
    183189 * @name VirtIO 1.0 SCSI Host Device Req command-specific response values
    184190 * @{  */
    185 #define VIRTIOSCSI_S_OK                            0           /**< control, command                                 */
    186 #define VIRTIOSCSI_S_OVERRUN                       1           /**< control                                          */
    187 #define VIRTIOSCSI_S_ABORTED                       2           /**< control                                          */
    188 #define VIRTIOSCSI_S_BAD_TARGET                    3           /**< control, command                                 */
    189 #define VIRTIOSCSI_S_RESET                         4           /**< control                                          */
    190 #define VIRTIOSCSI_S_BUSY                          5           /**< control, command                                 */
    191 #define VIRTIOSCSI_S_TRANSPORT_FAILURE             6           /**< control, command                                 */
    192 #define VIRTIOSCSI_S_TARGET_FAILURE                7           /**< control, command                                 */
    193 #define VIRTIOSCSI_S_NEXUS_FAILURE                 8           /**< control, command                                 */
    194 #define VIRTIOSCSI_S_FAILURE                       9           /**< control, command                                 */
    195 #define VIRTIOSCSI_S_INCORRECT_LUN                12           /**< command                                          */
     191#define VIRTIOSCSI_S_OK                             0          /**< control, command                                 */
     192#define VIRTIOSCSI_S_OVERRUN                        1          /**< control                                          */
     193#define VIRTIOSCSI_S_ABORTED                        2          /**< control                                          */
     194#define VIRTIOSCSI_S_BAD_TARGET                     3          /**< control, command                                 */
     195#define VIRTIOSCSI_S_RESET                          4          /**< control                                          */
     196#define VIRTIOSCSI_S_BUSY                           5          /**< control, command                                 */
     197#define VIRTIOSCSI_S_TRANSPORT_FAILURE              6          /**< control, command                                 */
     198#define VIRTIOSCSI_S_TARGET_FAILURE                 7          /**< control, command                                 */
     199#define VIRTIOSCSI_S_NEXUS_FAILURE                  8          /**< control, command                                 */
     200#define VIRTIOSCSI_S_FAILURE                        9          /**< control, command                                 */
     201#define VIRTIOSCSI_S_INCORRECT_LUN                  12         /**< command                                          */
    196202/** @} */
    197203
     
    461467
    462468/**
     469 * Implementation invokes this to reset the VirtIO device
     470 */
     471static void virtioScsiDeviceReset(PVIRTIOSCSI pVirtioScsi)
     472{
     473    pVirtioScsi->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT;
     474    pVirtioScsi->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT;
     475    virtioResetAll(pVirtioScsi->hVirtio);
     476
     477}
     478
     479static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pVirtioScsi, uint32_t uOffset,
     480                                    const void *pv, size_t cb, uint8_t fWrite)
     481{
     482    int rc = VINF_SUCCESS;
     483    if (MATCH_SCSI_CONFIG(uNumQueues))
     484    {
     485        SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);
     486    }
     487    else
     488    if (MATCH_SCSI_CONFIG(uSegMax))
     489    {
     490        SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);
     491    }
     492    else
     493    if (MATCH_SCSI_CONFIG(uMaxSectors))
     494    {
     495        SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);
     496    }
     497    else
     498    if (MATCH_SCSI_CONFIG(uCmdPerLun))
     499    {
     500        SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);
     501    }
     502    else
     503    if (MATCH_SCSI_CONFIG(uEventInfoSize))
     504    {
     505        SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);
     506    }
     507    else
     508    if (MATCH_SCSI_CONFIG(uSenseSize))
     509    {
     510        SCSI_CONFIG_ACCESSOR(uSenseSize);
     511    }
     512    else
     513    if (MATCH_SCSI_CONFIG(uCdbSize))
     514    {
     515        SCSI_CONFIG_ACCESSOR(uCdbSize);
     516    }
     517    else
     518    if (MATCH_SCSI_CONFIG(uMaxChannel))
     519    {
     520        SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);
     521    }
     522    else
     523    if (MATCH_SCSI_CONFIG(uMaxTarget))
     524    {
     525        SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);
     526    }
     527    else
     528    if (MATCH_SCSI_CONFIG(uMaxLun))
     529    {
     530        SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);
     531    }
     532    else
     533    {
     534        LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));
     535        rc = VERR_ACCESS_DENIED;
     536    }
     537    return rc;
     538}
     539
     540
     541/**
     542 * Get this callback from the virtio framework when the driver is ready so we know
     543 * the request for the number of queues is valid (for now presuming the driver(s) aren't
     544 * dynamically adding req queues but create them all while initializing
     545 * based on config information on host).
     546 */
     547static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, bool fVirtioReady)
     548{
     549#define MAX_QUEUENAME_SIZE 20
     550    Log2Func(("\n"));
     551    char pszQueueName[MAX_QUEUENAME_SIZE];
     552    if (fVirtioReady)
     553    {
     554        Log2Func(("VirtIO reports ready... Initializing queues\n"));
     555        virtioQueueAttach(hVirtio, VIRTIOSCSI_VIRTQ_CONTROLQ, "controlq");
     556        virtioQueueAttach(hVirtio, VIRTIOSCSI_VIRTQ_EVENTQ,   "eventq");
     557        for (uint16_t qIdx = VIRTIOSCSI_VIRTQ_REQ_BASE;
     558                      qIdx < VIRTIOSCSI_VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT;
     559                      qIdx++)
     560        {
     561            RTStrPrintf(pszQueueName, sizeof(pszQueueName), "requestq_%d", qIdx - 2);
     562            bool fEnabled = virtioQueueAttach(hVirtio, qIdx, (const char *)pszQueueName);
     563            if (!fEnabled)
     564                break;
     565        }
     566    } else
     567        Log2Func(("VirtIO is resetting\n"));
     568}
     569
     570/**
    463571 * Turns on/off the write status LED.
    464572 *
     
    559667 * @copydoc FNPDMDEVRESET
    560668 */
    561 static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns)
    562 {
    563     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    564     NOREF(pThis);
     669static DECLCALLBACK(void) virtioScsiR3PDMReset(PPDMDEVINS pDevIns)
     670{
     671    PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     672    virtioScsiDeviceReset(pVirtioScsi);
    565673
    566674//    ASMAtomicWriteBool(&pThis->fSignalIdle, true);
     
    571679//        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
    572680//   }
     681
    573682}
    574683
     
    807916}
    808917
    809 /**
    810  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    811  */
    812 static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    813 {
    814      PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
    815      PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE,        &pTarget->IBase);
    816      PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT,   &pTarget->IMediaPort);
    817      PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);
    818      PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS,    &pTarget->ILed);
    819      return NULL;
    820 }
    821 
    822 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pVirtioScsi, uint32_t uOffset,
    823                                     const void *pv, size_t cb, uint8_t fWrite)
    824 {
    825     int rc = VINF_SUCCESS;
    826     if (MATCH_SCSI_CONFIG(uNumQueues))
    827     {
    828         SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);
    829     }
    830     else
    831     if (MATCH_SCSI_CONFIG(uSegMax))
    832     {
    833         SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);
    834     }
    835     else
    836     if (MATCH_SCSI_CONFIG(uMaxSectors))
    837     {
    838         SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);
    839     }
    840     else
    841     if (MATCH_SCSI_CONFIG(uCmdPerLun))
    842     {
    843         SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);
    844     }
    845     else
    846     if (MATCH_SCSI_CONFIG(uEventInfoSize))
    847     {
    848         SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);
    849     }
    850     else
    851     if (MATCH_SCSI_CONFIG(uSenseSize))
    852     {
    853         SCSI_CONFIG_ACCESSOR(uSenseSize);
    854     }
    855     else
    856     if (MATCH_SCSI_CONFIG(uCdbSize))
    857     {
    858         SCSI_CONFIG_ACCESSOR(uCdbSize);
    859     }
    860     else
    861     if (MATCH_SCSI_CONFIG(uMaxChannel))
    862     {
    863         SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);
    864     }
    865     else
    866     if (MATCH_SCSI_CONFIG(uMaxTarget))
    867     {
    868         SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);
    869     }
    870     else
    871     if (MATCH_SCSI_CONFIG(uMaxLun))
    872     {
    873         SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);
    874     }
    875     else
    876     {
    877         LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));
    878         rc = VERR_ACCESS_DENIED;
    879     }
    880     return rc;
    881 }
    882 
    883 
    884 /**
    885  * Get this callback from the virtio framework when the driver is ready so we know
    886  * the request for the number of queues is valid (for now presuming the driver(s) aren't
    887  * dynamically adding req queues but create them all while initializing
    888  * based on config information on host).
    889  */
    890 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, bool fVirtioReady)
    891 {
    892 #define MAX_QUEUENAME_SIZE 20
    893     Log2Func(("\n"));
    894     char pszQueueName[MAX_QUEUENAME_SIZE];
    895     if (fVirtioReady)
    896     {
    897         Log2Func(("VirtIO reports ready... Initializing queues\n"));
    898         virtioQueueInit(hVirtio, VIRTIOSCSI_VIRTQ_CONTROLQ, "controlq");
    899         virtioQueueInit(hVirtio, VIRTIOSCSI_VIRTQ_EVENTQ,   "eventq");
    900         for (uint16_t qIdx = VIRTIOSCSI_VIRTQ_REQ_BASE; qIdx < virtioGetNumQueues(hVirtio); qIdx++)
    901         {
    902             RTStrPrintf(pszQueueName, sizeof(pszQueueName), "requestq_%d", qIdx - 2);
    903             bool fEnabled = virtioQueueInit(hVirtio, qIdx, (const char *)pszQueueName);
    904             if (!fEnabled)
    905                 break;
    906         }
    907     } else
    908         Log2Func(("VirtIO not ready\n"));
    909 }
    910918
    911919static DECLCALLBACK(void) virtioScsiQueueNotified(VIRTIOHANDLE hVirtio, uint16_t qIdx)
     
    10311039 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    10321040 */
     1041static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     1042{
     1043     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
     1044     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE,        &pTarget->IBase);
     1045     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT,   &pTarget->IMediaPort);
     1046     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);
     1047     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS,    &pTarget->ILed);
     1048     return NULL;
     1049}
     1050
     1051/**
     1052 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
     1053 */
    10331054static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    10341055{
     
    11761197    /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */
    11771198    pThis->virtioScsiConfig.uNumQueues      = VIRTIOSCSI_REQ_QUEUE_CNT;
    1178     pThis->virtioScsiConfig.uSegMax         = 1024; /* initial guess */
    1179     pThis->virtioScsiConfig.uMaxSectors     = 0x10000;
    1180     pThis->virtioScsiConfig.uCmdPerLun      = 64;   /* initial guess */
    1181     pThis->virtioScsiConfig.uEventInfoSize  = 100;  /* VirtIO 1.0 spec says this should based on # of negotiated features */
    1182     pThis->virtioScsiConfig.uSenseSize      = 96;   /* from VirtIO 1.0 spec, must restore this on reset */
    1183     pThis->virtioScsiConfig.uCdbSize        = 32;   /* from VirtIO 1.0 spec, must restore this on reset */
    1184     pThis->virtioScsiConfig.uMaxChannel     = 0;    /* from VirtIO 1.0 spec */
     1199    pThis->virtioScsiConfig.uSegMax         = VIRTIOSCSI_MAX_SEG_COUNT;
     1200    pThis->virtioScsiConfig.uMaxSectors     = VIRTIOSCSI_MAX_SECTORS_HINT;
     1201    pThis->virtioScsiConfig.uCmdPerLun      = VIRTIOSCSI_MAX_COMMANDS_PER_LUN;
     1202    pThis->virtioScsiConfig.uEventInfoSize  = sizeof(VIRTIO_SCSI_EVENT_T); /* Spec says at least this size! */
     1203    pThis->virtioScsiConfig.uSenseSize      = VIRTIOSCSI_SENSE_SIZE_DEFAULT;
     1204    pThis->virtioScsiConfig.uCdbSize        = VIRTIOSCSI_CDB_SIZE_DEFAULT;
     1205    pThis->virtioScsiConfig.uMaxChannel     = VIRTIOSCSI_MAX_CHANNEL_HINT;
    11851206    pThis->virtioScsiConfig.uMaxTarget      = pThis->cTargets;
    1186     pThis->virtioScsiConfig.uMaxLun         = 16383; /* from VirtIO 1.0 spec */
     1207    pThis->virtioScsiConfig.uMaxLun         = VIRTIOSCSI_MAX_LUN;
    11871208
    11881209    rc = virtioConstruct(pDevIns, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance,
     
    13571378    NULL,
    13581379    /* pfnReset */
    1359     virtioScsiR3Reset,
     1380    virtioScsiR3PDMReset,
    13601381    /* pfnSuspend */
    13611382    NULL,
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette