Date   

[PATCH] microcode: Enable microcode update from SOS.

fengwei.yin@...
 

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94 +++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/guest/ucode.c
create mode 100644 include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c
C_SRCS += arch/x86/guest/vmsr.c
C_SRCS += arch/x86/guest/vioapic.c
C_SRCS += arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu);
-void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);
diff --git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c
new file mode 100644
index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void)
+{
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v)
+{
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c
index 7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq of ops*/
static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/
enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap, emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject gp*/
enable_msr_interception(msr_bitmap, MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap, MSR_IA32_MTRR_DEF_TYPE);
@@ -191,6 +200,11 @@ int rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h b/include/arch/x86/guest/guest.h
index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm);
uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm);
struct vcpu *vcpu_from_vid(struct vm *vm, int vcpu_id);
diff --git a/include/arch/x86/guest/ucode.h b/include/arch/x86/guest/ucode.h
new file mode 100644
index 0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v);
+uint64_t get_microcode_version(void);
+
+#endif
--
2.7.4


Re: [PATCH] microcode: Enable microcode update from SOS.

Eddie Dong
 

Can we bypass the uCode update process for VM0? Why we need to intercept?

Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update from SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode 100644
arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS +=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c C_SRCS +=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg, int
vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void vm_gva2gpa(struct
vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff --git a/arch/x86/guest/ucode.c
b/arch/x86/guest/ucode.c new file mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void)
+{
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq of ops*/
static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap, emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject gp*/
enable_msr_interception(msr_bitmap, MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm); uint64_t
vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h b/include/arch/x86/guest/ucode.h new
file mode 100644 index 0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4



Re: [PATCH] microcode: Enable microcode update from SOS.

fengwei.yin@...
 

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update from SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode 100644
arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS +=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c C_SRCS +=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg, int
vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void vm_gva2gpa(struct
vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff --git a/arch/x86/guest/ucode.c
b/arch/x86/guest/ucode.c new file mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void)
+{
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq of ops*/
static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap, emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject gp*/
enable_msr_interception(msr_bitmap, MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm); uint64_t
vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h b/include/arch/x86/guest/ucode.h new
file mode 100644 index 0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4





Re: [PATCH] microcode: Enable microcode update from SOS.

Eddie Dong
 

That is stranger... We use identical mapping for VM0, right? Anyway, it is ok to leave as it is.

BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.

The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS +=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq
of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm); uint64_t
vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h b/include/arch/x86/guest/ucode.h
new file mode 100644 index 0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4





Re: [PATCH] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

On Wed, Mar 14, 2018 at 01:38:40PM +0800, Dong, Eddie wrote:
That is stranger... We use identical mapping for VM0, right? Anyway, it is ok to leave as it is.
Yes. We are using identical mapping for VM0. But Linux kernel uses vmalloc
to allocate memory to load uCode itself.

But I did try changing vmalloc to kmalloc in kernel. The uCode update still failed.
I could test it again to double check whether the failure is related with vmalloc.


BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.
Because we copy uCode per PAGE, gva is used to get the PAGE_SIZE aligned base address.
v is an address. So its bit 63 should be zero and we could use IA32E_REF_MASK directly.

Regards
Yin, Fengwei


The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS +=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq
of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm); uint64_t
vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h b/include/arch/x86/guest/ucode.h
new file mode 100644 index 0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4





Re: [PATCH] microcode: Enable microcode update from SOS.

Eddie Dong
 

Not sure if clear bit 63 is an architectural requirement or not.

+ Kevin.

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:48 PM
To: Dong, Eddie <eddie.dong@...>
Cc: acrn-dev@...
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.

On Wed, Mar 14, 2018 at 01:38:40PM +0800, Dong, Eddie wrote:
That is stranger... We use identical mapping for VM0, right? Anyway, it is ok
to leave as it is.
Yes. We are using identical mapping for VM0. But Linux kernel uses vmalloc
to allocate memory to load uCode itself.

But I did try changing vmalloc to kmalloc in kernel. The uCode update still
failed.
I could test it again to double check whether the failure is related with
vmalloc.


BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.
Because we copy uCode per PAGE, gva is used to get the PAGE_SIZE aligned
base address.
v is an address. So its bit 63 should be zero and we could use
IA32E_REF_MASK directly.

Regards
Yin, Fengwei


The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50
++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS
+=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c
C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int
reg, int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct
+ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as
freq of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm);
uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t
+*gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h new file mode 100644 index
0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4





Re: [PATCH] microcode: Enable microcode update from SOS.

Eddie Dong
 

BTW, when upload the uCode, should we check the guest uCode version with physical uCode version before doing real uCode upload? This can save time, and helps the real time behavior..

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:48 PM
To: acrn-dev@...
Cc: acrn-dev@...
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.

On Wed, Mar 14, 2018 at 01:38:40PM +0800, Dong, Eddie wrote:
That is stranger... We use identical mapping for VM0, right? Anyway, it is ok
to leave as it is.
Yes. We are using identical mapping for VM0. But Linux kernel uses vmalloc
to allocate memory to load uCode itself.

But I did try changing vmalloc to kmalloc in kernel. The uCode update still
failed.
I could test it again to double check whether the failure is related with
vmalloc.


BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.
Because we copy uCode per PAGE, gva is used to get the PAGE_SIZE aligned
base address.
v is an address. So its bit 63 should be zero and we could use
IA32E_REF_MASK directly.

Regards
Yin, Fengwei


The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50
++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS
+=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c
C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int
reg, int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct
+ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as
freq of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm);
uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t
+*gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h new file mode 100644 index
0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4





Re: [PATCH] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

On 03/14/2018 02:57 PM, Tian, Kevin wrote:
From: Dong, Eddie
Sent: Wednesday, March 14, 2018 2:50 PM

