hv: keylocker: Support keylocker backup MSRs for Guest VM
The logical processor scoped IWKey can be copied to or from a platform-scope storage copy called IWKeyBackup. Copying IWKey to IWKeyBackup is called ‘backing up IWKey’ and copying from IWKeyBackup to IWKey is called ‘restoring IWKey’. IWKeyBackup and the path between it and IWKey are protected against software and simple hardware attacks. This means that IWKeyBackup can be used to distribute an IWKey within the logical processors in a platform in a protected manner. Linux keylocker implementation uses this feature, so they are introduced by this patch. Tracked-On: #5695 Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
38cd5b481d
commit
d4aaf99d86
|
@ -270,6 +270,7 @@ static void vcpu_reset_internal(struct acrn_vcpu *vcpu, enum reset_mode mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
init_iwkey(vcpu);
|
init_iwkey(vcpu);
|
||||||
|
vcpu->arch.iwkey_copy_status = 0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct acrn_vcpu *get_running_vcpu(uint16_t pcpu_id)
|
struct acrn_vcpu *get_running_vcpu(uint16_t pcpu_id)
|
||||||
|
|
|
@ -468,6 +468,7 @@ int32_t create_vm(uint16_t vm_id, uint64_t pcpu_bitmap, struct acrn_vm_config *v
|
||||||
spinlock_init(&vm->vlapic_mode_lock);
|
spinlock_init(&vm->vlapic_mode_lock);
|
||||||
spinlock_init(&vm->ept_lock);
|
spinlock_init(&vm->ept_lock);
|
||||||
spinlock_init(&vm->emul_mmio_lock);
|
spinlock_init(&vm->emul_mmio_lock);
|
||||||
|
spinlock_init(&vm->arch_vm.iwkey_backup_lock);
|
||||||
|
|
||||||
vm->arch_vm.vlapic_mode = VM_VLAPIC_XAPIC;
|
vm->arch_vm.vlapic_mode = VM_VLAPIC_XAPIC;
|
||||||
vm->intr_inject_delay_delta = 0UL;
|
vm->intr_inject_delay_delta = 0UL;
|
||||||
|
@ -717,6 +718,7 @@ int32_t reset_vm(struct acrn_vm *vm)
|
||||||
reset_vioapics(vm);
|
reset_vioapics(vm);
|
||||||
destroy_secure_world(vm, false);
|
destroy_secure_world(vm, false);
|
||||||
vm->sworld_control.flag.active = 0UL;
|
vm->sworld_control.flag.active = 0UL;
|
||||||
|
vm->arch_vm.iwkey_backup_status = 0UL;
|
||||||
vm->state = VM_CREATED;
|
vm->state = VM_CREATED;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -61,6 +61,12 @@ static const uint32_t emulated_guest_msrs[NUM_GUEST_MSRS] = {
|
||||||
|
|
||||||
MSR_IA32_XSS,
|
MSR_IA32_XSS,
|
||||||
|
|
||||||
|
/* KeyLocker backup MSRs */
|
||||||
|
MSR_IA32_COPY_LOCAL_TO_PLATFORM,
|
||||||
|
MSR_IA32_COPY_PLATFORM_TO_LOCAL,
|
||||||
|
MSR_IA32_COPY_STATUS,
|
||||||
|
MSR_IA32_IWKEY_BACKUP_STATUS,
|
||||||
|
|
||||||
MSR_TEST_CTL,
|
MSR_TEST_CTL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -402,6 +408,17 @@ static int32_t write_pat_msr(struct acrn_vcpu *vcpu, uint64_t value)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @pre vcpu != NULL
|
||||||
|
*/
|
||||||
|
bool is_iwkey_backup_support(struct acrn_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
uint32_t eax = 0x19U, ebx = 0U, ecx = 0U, edx = 0U;
|
||||||
|
|
||||||
|
guest_cpuid(vcpu, &eax, &ebx, &ecx, &edx);
|
||||||
|
return (ebx & CPUID_EBX_KL_BACKUP_MSR) == CPUID_EBX_KL_BACKUP_MSR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @pre vcpu != NULL
|
* @pre vcpu != NULL
|
||||||
*/
|
*/
|
||||||
|
@ -516,6 +533,24 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MSR_IA32_COPY_STATUS:
|
||||||
|
{
|
||||||
|
if (is_iwkey_backup_support(vcpu)) {
|
||||||
|
v = vcpu->arch.iwkey_copy_status;
|
||||||
|
} else {
|
||||||
|
err = -EACCES;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MSR_IA32_IWKEY_BACKUP_STATUS:
|
||||||
|
{
|
||||||
|
if (is_iwkey_backup_support(vcpu)) {
|
||||||
|
v = vcpu->vm->arch_vm.iwkey_backup_status;
|
||||||
|
} else {
|
||||||
|
err = -EACCES;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MSR_TEST_CTL:
|
case MSR_TEST_CTL:
|
||||||
{
|
{
|
||||||
/* If has MSR_TEST_CTL, give emulated value
|
/* If has MSR_TEST_CTL, give emulated value
|
||||||
|
@ -842,6 +877,40 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MSR_IA32_COPY_LOCAL_TO_PLATFORM:
|
||||||
|
{
|
||||||
|
if ((v == 0x1UL) && is_iwkey_backup_support(vcpu)) {
|
||||||
|
vcpu->vm->arch_vm.iwkey_backup_status = 0UL;
|
||||||
|
spinlock_obtain(&vcpu->vm->arch_vm.iwkey_backup_lock);
|
||||||
|
vcpu->vm->arch_vm.iwkey_backup = vcpu->arch.IWKey;
|
||||||
|
spinlock_release(&vcpu->vm->arch_vm.iwkey_backup_lock);
|
||||||
|
/*
|
||||||
|
* Keylocker spec 0.76 Table 4-1:
|
||||||
|
* 'Backup/restore valid' bit and 'IWKeyBackup consumed' bit
|
||||||
|
*/
|
||||||
|
vcpu->vm->arch_vm.iwkey_backup_status = 0x9UL;
|
||||||
|
vcpu->arch.iwkey_copy_status = 1UL;
|
||||||
|
} else {
|
||||||
|
err = -EINVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MSR_IA32_COPY_PLATFORM_TO_LOCAL:
|
||||||
|
{
|
||||||
|
if ((v == 0x1UL) && is_iwkey_backup_support(vcpu) &&
|
||||||
|
(vcpu->vm->arch_vm.iwkey_backup_status == 0x9UL)) {
|
||||||
|
spinlock_obtain(&vcpu->vm->arch_vm.iwkey_backup_lock);
|
||||||
|
vcpu->arch.IWKey = vcpu->vm->arch_vm.iwkey_backup;
|
||||||
|
spinlock_release(&vcpu->vm->arch_vm.iwkey_backup_lock);
|
||||||
|
/* Load the new iwkey for this vcpu */
|
||||||
|
get_cpu_var(whose_iwkey) = NULL;
|
||||||
|
load_iwkey(vcpu);
|
||||||
|
vcpu->arch.iwkey_copy_status = 1UL;
|
||||||
|
} else {
|
||||||
|
err = -EINVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MSR_TEST_CTL:
|
case MSR_TEST_CTL:
|
||||||
{
|
{
|
||||||
/* If VM has MSR_TEST_CTL, ignore write operation
|
/* If VM has MSR_TEST_CTL, ignore write operation
|
||||||
|
|
|
@ -171,7 +171,7 @@ enum reset_mode;
|
||||||
#define SECURE_WORLD 1
|
#define SECURE_WORLD 1
|
||||||
|
|
||||||
#define NUM_WORLD_MSRS 2U
|
#define NUM_WORLD_MSRS 2U
|
||||||
#define NUM_COMMON_MSRS 17U
|
#define NUM_COMMON_MSRS 21U
|
||||||
#define NUM_GUEST_MSRS (NUM_WORLD_MSRS + NUM_COMMON_MSRS)
|
#define NUM_GUEST_MSRS (NUM_WORLD_MSRS + NUM_COMMON_MSRS)
|
||||||
|
|
||||||
#define EOI_EXIT_BITMAP_SIZE 256U
|
#define EOI_EXIT_BITMAP_SIZE 256U
|
||||||
|
@ -270,6 +270,12 @@ struct acrn_vcpu_arch {
|
||||||
/* Keylocker */
|
/* Keylocker */
|
||||||
struct iwkey IWKey;
|
struct iwkey IWKey;
|
||||||
bool cr4_kl_enabled;
|
bool cr4_kl_enabled;
|
||||||
|
/*
|
||||||
|
* Keylocker spec 4.4:
|
||||||
|
* Bit 0 - Status of most recent copy to or from IWKeyBackup.
|
||||||
|
* Bit 63:1 - Reserved.
|
||||||
|
*/
|
||||||
|
uint64_t iwkey_copy_status;
|
||||||
} __aligned(PAGE_SIZE);
|
} __aligned(PAGE_SIZE);
|
||||||
|
|
||||||
struct acrn_vm;
|
struct acrn_vm;
|
||||||
|
|
|
@ -116,6 +116,18 @@ struct vm_arch {
|
||||||
#endif
|
#endif
|
||||||
enum vm_vlapic_mode vlapic_mode; /* Represents vLAPIC mode across vCPUs*/
|
enum vm_vlapic_mode vlapic_mode; /* Represents vLAPIC mode across vCPUs*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keylocker spec 4.5:
|
||||||
|
* Bit 0 - Backup/restore valid.
|
||||||
|
* Bit 1 - Reserved.
|
||||||
|
* Bit 2 - Backup key storage read/write error.
|
||||||
|
* Bit 3 - IWKeyBackup consumed.
|
||||||
|
* Bit 63:4 - Reserved.
|
||||||
|
*/
|
||||||
|
uint64_t iwkey_backup_status;
|
||||||
|
spinlock_t iwkey_backup_lock; /* Spin-lock used to protect internal key backup/restore */
|
||||||
|
struct iwkey iwkey_backup;
|
||||||
|
|
||||||
/* reference to virtual platform to come here (as needed) */
|
/* reference to virtual platform to come here (as needed) */
|
||||||
} __aligned(PAGE_SIZE);
|
} __aligned(PAGE_SIZE);
|
||||||
|
|
||||||
|
|
|
@ -353,6 +353,10 @@
|
||||||
#define MSR_IA32_L2_MASK_BASE 0x00000D10U
|
#define MSR_IA32_L2_MASK_BASE 0x00000D10U
|
||||||
#define MSR_IA32_MBA_MASK_BASE 0x00000D50U
|
#define MSR_IA32_MBA_MASK_BASE 0x00000D50U
|
||||||
#define MSR_IA32_BNDCFGS 0x00000D90U
|
#define MSR_IA32_BNDCFGS 0x00000D90U
|
||||||
|
#define MSR_IA32_COPY_LOCAL_TO_PLATFORM 0x00000D91U
|
||||||
|
#define MSR_IA32_COPY_PLATFORM_TO_LOCAL 0x00000D92U
|
||||||
|
#define MSR_IA32_COPY_STATUS 0x00000990U
|
||||||
|
#define MSR_IA32_IWKEY_BACKUP_STATUS 0x00000991U
|
||||||
#define MSR_IA32_EFER 0xC0000080U
|
#define MSR_IA32_EFER 0xC0000080U
|
||||||
#define MSR_IA32_STAR 0xC0000081U
|
#define MSR_IA32_STAR 0xC0000081U
|
||||||
#define MSR_IA32_LSTAR 0xC0000082U
|
#define MSR_IA32_LSTAR 0xC0000082U
|
||||||
|
|
Loading…
Reference in New Issue