@@ -632,14 +632,36 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
632
632
sev_es_terminate (SEV_TERM_SET_GEN , GHCB_SEV_ES_GEN_REQ );
633
633
}
634
634
635
+ static enum es_result vc_insn_string_check (struct es_em_ctxt * ctxt ,
636
+ unsigned long address ,
637
+ bool write )
638
+ {
639
+ if (user_mode (ctxt -> regs ) && fault_in_kernel_space (address )) {
640
+ ctxt -> fi .vector = X86_TRAP_PF ;
641
+ ctxt -> fi .error_code = X86_PF_USER ;
642
+ ctxt -> fi .cr2 = address ;
643
+ if (write )
644
+ ctxt -> fi .error_code |= X86_PF_WRITE ;
645
+
646
+ return ES_EXCEPTION ;
647
+ }
648
+
649
+ return ES_OK ;
650
+ }
651
+
635
652
static enum es_result vc_insn_string_read (struct es_em_ctxt * ctxt ,
636
653
void * src , char * buf ,
637
654
unsigned int data_size ,
638
655
unsigned int count ,
639
656
bool backwards )
640
657
{
641
658
int i , b = backwards ? -1 : 1 ;
642
- enum es_result ret = ES_OK ;
659
+ unsigned long address = (unsigned long )src ;
660
+ enum es_result ret ;
661
+
662
+ ret = vc_insn_string_check (ctxt , address , false);
663
+ if (ret != ES_OK )
664
+ return ret ;
643
665
644
666
for (i = 0 ; i < count ; i ++ ) {
645
667
void * s = src + (i * data_size * b );
@@ -660,7 +682,12 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
660
682
bool backwards )
661
683
{
662
684
int i , s = backwards ? -1 : 1 ;
663
- enum es_result ret = ES_OK ;
685
+ unsigned long address = (unsigned long )dst ;
686
+ enum es_result ret ;
687
+
688
+ ret = vc_insn_string_check (ctxt , address , true);
689
+ if (ret != ES_OK )
690
+ return ret ;
664
691
665
692
for (i = 0 ; i < count ; i ++ ) {
666
693
void * d = dst + (i * data_size * s );
@@ -696,6 +723,9 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
696
723
static enum es_result vc_ioio_exitinfo (struct es_em_ctxt * ctxt , u64 * exitinfo )
697
724
{
698
725
struct insn * insn = & ctxt -> insn ;
726
+ size_t size ;
727
+ u64 port ;
728
+
699
729
* exitinfo = 0 ;
700
730
701
731
switch (insn -> opcode .bytes [0 ]) {
@@ -704,49 +734,51 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
704
734
case 0x6d :
705
735
* exitinfo |= IOIO_TYPE_INS ;
706
736
* exitinfo |= IOIO_SEG_ES ;
707
- * exitinfo |= ( ctxt -> regs -> dx & 0xffff ) << 16 ;
737
+ port = ctxt -> regs -> dx & 0xffff ;
708
738
break ;
709
739
710
740
/* OUTS opcodes */
711
741
case 0x6e :
712
742
case 0x6f :
713
743
* exitinfo |= IOIO_TYPE_OUTS ;
714
744
* exitinfo |= IOIO_SEG_DS ;
715
- * exitinfo |= ( ctxt -> regs -> dx & 0xffff ) << 16 ;
745
+ port = ctxt -> regs -> dx & 0xffff ;
716
746
break ;
717
747
718
748
/* IN immediate opcodes */
719
749
case 0xe4 :
720
750
case 0xe5 :
721
751
* exitinfo |= IOIO_TYPE_IN ;
722
- * exitinfo | = (u8 )insn -> immediate .value << 16 ;
752
+ port = (u8 )insn -> immediate .value & 0xffff ;
723
753
break ;
724
754
725
755
/* OUT immediate opcodes */
726
756
case 0xe6 :
727
757
case 0xe7 :
728
758
* exitinfo |= IOIO_TYPE_OUT ;
729
- * exitinfo | = (u8 )insn -> immediate .value << 16 ;
759
+ port = (u8 )insn -> immediate .value & 0xffff ;
730
760
break ;
731
761
732
762
/* IN register opcodes */
733
763
case 0xec :
734
764
case 0xed :
735
765
* exitinfo |= IOIO_TYPE_IN ;
736
- * exitinfo |= ( ctxt -> regs -> dx & 0xffff ) << 16 ;
766
+ port = ctxt -> regs -> dx & 0xffff ;
737
767
break ;
738
768
739
769
/* OUT register opcodes */
740
770
case 0xee :
741
771
case 0xef :
742
772
* exitinfo |= IOIO_TYPE_OUT ;
743
- * exitinfo |= ( ctxt -> regs -> dx & 0xffff ) << 16 ;
773
+ port = ctxt -> regs -> dx & 0xffff ;
744
774
break ;
745
775
746
776
default :
747
777
return ES_DECODE_FAILED ;
748
778
}
749
779
780
+ * exitinfo |= port << 16 ;
781
+
750
782
switch (insn -> opcode .bytes [0 ]) {
751
783
case 0x6c :
752
784
case 0x6e :
@@ -756,12 +788,15 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
756
788
case 0xee :
757
789
/* Single byte opcodes */
758
790
* exitinfo |= IOIO_DATA_8 ;
791
+ size = 1 ;
759
792
break ;
760
793
default :
761
794
/* Length determined by instruction parsing */
762
795
* exitinfo |= (insn -> opnd_bytes == 2 ) ? IOIO_DATA_16
763
796
: IOIO_DATA_32 ;
797
+ size = (insn -> opnd_bytes == 2 ) ? 2 : 4 ;
764
798
}
799
+
765
800
switch (insn -> addr_bytes ) {
766
801
case 2 :
767
802
* exitinfo |= IOIO_ADDR_16 ;
@@ -777,7 +812,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
777
812
if (insn_has_rep_prefix (insn ))
778
813
* exitinfo |= IOIO_REP ;
779
814
780
- return ES_OK ;
815
+ return vc_ioio_check ( ctxt , ( u16 ) port , size ) ;
781
816
}
782
817
783
818
static enum es_result vc_handle_ioio (struct ghcb * ghcb , struct es_em_ctxt * ctxt )
0 commit comments