Not sure if clear bit 63 is an architectural requirement or not.

+ Kevin.
I didn't understand. In 64bit mode, all 64bits are available. If
bit63 is cleared how can you find a valid gpa for it?
Yes. According to Documentation/x86/x86_64/mm.txt, the 64bit is
available. Let me check why the code could work and get you guys
back later.

Regards
Yin, Fengwei



-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:48 PM
To: Dong, Eddie <eddie.dong@...>
Cc: acrn-dev@...
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

On Wed, Mar 14, 2018 at 01:38:40PM +0800, Dong, Eddie wrote:
That is stranger... We use identical mapping for VM0, right? Anyway, it
is ok
to leave as it is.
Yes. We are using identical mapping for VM0. But Linux kernel uses
vmalloc
to allocate memory to load uCode itself.

But I did try changing vmalloc to kmalloc in kernel. The uCode update still
failed.
I could test it again to double check whether the failure is related with
vmalloc.


BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.
Because we copy uCode per PAGE, gva is used to get the PAGE_SIZE
aligned
base address.
v is an address. So its bit 63 should be zero and we could use
IA32E_REF_MASK directly.

Regards
Yin, Fengwei


The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50
++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS
+=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c
C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int
reg, int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct
+ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct
ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >>
CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva,
CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE
- 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as
freq of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE
VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable
MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu
*vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to
inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm);
uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t
+*gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h new file mode 100644 index
0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4




Re: [PATCH] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

On 03/14/2018 02:58 PM, Eddie Dong wrote:
BTW, when upload the uCode, should we check the guest uCode version with physical uCode version before doing real uCode upload? This can save time, and helps the real time behavior..
We expose the uCode version to SOS and SOS kernel does the check before
issue update the uCode.

Regards
Yin, Fengwei


-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:48 PM
To: acrn-dev@...
Cc: acrn-dev@...
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.

On Wed, Mar 14, 2018 at 01:38:40PM +0800, Dong, Eddie wrote:
That is stranger... We use identical mapping for VM0, right? Anyway, it is ok
to leave as it is.
Yes. We are using identical mapping for VM0. But Linux kernel uses vmalloc
to allocate memory to load uCode itself.

But I did try changing vmalloc to kmalloc in kernel. The uCode update still
failed.
I could test it again to double check whether the failure is related with
vmalloc.


BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.
Because we copy uCode per PAGE, gva is used to get the PAGE_SIZE aligned
base address.
v is an address. So its bit 63 should be zero and we could use
IA32E_REF_MASK directly.

Regards
Yin, Fengwei


The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50
++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS
+=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c
C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int
reg, int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct
+ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as
freq of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm);
uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t
+*gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h new file mode 100644 index
0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4





Re: [PATCH] microcode: Enable microcode update from SOS.

Eddie Dong
 

OK

-----Original Message-----
From: Yin, Fengwei
Sent: Wednesday, March 14, 2018 12:18 AM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update from
SOS.


On 03/14/2018 02:58 PM, Eddie Dong wrote:
BTW, when upload the uCode, should we check the guest uCode version
with physical uCode version before doing real uCode upload? This can save
time, and helps the real time behavior..
We expose the uCode version to SOS and SOS kernel does the check before
issue update the uCode.

Regards
Yin, Fengwei


-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:48 PM
To: acrn-dev@...
Cc: acrn-dev@...
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 01:38:40PM +0800, Dong, Eddie wrote:
That is stranger... We use identical mapping for VM0, right? Anyway,
it is ok
to leave as it is.
Yes. We are using identical mapping for VM0. But Linux kernel uses
vmalloc to allocate memory to load uCode itself.

But I did try changing vmalloc to kmalloc in kernel. The uCode update
still failed.
I could test it again to double check whether the failure is related
with vmalloc.


BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.
Because we copy uCode per PAGE, gva is used to get the PAGE_SIZE
aligned base address.
v is an address. So its bit 63 should be zero and we could use
IA32E_REF_MASK directly.

Regards
Yin, Fengwei


The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50
++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS
+=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c
C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int
reg, int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with
the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written
permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct
+ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as
freq of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE
VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm);
uint64_t
vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h
new file mode 100644 index
0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with
the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written
permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4







Re: [PATCH] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

On 03/14/2018 02:57 PM, Tian, Kevin wrote:
From: Dong, Eddie
Sent: Wednesday, March 14, 2018 2:50 PM

Not sure if clear bit 63 is an architectural requirement or not.

+ Kevin.
I didn't understand. In 64bit mode, all 64bits are available. If
bit63 is cleared how can you find a valid gpa for it?
Here is what I got:
bit63 of the line address is actually not used for now.
With 4-level paging, the PML4 entry is selected using:
bits 51:12 from CR3
bits 11:3 are from bits 47:39 of liner address.
bits 2:0 are all 0.

With 5-level paging, the PML5 entry is selected using:
bits 51:12 are from CR3
bits 11:3 are bits 56:48 of the line address.
bits 2:0 are all 0.

Also from "5-level paging and 5-Level EPT" White Paper:
A linear address is 48-bit canonical if bits 63:47 of the address are identical.
Similarly, an address is 57-bit canonical if bits 63:56 of the address are identical. Any
linear address is that 48-bit canonical is also 57-bit canonical.


But I do think we shouldn't clear 63bit now even it could work for now.
Will update the patch.

Regards
Yin, Fengwei



-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:48 PM
To: Dong, Eddie <eddie.dong@...>
Cc: acrn-dev@...
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

On Wed, Mar 14, 2018 at 01:38:40PM +0800, Dong, Eddie wrote:
That is stranger... We use identical mapping for VM0, right? Anyway, it
is ok
to leave as it is.
Yes. We are using identical mapping for VM0. But Linux kernel uses
vmalloc
to allocate memory to load uCode itself.

