Running a watchdog vdev (vdev wdt-sp805)

An emulation vdev behaves like its hardware equivalent.

Like a hardware watchdog, a watchdog vdev expects to be kicked at specified intervals, at which time it resets its counter. If it isn't kicked within the specified period, it takes whatever action it has been configured to take.

Functions such as sp805_control(), sp805_vread(), and sp805_vread() are similar to analogous vdtrace_*() functions and don't warrant further discussion here. As with the trace vdev, the source code for the watchdog vdevs is available on GitHub at github.com/qnx.

Notice that unlike vdev trace, the watchdog vdevs are single-threaded; it doesn't call vdev_thread_create() to create any new threads.

do_read() and do_write()

The sp805_vread() and sp805_vread() functions in this vdev are essentially like the analogous *_vread() and *_vwrite() functions in the trace vdev in that sp805_vread() is called to read what the device controller in the guest writes into the wdt-sp805 vdev's allocated memory space, and that sp805_vwrite() is called to write to this space when the device controller in the guest reads from this space (see Reading and writing in a vdev in the About Writing Vdevs chapter).

The sp805_vread() and sp805_vwrite() functions in this vdev differ from the analogous functions in the trace vdev, however, in that they call the do_read() and do_write() functions. The do_read() function refreshes any of the watchdog vdev's virtual registers that have been updated by a write from the device controller in the guest. The do_write() function updates these virtual registers when the device controller in the guest attempts to read them.

Note that calls to the do_v*() functions are inside mutexes to ensure that the memory isn't updated by an external action; for example, in sp805_vwrite(), the call to the do_write is as follows:

sp805_vwrite(vdev_t *const vdp, unsigned const cookie,
             const struct qvm_state_block *const vopnd,
             const struct qvm_state_block *const oopnd, struct guest_cpu *const gcp)
{

    uint32_t val;
    int const r = guest_cpu_read(gcp, GXF_NONE, oopnd, 1, &val, sizeof(val));
    if (r != EOK) {
        return guest_cpu_to_vrs(r);
    }

    pthread_mutex_lock(&vdp->v_mtx);
    unsigned const off = (unsigned)(vopnd->location - vdp->v_block.location);
    enum vdev_ref_status const rs = do_write(vdp, off, val, gcp);
    pthread_mutex_unlock(&vdp->v_mtx);
    return rs;
}

Timer management functions

See Terminating qvm process instances and guests in the “About Writing Vdevs” chapter in this guide, and wdog_bite() in the Virtual Device Developer's API Reference “wdog.h” chapter.