.. _opal-dumps:

==========
OPAL Dumps
==========

.. code-block:: c

   #define OPAL_REGISTER_DUMP_REGION		101
   #define OPAL_UNREGISTER_DUMP_REGION		102

   int64_t opal_register_dump_region(uint32_t id, uint64_t addr, uint64_t size);
   int64_t opal_unregister_dump_region(uint32_t id);

In the event of crashes, some service processors and firmware support gathering
a limited amount of memory from a limited number of memory regions to save into
a debug dump that can be useful for firmware and operating system developers
in diagnosing problems. Typically, firmware and kernel log buffers are useful to
save in a dump.

An OS can register a memory region with :ref:`OPAL_REGISTER_DUMP_REGION` and should,
when the region is no longer valid (e.g. when kexec()ing), it should unregister the
region with :ref:`OPAL_UNREGISTER_DUMP_REGION`.

An OS will be made aware of a dump being available through :ref:`OPAL_EVENT_DUMP_AVAIL`
being set from a :ref:`OPAL_POLL_EVENTS` call.

Retreiving dumps from a service processor can also be performed using the
:ref:`OPAL_DUMP_INFO`, :ref:`OPAL_DUMP_INFO2`, :ref:`OPAL_DUMP_READ`,
and :ref:`OPAL_DUMP_RESEND` calls. Dumps are identified by a ``uint32_t``, and
once a dump is acknowledged, this ID can be re-used.

Dumps can also be initiated by OPAL through the :ref:`OPAL_DUMP_INIT` call, which
will request that the service processor performs the requested type of dump.

A call to :ref:`OPAL_DUMP_ACK` indicates to the service processor that we have
retreived/acknowledged the dump and the service processor can free up the storage
used by it.

.. code-block:: c

   #define OPAL_DUMP_INIT				81
   #define OPAL_DUMP_INFO				82
   #define OPAL_DUMP_READ				83
   #define OPAL_DUMP_ACK				84
   #define OPAL_DUMP_RESEND				91
   #define OPAL_DUMP_INFO2				94

   int64_t opal_dump_init(uint8_t dump_type);
   int64_t opal_dump_info(uint32_t *dump_id, uint32_t *dump_size);
   int64_t opal_dump_read(uint32_t dump_id, struct opal_sg_list *list);
   int64_t opal_dump_ack(uint32_t dump_id);
   int64_t opal_dump_resend_notification(void);
   int64_t opal_dump_info2(uint32_t *dump_id, uint32_t *dump_size, uint32_t *dump_type);


.. _OPAL_REGISTER_DUMP_REGION:

OPAL_REGISTER_DUMP_REGION
=========================

.. code-block:: c

   #define OPAL_REGISTER_DUMP_REGION		101

   int64_t opal_register_dump_region(uint32_t id, uint64_t addr, uint64_t size);

This call is used to register regions of memory for a service processor to capture
when the host crashes.

e.g. if an assert is hit in OPAL, a service processor will copy the region of
memory into some kind of crash dump for further analysis.

This is an OPTIONAL feature that may be unsupported, the host OS should use an
:ref:`OPAL_CHECK_TOKEN` call to find out if :ref:`OPAL_REGISTER_DUMP_REGION` is supported.

:ref:`OPAL_REGISTER_DUMP_REGION` accepts 3 parameters:

- region ID
- address
- length

There is a range of region IDs that can be used by the host OS. A host OS should
start from OPAL_DUMP_REGION_HOST_END and work down if it wants to add a not well
defined region to dump. Currently the only well defined region is for the host
OS log buffer (e.g. dmesg on linux). ::

  /*
   * Dump region ID range usable by the OS
   */
   #define OPAL_DUMP_REGION_HOST_START		0x80
   #define OPAL_DUMP_REGION_LOG_BUF		0x80
   #define OPAL_DUMP_REGION_HOST_END		0xFF

:ref:`OPAL_REGISTER_DUMP_REGION` will return :ref:`OPAL_UNSUPPORTED` if the call is present but
the system doesn't support registering regions to be dumped.

In the event of being passed an invalid region ID, :ref:`OPAL_REGISTER_DUMP_REGION` will
return :ref:`OPAL_PARAMETER`.

Systems likely have a limit as to how many regions they can support being dumped. If
this limit is reached, :ref:`OPAL_REGISTER_DUMP_REGION` will return :ref:`OPAL_INTERNAL_ERROR`.

BUGS
----
Some skiboot versions incorrectly returned :ref:`OPAL_SUCCESS` in the case of
:ref:`OPAL_REGISTER_DUMP_REGION` being supported on a platform (so the call was present)
but the call being unsupported for some reason (e.g. on an IBM POWER7 machine).

See also: :ref:`OPAL_UNREGISTER_DUMP_REGION`

.. _OPAL_UNREGISTER_DUMP_REGION:

OPAL_UNREGISTER_DUMP_REGION
===========================

.. code-block:: c

   #define OPAL_UNREGISTER_DUMP_REGION		102

   int64_t opal_unregister_dump_region(uint32_t id);

While :ref:`OPAL_REGISTER_DUMP_REGION` registers a region, :ref:`OPAL_UNREGISTER_DUMP_REGION`
will unregister a region by region ID.

:ref:`OPAL_UNREGISTER_DUMP_REGION` takes one argument: the region ID.