But I did try changing vmalloc to kmalloc in kernel. The uCode update still
failed.
I could test it again to double check whether the failure is related with
vmalloc.


BTW, why:
gva = v & IA32E_REF_MASK;
It clears bit 63.
Because we copy uCode per PAGE, gva is used to get the PAGE_SIZE
aligned
base address.
v is an address. So its bit 63 should be zero and we could use
IA32E_REF_MASK directly.

Regards
Yin, Fengwei


The rest is fine to me.
Thx Eddie

-----Original Message-----
From: Yin, Fengwei
Sent: Tuesday, March 13, 2018 10:12 PM
To: acrn-dev@...
Cc: Dong, Eddie <eddie.dong@...>
Subject: Re: [acrn-dev] [PATCH] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 04:02:10AM +0000, Eddie Dong wrote:
Can we bypass the uCode update process for VM0? Why we need to
intercept?
Tried bypass the uCode update for VM0. But it doesn't work.

Regards
Yin, Fengwei


Thx Eddie

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of
fengwei.yin@...
Sent: Tuesday, March 13, 2018 7:19 PM
To: acrn-dev@...
Cc: Yin, Fengwei <fengwei.yin@...>
Subject: [acrn-dev] [PATCH] microcode: Enable microcode update
from
SOS.

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50
++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile index c0a7d06..d65e0c1 100644
--- a/Makefile
+++ b/Makefile
@@ -128,6 +128,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS
+=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c
C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int
reg, int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..8104e0d
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & IA32E_REF_MASK;
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct
+ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct
ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >>
CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & IA32E_REF_MASK;
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva,
CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE
- 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
7be4a45..4bf8df3 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as
freq of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE
VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable
MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu
*vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to
inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE); @@ -191,6 +200,11 @@ int
rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -281,6 +295,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 794699f..fe3be5b 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -76,6 +76,7 @@ bool vm_lapic_disabled(struct vm *vm);
uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t
+*gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h new file mode 100644 index
0000000..64df181
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
FITNESS
+FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
+INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES;
LOSS
OF
+USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED
AND ON
+ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
+OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY
OUT OF
THE
+USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t data;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4




Re: [PATCH] microcode: Enable microcode update from SOS.

Tian, Kevin
 

From: Yin, Fengwei
Sent: Wednesday, March 14, 2018 3:37 PM


On 03/14/2018 02:57 PM, Tian, Kevin wrote:
From: Dong, Eddie
Sent: Wednesday, March 14, 2018 2:50 PM

Not sure if clear bit 63 is an architectural requirement or not.

+ Kevin.
I didn't understand. In 64bit mode, all 64bits are available. If
bit63 is cleared how can you find a valid gpa for it?
Here is what I got:
bit63 of the line address is actually not used for now.
With 4-level paging, the PML4 entry is selected using:
bits 51:12 from CR3
bits 11:3 are from bits 47:39 of liner address.
bits 2:0 are all 0.

With 5-level paging, the PML5 entry is selected using:
bits 51:12 are from CR3
bits 11:3 are bits 56:48 of the line address.
bits 2:0 are all 0.

Also from "5-level paging and 5-Level EPT" White Paper:
A linear address is 48-bit canonical if bits 63:47 of the address are
identical.
Similarly, an address is 57-bit canonical if bits 63:56 of the address
are identical. Any
linear address is that 48-bit canonical is also 57-bit canonical.
Thanks for confirmation. sorry I forgot there is canonical
definition of available linear address bits. above info explains
why kernel va can be 0xffffffffxxxxxxxx and yes anyway we
don't need clear bit63 here. :-)

Thanks
Kevin


Re: [PATCH] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

On 03/14/2018 03:55 PM, Tian, Kevin wrote:
From: Yin, Fengwei
Sent: Wednesday, March 14, 2018 3:37 PM


On 03/14/2018 02:57 PM, Tian, Kevin wrote:
From: Dong, Eddie
Sent: Wednesday, March 14, 2018 2:50 PM

Not sure if clear bit 63 is an architectural requirement or not.

+ Kevin.
I didn't understand. In 64bit mode, all 64bits are available. If
bit63 is cleared how can you find a valid gpa for it?
Here is what I got:
bit63 of the line address is actually not used for now.
With 4-level paging, the PML4 entry is selected using:
bits 51:12 from CR3
bits 11:3 are from bits 47:39 of liner address.
bits 2:0 are all 0.

With 5-level paging, the PML5 entry is selected using:
bits 51:12 are from CR3
bits 11:3 are bits 56:48 of the line address.
bits 2:0 are all 0.

Also from "5-level paging and 5-Level EPT" White Paper:
A linear address is 48-bit canonical if bits 63:47 of the address are
identical.
Similarly, an address is 57-bit canonical if bits 63:56 of the address
are identical. Any
linear address is that 48-bit canonical is also 57-bit canonical.
Thanks for confirmation. sorry I forgot there is canonical
definition of available linear address bits. above info explains
why kernel va can be 0xffffffffxxxxxxxx and yes anyway we
don't need clear bit63 here. :-)
Yes. Working on new patch version.

Regards
Yin, Fengwei

Thanks
Kevin


