arch/mips/loongson64/cop2-ex.c

Source file repositories/reference/linux-study-clean/arch/mips/loongson64/cop2-ex.c

File Facts

System
Linux kernel
Corpus path
arch/mips/loongson64/cop2-ex.c
Extension
.c
Size
8057 bytes
Lines
342
Domain
Architecture Layer
Bucket
arch/mips
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 (!fpu_owned) {
			set_thread_flag(TIF_USEDFPU);
			init_fp_ctx(current);
			_restore_fp(current);
		}
		preempt_enable();

		return NOTIFY_STOP;	/* Don't call default notifier */

	case CU2_LWC2_OP:
		if (insn.loongson3_lswc2_format.ls == 0)
			goto sigbus;

		if (insn.loongson3_lswc2_format.fr == 0) {	/* gslq */
			if (!access_ok(addr, 16))
				goto sigbus;

			LoadDW(addr, value, res);
			if (res)
				goto fault;

			LoadDW(addr + 8, value_next, res);
			if (res)
				goto fault;

			regs->regs[insn.loongson3_lswc2_format.rt] = value;
			regs->regs[insn.loongson3_lswc2_format.rq] = value_next;
			compute_return_epc(regs);
		} else {					/* gslqc1 */
			if (!access_ok(addr, 16))
				goto sigbus;

			lose_fpu(1);
			LoadDW(addr, value, res);
			if (res)
				goto fault;

			LoadDW(addr + 8, value_next, res);
			if (res)
				goto fault;

			set_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rt], 0, value);
			set_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rq], 0, value_next);
			compute_return_epc(regs);
			own_fpu(1);
		}
		return NOTIFY_STOP;	/* Don't call default notifier */

	case CU2_SWC2_OP:
		if (insn.loongson3_lswc2_format.ls == 0)
			goto sigbus;

		if (insn.loongson3_lswc2_format.fr == 0) {	/* gssq */
			if (!access_ok(addr, 16))
				goto sigbus;

			/* write upper 8 bytes first */
			value_next = regs->regs[insn.loongson3_lswc2_format.rq];

			StoreDW(addr + 8, value_next, res);
			if (res)
				goto fault;
			value = regs->regs[insn.loongson3_lswc2_format.rt];

			StoreDW(addr, value, res);
			if (res)
				goto fault;

			compute_return_epc(regs);
		} else {					/* gssqc1 */
			if (!access_ok(addr, 16))
				goto sigbus;

			lose_fpu(1);
			value_next = get_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rq], 0);

			StoreDW(addr + 8, value_next, res);
			if (res)
				goto fault;

			value = get_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rt], 0);

			StoreDW(addr, value, res);
			if (res)
				goto fault;

			compute_return_epc(regs);
			own_fpu(1);
		}
		return NOTIFY_STOP;	/* Don't call default notifier */

Annotation

Implementation Notes