arch/parisc/kernel/unaligned.c

Source file repositories/reference/linux-study-clean/arch/parisc/kernel/unaligned.c

File Facts

System
Linux kernel
Corpus path
arch/parisc/kernel/unaligned.c
Extension
.c
Size
16442 bytes
Lines
684
Domain
Architecture Layer
Bucket
arch/parisc
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 (current->thread.flags & PARISC_UAC_SIGBUS) {
			goto force_sigbus;
		}

		if (!(current->thread.flags & PARISC_UAC_NOPRINT) &&
			__ratelimit(&ratelimit)) {
			printk(KERN_WARNING "%s(%d): unaligned access to " RFMT
				" at ip " RFMT " (iir " RFMT ")\n",
				current->comm, task_pid_nr(current), regs->ior,
				regs->iaoq[0], regs->iir);
#ifdef DEBUG_UNALIGNED
			show_regs(regs);
#endif		
		}

		if (!unaligned_enabled)
			goto force_sigbus;
	} else {
		static DEFINE_RATELIMIT_STATE(kernel_ratelimit, 5 * HZ, 5);
		if (!(current->thread.flags & PARISC_UAC_NOPRINT) &&
			!no_unaligned_warning &&
			__ratelimit(&kernel_ratelimit))
			pr_warn("Kernel: unaligned access to " RFMT " in %pS "
					"(iir " RFMT ")\n",
				regs->ior, (void *)regs->iaoq[0], regs->iir);
	}

	/* handle modification - OK, it's ugly, see the instruction manual */
	switch (MAJOR_OP(regs->iir))
	{
	case 0x03:
	case 0x09:
	case 0x0b:
		if (regs->iir&0x20)
		{
			modify = 1;
			if (regs->iir&0x1000)		/* short loads */
				if (regs->iir&0x200)
					newbase += IM5_3(regs->iir);
				else
					newbase += IM5_2(regs->iir);
			else if (regs->iir&0x2000)	/* scaled indexed */
			{
				int shift=0;
				switch (regs->iir & OPCODE1_MASK)
				{
				case OPCODE_LDH_I:
					shift= 1; break;
				case OPCODE_LDW_I:
					shift= 2; break;
				case OPCODE_LDD_I:
				case OPCODE_LDDA_I:
					shift= 3; break;
				}
				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift;
			} else				/* simple indexed */
				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
		}
		break;
	case 0x13:
	case 0x1b:
		modify = 1;
		newbase += IM14(regs->iir);
		break;
	case 0x14:
	case 0x1c:
		if (regs->iir&8)
		{
			modify = 1;
			newbase += IM14(regs->iir&~0xe);
		}
		break;
	case 0x16:
	case 0x1e:
		modify = 1;
		newbase += IM14(regs->iir&6);
		break;
	case 0x17:
	case 0x1f:
		if (regs->iir&4)
		{
			modify = 1;
			newbase += IM14(regs->iir&~4);
		}
		break;
	}

	/* TODO: make this cleaner... */
	switch (regs->iir & OPCODE1_MASK)
	{

Annotation

Implementation Notes