[PATCH v2] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.

Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Changes in v2:
- Not clear the bit63 of the address of uCode.

Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94 +++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/guest/ucode.c
create mode 100644 include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c35b705..13e408b 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,7 @@ C_SRCS += arch/x86/guest/vpic.c
C_SRCS += arch/x86/guest/vmsr.c
C_SRCS += arch/x86/guest/vioapic.c
C_SRCS += arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu);
-void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);
diff --git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c
new file mode 100644
index 0000000..44396dc
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void)
+{
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v)
+{
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & ~(CPU_PAGE_SIZE - 1);
+
+ vm_gva2gpa(vcpu, v, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
+
+ hva = hva & ~(CPU_PAGE_SIZE - 1);
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva, CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c
index edc456c..b371223 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq of ops*/
static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/
enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap, emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
+
/* below MSR protected from guest OS, if access to inject gp*/
enable_msr_interception(msr_bitmap, MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap, MSR_IA32_MTRR_DEF_TYPE);
@@ -185,6 +194,11 @@ int rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -273,6 +287,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h b/include/arch/x86/guest/guest.h
index 683433f..2649263 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -85,6 +85,7 @@ uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);
int init_vm0_boot_info(struct vm *vm);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm);
struct vcpu *vcpu_from_vid(struct vm *vm, int vcpu_id);
diff --git a/include/arch/x86/guest/ucode.h b/include/arch/x86/guest/ucode.h
new file mode 100644
index 0000000..a49c43b
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t date;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v);
+uint64_t get_microcode_version(void);
+
+#endif
--
2.7.4


Re: [PATCH v2] microcode: Enable microcode update from SOS.

Tian, Kevin
 

From: Yin, Fengwei
Sent: Wednesday, March 14, 2018 4:14 PM

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.
there is a problem with current implementation. microcode
needs being updated on all CPU cores, however SOS only
sees partial. If there is no plan to introduce a hypercall,
we need hook on the 1st MSR write from SOS and then
IPI to all physical cores to do update, and then simply
report success for subsequent MSR writes from SOS.


Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Changes in v2:
- Not clear the bit63 of the address of uCode.

Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/guest/ucode.c
create mode 100644 include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c35b705..13e408b 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,7 @@ C_SRCS += arch/x86/guest/vpic.c
C_SRCS += arch/x86/guest/vmsr.c
C_SRCS += arch/x86/guest/vioapic.c
C_SRCS += arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu);
-void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);
diff --git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c
new file mode 100644
index 0000000..44396dc
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void)
+{
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
is 0x2000 defined by SDM?

+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v)
+{
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & ~(CPU_PAGE_SIZE - 1);
+
+ vm_gva2gpa(vcpu, v, &gpa);
we shouldn't assume there is always an valid mapping here. I know
it's not this patch specific, as gva2gpa doesn't return any error today.
but it should be a cleanup task to emulate hardware behavior, i.e.
guest page table walking error should trigger exceptions back to
guest according to SDM.

+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
hva is already page aligned, meaning uhdr is in another page.
there is no guarantee that HPAs of two guest pages are contiguous.
you need walk guest pgtable again as long as page boundary is
crossed.

+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
do we need an error value returned here to emulate any
expected hardware behavior to SOS, e.g. changing of some
bit in MSR?

+
+ hva = hva & ~(CPU_PAGE_SIZE - 1);
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva,
CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
if microcode update fails, what should be done here?

+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c
index edc456c..b371223 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq of ops*/
static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/
enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
why only intercept for vm0? do you want other vm to trigger update?

+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE);
@@ -185,6 +194,11 @@ int rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -273,6 +287,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h
index 683433f..2649263 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -85,6 +85,7 @@ uint64_t vcpumask2pcpumask(struct vm *vm,
uint64_t vdmask);
int init_vm0_boot_info(struct vm *vm);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm);
struct vcpu *vcpu_from_vid(struct vm *vm, int vcpu_id);
diff --git a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h
new file mode 100644
index 0000000..a49c43b
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t date;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v);
+uint64_t get_microcode_version(void);
+
+#endif
--
2.7.4



Re: [PATCH v2] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

On Wed, Mar 14, 2018 at 10:17:53AM +0000, Tian, Kevin wrote:
From: Yin, Fengwei
Sent: Wednesday, March 14, 2018 4:14 PM

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.
there is a problem with current implementation. microcode
needs being updated on all CPU cores, however SOS only
sees partial. If there is no plan to introduce a hypercall,
we need hook on the 1st MSR write from SOS and then
IPI to all physical cores to do update, and then simply
report success for subsequent MSR writes from SOS.
Yes. It's on my TODO list. Because we only allow SOS to update
uCode, only pCPU running SOS get uCode updated.

We try not to change kernel source. So I prefer IPI approach(
cpu offline depends on the IPI also) and plan to address all
pCPU uCode update once we have IPI call ready.

Regards
Yin, Fengwei



Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Changes in v2:
- Not clear the bit63 of the address of uCode.

Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/guest/ucode.c
create mode 100644 include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c35b705..13e408b 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,7 @@ C_SRCS += arch/x86/guest/vpic.c
C_SRCS += arch/x86/guest/vmsr.c
C_SRCS += arch/x86/guest/vioapic.c
C_SRCS += arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu);
-void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);
diff --git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c
new file mode 100644
index 0000000..44396dc
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void)
+{
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
is 0x2000 defined by SDM?

+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v)
+{
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & ~(CPU_PAGE_SIZE - 1);
+
+ vm_gva2gpa(vcpu, v, &gpa);
we shouldn't assume there is always an valid mapping here. I know
it's not this patch specific, as gva2gpa doesn't return any error today.
but it should be a cleanup task to emulate hardware behavior, i.e.
guest page table walking error should trigger exceptions back to
guest according to SDM.

+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
hva is already page aligned, meaning uhdr is in another page.
there is no guarantee that HPAs of two guest pages are contiguous.
you need walk guest pgtable again as long as page boundary is
crossed.

+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
do we need an error value returned here to emulate any
expected hardware behavior to SOS, e.g. changing of some
bit in MSR?

+
+ hva = hva & ~(CPU_PAGE_SIZE - 1);
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva,
CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
if microcode update fails, what should be done here?

+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c
index edc456c..b371223 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq of ops*/
static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/
enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
why only intercept for vm0? do you want other vm to trigger update?

+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE);
@@ -185,6 +194,11 @@ int rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -273,6 +287,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h
index 683433f..2649263 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -85,6 +85,7 @@ uint64_t vcpumask2pcpumask(struct vm *vm,
uint64_t vdmask);
int init_vm0_boot_info(struct vm *vm);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm);
struct vcpu *vcpu_from_vid(struct vm *vm, int vcpu_id);
diff --git a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h
new file mode 100644
index 0000000..a49c43b
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t date;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v);
+uint64_t get_microcode_version(void);
+
+#endif
--
2.7.4





