X86/KVM: Clear encryption attribute when SEV is active
The guest physical memory area holding the struct pvclock_wall_clock and struct pvclock_vcpu_time_info are shared with the hypervisor. It periodically updates the contents of the memory. When SEV is active, the encryption attributes from the shared memory pages must be cleared so that both hypervisor and guest can access the data. Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Tested-by: Borislav Petkov <bp@suse.de> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: kvm@vger.kernel.org Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Paolo Bonzini <pbonzini@redhat.com> Link: https://lkml.kernel.org/r/20171020143059.3291-18-brijesh.singh@amd.com
This commit is contained in:
parent
4716276184
commit
819aeee065
|
@ -114,10 +114,11 @@ static int vvar_fault(const struct vm_special_mapping *sm,
|
|||
struct pvclock_vsyscall_time_info *pvti =
|
||||
pvclock_pvti_cpu0_va();
|
||||
if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) {
|
||||
ret = vm_insert_pfn(
|
||||
ret = vm_insert_pfn_prot(
|
||||
vma,
|
||||
vmf->address,
|
||||
__pa(pvti) >> PAGE_SHIFT);
|
||||
__pa(pvti) >> PAGE_SHIFT,
|
||||
pgprot_decrypted(vma->vm_page_prot));
|
||||
}
|
||||
} else if (sym_offset == image->sym_hvclock_page) {
|
||||
struct ms_hyperv_tsc_page *tsc_pg = hv_get_tsc_page();
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/sched/clock.h>
|
||||
|
||||
#include <asm/mem_encrypt.h>
|
||||
#include <asm/x86_init.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/kvmclock.h>
|
||||
|
@ -45,7 +46,7 @@ early_param("no-kvmclock", parse_no_kvmclock);
|
|||
|
||||
/* The hypervisor will put information about time periodically here */
|
||||
static struct pvclock_vsyscall_time_info *hv_clock;
|
||||
static struct pvclock_wall_clock wall_clock;
|
||||
static struct pvclock_wall_clock *wall_clock;
|
||||
|
||||
struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void)
|
||||
{
|
||||
|
@ -64,15 +65,15 @@ static void kvm_get_wallclock(struct timespec *now)
|
|||
int low, high;
|
||||
int cpu;
|
||||
|
||||
low = (int)__pa_symbol(&wall_clock);
|
||||
high = ((u64)__pa_symbol(&wall_clock) >> 32);
|
||||
low = (int)slow_virt_to_phys(wall_clock);
|
||||
high = ((u64)slow_virt_to_phys(wall_clock) >> 32);
|
||||
|
||||
native_write_msr(msr_kvm_wall_clock, low, high);
|
||||
|
||||
cpu = get_cpu();
|
||||
|
||||
vcpu_time = &hv_clock[cpu].pvti;
|
||||
pvclock_read_wallclock(&wall_clock, vcpu_time, now);
|
||||
pvclock_read_wallclock(wall_clock, vcpu_time, now);
|
||||
|
||||
put_cpu();
|
||||
}
|
||||
|
@ -249,11 +250,39 @@ static void kvm_shutdown(void)
|
|||
native_machine_shutdown();
|
||||
}
|
||||
|
||||
static phys_addr_t __init kvm_memblock_alloc(phys_addr_t size,
|
||||
phys_addr_t align)
|
||||
{
|
||||
phys_addr_t mem;
|
||||
|
||||
mem = memblock_alloc(size, align);
|
||||
if (!mem)
|
||||
return 0;
|
||||
|
||||
if (sev_active()) {
|
||||
if (early_set_memory_decrypted((unsigned long)__va(mem), size))
|
||||
goto e_free;
|
||||
}
|
||||
|
||||
return mem;
|
||||
e_free:
|
||||
memblock_free(mem, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init kvm_memblock_free(phys_addr_t addr, phys_addr_t size)
|
||||
{
|
||||
if (sev_active())
|
||||
early_set_memory_encrypted((unsigned long)__va(addr), size);
|
||||
|
||||
memblock_free(addr, size);
|
||||
}
|
||||
|
||||
void __init kvmclock_init(void)
|
||||
{
|
||||
struct pvclock_vcpu_time_info *vcpu_time;
|
||||
unsigned long mem;
|
||||
int size, cpu;
|
||||
unsigned long mem, mem_wall_clock;
|
||||
int size, cpu, wall_clock_size;
|
||||
u8 flags;
|
||||
|
||||
size = PAGE_ALIGN(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
|
||||
|
@ -267,21 +296,35 @@ void __init kvmclock_init(void)
|
|||
} else if (!(kvmclock && kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)))
|
||||
return;
|
||||
|
||||
printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
|
||||
msr_kvm_system_time, msr_kvm_wall_clock);
|
||||
|
||||
mem = memblock_alloc(size, PAGE_SIZE);
|
||||
if (!mem)
|
||||
wall_clock_size = PAGE_ALIGN(sizeof(struct pvclock_wall_clock));
|
||||
mem_wall_clock = kvm_memblock_alloc(wall_clock_size, PAGE_SIZE);
|
||||
if (!mem_wall_clock)
|
||||
return;
|
||||
|
||||
wall_clock = __va(mem_wall_clock);
|
||||
memset(wall_clock, 0, wall_clock_size);
|
||||
|
||||
mem = kvm_memblock_alloc(size, PAGE_SIZE);
|
||||
if (!mem) {
|
||||
kvm_memblock_free(mem_wall_clock, wall_clock_size);
|
||||
wall_clock = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
hv_clock = __va(mem);
|
||||
memset(hv_clock, 0, size);
|
||||
|
||||
if (kvm_register_clock("primary cpu clock")) {
|
||||
hv_clock = NULL;
|
||||
memblock_free(mem, size);
|
||||
kvm_memblock_free(mem, size);
|
||||
kvm_memblock_free(mem_wall_clock, wall_clock_size);
|
||||
wall_clock = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
|
||||
msr_kvm_system_time, msr_kvm_wall_clock);
|
||||
|
||||
if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT))
|
||||
pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
|
||||
|
||||
|
|
Loading…
Reference in New Issue