Skip to content

Commit 43969b6

Browse files
Coreforgegeerlingguy
authored andcommitted
some SIMD stuff for unity (not quite enough yet)
1 parent e835b94 commit 43969b6

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

arch/arm64/kernel/compat_alignment.c

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <asm/ptrace.h>
1313
#include <asm/traps.h>
1414

15+
#include <asm/fpsimd.h>
16+
1517
/*
1618
* 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
1719
*
@@ -399,14 +401,18 @@ int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs)
399401
*
400402
*[ 555.449674] Load/Store: op0 0x3 op1 0x1 op2 0x1 op3 0x3 op4 0x0
401403
[ 555.449677] Faulting instruction: 0x3c830021
404+
405+
stur q1, [x1, #16]
406+
potentially also ldur q0, [x1, #32] and ldur q1, [x1, #48]
402407
*
403408
*
404409
*
405410
*/
406411

407412
struct fixupDescription{
408413
void* addr;
409-
//
414+
415+
// datax_simd has to be located directly after datax in memory
410416
u64 data1;
411417
u64 data1_simd;
412418
u64 data2;
@@ -474,24 +480,40 @@ static int alignment_get_arm64(struct pt_regs *regs, __le64 __user *ip, u32 *ins
474480
return 0;
475481
}*/
476482

483+
// saves the contents of the simd register reg to dst
484+
void read_simd_reg(int reg, __uint128_t* dst){
485+
struct user_fpsimd_state st;
486+
fpsimd_save_state(&st);
487+
*dst = st.vregs[reg];
488+
}
489+
477490
int do_ls_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
478491
int r;
492+
/*if(desc->width > 64){
493+
printk("Currently cannot process ls_fixup with a size of %d bits\n", desc->width);
494+
return 1;
495+
}*/
479496
if(!desc->load){
480497
uint8_t* addr = desc->addr;
481498
int bcount = desc->width / 8; // since the field stores the width in bits. Honestly, there's no particular reason for that
499+
482500
//printk("Storing %d bytes (pair: %d) to 0x%llx",bcount, desc->pair, desc->addr);
501+
int addrIt = 0;
483502
for(int i = 0; i < bcount; i++){
484-
if((r=put_user(desc->data1 & 0xff, (uint8_t __user *)addr)))
503+
if((r=put_user( (*(((uint8_t*)(&desc->data1)) + addrIt) & 0xff), (uint8_t __user *)addr)))
485504
return r;
486-
desc->data1 >>= 8;
505+
//desc->data1 >>= 8;
506+
addrIt++;
487507
addr++;
488508
}
489509

510+
addrIt = 0;
490511
if(desc->pair){
491512
for(int i = 0; i < bcount; i++){
492-
if((r=put_user(desc->data2 & 0xff, (uint8_t __user *)addr)))
513+
if((r=put_user((*(((uint8_t*)(&desc->data2)) + addrIt) & 0xff) & 0xff, (uint8_t __user *)addr)))
493514
return r;
494-
desc->data2 >>= 8;
515+
//desc->data2 >>= 8;
516+
addrIt++;
495517
addr++;
496518
}
497519
}
@@ -722,6 +744,43 @@ int lsr_offset_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* d
722744
return 0;
723745
}
724746

747+
int lsr_unscaled_immediate_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
748+
uint8_t size = (instr >> 30) & 3;
749+
uint8_t simd = (instr >> 26) & 1;
750+
uint8_t opc = (instr >> 22) & 3;
751+
uint16_t imm9 = (instr >> 12) & 0x1ff;
752+
uint8_t Rn = (instr >> 5) & 0x1f;
753+
uint8_t Rt = instr & 0x1f;
754+
755+
int16_t fullImm = 0;
756+
// sign extend it
757+
if(imm9 & 0x100){
758+
fullImm = 0xfe00 | imm9;
759+
} else {
760+
fullImm = imm9;
761+
}
762+
u64 addr = regs->regs[Rn];
763+
desc->addr = addr + fullImm;
764+
desc->pair = 0;
765+
766+
int load = opc & 1;
767+
if(load){
768+
return 1;
769+
}
770+
if(simd){
771+
desc->simd = 1;
772+
desc->width = 8 << (size | (opc << 1));
773+
// assuming store
774+
__uint128_t tmp;
775+
read_simd_reg(Rt, &tmp);
776+
desc->data1 = tmp;
777+
desc->data1_simd = *(((u64*)&tmp) + 1);
778+
return do_ls_fixup(instr, regs, desc);
779+
}
780+
printk("SIMD: %d\n", simd);
781+
return 1;
782+
}
783+
725784
int ls_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
726785
uint8_t op0;
727786
uint8_t op1;
@@ -759,6 +818,16 @@ int ls_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
759818
// register offset load/store
760819
r = lsr_offset_fixup(instr, regs, desc);
761820
}
821+
if((op0 & 3) == 3 && (op2 & 2) == 0 && (op3 & 0x20) == 0x0 && op4 == 0){
822+
// register load/store unscaled immediate
823+
r = lsr_unscaled_immediate_fixup(instr, regs, desc);
824+
printk("Likely SIMD stuff, which isn't being handled properly at all!\n");
825+
if(r){
826+
arm64_skip_faulting_instruction(regs, 4);
827+
// skip anyways
828+
}
829+
//r = 0;
830+
}
762831
if(r){
763832
printk("Load/Store: op0 0x%x op1 0x%x op2 0x%x op3 0x%x op4 0x%x\n", op0, op1, op2, op3, op4);
764833
}

arch/arm64/mm/fault.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,9 +726,10 @@ static int do_alignment_fault(unsigned long far, unsigned long esr,
726726

727727
if(user_mode(regs)){
728728
// aarch64 user mode
729-
if(!do_alignment_fixup(far, regs)){
729+
if(do_alignment_fixup(far, regs) == 0){
730730
return 0;
731731
}
732+
printk("Unfixed alignment issue\n");
732733
}
733734
do_bad_area(far, esr, regs);
734735
return 0;

0 commit comments

Comments
 (0)