[PATCH 1/2] Add CHECK and CHECK_RET macro

Yan, Like
 

From: "Yan, Like" <like.yan@...>

- CHECK macro checks the given condition, if false, print a fatal
message, dump both host and guest context and return void;
- CHECK_RET macro checks the given condition, if false, print a fatal
message, dump both host and guest context and return a given value;
- dump_contexts function dump host and guest contexts

Change-Id: I482998c0ac7de32474097032abbf3835057c1f21
Signed-off-by: Yan, Like <like.yan@...>
---
debug/dump.c | 10 ++++++++++
include/debug/assert.h | 33 ++++++++++++++++++++++++++++++---
include/debug/dump.h | 5 +++++
3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/debug/dump.c b/debug/dump.c
index 87fb334..9e02caf 100644
--- a/debug/dump.c
+++ b/debug/dump.c
@@ -293,6 +293,16 @@ void __assert(uint32_t line, const char *file, char *txt)
} while (1);
}

+void dump_contexts(void)
+{
+ uint32_t cpu_id = get_cpu_id();
+ uint64_t rsp = cpu_rsp_get();
+ uint64_t rbp = cpu_rbp_get();
+
+ show_host_call_trace(rsp, rbp, cpu_id);
+ dump_guest_context(cpu_id);
+}
+
void dump_exception(struct intr_ctx *ctx, uint32_t cpu_id)
{
const char *name = "Not defined";
diff --git a/include/debug/assert.h b/include/debug/assert.h
index 83b26c1..b777fdd 100644
--- a/include/debug/assert.h
+++ b/include/debug/assert.h
@@ -34,18 +34,45 @@
#ifdef HV_DEBUG
void __assert(uint32_t line, const char *file, char *txt);

-#define ASSERT(x, ...) \
- if (!(x)) {\
- pr_fatal(__VA_ARGS__);\
+#define ASSERT(x, ...) \
+ if (!(x)) { \
+ pr_fatal(__VA_ARGS__); \
__assert(__LINE__, __FILE__, "fatal error");\
}
+
+#define CHECK(x, ...) \
+ if (!(x)) { \
+ pr_fatal(__VA_ARGS__); \
+ dump_contexts(); \
+ return ; \
+ }
+
+#define CHECK_RET(x, r, ...) \
+ if (!(x)) { \
+ pr_fatal(__VA_ARGS__); \
+ dump_contexts(); \
+ return (r); \
+ }
#else
#define ASSERT(x, ...) \
if (!(x)) { \
+ pr_fatal(__VA_ARGS__); \
do { \
asm volatile ("pause" ::: "memory"); \
} while (1); \
}
+
+#define CHECK(x, ...) \
+ if (!(x)) { \
+ pr_fatal(__VA_ARGS__); \
+ return ; \
+ }
+
+#define CHECK_RET(x, r, ...) \
+ if (!(x)) { \
+ pr_fatal(__VA_ARGS__); \
+ return (r); \
+ }
#endif

/* Force a compilation error if condition is false */
diff --git a/include/debug/dump.h b/include/debug/dump.h
index 1d3ebf3..d38415a 100644
--- a/include/debug/dump.h
+++ b/include/debug/dump.h
@@ -37,11 +37,16 @@ struct intr_ctx;
#define CALL_TRACE_HIERARCHY_MAX 20
#define DUMP_STACK_SIZE 0x200

+void dump_contexts(void);
void dump_exception(struct intr_ctx *ctx, uint32_t cpu_id);
void dump_interrupt(struct intr_ctx *ctx);

#else

+static inline void dump_contexts(void)
+{
+}
+
static inline void dump_exception(__unused struct intr_ctx *ctx,
__unused uint32_t cpu_id)
{
--
2.7.4


[PATCH 2/2] Cleanup ASSERT in hypercall/vmexit

Yan, Like
 

From: "Yan, Like" <like.yan@...>

Replace ASSERT which should not pause hypervisor with CHECK or
CHECK_RET in hypercall and vmexit handling.

Change-Id: If80b6be0abb808365e0208557a2682e67d245277
Signed-off-by: Yan, Like <like.yan@...>
---
arch/x86/vmexit.c | 7 +++++--
common/hypercall.c | 18 ++++++++++--------
2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/arch/x86/vmexit.c b/arch/x86/vmexit.c
index 3b1b536..25e7e95 100644
--- a/arch/x86/vmexit.c
+++ b/arch/x86/vmexit.c
@@ -349,7 +349,9 @@ int cr_access_handler(struct vcpu *vcpu)
};
int idx = VM_EXIT_CR_ACCESS_REG_IDX(vcpu->arch_vcpu.exit_qualification);

- ASSERT(idx != 4, "index should not be 4 (target SP)");
+ CHECK_RET(idx != 4, -EINVAL,
+ "%s: index should not be 4 (target SP)", __func__);
+
regptr = cur_context->guest_cpu_regs.longs + reg_trans_tab[idx];

switch ((VM_EXIT_CR_ACCESS_ACCESS_TYPE
@@ -389,7 +391,8 @@ int cr_access_handler(struct vcpu *vcpu)
*regptr = vlapic_get_cr8(vcpu->arch_vcpu.vlapic);
break;
default:
- panic("Unhandled CR access");
+ pr_fatal("Unhandled CR access");
+ dump_contexts();
return -EINVAL;
}

diff --git a/common/hypercall.c b/common/hypercall.c
index a3218bf..4693622 100644
--- a/common/hypercall.c
+++ b/common/hypercall.c
@@ -379,7 +379,8 @@ int64_t hcall_notify_req_finish(uint64_t vmid, uint64_t vcpu_id)
vmid, vcpu_id);

vcpu = vcpu_from_vid(target_vm, vcpu_id);
- ASSERT(vcpu != NULL, "Failed to get VCPU context.");
+ CHECK_RET(vcpu != NULL, -1,
+ "%s: Failed to get VCPU context.", __func__);

req_buf = (struct vhm_request_buffer *)target_vm->sw.req_buf;
req = req_buf->req_queue + vcpu_id;
@@ -541,12 +542,14 @@ int64_t hcall_assign_ptdev(struct vm *vm, uint64_t vmid, uint64_t param)

/* create a iommu domain for target VM if not created */
if (!target_vm->iommu_domain) {
- ASSERT(target_vm->arch_vm.ept, "EPT of VM not set!");
+ CHECK_RET(target_vm->arch_vm.ept, -1,
+ "%s: EPT of VM not set!", __func__);
/* TODO: how to get vm's address width? */
target_vm->iommu_domain = create_iommu_domain(vmid,
target_vm->arch_vm.ept, 48);
- ASSERT(target_vm->iommu_domain,
- "failed to created iommu domain!");
+ CHECK_RET(target_vm->iommu_domain, -1,
+ "%s: failed to created iommu domain!",
+ __func__);
}
ret = assign_iommu_device(target_vm->iommu_domain,
(uint8_t)(bdf >> 8), (uint8_t)(bdf & 0xff));
@@ -672,7 +675,7 @@ static void fire_vhm_interrupt(void)
ASSERT(vm0, "VM Pointer is NULL");

vcpu = vcpu_from_vid(vm0, 0);
- ASSERT(vcpu, "vcpu_from_vid failed");
+ CHECK(vcpu, "%s: vcpu_from_vid failed", __func__);

vlapic_intr_edge(vcpu, VECTOR_VIRT_IRQ_VHM);
}
@@ -720,9 +723,8 @@ int acrn_insert_request_wait(struct vcpu *vcpu, struct vhm_request *req)
(void *)HPA2HVA(vcpu->vm->sw.req_buf);
long cur;

- ASSERT(sizeof(*req) == (4096/VHM_REQUEST_MAX),
- "vhm_request page broken!");
-
+ CHECK_RET(sizeof(*req) == (4096/VHM_REQUEST_MAX), -1,
+ "%s: vhm_request page broken!", __func__);

if (!vcpu || !req || vcpu->vm->sw.req_buf == 0)
return -1;
--
2.7.4


Re: [PATCH v2] microcode: Enable microcode update from SOS.

Yin, Fengwei <fengwei.yin@...>
 

On Wed, Mar 14, 2018 at 10:17:53AM +0000, Tian, Kevin wrote:
From: Yin, Fengwei
Sent: Wednesday, March 14, 2018 4:14 PM

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.
there is a problem with current implementation. microcode
needs being updated on all CPU cores, however SOS only
sees partial. If there is no plan to introduce a hypercall,
we need hook on the 1st MSR write from SOS and then
IPI to all physical cores to do update, and then simply
report success for subsequent MSR writes from SOS.


Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Changes in v2:
- Not clear the bit63 of the address of uCode.

Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/guest/ucode.c
create mode 100644 include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c35b705..13e408b 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,7 @@ C_SRCS += arch/x86/guest/vpic.c
C_SRCS += arch/x86/guest/vmsr.c
C_SRCS += arch/x86/guest/vioapic.c
C_SRCS += arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu);
-void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);
diff --git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c
new file mode 100644
index 0000000..44396dc
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void)
+{
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
is 0x2000 defined by SDM?
Yes. It's in Table 9-7 of SDM vol 3. Should I add comments for 2000?


+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v)
+{
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & ~(CPU_PAGE_SIZE - 1);
+
+ vm_gva2gpa(vcpu, v, &gpa);
we shouldn't assume there is always an valid mapping here. I know
it's not this patch specific, as gva2gpa doesn't return any error today.
but it should be a cleanup task to emulate hardware behavior, i.e.
guest page table walking error should trigger exceptions back to
guest according to SDM.
For uCode case, there is valid mapping for sure. The uCode itself
is loaded by kernel to memory allocated with vmalloc. When the uCode
is copied to this memory, SOS kernel setup guest mapping. And then
kernel will update MSR_IA32_BIOS_UPDT_TRIG and trap to HV. So, at
this moment, the mapping is setup already.

+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
hva is already page aligned, meaning uhdr is in another page.
there is no guarantee that HPAs of two guest pages are contiguous.
you need walk guest pgtable again as long as page boundary is
crossed.
Sorry for the variables name which is confusing. hva is host virtual
address of v instead of gva (It may be better to change gva to v_aligned).

gva is page aligned while hva is not. I will change gva to v_aligned.

+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
do we need an error value returned here to emulate any
expected hardware behavior to SOS, e.g. changing of some
bit in MSR?
There is no return value for MSR_IA32_BIOS_UPDT_TRIG update.
SOS kernel will query the uCode version again to check whether
the uCode update is success or fail.

+
+ hva = hva & ~(CPU_PAGE_SIZE - 1);
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva,
CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
if microcode update fails, what should be done here?
My understanding is we don't need to do anything here. SOS kernel will
query uCode version again. If the uCode version read from msr is same
as uCode file, that means the uCode update is success. Otherwise, uCode
update is fail.


+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c
index edc456c..b371223 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq of ops*/
static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/
enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
why only intercept for vm0? do you want other vm to trigger update?
The policy is only allow SOS to do uCode update and deny uCode update
for all UOS.

Regards
Yin, Fengwei

+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE);
@@ -185,6 +194,11 @@ int rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -273,6 +287,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h
index 683433f..2649263 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -85,6 +85,7 @@ uint64_t vcpumask2pcpumask(struct vm *vm,
uint64_t vdmask);
int init_vm0_boot_info(struct vm *vm);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm);
struct vcpu *vcpu_from_vid(struct vm *vm, int vcpu_id);
diff --git a/include/arch/x86/guest/ucode.h
b/include/arch/x86/guest/ucode.h
new file mode 100644
index 0000000..a49c43b
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t date;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v);
+uint64_t get_microcode_version(void);
+
+#endif
--
2.7.4





