@@ -513,28 +513,47 @@ void read_simd_reg(int reg, u64 dst[2]){
513513 kernel_neon_end ();
514514}
515515
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+
516533int do_ls_fixup (u32 instr , struct pt_regs * regs , struct fixupDescription * desc ){
517534 int r ;
518- u64 data1 [2 ];
519- u64 data2 [2 ];
535+ u64 data1 [2 ] = { 0 , 0 } ;
536+ u64 data2 [2 ] = { 0 , 0 } ;
520537
521538 // 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 ];
534556 }
535- } else {
536- data1 [0 ] = regs -> regs [desc -> reg1 ];
537- data2 [0 ] = regs -> regs [desc -> reg2 ];
538557 }
539558
540559 /*if(desc->width > 64){
@@ -571,8 +590,54 @@ int do_ls_fixup(u32 instr, struct pt_regs *regs, struct fixupDescription* desc){
571590 }
572591 arm64_skip_faulting_instruction (regs , 4 );
573592 } 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+
576641 }
577642 return 0 ;
578643}
@@ -732,7 +797,7 @@ int ls_reg_unsigned_imm(u32 instr, struct pt_regs *regs, struct fixupDescription
732797 if ((size & 1 ) && simd && (opc & 2 )){
733798 return 1 ;
734799 }
735-
800+ desc -> load = load ;
736801 desc -> reg1 = Rt ;
737802 desc -> simd = simd ;
738803 desc -> extendSign = extend_sign ;
@@ -848,9 +913,10 @@ int lsr_unscaled_immediate_fixup(u32 instr, struct pt_regs *regs, struct fixupDe
848913 desc -> pair = 0 ;
849914
850915 int load = opc & 1 ;
851- if (load ){
916+ desc -> load = load ;
917+ /*if(load){
852918 return 1;
853- }
919+ }*/
854920 desc -> reg1 = Rt ;
855921 if (simd ){
856922 desc -> simd = 1 ;
@@ -861,6 +927,10 @@ int lsr_unscaled_immediate_fixup(u32 instr, struct pt_regs *regs, struct fixupDe
861927 desc->data1 = tmp;
862928 desc->data1_simd = *(((u64*)&tmp) + 1);*/
863929 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 );
864934 }
865935 ///printk("SIMD: %d\n", simd);
866936 return 1 ;
0 commit comments