Skip to content

Commit 2e97a0c

Browse files
committed
Merge tag 'x86_misc_for_v5.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull misc x86 updates from Borislav Petkov: "The pile which we cannot find the proper topic for so we stick it in x86/misc: - Add support for decoding instructions which do MMIO accesses in order to use it in SEV and TDX guests - An include fix and reorg to allow for removing set_fs in UML later" * tag 'x86_misc_for_v5.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mtrr: Remove the mtrr_bp_init() stub x86/sev-es: Use insn_decode_mmio() for MMIO implementation x86/insn-eval: Introduce insn_decode_mmio() x86/insn-eval: Introduce insn_get_modrm_reg_ptr() x86/insn-eval: Handle insn_get_opcode() failure
2 parents 4a692ae + 4d5cff6 commit 2e97a0c

File tree

6 files changed

+169
-141
lines changed

6 files changed

+169
-141
lines changed

arch/x86/include/asm/insn-eval.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ bool insn_has_rep_prefix(struct insn *insn);
1919
void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs);
2020
int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs);
2121
int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs);
22+
unsigned long *insn_get_modrm_reg_ptr(struct insn *insn, struct pt_regs *regs);
2223
unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx);
2324
int insn_get_code_seg_params(struct pt_regs *regs);
2425
int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip);
@@ -29,4 +30,16 @@ int insn_fetch_from_user_inatomic(struct pt_regs *regs,
2930
bool insn_decode_from_regs(struct insn *insn, struct pt_regs *regs,
3031
unsigned char buf[MAX_INSN_SIZE], int buf_size);
3132

33+
enum mmio_type {
34+
MMIO_DECODE_FAILED,
35+
MMIO_WRITE,
36+
MMIO_WRITE_IMM,
37+
MMIO_READ,
38+
MMIO_READ_ZERO_EXTEND,
39+
MMIO_READ_SIGN_EXTEND,
40+
MMIO_MOVS,
41+
};
42+
43+
enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes);
44+
3245
#endif /* _ASM_X86_INSN_EVAL_H */

arch/x86/include/asm/mtrr.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
#define _ASM_X86_MTRR_H
2525

2626
#include <uapi/asm/mtrr.h>
27-
#include <asm/memtype.h>
2827

28+
void mtrr_bp_init(void);
2929

3030
/*
3131
* The following functions are for use by other drivers that cannot use
@@ -43,7 +43,6 @@ extern int mtrr_del(int reg, unsigned long base, unsigned long size);
4343
extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
4444
extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
4545
extern void mtrr_ap_init(void);
46-
extern void mtrr_bp_init(void);
4746
extern void set_mtrr_aps_delayed_init(void);
4847
extern void mtrr_aps_init(void);
4948
extern void mtrr_bp_restore(void);
@@ -84,11 +83,6 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
8483
static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
8584
{
8685
}
87-
static inline void mtrr_bp_init(void)
88-
{
89-
pat_disable("PAT support disabled because CONFIG_MTRR is disabled in the kernel.");
90-
}
91-
9286
#define mtrr_ap_init() do {} while (0)
9387
#define set_mtrr_aps_delayed_init() do {} while (0)
9488
#define mtrr_aps_init() do {} while (0)

arch/x86/kernel/setup.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <asm/kasan.h>
4141
#include <asm/kaslr.h>
4242
#include <asm/mce.h>
43+
#include <asm/memtype.h>
4344
#include <asm/mtrr.h>
4445
#include <asm/realmode.h>
4546
#include <asm/olpc_ofw.h>
@@ -967,7 +968,11 @@ void __init setup_arch(char **cmdline_p)
967968
max_pfn = e820__end_of_ram_pfn();
968969

969970
/* update e820 for memory not covered by WB MTRRs */
970-
mtrr_bp_init();
971+
if (IS_ENABLED(CONFIG_MTRR))
972+
mtrr_bp_init();
973+
else
974+
pat_disable("PAT support disabled because CONFIG_MTRR is disabled in the kernel.");
975+
971976
if (mtrr_trim_uncached_memory(max_pfn))
972977
max_pfn = e820__end_of_ram_pfn();
973978

