cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cr4_cpuid_sync_test.c (2339B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * CR4 and CPUID sync test
      4 *
      5 * Copyright 2018, Red Hat, Inc. and/or its affiliates.
      6 *
      7 * Author:
      8 *   Wei Huang <wei@redhat.com>
      9 */
     10
     11#include <fcntl.h>
     12#include <stdio.h>
     13#include <stdlib.h>
     14#include <string.h>
     15#include <sys/ioctl.h>
     16
     17#include "test_util.h"
     18
     19#include "kvm_util.h"
     20#include "processor.h"
     21
     22#define X86_FEATURE_XSAVE	(1<<26)
     23#define X86_FEATURE_OSXSAVE	(1<<27)
     24#define VCPU_ID			1
     25
     26static inline bool cr4_cpuid_is_sync(void)
     27{
     28	int func, subfunc;
     29	uint32_t eax, ebx, ecx, edx;
     30	uint64_t cr4;
     31
     32	func = 0x1;
     33	subfunc = 0x0;
     34	__asm__ __volatile__("cpuid"
     35			     : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
     36			     : "a"(func), "c"(subfunc));
     37
     38	cr4 = get_cr4();
     39
     40	return (!!(ecx & X86_FEATURE_OSXSAVE)) == (!!(cr4 & X86_CR4_OSXSAVE));
     41}
     42
     43static void guest_code(void)
     44{
     45	uint64_t cr4;
     46
     47	/* turn on CR4.OSXSAVE */
     48	cr4 = get_cr4();
     49	cr4 |= X86_CR4_OSXSAVE;
     50	set_cr4(cr4);
     51
     52	/* verify CR4.OSXSAVE == CPUID.OSXSAVE */
     53	GUEST_ASSERT(cr4_cpuid_is_sync());
     54
     55	/* notify hypervisor to change CR4 */
     56	GUEST_SYNC(0);
     57
     58	/* check again */
     59	GUEST_ASSERT(cr4_cpuid_is_sync());
     60
     61	GUEST_DONE();
     62}
     63
     64int main(int argc, char *argv[])
     65{
     66	struct kvm_run *run;
     67	struct kvm_vm *vm;
     68	struct kvm_sregs sregs;
     69	struct kvm_cpuid_entry2 *entry;
     70	struct ucall uc;
     71	int rc;
     72
     73	entry = kvm_get_supported_cpuid_entry(1);
     74	if (!(entry->ecx & X86_FEATURE_XSAVE)) {
     75		print_skip("XSAVE feature not supported");
     76		return 0;
     77	}
     78
     79	/* Tell stdout not to buffer its content */
     80	setbuf(stdout, NULL);
     81
     82	/* Create VM */
     83	vm = vm_create_default(VCPU_ID, 0, guest_code);
     84	run = vcpu_state(vm, VCPU_ID);
     85
     86	while (1) {
     87		rc = _vcpu_run(vm, VCPU_ID);
     88
     89		TEST_ASSERT(rc == 0, "vcpu_run failed: %d\n", rc);
     90		TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
     91			    "Unexpected exit reason: %u (%s),\n",
     92			    run->exit_reason,
     93			    exit_reason_str(run->exit_reason));
     94
     95		switch (get_ucall(vm, VCPU_ID, &uc)) {
     96		case UCALL_SYNC:
     97			/* emulate hypervisor clearing CR4.OSXSAVE */
     98			vcpu_sregs_get(vm, VCPU_ID, &sregs);
     99			sregs.cr4 &= ~X86_CR4_OSXSAVE;
    100			vcpu_sregs_set(vm, VCPU_ID, &sregs);
    101			break;
    102		case UCALL_ABORT:
    103			TEST_FAIL("Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
    104			break;
    105		case UCALL_DONE:
    106			goto done;
    107		default:
    108			TEST_FAIL("Unknown ucall %lu", uc.cmd);
    109		}
    110	}
    111
    112done:
    113	kvm_vm_free(vm);
    114	return 0;
    115}