cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

unaligned_64.c (18042B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * unaligned.c: Unaligned load/store trap handling with special
      4 *              cases for the kernel to do them more quickly.
      5 *
      6 * Copyright (C) 1996,2008 David S. Miller (davem@davemloft.net)
      7 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
      8 */
      9
     10
     11#include <linux/jiffies.h>
     12#include <linux/kernel.h>
     13#include <linux/sched.h>
     14#include <linux/mm.h>
     15#include <linux/extable.h>
     16#include <asm/asi.h>
     17#include <asm/ptrace.h>
     18#include <asm/pstate.h>
     19#include <asm/processor.h>
     20#include <linux/uaccess.h>
     21#include <linux/smp.h>
     22#include <linux/bitops.h>
     23#include <linux/perf_event.h>
     24#include <linux/ratelimit.h>
     25#include <linux/context_tracking.h>
     26#include <asm/fpumacro.h>
     27#include <asm/cacheflush.h>
     28#include <asm/setup.h>
     29
     30#include "entry.h"
     31#include "kernel.h"
     32
     33enum direction {
     34	load,    /* ld, ldd, ldh, ldsh */
     35	store,   /* st, std, sth, stsh */
     36	both,    /* Swap, ldstub, cas, ... */
     37	fpld,
     38	fpst,
     39	invalid,
     40};
     41
     42static inline enum direction decode_direction(unsigned int insn)
     43{
     44	unsigned long tmp = (insn >> 21) & 1;
     45
     46	if (!tmp)
     47		return load;
     48	else {
     49		switch ((insn>>19)&0xf) {
     50		case 15: /* swap* */
     51			return both;
     52		default:
     53			return store;
     54		}
     55	}
     56}
     57
     58/* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */
     59static inline int decode_access_size(struct pt_regs *regs, unsigned int insn)
     60{
     61	unsigned int tmp;
     62
     63	tmp = ((insn >> 19) & 0xf);
     64	if (tmp == 11 || tmp == 14) /* ldx/stx */
     65		return 8;
     66	tmp &= 3;
     67	if (!tmp)
     68		return 4;
     69	else if (tmp == 3)
     70		return 16;	/* ldd/std - Although it is actually 8 */
     71	else if (tmp == 2)
     72		return 2;
     73	else {
     74		printk("Impossible unaligned trap. insn=%08x\n", insn);
     75		die_if_kernel("Byte sized unaligned access?!?!", regs);
     76
     77		/* GCC should never warn that control reaches the end
     78		 * of this function without returning a value because
     79		 * die_if_kernel() is marked with attribute 'noreturn'.
     80		 * Alas, some versions do...
     81		 */
     82
     83		return 0;
     84	}
     85}
     86
     87static inline int decode_asi(unsigned int insn, struct pt_regs *regs)
     88{
     89	if (insn & 0x800000) {
     90		if (insn & 0x2000)
     91			return (unsigned char)(regs->tstate >> 24);	/* %asi */
     92		else
     93			return (unsigned char)(insn >> 5);		/* imm_asi */
     94	} else
     95		return ASI_P;
     96}
     97
     98/* 0x400000 = signed, 0 = unsigned */
     99static inline int decode_signedness(unsigned int insn)
    100{
    101	return (insn & 0x400000);
    102}
    103
    104static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
    105				       unsigned int rd, int from_kernel)
    106{
    107	if (rs2 >= 16 || rs1 >= 16 || rd >= 16) {
    108		if (from_kernel != 0)
    109			__asm__ __volatile__("flushw");
    110		else
    111			flushw_user();
    112	}
    113}
    114
    115static inline long sign_extend_imm13(long imm)
    116{
    117	return imm << 51 >> 51;
    118}
    119
    120static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
    121{
    122	unsigned long value, fp;
    123	
    124	if (reg < 16)
    125		return (!reg ? 0 : regs->u_regs[reg]);
    126
    127	fp = regs->u_regs[UREG_FP];
    128
    129	if (regs->tstate & TSTATE_PRIV) {
    130		struct reg_window *win;
    131		win = (struct reg_window *)(fp + STACK_BIAS);
    132		value = win->locals[reg - 16];
    133	} else if (!test_thread_64bit_stack(fp)) {
    134		struct reg_window32 __user *win32;
    135		win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
    136		get_user(value, &win32->locals[reg - 16]);
    137	} else {
    138		struct reg_window __user *win;
    139		win = (struct reg_window __user *)(fp + STACK_BIAS);
    140		get_user(value, &win->locals[reg - 16]);
    141	}
    142	return value;
    143}
    144
    145static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
    146{
    147	unsigned long fp;
    148
    149	if (reg < 16)
    150		return &regs->u_regs[reg];
    151
    152	fp = regs->u_regs[UREG_FP];
    153
    154	if (regs->tstate & TSTATE_PRIV) {
    155		struct reg_window *win;
    156		win = (struct reg_window *)(fp + STACK_BIAS);
    157		return &win->locals[reg - 16];
    158	} else if (!test_thread_64bit_stack(fp)) {
    159		struct reg_window32 *win32;
    160		win32 = (struct reg_window32 *)((unsigned long)((u32)fp));
    161		return (unsigned long *)&win32->locals[reg - 16];
    162	} else {
    163		struct reg_window *win;
    164		win = (struct reg_window *)(fp + STACK_BIAS);
    165		return &win->locals[reg - 16];
    166	}
    167}
    168
    169unsigned long compute_effective_address(struct pt_regs *regs,
    170					unsigned int insn, unsigned int rd)
    171{
    172	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
    173	unsigned int rs1 = (insn >> 14) & 0x1f;
    174	unsigned int rs2 = insn & 0x1f;
    175	unsigned long addr;
    176
    177	if (insn & 0x2000) {
    178		maybe_flush_windows(rs1, 0, rd, from_kernel);
    179		addr = (fetch_reg(rs1, regs) + sign_extend_imm13(insn));
    180	} else {
    181		maybe_flush_windows(rs1, rs2, rd, from_kernel);
    182		addr = (fetch_reg(rs1, regs) + fetch_reg(rs2, regs));
    183	}
    184
    185	if (!from_kernel && test_thread_flag(TIF_32BIT))
    186		addr &= 0xffffffff;
    187
    188	return addr;
    189}
    190
    191/* This is just to make gcc think die_if_kernel does return... */
    192static void __used unaligned_panic(char *str, struct pt_regs *regs)
    193{
    194	die_if_kernel(str, regs);
    195}
    196
    197extern int do_int_load(unsigned long *dest_reg, int size,
    198		       unsigned long *saddr, int is_signed, int asi);
    199	
    200extern int __do_int_store(unsigned long *dst_addr, int size,
    201			  unsigned long src_val, int asi);
    202
    203static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr,
    204			       struct pt_regs *regs, int asi, int orig_asi)
    205{
    206	unsigned long zero = 0;
    207	unsigned long *src_val_p = &zero;
    208	unsigned long src_val;
    209
    210	if (size == 16) {
    211		size = 8;
    212		zero = (((long)(reg_num ?
    213		        (unsigned int)fetch_reg(reg_num, regs) : 0)) << 32) |
    214			(unsigned int)fetch_reg(reg_num + 1, regs);
    215	} else if (reg_num) {
    216		src_val_p = fetch_reg_addr(reg_num, regs);
    217	}
    218	src_val = *src_val_p;
    219	if (unlikely(asi != orig_asi)) {
    220		switch (size) {
    221		case 2:
    222			src_val = swab16(src_val);
    223			break;
    224		case 4:
    225			src_val = swab32(src_val);
    226			break;
    227		case 8:
    228			src_val = swab64(src_val);
    229			break;
    230		case 16:
    231		default:
    232			BUG();
    233			break;
    234		}
    235	}
    236	return __do_int_store(dst_addr, size, src_val, asi);
    237}
    238
    239static inline void advance(struct pt_regs *regs)
    240{
    241	regs->tpc   = regs->tnpc;
    242	regs->tnpc += 4;
    243	if (test_thread_flag(TIF_32BIT)) {
    244		regs->tpc &= 0xffffffff;
    245		regs->tnpc &= 0xffffffff;
    246	}
    247}
    248
    249static inline int floating_point_load_or_store_p(unsigned int insn)
    250{
    251	return (insn >> 24) & 1;
    252}
    253
    254static inline int ok_for_kernel(unsigned int insn)
    255{
    256	return !floating_point_load_or_store_p(insn);
    257}
    258
    259static void kernel_mna_trap_fault(int fixup_tstate_asi)
    260{
    261	struct pt_regs *regs = current_thread_info()->kern_una_regs;
    262	unsigned int insn = current_thread_info()->kern_una_insn;
    263	const struct exception_table_entry *entry;
    264
    265	entry = search_exception_tables(regs->tpc);
    266	if (!entry) {
    267		unsigned long address;
    268
    269		address = compute_effective_address(regs, insn,
    270						    ((insn >> 25) & 0x1f));
    271        	if (address < PAGE_SIZE) {
    272                	printk(KERN_ALERT "Unable to handle kernel NULL "
    273			       "pointer dereference in mna handler");
    274        	} else
    275                	printk(KERN_ALERT "Unable to handle kernel paging "
    276			       "request in mna handler");
    277	        printk(KERN_ALERT " at virtual address %016lx\n",address);
    278		printk(KERN_ALERT "current->{active_,}mm->context = %016lx\n",
    279			(current->mm ? CTX_HWBITS(current->mm->context) :
    280			CTX_HWBITS(current->active_mm->context)));
    281		printk(KERN_ALERT "current->{active_,}mm->pgd = %016lx\n",
    282			(current->mm ? (unsigned long) current->mm->pgd :
    283			(unsigned long) current->active_mm->pgd));
    284	        die_if_kernel("Oops", regs);
    285		/* Not reached */
    286	}
    287	regs->tpc = entry->fixup;
    288	regs->tnpc = regs->tpc + 4;
    289
    290	if (fixup_tstate_asi) {
    291		regs->tstate &= ~TSTATE_ASI;
    292		regs->tstate |= (ASI_AIUS << 24UL);
    293	}
    294}
    295
    296static void log_unaligned(struct pt_regs *regs)
    297{
    298	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
    299
    300	if (__ratelimit(&ratelimit)) {
    301		printk("Kernel unaligned access at TPC[%lx] %pS\n",
    302		       regs->tpc, (void *) regs->tpc);
    303	}
    304}
    305
    306asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
    307{
    308	enum direction dir = decode_direction(insn);
    309	int size = decode_access_size(regs, insn);
    310	int orig_asi, asi;
    311
    312	current_thread_info()->kern_una_regs = regs;
    313	current_thread_info()->kern_una_insn = insn;
    314
    315	orig_asi = asi = decode_asi(insn, regs);
    316
    317	/* If this is a {get,put}_user() on an unaligned userspace pointer,
    318	 * just signal a fault and do not log the event.
    319	 */
    320	if (asi == ASI_AIUS) {
    321		kernel_mna_trap_fault(0);
    322		return;
    323	}
    324
    325	log_unaligned(regs);
    326
    327	if (!ok_for_kernel(insn) || dir == both) {
    328		printk("Unsupported unaligned load/store trap for kernel "
    329		       "at <%016lx>.\n", regs->tpc);
    330		unaligned_panic("Kernel does fpu/atomic "
    331				"unaligned load/store.", regs);
    332
    333		kernel_mna_trap_fault(0);
    334	} else {
    335		unsigned long addr, *reg_addr;
    336		int err;
    337
    338		addr = compute_effective_address(regs, insn,
    339						 ((insn >> 25) & 0x1f));
    340		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
    341		switch (asi) {
    342		case ASI_NL:
    343		case ASI_AIUPL:
    344		case ASI_AIUSL:
    345		case ASI_PL:
    346		case ASI_SL:
    347		case ASI_PNFL:
    348		case ASI_SNFL:
    349			asi &= ~0x08;
    350			break;
    351		}
    352		switch (dir) {
    353		case load:
    354			reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
    355			err = do_int_load(reg_addr, size,
    356					  (unsigned long *) addr,
    357					  decode_signedness(insn), asi);
    358			if (likely(!err) && unlikely(asi != orig_asi)) {
    359				unsigned long val_in = *reg_addr;
    360				switch (size) {
    361				case 2:
    362					val_in = swab16(val_in);
    363					break;
    364				case 4:
    365					val_in = swab32(val_in);
    366					break;
    367				case 8:
    368					val_in = swab64(val_in);
    369					break;
    370				case 16:
    371				default:
    372					BUG();
    373					break;
    374				}
    375				*reg_addr = val_in;
    376			}
    377			break;
    378
    379		case store:
    380			err = do_int_store(((insn>>25)&0x1f), size,
    381					   (unsigned long *) addr, regs,
    382					   asi, orig_asi);
    383			break;
    384
    385		default:
    386			panic("Impossible kernel unaligned trap.");
    387			/* Not reached... */
    388		}
    389		if (unlikely(err))
    390			kernel_mna_trap_fault(1);
    391		else
    392			advance(regs);
    393	}
    394}
    395
    396int handle_popc(u32 insn, struct pt_regs *regs)
    397{
    398	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
    399	int ret, rd = ((insn >> 25) & 0x1f);
    400	u64 value;
    401	                        
    402	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
    403	if (insn & 0x2000) {
    404		maybe_flush_windows(0, 0, rd, from_kernel);
    405		value = sign_extend_imm13(insn);
    406	} else {
    407		maybe_flush_windows(0, insn & 0x1f, rd, from_kernel);
    408		value = fetch_reg(insn & 0x1f, regs);
    409	}
    410	ret = hweight64(value);
    411	if (rd < 16) {
    412		if (rd)
    413			regs->u_regs[rd] = ret;
    414	} else {
    415		unsigned long fp = regs->u_regs[UREG_FP];
    416
    417		if (!test_thread_64bit_stack(fp)) {
    418			struct reg_window32 __user *win32;
    419			win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
    420			put_user(ret, &win32->locals[rd - 16]);
    421		} else {
    422			struct reg_window __user *win;
    423			win = (struct reg_window __user *)(fp + STACK_BIAS);
    424			put_user(ret, &win->locals[rd - 16]);
    425		}
    426	}
    427	advance(regs);
    428	return 1;
    429}
    430
    431extern void do_fpother(struct pt_regs *regs);
    432extern void do_privact(struct pt_regs *regs);
    433extern void sun4v_data_access_exception(struct pt_regs *regs,
    434					unsigned long addr,
    435					unsigned long type_ctx);
    436
    437int handle_ldf_stq(u32 insn, struct pt_regs *regs)
    438{
    439	unsigned long addr = compute_effective_address(regs, insn, 0);
    440	int freg;
    441	struct fpustate *f = FPUSTATE;
    442	int asi = decode_asi(insn, regs);
    443	int flag;
    444
    445	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
    446
    447	save_and_clear_fpu();
    448	current_thread_info()->xfsr[0] &= ~0x1c000;
    449	if (insn & 0x200000) {
    450		/* STQ */
    451		u64 first = 0, second = 0;
    452		
    453		freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
    454		flag = (freg < 32) ? FPRS_DL : FPRS_DU;
    455		if (freg & 3) {
    456			current_thread_info()->xfsr[0] |= (6 << 14) /* invalid_fp_register */;
    457			do_fpother(regs);
    458			return 0;
    459		}
    460		if (current_thread_info()->fpsaved[0] & flag) {
    461			first = *(u64 *)&f->regs[freg];
    462			second = *(u64 *)&f->regs[freg+2];
    463		}
    464		if (asi < 0x80) {
    465			do_privact(regs);
    466			return 1;
    467		}
    468		switch (asi) {
    469		case ASI_P:
    470		case ASI_S: break;
    471		case ASI_PL:
    472		case ASI_SL: 
    473			{
    474				/* Need to convert endians */
    475				u64 tmp = __swab64p(&first);
    476				
    477				first = __swab64p(&second);
    478				second = tmp;
    479				break;
    480			}
    481		default:
    482			if (tlb_type == hypervisor)
    483				sun4v_data_access_exception(regs, addr, 0);
    484			else
    485				spitfire_data_access_exception(regs, 0, addr);
    486			return 1;
    487		}
    488		if (put_user (first >> 32, (u32 __user *)addr) ||
    489		    __put_user ((u32)first, (u32 __user *)(addr + 4)) ||
    490		    __put_user (second >> 32, (u32 __user *)(addr + 8)) ||
    491		    __put_user ((u32)second, (u32 __user *)(addr + 12))) {
    492			if (tlb_type == hypervisor)
    493				sun4v_data_access_exception(regs, addr, 0);
    494			else
    495				spitfire_data_access_exception(regs, 0, addr);
    496		    	return 1;
    497		}
    498	} else {
    499		/* LDF, LDDF, LDQF */
    500		u32 data[4] __attribute__ ((aligned(8)));
    501		int size, i;
    502		int err;
    503
    504		if (asi < 0x80) {
    505			do_privact(regs);
    506			return 1;
    507		} else if (asi > ASI_SNFL) {
    508			if (tlb_type == hypervisor)
    509				sun4v_data_access_exception(regs, addr, 0);
    510			else
    511				spitfire_data_access_exception(regs, 0, addr);
    512			return 1;
    513		}
    514		switch (insn & 0x180000) {
    515		case 0x000000: size = 1; break;
    516		case 0x100000: size = 4; break;
    517		default: size = 2; break;
    518		}
    519		if (size == 1)
    520			freg = (insn >> 25) & 0x1f;
    521		else
    522			freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
    523		flag = (freg < 32) ? FPRS_DL : FPRS_DU;
    524
    525		for (i = 0; i < size; i++)
    526			data[i] = 0;
    527		
    528		err = get_user (data[0], (u32 __user *) addr);
    529		if (!err) {
    530			for (i = 1; i < size; i++)
    531				err |= __get_user (data[i], (u32 __user *)(addr + 4*i));
    532		}
    533		if (err && !(asi & 0x2 /* NF */)) {
    534			if (tlb_type == hypervisor)
    535				sun4v_data_access_exception(regs, addr, 0);
    536			else
    537				spitfire_data_access_exception(regs, 0, addr);
    538			return 1;
    539		}
    540		if (asi & 0x8) /* Little */ {
    541			u64 tmp;
    542
    543			switch (size) {
    544			case 1: data[0] = le32_to_cpup(data + 0); break;
    545			default:*(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 0));
    546				break;
    547			case 4: tmp = le64_to_cpup((u64 *)(data + 0));
    548				*(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 2));
    549				*(u64 *)(data + 2) = tmp;
    550				break;
    551			}
    552		}
    553		if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) {
    554			current_thread_info()->fpsaved[0] = FPRS_FEF;
    555			current_thread_info()->gsr[0] = 0;
    556		}
    557		if (!(current_thread_info()->fpsaved[0] & flag)) {
    558			if (freg < 32)
    559				memset(f->regs, 0, 32*sizeof(u32));
    560			else
    561				memset(f->regs+32, 0, 32*sizeof(u32));
    562		}
    563		memcpy(f->regs + freg, data, size * 4);
    564		current_thread_info()->fpsaved[0] |= flag;
    565	}
    566	advance(regs);
    567	return 1;
    568}
    569
    570void handle_ld_nf(u32 insn, struct pt_regs *regs)
    571{
    572	int rd = ((insn >> 25) & 0x1f);
    573	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
    574	unsigned long *reg;
    575	                        
    576	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
    577
    578	maybe_flush_windows(0, 0, rd, from_kernel);
    579	reg = fetch_reg_addr(rd, regs);
    580	if (from_kernel || rd < 16) {
    581		reg[0] = 0;
    582		if ((insn & 0x780000) == 0x180000)
    583			reg[1] = 0;
    584	} else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
    585		put_user(0, (int __user *) reg);
    586		if ((insn & 0x780000) == 0x180000)
    587			put_user(0, ((int __user *) reg) + 1);
    588	} else {
    589		put_user(0, (unsigned long __user *) reg);
    590		if ((insn & 0x780000) == 0x180000)
    591			put_user(0, (unsigned long __user *) reg + 1);
    592	}
    593	advance(regs);
    594}
    595
    596void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
    597{
    598	enum ctx_state prev_state = exception_enter();
    599	unsigned long pc = regs->tpc;
    600	unsigned long tstate = regs->tstate;
    601	u32 insn;
    602	u64 value;
    603	u8 freg;
    604	int flag;
    605	struct fpustate *f = FPUSTATE;
    606
    607	if (tstate & TSTATE_PRIV)
    608		die_if_kernel("lddfmna from kernel", regs);
    609	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
    610	if (test_thread_flag(TIF_32BIT))
    611		pc = (u32)pc;
    612	if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
    613		int asi = decode_asi(insn, regs);
    614		u32 first, second;
    615		int err;
    616
    617		if ((asi > ASI_SNFL) ||
    618		    (asi < ASI_P))
    619			goto daex;
    620		first = second = 0;
    621		err = get_user(first, (u32 __user *)sfar);
    622		if (!err)
    623			err = get_user(second, (u32 __user *)(sfar + 4));
    624		if (err) {
    625			if (!(asi & 0x2))
    626				goto daex;
    627			first = second = 0;
    628		}
    629		save_and_clear_fpu();
    630		freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
    631		value = (((u64)first) << 32) | second;
    632		if (asi & 0x8) /* Little */
    633			value = __swab64p(&value);
    634		flag = (freg < 32) ? FPRS_DL : FPRS_DU;
    635		if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) {
    636			current_thread_info()->fpsaved[0] = FPRS_FEF;
    637			current_thread_info()->gsr[0] = 0;
    638		}
    639		if (!(current_thread_info()->fpsaved[0] & flag)) {
    640			if (freg < 32)
    641				memset(f->regs, 0, 32*sizeof(u32));
    642			else
    643				memset(f->regs+32, 0, 32*sizeof(u32));
    644		}
    645		*(u64 *)(f->regs + freg) = value;
    646		current_thread_info()->fpsaved[0] |= flag;
    647	} else {
    648daex:
    649		if (tlb_type == hypervisor)
    650			sun4v_data_access_exception(regs, sfar, sfsr);
    651		else
    652			spitfire_data_access_exception(regs, sfsr, sfar);
    653		goto out;
    654	}
    655	advance(regs);
    656out:
    657	exception_exit(prev_state);
    658}
    659
    660void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
    661{
    662	enum ctx_state prev_state = exception_enter();
    663	unsigned long pc = regs->tpc;
    664	unsigned long tstate = regs->tstate;
    665	u32 insn;
    666	u64 value;
    667	u8 freg;
    668	int flag;
    669	struct fpustate *f = FPUSTATE;
    670
    671	if (tstate & TSTATE_PRIV)
    672		die_if_kernel("stdfmna from kernel", regs);
    673	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
    674	if (test_thread_flag(TIF_32BIT))
    675		pc = (u32)pc;
    676	if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
    677		int asi = decode_asi(insn, regs);
    678		freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
    679		value = 0;
    680		flag = (freg < 32) ? FPRS_DL : FPRS_DU;
    681		if ((asi > ASI_SNFL) ||
    682		    (asi < ASI_P))
    683			goto daex;
    684		save_and_clear_fpu();
    685		if (current_thread_info()->fpsaved[0] & flag)
    686			value = *(u64 *)&f->regs[freg];
    687		switch (asi) {
    688		case ASI_P:
    689		case ASI_S: break;
    690		case ASI_PL:
    691		case ASI_SL: 
    692			value = __swab64p(&value); break;
    693		default: goto daex;
    694		}
    695		if (put_user (value >> 32, (u32 __user *) sfar) ||
    696		    __put_user ((u32)value, (u32 __user *)(sfar + 4)))
    697			goto daex;
    698	} else {
    699daex:
    700		if (tlb_type == hypervisor)
    701			sun4v_data_access_exception(regs, sfar, sfsr);
    702		else
    703			spitfire_data_access_exception(regs, sfsr, sfar);
    704		goto out;
    705	}
    706	advance(regs);
    707out:
    708	exception_exit(prev_state);
    709}