Skip to content

Commit c494eb3

Browse files
kirylhansendc
authored andcommitted
x86/sev-es: Use insn_decode_mmio() for MMIO implementation
Switch SEV implementation to insn_decode_mmio(). The helper is going to be used by TDX too. No functional changes. Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: Andi Kleen <[email protected]> Reviewed-by: Tony Luck <[email protected]> Tested-by: Joerg Roedel <[email protected]> Acked-by: Tom Lendacky <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 70a81f9 commit c494eb3

File tree

1 file changed

+41
-131
lines changed

1 file changed

+41
-131
lines changed

arch/x86/kernel/sev.c

Lines changed: 41 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -776,22 +776,6 @@ static void __init vc_early_forward_exception(struct es_em_ctxt *ctxt)
776776
do_early_exception(ctxt->regs, trapnr);
777777
}
778778

779-
static long *vc_insn_get_reg(struct es_em_ctxt *ctxt)
780-
{
781-
long *reg_array;
782-
int offset;
783-
784-
reg_array = (long *)ctxt->regs;
785-
offset = insn_get_modrm_reg_off(&ctxt->insn, ctxt->regs);
786-
787-
if (offset < 0)
788-
return NULL;
789-
790-
offset /= sizeof(long);
791-
792-
return reg_array + offset;
793-
}
794-
795779
static long *vc_insn_get_rm(struct es_em_ctxt *ctxt)
796780
{
797781
long *reg_array;
@@ -839,76 +823,6 @@ static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
839823
return sev_es_ghcb_hv_call(ghcb, true, ctxt, exit_code, exit_info_1, exit_info_2);
840824
}
841825

842-
static enum es_result vc_handle_mmio_twobyte_ops(struct ghcb *ghcb,
843-
struct es_em_ctxt *ctxt)
844-
{
845-
struct insn *insn = &ctxt->insn;
846-
unsigned int bytes = 0;
847-
enum es_result ret;
848-
int sign_byte;
849-
long *reg_data;
850-
851-
switch (insn->opcode.bytes[1]) {
852-
/* MMIO Read w/ zero-extension */
853-
case 0xb6:
854-
bytes = 1;
855-
fallthrough;
856-
case 0xb7:
857-
if (!bytes)
858-
bytes = 2;
859-
860-
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
861-
if (ret)
862-
break;
863-
864-
/* Zero extend based on operand size */
865-
reg_data = vc_insn_get_reg(ctxt);
866-
if (!reg_data)
867-
return ES_DECODE_FAILED;
868-
869-
memset(reg_data, 0, insn->opnd_bytes);
870-
871-
memcpy(reg_data, ghcb->shared_buffer, bytes);
872-
break;
873-
874-
/* MMIO Read w/ sign-extension */
875-
case 0xbe:
876-
bytes = 1;
877-
fallthrough;
878-
case 0xbf:
879-
if (!bytes)
880-
bytes = 2;
881-
882-
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
883-
if (ret)
884-
break;
885-
886-
/* Sign extend based on operand size */
887-
reg_data = vc_insn_get_reg(ctxt);
888-
if (!reg_data)
889-
return ES_DECODE_FAILED;
890-
891-
if (bytes == 1) {
892-
u8 *val = (u8 *)ghcb->shared_buffer;
893-
894-
sign_byte = (*val & 0x80) ? 0xff : 0x00;
895-
} else {
896-
u16 *val = (u16 *)ghcb->shared_buffer;
897-
898-
sign_byte = (*val & 0x8000) ? 0xff : 0x00;
899-
}
900-
memset(reg_data, sign_byte, insn->opnd_bytes);
901-
902-
memcpy(reg_data, ghcb->shared_buffer, bytes);
903-
break;
904-
905-
default:
906-
ret = ES_UNSUPPORTED;
907-
}
908-
909-
return ret;
910-
}
911-
912826
/*
913827
* The MOVS instruction has two memory operands, which raises the
914828
* problem that it is not known whether the access to the source or the
@@ -976,83 +890,79 @@ static enum es_result vc_handle_mmio_movs(struct es_em_ctxt *ctxt,
976890
return ES_RETRY;
977891
}
978892

979-
static enum es_result vc_handle_mmio(struct ghcb *ghcb,
980-
struct es_em_ctxt *ctxt)
893+
static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
981894
{
982895
struct insn *insn = &ctxt->insn;
983896
unsigned int bytes = 0;
897+
enum mmio_type mmio;
984898
enum es_result ret;
899+
u8 sign_byte;
985900
long *reg_data;
986901

987-
switch (insn->opcode.bytes[0]) {
988-
/* MMIO Write */
989-
case 0x88:
990-
bytes = 1;
991-
fallthrough;
992-
case 0x89:
993-
if (!bytes)
994-
bytes = insn->opnd_bytes;
902+
mmio = insn_decode_mmio(insn, &bytes);
903+
if (mmio == MMIO_DECODE_FAILED)
904+
return ES_DECODE_FAILED;
995905

