arch/powerpc/platforms/pseries/dtl.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/pseries/dtl.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/pseries/dtl.c
Extension
.c
Size
9717 bytes
Lines
445
Domain
Architecture Layer
Bucket
arch/powerpc
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 dtl_fops = {
	.open		= dtl_file_open,
	.release	= dtl_file_release,
	.read		= dtl_file_read,
};

static struct dentry *dtl_dir;

static void dtl_setup_file(struct dtl *dtl)
{
	char name[10];

	sprintf(name, "cpu-%d", dtl->cpu);

	debugfs_create_file(name, 0400, dtl_dir, dtl, &dtl_fops);
}

static int dtl_init(void)
{
	int i;

	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
		return -ENODEV;

	/* set up common debugfs structure */

	dtl_dir = debugfs_create_dir("dtl", arch_debugfs_dir);

	debugfs_create_x8("dtl_event_mask", 0600, dtl_dir, &dtl_event_mask);
	debugfs_create_u32("dtl_buf_entries", 0400, dtl_dir, &dtl_buf_entries);

	/* set up the per-cpu log structures */
	for_each_possible_cpu(i) {
		struct dtl *dtl = &per_cpu(cpu_dtl, i);
		spin_lock_init(&dtl->lock);
		dtl->cpu = i;

		dtl_setup_file(dtl);
	}

	return 0;
}
machine_arch_initcall(pseries, dtl_init);
#endif /* CONFIG_DTL */

#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
/*
 * Scan the dispatch trace log and count up the stolen time.
 * Should be called with interrupts disabled.
 */
static notrace u64 scan_dispatch_log(u64 stop_tb)
{
	u64 i = local_paca->dtl_ridx;
	struct dtl_entry *dtl = local_paca->dtl_curr;
	struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
	struct lppaca *vpa = local_paca->lppaca_ptr;
	u64 tb_delta;
	u64 stolen = 0;
	u64 dtb;

	if (!dtl)
		return 0;

	if (i == be64_to_cpu(vpa->dtl_idx))
		return 0;
	while (i < be64_to_cpu(vpa->dtl_idx)) {
		dtb = be64_to_cpu(dtl->timebase);
		tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
			be32_to_cpu(dtl->ready_to_enqueue_time);
		barrier();
		if (i + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx)) {
			/* buffer has overflowed */
			i = be64_to_cpu(vpa->dtl_idx) - N_DISPATCH_LOG;
			dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
			continue;
		}
		if (dtb > stop_tb)
			break;
#ifdef CONFIG_DTL
		if (dtl_consumer)
			dtl_consumer(dtl, i);
#endif
		stolen += tb_delta;
		++i;
		++dtl;
		if (dtl == dtl_end)
			dtl = local_paca->dispatch_log;
	}
	local_paca->dtl_ridx = i;
	local_paca->dtl_curr = dtl;

Annotation

Implementation Notes