|
10 | 10 | */ |
11 | 11 |
|
12 | 12 | #ifndef __BOOT_COMPRESSED |
13 | | -#define error(v) pr_err(v) |
14 | | -#define has_cpuflag(f) boot_cpu_has(f) |
| 13 | +#define error(v) pr_err(v) |
| 14 | +#define has_cpuflag(f) boot_cpu_has(f) |
| 15 | +#define sev_printk(fmt, ...) printk(fmt, ##__VA_ARGS__) |
| 16 | +#define sev_printk_rtl(fmt, ...) printk_ratelimited(fmt, ##__VA_ARGS__) |
| 17 | +#else |
| 18 | +#define sev_printk(fmt, ...) |
| 19 | +#define sev_printk_rtl(fmt, ...) |
15 | 20 | #endif |
16 | 21 |
|
17 | 22 | /* I/O parameters for CPUID-related helpers */ |
@@ -531,13 +536,18 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code) |
531 | 536 | { |
532 | 537 | unsigned int subfn = lower_bits(regs->cx, 32); |
533 | 538 | unsigned int fn = lower_bits(regs->ax, 32); |
| 539 | + u16 opcode = *(unsigned short *)regs->ip; |
534 | 540 | struct cpuid_leaf leaf; |
535 | 541 | int ret; |
536 | 542 |
|
537 | 543 | /* Only CPUID is supported via MSR protocol */ |
538 | 544 | if (exit_code != SVM_EXIT_CPUID) |
539 | 545 | goto fail; |
540 | 546 |
|
| 547 | + /* Is it really a CPUID insn? */ |
| 548 | + if (opcode != 0xa20f) |
| 549 | + goto fail; |
| 550 | + |
541 | 551 | leaf.fn = fn; |
542 | 552 | leaf.subfn = subfn; |
543 | 553 |
|
@@ -991,3 +1001,92 @@ static void __init setup_cpuid_table(const struct cc_blob_sev_info *cc_info) |
991 | 1001 | cpuid_ext_range_max = fn->eax; |
992 | 1002 | } |
993 | 1003 | } |
| 1004 | + |
| 1005 | +static enum es_result vc_check_opcode_bytes(struct es_em_ctxt *ctxt, |
| 1006 | + unsigned long exit_code) |
| 1007 | +{ |
| 1008 | + unsigned int opcode = (unsigned int)ctxt->insn.opcode.value; |
| 1009 | + u8 modrm = ctxt->insn.modrm.value; |
| 1010 | + |
| 1011 | + switch (exit_code) { |
| 1012 | + |
| 1013 | + case SVM_EXIT_IOIO: |
| 1014 | + case SVM_EXIT_NPF: |
| 1015 | + /* handled separately */ |
| 1016 | + return ES_OK; |
| 1017 | + |
| 1018 | + case SVM_EXIT_CPUID: |
| 1019 | + if (opcode == 0xa20f) |
| 1020 | + return ES_OK; |
| 1021 | + break; |
| 1022 | + |
| 1023 | + case SVM_EXIT_INVD: |
| 1024 | + if (opcode == 0x080f) |
| 1025 | + return ES_OK; |
| 1026 | + break; |
| 1027 | + |
| 1028 | + case SVM_EXIT_MONITOR: |
| 1029 | + if (opcode == 0x010f && modrm == 0xc8) |
| 1030 | + return ES_OK; |
| 1031 | + break; |
| 1032 | + |
| 1033 | + case SVM_EXIT_MWAIT: |
| 1034 | + if (opcode == 0x010f && modrm == 0xc9) |
| 1035 | + return ES_OK; |
| 1036 | + break; |
| 1037 | + |
| 1038 | + case SVM_EXIT_MSR: |
| 1039 | + /* RDMSR */ |
| 1040 | + if (opcode == 0x320f || |
| 1041 | + /* WRMSR */ |
| 1042 | + opcode == 0x300f) |
| 1043 | + return ES_OK; |
| 1044 | + break; |
| 1045 | + |
| 1046 | + case SVM_EXIT_RDPMC: |
| 1047 | + if (opcode == 0x330f) |
| 1048 | + return ES_OK; |
| 1049 | + break; |
| 1050 | + |
| 1051 | + case SVM_EXIT_RDTSC: |
| 1052 | + if (opcode == 0x310f) |
| 1053 | + return ES_OK; |
| 1054 | + break; |
| 1055 | + |
| 1056 | + case SVM_EXIT_RDTSCP: |
| 1057 | + if (opcode == 0x010f && modrm == 0xf9) |
| 1058 | + return ES_OK; |
| 1059 | + break; |
| 1060 | + |
| 1061 | + case SVM_EXIT_READ_DR7: |
| 1062 | + if (opcode == 0x210f && |
| 1063 | + X86_MODRM_REG(ctxt->insn.modrm.value) == 7) |
| 1064 | + return ES_OK; |
| 1065 | + break; |
| 1066 | + |
| 1067 | + case SVM_EXIT_VMMCALL: |
| 1068 | + if (opcode == 0x010f && modrm == 0xd9) |
| 1069 | + return ES_OK; |
| 1070 | + |
| 1071 | + break; |
| 1072 | + |
| 1073 | + case SVM_EXIT_WRITE_DR7: |
| 1074 | + if (opcode == 0x230f && |
| 1075 | + X86_MODRM_REG(ctxt->insn.modrm.value) == 7) |
| 1076 | + return ES_OK; |
| 1077 | + break; |
| 1078 | + |
| 1079 | + case SVM_EXIT_WBINVD: |
| 1080 | + if (opcode == 0x90f) |
| 1081 | + return ES_OK; |
| 1082 | + break; |
| 1083 | + |
| 1084 | + default: |
| 1085 | + break; |
| 1086 | + } |
| 1087 | + |
| 1088 | + sev_printk(KERN_ERR "Wrong/unhandled opcode bytes: 0x%x, exit_code: 0x%lx, rIP: 0x%lx\n", |
| 1089 | + opcode, exit_code, ctxt->regs->ip); |
| 1090 | + |
| 1091 | + return ES_UNSUPPORTED; |
| 1092 | +} |
0 commit comments