@@ -513,28 +513,47 @@ void read_simd_reg(int reg, u64 dst[2]){
513
513
kernel_neon_end ();
514
514
}
515
515
516
+
517
+ void write_simd_reg (int reg , u64 src [2 ]){
518
+
519
+ if (!may_use_simd ()){
520
+ printk ("may_use_simd returned false!\n" );
521
+ }
522
+ kernel_neon_begin ();
523
+ if (current -> thread .sve_state ){
524
+ printk ("SVE state is not NULL!\n" );
525
+ }
526
+
527
+ * ((u64 * )(& current -> thread .uw .fpsimd_state .vregs [reg ])) = src [0 ];
528
+ * (((u64 * )(& current -> thread .uw .fpsimd_state .vregs [reg ])) + 1 ) = src [1 ];
529
+
530
+ kernel_neon_end ();
531
+ }
532
+
516
533
int do_ls_fixup (u32 instr , struct pt_regs * regs , struct fixupDescription * desc ){
517
534
int r ;
518
- u64 data1 [2 ];
519
- u64 data2 [2 ];
535
+ u64 data1 [2 ] = { 0 , 0 } ;
536
+ u64 data2 [2 ] = { 0 , 0 } ;
520
537
521
538
// the reg indices have to always be valid, even if the reg isn't being used
522
- if (desc -> simd ){
523
- // At least currently, there aren't any simd instructions supported that use more than one data register
524
- //__uint128_t tmp;
525
-
526
- // probably better for performance to read both registers with one function to kernel_neon_* doesn't have to be called more than once
527
- read_simd_reg (desc -> reg1 , data1 );
528
- read_simd_reg (desc -> reg2 , data2 );
529
- //data1[0] = tmp;
530
- //data1[1] = *(((u64*)&tmp) + 1);
531
- ///printk("SIMD: storing 0x%llx %llx (%d bits) at 0x%px", data1[1], data1[0], desc->width, desc->addr);
532
- if (desc -> width < 128 ){
533
- return -1 ;
539
+ if (!desc -> load ){
540
+ if (desc -> simd ){
541
+ // At least currently, there aren't any simd instructions supported that use more than one data register
542
+ //__uint128_t tmp;
543
+
544
+ // probably better for performance to read both registers with one function to kernel_neon_* doesn't have to be called more than once
545
+ read_simd_reg (desc -> reg1 , data1 );
546
+ read_simd_reg (desc -> reg2 , data2 );
547
+ //data1[0] = tmp;
548
+ //data1[1] = *(((u64*)&tmp) + 1);
549
+ ///printk("SIMD: storing 0x%llx %llx (%d bits) at 0x%px", data1[1], data1[0], desc->width, desc->addr);
550
+ /*if(desc->width < 128){
551
+ return -1;
552
+ }*/
553
+ } else {
554
+ data1 [0 ] = regs -> regs [desc -> reg1 ];
555
+ data2 [0 ] = regs -> regs [desc -> reg2 ];
534
556
}
535
- } else {
536
- data1 [0 ] = regs -> regs [desc -> reg1 ];
537
- data2 [0 ] = regs -> regs [desc -> reg2 ];
538
557
}
539
558
540
559
/*if(desc->width > 64){
@@ -571,8 +590,54 @@ int do_ls_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
571
590
}
572
591
arm64_skip_faulting_instruction (regs , 4 );
573
592
} else {
574
- printk ("Loading is currently not implemented (addr 0x%px)\n" , desc -> addr );
575
- return -1 ;
593
+ //printk("Loading is currently not implemented (addr 0x%px)\n", desc->addr);
594
+
595
+ uint8_t * addr = desc -> addr ;
596
+ int bcount = desc -> width / 8 ; // since the field stores the width in bits. Honestly, there's no particular reason for that
597
+
598
+ //printk("Storing %d bytes (pair: %d) to 0x%llx",bcount, desc->pair, desc->addr);
599
+ int addrIt = 0 ;
600
+ for (int i = 0 ; i < bcount ; i ++ ){
601
+ uint8_t val ;
602
+ if ((r = get_user ( val , (uint8_t __user * )addr ))){
603
+ printk ("Failed to write data at 0x%px (base was 0x%px)\n" , addr , desc -> addr );
604
+ return r ;
605
+ }
606
+ * (((uint8_t * )data1 ) + addrIt ) = val ;
607
+ //desc->data1 >>= 8;
608
+ addrIt ++ ;
609
+ addr ++ ;
610
+ }
611
+
612
+ if (desc -> simd ){
613
+ write_simd_reg (desc -> reg1 , data1 );
614
+ } else {
615
+ regs -> regs [desc -> reg1 ] = data1 [0 ];
616
+ }
617
+
618
+ addrIt = 0 ;
619
+ if (desc -> pair ){
620
+ for (int i = 0 ; i < bcount ; i ++ ){
621
+ uint8_t val ;
622
+ if ((r = get_user (val , (uint8_t __user * )addr ))){
623
+ printk ("Failed to write data at 0x%px (base was 0x%px)\n" , addr , desc -> addr );
624
+ return r ;
625
+ }
626
+ * (((uint8_t * )data2 ) + addrIt ) = val ;
627
+ //desc->data2 >>= 8;
628
+ addrIt ++ ;
629
+ addr ++ ;
630
+ }
631
+
632
+ if (desc -> simd ){
633
+ write_simd_reg (desc -> reg2 , data1 );
634
+ } else {
635
+ regs -> regs [desc -> reg2 ] = data1 [0 ];
636
+ }
637
+ }
638
+ arm64_skip_faulting_instruction (regs , 4 );
639
+
640
+
576
641
}
577
642
return 0 ;
578
643
}
@@ -732,7 +797,7 @@ int ls_reg_unsigned_imm(u32 instr, struct pt_regs *regs, struct fixupDescription
732
797
if ((size & 1 ) && simd && (opc & 2 )){
733
798
return 1 ;
734
799
}
735
-
800
+ desc -> load = load ;
736
801
desc -> reg1 = Rt ;
737
802
desc -> simd = simd ;
738
803
desc -> extendSign = extend_sign ;
@@ -848,9 +913,10 @@ int lsr_unscaled_immediate_fixup(u32 instr, struct pt_regs *regs, struct fixupDe
848
913
desc -> pair = 0 ;
849
914
850
915
int load = opc & 1 ;
851
- if (load ){
916
+ desc -> load = load ;
917
+ /*if(load){
852
918
return 1;
853
- }
919
+ }*/
854
920
desc -> reg1 = Rt ;
855
921
if (simd ){
856
922
desc -> simd = 1 ;
@@ -861,6 +927,10 @@ int lsr_unscaled_immediate_fixup(u32 instr, struct pt_regs *regs, struct fixupDe
861
927
desc->data1 = tmp;
862
928
desc->data1_simd = *(((u64*)&tmp) + 1);*/
863
929
return do_ls_fixup (instr , regs , desc );
930
+ } else {
931
+ desc -> simd = 0 ;
932
+ desc -> width = 8 << size ;
933
+ return do_ls_fixup (instr , regs , desc );
864
934
}
865
935
///printk("SIMD: %d\n", simd);
866
936
return 1 ;
0 commit comments