Re: [PATCH v2] microcode: Enable microcode update from SOS.

Eddie Dong
 

Acked by <Eddie.dong@...>

Leave to Anthony...

-----Original Message-----
From: acrn-dev@...
[mailto:acrn-dev@...] On Behalf Of Yin, Fengwei
Sent: Wednesday, March 14, 2018 3:28 AM
To: acrn-dev@...
Subject: Re: [acrn-dev] [PATCH v2] microcode: Enable microcode update
from SOS.

On Wed, Mar 14, 2018 at 10:17:53AM +0000, Tian, Kevin wrote:
From: Yin, Fengwei
Sent: Wednesday, March 14, 2018 4:14 PM

From: Yin Fengwei <fengwei.yin@...>

microcode update from UOS is disabled.
microcode version checking is available for both SOS and UOS.
there is a problem with current implementation. microcode needs being
updated on all CPU cores, however SOS only sees partial. If there is
no plan to introduce a hypercall, we need hook on the 1st MSR write
from SOS and then IPI to all physical cores to do update, and then
simply report success for subsequent MSR writes from SOS.
Yes. It's on my TODO list. Because we only allow SOS to update uCode, only
pCPU running SOS get uCode updated.

We try not to change kernel source. So I prefer IPI approach( cpu offline
depends on the IPI also) and plan to address all pCPU uCode update once we
have IPI call ready.

