mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	x86: Fix instruction decoder to handle grouped AVX instructions
For reducing memory usage of attribute table, x86 instruction decoder puts "Group" attribute only on "no-last-prefix" attribute table (same as vex_p == 0 case). Thus, the decoder should look no-last-prefix table first, and then only if it is not a group, move on to "with-last-prefix" table (vex_p != 0). However, current implementation, inat_get_avx_attribute() looks with-last-prefix directly. So, when decoding a grouped AVX instruction, the decoder fails to find correct group because there is no "Group" attribute on the table. This ends up with the mis-decoding of instructions, as Ingo reported in http://thread.gmane.org/gmane.linux.kernel/1214103 This patch fixes it to check no-last-prefix table first even if that is an AVX instruction, and get an attribute from "with last-prefix" table only if that is not a group. Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: yrl.pp-manager.tt@hitachi.com Link: http://lkml.kernel.org/r/20111205120539.15475.91428.stgit@cloud Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
		
							parent
							
								
									1056c3e916
								
							
						
					
					
						commit
						130b78b2bf
					
				
					 2 changed files with 11 additions and 2 deletions
				
			
		|  | @ -82,9 +82,16 @@ insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m, | |||
| 	const insn_attr_t *table; | ||||
| 	if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX) | ||||
| 		return 0; | ||||
| 	table = inat_avx_tables[vex_m][vex_p]; | ||||
| 	/* At first, this checks the master table */ | ||||
| 	table = inat_avx_tables[vex_m][0]; | ||||
| 	if (!table) | ||||
| 		return 0; | ||||
| 	if (!inat_is_group(table[opcode]) && vex_p) { | ||||
| 		/* If this is not a group, get attribute directly */ | ||||
| 		table = inat_avx_tables[vex_m][vex_p]; | ||||
| 		if (!table) | ||||
| 			return 0; | ||||
| 	} | ||||
| 	return table[opcode]; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -202,7 +202,7 @@ void insn_get_opcode(struct insn *insn) | |||
| 		m = insn_vex_m_bits(insn); | ||||
| 		p = insn_vex_p_bits(insn); | ||||
| 		insn->attr = inat_get_avx_attribute(op, m, p); | ||||
| 		if (!inat_accept_vex(insn->attr)) | ||||
| 		if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr)) | ||||
| 			insn->attr = 0;	/* This instruction is bad */ | ||||
| 		goto end;	/* VEX has only 1 byte for opcode */ | ||||
| 	} | ||||
|  | @ -249,6 +249,8 @@ void insn_get_modrm(struct insn *insn) | |||
| 			pfx = insn_last_prefix(insn); | ||||
| 			insn->attr = inat_get_group_attribute(mod, pfx, | ||||
| 							      insn->attr); | ||||
| 			if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) | ||||
| 				insn->attr = 0;	/* This is bad */ | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Masami Hiramatsu
						Masami Hiramatsu