2011ǯ10��12��
ARM Linux�Υ桼���ץ�����फ��Cortex-A9�Υ������륫���󥿤����Ѥ���
��������Cortex-A9�Υ������륫���󥿤����Ѥ�����ñ�ʼ¹Ի��֤η�¬��ˡ�פȤ���������ñ¤¤Þ¤ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Î¤È¤ï¿½ï¿½Ë¤ï¿½ï¿½Ã¸ï¿½ï¿½â¡¼ï¿½É¤Ç»ï¿½ï¿½Ñ¤ï¿½ï¿½ë¤³ï¿½È¤ï¿½ï¿½ï¿½ï¿½ï¿½È¤ï¿½ï¿½Æ¤ï¿½ï¿½Þ¤ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Îµï¿½ï¿½ï¿½ï¿½ÎºÇ¸ï¿½Ë¤ï¿½ñ¤¤¤ï¿½ï¿½È¤ï¿½ï¿½ê¡¢ï¿½æ¡¼ï¿½ï¿½ï¿½ï¿½ï¿½â¡¼ï¿½É¤ï¿½ï¿½ï¿½Ñ¥Õ¥ï¿½ï¿½ï¿½ï¿½Þ¥ó¥¹¥ï¿½Ë¥ï¿½ï¿½Î¥ì¥¸ï¿½ï¿½ï¿½ï¿½ï¿½Ë¥ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ë¤¿ï¿½ï¿½Ë¤Ï¤ï¿½ï¿½é¤«ï¿½ï¿½ï¿½ï¿½User Enable Register(PMUSERENR)�ˤƥ�����������Ĥ��Ƥ���ɬ�פ�����ޤ�����ñ�ʥ����ͥ�⥸�塼����äƤ�����äƤߤޤ�����
�����ͥ�⥸�塼��κ���
�桼�����⡼�ɤ����Performance Monitoring Unit�ؤΥ�����������Ĥ���ˤϡ����餫�����ø��⡼�ɤ�PMUSERENR�쥸������bit0��Ω�ƤƤ���ɬ�פ�����ޤ����ܤ�����ARM��Architecture Reference Manual�򸫤Ƥ���������
���Ҥ˺ܤäƤ��륫���ͥ�⥸�塼���Ǥ�HelloWorld�Υ������򾯤��ѹ����ưʲ���������ޤ������ʻ��ͤˤ����Τϡ�Linux �ǥХ����ɥ饤�Хץ�����ߥ󥰡�)
pmuser.c
#include <linux/module.h> #include <linux/init.h> #define PMUSERENR_EN 0 MODULE_LICENSE("Dual BSD/GPL"); static int pmuser_init(void) { unsigned long x; asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (x)); x |= 1 << PMUSERENR_EN; asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r" (x)); printk(KERN_ALERT "Enabled accessing Performance Monitoring Unit from user space\n"); return 0; } static void pmuser_exit(void) { unsigned long x; asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (x)); x &= ~(1 << PMUSERENR_EN); asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r" (x)); printk(KERN_ALERT "Disabled accessing Performance Monitoring Unit from user space\n"); } module_init(pmuser_init); module_exit(pmuser_exit);
Makefile
obj-m := pmuser.o KERNEL_DIR = ../../kernel all: make -C $(KERNEL_DIR) M=$(PWD) modules clean: make -C $(KERNEL_DIR) M=$(PWD) clean
Makefile���KERNEL_DIR�ϥ����ͥ����ΤΥ������Υǥ��쥯�ȥ��ؤ��褦�˽������Ƥ���������
�̾�Υ����ͥ�Υӥ�ɤΤ褦�ˡ�ARCH=arm, CROSS_COMPILE=... �δĶ��ѿ��򥻥åȤ��Ƥ���
$ make make -C ../../kernel M=/opt/koba/kzm/android/work/kernel_modules/pmuser modules make[1]: Entering directory `/opt/koba/kzm/work/kernel' CC [M] /opt/koba/kzm/work/kernel_modules/pmuser/pmuser.o Building modules, stage 2. MODPOST 1 modules LD [M] /opt/koba/kzm/work/kernel_modules/pmuser/pmuser.ko make[1]: Leaving directory `/opt/koba/kzm/work/kernel' $
����ǡ�pmuser.ko ���Ǥ��ޤ�����
�ƥ��ȥץ������
�����ε�����Ʊ����Τ�Ȥ��ޤ���
pmon_ca9.h
#ifndef __KMC_PMON_CA9_H #define __KMC_PMON_CA9_H /* Performance Monitor Control Register of Cortex A9*/ #define PMCR_D 3 #define PMCR_C 2 #define PMCR_E 0 #define PMCNTENSET_C 31 volatile __inline__ static unsigned long __attribute__((always_inline)) pmon_start_cycle_counter() { unsigned long x; x = 1 << PMCNTENSET_C; asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r" (x)); asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (x)); x |= ((1 << PMCR_D) | (1 << PMCR_C) | (1 << PMCR_E)); asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r" (x)); asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (x)); return x; } volatile __inline__ static unsigned long __attribute__((always_inline)) pmon_read_cycle_counter() { unsigned long x; asm volatile ("mrc p15, 0, %0, c9, c13, 0": "=r" (x)); return x; } #endif /* __KMC_PMON_CA9_H */
test.c
#include <stdio.h> #include "pmon_ca9.h" int func(int x) { int sum = 0; int i; for (i = 1; i <= x; i++) { sum += i; } return sum; } int main() { unsigned long start, end; int x; start = pmon_start_cycle_counter(); x = func(1000); end = pmon_read_cycle_counter(); printf("time = %ld, x = %d\n", end - start, x); return x; }
�¹���
ARM Ubuntu�ξ�Ǥ��Υƥ��ȥץ�������ӥ�ɤ��Ƽ¹Ԥ��Ƥߤޤ���
user@arm-maverick:~/work/pmon$ gcc -o test test.c user@arm-maverick:~/work/pmon$ ls pmon_ca9.h pmuser.ko test test.c user@arm-maverick:~/work/pmon$ ./test Illegal instruction
���̤˼¹Ԥ���Ȥ��Τ褦���㳰�ǰ۾ェλ���Ƥ��ޤ��ޤ����桼�����⡼�ɤǤ�PMU�Υ����������ػߤ���Ƥ��뤫��Ǥ���
�����ä������ͥ�⥸�塼�������ɤ��Ƥ��顢���ټ¹Ԥ��Ƥߤޤ���
user@arm-maverick:~/work/pmon$ sudo insmod ./pmuser.ko user@arm-maverick:~/work/pmon$ ./test time = 146, x = 500500
����餷��ư���Ƥ���褦�Ǥ���
2011.10.13 �ɵ�
�������SMP(Symmetric Multiprocessing)���θ���Ƥ��ޤ���
�����󥿤�����ȥ����󥿤��ɤ߽Ф����̡��Υ����Ǽ¹Ԥ��줿�餪�������ʤ�ޤ���