cregit-Linux how code gets into the kernel

Release 4.14 arch/mips/oprofile/op_model_loongson3.c

/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 */
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/smp.h>
#include <linux/proc_fs.h>
#include <linux/oprofile.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <irq.h>
#include <loongson.h>
#include "op_impl.h"


#define LOONGSON3_PERFCNT_OVERFLOW	(1ULL << 63)


#define LOONGSON3_PERFCTRL_EXL		(1UL << 0)

#define LOONGSON3_PERFCTRL_KERNEL	(1UL << 1)

#define LOONGSON3_PERFCTRL_SUPERVISOR	(1UL << 2)

#define LOONGSON3_PERFCTRL_USER		(1UL << 3)

#define LOONGSON3_PERFCTRL_ENABLE	(1UL << 4)

#define LOONGSON3_PERFCTRL_W		(1UL << 30)

#define LOONGSON3_PERFCTRL_M		(1UL << 31)

#define LOONGSON3_PERFCTRL_EVENT(idx, event) \
	(((event) & (idx ? 0x0f : 0x3f)) << 5)

/* Loongson-3 PerfCount performance counter1 register */

#define read_c0_perflo1() __read_64bit_c0_register($25, 0)

#define write_c0_perflo1(val) __write_64bit_c0_register($25, 0, val)

#define read_c0_perfhi1() __read_64bit_c0_register($25, 1)

#define write_c0_perfhi1(val) __write_64bit_c0_register($25, 1, val)

/* Loongson-3 PerfCount performance counter2 register */

#define read_c0_perflo2() __read_64bit_c0_register($25, 2)

#define write_c0_perflo2(val) __write_64bit_c0_register($25, 2, val)

#define read_c0_perfhi2() __read_64bit_c0_register($25, 3)

#define write_c0_perfhi2(val) __write_64bit_c0_register($25, 3, val)


static int (*save_perf_irq)(void);


static struct loongson3_register_config {
	
unsigned int control1;
	
unsigned int control2;
	
unsigned long long reset_counter1;
	
unsigned long long reset_counter2;
	

int ctr1_enable, ctr2_enable;

} reg;


static void reset_counters(void *arg) { write_c0_perfhi1(0); write_c0_perfhi2(0); write_c0_perflo1(0xc0000000); write_c0_perflo2(0x40000000); }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen30100.00%1100.00%
Total30100.00%1100.00%

/* Compute all of the registers in preparation for enabling profiling. */
static void loongson3_reg_setup(struct op_counter_config *ctr) { unsigned int control1 = 0; unsigned int control2 = 0; reg.reset_counter1 = 0; reg.reset_counter2 = 0; /* Compute the performance counter control word. */ /* For now count kernel and user mode */ if (ctr[0].enabled) { control1 |= LOONGSON3_PERFCTRL_EVENT(0, ctr[0].event) | LOONGSON3_PERFCTRL_ENABLE; if (ctr[0].kernel) control1 |= LOONGSON3_PERFCTRL_KERNEL; if (ctr[0].user) control1 |= LOONGSON3_PERFCTRL_USER; reg.reset_counter1 = 0x8000000000000000ULL - ctr[0].count; } if (ctr[1].enabled) { control2 |= LOONGSON3_PERFCTRL_EVENT(1, ctr[1].event) | LOONGSON3_PERFCTRL_ENABLE; if (ctr[1].kernel) control2 |= LOONGSON3_PERFCTRL_KERNEL; if (ctr[1].user) control2 |= LOONGSON3_PERFCTRL_USER; reg.reset_counter2 = 0x8000000000000000ULL - ctr[1].count; } if (ctr[0].enabled) control1 |= LOONGSON3_PERFCTRL_EXL; if (ctr[1].enabled) control2 |= LOONGSON3_PERFCTRL_EXL; reg.control1 = control1; reg.control2 = control2; reg.ctr1_enable = ctr[0].enabled; reg.ctr2_enable = ctr[1].enabled; }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen229100.00%1100.00%
Total229100.00%1100.00%

