All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-help] mprotect in Xenomai
@ 2011-06-20 14:14 Michael Thalmeier
  2011-06-20 14:57 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Thalmeier @ 2011-06-20 14:14 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: Type: text/plain, Size: 550 bytes --]

 Hello !

 We have a xenomai application that uses mprotect to change write 
 protection in order to set and clear breakpoint codes.
 This works quite well (the code invoking mprotect switches to linux, 
 but thats ok).
 The problem is that from time to time the realtime task executing code 
 in the area changed with mprotect also switches domains to handle a page 
 fault.
 Is there some functionality in xenomai to change memory protection not 
 using mprotect ?
 Attached you find a short sample that can reproduce this problem.

 Thanks Michael

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tst_mprotect.c --]
[-- Type: text/x-c; name=tst_mprotect.c, Size: 4474 bytes --]

/*
 * Description:
 *
 *	mprotect test
 */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <rtdm/rtdm.h>
#include <native/task.h>
#include <native/timer.h>
#include <native/mutex.h>
#include <rtdk.h>
#include <signal.h>
#include <execinfo.h>

#define NUM_LOOPS 1000000
#define RTT_PRIO  99

RT_TASK rt_task_desc;
static int finished = 0;

///////////////////////////////////////////////////
// defined from xenomai syscall.h
#define SIGDEBUG_UNDEFINED			0
#define SIGDEBUG_MIGRATE_SIGNAL		1
#define SIGDEBUG_MIGRATE_SYSCALL	2
#define SIGDEBUG_MIGRATE_FAULT		3
#define SIGDEBUG_MIGRATE_PRIOINV	4
#define SIGDEBUG_NOMLOCK			5
#define SIGDEBUG_WATCHDOG			6
///////////////////////////////////////////////////
// own defined
#define SIGDEBUG_STOPTHREAD			17

static const char *GetSIGXCPUsubCode(int subSig) {

	if (subSig == SIGDEBUG_UNDEFINED)			return "SD_UNDEFINED";
	if (subSig == SIGDEBUG_MIGRATE_SIGNAL)		return "SD_MIGRATE_SIGNAL";
	if (subSig == SIGDEBUG_MIGRATE_SYSCALL)		return "SD_MIGRATE_SYSCALL";
	if (subSig == SIGDEBUG_MIGRATE_FAULT)		return "SD_MIGRATE_FAULT";
	if (subSig == SIGDEBUG_MIGRATE_PRIOINV)		return "SD_MIGRATE_PRIOINV";
	if (subSig == SIGDEBUG_NOMLOCK)				return "SD_NOMLOCK";
	if (subSig == SIGDEBUG_WATCHDOG)			return "SD_WATCHDOG";
	if (subSig == SIGDEBUG_STOPTHREAD)			return "SD_STOPTHREAD";
	return "???";
}

static void warn_upon_switch(int sig, siginfo_t *info, void *context)
{
	if (sig == SIGXCPU) {

		printf("received SIGXCPU\n");
		printf("SIGXCPU subcode: %s\n", GetSIGXCPUsubCode(info->si_value.sival_int));
		
		finished = 1;
	}
}

/* This is the realtime task */
static void rt_task_proc(void *arg)
{
	unsigned long long counter = 0;
	
	rt_task_set_mode(0, T_WARNSW, NULL);

	if (rt_task_set_periodic(NULL, TM_NOW, 100000)) {
		rt_printf("failed to set high periodic\n");
		return;
	}
	while (!finished) {
		rt_task_wait_period(NULL);
		if (counter > 1000) {
			counter = 0;
			rt_printf(".");
		}
	}
}

void foo(void)
{
	printf("foo\n");
}

int main(int argc, char *argv[])
{
	int ret;
	int flags = PROT_READ | PROT_EXEC;
	uint8_t awl_orig_instr = 0;
	const uint8_t awl_break_code = 0xcc;
	char * addr = NULL;
	struct sigaction sa_new, sa_old;
	int counter = 1;

	sa_new.sa_sigaction = warn_upon_switch;
	sa_new.sa_flags		=   SA_SIGINFO  /*  Invoke signal-catching function with
											three arguments instead of one. */
						  | SA_NODEFER;	/*  Don't automatically block the signal when
											its handler is being executed. */
	sigemptyset(&sa_new.sa_mask);
	
	if (sigaction(SIGXCPU, &sa_new, &sa_old) < 0) {
		printf("failed to install signal handler for SIGXCPU\n");
		exit(1);
	}

	rt_task_set_mode(0, T_WARNSW, NULL);

	/* No memory-swapping for this programm */
	ret = mlockall(MCL_CURRENT | MCL_FUTURE);
	if (ret) {
		perror("ERROR : mlockall has failled");
		exit(1);
	}
	printf("foo = %p rt_task_proc=%p\n", &foo, &rt_task_proc);
	addr = &rt_task_proc - ((int)(&rt_task_proc) & (0x1000 - 1));
	printf("addr = %p\n", addr);


	if (rt_task_shadow(NULL, "main", 50, 0)) {
		printf("failed to shadow main task\n");
		exit(1);
	}

	rt_print_auto_init(1);

	/*
	 * Turn the current linux task into a xenomai RT-task 
	 * highest priority
	 */
	ret = rt_task_create(&rt_task_desc, "RTT", 0, RTT_PRIO, T_JOINABLE);
	if (ret) {
		fprintf(stderr, "ERROR : rt_task_create: %s\n",
			strerror(-ret));
		exit(1);
	}
	rt_printf("Created task\n");
	ret = rt_task_start(&rt_task_desc, &rt_task_proc, NULL);
	if (ret) {
		fprintf(stderr, "ERROR : rt_task_start: %s\n",
			strerror(-ret));
		exit(1);
	}
	rt_printf("Started task\n");

	while (!finished) {
		flags = PROT_READ | PROT_EXEC | PROT_WRITE;
		mprotect(addr , 0x1000,  flags);

		// set breakpoint code
		if (!awl_orig_instr) {
			memcpy(&awl_orig_instr, &foo, sizeof(awl_orig_instr));
			memcpy(&foo, &awl_break_code, sizeof(awl_break_code));
		}
		// restore original code
		else {
			memcpy(&foo, &awl_orig_instr, sizeof(awl_orig_instr));
			awl_orig_instr = 0;
		}
		
		//rt_printf("- removing memory protection\n");
		flags = PROT_READ | PROT_EXEC;
		mprotect(addr, 0x1000,  flags);

		if (counter++ > 10) {
			counter = 1;
		}

		usleep(counter);
	}

	rt_task_join(&rt_task_desc);
	printf("Task joined\n");

	return 0;
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-06-22  7:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-20 14:14 [Xenomai-help] mprotect in Xenomai Michael Thalmeier
2011-06-20 14:57 ` Gilles Chanteperdrix
2011-06-20 15:29   ` Johann Obermayr
2011-06-21  9:08   ` Michael Thalmeier
2011-06-21 10:41     ` Gilles Chanteperdrix
2011-06-21 22:17     ` Gilles Chanteperdrix
2011-06-22  7:08       ` Michael Thalmeier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.