tree: git://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git arm64-compat-alignment-fixups head: 16de979d9372710aaa42cd93d3af1e9a43d53369 commit: 16de979d9372710aaa42cd93d3af1e9a43d53369 [2/2] arm64: compat: Implement misalignment fixups for multiword loads config: arm64-randconfig-s031-20220622 (https://download.01.org/0day-ci/archive/20220624/202206240929.vrpaSMjy-lkp@intel.com/config) compiler: aarch64-linux-gcc (GCC) 11.3.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.4-31-g4880bd19-dirty # https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/commit/?id=16de979d9372710aaa42cd93d3af1e9a43d53369 git remote add ardb git://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git git fetch --no-tags ardb arm64-compat-alignment-fixups git checkout 16de979d9372710aaa42cd93d3af1e9a43d53369 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arm64 SHELL=/bin/bash arch/arm64/kernel/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot sparse warnings: (new ones prefixed by >>) >> arch/arm64/kernel/compat_alignment.c:87:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const [noderef] __user *addr @@ got void * @@ arch/arm64/kernel/compat_alignment.c:87:25: sparse: expected void const [noderef] __user *addr arch/arm64/kernel/compat_alignment.c:87:25: sparse: got void * >> arch/arm64/kernel/compat_alignment.c:104:21: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned long long [noderef] __user *__p @@ got unsigned long long [usertype] * @@ arch/arm64/kernel/compat_alignment.c:104:21: sparse: expected unsigned long long [noderef] __user *__p arch/arm64/kernel/compat_alignment.c:104:21: sparse: got unsigned long long [usertype] * arch/arm64/kernel/compat_alignment.c:114:21: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned long long [noderef] __user *__p @@ got unsigned long long [usertype] * @@ arch/arm64/kernel/compat_alignment.c:114:21: sparse: expected unsigned long long [noderef] __user *__p arch/arm64/kernel/compat_alignment.c:114:21: sparse: got unsigned long long [usertype] * arch/arm64/kernel/compat_alignment.c:149:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const [noderef] __user *addr @@ got void * @@ arch/arm64/kernel/compat_alignment.c:149:25: sparse: expected void const [noderef] __user *addr arch/arm64/kernel/compat_alignment.c:149:25: sparse: got void * >> arch/arm64/kernel/compat_alignment.c:168:37: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned int [noderef] __user *__p @@ got unsigned int [usertype] * @@ arch/arm64/kernel/compat_alignment.c:168:37: sparse: expected unsigned int [noderef] __user *__p arch/arm64/kernel/compat_alignment.c:168:37: sparse: got unsigned int [usertype] * arch/arm64/kernel/compat_alignment.c:172:37: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned int [noderef] __user *__p @@ got unsigned int [usertype] * @@ arch/arm64/kernel/compat_alignment.c:172:37: sparse: expected unsigned int [noderef] __user *__p arch/arm64/kernel/compat_alignment.c:172:37: sparse: got unsigned int [usertype] * >> arch/arm64/kernel/compat_alignment.c:370:17: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned int [noderef] __user *__p @@ got unsigned int [usertype] *ip @@ arch/arm64/kernel/compat_alignment.c:370:17: sparse: expected unsigned int [noderef] __user *__p arch/arm64/kernel/compat_alignment.c:370:17: sparse: got unsigned int [usertype] *ip >> arch/arm64/kernel/compat_alignment.c:374:17: sparse: sparse: cast to restricted __le32 >> arch/arm64/kernel/compat_alignment.c:374:17: sparse: sparse: cast to restricted __le32 >> arch/arm64/kernel/compat_alignment.c:374:17: sparse: sparse: cast to restricted __le32 >> arch/arm64/kernel/compat_alignment.c:374:17: sparse: sparse: cast to restricted __le32 >> arch/arm64/kernel/compat_alignment.c:374:17: sparse: sparse: cast to restricted __le32 >> arch/arm64/kernel/compat_alignment.c:374:17: sparse: sparse: cast to restricted __le32 >> arch/arm64/kernel/compat_alignment.c:383:17: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned short [noderef] __user *__p @@ got unsigned short [usertype] *ip @@ arch/arm64/kernel/compat_alignment.c:383:17: sparse: expected unsigned short [noderef] __user *__p arch/arm64/kernel/compat_alignment.c:383:17: sparse: got unsigned short [usertype] *ip >> arch/arm64/kernel/compat_alignment.c:387:17: sparse: sparse: cast to restricted __le16 >> arch/arm64/kernel/compat_alignment.c:387:17: sparse: sparse: cast to restricted __le16 >> arch/arm64/kernel/compat_alignment.c:387:17: sparse: sparse: cast to restricted __le16 >> arch/arm64/kernel/compat_alignment.c:387:17: sparse: sparse: cast to restricted __le16 vim +87 arch/arm64/kernel/compat_alignment.c 79 80 static int 81 do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs) 82 { 83 unsigned int rd = RD_BITS(instr); 84 unsigned int rd2; 85 int load; 86 > 87 if (!access_ok((void *)addr, sizeof(u64))) 88 return TYPE_FAULT; 89 90 if ((instr & 0xfe000000) == 0xe8000000) { 91 /* ARMv7 Thumb-2 32-bit LDRD/STRD */ 92 rd2 = (instr >> 8) & 0xf; 93 load = !!(LDST_L_BIT(instr)); 94 } else if (((rd & 1) == 1) || (rd == 14)) 95 goto bad; 96 else { 97 load = ((instr & 0xf0) == 0xd0); 98 rd2 = rd + 1; 99 } 100 101 if (load) { 102 unsigned long val; 103 > 104 if (get_user(val, (u64 *)addr)) 105 return TYPE_FAULT; 106 107 // TODO endianness 108 regs->regs[rd] = lower_32_bits(val); 109 regs->regs[rd2] = upper_32_bits(val); 110 } else { 111 // TODO endianness 112 unsigned long val = (regs->regs[rd] & U32_MAX) | 113 (u32)(regs->regs[rd] << 32); 114 if (put_user(val, (u64 *)addr)) 115 return TYPE_FAULT; 116 } 117 118 return TYPE_LDST; 119 bad: 120 return TYPE_ERROR; 121 } 122 123 /* 124 * LDM/STM alignment handler. 125 * 126 * There are 4 variants of this instruction: 127 * 128 * B = rn pointer before instruction, A = rn pointer after instruction 129 * ------ increasing address -----> 130 * | | r0 | r1 | ... | rx | | 131 * PU = 01 B A 132 * PU = 11 B A 133 * PU = 00 A B 134 * PU = 10 A B 135 */ 136 static int 137 do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) 138 { 139 unsigned int rd, rn, correction, nr_regs, regbits; 140 unsigned long eaddr, newaddr; 141 unsigned int val; 142 143 correction = 4; /* processor implementation defined */ 144 regs->pc += correction; 145 146 /* count the number of registers in the mask to be transferred */ 147 nr_regs = hweight16(REGMASK_BITS(instr)) * 4; 148 149 if (!access_ok((void *)addr, nr_regs * sizeof(u32))) 150 return TYPE_FAULT; 151 152 rn = RN_BITS(instr); 153 newaddr = eaddr = regs->regs[rn]; 154 155 if (!LDST_U_BIT(instr)) 156 nr_regs = -nr_regs; 157 newaddr += nr_regs; 158 if (!LDST_U_BIT(instr)) 159 eaddr = newaddr; 160 161 if (LDST_P_EQ_U(instr)) /* U = P */ 162 eaddr += 4; 163 164 for (regbits = REGMASK_BITS(instr), rd = 0; regbits; 165 regbits >>= 1, rd += 1) 166 if (regbits & 1) { 167 if (LDST_L_BIT(instr)) { > 168 if (get_user(val, (u32 *)eaddr)) 169 goto fault; 170 regs->regs[rd] = val; 171 } else 172 if (put_user((u32)regs->regs[rd], (u32 *)eaddr)) 173 goto fault; 174 eaddr += 4; 175 } 176 177 if (LDST_W_BIT(instr)) 178 regs->regs[rn] = newaddr; 179 if (!LDST_L_BIT(instr) || !(REGMASK_BITS(instr) & (1 << 15))) 180 regs->pc -= correction; 181 return TYPE_DONE; 182 183 fault: 184 regs->pc -= correction; 185 return TYPE_FAULT; 186 } 187 -- 0-DAY CI Kernel Test Service https://01.org/lkp