/* Program all of the registers in preparation for enabling profiling. */
static void loongson3_cpu_setup(void *args) { uint64_t perfcount1, perfcount2; perfcount1 = reg.reset_counter1; perfcount2 = reg.reset_counter2; write_c0_perfhi1(perfcount1); write_c0_perfhi2(perfcount2); }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen37100.00%1100.00%
Total37100.00%1100.00%


static void loongson3_cpu_start(void *args) { /* Start all counters on current CPU */ reg.control1 |= (LOONGSON3_PERFCTRL_W|LOONGSON3_PERFCTRL_M); reg.control2 |= (LOONGSON3_PERFCTRL_W|LOONGSON3_PERFCTRL_M); if (reg.ctr1_enable) write_c0_perflo1(reg.control1); if (reg.ctr2_enable) write_c0_perflo2(reg.control2); }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen57100.00%1100.00%
Total57100.00%1100.00%


static void loongson3_cpu_stop(void *args) { /* Stop all counters on current CPU */ write_c0_perflo1(0xc0000000); write_c0_perflo2(0x40000000); memset(&reg, 0, sizeof(reg)); }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen34100.00%1100.00%
Total34100.00%1100.00%


static int loongson3_perfcount_handler(void) { unsigned long flags; uint64_t counter1, counter2; uint32_t cause, handled = IRQ_NONE; struct pt_regs *regs = get_irq_regs(); cause = read_c0_cause(); if (!(cause & CAUSEF_PCI)) return handled; counter1 = read_c0_perfhi1(); counter2 = read_c0_perfhi2(); local_irq_save(flags); if (counter1 & LOONGSON3_PERFCNT_OVERFLOW) { if (reg.ctr1_enable) oprofile_add_sample(regs, 0); counter1 = reg.reset_counter1; } if (counter2 & LOONGSON3_PERFCNT_OVERFLOW) { if (reg.ctr2_enable) oprofile_add_sample(regs, 1); counter2 = reg.reset_counter2; } local_irq_restore(flags); write_c0_perfhi1(counter1); write_c0_perfhi2(counter2); if (!(cause & CAUSEF_TI)) handled = IRQ_HANDLED; return handled; }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen149100.00%1100.00%
Total149100.00%1100.00%


static int loongson3_starting_cpu(unsigned int cpu) { write_c0_perflo1(reg.control1); write_c0_perflo2(reg.control2); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen2074.07%150.00%
Richard Cochran725.93%150.00%
Total27100.00%2100.00%


static int loongson3_dying_cpu(unsigned int cpu) { write_c0_perflo1(0xc0000000); write_c0_perflo2(0x40000000); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen1356.52%150.00%
Richard Cochran1043.48%150.00%
Total23100.00%2100.00%


static int __init loongson3_init(void) { on_each_cpu(reset_counters, NULL, 1); cpuhp_setup_state_nocalls(CPUHP_AP_MIPS_OP_LOONGSON3_STARTING, "mips/oprofile/loongson3:starting", loongson3_starting_cpu, loongson3_dying_cpu); save_perf_irq = perf_irq; perf_irq = loongson3_perfcount_handler; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen3280.00%133.33%
Richard Cochran717.50%133.33%
Thomas Gleixner12.50%133.33%
Total40100.00%3100.00%


static void loongson3_exit(void) { on_each_cpu(reset_counters, NULL, 1); cpuhp_remove_state_nocalls(CPUHP_AP_MIPS_OP_LOONGSON3_STARTING); perf_irq = save_perf_irq; }

Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen2492.31%150.00%
Richard Cochran27.69%150.00%
Total26100.00%2100.00%

struct op_mips_model op_model_loongson3_ops = { .reg_setup = loongson3_reg_setup, .cpu_setup = loongson3_cpu_setup, .init = loongson3_init, .exit = loongson3_exit, .cpu_start = loongson3_cpu_start, .cpu_stop = loongson3_cpu_stop, .cpu_type = "mips/loongson3", .num_counters = 2 };

Overall Contributors

PersonTokensPropCommitsCommitProp
Huacai Chen83896.77%125.00%
Richard Cochran263.00%125.00%
Linus Torvalds10.12%125.00%
Thomas Gleixner10.12%125.00%
Total866100.00%4100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.