996-
reg_data = vc_insn_get_reg(ctxt);
906+
if (mmio != MMIO_WRITE_IMM && mmio != MMIO_MOVS) {
907+
reg_data = insn_get_modrm_reg_ptr(insn, ctxt->regs);
997908
if (!reg_data)
998909
return ES_DECODE_FAILED;
910+
}
999911

912+
switch (mmio) {
913+
case MMIO_WRITE:
1000914
memcpy(ghcb->shared_buffer, reg_data, bytes);
1001-
1002915
ret = vc_do_mmio(ghcb, ctxt, bytes, false);
1003916
break;
1004-
1005-
case 0xc6:
1006-
bytes = 1;
1007-
fallthrough;
1008-
case 0xc7:
1009-
if (!bytes)
1010-
bytes = insn->opnd_bytes;
1011-
917+
case MMIO_WRITE_IMM:
1012918
memcpy(ghcb->shared_buffer, insn->immediate1.bytes, bytes);
1013-
1014919
ret = vc_do_mmio(ghcb, ctxt, bytes, false);
1015920
break;
1016-
1017-
/* MMIO Read */
1018-
case 0x8a:
1019-
bytes = 1;
1020-
fallthrough;
1021-
case 0x8b:
1022-
if (!bytes)
1023-
bytes = insn->opnd_bytes;
1024-
921+
case MMIO_READ:
1025922
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
1026923
if (ret)
1027924
break;
1028925

1029-
reg_data = vc_insn_get_reg(ctxt);
1030-
if (!reg_data)
1031-
return ES_DECODE_FAILED;
1032-
1033926
/* Zero-extend for 32-bit operation */
1034927
if (bytes == 4)
1035928
*reg_data = 0;
1036929

1037930
memcpy(reg_data, ghcb->shared_buffer, bytes);
1038931
break;
932+
case MMIO_READ_ZERO_EXTEND:
933+
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
934+
if (ret)
935+
break;
936+
937+
/* Zero extend based on operand size */
938+
memset(reg_data, 0, insn->opnd_bytes);
939+
memcpy(reg_data, ghcb->shared_buffer, bytes);
940+
break;
941+
case MMIO_READ_SIGN_EXTEND:
942+
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
943+
if (ret)
944+
break;
1039945

1040-
/* MOVS instruction */
1041-
case 0xa4:
1042-
bytes = 1;
1043-
fallthrough;
1044-
case 0xa5:
1045-
if (!bytes)
1046-
bytes = insn->opnd_bytes;
946+
if (bytes == 1) {
947+
u8 *val = (u8 *)ghcb->shared_buffer;
1047948

1048-
ret = vc_handle_mmio_movs(ctxt, bytes);
949+
sign_byte = (*val & 0x80) ? 0xff : 0x00;
950+
} else {
951+
u16 *val = (u16 *)ghcb->shared_buffer;
952+
953+
sign_byte = (*val & 0x8000) ? 0xff : 0x00;
954+
}
955+
956+
/* Sign extend based on operand size */
957+
memset(reg_data, sign_byte, insn->opnd_bytes);
958+
memcpy(reg_data, ghcb->shared_buffer, bytes);
1049959
break;
1050-
/* Two-Byte Opcodes */
1051-
case 0x0f:
1052-
ret = vc_handle_mmio_twobyte_ops(ghcb, ctxt);
960+
case MMIO_MOVS:
961+
ret = vc_handle_mmio_movs(ctxt, bytes);
1053962
break;
1054963
default:
1055964
ret = ES_UNSUPPORTED;
965+
break;
1056966
}
1057967

1058968
return ret;

0 commit comments

Comments
 (0)