-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
x86/boot/compressed/64: Add stage1 #VC handler
Add the first handler for #VC exceptions. At stage 1 there is no GHCB yet because the kernel might still be running on the EFI page table. The stage 1 handler is limited to the MSR-based protocol to talk to the hypervisor and can only support CPUID exit-codes, but that is enough to get to stage 2. [ bp: Zap superfluous newlines after rd/wrmsr instruction mnemonics. ] Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20200907131613.12703-20-joro@8bytes.org
- Loading branch information
Joerg Roedel
authored and
Borislav Petkov
committed
Sep 7, 2020
1 parent
21cf237
commit 29dcc60
Showing
9 changed files
with
160 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* AMD Encrypted Register State Support | ||
* | ||
* Author: Joerg Roedel <jroedel@suse.de> | ||
*/ | ||
|
||
/* | ||
* misc.h needs to be first because it knows how to include the other kernel | ||
* headers in the pre-decompression code in a way that does not break | ||
* compilation. | ||
*/ | ||
#include "misc.h" | ||
|
||
#include <asm/sev-es.h> | ||
#include <asm/msr-index.h> | ||
#include <asm/ptrace.h> | ||
#include <asm/svm.h> | ||
|
||
static inline u64 sev_es_rd_ghcb_msr(void) | ||
{ | ||
unsigned long low, high; | ||
|
||
asm volatile("rdmsr" : "=a" (low), "=d" (high) : | ||
"c" (MSR_AMD64_SEV_ES_GHCB)); | ||
|
||
return ((high << 32) | low); | ||
} | ||
|
||
static inline void sev_es_wr_ghcb_msr(u64 val) | ||
{ | ||
u32 low, high; | ||
|
||
low = val & 0xffffffffUL; | ||
high = val >> 32; | ||
|
||
asm volatile("wrmsr" : : "c" (MSR_AMD64_SEV_ES_GHCB), | ||
"a"(low), "d" (high) : "memory"); | ||
} | ||
|
||
#undef __init | ||
#define __init | ||
|
||
/* Include code for early handlers */ | ||
#include "../../kernel/sev-es-shared.c" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* AMD Encrypted Register State Support | ||
* | ||
* Author: Joerg Roedel <jroedel@suse.de> | ||
*/ | ||
|
||
#ifndef __ASM_ENCRYPTED_STATE_H | ||
#define __ASM_ENCRYPTED_STATE_H | ||
|
||
#include <linux/types.h> | ||
|
||
#define GHCB_SEV_CPUID_REQ 0x004UL | ||
#define GHCB_CPUID_REQ_EAX 0 | ||
#define GHCB_CPUID_REQ_EBX 1 | ||
#define GHCB_CPUID_REQ_ECX 2 | ||
#define GHCB_CPUID_REQ_EDX 3 | ||
#define GHCB_CPUID_REQ(fn, reg) (GHCB_SEV_CPUID_REQ | \ | ||
(((unsigned long)reg & 3) << 30) | \ | ||
(((unsigned long)fn) << 32)) | ||
|
||
#define GHCB_SEV_CPUID_RESP 0x005UL | ||
#define GHCB_SEV_TERMINATE 0x100UL | ||
|
||
#define GHCB_SEV_GHCB_RESP_CODE(v) ((v) & 0xfff) | ||
#define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); } | ||
|
||
void do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code); | ||
|
||
static inline u64 lower_bits(u64 val, unsigned int bits) | ||
{ | ||
u64 mask = (1ULL << bits) - 1; | ||
|
||
return (val & mask); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* AMD Encrypted Register State Support | ||
* | ||
* Author: Joerg Roedel <jroedel@suse.de> | ||
* | ||
* This file is not compiled stand-alone. It contains code shared | ||
* between the pre-decompression boot code and the running Linux kernel | ||
* and is included directly into both code-bases. | ||
*/ | ||
|
||
/* | ||
* Boot VC Handler - This is the first VC handler during boot, there is no GHCB | ||
* page yet, so it only supports the MSR based communication with the | ||
* hypervisor and only the CPUID exit-code. | ||
*/ | ||
void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code) | ||
{ | ||
unsigned int fn = lower_bits(regs->ax, 32); | ||
unsigned long val; | ||
|
||
/* Only CPUID is supported via MSR protocol */ | ||
if (exit_code != SVM_EXIT_CPUID) | ||
goto fail; | ||
|
||
sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_EAX)); | ||
VMGEXIT(); | ||
val = sev_es_rd_ghcb_msr(); | ||
if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP) | ||
goto fail; | ||
regs->ax = val >> 32; | ||
|
||
sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_EBX)); | ||
VMGEXIT(); | ||
val = sev_es_rd_ghcb_msr(); | ||
if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP) | ||
goto fail; | ||
regs->bx = val >> 32; | ||
|
||
sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_ECX)); | ||
VMGEXIT(); | ||
val = sev_es_rd_ghcb_msr(); | ||
if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP) | ||
goto fail; | ||
regs->cx = val >> 32; | ||
|
||
sev_es_wr_ghcb_msr(GHCB_CPUID_REQ(fn, GHCB_CPUID_REQ_EDX)); | ||
VMGEXIT(); | ||
val = sev_es_rd_ghcb_msr(); | ||
if (GHCB_SEV_GHCB_RESP_CODE(val) != GHCB_SEV_CPUID_RESP) | ||
goto fail; | ||
regs->dx = val >> 32; | ||
|
||
/* Skip over the CPUID two-byte opcode */ | ||
regs->ip += 2; | ||
|
||
return; | ||
|
||
fail: | ||
sev_es_wr_ghcb_msr(GHCB_SEV_TERMINATE); | ||
VMGEXIT(); | ||
|
||
/* Shouldn't get here - if we do halt the machine */ | ||
while (true) | ||
asm volatile("hlt\n"); | ||
} |