arch/x86/kernel/sev.c

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

795-
static long *vc_insn_get_reg(struct es_em_ctxt *ctxt)
796-
{
797-
long *reg_array;
798-
int offset;
799-
800-
reg_array = (long *)ctxt->regs;
801-
offset = insn_get_modrm_reg_off(&ctxt->insn, ctxt->regs);
802-
803-
if (offset < 0)
804-
return NULL;
805-
806-
offset /= sizeof(long);
807-
808-
return reg_array + offset;
809-
}
810-
811795
static long *vc_insn_get_rm(struct es_em_ctxt *ctxt)
812796
{
813797
long *reg_array;
@@ -855,76 +839,6 @@ static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
855839
return sev_es_ghcb_hv_call(ghcb, true, ctxt, exit_code, exit_info_1, exit_info_2);
856840
}
857841

858-
static enum es_result vc_handle_mmio_twobyte_ops(struct ghcb *ghcb,
859-
struct es_em_ctxt *ctxt)
860-
{
861-
struct insn *insn = &ctxt->insn;
862-
unsigned int bytes = 0;
863-
enum es_result ret;
864-
int sign_byte;
865-
long *reg_data;
866-
867-
switch (insn->opcode.bytes[1]) {
868-
/* MMIO Read w/ zero-extension */
869-
case 0xb6:
870-
bytes = 1;
871-
fallthrough;
872-
case 0xb7:
873-
if (!bytes)
874-
bytes = 2;
875-
876-
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
877-
if (ret)
878-
break;
879-
880-
/* Zero extend based on operand size */
881-
reg_data = vc_insn_get_reg(ctxt);
882-
if (!reg_data)
883-
return ES_DECODE_FAILED;
884-
885-
memset(reg_data, 0, insn->opnd_bytes);
886-
887-
memcpy(reg_data, ghcb->shared_buffer, bytes);
888-
break;
889-
890-
/* MMIO Read w/ sign-extension */
891-
case 0xbe:
892-
bytes = 1;
893-
fallthrough;
894-
case 0xbf:
895-
if (!bytes)
896-
bytes = 2;
897-
898-
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
899-
if (ret)
900-
break;
901-
902-
/* Sign extend based on operand size */
903-
reg_data = vc_insn_get_reg(ctxt);
904-
if (!reg_data)
905-
return ES_DECODE_FAILED;
906-
907-
if (bytes == 1) {
908-
u8 *val = (u8 *)ghcb->shared_buffer;
909-
910-
sign_byte = (*val & 0x80) ? 0xff : 0x00;
911-
} else {
912-
u16 *val = (u16 *)ghcb->shared_buffer;
913-
914-
sign_byte = (*val & 0x8000) ? 0xff : 0x00;
915-
}
916-
memset(reg_data, sign_byte, insn->opnd_bytes);
917-
918-
memcpy(reg_data, ghcb->shared_buffer, bytes);
919-
break;
920-
921-
default:
922-
ret = ES_UNSUPPORTED;
923-
}
924-
925-
return ret;
926-
}
927-
928842
/*
929843
* The MOVS instruction has two memory operands, which raises the
930844
* problem that it is not known whether the access to the source or the
@@ -992,83 +906,79 @@ static enum es_result vc_handle_mmio_movs(struct es_em_ctxt *ctxt,
992906
return ES_RETRY;
993907
}
994908

995-
static enum es_result vc_handle_mmio(struct ghcb *ghcb,
996-
struct es_em_ctxt *ctxt)
909+
static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
997910
{
998911
struct insn *insn = &ctxt->insn;
999912
unsigned int bytes = 0;
913+
enum mmio_type mmio;
1000914
enum es_result ret;
915+
u8 sign_byte;
1001916
long *reg_data;
1002917

1003-
switch (insn->opcode.bytes[0]) {
1004-
/* MMIO Write */
1005-
case 0x88:
1006-
bytes = 1;
1007-
fallthrough;
1008-
case 0x89:
1009-
if (!bytes)
1010-
bytes = insn->opnd_bytes;
918+
mmio = insn_decode_mmio(insn, &bytes);
919+
if (mmio == MMIO_DECODE_FAILED)
920+
return ES_DECODE_FAILED;
1011921

