104 lines
2.4 KiB
C
104 lines
2.4 KiB
C
/*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Make sure we receive EVL_HMDIAG_STAGEX when locked out from the
|
|
* out-of-band stage because of a stax-based serialization.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/ioctl.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <pthread.h>
|
|
#include <error.h>
|
|
#include <errno.h>
|
|
#include <evl/evl.h>
|
|
#include <uapi/evl/devices/hectic.h>
|
|
#include "helpers.h"
|
|
|
|
static int drvfd;
|
|
|
|
static volatile sig_atomic_t notified;
|
|
|
|
static void sigdebug_handler(int sig, siginfo_t *si, void *context)
|
|
{
|
|
if (sigdebug_marked(si) &&
|
|
sigdebug_cause(si) == EVL_HMDIAG_STAGEX) {
|
|
notified = true;
|
|
return;
|
|
}
|
|
|
|
evl_sigdebug_handler(sig, si, context);
|
|
exit(1); /* bad */
|
|
}
|
|
|
|
static void *test_thread(void *arg)
|
|
{
|
|
int tfd, ret;
|
|
|
|
__Tcall_assert(tfd, evl_attach_self("stax-warn-test:%d", getpid()));
|
|
__Tcall_assert(ret, evl_set_thread_mode(tfd, T_WOSX, NULL));
|
|
|
|
/*
|
|
* In-band main() currently holds the stax, we should get
|
|
* SIGDEBUG as a result of issuing a lock request.
|
|
*/
|
|
ret = oob_ioctl(drvfd, EVL_HECIOC_LOCK_STAX);
|
|
__Texpr_assert(ret == 0);
|
|
|
|
ret = oob_ioctl(drvfd, EVL_HECIOC_UNLOCK_STAX);
|
|
__Texpr_assert(ret == 0);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct sigaction sa;
|
|
pthread_t tid;
|
|
int ret;
|
|
|
|
/*
|
|
* CAUTION: this test uses an internal interface of the
|
|
* 'hectic' driver in order to test the stax mechanism. This
|
|
* interface is enabling the caller to do something wrong and
|
|
* nasty, i.e. holding a stax across the kernel/user space
|
|
* boundary. This is only for the purpose of testing this
|
|
* mechanism, this is bad, applications should never do this,
|
|
* ever. IOW, a stax should be held while in kernel space
|
|
* exclusively, always released before returning to user.
|
|
*/
|
|
drvfd = open("/dev/hectic", O_RDONLY);
|
|
if (drvfd < 0)
|
|
return EXIT_NO_SUPPORT;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
sa.sa_sigaction = sigdebug_handler;
|
|
sa.sa_flags = SA_SIGINFO;
|
|
sigaction(SIGDEBUG, &sa, NULL);
|
|
|
|
ret = ioctl(drvfd, EVL_HECIOC_LOCK_STAX);
|
|
if (ret) {
|
|
if (errno == ENOTTY)
|
|
return EXIT_NO_SUPPORT;
|
|
__Texpr_assert(ret == 0);
|
|
}
|
|
|
|
new_thread(&tid, SCHED_FIFO, 1, test_thread, NULL);
|
|
|
|
/* Wait for the oob thread to try locking the stax. */
|
|
sleep(1);
|
|
|
|
ret = ioctl(drvfd, EVL_HECIOC_UNLOCK_STAX);
|
|
__Texpr_assert(ret == 0);
|
|
|
|
pthread_join(tid, NULL);
|
|
|
|
__Texpr_assert(notified);
|
|
|
|
return 0;
|
|
}
|