Regards
Yin, Fengwei



Signed-off-by: Yin Fengwei <fengwei.yin@...>
---
Changes in v2:
- Not clear the bit63 of the address of uCode.

Makefile | 1 +
arch/x86/guest/instr_emul_wrapper.h | 1 -
arch/x86/guest/ucode.c | 94
+++++++++++++++++++++++++++++++++++++
arch/x86/guest/vmsr.c | 23 +++++++++
include/arch/x86/guest/guest.h | 1 +
include/arch/x86/guest/ucode.h | 50 ++++++++++++++++++++
6 files changed, 169 insertions(+), 1 deletion(-) create mode
100644 arch/x86/guest/ucode.c create mode 100644
include/arch/x86/guest/ucode.h

diff --git a/Makefile b/Makefile
index c35b705..13e408b 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,7 @@ C_SRCS += arch/x86/guest/vpic.c C_SRCS +=
arch/x86/guest/vmsr.c C_SRCS += arch/x86/guest/vioapic.c C_SRCS
+=
arch/x86/guest/instr_emul.c
+C_SRCS += arch/x86/guest/ucode.c
C_SRCS += lib/spinlock.c
C_SRCS += lib/udelay.c
C_SRCS += lib/strnlen.c
diff --git a/arch/x86/guest/instr_emul_wrapper.h
b/arch/x86/guest/instr_emul_wrapper.h
index 3581e9b..48e311f 100644
--- a/arch/x86/guest/instr_emul_wrapper.h
+++ b/arch/x86/guest/instr_emul_wrapper.h
@@ -200,4 +200,3 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg,
int vm_set_seg_desc(struct vcpu *vcpu, int reg,
struct seg_desc *desc);
int vm_restart_instruction(struct vcpu *vcpu); -void
vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa); diff
--git a/arch/x86/guest/ucode.c b/arch/x86/guest/ucode.c new file
mode 100644 index 0000000..44396dc
--- /dev/null
+++ b/arch/x86/guest/ucode.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#include <hv_lib.h>
+#include <acrn_common.h>
+#include <hv_arch.h>
+#include <hv_debug.h>
+#include <ucode.h>
+
+uint64_t get_microcode_version(void) {
+ uint64_t val;
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ msr_write(MSR_IA32_BIOS_SIGN_ID, 0);
+ native_cpuid_count(CPUID_FEATURES, 0, &eax, &ebx, &ecx,
&edx);
+ val = msr_read(MSR_IA32_BIOS_SIGN_ID);
+
+ return val;
+}
+
+#define GET_DATA_SIZE(hdptr) ((hdptr)->data_size ? : 2000)
is 0x2000 defined by SDM?

