arch/riscv/kernel/unaligned_access_speed.c

Source file repositories/reference/linux-study-clean/arch/riscv/kernel/unaligned_access_speed.c

File Facts

System
Linux kernel
Corpus path
arch/riscv/kernel/unaligned_access_speed.c
Extension
.c
Size
11798 bytes
Lines
415
Domain
Architecture Layer
Bucket
arch/riscv
Inferred role
Architecture Layer: implementation source
Status
source 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

if (!bufs[cpu]) {
			pr_warn("Allocation failure, not measuring misaligned performance\n");
			goto out;
		}
	}

	on_each_cpu(_check_unaligned_access, bufs, 1);

out:
	for_each_cpu(cpu, cpu_online_mask) {
		if (bufs[cpu])
			__free_pages(bufs[cpu], MISALIGNED_BUFFER_ORDER);
	}

	kfree(bufs);
}
#else /* CONFIG_RISCV_PROBE_UNALIGNED_ACCESS */
static void __init check_unaligned_access_speed_all_cpus(void)
{
}
#endif

DEFINE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key);

static void modify_unaligned_access_branches(const cpumask_t *mask)
{
	bool fast = true;
	int cpu;

	for_each_cpu(cpu, mask) {
		if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_FAST) {
			fast = false;
			break;
		}
	}

	if (fast)
		static_branch_enable_cpuslocked(&fast_unaligned_access_speed_key);
	else
		static_branch_disable_cpuslocked(&fast_unaligned_access_speed_key);
}

static int riscv_online_cpu(unsigned int cpu)
{
	int ret = cpu_online_unaligned_access_init(cpu);

	if (ret)
		return ret;

	/* We are already set since the last check */
	if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN) {
		goto exit;
	} else if (unaligned_scalar_speed_param != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN) {
		per_cpu(misaligned_access_speed, cpu) = unaligned_scalar_speed_param;
		goto exit;
	}

#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS
	{
		static struct page *buf;

		buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
		if (!buf) {
			pr_warn("Allocation failure, not measuring misaligned performance\n");
			return -ENOMEM;
		}

		check_unaligned_access(buf);
		__free_pages(buf, MISALIGNED_BUFFER_ORDER);
	}
#endif

exit:
	modify_unaligned_access_branches(cpu_online_mask);

	return 0;
}

static int riscv_offline_cpu(unsigned int cpu)
{
	cpumask_t mask;

	cpumask_copy(&mask, cpu_online_mask);
	cpumask_clear_cpu(cpu, &mask);

	modify_unaligned_access_branches(&mask);

	return 0;
}

Annotation

Implementation Notes