Skip to content

Commit bdf561a

Browse files
committed
added dc zva to the alignment trap
1 parent 07faf3d commit bdf561a

1 file changed

Lines changed: 92 additions & 2 deletions

File tree

arch/arm64/kernel/compat_alignment.c

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ potentially also ldur q0, [x1, #32] and ldur q1, [x1, #48]
414414
*/
415415

416416
#include <linux/timekeeping.h>
417+
#include <generated/asm/sysreg-defs.h>
417418

418419
struct fixupDescription{
419420
void* addr;
@@ -756,6 +757,38 @@ __attribute__((always_inline)) inline int get_data(int size, uint8_t* data, void
756757
return r;
757758
}
758759

760+
int memset_io_user(uint64_t size, uint8_t c, void* addr){
761+
int r = 0;
762+
uint64_t pattern = c;
763+
pattern |= pattern << 8;
764+
pattern |= pattern << 16;
765+
pattern |= pattern << 32;
766+
uint64_t cnt = 0;
767+
while(cnt < size){
768+
if((uint64_t)(addr + cnt) % 8){
769+
if((r = put_user(c, (uint8_t __user*) addr))){
770+
printk("Failed to write data at 0x%px (%d)(base was 0x%px)\n", addr + cnt, r, addr);
771+
return r;
772+
}
773+
cnt++;
774+
} else if(size - cnt >= 8){
775+
if((r = put_user(pattern, (uint64_t __user*) addr))){
776+
printk("Failed to write data at 0x%px (%d)(base was 0x%px)\n", addr + cnt, r, addr);
777+
return r;
778+
}
779+
cnt += 8;
780+
} else{
781+
if((r = put_user(c, (uint8_t __user*) addr))){
782+
printk("Failed to write data at 0x%px (%d)(base was 0x%px)\n", addr + cnt, r, addr);
783+
return r;
784+
}
785+
cnt++;
786+
}
787+
788+
}
789+
return r;
790+
}
791+
759792
int do_ls_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
760793
int r;
761794
u64 data1[2] = {0,0};
@@ -1216,6 +1249,60 @@ __attribute__((always_inline)) inline int ls_fixup(u32 instr, struct pt_regs *re
12161249
return r;
12171250
}
12181251

1252+
__attribute__((always_inline)) inline int system_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
1253+
uint8_t op1;
1254+
uint8_t op2;
1255+
uint8_t CRn;
1256+
uint8_t CRm;
1257+
uint8_t Rt;
1258+
bool L;
1259+
int r = 0;
1260+
1261+
op1 = (instr >> 16) & 0x7;
1262+
op2 = (instr >> 5) & 0x7;
1263+
CRn = (instr >> 12) & 0xf;
1264+
CRm = (instr >> 8) & 0xf;
1265+
L = (instr >> 21) & 1;
1266+
Rt = instr & 0x1f;
1267+
1268+
if(!L){
1269+
// SYS
1270+
// proper decoding would be nicer here, but I don't expect to see too many system instructions
1271+
if((op1 == 0x3) && (op2 == 1) && (CRn = 0x7) && (CRm == 4)){
1272+
// dc zva
1273+
uint64_t dczid_el0 = read_sysreg_s(SYS_DCZID_EL0);
1274+
if(!((dczid_el0 >> DCZID_EL0_DZP_SHIFT) & 1)){
1275+
uint16_t blksize = 4 << (dczid_el0 & 0xf);
1276+
r = memset_io_user(blksize, 0, regs->user_regs.regs[Rt]);
1277+
arm64_skip_faulting_instruction(regs, 4);
1278+
return r;
1279+
} else {
1280+
printk("DC ZVA is not allowed!\n");
1281+
return 1;
1282+
}
1283+
}
1284+
}
1285+
1286+
printk("Unhandled system instruction. op1=0x%x op2=0x%x CRn=0x%x CRm=0x%x\n", op1, op2, CRn, CRm);
1287+
return 1;
1288+
}
1289+
1290+
__attribute__((always_inline)) inline int branch_except_system_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
1291+
uint8_t op0;
1292+
uint32_t op1;
1293+
uint8_t op2;
1294+
1295+
op0 = (instr >> 29) & 0x7;
1296+
op1 = (instr >> 5) & 0x1fffff;
1297+
op2 = instr & 0x1f;
1298+
1299+
if((op0 == 0x6) && (op1 & 0x1ec000) == 0x84000){
1300+
return system_fixup(instr, regs, desc);
1301+
}
1302+
printk("Unhandled Branch/Exception generating/System instruction. op0=0x%x op1=0x%x op2=0x%x\n", op0, op1, op2);
1303+
return 1;
1304+
}
1305+
12191306
uint32_t* seenCMDs;
12201307
size_t seenCMDCount = 0;
12211308
size_t seenCMDSize = 0;
@@ -1277,8 +1364,11 @@ int do_alignment_fixup(unsigned long addr, struct pt_regs *regs){
12771364
}
12781365

12791366
return r;
1280-
} else {
1281-
printk("Not handling instruction with op0 0x%x ",op0);
1367+
} else if((op0 & 0xe) == 0xa){
1368+
// System instructions, needed for dc zva
1369+
return branch_except_system_fixup(instr, regs, &desc);
1370+
}else {
1371+
printk("Not handling instruction with op0 0x%x (instruction is 0x%08x)",op0, instr);
12821372
}
12831373
return -1;
12841374
}

0 commit comments

Comments
 (0)