arch/s390/kernel/perf_cpum_cf.c

Source file repositories/reference/linux-study-clean/arch/s390/kernel/perf_cpum_cf.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/perf_cpum_cf.c
Extension
.c
Size
56354 bytes
Lines
1948
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations cfset_fops = {
	.owner = THIS_MODULE,
	.open = cfset_open,
	.release = cfset_release,
	.unlocked_ioctl	= cfset_ioctl,
};

static struct miscdevice cfset_dev = {
	.name	= S390_HWCTR_DEVICE,
	.minor	= MISC_DYNAMIC_MINOR,
	.fops	= &cfset_fops,
	.mode	= 0666,
};

/* Hotplug add of a CPU. Scan through all active processes and add
 * that CPU to the list of CPUs supplied with ioctl(..., START, ...).
 */
static int cfset_online_cpu(unsigned int cpu)
{
	struct cfset_call_on_cpu_parm p;
	struct cfset_request *rp;

	if (!list_empty(&cfset_session.head)) {
		list_for_each_entry(rp, &cfset_session.head, node) {
			p.sets = rp->ctrset;
			cfset_ioctl_on(&p);
			cpumask_set_cpu(cpu, &rp->mask);
		}
	}
	return 0;
}

/* Hotplug remove of a CPU. Scan through all active processes and clear
 * that CPU from the list of CPUs supplied with ioctl(..., START, ...).
 * Adjust reference counts.
 */
static int cfset_offline_cpu(unsigned int cpu)
{
	struct cfset_call_on_cpu_parm p;
	struct cfset_request *rp;

	if (!list_empty(&cfset_session.head)) {
		list_for_each_entry(rp, &cfset_session.head, node) {
			p.sets = rp->ctrset;
			cfset_ioctl_off(&p);
			cpumask_clear_cpu(cpu, &rp->mask);
		}
	}
	return 0;
}

static void cfdiag_read(struct perf_event *event)
{
}

static int get_authctrsets(void)
{
	unsigned long auth = 0;
	enum cpumf_ctr_set i;

	for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
		if (cpumf_ctr_info.auth_ctl & cpumf_ctr_ctl[i])
			auth |= cpumf_ctr_ctl[i];
	}
	return auth;
}

/* Setup the event. Test for authorized counter sets and only include counter
 * sets which are authorized at the time of the setup. Including unauthorized
 * counter sets result in specification exception (and panic).
 */
static int cfdiag_event_init2(struct perf_event *event)
{
	struct perf_event_attr *attr = &event->attr;
	int err = 0;

	/* Set sample_period to indicate sampling */
	event->hw.config = attr->config;
	event->hw.sample_period = attr->sample_period;
	local64_set(&event->hw.period_left, event->hw.sample_period);
	local64_set(&event->count, 0);
	event->hw.last_period = event->hw.sample_period;

	/* Add all authorized counter sets to config_base. The
	 * the hardware init function is either called per-cpu or just once
	 * for all CPUS (event->cpu == -1).  This depends on the whether
	 * counting is started for all CPUs or on a per workload base where
	 * the perf event moves from one CPU to another CPU.
	 * Checking the authorization on any CPU is fine as the hardware
	 * applies the same authorization settings to all CPUs.

Annotation

Implementation Notes