A host OS should check :ref:`OPAL_UNREGISTER_DUMP_REGION` is supported through a call to
:ref:`OPAL_CHECK_TOKEN`.

If :ref:`OPAL_UNREGISTER_DUMP_REGION` is called on a system where the call is present but
unsupported, it will return :ref:`OPAL_UNSUPPORTED`.

BUGS
----
Some skiboot versions incorrectly returned :ref:`OPAL_SUCCESS` in the case of
:ref:`OPAL_UNREGISTER_DUMP_REGION` being supported on a platform (so the call was present)
but the call being unsupported for some reason (e.g. on an IBM POWER7 machine).

.. _OPAL_DUMP_INIT:

OPAL_DUMP_INIT
==============

.. code-block:: c

   #define OPAL_DUMP_INIT				81

   #define DUMP_TYPE_FSP		0x01
   #define DUMP_TYPE_SYS		0x02
   #define DUMP_TYPE_SMA		0x03

   int64_t opal_dump_init(uint8_t dump_type);

Ask the service processor to initiate a dump. Currently, only ``DUMP_TYPE_FSP``
is supported.

Currently only implemented on FSP based systems. Use :ref:`OPAL_CHECK_TOKEN` to
ensure the call is valid.

Returns
-------
:ref:`OPAL_SUCCESS`
     Dump initiated
:ref:`OPAL_PARAMETER`
     Unsupported dump type. Currently only ``DUMP_TYPE_FSP`` is supported and
     only on FSP based platforms.
:ref:`OPAL_INTERNAL_ERROR`
     Failed to ask service processor to initiated dump.

.. _OPAL_DUMP_INFO:

OPAL_DUMP_INFO
==============

.. code-block:: c

   #define OPAL_DUMP_INFO				82

   int64_t opal_dump_info(uint32_t *dump_id, uint32_t *dump_size);

Obsolete, use :ref:`OPAL_DUMP_INFO2` instead.

No upstream Linux code ever used :ref:`OPAL_DUMP_INFO`, although early PowerKVM
trees did. :ref:`OPAL_DUMP_INFO` is implemented as a wrapper around
:ref:`OPAL_DUMP_INFO2`.

.. _OPAL_DUMP_READ:

OPAL_DUMP_READ
==============

.. code-block:: c

   #define OPAL_DUMP_READ				83

   int64_t opal_dump_read(uint32_t dump_id, struct opal_sg_list *list);

Read ``dump_id`` dump from the service processor into memory.


Returns
-------
:ref:`OPAL_INTERNAL_ERROR`
     Invalid Dump ID or internal error.
:ref:`OPAL_PARAMETER`
     Insuffcient space to store dump.
:ref:`OPAL_BUSY_EVENT`
     Fetching dump, call :ref:`OPAL_POLL_EVENTS` to crank the state machine,
     and call :ref:`OPAL_DUMP_READ` again until neither :ref:`OPAL_BUSY_EVENT`
     nor :ref:`OPAL_BUSY` are returned.
:ref:`OPAL_PARTIAL`
     Only part of the dump was read.
:ref:`OPAL_SUCCESS`
     Dump successfully read.

.. _OPAL_DUMP_ACK:

OPAL_DUMP_ACK
=============

.. code-block:: c

   #define OPAL_DUMP_ACK				84

   int64_t opal_dump_ack(uint32_t dump_id);

Acknowledge the dump to the service processor. This means the service processor
can re-claim the storage space used by the dump. Effectively, this is an
``unlink`` style operation.

Returns
-------
:ref:`OPAL_SUCCESS`
     Dump successfully acknowledged.
:ref:`OPAL_INTERNAL_ERROR`
     Failed to acknowledge the dump, e.g. could not communicate with service
     processor.
:ref:`OPAL_PARAMETER`
     Invalid dump ID.


.. _OPAL_DUMP_RESEND:

OPAL_DUMP_RESEND
================

.. code-block:: c

   #define OPAL_DUMP_RESEND				91

   int64_t opal_dump_resend_notification(void);

Resend notification to the OS if there is a dump available. This will
cause OPAL to check if a dump is available and set the
:ref:`OPAL_EVENT_DUMP_AVAIL` bit in the next :ref:`OPAL_POLL_EVENTS` call.

Returns
-------
:ref:`OPAL_SUCCESS`
     Successfully reset :ref:`OPAL_EVENT_DUMP_AVAIL` bit.

In future, this may return other standard OPAL error codes.

.. _OPAL_DUMP_INFO2:

OPAL_DUMP_INFO2
===============

.. code-block:: c

   #define OPAL_DUMP_INFO2				94

   #define DUMP_TYPE_FSP		0x01
   #define DUMP_TYPE_SYS		0x02
   #define DUMP_TYPE_SMA		0x03

   int64_t opal_dump_info2(uint32_t *dump_id, uint32_t *dump_size, uint32_t *dump_type);

Retreives information about a dump, notably it's ``dump_id``, size, and type.
Call this after the :ref:`OPAL_EVENT_DUMP_AVAIL` bit is set from a
:ref:`OPAL_POLL_EVENTS` call. It will retreive the information on the *next*
dump to be retreived and/or ACKed, even though there may be more than one dump
available for retreiving.

This call replaces :ref:`OPAL_DUMP_INFO`.

Returns
-------
:ref:`OPAL_SUCCESS`
     Information retreived.
:ref:`OPAL_INTERNAL_ERROR`
     No dump available or internal error.
