aprof.c

/**
 * @file aprof.c
 *
 * @remark Copyright 2013 P.J. Drongowski
 * @remark Read the file COPYING
 *
 * @author Paul J. Drongowski
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/workqueue.h>
#include <linux/time.h>
#include <asm/mutex.h>


//
// Read the Secure Use and Non-secure Access Validation
// Control Register and return its value.
//
static inline unsigned long
armv6_sunsav_read(void)
{
	u32 val;
	asm volatile("mrc   p15, 0, %0, c15, c9, 0" : "=r"(val));
	return val;
}

//
// Write the Secure Use and Non-secure Access Validation
// Control Register
//
static inline void
armv6_subsav_write(unsigned long val)
{
	asm volatile("mcr   p15, 0, %0, c15, c9, 0" : : "r"(val));
}



static int __init aprofile_init(void)
{
	int err = 0 ;
	unsigned long sunsav = 0 ;
	printk ("aprofile module loaded\n") ;

	// Enable user-space access to the Performance Monitor counters
	armv6_subsav_write(0x1) ;
	// Read the Secure User and Non-secure Access Validation register
	sunsav = armv6_sunsav_read() ;

	printk ("SUNSAV: %lu\n", sunsav) ;

	return( err ) ;
}

static void __exit aprofile_exit(void)
{
	unsigned long sunsav = 0 ;

	// Disable user-space access to the Performance Monitor counters
	armv6_subsav_write(0x0) ;
	// Read the Secure User and Non-secure Access Validation register
	sunsav = armv6_sunsav_read() ;

	printk ("SUNSAV: %lu\n", sunsav) ;
	printk ("aprofile module unloading...\n") ;
}

module_init(aprofile_init);
module_exit(aprofile_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul Drongowski");
MODULE_DESCRIPTION("Simple ARMv6 profiler");