Attachment 'MC2-litmut-rt-imx6-rtss15.patch'

Download

   1 From d6790ee609a62386c2803cbe74b84354af99bb73 Mon Sep 17 00:00:00 2001
   2 From: Bjoern Brandenburg <bbb@mpi-sws.org>
   3 Date: Thu, 20 Jun 2013 12:49:18 +0200
   4 Subject: [PATCH 001/119] Add LITMUS^RT directory
   5 
   6 Hookup litmus/ with kernel and add extra version.
   7 ---
   8  Makefile         | 2 +-
   9  arch/arm/Kconfig | 3 +++
  10  arch/x86/Kconfig | 2 ++
  11  litmus/Kconfig   | 3 +++
  12  litmus/Makefile  | 3 +++
  13  5 files changed, 12 insertions(+), 1 deletion(-)
  14  create mode 100644 litmus/Kconfig
  15  create mode 100644 litmus/Makefile
  16 
  17 diff --git a/Makefile b/Makefile
  18 index 3071428..dd0cb2e 100644
  19 --- a/Makefile
  20 +++ b/Makefile
  21 @@ -733,7 +733,7 @@ export mod_sign_cmd
  22  
  23  
  24  ifeq ($(KBUILD_EXTMOD),)
  25 -core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
  26 +core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/ litmus/
  27  
  28  vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
  29  		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
  30 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
  31 index ea6ec7e..131ec84 100644
  32 --- a/arch/arm/Kconfig
  33 +++ b/arch/arm/Kconfig
  34 @@ -2269,3 +2269,6 @@ source "crypto/Kconfig"
  35  source "lib/Kconfig"
  36  
  37  source "arch/arm/kvm/Kconfig"
  38 +
  39 +source "litmus/Kconfig"
  40 +
  41 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
  42 index fe120da..bd67fd1 100644
  43 --- a/arch/x86/Kconfig
  44 +++ b/arch/x86/Kconfig
  45 @@ -2346,3 +2346,5 @@ source "crypto/Kconfig"
  46  source "arch/x86/kvm/Kconfig"
  47  
  48  source "lib/Kconfig"
  49 +
  50 +source "litmus/Kconfig"
  51 diff --git a/litmus/Kconfig b/litmus/Kconfig
  52 new file mode 100644
  53 index 0000000..382b2e4
  54 --- /dev/null
  55 +++ b/litmus/Kconfig
  56 @@ -0,0 +1,3 @@
  57 +menu "LITMUS^RT"
  58 +
  59 +endmenu
  60 diff --git a/litmus/Makefile b/litmus/Makefile
  61 new file mode 100644
  62 index 0000000..f0ed31f
  63 --- /dev/null
  64 +++ b/litmus/Makefile
  65 @@ -0,0 +1,3 @@
  66 +#
  67 +# Makefile for LITMUS^RT
  68 +#
  69 -- 
  70 1.8.1.2
  71 
  72 
  73 From efbaae0016a8bc98cc6d24e17ee242a52b356f17 Mon Sep 17 00:00:00 2001
  74 From: Bjoern Brandenburg <bbb@mpi-sws.org>
  75 Date: Sun, 23 Jun 2013 11:41:27 +0200
  76 Subject: [PATCH 002/119] Feather-Trace: add platform independent
  77  implementation
  78 
  79 This patch adds the simple fallback implementation and creates dummy
  80 hooks in the x86 and ARM Kconfig files.
  81 ---
  82  arch/arm/Kconfig                |   3 +
  83  arch/x86/Kconfig                |   3 +
  84  include/litmus/feather_buffer.h | 118 ++++++++++++++++++++++++++++++++++++++++
  85  include/litmus/feather_trace.h  |  69 +++++++++++++++++++++++
  86  litmus/Kconfig                  |  25 +++++++++
  87  litmus/Makefile                 |   2 +
  88  litmus/ft_event.c               |  43 +++++++++++++++
  89  7 files changed, 263 insertions(+)
  90  create mode 100644 include/litmus/feather_buffer.h
  91  create mode 100644 include/litmus/feather_trace.h
  92  create mode 100644 litmus/ft_event.c
  93 
  94 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
  95 index 131ec84..ecfd735 100644
  96 --- a/arch/arm/Kconfig
  97 +++ b/arch/arm/Kconfig
  98 @@ -2270,5 +2270,8 @@ source "lib/Kconfig"
  99  
 100  source "arch/arm/kvm/Kconfig"
 101  
 102 +config ARCH_HAS_FEATHER_TRACE
 103 +	def_bool n
 104 +
 105  source "litmus/Kconfig"
 106  
 107 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
 108 index bd67fd1..0216c93 100644
 109 --- a/arch/x86/Kconfig
 110 +++ b/arch/x86/Kconfig
 111 @@ -2347,4 +2347,7 @@ source "arch/x86/kvm/Kconfig"
 112  
 113  source "lib/Kconfig"
 114  
 115 +config ARCH_HAS_FEATHER_TRACE
 116 +	def_bool n
 117 +
 118  source "litmus/Kconfig"
 119 diff --git a/include/litmus/feather_buffer.h b/include/litmus/feather_buffer.h
 120 new file mode 100644
 121 index 0000000..38de95b
 122 --- /dev/null
 123 +++ b/include/litmus/feather_buffer.h
 124 @@ -0,0 +1,118 @@
 125 +#ifndef _FEATHER_BUFFER_H_
 126 +#define _FEATHER_BUFFER_H_
 127 +
 128 +/* requires UINT_MAX and memcpy */
 129 +
 130 +#define SLOT_FREE	0
 131 +#define	SLOT_BUSY 	1
 132 +#define	SLOT_READY	2
 133 +
 134 +struct ft_buffer {
 135 +	unsigned int	slot_count;
 136 +	unsigned int	slot_size;
 137 +
 138 +	int 		free_count;
 139 +	unsigned int 	write_idx;
 140 +	unsigned int 	read_idx;
 141 +
 142 +	char*		slots;
 143 +	void*		buffer_mem;
 144 +	unsigned int	failed_writes;
 145 +};
 146 +
 147 +static inline int init_ft_buffer(struct ft_buffer*	buf,
 148 +				 unsigned int 		slot_count,
 149 +				 unsigned int 		slot_size,
 150 +				 char*			slots,
 151 +				 void* 			buffer_mem)
 152 +{
 153 +	int i = 0;
 154 +	if (!slot_count || UINT_MAX % slot_count != slot_count - 1) {
 155 +		/* The slot count must divide UNIT_MAX + 1 so that when it
 156 +		 * wraps around the index correctly points to 0.
 157 +		 */
 158 +		return 0;
 159 +	} else {
 160 +		buf->slot_count    = slot_count;
 161 +		buf->slot_size     = slot_size;
 162 +		buf->slots         = slots;
 163 +		buf->buffer_mem    = buffer_mem;
 164 +		buf->free_count    = slot_count;
 165 +		buf->write_idx     = 0;
 166 +		buf->read_idx      = 0;
 167 +		buf->failed_writes = 0;
 168 +		for (i = 0; i < slot_count; i++)
 169 +			buf->slots[i] = SLOT_FREE;
 170 +		return 1;
 171 +	}
 172 +}
 173 +
 174 +static inline int ft_buffer_start_write(struct ft_buffer* buf, void **ptr)
 175 +{
 176 +	int free = fetch_and_dec(&buf->free_count);
 177 +	unsigned int idx;
 178 +	if (free <= 0) {
 179 +		fetch_and_inc(&buf->free_count);
 180 +		*ptr = 0;
 181 +		fetch_and_inc(&buf->failed_writes);
 182 +		return 0;
 183 +	} else {
 184 +		idx  = fetch_and_inc((int*) &buf->write_idx) % buf->slot_count;
 185 +		buf->slots[idx] = SLOT_BUSY;
 186 +		*ptr = ((char*) buf->buffer_mem) + idx * buf->slot_size;
 187 +		return 1;
 188 +	}
 189 +}
 190 +
 191 +/* For single writer scenarios, with fewer atomic ops. */
 192 +static inline int ft_buffer_start_single_write(struct ft_buffer* buf, void **ptr)
 193 +{
 194 +	unsigned int idx;
 195 +
 196 +	if (buf->free_count <= 0) {
 197 +		*ptr = 0;
 198 +		/* single writer: no atomicity needed */
 199 +		buf->failed_writes++;
 200 +		return 0;
 201 +	} else {
 202 +		/* free_count is positive, and can only increase since we are
 203 +		 * (by assumption) the only writer accessing the buffer.
 204 +		 */
 205 +
 206 +		idx  = buf->write_idx++ % buf->slot_count;
 207 +		buf->slots[idx] = SLOT_BUSY;
 208 +		*ptr = ((char*) buf->buffer_mem) + idx * buf->slot_size;
 209 +
 210 +		ft_atomic_dec(&buf->free_count);
 211 +		return 1;
 212 +	}
 213 +}
 214 +
 215 +static inline void ft_buffer_finish_write(struct ft_buffer* buf, void *ptr)
 216 +{
 217 +	unsigned int idx = ((char*) ptr - (char*) buf->buffer_mem) / buf->slot_size;
 218 +	buf->slots[idx]  = SLOT_READY;
 219 +}
 220 +
 221 +
 222 +/* exclusive reader access is assumed */
 223 +static inline int ft_buffer_read(struct ft_buffer* buf, void* dest)
 224 +{
 225 +	unsigned int idx;
 226 +	if (buf->free_count == buf->slot_count)
 227 +		/* nothing available */
 228 +		return 0;
 229 +	idx = buf->read_idx % buf->slot_count;
 230 +	if (buf->slots[idx] == SLOT_READY) {
 231 +		memcpy(dest, ((char*) buf->buffer_mem) + idx * buf->slot_size,
 232 +		       buf->slot_size);
 233 +		buf->slots[idx] = SLOT_FREE;
 234 +		buf->read_idx++;
 235 +		fetch_and_inc(&buf->free_count);
 236 +		return 1;
 237 +	} else
 238 +		return 0;
 239 +}
 240 +
 241 +
 242 +#endif
 243 diff --git a/include/litmus/feather_trace.h b/include/litmus/feather_trace.h
 244 new file mode 100644
 245 index 0000000..dbeca46
 246 --- /dev/null
 247 +++ b/include/litmus/feather_trace.h
 248 @@ -0,0 +1,69 @@
 249 +#ifndef _FEATHER_TRACE_H_
 250 +#define _FEATHER_TRACE_H_
 251 +
 252 +#include <asm/atomic.h>
 253 +
 254 +int ft_enable_event(unsigned long id);
 255 +int ft_disable_event(unsigned long id);
 256 +int ft_is_event_enabled(unsigned long id);
 257 +int ft_disable_all_events(void);
 258 +
 259 +/* atomic_* funcitons are inline anyway */
 260 +static inline int fetch_and_inc(int *val)
 261 +{
 262 +	return atomic_add_return(1, (atomic_t*) val) - 1;
 263 +}
 264 +
 265 +static inline int fetch_and_dec(int *val)
 266 +{
 267 +	return atomic_sub_return(1, (atomic_t*) val) + 1;
 268 +}
 269 +
 270 +static inline void ft_atomic_dec(int *val)
 271 +{
 272 +	atomic_sub(1, (atomic_t*) val);
 273 +}
 274 +
 275 +/* Don't use rewriting implementation if kernel text pages are read-only.
 276 + * Ftrace gets around this by using the identity mapping, but that's more
 277 + * effort that is warrented right now for Feather-Trace.
 278 + * Eventually, it may make sense to replace Feather-Trace with ftrace.
 279 + */
 280 +#if defined(CONFIG_ARCH_HAS_FEATHER_TRACE) && !defined(CONFIG_DEBUG_RODATA)
 281 +
 282 +#include <asm/feather_trace.h>
 283 +
 284 +#else /* !__ARCH_HAS_FEATHER_TRACE */
 285 +
 286 +/* provide default implementation */
 287 +#include <linux/timex.h> /* for get_cycles() */
 288 +
 289 +static inline unsigned long long ft_timestamp(void)
 290 +{
 291 +	return get_cycles();
 292 +}
 293 +
 294 +#define feather_callback
 295 +
 296 +#define MAX_EVENTS 1024
 297 +
 298 +extern int ft_events[MAX_EVENTS];
 299 +
 300 +#define ft_event(id, callback) \
 301 +	if (ft_events[id]) callback();
 302 +
 303 +#define ft_event0(id, callback) \
 304 +	if (ft_events[id]) callback(id);
 305 +
 306 +#define ft_event1(id, callback, param) \
 307 +	if (ft_events[id]) callback(id, param);
 308 +
 309 +#define ft_event2(id, callback, param, param2) \
 310 +	if (ft_events[id]) callback(id, param, param2);
 311 +
 312 +#define ft_event3(id, callback, p, p2, p3) \
 313 +	if (ft_events[id]) callback(id, p, p2, p3);
 314 +
 315 +#endif /* __ARCH_HAS_FEATHER_TRACE */
 316 +
 317 +#endif
 318 diff --git a/litmus/Kconfig b/litmus/Kconfig
 319 index 382b2e4..70ddbad 100644
 320 --- a/litmus/Kconfig
 321 +++ b/litmus/Kconfig
 322 @@ -1,3 +1,28 @@
 323  menu "LITMUS^RT"
 324  
 325 +menu "Tracing"
 326 +
 327 +config FEATHER_TRACE
 328 +	bool "Feather-Trace Infrastructure"
 329 +	default y
 330 +	help
 331 +	  Feather-Trace basic tracing infrastructure. Includes device file
 332 +	  driver and instrumentation point support.
 333 +
 334 +	  There are actually two implementations of Feather-Trace.
 335 +	  1) A slower, but portable, default implementation.
 336 +	  2) Architecture-specific implementations that rewrite kernel .text at runtime.
 337 +
 338 +	  If enabled, Feather-Trace will be based on 2) if available (currently only for x86).
 339 +	  However, if DEBUG_RODATA=y, then Feather-Trace will choose option 1) in any case
 340 +	  to avoid problems with write-protected .text pages.
 341 +
 342 +	  Bottom line: to avoid increased overheads, choose DEBUG_RODATA=n.
 343 +
 344 +	  Note that this option only enables the basic Feather-Trace infrastructure;
 345 +	  you still need to enable SCHED_TASK_TRACE and/or SCHED_OVERHEAD_TRACE to
 346 +	  actually enable any events.
 347 +
 348 +endmenu
 349 +
 350  endmenu
 351 diff --git a/litmus/Makefile b/litmus/Makefile
 352 index f0ed31f..4c6130b 100644
 353 --- a/litmus/Makefile
 354 +++ b/litmus/Makefile
 355 @@ -1,3 +1,5 @@
 356  #
 357  # Makefile for LITMUS^RT
 358  #
 359 +
 360 +obj-$(CONFIG_FEATHER_TRACE) += ft_event.o
 361 diff --git a/litmus/ft_event.c b/litmus/ft_event.c
 362 new file mode 100644
 363 index 0000000..399a07b
 364 --- /dev/null
 365 +++ b/litmus/ft_event.c
 366 @@ -0,0 +1,43 @@
 367 +#include <linux/types.h>
 368 +
 369 +#include <litmus/feather_trace.h>
 370 +
 371 +#if !defined(CONFIG_ARCH_HAS_FEATHER_TRACE) || defined(CONFIG_DEBUG_RODATA)
 372 +/* provide dummy implementation */
 373 +
 374 +int ft_events[MAX_EVENTS];
 375 +
 376 +int ft_enable_event(unsigned long id)
 377 +{
 378 +	if (id < MAX_EVENTS) {
 379 +		ft_events[id]++;
 380 +		return 1;
 381 +	} else
 382 +		return 0;
 383 +}
 384 +
 385 +int ft_disable_event(unsigned long id)
 386 +{
 387 +	if (id < MAX_EVENTS && ft_events[id]) {
 388 +		ft_events[id]--;
 389 +		return 1;
 390 +	} else
 391 +		return 0;
 392 +}
 393 +
 394 +int ft_disable_all_events(void)
 395 +{
 396 +	int i;
 397 +
 398 +	for (i = 0; i < MAX_EVENTS; i++)
 399 +		ft_events[i] = 0;
 400 +
 401 +	return MAX_EVENTS;
 402 +}
 403 +
 404 +int ft_is_event_enabled(unsigned long id)
 405 +{
 406 +	return 	id < MAX_EVENTS && ft_events[id];
 407 +}
 408 +
 409 +#endif
 410 -- 
 411 1.8.1.2
 412 
 413 
 414 From 32f9c06ee90e860a7c6fbe8d27b2c219804bfee2 Mon Sep 17 00:00:00 2001
 415 From: Bjoern Brandenburg <bbb@mpi-sws.org>
 416 Date: Sun, 23 Jun 2013 11:46:23 +0200
 417 Subject: [PATCH 003/119] Feather-Trace: add x86 binary rewriting
 418  implementation
 419 
 420 This patch adds the x86-specific implementation of Feather-Trace
 421 triggers that works by rewriting jump instructions.
 422 ---
 423  arch/x86/Kconfig                        |   2 +-
 424  arch/x86/include/asm/feather_trace.h    |  17 +++++
 425  arch/x86/include/asm/feather_trace_32.h | 115 +++++++++++++++++++++++++++++
 426  arch/x86/include/asm/feather_trace_64.h | 124 ++++++++++++++++++++++++++++++++
 427  arch/x86/kernel/Makefile                |   2 +
 428  arch/x86/kernel/ft_event.c              | 118 ++++++++++++++++++++++++++++++
 429  litmus/Kconfig                          |   1 +
 430  7 files changed, 378 insertions(+), 1 deletion(-)
 431  create mode 100644 arch/x86/include/asm/feather_trace.h
 432  create mode 100644 arch/x86/include/asm/feather_trace_32.h
 433  create mode 100644 arch/x86/include/asm/feather_trace_64.h
 434  create mode 100644 arch/x86/kernel/ft_event.c
 435 
 436 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
 437 index 0216c93..171cdc9 100644
 438 --- a/arch/x86/Kconfig
 439 +++ b/arch/x86/Kconfig
 440 @@ -2348,6 +2348,6 @@ source "arch/x86/kvm/Kconfig"
 441  source "lib/Kconfig"
 442  
 443  config ARCH_HAS_FEATHER_TRACE
 444 -	def_bool n
 445 +	def_bool y
 446  
 447  source "litmus/Kconfig"
 448 diff --git a/arch/x86/include/asm/feather_trace.h b/arch/x86/include/asm/feather_trace.h
 449 new file mode 100644
 450 index 0000000..4fd3163
 451 --- /dev/null
 452 +++ b/arch/x86/include/asm/feather_trace.h
 453 @@ -0,0 +1,17 @@
 454 +#ifndef _ARCH_FEATHER_TRACE_H
 455 +#define _ARCH_FEATHER_TRACE_H
 456 +
 457 +#include <asm/msr.h>
 458 +
 459 +static inline unsigned long long ft_timestamp(void)
 460 +{
 461 +	return __native_read_tsc();
 462 +}
 463 +
 464 +#ifdef CONFIG_X86_32
 465 +#include "feather_trace_32.h"
 466 +#else
 467 +#include "feather_trace_64.h"
 468 +#endif
 469 +
 470 +#endif
 471 diff --git a/arch/x86/include/asm/feather_trace_32.h b/arch/x86/include/asm/feather_trace_32.h
 472 new file mode 100644
 473 index 0000000..75e81a9
 474 --- /dev/null
 475 +++ b/arch/x86/include/asm/feather_trace_32.h
 476 @@ -0,0 +1,115 @@
 477 +/* Copyright (c) 2007-2012 Björn Brandenburg, <bbb@mpi-sws.org>
 478 + *
 479 + * Permission is hereby granted, free of charge, to any person obtaining
 480 + * a copy of this software and associated documentation files (the
 481 + * "Software"), to deal in the Software without restriction, including
 482 + * without limitation the rights to use, copy, modify, merge, publish,
 483 + * distribute, sublicense, and/or sell copies of the Software, and to
 484 + * permit persons to whom the Software is furnished to do so, subject to
 485 + * the following conditions:
 486 + *
 487 + * The above copyright notice and this permission notice shall be
 488 + * included in all copies or substantial portions of the Software.
 489 + *
 490 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 491 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 492 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 493 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 494 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 495 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 496 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 497 + * SOFTWARE.
 498 + */
 499 +
 500 +/* Do not directly include this file. Include feather_trace.h instead */
 501 +
 502 +#define feather_callback __attribute__((regparm(3)))  __attribute__((used))
 503 +
 504 +/*
 505 + * Make the compiler reload any register that is not saved in a cdecl function
 506 + * call (minus the registers that we explicitly clobber as output registers).
 507 + */
 508 +#define __FT_CLOBBER_LIST0 "memory", "cc", "eax", "edx", "ecx"
 509 +#define __FT_CLOBBER_LIST1 "memory", "cc", "eax", "ecx"
 510 +#define __FT_CLOBBER_LIST2 "memory", "cc", "eax"
 511 +#define __FT_CLOBBER_LIST3 "memory", "cc", "eax"
 512 +
 513 +#define __FT_TMP1(x) "=d" (x)
 514 +#define __FT_ARG1(x) "0" ((long) (x))
 515 +#define __FT_TMP2(x) "=c" (x)
 516 +#define __FT_ARG2(x) "1" ((long) (x))
 517 +
 518 +#define __FT_ARG3(x) "r" ((long) (x))
 519 +
 520 +#define ft_event(id, callback)                                  \
 521 +        __asm__ __volatile__(                                   \
 522 +            "1: jmp 2f                                    \n\t" \
 523 +	    " call " #callback "                          \n\t" \
 524 +            ".section __event_table, \"aw\"               \n\t" \
 525 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 526 +            ".previous                                    \n\t" \
 527 +            "2:                                           \n\t" \
 528 +	    : : : __FT_CLOBBER_LIST0)
 529 +
 530 +#define ft_event0(id, callback)                                 \
 531 +        __asm__ __volatile__(                                   \
 532 +            "1: jmp 2f                                    \n\t" \
 533 +            " movl $" #id  ", %%eax                       \n\t" \
 534 +	    " call " #callback "                          \n\t" \
 535 +            ".section __event_table, \"aw\"               \n\t" \
 536 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 537 +            ".previous                                    \n\t" \
 538 +            "2:                                           \n\t" \
 539 +	    : : : __FT_CLOBBER_LIST0)
 540 +
 541 +#define ft_event1(id, callback, param)				\
 542 +	do {							\
 543 +		long __ft_tmp1;					\
 544 +        __asm__ __volatile__(                                   \
 545 +            "1: jmp 2f                                    \n\t" \
 546 +            " movl $" #id  ", %%eax                       \n\t" \
 547 +	    " call " #callback "                          \n\t" \
 548 +            ".section __event_table, \"aw\"               \n\t" \
 549 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 550 +            ".previous                                    \n\t" \
 551 +            "2:                                           \n\t" \
 552 +	    : __FT_TMP1(__ft_tmp1)				\
 553 +	    : __FT_ARG1(param)					\
 554 +	    : __FT_CLOBBER_LIST1);				\
 555 +	} while (0);
 556 +
 557 +#define ft_event2(id, callback, param, param2)                  \
 558 +	do {							\
 559 +		long __ft_tmp1, __ft_tmp2;			\
 560 +        __asm__ __volatile__(                                   \
 561 +            "1: jmp 2f                                    \n\t" \
 562 +            " movl $" #id  ", %%eax                       \n\t" \
 563 +	    " call " #callback "                          \n\t" \
 564 +            ".section __event_table, \"aw\"               \n\t" \
 565 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 566 +            ".previous                                    \n\t" \
 567 +            "2:                                           \n\t" \
 568 +	    : __FT_TMP1(__ft_tmp1), __FT_TMP2(__ft_tmp2)	\
 569 +	    : __FT_ARG1(param), __FT_ARG2(param2)		\
 570 +	    : __FT_CLOBBER_LIST2);				\
 571 +	} while (0);
 572 +
 573 +
 574 +#define ft_event3(id, callback, param, param2, param3)		\
 575 +	do {							\
 576 +		long __ft_tmp1, __ft_tmp2;			\
 577 +        __asm__ __volatile__(                                   \
 578 +            "1: jmp 2f                                    \n\t" \
 579 +	    " subl $4, %%esp                              \n\t" \
 580 +            " movl $" #id  ", %%eax                       \n\t" \
 581 +	    " movl %2, (%%esp)                            \n\t" \
 582 +	    " call " #callback "                          \n\t" \
 583 +	    " addl $4, %%esp                              \n\t" \
 584 +            ".section __event_table, \"aw\"               \n\t" \
 585 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 586 +            ".previous                                    \n\t" \
 587 +            "2:                                           \n\t" \
 588 +	    : __FT_TMP1(__ft_tmp1), __FT_TMP2(__ft_tmp2)	\
 589 +	    : __FT_ARG1(param), __FT_ARG2(param2), __FT_ARG3(param3)	\
 590 +	    : __FT_CLOBBER_LIST3);				\
 591 +	} while (0);
 592 diff --git a/arch/x86/include/asm/feather_trace_64.h b/arch/x86/include/asm/feather_trace_64.h
 593 new file mode 100644
 594 index 0000000..5ce49e2
 595 --- /dev/null
 596 +++ b/arch/x86/include/asm/feather_trace_64.h
 597 @@ -0,0 +1,124 @@
 598 +/* Copyright (c) 2010 Andrea Bastoni, <bastoni@cs.unc.edu>
 599 + * Copyright (c) 2012 Björn Brandenburg, <bbb@mpi-sws.org>
 600 + *
 601 + * Permission is hereby granted, free of charge, to any person obtaining
 602 + * a copy of this software and associated documentation files (the
 603 + * "Software"), to deal in the Software without restriction, including
 604 + * without limitation the rights to use, copy, modify, merge, publish,
 605 + * distribute, sublicense, and/or sell copies of the Software, and to
 606 + * permit persons to whom the Software is furnished to do so, subject to
 607 + * the following conditions:
 608 + *
 609 + * The above copyright notice and this permission notice shall be
 610 + * included in all copies or substantial portions of the Software.
 611 + *
 612 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 613 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 614 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 615 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 616 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 617 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 618 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 619 + * SOFTWARE.
 620 + */
 621 +
 622 +/* Do not directly include this file. Include feather_trace.h instead */
 623 +
 624 +/* regparm is the default on x86_64 */
 625 +#define feather_callback  __attribute__((used))
 626 +
 627 +#define __FT_EVENT_TABLE(id,from,to) \
 628 +            ".section __event_table, \"aw\"\n\t" \
 629 +	    ".balign 8\n\t" \
 630 +            ".quad " #id  ", 0, " #from ", " #to " \n\t" \
 631 +            ".previous \n\t"
 632 +
 633 +/*
 634 + * x86_64 caller only owns rbp, rbx, r12-r15;
 635 + * the callee can freely modify the others.
 636 + */
 637 +#define __FT_CLOBBER_LIST0	"memory", "cc", "rdi", "rsi", "rdx", "rcx", \
 638 +			"r8", "r9", "r10", "r11", "rax"
 639 +
 640 +#define __FT_CLOBBER_LIST1	"memory", "cc", "rdi", "rdx", "rcx", \
 641 +			"r8", "r9", "r10", "r11", "rax"
 642 +
 643 +#define __FT_CLOBBER_LIST2	"memory", "cc", "rdi", "rcx", \
 644 +			"r8", "r9", "r10", "r11", "rax"
 645 +
 646 +#define __FT_CLOBBER_LIST3	"memory", "cc", "rdi", \
 647 +			"r8", "r9", "r10", "r11", "rax"
 648 +
 649 +/* The registers RDI, RSI, RDX, RCX, R8 and R9 are used for integer and pointer
 650 + * arguments. */
 651 +
 652 +/* RSI */
 653 +#define __FT_TMP1(x) "=S" (x)
 654 +#define __FT_ARG1(x) "0" ((long) (x))
 655 +
 656 +/* RDX */
 657 +#define __FT_TMP2(x) "=d" (x)
 658 +#define __FT_ARG2(x) "1" ((long) (x))
 659 +
 660 +/* RCX */
 661 +#define __FT_TMP3(x) "=c" (x)
 662 +#define __FT_ARG3(x) "2" ((long) (x))
 663 +
 664 +#define ft_event(id, callback)                                  \
 665 +        __asm__ __volatile__(                                   \
 666 +            "1: jmp 2f                                    \n\t" \
 667 +	    " call " #callback "                          \n\t" \
 668 +            __FT_EVENT_TABLE(id,1b,2f)				\
 669 +            "2:                                           \n\t" \
 670 +        : : : __FT_CLOBBER_LIST0)
 671 +
 672 +#define ft_event0(id, callback)                                 \
 673 +        __asm__ __volatile__(                                   \
 674 +            "1: jmp 2f                                    \n\t" \
 675 +	    " movq $" #id ", %%rdi			  \n\t" \
 676 +	    " call " #callback "                          \n\t" \
 677 +	    __FT_EVENT_TABLE(id,1b,2f)				\
 678 +            "2:                                           \n\t" \
 679 +        : :  : __FT_CLOBBER_LIST0)
 680 +
 681 +#define ft_event1(id, callback, param)                          \
 682 +	do {							\
 683 +		long __ft_tmp1;					\
 684 +	__asm__ __volatile__(                                   \
 685 +	    "1: jmp 2f                                    \n\t" \
 686 +	    " movq $" #id ", %%rdi			  \n\t" \
 687 +	    " call " #callback "                          \n\t" \
 688 +	    __FT_EVENT_TABLE(id,1b,2f)				\
 689 +	    "2:                                           \n\t" \
 690 +	    : __FT_TMP1(__ft_tmp1)				\
 691 +	    : __FT_ARG1(param)					\
 692 +	    : __FT_CLOBBER_LIST1);				\
 693 +	} while (0);
 694 +
 695 +#define ft_event2(id, callback, param, param2)                  \
 696 +	do {							\
 697 +		long __ft_tmp1, __ft_tmp2;			\
 698 +        __asm__ __volatile__(                                   \
 699 +            "1: jmp 2f                                    \n\t" \
 700 +	    " movq $" #id ", %%rdi			  \n\t" \
 701 +	    " call " #callback "                          \n\t" \
 702 +            __FT_EVENT_TABLE(id,1b,2f)				\
 703 +            "2:                                           \n\t" \
 704 +	    : __FT_TMP1(__ft_tmp1), __FT_TMP2(__ft_tmp2)	\
 705 +	    : __FT_ARG1(param), __FT_ARG2(param2)		\
 706 +	    : __FT_CLOBBER_LIST2);				\
 707 +	} while (0);
 708 +
 709 +#define ft_event3(id, callback, param, param2, param3)		\
 710 +	do {							\
 711 +		long __ft_tmp1, __ft_tmp2, __ft_tmp3;		\
 712 +        __asm__ __volatile__(                                   \
 713 +            "1: jmp 2f                                    \n\t" \
 714 +	    " movq $" #id ", %%rdi			  \n\t" \
 715 +	    " call " #callback "                          \n\t" \
 716 +            __FT_EVENT_TABLE(id,1b,2f)				\
 717 +            "2:                                           \n\t" \
 718 +	    : __FT_TMP1(__ft_tmp1), __FT_TMP2(__ft_tmp2), __FT_TMP3(__ft_tmp3) \
 719 +	    : __FT_ARG1(param), __FT_ARG2(param2), __FT_ARG3(param3)	\
 720 +	    : __FT_CLOBBER_LIST3);				\
 721 +	} while (0);
 722 diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
 723 index 7bd3bd3..d38a5a7 100644
 724 --- a/arch/x86/kernel/Makefile
 725 +++ b/arch/x86/kernel/Makefile
 726 @@ -103,6 +103,8 @@ obj-$(CONFIG_UPROBES)			+= uprobes.o
 727  
 728  obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 729  
 730 +obj-$(CONFIG_FEATHER_TRACE)	+= ft_event.o
 731 +
 732  ###
 733  # 64 bit specific files
 734  ifeq ($(CONFIG_X86_64),y)
 735 diff --git a/arch/x86/kernel/ft_event.c b/arch/x86/kernel/ft_event.c
 736 new file mode 100644
 737 index 0000000..37cc332
 738 --- /dev/null
 739 +++ b/arch/x86/kernel/ft_event.c
 740 @@ -0,0 +1,118 @@
 741 +#include <linux/types.h>
 742 +
 743 +#include <litmus/feather_trace.h>
 744 +
 745 +/* the feather trace management functions assume
 746 + * exclusive access to the event table
 747 + */
 748 +
 749 +#ifndef CONFIG_DEBUG_RODATA
 750 +
 751 +#define BYTE_JUMP      0xeb
 752 +#define BYTE_JUMP_LEN  0x02
 753 +
 754 +/* for each event, there is an entry in the event table */
 755 +struct trace_event {
 756 +	long 	id;
 757 +	long	count;
 758 +	long	start_addr;
 759 +	long	end_addr;
 760 +};
 761 +
 762 +extern struct trace_event  __start___event_table[];
 763 +extern struct trace_event  __stop___event_table[];
 764 +
 765 +/* Workaround: if no events are defined, then the event_table section does not
 766 + * exist and the above references cause linker errors. This could probably be
 767 + * fixed by adjusting the linker script, but it is easier to maintain for us if
 768 + * we simply create a dummy symbol in the event table section.
 769 + */
 770 +int __event_table_dummy[0] __attribute__ ((section("__event_table")));
 771 +
 772 +int ft_enable_event(unsigned long id)
 773 +{
 774 +	struct trace_event* te = __start___event_table;
 775 +	int count = 0;
 776 +	char* delta;
 777 +	unsigned char* instr;
 778 +
 779 +	while (te < __stop___event_table) {
 780 +		if (te->id == id && ++te->count == 1) {
 781 +			instr  = (unsigned char*) te->start_addr;
 782 +			/* make sure we don't clobber something wrong */
 783 +			if (*instr == BYTE_JUMP) {
 784 +				delta  = (((unsigned char*) te->start_addr) + 1);
 785 +				*delta = 0;
 786 +			}
 787 +		}
 788 +		if (te->id == id)
 789 +			count++;
 790 +		te++;
 791 +	}
 792 +
 793 +	printk(KERN_DEBUG "ft_enable_event: enabled %d events\n", count);
 794 +	return count;
 795 +}
 796 +
 797 +int ft_disable_event(unsigned long id)
 798 +{
 799 +	struct trace_event* te = __start___event_table;
 800 +	int count = 0;
 801 +	char* delta;
 802 +	unsigned char* instr;
 803 +
 804 +	while (te < __stop___event_table) {
 805 +		if (te->id == id && --te->count == 0) {
 806 +			instr  = (unsigned char*) te->start_addr;
 807 +			if (*instr == BYTE_JUMP) {
 808 +				delta  = (((unsigned char*) te->start_addr) + 1);
 809 +				*delta = te->end_addr - te->start_addr -
 810 +					BYTE_JUMP_LEN;
 811 +			}
 812 +		}
 813 +		if (te->id == id)
 814 +			count++;
 815 +		te++;
 816 +	}
 817 +
 818 +	printk(KERN_DEBUG "ft_disable_event: disabled %d events\n", count);
 819 +	return count;
 820 +}
 821 +
 822 +int ft_disable_all_events(void)
 823 +{
 824 +	struct trace_event* te = __start___event_table;
 825 +	int count = 0;
 826 +	char* delta;
 827 +	unsigned char* instr;
 828 +
 829 +	while (te < __stop___event_table) {
 830 +		if (te->count) {
 831 +			instr  = (unsigned char*) te->start_addr;
 832 +			if (*instr == BYTE_JUMP) {
 833 +				delta  = (((unsigned char*) te->start_addr)
 834 +					  + 1);
 835 +				*delta = te->end_addr - te->start_addr -
 836 +					BYTE_JUMP_LEN;
 837 +				te->count = 0;
 838 +				count++;
 839 +			}
 840 +		}
 841 +		te++;
 842 +	}
 843 +	return count;
 844 +}
 845 +
 846 +int ft_is_event_enabled(unsigned long id)
 847 +{
 848 +	struct trace_event* te = __start___event_table;
 849 +
 850 +	while (te < __stop___event_table) {
 851 +		if (te->id == id)
 852 +			return te->count;
 853 +		te++;
 854 +	}
 855 +	return 0;
 856 +}
 857 +
 858 +#endif
 859 diff --git a/litmus/Kconfig b/litmus/Kconfig
 860 index 70ddbad..7456eb2 100644
 861 --- a/litmus/Kconfig
 862 +++ b/litmus/Kconfig
 863 @@ -4,6 +4,7 @@ menu "Tracing"
 864  
 865  config FEATHER_TRACE
 866  	bool "Feather-Trace Infrastructure"
 867 +	depends on !RELOCATABLE
 868  	default y
 869  	help
 870  	  Feather-Trace basic tracing infrastructure. Includes device file
 871 -- 
 872 1.8.1.2
 873 
 874 
 875 From e46b5c3c4264a15b363502bcb980e3587131d826 Mon Sep 17 00:00:00 2001
 876 From: Bjoern Brandenburg <bbb@mpi-sws.org>
 877 Date: Sun, 23 Jun 2013 12:00:35 +0200
 878 Subject: [PATCH 004/119] Feather-Trace: add generic ftdev device driver
 879 
 880 This patch adds the ftdev device driver, which is used to export
 881 samples collected with Feather-Trace to userspace.
 882 ---
 883  include/litmus/ftdev.h |  58 +++++++
 884  litmus/Makefile        |   2 +-
 885  litmus/ftdev.c         | 439 +++++++++++++++++++++++++++++++++++++++++++++++++
 886  3 files changed, 498 insertions(+), 1 deletion(-)
 887  create mode 100644 include/litmus/ftdev.h
 888  create mode 100644 litmus/ftdev.c
 889 
 890 diff --git a/include/litmus/ftdev.h b/include/litmus/ftdev.h
 891 new file mode 100644
 892 index 0000000..a566b0b
 893 --- /dev/null
 894 +++ b/include/litmus/ftdev.h
 895 @@ -0,0 +1,58 @@
 896 +#ifndef _LITMUS_FTDEV_H_
 897 +#define	_LITMUS_FTDEV_H_
 898 +
 899 +#include <litmus/feather_trace.h>
 900 +#include <litmus/feather_buffer.h>
 901 +#include <linux/mutex.h>
 902 +#include <linux/cdev.h>
 903 +
 904 +#define FTDEV_ENABLE_CMD 	0
 905 +#define FTDEV_DISABLE_CMD 	1
 906 +#define FTDEV_CALIBRATE		0x1410
 907 +
 908 +struct ftdev;
 909 +
 910 +/* return 0 if buffer can be opened, otherwise -$REASON */
 911 +typedef int  (*ftdev_can_open_t)(struct ftdev* dev, unsigned int buf_no);
 912 +/* return 0 on success, otherwise -$REASON */
 913 +typedef int  (*ftdev_alloc_t)(struct ftdev* dev, unsigned int buf_no);
 914 +typedef void (*ftdev_free_t)(struct ftdev* dev, unsigned int buf_no);
 915 +typedef long (*ftdev_calibrate_t)(struct ftdev* dev, unsigned int buf_no, unsigned long user_arg);
 916 +/* Let devices handle writes from userspace. No synchronization provided. */
 917 +typedef ssize_t (*ftdev_write_t)(struct ft_buffer* buf, size_t len, const char __user *from);
 918 +
 919 +struct ftdev_event;
 920 +
 921 +struct ftdev_minor {
 922 +	struct ft_buffer*	buf;
 923 +	unsigned int		readers;
 924 +	struct mutex		lock;
 925 +	/* FIXME: filter for authorized events */
 926 +	struct ftdev_event*	events;
 927 +	struct device*		device;
 928 +	struct ftdev*		ftdev;
 929 +};
 930 +
 931 +struct ftdev {
 932 +	dev_t			major;
 933 +	struct cdev		cdev;
 934 +	struct class*		class;
 935 +	const char*		name;
 936 +	struct ftdev_minor*	minor;
 937 +	unsigned int		minor_cnt;
 938 +	ftdev_alloc_t		alloc;
 939 +	ftdev_free_t		free;
 940 +	ftdev_can_open_t	can_open;
 941 +	ftdev_write_t		write;
 942 +	ftdev_calibrate_t	calibrate;
 943 +};
 944 +
 945 +struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size);
 946 +void free_ft_buffer(struct ft_buffer* buf);
 947 +
 948 +int ftdev_init(	struct ftdev* ftdev, struct module* owner,
 949 +		const int minor_cnt, const char* name);
 950 +void ftdev_exit(struct ftdev* ftdev);
 951 +int register_ftdev(struct ftdev* ftdev);
 952 +
 953 +#endif
 954 diff --git a/litmus/Makefile b/litmus/Makefile
 955 index 4c6130b..bca61e6 100644
 956 --- a/litmus/Makefile
 957 +++ b/litmus/Makefile
 958 @@ -2,4 +2,4 @@
 959  # Makefile for LITMUS^RT
 960  #
 961  
 962 -obj-$(CONFIG_FEATHER_TRACE) += ft_event.o
 963 +obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o
 964 diff --git a/litmus/ftdev.c b/litmus/ftdev.c
 965 new file mode 100644
 966 index 0000000..13f1d48
 967 --- /dev/null
 968 +++ b/litmus/ftdev.c
 969 @@ -0,0 +1,439 @@
 970 +#include <linux/sched.h>
 971 +#include <linux/fs.h>
 972 +#include <linux/slab.h>
 973 +#include <linux/cdev.h>
 974 +#include <asm/uaccess.h>
 975 +#include <linux/module.h>
 976 +#include <linux/device.h>
 977 +#include <linux/vmalloc.h>
 978 +
 979 +#include <litmus/feather_trace.h>
 980 +#include <litmus/ftdev.h>
 981 +
 982 +struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size)
 983 +{
 984 +	struct ft_buffer* buf;
 985 +	size_t total = (size + 1) * count;
 986 +	char* mem;
 987 +
 988 +	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 989 +	if (!buf)
 990 +		return NULL;
 991 +
 992 +
 993 +	mem = vmalloc(total);
 994 +
 995 +	if (!mem) {
 996 +		kfree(buf);
 997 +		return NULL;
 998 +	}
 999 +
1000 +	if (!init_ft_buffer(buf, count, size,
1001 +			    mem + (count * size),  /* markers at the end */
1002 +			    mem)) {                /* buffer objects     */
1003 +		vfree(mem);
1004 +		kfree(buf);
1005 +		return NULL;
1006 +	}
1007 +	return buf;
1008 +}
1009 +
1010 +void free_ft_buffer(struct ft_buffer* buf)
1011 +{
1012 +	if (buf) {
1013 +		vfree(buf->buffer_mem);
1014 +		kfree(buf);
1015 +	}
1016 +}
1017 +
1018 +struct ftdev_event {
1019 +	int id;
1020 +	struct ftdev_event* next;
1021 +};
1022 +
1023 +static int activate(struct ftdev_event** chain, int id)
1024 +{
1025 +	struct ftdev_event* ev = kmalloc(sizeof(*ev), GFP_KERNEL);
1026 +	if (ev) {
1027 +		printk(KERN_INFO
1028 +		       "Enabling feather-trace event %d.\n", (int) id);
1029 +		ft_enable_event(id);
1030 +		ev->id = id;
1031 +		ev->next = *chain;
1032 +		*chain    = ev;
1033 +	}
1034 +	return ev ? 0 : -ENOMEM;
1035 +}
1036 +
1037 +static void deactivate(struct ftdev_event** chain, int id)
1038 +{
1039 +	struct ftdev_event **cur = chain;
1040 +	struct ftdev_event *nxt;
1041 +	while (*cur) {
1042 +		if ((*cur)->id == id) {
1043 +			nxt   = (*cur)->next;
1044 +			kfree(*cur);
1045 +			*cur  = nxt;
1046 +			printk(KERN_INFO
1047 +			       "Disabling feather-trace event %d.\n", (int) id);
1048 +			ft_disable_event(id);
1049 +			break;
1050 +		}
1051 +		cur = &(*cur)->next;
1052 +	}
1053 +}
1054 +
1055 +static int ftdev_open(struct inode *in, struct file *filp)
1056 +{
1057 +	struct ftdev* ftdev;
1058 +	struct ftdev_minor* ftdm;
1059 +	unsigned int buf_idx = iminor(in);
1060 +	int err = 0;
1061 +
1062 +	ftdev = container_of(in->i_cdev, struct ftdev, cdev);
1063 +
1064 +	if (buf_idx >= ftdev->minor_cnt) {
1065 +		err = -ENODEV;
1066 +		goto out;
1067 +	}
1068 +	if (ftdev->can_open && (err = ftdev->can_open(ftdev, buf_idx)))
1069 +		goto out;
1070 +
1071 +	ftdm = ftdev->minor + buf_idx;
1072 +	ftdm->ftdev = ftdev;
1073 +	filp->private_data = ftdm;
1074 +
1075 +	if (mutex_lock_interruptible(&ftdm->lock)) {
1076 +		err = -ERESTARTSYS;
1077 +		goto out;
1078 +	}
1079 +
1080 +	if (!ftdm->readers && ftdev->alloc)
1081 +		err = ftdev->alloc(ftdev, buf_idx);
1082 +	if (0 == err)
1083 +		ftdm->readers++;
1084 +
1085 +	mutex_unlock(&ftdm->lock);
1086 +out:
1087 +	return err;
1088 +}
1089 +
1090 +static int ftdev_release(struct inode *in, struct file *filp)
1091 +{
1092 +	struct ftdev* ftdev;
1093 +	struct ftdev_minor* ftdm;
1094 +	unsigned int buf_idx = iminor(in);
1095 +	int err = 0;
1096 +
1097 +	ftdev = container_of(in->i_cdev, struct ftdev, cdev);
1098 +
1099 +	if (buf_idx >= ftdev->minor_cnt) {
1100 +		err = -ENODEV;
1101 +		goto out;
1102 +	}
1103 +	ftdm = ftdev->minor + buf_idx;
1104 +
1105 +	if (mutex_lock_interruptible(&ftdm->lock)) {
1106 +		err = -ERESTARTSYS;
1107 +		goto out;
1108 +	}
1109 +
1110 +	if (ftdm->readers == 1) {
1111 +		while (ftdm->events)
1112 +			deactivate(&ftdm->events, ftdm->events->id);
1113 +
1114 +		/* wait for any pending events to complete */
1115 +		set_current_state(TASK_UNINTERRUPTIBLE);
1116 +		schedule_timeout(HZ);
1117 +
1118 +		printk(KERN_ALERT "Failed trace writes: %u\n",
1119 +		       ftdm->buf->failed_writes);
1120 +
1121 +		if (ftdev->free)
1122 +			ftdev->free(ftdev, buf_idx);
1123 +	}
1124 +
1125 +	ftdm->readers--;
1126 +	mutex_unlock(&ftdm->lock);
1127 +out:
1128 +	return err;
1129 +}
1130 +
1131 +/* based on ft_buffer_read
1132 + * @returns < 0 : page fault
1133 + *          = 0 : no data available
1134 + *          = 1 : one slot copied
1135 + */
1136 +static int ft_buffer_copy_to_user(struct ft_buffer* buf, char __user *dest)
1137 +{
1138 +	unsigned int idx;
1139 +	int err = 0;
1140 +	if (buf->free_count != buf->slot_count) {
1141 +		/* data available */
1142 +		idx = buf->read_idx % buf->slot_count;
1143 +		if (buf->slots[idx] == SLOT_READY) {
1144 +			err = copy_to_user(dest, ((char*) buf->buffer_mem) +
1145 +					   idx * buf->slot_size,
1146 +					   buf->slot_size);
1147 +			if (err == 0) {
1148 +				/* copy ok */
1149 +				buf->slots[idx] = SLOT_FREE;
1150 +				buf->read_idx++;
1151 +				fetch_and_inc(&buf->free_count);
1152 +				err = 1;
1153 +			}
1154 +		}
1155 +	}
1156 +	return err;
1157 +}
1158 +
1159 +static ssize_t ftdev_read(struct file *filp,
1160 +			  char __user *to, size_t len, loff_t *f_pos)
1161 +{
1162 +	/* 	we ignore f_pos, this is strictly sequential */
1163 +
1164 +	ssize_t err = 0;
1165 +	size_t chunk;
1166 +	int copied;
1167 +	struct ftdev_minor* ftdm = filp->private_data;
1168 +
1169 +	if (mutex_lock_interruptible(&ftdm->lock)) {
1170 +		err = -ERESTARTSYS;
1171 +		goto out;
1172 +	}
1173 +
1174 +
1175 +	chunk = ftdm->buf->slot_size;
1176 +	while (len >= chunk) {
1177 +		copied = ft_buffer_copy_to_user(ftdm->buf, to);
1178 +		if (copied == 1) {
1179 +			len    -= chunk;
1180 +			to     += chunk;
1181 +			err    += chunk;
1182 +	        } else if (err == 0 && copied == 0 && ftdm->events) {
1183 +			/* Only wait if there are any events enabled and only
1184 +			 * if we haven't copied some data yet. We cannot wait
1185 +			 * here with copied data because that data would get
1186 +			 * lost if the task is interrupted (e.g., killed).
1187 +			 */
1188 +			mutex_unlock(&ftdm->lock);
1189 +			set_current_state(TASK_INTERRUPTIBLE);
1190 +
1191 +			schedule_timeout(50);
1192 +
1193 +			if (signal_pending(current)) {
1194 +				if (err == 0)
1195 +					/* nothing read yet, signal problem */
1196 +					err = -ERESTARTSYS;
1197 +				goto out;
1198 +			}
1199 +			if (mutex_lock_interruptible(&ftdm->lock)) {
1200 +				err = -ERESTARTSYS;
1201 +				goto out;
1202 +			}
1203 +		} else if (copied < 0) {
1204 +			/* page fault */
1205 +			err = copied;
1206 +			break;
1207 +		} else
1208 +			/* nothing left to get, return to user space */
1209 +			break;
1210 +	}
1211 +	mutex_unlock(&ftdm->lock);
1212 +out:
1213 +	return err;
1214 +}
1215 +
1216 +static long ftdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1217 +{
1218 +	long err = -ENOIOCTLCMD;
1219 +	struct ftdev_minor* ftdm = filp->private_data;
1220 +
1221 +	if (mutex_lock_interruptible(&ftdm->lock)) {
1222 +		err = -ERESTARTSYS;
1223 +		goto out;
1224 +	}
1225 +
1226 +	/* FIXME: check id against list of acceptable events */
1227 +
1228 +	switch (cmd) {
1229 +	case  FTDEV_ENABLE_CMD:
1230 +		if (activate(&ftdm->events, arg))
1231 +			err = -ENOMEM;
1232 +		else
1233 +			err = 0;
1234 +		break;
1235 +
1236 +	case FTDEV_DISABLE_CMD:
1237 +		deactivate(&ftdm->events, arg);
1238 +		err = 0;
1239 +		break;
1240 +
1241 +	case FTDEV_CALIBRATE:
1242 +		if (ftdm->ftdev->calibrate) {
1243 +			err = ftdm->ftdev->calibrate(ftdm->ftdev, iminor(filp->f_dentry->d_inode), arg);
1244 +		}
1245 +		break;
1246 +
1247 +	default:
1248 +		printk(KERN_DEBUG "ftdev: strange ioctl (%u, %lu)\n", cmd, arg);
1249 +	};
1250 +
1251 +	mutex_unlock(&ftdm->lock);
1252 +out:
1253 +	return err;
1254 +}
1255 +
1256 +static ssize_t ftdev_write(struct file *filp, const char __user *from,
1257 +			   size_t len, loff_t *f_pos)
1258 +{
1259 +	struct ftdev_minor* ftdm = filp->private_data;
1260 +	ssize_t err = -EINVAL;
1261 +	struct ftdev* ftdev = ftdm->ftdev;
1262 +
1263 +	/* dispatch write to buffer-specific code, if available */
1264 +	if (ftdev->write)
1265 +		err = ftdev->write(ftdm->buf, len, from);
1266 +
1267 +	return err;
1268 +}
1269 +
1270 +struct file_operations ftdev_fops = {
1271 +	.owner   = THIS_MODULE,
1272 +	.open    = ftdev_open,
1273 +	.release = ftdev_release,
1274 +	.write   = ftdev_write,
1275 +	.read    = ftdev_read,
1276 +	.unlocked_ioctl = ftdev_ioctl,
1277 +};
1278 +
1279 +int ftdev_init(	struct ftdev* ftdev, struct module* owner,
1280 +		const int minor_cnt, const char* name)
1281 +{
1282 +	int i, err;
1283 +
1284 +	BUG_ON(minor_cnt < 1);
1285 +
1286 +	cdev_init(&ftdev->cdev, &ftdev_fops);
1287 +	ftdev->name = name;
1288 +	ftdev->minor_cnt = minor_cnt;
1289 +	ftdev->cdev.owner = owner;
1290 +	ftdev->cdev.ops = &ftdev_fops;
1291 +	ftdev->alloc    = NULL;
1292 +	ftdev->free     = NULL;
1293 +	ftdev->can_open = NULL;
1294 +	ftdev->write	= NULL;
1295 +	ftdev->calibrate = NULL;
1296 +
1297 +	ftdev->minor = kcalloc(ftdev->minor_cnt, sizeof(*ftdev->minor),
1298 +			GFP_KERNEL);
1299 +	if (!ftdev->minor) {
1300 +		printk(KERN_WARNING "ftdev(%s): Could not allocate memory\n",
1301 +			ftdev->name);
1302 +		err = -ENOMEM;
1303 +		goto err_out;
1304 +	}
1305 +
1306 +	for (i = 0; i < ftdev->minor_cnt; i++) {
1307 +		mutex_init(&ftdev->minor[i].lock);
1308 +		ftdev->minor[i].readers = 0;
1309 +		ftdev->minor[i].buf     = NULL;
1310 +		ftdev->minor[i].events  = NULL;
1311 +	}
1312 +
1313 +	ftdev->class = class_create(owner, ftdev->name);
1314 +	if (IS_ERR(ftdev->class)) {
1315 +		err = PTR_ERR(ftdev->class);
1316 +		printk(KERN_WARNING "ftdev(%s): "
1317 +			"Could not create device class.\n", ftdev->name);
1318 +		goto err_dealloc;
1319 +	}
1320 +
1321 +	return 0;
1322 +
1323 +err_dealloc:
1324 +	kfree(ftdev->minor);
1325 +err_out:
1326 +	return err;
1327 +}
1328 +
1329 +/*
1330 + * Destroy minor devices up to, but not including, up_to.
1331 + */
1332 +static void ftdev_device_destroy(struct ftdev* ftdev, unsigned int up_to)
1333 +{
1334 +	dev_t minor_cntr;
1335 +
1336 +	if (up_to < 1)
1337 +		up_to = (ftdev->minor_cnt < 1) ? 0 : ftdev->minor_cnt;
1338 +
1339 +	for (minor_cntr = 0; minor_cntr < up_to; ++minor_cntr)
1340 +		device_destroy(ftdev->class, MKDEV(ftdev->major, minor_cntr));
1341 +}
1342 +
1343 +void ftdev_exit(struct ftdev* ftdev)
1344 +{
1345 +	printk("ftdev(%s): Exiting\n", ftdev->name);
1346 +	ftdev_device_destroy(ftdev, -1);
1347 +	cdev_del(&ftdev->cdev);
1348 +	unregister_chrdev_region(MKDEV(ftdev->major, 0), ftdev->minor_cnt);
1349 +	class_destroy(ftdev->class);
1350 +	kfree(ftdev->minor);
1351 +}
1352 +
1353 +int register_ftdev(struct ftdev* ftdev)
1354 +{
1355 +	struct device **device;
1356 +	dev_t trace_dev_tmp, minor_cntr;
1357 +	int err;
1358 +
1359 +	err = alloc_chrdev_region(&trace_dev_tmp, 0, ftdev->minor_cnt,
1360 +			ftdev->name);
1361 +	if (err) {
1362 +		printk(KERN_WARNING "ftdev(%s): "
1363 +		       "Could not allocate char. device region (%d minors)\n",
1364 +		       ftdev->name, ftdev->minor_cnt);
1365 +		goto err_out;
1366 +	}
1367 +
1368 +	ftdev->major = MAJOR(trace_dev_tmp);
1369 +
1370 +	err = cdev_add(&ftdev->cdev, trace_dev_tmp, ftdev->minor_cnt);
1371 +	if (err) {
1372 +		printk(KERN_WARNING "ftdev(%s): "
1373 +		       "Could not add cdev for major %u with %u minor(s).\n",
1374 +		       ftdev->name, ftdev->major, ftdev->minor_cnt);
1375 +		goto err_unregister;
1376 +	}
1377 +
1378 +	/* create the minor device(s) */
1379 +	for (minor_cntr = 0; minor_cntr < ftdev->minor_cnt; ++minor_cntr)
1380 +	{
1381 +		trace_dev_tmp = MKDEV(ftdev->major, minor_cntr);
1382 +		device = &ftdev->minor[minor_cntr].device;
1383 +
1384 +		*device = device_create(ftdev->class, NULL, trace_dev_tmp, NULL,
1385 +				"litmus/%s%d", ftdev->name, minor_cntr);
1386 +		if (IS_ERR(*device)) {
1387 +			err = PTR_ERR(*device);
1388 +			printk(KERN_WARNING "ftdev(%s): "
1389 +				"Could not create device major/minor number "
1390 +				"%u/%u\n", ftdev->name, ftdev->major,
1391 +				minor_cntr);
1392 +			printk(KERN_WARNING "ftdev(%s): "
1393 +				"will attempt deletion of allocated devices.\n",
1394 +				ftdev->name);
1395 +			goto err_minors;
1396 +		}
1397 +	}
1398 +
1399 +	return 0;
1400 +
1401 +err_minors:
1402 +	ftdev_device_destroy(ftdev, minor_cntr);
1403 +	cdev_del(&ftdev->cdev);
1404 +err_unregister:
1405 +	unregister_chrdev_region(MKDEV(ftdev->major, 0), ftdev->minor_cnt);
1406 +err_out:
1407 +	return err;
1408 +}
1409 -- 
1410 1.8.1.2
1411 
1412 
1413 From 7b317d9036b3fc0280327586ef52dfa6cb6dd250 Mon Sep 17 00:00:00 2001
1414 From: Bjoern Brandenburg <bbb@mpi-sws.org>
1415 Date: Sun, 23 Jun 2013 14:40:52 +0200
1416 Subject: [PATCH 005/119] Feather-Trace: add LITMUS^RT overhead tracing
1417  infrastructure
1418 
1419 This patch adds the main infrastructure for tracing overheads in
1420 LITMUS^RT.  It does not yet introduce any tracepoints into the kernel.
1421 ---
1422  include/litmus/trace.h | 142 +++++++++++++
1423  litmus/Kconfig         |  25 +++
1424  litmus/Makefile        |   1 +
1425  litmus/trace.c         | 562 +++++++++++++++++++++++++++++++++++++++++++++++++
1426  4 files changed, 730 insertions(+)
1427  create mode 100644 include/litmus/trace.h
1428  create mode 100644 litmus/trace.c
1429 
1430 diff --git a/include/litmus/trace.h b/include/litmus/trace.h
1431 new file mode 100644
1432 index 0000000..6017872
1433 --- /dev/null
1434 +++ b/include/litmus/trace.h
1435 @@ -0,0 +1,142 @@
1436 +#ifndef _SYS_TRACE_H_
1437 +#define	_SYS_TRACE_H_
1438 +
1439 +#ifdef CONFIG_SCHED_OVERHEAD_TRACE
1440 +
1441 +
1442 +#include <litmus/feather_trace.h>
1443 +#include <litmus/feather_buffer.h>
1444 +
1445 +
1446 +/*********************** TIMESTAMPS ************************/
1447 +
1448 +enum task_type_marker {
1449 +	TSK_BE,
1450 +	TSK_RT,
1451 +	TSK_UNKNOWN
1452 +};
1453 +
1454 +struct timestamp {
1455 +	uint64_t		timestamp:48;
1456 +	uint64_t		pid:16;
1457 +	uint32_t		seq_no;
1458 +	uint8_t			cpu;
1459 +	uint8_t			event;
1460 +	uint8_t			task_type:2;
1461 +	uint8_t			irq_flag:1;
1462 +	uint8_t			irq_count:5;
1463 +};
1464 +
1465 +/* tracing callbacks */
1466 +feather_callback void msg_sent(unsigned long event, unsigned long to);
1467 +feather_callback void msg_received(unsigned long event);
1468 +
1469 +#define MSG_TIMESTAMP_SENT(id, to) \
1470 +	ft_event1(id, msg_sent, (unsigned long) to);
1471 +
1472 +#define MSG_TIMESTAMP_RECEIVED(id) \
1473 +	ft_event0(id, msg_received);
1474 +
1475 +feather_callback void save_cpu_timestamp(unsigned long event);
1476 +feather_callback void save_cpu_timestamp_time(unsigned long event, unsigned long time_ptr);
1477 +feather_callback void save_cpu_timestamp_irq(unsigned long event, unsigned long irq_count_ptr);
1478 +feather_callback void save_cpu_timestamp_task(unsigned long event, unsigned long t_ptr);
1479 +feather_callback void save_cpu_timestamp_def(unsigned long event, unsigned long type);
1480 +feather_callback void save_cpu_task_latency(unsigned long event, unsigned long when_ptr);
1481 +
1482 +#define CPU_TIMESTAMP_TIME(id, time_ptr) \
1483 +	ft_event1(id, save_cpu_timestamp_time, (unsigned long) time_ptr)
1484 +
1485 +#define CPU_TIMESTAMP_IRQ(id, irq_count_ptr) \
1486 +	ft_event1(id, save_cpu_timestamp_irq, (unsigned long) irq_count_ptr)
1487 +
1488 +#define CPU_TIMESTAMP(id) ft_event0(id, save_cpu_timestamp)
1489 +
1490 +#define CPU_DTIMESTAMP(id, def)  ft_event1(id, save_cpu_timestamp_def, (unsigned long) def)
1491 +
1492 +#define CPU_TIMESTAMP_CUR(id) CPU_DTIMESTAMP(id, is_realtime(current) ? TSK_RT : TSK_BE)
1493 +
1494 +#define CPU_TTIMESTAMP(id, task) \
1495 +	ft_event1(id, save_cpu_timestamp_task, (unsigned long) task)
1496 +
1497 +#define CPU_LTIMESTAMP(id, task) \
1498 +	ft_event1(id, save_cpu_task_latency, (unsigned long) task)
1499 +
1500 +#else /* !CONFIG_SCHED_OVERHEAD_TRACE */
1501 +
1502 +#define MSG_TIMESTAMP_SENT(id, to)
1503 +#define MSG_TIMESTAMP_RECEIVED(id)
1504 +
1505 +#define CPU_TIMESTAMP_TIME(id, time_ptr)
1506 +#define CPU_TIMESTAMP_IRQ(id, irq_count_ptr)
1507 +#define CPU_TIMESTAMP(id)
1508 +#define CPU_DTIMESTAMP(id, def)
1509 +#define CPU_TIMESTAMP_CUR(id)
1510 +#define CPU_TTIMESTAMP(id, task)
1511 +#define CPU_LTIMESTAMP(id, task)
1512 +
1513 +#endif
1514 +
1515 +
1516 +/* Convention for timestamps
1517 + * =========================
1518 + *
1519 + * In order to process the trace files with a common tool, we use the following
1520 + * convention to measure execution times: The end time id of a code segment is
1521 + * always the next number after the start time event id.
1522 + */
1523 +
1524 +#define __TS_SYSCALL_IN_START(p)	CPU_TIMESTAMP_TIME(10, p)
1525 +#define __TS_SYSCALL_IN_END(p)		CPU_TIMESTAMP_IRQ(11, p)
1526 +
1527 +#define TS_SYSCALL_OUT_START		CPU_TIMESTAMP_CUR(20)
1528 +#define TS_SYSCALL_OUT_END		CPU_TIMESTAMP_CUR(21)
1529 +
1530 +#define TS_LOCK_START			CPU_TIMESTAMP_CUR(30)
1531 +#define TS_LOCK_END			CPU_TIMESTAMP_CUR(31)
1532 +
1533 +#define TS_LOCK_SUSPEND			CPU_TIMESTAMP_CUR(38)
1534 +#define TS_LOCK_RESUME			CPU_TIMESTAMP_CUR(39)
1535 +
1536 +#define TS_UNLOCK_START			CPU_TIMESTAMP_CUR(40)
1537 +#define TS_UNLOCK_END			CPU_TIMESTAMP_CUR(41)
1538 +
1539 +#define TS_SCHED_START			CPU_DTIMESTAMP(100, TSK_UNKNOWN) /* we only
1540 +								      * care
1541 +								      * about
1542 +								      * next */
1543 +#define TS_SCHED_END(t)			CPU_TTIMESTAMP(101, t)
1544 +#define TS_SCHED2_START(t) 		CPU_TTIMESTAMP(102, t)
1545 +#define TS_SCHED2_END(t)       		CPU_TTIMESTAMP(103, t)
1546 +
1547 +#define TS_CXS_START(t)			CPU_TTIMESTAMP(104, t)
1548 +#define TS_CXS_END(t)			CPU_TTIMESTAMP(105, t)
1549 +
1550 +#define TS_RELEASE_START		CPU_DTIMESTAMP(106, TSK_RT)
1551 +#define TS_RELEASE_END			CPU_DTIMESTAMP(107, TSK_RT)
1552 +
1553 +#define TS_TICK_START(t)		CPU_TTIMESTAMP(110, t)
1554 +#define TS_TICK_END(t) 			CPU_TTIMESTAMP(111, t)
1555 +
1556 +#define TS_QUANTUM_BOUNDARY_START	CPU_TIMESTAMP_CUR(112)
1557 +#define TS_QUANTUM_BOUNDARY_END		CPU_TIMESTAMP_CUR(113)
1558 +
1559 +
1560 +#define TS_PLUGIN_SCHED_START		/* TIMESTAMP(120) */  /* currently unused */
1561 +#define TS_PLUGIN_SCHED_END		/* TIMESTAMP(121) */
1562 +
1563 +#define TS_PLUGIN_TICK_START		/* TIMESTAMP(130) */
1564 +#define TS_PLUGIN_TICK_END		/* TIMESTAMP(131) */
1565 +
1566 +#define TS_ENTER_NP_START		CPU_TIMESTAMP(140)
1567 +#define TS_ENTER_NP_END			CPU_TIMESTAMP(141)
1568 +
1569 +#define TS_EXIT_NP_START		CPU_TIMESTAMP(150)
1570 +#define TS_EXIT_NP_END			CPU_TIMESTAMP(151)
1571 +
1572 +#define TS_SEND_RESCHED_START(c)	MSG_TIMESTAMP_SENT(190, c)
1573 +#define TS_SEND_RESCHED_END		MSG_TIMESTAMP_RECEIVED(191)
1574 +
1575 +#define TS_RELEASE_LATENCY(when)	CPU_LTIMESTAMP(208, &(when))
1576 +
1577 +#endif /* !_SYS_TRACE_H_ */
1578 diff --git a/litmus/Kconfig b/litmus/Kconfig
1579 index 7456eb2..0c7e06b 100644
1580 --- a/litmus/Kconfig
1581 +++ b/litmus/Kconfig
1582 @@ -24,6 +24,31 @@ config FEATHER_TRACE
1583  	  you still need to enable SCHED_TASK_TRACE and/or SCHED_OVERHEAD_TRACE to
1584  	  actually enable any events.
1585  
1586 +config SCHED_OVERHEAD_TRACE
1587 +	bool "Record timestamps for overhead measurements"
1588 +	depends on FEATHER_TRACE
1589 +	default y
1590 +	help
1591 +	  Export event stream for overhead tracing.
1592 +	  Say Yes for overhead tracing.
1593 +
1594 +config SCHED_OVERHEAD_TRACE_SHIFT
1595 +       int "Buffer size for Feather-Trace overhead data"
1596 +       depends on SCHED_OVERHEAD_TRACE
1597 +       range 15 32
1598 +       default 22
1599 +       help
1600 +
1601 +         Select the buffer size for the Feather-Trace overhead tracing
1602 +         infrastructure (/dev/litmus/ft_trace0 & ftcat) as a power of two.  The
1603 +         larger the buffer, the less likely the chance of buffer overflows if
1604 +         the ftcat process is starved by real-time activity. In machines with
1605 +         large memories, large buffer sizes are recommended.
1606 +
1607 +	 Examples: 16 =>   2 MB
1608 +		   24 => 512 MB
1609 +		   26 =>  2G MB
1610 +
1611  endmenu
1612  
1613  endmenu
1614 diff --git a/litmus/Makefile b/litmus/Makefile
1615 index bca61e6..99f90c3 100644
1616 --- a/litmus/Makefile
1617 +++ b/litmus/Makefile
1618 @@ -3,3 +3,4 @@
1619  #
1620  
1621  obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o
1622 +obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o
1623 diff --git a/litmus/trace.c b/litmus/trace.c
1624 new file mode 100644
1625 index 0000000..a378623
1626 --- /dev/null
1627 +++ b/litmus/trace.c
1628 @@ -0,0 +1,562 @@
1629 +#include <linux/sched.h>
1630 +#include <linux/module.h>
1631 +#include <linux/uaccess.h>
1632 +
1633 +#include <litmus/ftdev.h>
1634 +#include <litmus/trace.h>
1635 +
1636 +/* dummy definition of is_realtime() */
1637 +#define is_realtime(t) (0)
1638 +
1639 +/******************************************************************************/
1640 +/*                          Allocation                                        */
1641 +/******************************************************************************/
1642 +
1643 +static struct ftdev cpu_overhead_dev;
1644 +static struct ftdev msg_overhead_dev;
1645 +
1646 +#define cpu_trace_ts_buf(cpu) cpu_overhead_dev.minor[(cpu)].buf
1647 +#define msg_trace_ts_buf(cpu) msg_overhead_dev.minor[(cpu)].buf
1648 +
1649 +DEFINE_PER_CPU(atomic_t, irq_fired_count;)
1650 +DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, cpu_irq_fired_count);
1651 +
1652 +static DEFINE_PER_CPU(unsigned int, cpu_ts_seq_no);
1653 +static DEFINE_PER_CPU(unsigned int, msg_ts_seq_no);
1654 +
1655 +static int64_t cycle_offset[NR_CPUS][NR_CPUS];
1656 +
1657 +void ft_irq_fired(void)
1658 +{
1659 +	/* Only called with preemptions disabled.  */
1660 +	atomic_inc(&__get_cpu_var(irq_fired_count));
1661 +	atomic_inc(&__get_cpu_var(cpu_irq_fired_count));
1662 +}
1663 +
1664 +static inline void clear_irq_fired(void)
1665 +{
1666 +	atomic_set(&__raw_get_cpu_var(irq_fired_count), 0);
1667 +}
1668 +
1669 +static inline unsigned int get_and_clear_irq_fired(void)
1670 +{
1671 +	/* This is potentially not atomic  since we might migrate if
1672 +	 * preemptions are not disabled. As a tradeoff between
1673 +	 * accuracy and tracing overheads, this seems acceptable.
1674 +	 * If it proves to be a problem, then one could add a callback
1675 +	 * from the migration code to invalidate irq_fired_count.
1676 +	 */
1677 +	return atomic_xchg(&__raw_get_cpu_var(irq_fired_count), 0);
1678 +}
1679 +
1680 +static inline unsigned int get_and_clear_irq_fired_for_cpu(int cpu)
1681 +{
1682 +	return atomic_xchg(&per_cpu(irq_fired_count, cpu), 0);
1683 +}
1684 +
1685 +static inline void cpu_clear_irq_fired(void)
1686 +{
1687 +	atomic_set(&__raw_get_cpu_var(cpu_irq_fired_count), 0);
1688 +}
1689 +
1690 +static inline unsigned int cpu_get_and_clear_irq_fired(void)
1691 +{
1692 +	return atomic_xchg(&__raw_get_cpu_var(cpu_irq_fired_count), 0);
1693 +}
1694 +
1695 +static inline void save_irq_flags(struct timestamp *ts, unsigned int irq_count)
1696 +{
1697 +	/* Store how many interrupts occurred. */
1698 +	ts->irq_count = irq_count;
1699 +	/* Extra flag because ts->irq_count overflows quickly. */
1700 +	ts->irq_flag  = irq_count > 0;
1701 +}
1702 +
1703 +#define NO_IRQ_COUNT 0
1704 +#define LOCAL_IRQ_COUNT 1
1705 +#define REMOTE_IRQ_COUNT 2
1706 +
1707 +#define DO_NOT_RECORD_TIMESTAMP 0
1708 +#define RECORD_LOCAL_TIMESTAMP 1
1709 +#define RECORD_OFFSET_TIMESTAMP 2
1710 +
1711 +static inline void __write_record(
1712 +	uint8_t event,
1713 +	uint8_t type,
1714 +	uint16_t pid_fragment,
1715 +	unsigned int irq_count,
1716 +	int record_irq,
1717 +	int hide_irq,
1718 +	uint64_t timestamp,
1719 +	int record_timestamp,
1720 +
1721 +	int only_single_writer,
1722 +	int is_cpu_timestamp,
1723 +	int local_cpu,
1724 +	uint8_t other_cpu)
1725 +{
1726 +	unsigned long flags;
1727 +	unsigned int seq_no;
1728 +	struct timestamp *ts;
1729 +	int cpu;
1730 +	struct ft_buffer* buf;
1731 +
1732 +	/* Avoid preemptions while recording the timestamp. This reduces the
1733 +	 * number of "out of order" timestamps in the stream and makes
1734 +	 * post-processing easier. */
1735 +
1736 +	local_irq_save(flags);
1737 +
1738 +	if (local_cpu)
1739 +		cpu = smp_processor_id();
1740 +	else
1741 +		cpu = other_cpu;
1742 +
1743 +	/* resolved during function inlining */
1744 +	if (is_cpu_timestamp) {
1745 +		seq_no = __get_cpu_var(cpu_ts_seq_no)++;
1746 +		buf = cpu_trace_ts_buf(cpu);
1747 +	} else {
1748 +		seq_no = fetch_and_inc((int *) &per_cpu(msg_ts_seq_no, cpu));
1749 +		buf = msg_trace_ts_buf(cpu);
1750 +	}
1751 +
1752 +	/* If buf is non-NULL here, then the buffer cannot be deallocated until
1753 +	 * we turn interrupts on again. This is because free_timestamp_buffer()
1754 +	 * indirectly causes TLB invalidations due to modifications of the
1755 +	 * kernel address space, namely via vfree() in free_ft_buffer(), which
1756 +	 * cannot be processed until we turn on interrupts again.
1757 +	 */
1758 +
1759 +	if (buf &&
1760 +	    (only_single_writer /* resolved during function inlining */
1761 +	     ? ft_buffer_start_single_write(buf, (void**)  &ts)
1762 +	     : ft_buffer_start_write(buf, (void**) &ts))) {
1763 +		ts->event     = event;
1764 +		ts->seq_no    = seq_no;
1765 +
1766 +		ts->task_type = type;
1767 +		ts->pid	      = pid_fragment;
1768 +
1769 +		ts->cpu       = cpu;
1770 +
1771 +		if (record_irq) {
1772 +			if (local_cpu)
1773 +				irq_count = cpu_get_and_clear_irq_fired();
1774 +			else
1775 +				irq_count = get_and_clear_irq_fired_for_cpu(cpu);
1776 +		}
1777 +
1778 +		save_irq_flags(ts, irq_count - hide_irq);
1779 +
1780 +		if (record_timestamp)
1781 +			timestamp = ft_timestamp();
1782 +		if (record_timestamp == RECORD_OFFSET_TIMESTAMP)
1783 +			timestamp += cycle_offset[smp_processor_id()][cpu];
1784 +
1785 +		ts->timestamp = timestamp;
1786 +		ft_buffer_finish_write(buf, ts);
1787 +	}
1788 +
1789 +	local_irq_restore(flags);
1790 +}
1791 +
1792 +
1793 +static inline void write_cpu_timestamp(
1794 +	uint8_t event,
1795 +	uint8_t type,
1796 +	uint16_t pid_fragment,
1797 +	unsigned int irq_count,
1798 +	int record_irq,
1799 +	int hide_irq,
1800 +	uint64_t timestamp,
1801 +	int record_timestamp)
1802 +{
1803 +	__write_record(event, type,
1804 +		       pid_fragment,
1805 +		       irq_count, record_irq, hide_irq,
1806 +		       timestamp, record_timestamp,
1807 +		       1 /* only_single_writer */,
1808 +		       1 /* is_cpu_timestamp */,
1809 +		       1 /* local_cpu */,
1810 +		       0xff /* other_cpu */);
1811 +}
1812 +
1813 +static inline void save_msg_timestamp(
1814 +	uint8_t event,
1815 +	int hide_irq)
1816 +{
1817 +	struct task_struct *t  = current;
1818 +	__write_record(event, is_realtime(t) ? TSK_RT : TSK_BE,
1819 +		       t->pid,
1820 +		       0, LOCAL_IRQ_COUNT, hide_irq,
1821 +		       0, RECORD_LOCAL_TIMESTAMP,
1822 +		       0 /* only_single_writer */,
1823 +		       0 /* is_cpu_timestamp */,
1824 +		       1 /* local_cpu */,
1825 +		       0xff /* other_cpu */);
1826 +}
1827 +
1828 +static inline void save_remote_msg_timestamp(
1829 +	uint8_t event,
1830 +	uint8_t remote_cpu)
1831 +{
1832 +	struct task_struct *t  = current;
1833 +	__write_record(event, is_realtime(t) ? TSK_RT : TSK_BE,
1834 +		       t->pid,
1835 +		       0, REMOTE_IRQ_COUNT, 0,
1836 +		       0, RECORD_OFFSET_TIMESTAMP,
1837 +		       0 /* only_single_writer */,
1838 +		       0 /* is_cpu_timestamp */,
1839 +		       0 /* local_cpu */,
1840 +		       remote_cpu);
1841 +}
1842 +
1843 +feather_callback void save_cpu_timestamp_def(unsigned long event,
1844 +					     unsigned long type)
1845 +{
1846 +	write_cpu_timestamp(event, type,
1847 +			    current->pid,
1848 +			    0, LOCAL_IRQ_COUNT, 0,
1849 +			    0, RECORD_LOCAL_TIMESTAMP);
1850 +}
1851 +
1852 +feather_callback void save_cpu_timestamp_task(unsigned long event,
1853 +					      unsigned long t_ptr)
1854 +{
1855 +	struct task_struct *t = (struct task_struct *) t_ptr;
1856 +	int rt = is_realtime(t);
1857 +
1858 +	write_cpu_timestamp(event, rt ? TSK_RT : TSK_BE,
1859 +			    t->pid,
1860 +			    0, LOCAL_IRQ_COUNT, 0,
1861 +			    0, RECORD_LOCAL_TIMESTAMP);
1862 +}
1863 +
1864 +feather_callback void save_cpu_task_latency(unsigned long event,
1865 +					    unsigned long when_ptr)
1866 +{
1867 +	lt_t now = litmus_clock();
1868 +	lt_t *when = (lt_t*) when_ptr;
1869 +
1870 +	write_cpu_timestamp(event, TSK_RT,
1871 +			    0,
1872 +			    0, LOCAL_IRQ_COUNT, 0,
1873 +			    now - *when, DO_NOT_RECORD_TIMESTAMP);
1874 +}
1875 +
1876 +/* fake timestamp to user-reported time */
1877 +feather_callback void save_cpu_timestamp_time(unsigned long event,
1878 +			 unsigned long ptr)
1879 +{
1880 +	uint64_t* time = (uint64_t*) ptr;
1881 +
1882 +	write_cpu_timestamp(event, is_realtime(current) ? TSK_RT : TSK_BE,
1883 +			    current->pid,
1884 +			    0, LOCAL_IRQ_COUNT, 0,
1885 +			    *time, DO_NOT_RECORD_TIMESTAMP);
1886 +}
1887 +
1888 +/* Record user-reported IRQ count */
1889 +feather_callback void save_cpu_timestamp_irq(unsigned long event,
1890 +			unsigned long irq_counter_ptr)
1891 +{
1892 +	uint64_t* irqs = (uint64_t*) irq_counter_ptr;
1893 +
1894 +	write_cpu_timestamp(event, is_realtime(current) ? TSK_RT : TSK_BE,
1895 +			    current->pid,
1896 +			    *irqs, NO_IRQ_COUNT, 0,
1897 +			    0, RECORD_LOCAL_TIMESTAMP);
1898 +}
1899 +
1900 +
1901 +feather_callback void msg_sent(unsigned long event, unsigned long to)
1902 +{
1903 +	save_remote_msg_timestamp(event, to);
1904 +}
1905 +
1906 +/* Suppresses one IRQ from the irq count. Used by TS_SEND_RESCHED_END, which is
1907 + * called from within an interrupt that is expected. */
1908 +feather_callback void msg_received(unsigned long event)
1909 +{
1910 +	save_msg_timestamp(event, 1);
1911 +}
1912 +
1913 +static void __add_timestamp_user(struct timestamp *pre_recorded)
1914 +{
1915 +	unsigned long flags;
1916 +	unsigned int seq_no;
1917 +	struct timestamp *ts;
1918 +	struct ft_buffer* buf;
1919 +	int cpu;
1920 +
1921 +	local_irq_save(flags);
1922 +
1923 +	cpu = smp_processor_id();
1924 +	buf = cpu_trace_ts_buf(cpu);
1925 +
1926 +	seq_no = __get_cpu_var(cpu_ts_seq_no)++;
1927 +	if (buf && ft_buffer_start_single_write(buf, (void**)  &ts)) {
1928 +		*ts = *pre_recorded;
1929 +		ts->seq_no = seq_no;
1930 +		ts->cpu	   = raw_smp_processor_id();
1931 +	        save_irq_flags(ts, get_and_clear_irq_fired());
1932 +		ft_buffer_finish_write(buf, ts);
1933 +	}
1934 +
1935 +	local_irq_restore(flags);
1936 +}
1937 +
1938 +/******************************************************************************/
1939 +/*                        DEVICE FILE DRIVER                                  */
1940 +/******************************************************************************/
1941 +
1942 +struct calibrate_info {
1943 +	atomic_t ready;
1944 +
1945 +	uint64_t cycle_count;
1946 +};
1947 +
1948 +static void calibrate_helper(void *_info)
1949 +{
1950 +	struct calibrate_info *info = _info;
1951 +	/* check in with master */
1952 +	atomic_inc(&info->ready);
1953 +
1954 +	/* wait for master to signal start */
1955 +	while (atomic_read(&info->ready))
1956 +		cpu_relax();
1957 +
1958 +	/* report time stamp */
1959 +	info->cycle_count = ft_timestamp();
1960 +
1961 +	/* tell master that we are done */
1962 +	atomic_inc(&info->ready);
1963 +}
1964 +
1965 +
1966 +static int64_t calibrate_cpu(int cpu)
1967 +{
1968 +	uint64_t cycles;
1969 +	struct calibrate_info info;
1970 +	unsigned long flags;
1971 +	int64_t  delta;
1972 +
1973 +	atomic_set(&info.ready, 0);
1974 +	info.cycle_count = 0;
1975 +	smp_wmb();
1976 +
1977 +	smp_call_function_single(cpu, calibrate_helper, &info, 0);
1978 +
1979 +	/* wait for helper to become active */
1980 +	while (!atomic_read(&info.ready))
1981 +		cpu_relax();
1982 +
1983 +	/* avoid interrupt interference */
1984 +	local_irq_save(flags);
1985 +
1986 +	/* take measurement */
1987 +	atomic_set(&info.ready, 0);
1988 +	smp_wmb();
1989 +	cycles = ft_timestamp();
1990 +
1991 +	/* wait for helper reading */
1992 +	while (!atomic_read(&info.ready))
1993 +		cpu_relax();
1994 +
1995 +	/* positive offset: the other guy is ahead of us */
1996 +	delta  = (int64_t) info.cycle_count;
1997 +	delta -= (int64_t) cycles;
1998 +
1999 +	local_irq_restore(flags);
2000 +
2001 +	return delta;
2002 +}
2003 +
2004 +#define NUM_SAMPLES 10
2005 +
2006 +static long calibrate_tsc_offsets(struct ftdev* ftdev, unsigned int idx,
2007 +				  unsigned long uarg)
2008 +{
2009 +	int cpu, self, i;
2010 +	int64_t delta, sample;
2011 +
2012 +	preempt_disable();
2013 +	self = smp_processor_id();
2014 +
2015 +	if (uarg)
2016 +		printk(KERN_INFO "Feather-Trace: determining TSC offsets for P%d\n", self);
2017 +
2018 +	for_each_online_cpu(cpu)
2019 +		if (cpu != self) {
2020 +			delta = calibrate_cpu(cpu);
2021 +			for (i = 1; i < NUM_SAMPLES; i++) {
2022 +			        sample = calibrate_cpu(cpu);
2023 +				delta = sample < delta ? sample : delta;
2024 +			}
2025 +
2026 +			cycle_offset[self][cpu] = delta;
2027 +
2028 +			if (uarg)
2029 +				printk(KERN_INFO "Feather-Trace: TSC offset for P%d->P%d is %lld cycles.\n",
2030 +				       self, cpu, cycle_offset[self][cpu]);
2031 +		}
2032 +
2033 +	preempt_enable();
2034 +	return 0;
2035 +}
2036 +
2037 +#define NO_TIMESTAMPS (2 << CONFIG_SCHED_OVERHEAD_TRACE_SHIFT)
2038 +
2039 +static int alloc_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
2040 +{
2041 +	unsigned int count = NO_TIMESTAMPS;
2042 +
2043 +	/* An overhead-tracing timestamp should be exactly 16 bytes long. */
2044 +	BUILD_BUG_ON(sizeof(struct timestamp) != 16);
2045 +
2046 +	while (count && !ftdev->minor[idx].buf) {
2047 +		printk("time stamp buffer: trying to allocate %u time stamps for minor=%u.\n", count, idx);
2048 +		ftdev->minor[idx].buf = alloc_ft_buffer(count, sizeof(struct timestamp));
2049 +		count /= 2;
2050 +	}
2051 +	return ftdev->minor[idx].buf ? 0 : -ENOMEM;
2052 +}
2053 +
2054 +static void free_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
2055 +{
2056 +	ftdev->minor[idx].buf = NULL;
2057 +	/* Make sure all cores have actually seen buf == NULL before
2058 +	 * yanking out the mappings from underneath them. */
2059 +	smp_wmb();
2060 +	free_ft_buffer(ftdev->minor[idx].buf);
2061 +}
2062 +
2063 +static ssize_t write_timestamp_from_user(struct ft_buffer* buf, size_t len,
2064 +					 const char __user *from)
2065 +{
2066 +	ssize_t consumed = 0;
2067 +	struct timestamp ts;
2068 +
2069 +	/* don't give us partial timestamps */
2070 +	if (len % sizeof(ts))
2071 +		return -EINVAL;
2072 +
2073 +	while (len >= sizeof(ts)) {
2074 +		if (copy_from_user(&ts, from, sizeof(ts))) {
2075 +			consumed = -EFAULT;
2076 +			goto out;
2077 +		}
2078 +		len  -= sizeof(ts);
2079 +		from += sizeof(ts);
2080 +		consumed += sizeof(ts);
2081 +
2082 +		/* Note: this always adds to the buffer of the CPU-local
2083 +		 * device, not necessarily to the device that the system call
2084 +		 * was invoked on. This is admittedly a bit ugly, but requiring
2085 +		 * tasks to only write to the appropriate device would make
2086 +		 * tracing from userspace under global and clustered scheduling
2087 +		 * exceedingly difficult. Writing to remote buffers would
2088 +		 * require to not use ft_buffer_start_single_write(), which we
2089 +		 * want to do to reduce the number of atomic ops in the common
2090 +		 * case (which is the recording of CPU-local scheduling
2091 +		 * overheads).
2092 +		 */
2093 +		__add_timestamp_user(&ts);
2094 +	}
2095 +
2096 +out:
2097 +	return consumed;
2098 +}
2099 +
2100 +static int __init init_cpu_ft_overhead_trace(void)
2101 +{
2102 +	int err, cpu;
2103 +
2104 +	printk("Initializing Feather-Trace per-cpu overhead tracing device.\n");
2105 +	err = ftdev_init(&cpu_overhead_dev, THIS_MODULE,
2106 +			 num_online_cpus(), "ft_cpu_trace");
2107 +	if (err)
2108 +		goto err_out;
2109 +
2110 +	cpu_overhead_dev.alloc = alloc_timestamp_buffer;
2111 +	cpu_overhead_dev.free  = free_timestamp_buffer;
2112 +	cpu_overhead_dev.write = write_timestamp_from_user;
2113 +
2114 +	err = register_ftdev(&cpu_overhead_dev);
2115 +	if (err)
2116 +		goto err_dealloc;
2117 +
2118 +	for (cpu = 0; cpu < NR_CPUS; cpu++)  {
2119 +		per_cpu(cpu_ts_seq_no, cpu) = 0;
2120 +	}
2121 +
2122 +	return 0;
2123 +
2124 +err_dealloc:
2125 +	ftdev_exit(&cpu_overhead_dev);
2126 +err_out:
2127 +	printk(KERN_WARNING "Could not register per-cpu ft_trace device.\n");
2128 +	return err;
2129 +}
2130 +
2131 +static int __init init_msg_ft_overhead_trace(void)
2132 +{
2133 +	int err, cpu;
2134 +
2135 +	printk("Initializing Feather-Trace per-cpu message overhead tracing device.\n");
2136 +	err = ftdev_init(&msg_overhead_dev, THIS_MODULE,
2137 +			 num_online_cpus(), "ft_msg_trace");
2138 +	if (err)
2139 +		goto err_out;
2140 +
2141 +	msg_overhead_dev.alloc = alloc_timestamp_buffer;
2142 +	msg_overhead_dev.free  = free_timestamp_buffer;
2143 +	msg_overhead_dev.calibrate = calibrate_tsc_offsets;
2144 +
2145 +	err = register_ftdev(&msg_overhead_dev);
2146 +	if (err)
2147 +		goto err_dealloc;
2148 +
2149 +	for (cpu = 0; cpu < NR_CPUS; cpu++)  {
2150 +		per_cpu(msg_ts_seq_no, cpu) = 0;
2151 +	}
2152 +
2153 +	return 0;
2154 +
2155 +err_dealloc:
2156 +	ftdev_exit(&msg_overhead_dev);
2157 +err_out:
2158 +	printk(KERN_WARNING "Could not register message ft_trace device.\n");
2159 +	return err;
2160 +}
2161 +
2162 +
2163 +static int __init init_ft_overhead_trace(void)
2164 +{
2165 +	int err, i, j;
2166 +
2167 +	for (i = 0; i < NR_CPUS; i++)
2168 +		for (j = 0; j < NR_CPUS; j++)
2169 +			cycle_offset[i][j] = 0;
2170 +
2171 +	err = init_cpu_ft_overhead_trace();
2172 +	if (err)
2173 +		return err;
2174 +
2175 +	err = init_msg_ft_overhead_trace();
2176 +	if (err)
2177 +		ftdev_exit(&cpu_overhead_dev);
2178 +		return err;
2179 +
2180 +	return 0;
2181 +}
2182 +
2183 +static void __exit exit_ft_overhead_trace(void)
2184 +{
2185 +	ftdev_exit(&cpu_overhead_dev);
2186 +	ftdev_exit(&msg_overhead_dev);
2187 +}
2188 +
2189 +module_init(init_ft_overhead_trace);
2190 +module_exit(exit_ft_overhead_trace);
2191 -- 
2192 1.8.1.2
2193 
2194 
2195 From 530f3c252277104613501e10cbfa63c09e4ca9c0 Mon Sep 17 00:00:00 2001
2196 From: Bjoern Brandenburg <bbb@mpi-sws.org>
2197 Date: Sun, 23 Jun 2013 14:51:57 +0200
2198 Subject: [PATCH 006/119] Integrate ft_irq_fired() with Linux
2199 
2200 This patch hooks up Feather-Trace's ft_irq_fired() handler with
2201 Linux's interrupt handling infrastructure.
2202 ---
2203  include/linux/hardirq.h    |  4 ++++
2204  include/litmus/trace_irq.h | 14 ++++++++++++++
2205  kernel/sched/core.c        |  5 +++++
2206  kernel/softirq.c           |  3 +++
2207  4 files changed, 26 insertions(+)
2208  create mode 100644 include/litmus/trace_irq.h
2209 
2210 diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
2211 index c1d6555..7ad5fd8 100644
2212 --- a/include/linux/hardirq.h
2213 +++ b/include/linux/hardirq.h
2214 @@ -7,6 +7,8 @@
2215  #include <linux/vtime.h>
2216  #include <asm/hardirq.h>
2217  
2218 +#include <litmus/trace_irq.h>
2219 +
2220  /*
2221   * We put the hardirq and softirq counter into the preemption
2222   * counter. The bitmask has the following meaning:
2223 @@ -154,6 +156,7 @@ extern void rcu_nmi_exit(void);
2224  		account_irq_enter_time(current);	\
2225  		add_preempt_count(HARDIRQ_OFFSET);	\
2226  		trace_hardirq_enter();			\
2227 +		ft_irq_fired();				\
2228  	} while (0)
2229  
2230  /*
2231 @@ -184,6 +187,7 @@ extern void irq_exit(void);
2232  		add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET);	\
2233  		rcu_nmi_enter();				\
2234  		trace_hardirq_enter();				\
2235 +		ft_irq_fired();					\
2236  	} while (0)
2237  
2238  #define nmi_exit()						\
2239 diff --git a/include/litmus/trace_irq.h b/include/litmus/trace_irq.h
2240 new file mode 100644
2241 index 0000000..0d0c042
2242 --- /dev/null
2243 +++ b/include/litmus/trace_irq.h
2244 @@ -0,0 +1,14 @@
2245 +#ifndef _LITMUS_TRACE_IRQ_H_
2246 +#define	_LITMUS_TRACE_IRQ_H_
2247 +
2248 +#ifdef CONFIG_SCHED_OVERHEAD_TRACE
2249 +
2250 +void ft_irq_fired(void);
2251 +
2252 +#else
2253 +
2254 +#define ft_irq_fired() /* nothing to do */
2255 +
2256 +#endif
2257 +
2258 +#endif
2259 diff --git a/kernel/sched/core.c b/kernel/sched/core.c
2260 index b4308d7..7eefaab 100644
2261 --- a/kernel/sched/core.c
2262 +++ b/kernel/sched/core.c
2263 @@ -1408,7 +1408,12 @@ void scheduler_ipi(void)
2264  	if (llist_empty(&this_rq()->wake_list)
2265  			&& !tick_nohz_full_cpu(smp_processor_id())
2266  			&& !got_nohz_idle_kick())
2267 +	{
2268 +		/* If we don't call irq_enter(), we need to triggger the IRQ
2269 +		 * tracing manually. */
2270 +		ft_irq_fired();
2271  		return;
2272 +	}
2273  
2274  	/*
2275  	 * Not all reschedule IPI handlers call irq_enter/irq_exit, since
2276 diff --git a/kernel/softirq.c b/kernel/softirq.c
2277 index 787b3a0..fe8890b 100644
2278 --- a/kernel/softirq.c
2279 +++ b/kernel/softirq.c
2280 @@ -226,6 +226,9 @@ asmlinkage void __do_softirq(void)
2281  	 */
2282  	current->flags &= ~PF_MEMALLOC;
2283  
2284 +	/* Mark Feather-Trace samples as "disturbed". */
2285 +	ft_irq_fired();
2286 +
2287  	pending = local_softirq_pending();
2288  	account_irq_enter_time(current);
2289  
2290 -- 
2291 1.8.1.2
2292 
2293 
2294 From 93919aeeb7b30971603a3d67b3d12091a45e9fbf Mon Sep 17 00:00:00 2001
2295 From: Bjoern Brandenburg <bbb@mpi-sws.org>
2296 Date: Wed, 26 Jun 2013 18:45:30 +0200
2297 Subject: [PATCH 007/119] Add SCHED, SCHED2, TICK, and CXS overhead tracepoints
2298 
2299 This patch integrates the overhead tracepoints into the Linux
2300 scheduler that are compatible with plain vanilla Linux (i.e., not
2301 specific to LITMUS^RT plugins).  This can be used to measure the
2302 overheads of an otherwise unmodified kernel.
2303 ---
2304  kernel/sched/core.c | 20 +++++++++++++++++++-
2305  1 file changed, 19 insertions(+), 1 deletion(-)
2306 
2307 diff --git a/kernel/sched/core.c b/kernel/sched/core.c
2308 index 7eefaab..3a471d6 100644
2309 --- a/kernel/sched/core.c
2310 +++ b/kernel/sched/core.c
2311 @@ -86,6 +86,8 @@
2312  #include "../workqueue_internal.h"
2313  #include "../smpboot.h"
2314  
2315 +#include <litmus/trace.h>
2316 +
2317  #define CREATE_TRACE_POINTS
2318  #include <trace/events/sched.h>
2319  
2320 @@ -2748,6 +2750,8 @@ void scheduler_tick(void)
2321  
2322  	sched_clock_tick();
2323  
2324 +	TS_TICK_START(current);
2325 +
2326  	raw_spin_lock(&rq->lock);
2327  	update_rq_clock(rq);
2328  	update_cpu_load_active(rq);
2329 @@ -2761,6 +2765,8 @@ void scheduler_tick(void)
2330  	trigger_load_balance(rq, cpu);
2331  #endif
2332  	rq_last_tick_reset(rq);
2333 +
2334 +	TS_TICK_END(current);
2335  }
2336  
2337  #ifdef CONFIG_NO_HZ_FULL
2338 @@ -2972,6 +2978,8 @@ need_resched:
2339  	rcu_note_context_switch(cpu);
2340  	prev = rq->curr;
2341  
2342 +	TS_SCHED_START;
2343 +
2344  	schedule_debug(prev);
2345  
2346  	if (sched_feat(HRTICK))
2347 @@ -3024,7 +3032,10 @@ need_resched:
2348  		rq->curr = next;
2349  		++*switch_count;
2350  
2351 +		TS_SCHED_END(next);
2352 +		TS_CXS_START(next);
2353  		context_switch(rq, prev, next); /* unlocks the rq */
2354 +		TS_CXS_END(current);
2355  		/*
2356  		 * The context switch have flipped the stack from under us
2357  		 * and restored the local variables which were saved when
2358 @@ -3033,12 +3044,19 @@ need_resched:
2359  		 */
2360  		cpu = smp_processor_id();
2361  		rq = cpu_rq(cpu);
2362 -	} else
2363 +	} else {
2364 +		TS_SCHED_END(prev);
2365  		raw_spin_unlock_irq(&rq->lock);
2366 +	}
2367 +
2368 +	TS_SCHED2_START(prev);
2369  
2370  	post_schedule(rq);
2371  
2372  	sched_preempt_enable_no_resched();
2373 +
2374 +	TS_SCHED2_END(prev);
2375 +
2376  	if (need_resched())
2377  		goto need_resched;
2378  }
2379 -- 
2380 1.8.1.2
2381 
2382 
2383 From 5ce8d2c4a1fa8e5a4bca25891f2e892ef55fc89f Mon Sep 17 00:00:00 2001
2384 From: Felipe Cerqueira <felipec@mpi-sws.org>
2385 Date: Mon, 11 Feb 2013 18:10:50 +0100
2386 Subject: [PATCH 008/119] Export x86 cache topology
2387 
2388 This patch adds get_shared_cpu_map(), which allows the caller to infer
2389 which CPUs share a cache at a given level.
2390 ---
2391  arch/x86/include/asm/processor.h      |  4 ++++
2392  arch/x86/kernel/cpu/intel_cacheinfo.c | 17 +++++++++++++++++
2393  2 files changed, 21 insertions(+)
2394 
2395 diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
2396 index 22224b3..254dd2b 100644
2397 --- a/arch/x86/include/asm/processor.h
2398 +++ b/arch/x86/include/asm/processor.h
2399 @@ -173,6 +173,10 @@ void print_cpu_msr(struct cpuinfo_x86 *);
2400  extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
2401  extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
2402  extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
2403 +#ifdef CONFIG_SYSFS
2404 +extern int get_shared_cpu_map(cpumask_var_t mask,
2405 +			       unsigned int cpu, int index);
2406 +#endif
2407  
2408  extern void detect_extended_topology(struct cpuinfo_x86 *c);
2409  extern void detect_ht(struct cpuinfo_x86 *c);
2410 diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
2411 index 7c6f7d5..033939b 100644
2412 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c
2413 +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
2414 @@ -744,6 +744,23 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
2415  static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
2416  #define CPUID4_INFO_IDX(x, y)	(&((per_cpu(ici_cpuid4_info, x))[y]))
2417  
2418 +/* returns CPUs that share the index cache with cpu */
2419 +int get_shared_cpu_map(cpumask_var_t mask, unsigned int cpu, int index)
2420 +{
2421 +	int ret = 0;
2422 +	struct _cpuid4_info *this_leaf;
2423 +
2424 +	if (index >= num_cache_leaves) {
2425 +		index = num_cache_leaves - 1;
2426 +		ret = index;
2427 +	}
2428 +
2429 +	this_leaf = CPUID4_INFO_IDX(cpu,index);
2430 +	cpumask_copy(mask, to_cpumask(this_leaf->shared_cpu_map));
2431 +
2432 +	return ret;
2433 +}
2434 +
2435  #ifdef CONFIG_SMP
2436  
2437  static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index)
2438 -- 
2439 1.8.1.2
2440 
2441 
2442 From 74a89132e046e7a35f16f6eab9c6884679d48f27 Mon Sep 17 00:00:00 2001
2443 From: Bjoern Brandenburg <bbb@mpi-sws.org>
2444 Date: Sun, 23 Jun 2013 15:26:01 +0200
2445 Subject: [PATCH 009/119] Add object list to inodes
2446 
2447 This patch adds a list of arbitrary objects to inodes.
2448 
2449 This is used by Linux's locking API to attach lock objects to inodes
2450 (which represent namespaces in Linux's locking API).
2451 ---
2452  fs/inode.c         | 2 ++
2453  include/linux/fs.h | 5 +++++
2454  2 files changed, 7 insertions(+)
2455 
2456 diff --git a/fs/inode.c b/fs/inode.c
2457 index 00d5fc3..a80e326 100644
2458 --- a/fs/inode.c
2459 +++ b/fs/inode.c
2460 @@ -370,6 +370,8 @@ void inode_init_once(struct inode *inode)
2461  #ifdef CONFIG_FSNOTIFY
2462  	INIT_HLIST_HEAD(&inode->i_fsnotify_marks);
2463  #endif
2464 +	INIT_LIST_HEAD(&inode->i_obj_list);
2465 +	mutex_init(&inode->i_obj_mutex);
2466  }
2467  EXPORT_SYMBOL(inode_init_once);
2468  
2469 diff --git a/include/linux/fs.h b/include/linux/fs.h
2470 index 65c2be2..8a0ac17 100644
2471 --- a/include/linux/fs.h
2472 +++ b/include/linux/fs.h
2473 @@ -508,6 +508,7 @@ static inline int mapping_writably_mapped(struct address_space *mapping)
2474  
2475  struct posix_acl;
2476  #define ACL_NOT_CACHED ((void *)(-1))
2477 +struct inode_obj_id_table;
2478  
2479  #define IOP_FASTPERM	0x0001
2480  #define IOP_LOOKUP	0x0002
2481 @@ -606,6 +607,10 @@ struct inode {
2482  #ifdef CONFIG_IMA
2483  	atomic_t		i_readcount; /* struct files open RO */
2484  #endif
2485 +
2486 +	struct list_head	i_obj_list;
2487 +	struct mutex		i_obj_mutex;
2488 +
2489  	void			*i_private; /* fs or device private pointer */
2490  };
2491  
2492 -- 
2493 1.8.1.2
2494 
2495 
2496 From 7fb0ac2758b6e277de7bd753fdbe8596048d156c Mon Sep 17 00:00:00 2001
2497 From: Bjoern Brandenburg <bbb@mpi-sws.org>
2498 Date: Sun, 23 Jun 2013 16:29:07 +0200
2499 Subject: [PATCH 010/119] Add TRACE() debug tracing support
2500 
2501 This patch adds the infrastructure for the TRACE() debug macro.
2502 ---
2503  include/litmus/debug_trace.h |  40 +++++++
2504  kernel/printk.c              |  13 ++-
2505  litmus/Kconfig               |  53 +++++++++
2506  litmus/Makefile              |   1 +
2507  litmus/sched_trace.c         | 251 +++++++++++++++++++++++++++++++++++++++++++
2508  5 files changed, 357 insertions(+), 1 deletion(-)
2509  create mode 100644 include/litmus/debug_trace.h
2510  create mode 100644 litmus/sched_trace.c
2511 
2512 diff --git a/include/litmus/debug_trace.h b/include/litmus/debug_trace.h
2513 new file mode 100644
2514 index 0000000..1266ac6
2515 --- /dev/null
2516 +++ b/include/litmus/debug_trace.h
2517 @@ -0,0 +1,40 @@
2518 +#ifndef LITMUS_DEBUG_TRACE_H
2519 +#define LITMUS_DEBUG_TRACE_H
2520 +
2521 +#ifdef CONFIG_SCHED_DEBUG_TRACE
2522 +void sched_trace_log_message(const char* fmt, ...);
2523 +void dump_trace_buffer(int max);
2524 +#else
2525 +
2526 +#define sched_trace_log_message(fmt, ...)
2527 +
2528 +#endif
2529 +
2530 +extern atomic_t __log_seq_no;
2531 +
2532 +#ifdef CONFIG_SCHED_DEBUG_TRACE_CALLER
2533 +#define TRACE_PREFIX "%d P%d [%s@%s:%d]: "
2534 +#define TRACE_ARGS  atomic_add_return(1, &__log_seq_no),	\
2535 +		raw_smp_processor_id(),				\
2536 +		__FUNCTION__, __FILE__, __LINE__
2537 +#else
2538 +#define TRACE_PREFIX "%d P%d: "
2539 +#define TRACE_ARGS  atomic_add_return(1, &__log_seq_no), \
2540 +		raw_smp_processor_id()
2541 +#endif
2542 +
2543 +#define TRACE(fmt, args...)						\
2544 +	sched_trace_log_message(TRACE_PREFIX fmt,			\
2545 +				TRACE_ARGS,  ## args)
2546 +
2547 +#define TRACE_TASK(t, fmt, args...)			\
2548 +	TRACE("(%s/%d:%d) " fmt,			 \
2549 +	      t ? (t)->comm : "null",			 \
2550 +	      t ? (t)->pid : 0,				 \
2551 +	      t ? (t)->rt_param.job_params.job_no : 0,	 \
2552 +	      ##args)
2553 +
2554 +#define TRACE_CUR(fmt, args...) \
2555 +	TRACE_TASK(current, fmt, ## args)
2556 +
2557 +#endif
2558 diff --git a/kernel/printk.c b/kernel/printk.c
2559 index d37d45c..5616e59 100644
2560 --- a/kernel/printk.c
2561 +++ b/kernel/printk.c
2562 @@ -66,6 +66,13 @@ int console_printk[4] = {
2563  };
2564  
2565  /*
2566 + * divert printk() messages when there is a LITMUS^RT debug listener
2567 + */
2568 +#include <litmus/debug_trace.h>
2569 +int trace_override = 0;
2570 +int trace_recurse  = 0;
2571 +
2572 +/*
2573   * Low level drivers may need that to know if they can schedule in
2574   * their unblank() callback or not. So let's export it.
2575   */
2576 @@ -1552,6 +1559,10 @@ asmlinkage int vprintk_emit(int facility, int level,
2577  	 */
2578  	text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
2579  
2580 +	/* if LITMUS^RT tracer is active divert printk() msgs */
2581 +	if (trace_override && !trace_recurse)
2582 +		TRACE("%s", text);
2583 +
2584  	/* mark and strip a trailing newline */
2585  	if (text_len && text[text_len-1] == '\n') {
2586  		text_len--;
2587 @@ -2478,7 +2489,7 @@ static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
2588  void wake_up_klogd(void)
2589  {
2590  	preempt_disable();
2591 -	if (waitqueue_active(&log_wait)) {
2592 +	if (!trace_override && waitqueue_active(&log_wait)) {
2593  		this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
2594  		irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
2595  	}
2596 diff --git a/litmus/Kconfig b/litmus/Kconfig
2597 index 0c7e06b..e4624ee 100644
2598 --- a/litmus/Kconfig
2599 +++ b/litmus/Kconfig
2600 @@ -49,6 +49,59 @@ config SCHED_OVERHEAD_TRACE_SHIFT
2601  		   24 => 512 MB
2602  		   26 =>  2G MB
2603  
2604 +config SCHED_DEBUG_TRACE
2605 +	bool "TRACE() debugging"
2606 +	default n
2607 +	help
2608 +	  Include support for sched_trace_log_messageg(), which is used to
2609 +	  implement TRACE(). If disabled, no TRACE() messages will be included
2610 +	  in the kernel, and no overheads due to debugging statements will be
2611 +	  incurred by the scheduler. Disable if the overhead is not acceptable
2612 +	  (e.g. benchmarking).
2613 +
2614 +	  Say Yes for debugging.
2615 +	  Say No for overhead tracing.
2616 +
2617 +config SCHED_DEBUG_TRACE_SHIFT
2618 +       int "Buffer size for TRACE() buffer"
2619 +       depends on SCHED_DEBUG_TRACE
2620 +       range 14 22
2621 +       default 18
2622 +       help
2623 +
2624 +	Select the amount of memory needed per for the TRACE() buffer, as a
2625 +	power of two. The TRACE() buffer is global and statically allocated. If
2626 +	the buffer is too small, there will be holes in the TRACE() log if the
2627 +	buffer-flushing task is starved.
2628 +
2629 +	The default should be sufficient for most systems. Increase the buffer
2630 +	size if the log contains holes. Reduce the buffer size when running on
2631 +	a memory-constrained system.
2632 +
2633 +	Examples: 14 =>  16KB
2634 +		  18 => 256KB
2635 +		  20 =>   1MB
2636 +
2637 +        This buffer is exported to usespace using a misc device as
2638 +        'litmus/log'. On a system with default udev rules, a corresponding
2639 +        character device node should be created at /dev/litmus/log. The buffer
2640 +        can be flushed using cat, e.g., 'cat /dev/litmus/log > my_log_file.txt'.
2641 +
2642 +config SCHED_DEBUG_TRACE_CALLER
2643 +       bool "Include [function@file:line] tag in TRACE() log"
2644 +       depends on SCHED_DEBUG_TRACE
2645 +       default n
2646 +       help
2647 +         With this option enabled, TRACE() prepends
2648 +
2649 +	      "[<function name>@<filename>:<line number>]"
2650 +
2651 +	 to each message in the debug log. Enable this to aid in figuring out
2652 +         what was called in which order. The downside is that it adds a lot of
2653 +         clutter.
2654 +
2655 +	 If unsure, say No.
2656 +
2657  endmenu
2658  
2659  endmenu
2660 diff --git a/litmus/Makefile b/litmus/Makefile
2661 index 99f90c3..07f065f 100644
2662 --- a/litmus/Makefile
2663 +++ b/litmus/Makefile
2664 @@ -3,4 +3,5 @@
2665  #
2666  
2667  obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o
2668 +obj-$(CONFIG_SCHED_DEBUG_TRACE) += sched_trace.o
2669  obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o
2670 diff --git a/litmus/sched_trace.c b/litmus/sched_trace.c
2671 new file mode 100644
2672 index 0000000..426a9dd
2673 --- /dev/null
2674 +++ b/litmus/sched_trace.c
2675 @@ -0,0 +1,251 @@
2676 +/*
2677 + * sched_trace.c -- record scheduling events to a byte stream.
2678 + */
2679 +#include <linux/spinlock.h>
2680 +#include <linux/mutex.h>
2681 +
2682 +#include <linux/fs.h>
2683 +#include <linux/slab.h>
2684 +#include <linux/miscdevice.h>
2685 +#include <asm/uaccess.h>
2686 +#include <linux/module.h>
2687 +#include <linux/sysrq.h>
2688 +#include <linux/sched.h>
2689 +#include <linux/kfifo.h>
2690 +
2691 +atomic_t __log_seq_no = ATOMIC_INIT(0);
2692 +
2693 +#define SCHED_TRACE_NAME "litmus/log"
2694 +
2695 +/* Compute size of TRACE() buffer */
2696 +#define LITMUS_TRACE_BUF_SIZE (1 << CONFIG_SCHED_DEBUG_TRACE_SHIFT)
2697 +
2698 +/* Max length of one read from the buffer */
2699 +#define MAX_READ_LEN (64 * 1024)
2700 +
2701 +/* Max length for one write --- by TRACE() --- to the buffer. This is used to
2702 + * allocate a per-cpu buffer for printf() formatting. */
2703 +#define MSG_SIZE 255
2704 +
2705 +
2706 +static DEFINE_MUTEX(reader_mutex);
2707 +static atomic_t reader_cnt = ATOMIC_INIT(0);
2708 +static DEFINE_KFIFO(debug_buffer, char, LITMUS_TRACE_BUF_SIZE);
2709 +
2710 +
2711 +static DEFINE_RAW_SPINLOCK(log_buffer_lock);
2712 +static DEFINE_PER_CPU(char[MSG_SIZE], fmt_buffer);
2713 +
2714 +/*
2715 + * sched_trace_log_message - Write to the trace buffer (log_buffer)
2716 + *
2717 + * This is the only function accessing the log_buffer from inside the
2718 + * kernel for writing.
2719 + * Concurrent access to sched_trace_log_message must be serialized using
2720 + * log_buffer_lock
2721 + * The maximum length of a formatted message is 255
2722 + */
2723 +void sched_trace_log_message(const char* fmt, ...)
2724 +{
2725 +	unsigned long 	flags;
2726 +	va_list 	args;
2727 +	size_t		len;
2728 +	char*		buf;
2729 +
2730 +	if (!atomic_read(&reader_cnt))
2731 +		/* early exit if nobody is listening */
2732 +		return;
2733 +
2734 +	va_start(args, fmt);
2735 +	local_irq_save(flags);
2736 +
2737 +	/* format message */
2738 +	buf = __get_cpu_var(fmt_buffer);
2739 +	len = vscnprintf(buf, MSG_SIZE, fmt, args);
2740 +
2741 +	raw_spin_lock(&log_buffer_lock);
2742 +	/* Don't copy the trailing null byte, we don't want null bytes in a
2743 +	 * text file.
2744 +	 */
2745 +	kfifo_in(&debug_buffer, buf, len);
2746 +	raw_spin_unlock(&log_buffer_lock);
2747 +
2748 +	local_irq_restore(flags);
2749 +	va_end(args);
2750 +}
2751 +
2752 +
2753 +/*
2754 + * log_read - Read the trace buffer
2755 + *
2756 + * This function is called as a file operation from userspace.
2757 + * Readers can sleep. Access is serialized through reader_mutex
2758 + */
2759 +static ssize_t log_read(struct file *filp,
2760 +			char __user *to, size_t len,
2761 +			loff_t *f_pos)
2762 +{
2763 +	/* we ignore f_pos, this is strictly sequential */
2764 +
2765 +	ssize_t error = -EINVAL;
2766 +	char* mem;
2767 +
2768 +	if (mutex_lock_interruptible(&reader_mutex)) {
2769 +		error = -ERESTARTSYS;
2770 +		goto out;
2771 +	}
2772 +
2773 +	if (len > MAX_READ_LEN)
2774 +		len = MAX_READ_LEN;
2775 +
2776 +	mem = kmalloc(len, GFP_KERNEL);
2777 +	if (!mem) {
2778 +		error = -ENOMEM;
2779 +		goto out_unlock;
2780 +	}
2781 +
2782 +	error = kfifo_out(&debug_buffer, mem, len);
2783 +	while (!error) {
2784 +		set_current_state(TASK_INTERRUPTIBLE);
2785 +		schedule_timeout(110);
2786 +		if (signal_pending(current))
2787 +			error = -ERESTARTSYS;
2788 +		else
2789 +			error = kfifo_out(&debug_buffer, mem, len);
2790 +	}
2791 +
2792 +	if (error > 0 && copy_to_user(to, mem, error))
2793 +		error = -EFAULT;
2794 +
2795 +	kfree(mem);
2796 + out_unlock:
2797 +	mutex_unlock(&reader_mutex);
2798 + out:
2799 +	return error;
2800 +}
2801 +
2802 +/*
2803 + * Enable redirection of printk() messages to the trace buffer.
2804 + * Defined in kernel/printk.c
2805 + */
2806 +extern int trace_override;
2807 +extern int trace_recurse;
2808 +
2809 +/*
2810 + * log_open - open the global log message ring buffer.
2811 + */
2812 +static int log_open(struct inode *in, struct file *filp)
2813 +{
2814 +	int error = -EINVAL;
2815 +
2816 +	if (mutex_lock_interruptible(&reader_mutex)) {
2817 +		error = -ERESTARTSYS;
2818 +		goto out;
2819 +	}
2820 +
2821 +	atomic_inc(&reader_cnt);
2822 +	error = 0;
2823 +
2824 +	printk(KERN_DEBUG
2825 +	       "sched_trace kfifo with buffer starting at: 0x%p\n",
2826 +	       debug_buffer.buf);
2827 +
2828 +	/* override printk() */
2829 +	trace_override++;
2830 +
2831 +	mutex_unlock(&reader_mutex);
2832 + out:
2833 +	return error;
2834 +}
2835 +
2836 +static int log_release(struct inode *in, struct file *filp)
2837 +{
2838 +	int error = -EINVAL;
2839 +
2840 +	if (mutex_lock_interruptible(&reader_mutex)) {
2841 +		error = -ERESTARTSYS;
2842 +		goto out;
2843 +	}
2844 +
2845 +	atomic_dec(&reader_cnt);
2846 +
2847 +	/* release printk() overriding */
2848 +	trace_override--;
2849 +
2850 +	printk(KERN_DEBUG "sched_trace kfifo released\n");
2851 +
2852 +	mutex_unlock(&reader_mutex);
2853 + out:
2854 +	return error;
2855 +}
2856 +
2857 +/*
2858 + * log_fops  - The file operations for accessing the global LITMUS log message
2859 + *             buffer.
2860 + *
2861 + * Except for opening the device file it uses the same operations as trace_fops.
2862 + */
2863 +static struct file_operations log_fops = {
2864 +	.owner   = THIS_MODULE,
2865 +	.open    = log_open,
2866 +	.release = log_release,
2867 +	.read    = log_read,
2868 +};
2869 +
2870 +static struct miscdevice litmus_log_dev = {
2871 +	.name    = SCHED_TRACE_NAME,
2872 +	.minor   = MISC_DYNAMIC_MINOR,
2873 +	.fops    = &log_fops,
2874 +};
2875 +
2876 +#ifdef CONFIG_MAGIC_SYSRQ
2877 +void dump_trace_buffer(int max)
2878 +{
2879 +	char line[80];
2880 +	int len;
2881 +	int count = 0;
2882 +
2883 +	/* potential, but very unlikely, race... */
2884 +	trace_recurse = 1;
2885 +	while ((max == 0 || count++ < max) &&
2886 +	       (len = kfifo_out(&debug_buffer, line, sizeof(line - 1))) > 0) {
2887 +		line[len] = '\0';
2888 +		printk("%s", line);
2889 +	}
2890 +	trace_recurse = 0;
2891 +}
2892 +
2893 +static void sysrq_dump_trace_buffer(int key)
2894 +{
2895 +	dump_trace_buffer(100);
2896 +}
2897 +
2898 +static struct sysrq_key_op sysrq_dump_trace_buffer_op = {
2899 +	.handler	= sysrq_dump_trace_buffer,
2900 +	.help_msg	= "dump-trace-buffer(Y)",
2901 +	.action_msg	= "writing content of TRACE() buffer",
2902 +};
2903 +#endif
2904 +
2905 +static int __init init_sched_trace(void)
2906 +{
2907 +	printk("Initializing TRACE() device\n");
2908 +
2909 +#ifdef CONFIG_MAGIC_SYSRQ
2910 +	/* offer some debugging help */
2911 +	if (!register_sysrq_key('y', &sysrq_dump_trace_buffer_op))
2912 +		printk("Registered dump-trace-buffer(Y) magic sysrq.\n");
2913 +	else
2914 +		printk("Could not register dump-trace-buffer(Y) magic sysrq.\n");
2915 +#endif
2916 +
2917 +	return misc_register(&litmus_log_dev);
2918 +}
2919 +
2920 +static void __exit exit_sched_trace(void)
2921 +{
2922 +	misc_deregister(&litmus_log_dev);
2923 +}
2924 +
2925 +module_init(init_sched_trace);
2926 +module_exit(exit_sched_trace);
2927 -- 
2928 1.8.1.2
2929 
2930 
2931 From 39587f773d6b64c8f7ab82d7e222de45899cb36f Mon Sep 17 00:00:00 2001
2932 From: Felipe Cerqueira <felipec@mpi-sws.org>
2933 Date: Mon, 11 Feb 2013 16:36:35 +0100
2934 Subject: [PATCH 011/119] Add hrtimer_start_on() support
2935 
2936 This patch adds hrtimer_start_on(), which allows arming timers on
2937 remote CPUs.  This is needed to avoided timer interrupts on "shielded"
2938 CPUs and is also useful for implementing semi-partitioned schedulers.
2939 ---
2940  arch/arm/Kconfig                   |  3 ++
2941  arch/x86/Kconfig                   |  3 ++
2942  arch/x86/include/asm/entry_arch.h  |  1 +
2943  arch/x86/include/asm/hw_irq.h      |  3 ++
2944  arch/x86/include/asm/irq_vectors.h |  6 +++
2945  arch/x86/kernel/entry_64.S         |  2 +
2946  arch/x86/kernel/irqinit.c          |  3 ++
2947  arch/x86/kernel/smp.c              | 23 +++++++++
2948  include/linux/hrtimer.h            | 32 +++++++++++++
2949  include/linux/smp.h                |  5 ++
2950  kernel/hrtimer.c                   | 95 ++++++++++++++++++++++++++++++++++++++
2951  11 files changed, 176 insertions(+)
2952 
2953 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
2954 index ecfd735..81dddd7 100644
2955 --- a/arch/arm/Kconfig
2956 +++ b/arch/arm/Kconfig
2957 @@ -2273,5 +2273,8 @@ source "arch/arm/kvm/Kconfig"
2958  config ARCH_HAS_FEATHER_TRACE
2959  	def_bool n
2960  
2961 +config ARCH_HAS_SEND_PULL_TIMERS
2962 +	def_bool n
2963 +
2964  source "litmus/Kconfig"
2965  
2966 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
2967 index 171cdc9..b069526 100644
2968 --- a/arch/x86/Kconfig
2969 +++ b/arch/x86/Kconfig
2970 @@ -2350,4 +2350,7 @@ source "lib/Kconfig"
2971  config ARCH_HAS_FEATHER_TRACE
2972  	def_bool y
2973  
2974 +config ARCH_HAS_SEND_PULL_TIMERS
2975 +	def_bool y
2976 +
2977  source "litmus/Kconfig"
2978 diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
2979 index 9bd4eca..3a3c2f1 100644
2980 --- a/arch/x86/include/asm/entry_arch.h
2981 +++ b/arch/x86/include/asm/entry_arch.h
2982 @@ -13,6 +13,7 @@
2983  BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
2984  BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
2985  BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
2986 +BUILD_INTERRUPT(pull_timers_interrupt,PULL_TIMERS_VECTOR)
2987  BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
2988  BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
2989  #endif
2990 diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
2991 index 1da97ef..672de93 100644
2992 --- a/arch/x86/include/asm/hw_irq.h
2993 +++ b/arch/x86/include/asm/hw_irq.h
2994 @@ -77,6 +77,8 @@ extern void threshold_interrupt(void);
2995  extern void call_function_interrupt(void);
2996  extern void call_function_single_interrupt(void);
2997  
2998 +extern void pull_timers_interrupt(void);
2999 +
3000  /* IOAPIC */
3001  #define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1<<(x)) & io_apic_irqs))
3002  extern unsigned long io_apic_irqs;
3003 @@ -166,6 +168,7 @@ extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
3004  extern void smp_reschedule_interrupt(struct pt_regs *);
3005  extern void smp_call_function_interrupt(struct pt_regs *);
3006  extern void smp_call_function_single_interrupt(struct pt_regs *);
3007 +extern void smp_pull_timers_interrupt(struct pt_regs *);
3008  #ifdef CONFIG_X86_32
3009  extern void smp_invalidate_interrupt(struct pt_regs *);
3010  #else
3011 diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
3012 index 5702d7e..224116b 100644
3013 --- a/arch/x86/include/asm/irq_vectors.h
3014 +++ b/arch/x86/include/asm/irq_vectors.h
3015 @@ -124,6 +124,12 @@
3016   */
3017  #define LOCAL_TIMER_VECTOR		0xef
3018  
3019 +/*
3020 + * LITMUS^RT pull timers IRQ vector.
3021 + * Make sure it's not used by Linux.
3022 + */
3023 +#define PULL_TIMERS_VECTOR		0xdf
3024 +
3025  #define NR_VECTORS			 256
3026  
3027  #define FPU_IRQ				  13
3028 diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
3029 index 7ac938a..2a54337 100644
3030 --- a/arch/x86/kernel/entry_64.S
3031 +++ b/arch/x86/kernel/entry_64.S
3032 @@ -1183,6 +1183,8 @@ apicinterrupt CALL_FUNCTION_VECTOR \
3033  	call_function_interrupt smp_call_function_interrupt
3034  apicinterrupt RESCHEDULE_VECTOR \
3035  	reschedule_interrupt smp_reschedule_interrupt
3036 +apicinterrupt PULL_TIMERS_VECTOR \
3037 +	pull_timers_interrupt smp_pull_timers_interrupt
3038  #endif
3039  
3040  apicinterrupt ERROR_APIC_VECTOR \
3041 diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
3042 index a2a1fbc..77979d9 100644
3043 --- a/arch/x86/kernel/irqinit.c
3044 +++ b/arch/x86/kernel/irqinit.c
3045 @@ -145,6 +145,9 @@ static void __init smp_intr_init(void)
3046  	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
3047  			call_function_single_interrupt);
3048  
3049 +	/* IPI for hrtimer pulling on remote cpus */
3050 +	alloc_intr_gate(PULL_TIMERS_VECTOR, pull_timers_interrupt);
3051 +
3052  	/* Low priority IPI to cleanup after moving an irq */
3053  	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
3054  	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
3055 diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
3056 index 48d2b7d..a52ef7f 100644
3057 --- a/arch/x86/kernel/smp.c
3058 +++ b/arch/x86/kernel/smp.c
3059 @@ -24,6 +24,8 @@
3060  #include <linux/cpu.h>
3061  #include <linux/gfp.h>
3062  
3063 +#include <litmus/debug_trace.h>
3064 +
3065  #include <asm/mtrr.h>
3066  #include <asm/tlbflush.h>
3067  #include <asm/mmu_context.h>
3068 @@ -163,6 +165,16 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)