arch/csky/abiv2/fpu.c

Source file repositories/reference/linux-study-clean/arch/csky/abiv2/fpu.c

File Facts

System
Linux kernel
Corpus path
arch/csky/abiv2/fpu.c
Extension
.c
Size
5431 bytes
Lines
271
Domain
Architecture Layer
Bucket
arch/csky
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

// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#include <linux/ptrace.h>
#include <linux/uaccess.h>
#include <abi/reg_ops.h>

#define MTCR_MASK	0xFC00FFE0
#define MFCR_MASK	0xFC00FFE0
#define MTCR_DIST	0xC0006420
#define MFCR_DIST	0xC0006020

/*
 * fpu_libc_helper() is to help libc to excute:
 *  - mfcr %a, cr<1, 2>
 *  - mfcr %a, cr<2, 2>
 *  - mtcr %a, cr<1, 2>
 *  - mtcr %a, cr<2, 2>
 */
int fpu_libc_helper(struct pt_regs *regs)
{
	int fault;
	unsigned long instrptr, regx = 0;
	unsigned long index = 0, tmp = 0;
	unsigned long tinstr = 0;
	u16 instr_hi, instr_low;

	instrptr = instruction_pointer(regs);
	if (instrptr & 1)
		return 0;

	fault = __get_user(instr_low, (u16 *)instrptr);
	if (fault)
		return 0;

	fault = __get_user(instr_hi, (u16 *)(instrptr + 2));
	if (fault)
		return 0;

	tinstr = instr_hi | ((unsigned long)instr_low << 16);

	if (((tinstr >> 21) & 0x1F) != 2)
		return 0;

	if ((tinstr & MTCR_MASK) == MTCR_DIST) {
		index = (tinstr >> 16) & 0x1F;
		if (index > 13)
			return 0;

		tmp = tinstr & 0x1F;
		if (tmp > 2)
			return 0;

		regx =  *(&regs->a0 + index);

		if (tmp == 1)
			mtcr("cr<1, 2>", regx);
		else if (tmp == 2)
			mtcr("cr<2, 2>", regx);
		else
			return 0;

		regs->pc += 4;
		return 1;
	}

	if ((tinstr & MFCR_MASK) == MFCR_DIST) {
		index = tinstr & 0x1F;
		if (index > 13)
			return 0;

		tmp = ((tinstr >> 16) & 0x1F);
		if (tmp > 2)
			return 0;

		if (tmp == 1)
			regx = mfcr("cr<1, 2>");
		else if (tmp == 2)
			regx = mfcr("cr<2, 2>");
		else
			return 0;

		*(&regs->a0 + index) = regx;

		regs->pc += 4;
		return 1;
	}

	return 0;
}

Annotation

Implementation Notes