+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v) {
+ uint64_t hva, gpa, gva;
+ struct ucode_header *uhdr;
+ int data_size, data_page_num;
+ uint8_t *ptr, *ucode_ptr;
+
+ /* gva will be used as iterator to copy uCode to HV buffer.
+ * It will be aligned to CPU_PAGE_SIZE of v, increased
+ * by CPU_PAGE_SIZE and convert to hva for each step.
+ */
+ gva = v & ~(CPU_PAGE_SIZE - 1);
+
+ vm_gva2gpa(vcpu, v, &gpa);
we shouldn't assume there is always an valid mapping here. I know it's
not this patch specific, as gva2gpa doesn't return any error today.
but it should be a cleanup task to emulate hardware behavior, i.e.
guest page table walking error should trigger exceptions back to guest
according to SDM.

+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+
+ /* hva is used to get uhdr here */
+ uhdr = (struct ucode_header *)(hva - sizeof(struct ucode_header));
hva is already page aligned, meaning uhdr is in another page.
there is no guarantee that HPAs of two guest pages are contiguous.
you need walk guest pgtable again as long as page boundary is crossed.

+
+ data_size = GET_DATA_SIZE(uhdr) + sizeof(struct ucode_header) +
+ ((uint64_t)uhdr & (CPU_PAGE_SIZE - 1));
+ data_page_num =
+ (data_size + CPU_PAGE_SIZE - 1) >> CPU_PAGE_SHIFT;
+
+ ptr = ucode_ptr = alloc_pages(data_page_num);
+ if (ptr == NULL)
+ return;
do we need an error value returned here to emulate any expected
hardware behavior to SOS, e.g. changing of some bit in MSR?

+
+ hva = hva & ~(CPU_PAGE_SIZE - 1);
+ while (data_page_num--) {
+ memcpy_s(ptr, CPU_PAGE_SIZE, (void *)hva,
CPU_PAGE_SIZE);
+
+ ptr += CPU_PAGE_SIZE;
+ gva += CPU_PAGE_SIZE;
+
+ vm_gva2gpa(vcpu, gva, &gpa);
+ hva = (uint64_t)GPA2HVA(vcpu->vm, gpa);
+ }
+
+ msr_write(MSR_IA32_BIOS_UPDT_TRIG,
+ (uint64_t)ucode_ptr + (v & (CPU_PAGE_SIZE - 1)));
+ get_microcode_version();
if microcode update fails, what should be done here?

+
+ free(ucode_ptr);
+}
diff --git a/arch/x86/guest/vmsr.c b/arch/x86/guest/vmsr.c index
edc456c..b371223 100644
--- a/arch/x86/guest/vmsr.c
+++ b/arch/x86/guest/vmsr.c
@@ -32,10 +32,13 @@
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
+#include <ucode.h>

/*MRS need to be emulated, the order in this array better as freq
of ops*/ static const uint32_t emulated_msrs[] = {
MSR_IA32_TSC_DEADLINE, /* Enable TSC_DEADLINE VMEXIT */
+ MSR_IA32_BIOS_SIGN_ID, /* Enable MSR_IA32_BIOS_SIGN_ID */
+

/* following MSR not emulated now */
/*
@@ -51,6 +54,7 @@ static const uint32_t emulated_msrs[] = {
/* the index is matched with emulated msrs array*/ enum {
IDX_TSC_DEADLINE,
+ IDX_BIOS_SIGN_ID,

IDX_MAX_MSR
};
@@ -129,6 +133,11 @@ void init_msr_emulation(struct vcpu *vcpu)
for (i = 0; i < msrs_count; i++)
enable_msr_interception(msr_bitmap,
emulated_msrs[i]);

+ /* Only enable uCode update for SOS */
+ if (is_vm0(vcpu->vm))
+ enable_msr_interception(msr_bitmap,
+ MSR_IA32_BIOS_UPDT_TRIG);
why only intercept for vm0? do you want other vm to trigger update?

+
/* below MSR protected from guest OS, if access to inject
gp*/
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_CAP);
enable_msr_interception(msr_bitmap,
MSR_IA32_MTRR_DEF_TYPE);
@@ -185,6 +194,11 @@ int rdmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ v = get_microcode_version();
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
@@ -273,6 +287,15 @@ int wrmsr_handler(struct vcpu *vcpu)
vcpu_inject_gp(vcpu);
break;
}
+ case MSR_IA32_BIOS_SIGN_ID:
+ {
+ break;
+ }
+ case MSR_IA32_BIOS_UPDT_TRIG:
+ {
+ acrn_update_ucode(vcpu, v);
+ break;
+ }

/* following MSR not emulated now just left for future */
case MSR_IA32_SYSENTER_CS:
diff --git a/include/arch/x86/guest/guest.h
b/include/arch/x86/guest/guest.h index 683433f..2649263 100644
--- a/include/arch/x86/guest/guest.h
+++ b/include/arch/x86/guest/guest.h
@@ -85,6 +85,7 @@ uint64_t vcpumask2pcpumask(struct vm *vm,
uint64_t
vdmask); int init_vm0_boot_info(struct vm *vm);

uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
+void vm_gva2gpa(struct vcpu *vcpu, uint64_t gla, uint64_t *gpa);

struct vcpu *get_primary_vcpu(struct vm *vm); struct vcpu
*vcpu_from_vid(struct vm *vm, int vcpu_id); diff --git
a/include/arch/x86/guest/ucode.h b/include/arch/x86/guest/ucode.h
new file mode 100644 index 0000000..a49c43b
--- /dev/null
+++ b/include/arch/x86/guest/ucode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+without
+ * modification, are permitted provided that the following
+conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products
derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT
NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS
OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF
THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _ARCH_X86_UCODE_H
+#define _ARCH_X86_UCODE_H
+
+struct ucode_header {
+ uint32_t header_ver;
+ uint32_t update_ver;
+ uint32_t date;
+ uint32_t proc_sig;
+ uint32_t checksum;
+ uint32_t loader_ver;
+ uint32_t proc_flags;
+ uint32_t data_size;
+ uint32_t total_size;
+ uint32_t reserved[3];
+};
+
+void acrn_update_ucode(struct vcpu *vcpu, uint64_t v); uint64_t
+get_microcode_version(void);
+
+#endif
--
2.7.4




1 - 20 of 36191