1012-
reg_data = vc_insn_get_reg(ctxt);
922+
if (mmio != MMIO_WRITE_IMM && mmio != MMIO_MOVS) {
923+
reg_data = insn_get_modrm_reg_ptr(insn, ctxt->regs);
1013924
if (!reg_data)
1014925
return ES_DECODE_FAILED;
926+
}
1015927

928+
switch (mmio) {
929+
case MMIO_WRITE:
1016930
memcpy(ghcb->shared_buffer, reg_data, bytes);
1017-
1018931
ret = vc_do_mmio(ghcb, ctxt, bytes, false);
1019932
break;
1020-
1021-
case 0xc6:
1022-
bytes = 1;
1023-
fallthrough;
1024-
case 0xc7:
1025-
if (!bytes)
1026-
bytes = insn->opnd_bytes;
1027-
933+
case MMIO_WRITE_IMM:
1028934
memcpy(ghcb->shared_buffer, insn->immediate1.bytes, bytes);
1029-
1030935
ret = vc_do_mmio(ghcb, ctxt, bytes, false);
1031936
break;
1032-
1033-
/* MMIO Read */
1034-
case 0x8a:
1035-
bytes = 1;
1036-
fallthrough;
1037-
case 0x8b:
1038-
if (!bytes)
1039-
bytes = insn->opnd_bytes;
1040-
937+
case MMIO_READ:
1041938
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
1042939
if (ret)
1043940
break;
1044941

1045-
reg_data = vc_insn_get_reg(ctxt);
1046-
if (!reg_data)
1047-
return ES_DECODE_FAILED;
1048-
1049942
/* Zero-extend for 32-bit operation */
1050943
if (bytes == 4)
1051944
*reg_data = 0;
1052945

1053946
memcpy(reg_data, ghcb->shared_buffer, bytes);
1054947
break;
948+
case MMIO_READ_ZERO_EXTEND:
949+
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
950+
if (ret)
951+
break;
952+
953+
/* Zero extend based on operand size */
954+
memset(reg_data, 0, insn->opnd_bytes);
955+
memcpy(reg_data, ghcb->shared_buffer, bytes);
956+
break;
957+
case MMIO_READ_SIGN_EXTEND:
958+
ret = vc_do_mmio(ghcb, ctxt, bytes, true);
959+
if (ret)
960+
break;
1055961

1056-
/* MOVS instruction */
1057-
case 0xa4:
1058-
bytes = 1;
1059-
fallthrough;
1060-
case 0xa5:
1061-
if (!bytes)
1062-
bytes = insn->opnd_bytes;
962+
if (bytes == 1) {
963+
u8 *val = (u8 *)ghcb->shared_buffer;
1063964

1064-
ret = vc_handle_mmio_movs(ctxt, bytes);
965+
sign_byte = (*val & 0x80) ? 0xff : 0x00;
966+
} else {
967+
u16 *val = (u16 *)ghcb->shared_buffer;
968+
969+
sign_byte = (*val & 0x8000) ? 0xff : 0x00;
970+
}
971+
972+
/* Sign extend based on operand size */
973+
memset(reg_data, sign_byte, insn->opnd_bytes);
974+
memcpy(reg_data, ghcb->shared_buffer, bytes);
1065975
break;
1066-
/* Two-Byte Opcodes */
1067-
case 0x0f:
1068-
ret = vc_handle_mmio_twobyte_ops(ghcb, ctxt);
976+
case MMIO_MOVS:
977+
ret = vc_handle_mmio_movs(ctxt, bytes);
1069978
break;
1070979
default:
1071980
ret = ES_UNSUPPORTED;
981+
break;
1072982
}
1073983

1074984
return ret;

arch/x86/kvm/mmu/spte.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "spte.h"
1717

1818
#include <asm/e820/api.h>
19+
#include <asm/memtype.h>
1920
#include <asm/vmx.h>
2021

2122
static bool __read_mostly enable_mmio_caching = true;

0 commit comments

Comments
 (0)