You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libshit/tools/qemu-7.2.0.patch

562 lines
21 KiB
Diff

diff --git a/linux-user/main.c b/linux-user/main.c
index a17fed045b..999b65bfc1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -123,6 +123,7 @@ static void usage(int exitcode);
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release;
+const char *qemu_execve_path;
#if !defined(TARGET_DEFAULT_STACK_SIZE)
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
@@ -362,6 +363,11 @@ static void handle_arg_guest_base(const char *arg)
have_guest_base = true;
}
+static void handle_arg_execve(const char *arg)
+{
+ qemu_execve_path = strdup(arg);
+}
+
static void handle_arg_reserved_va(const char *arg)
{
char *p;
@@ -464,6 +470,8 @@ static const struct qemu_argument arg_table[] = {
"uname", "set qemu uname release string to 'uname'"},
{"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
"address", "set guest_base address to 'address'"},
+ {"execve", "QEMU_EXECVE", true, handle_arg_execve,
+ "", "use this interpreter when a process calls execve()"},
{"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
"size", "reserve 'size' bytes for guest virtual address space"},
{"d", "QEMU_LOG", true, handle_arg_log,
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 10f5079331..d2c6919f60 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -321,7 +321,7 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
* It must be called with mmap_lock() held.
* Return -1 if error.
*/
-abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align)
+abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align, bool map_32bit)
{
void *ptr, *prev;
abi_ulong addr;
@@ -356,7 +356,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align)
* - shmat() with SHM_REMAP flag
*/
ptr = mmap(g2h_untagged(addr), size, PROT_NONE,
- MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+ MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE|(map_32bit?MAP_32BIT:0), -1, 0);
/* ENOMEM, if host address space has no memory */
if (ptr == MAP_FAILED) {
@@ -367,7 +367,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align)
This is used to modify the search algorithm below. */
repeat = (ptr == prev ? repeat + 1 : 0);
- if (h2g_valid(ptr + size - 1)) {
+ if (map_32bit ? h2g(ptr+size-1) == (uint32_t) (ptrdiff_t) (ptr+size-1): h2g_valid(ptr + size - 1)) {
addr = h2g(ptr);
if ((addr & (align - 1)) == 0) {
@@ -484,7 +484,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
if (!(flags & MAP_FIXED)) {
host_len = len + offset - host_offset;
host_len = HOST_PAGE_ALIGN(host_len);
- start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE);
+ start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE, flags & MAP_32BIT);
if (start == (abi_ulong)-1) {
errno = ENOMEM;
goto fail;
@@ -799,7 +799,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
} else if (flags & MREMAP_MAYMOVE) {
abi_ulong mmap_start;
- mmap_start = mmap_find_vma(0, new_size, TARGET_PAGE_SIZE);
+ mmap_start = mmap_find_vma(0, new_size, TARGET_PAGE_SIZE, flags & MAP_32BIT);
if (mmap_start == -1) {
errno = ENOMEM;
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 9ae5a812cd..8ab56ff3b6 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1086,6 +1086,9 @@ UNUSED static struct flags mmap_flags[] = {
#ifdef MAP_POPULATE
FLAG_TARGET(MAP_POPULATE),
#endif
+#ifdef TARGET_MAP_32BIT
+ FLAG_TARGET(MAP_32BIT),
+#endif
#ifdef TARGET_MAP_UNINITIALIZED
FLAG_TARGET(MAP_UNINITIALIZED),
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 24b25759be..9ce518bb7a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -166,6 +166,7 @@ struct file_clone_range {
#include <libdrm/drm.h>
#include <libdrm/i915_drm.h>
#endif
+#include <linux/binfmts.h>
#include "linux_loop.h"
#include "uname.h"
@@ -1058,7 +1059,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
{
abi_ulong target_rlim_swap;
rlim_t result;
-
+
target_rlim_swap = tswapal(target_rlim);
if (target_rlim_swap == TARGET_RLIM_INFINITY)
return RLIM_INFINITY;
@@ -1066,7 +1067,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
result = target_rlim_swap;
if (target_rlim_swap != (rlim_t)result)
return RLIM_INFINITY;
-
+
return result;
}
#endif
@@ -1076,13 +1077,13 @@ static inline abi_ulong host_to_target_rlim(rlim_t rlim)
{
abi_ulong target_rlim_swap;
abi_ulong result;
-
+
if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
target_rlim_swap = TARGET_RLIM_INFINITY;
else
target_rlim_swap = rlim;
result = tswapal(target_rlim_swap);
-
+
return result;
}
#endif
@@ -1809,9 +1810,9 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
abi_ulong target_cmsg_addr;
struct target_cmsghdr *target_cmsg, *target_cmsg_start;
socklen_t space = 0;
-
+
msg_controllen = tswapal(target_msgh->msg_controllen);
- if (msg_controllen < sizeof (struct target_cmsghdr))
+ if (msg_controllen < sizeof (struct target_cmsghdr))
goto the_end;
target_cmsg_addr = tswapal(target_msgh->msg_control);
target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
@@ -1897,7 +1898,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
socklen_t space = 0;
msg_controllen = tswapal(target_msgh->msg_controllen);
- if (msg_controllen < sizeof (struct target_cmsghdr))
+ if (msg_controllen < sizeof (struct target_cmsghdr))
goto the_end;
target_cmsg_addr = tswapal(target_msgh->msg_control);
target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
@@ -4591,7 +4592,7 @@ static inline abi_ulong do_shmat(CPUArchState *cpu_env,
abi_ulong mmap_start;
/* In order to use the host shmat, we need to honor host SHMLBA. */
- mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
+ mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba), false);
if (mmap_start == -1) {
errno = ENOMEM;
@@ -6015,6 +6016,9 @@ static const StructEntry struct_termios_def = {
};
static const bitmask_transtbl mmap_flags_tbl[] = {
+#ifdef TARGET_MAP_32BIT
+ { TARGET_MAP_32BIT, TARGET_MAP_32BIT, MAP_32BIT, MAP_32BIT },
+#endif
{ TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
{ TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
{ TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
@@ -6209,7 +6213,7 @@ abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
}
unlock_user_struct(target_ldt_info, ptr, 1);
- if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
+ if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
return -TARGET_EINVAL;
seg_32bit = ldt_info.flags & 1;
@@ -6287,7 +6291,7 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
lp = (uint32_t *)(gdt_table + idx);
entry_1 = tswap32(lp[0]);
entry_2 = tswap32(lp[1]);
-
+
read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
contents = (entry_2 >> 10) & 3;
seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
@@ -6303,8 +6307,8 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
(read_exec_only << 3) | (limit_in_pages << 4) |
(seg_not_present << 5) | (useable << 6) | (lm << 7);
limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
- base_addr = (entry_1 >> 16) |
- (entry_2 & 0xff000000) |
+ base_addr = (entry_1 >> 16) |
+ (entry_2 & 0xff000000) |
((entry_2 & 0xff) << 16);
target_ldt_info->base_addr = tswapal(base_addr);
target_ldt_info->limit = tswap32(limit);
@@ -8378,6 +8382,131 @@ static target_timer_t get_timer_id(abi_long arg)
return timerid;
}
+/* qemu_execve() Must return target values and target errnos.
+ *
+ * Although execve() is not an interruptible syscall it is
+ * a special case where we must use the safe_syscall wrapper:
+ * if we allow a signal to happen before we make the host
+ * syscall then we will 'lose' it, because at the point of
+ * execve the process leaves QEMU's control. So we use the
+ * safe syscall wrapper to ensure that we either take the
+ * signal as a guest signal, or else it does not happen
+ * before the execve completes and makes it the other
+ * program's problem.
+ */
+static abi_long qemu_execve(char *filename, char *argv[],
+ char *envp[])
+{
+ char *i_arg = NULL, *i_name = NULL;
+ char **new_argp;
+ int argc, fd, ret, i, offset = 5;
+ char *cp;
+ char buf[BINPRM_BUF_SIZE];
+
+ /* normal execve case */
+ if (qemu_execve_path == NULL || *qemu_execve_path == 0) {
+ return get_errno(safe_execve(filename, argv, envp));
+ }
+
+ for (argc = 0; argv[argc] != NULL; argc++) {
+ /* nothing */ ;
+ }
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ return get_errno(fd);
+ }
+
+ ret = read(fd, buf, BINPRM_BUF_SIZE);
+ if (ret == -1) {
+ close(fd);
+ return get_errno(ret);
+ }
+
+ /* if we have less than 2 bytes, we can guess it is not executable */
+ if (ret < 2) {
+ close(fd);
+ return -host_to_target_errno(ENOEXEC);
+ }
+
+ close(fd);
+
+ /* adapted from the kernel
+ * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_script.c
+ */
+ if ((buf[0] == '#') && (buf[1] == '!')) {
+ /*
+ * This section does the #! interpretation.
+ * Sorta complicated, but hopefully it will work. -TYT
+ */
+
+ buf[BINPRM_BUF_SIZE - 1] = '\0';
+ cp = strchr(buf, '\n');
+ if (cp == NULL) {
+ cp = buf + BINPRM_BUF_SIZE - 1;
+ }
+ *cp = '\0';
+ while (cp > buf) {
+ cp--;
+ if ((*cp == ' ') || (*cp == '\t')) {
+ *cp = '\0';
+ } else {
+ break;
+ }
+ }
+ for (cp = buf + 2; (*cp == ' ') || (*cp == '\t'); cp++) {
+ /* nothing */ ;
+ }
+ if (*cp == '\0') {
+ return -ENOEXEC; /* No interpreter name found */
+ }
+ i_name = cp;
+ i_arg = NULL;
+ for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
+ /* nothing */ ;
+ }
+ while ((*cp == ' ') || (*cp == '\t')) {
+ *cp++ = '\0';
+ }
+ if (*cp) {
+ i_arg = cp;
+ }
+
+ if (i_arg) {
+ offset += 2;
+ } else {
+ offset += 1;
+ }
+ }
+
+ new_argp = alloca((argc + offset + 1) * sizeof(void *));
+
+ /* Copy the original arguments with offset */
+ for (i = 0; i < argc; i++) {
+ new_argp[i + offset] = argv[i];
+ }
+
+ new_argp[0] = strdup(qemu_execve_path);
+ new_argp[1] = strdup("--execve");
+ new_argp[2] = strdup(qemu_execve_path);
+ new_argp[3] = strdup("-0");
+ new_argp[offset] = filename;
+ new_argp[argc + offset] = NULL;
+
+ if (i_name) {
+ new_argp[4] = i_name;
+ new_argp[5] = i_name;
+
+ if (i_arg) {
+ new_argp[6] = i_arg;
+ }
+ } else {
+ new_argp[4] = argv[0];
+ }
+
+ return get_errno(safe_execve(qemu_execve_path, new_argp, envp));
+}
+
static int target_to_host_cpu_mask(unsigned long *host_mask,
size_t host_size,
abi_ulong target_addr,
@@ -8922,20 +9051,10 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
if (!(p = lock_user_string(arg1)))
goto execve_efault;
- /* Although execve() is not an interruptible syscall it is
- * a special case where we must use the safe_syscall wrapper:
- * if we allow a signal to happen before we make the host
- * syscall then we will 'lose' it, because at the point of
- * execve the process leaves QEMU's control. So we use the
- * safe syscall wrapper to ensure that we either take the
- * signal as a guest signal, or else it does not happen
- * before the execve completes and makes it the other
- * program's problem.
- */
if (is_proc_myself(p, "exe")) {
- ret = get_errno(safe_execve(exec_path, argp, envp));
+ ret = qemu_execve(exec_path, argp, envp);
} else {
- ret = get_errno(safe_execve(p, argp, envp));
+ ret = qemu_execve(p, argp, envp);
}
unlock_user(p, arg1, 0);
@@ -11473,7 +11592,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
#if defined(TARGET_NR_fchownat)
case TARGET_NR_fchownat:
- if (!(p = lock_user_string(arg2)))
+ if (!(p = lock_user_string(arg2)))
return -TARGET_EFAULT;
ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
low2highgid(arg4), arg5));
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 77864de57f..c0bcfacd42 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1330,6 +1330,7 @@ struct target_winsize {
#else
#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */
#define TARGET_MAP_ANONYMOUS 0x20 /* don't use a file */
+#define TARGET_MAP_32BIT 0x40
#define TARGET_MAP_GROWSDOWN 0x0100 /* stack-like segment */
#define TARGET_MAP_DENYWRITE 0x0800 /* ETXTBSY */
#define TARGET_MAP_EXECUTABLE 0x1000 /* mark it as an executable */
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index 0280e76add..7586971298 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -27,6 +27,7 @@ void init_task_state(TaskState *ts);
void task_settid(TaskState *);
void stop_all_tasks(void);
extern const char *qemu_uname_release;
+extern const char *qemu_execve_path;
extern unsigned long mmap_min_addr;
typedef struct IOCTLEntry IOCTLEntry;
diff --git a/linux-user/user-mmap.h b/linux-user/user-mmap.h
index 480ce1c114..042bd299dd 100644
--- a/linux-user/user-mmap.h
+++ b/linux-user/user-mmap.h
@@ -28,7 +28,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice);
extern unsigned long last_brk;
extern abi_ulong mmap_next_start;
-abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
+abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong, bool);
void mmap_fork_start(void);
void mmap_fork_end(int child);
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 22b681ca37..8986804373 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1608,6 +1608,7 @@ typedef struct X86CPUDefinition {
int family;
int model;
int stepping;
+ int brand_id;
FeatureWordArray features;
const char *model_id;
const CPUCaches *const cache_info;
@@ -2093,6 +2094,54 @@ static const X86CPUDefinition builtin_x86_defs[] = {
.xlevel = 0,
.model_id = "",
},
+ {
+ /* http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0000F4A_K8_Clawhammer_CPUID.txt */
+ .name = "athlon-64",
+ .level = 1,
+ .vendor = CPUID_VENDOR_AMD,
+ .family = 15,
+ .model = 4,
+ .stepping = 10,
+ .features[FEAT_1_EDX] =
+ CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE |
+ CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE |
+ CPUID_CX8 | CPUID_APIC | CPUID_SEP |
+ CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
+ CPUID_PAT | CPUID_PSE36 | /*no: CPUID_PN |*/ CPUID_CLFLUSH |
+ /*no: CPUID_DTS | CPUID_ACPI |*/ CPUID_MMX |
+ CPUID_FXSR | CPUID_SSE | CPUID_SSE2,
+ .features[FEAT_8000_0001_EDX] =
+ (CPUID_EXT2_FPU | CPUID_EXT2_VME | CPUID_EXT2_DE | CPUID_EXT2_PSE |
+ CPUID_EXT2_TSC | CPUID_EXT2_MSR | CPUID_EXT2_PAE | CPUID_EXT2_MCE |
+ CPUID_EXT2_CX8 | CPUID_EXT2_APIC | CPUID_EXT2_SYSCALL |
+ CPUID_EXT2_MTRR | CPUID_EXT2_PGE | CPUID_EXT2_MCA | CPUID_EXT2_CMOV |
+ CPUID_EXT2_PAT | CPUID_EXT2_PSE36 | /*no: CPUID_EXT2_MP */
+ CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_MMX |
+ CPUID_EXT2_FXSR | /*no: CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1G | CPUID_EXT2_RTDSCP*/
+ CPUID_EXT2_LM | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_3DNOW) &
+ ~CPUID_EXT2_AMD_ALIASES,
+ /* todo cache info 0x80000005-6 */
+ .features[FEAT_8000_0007_EDX] = 0x0f, /*??*/
+ /*.phys_bits = 0x00003028,*/
+ .xlevel = 0x80000018,
+ .brand_id = 0x106,
+ .model_id = "AMD Athlon(tm) 64 Processor 2800+",
+ },
+ {
+ .name = "u3-64bit-minimal",
+ .level = 1,
+ .vendor = CPUID_VENDOR_AMD,
+ .family = 15,
+ .model = 4,
+ .stepping = 10,
+ .features[FEAT_1_EDX] =
+ PENTIUM2_FEATURES | PPRO_FEATURES | CPUID_CLFLUSH /*sse2?*/,
+ .features[FEAT_8000_0001_EDX] =
+ /* NX: amd: since amd64, intel: P4 Prescott+ */
+ CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_LM,
+ .xlevel = 0x80000018,
+ .model_id = "Fuck off",
+ },
{
.name = "athlon",
.level = 2,
@@ -4409,6 +4458,41 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
env->cpuid_version |= value & 0xf;
}
+static void x86_cpuid_version_get_brand_id(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int64_t value;
+
+ value = env->cpuid_brand_id;
+ visit_type_int(v, name, &value, errp);
+}
+
+static void x86_cpuid_version_set_brand_id(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ const int64_t min = 0;
+ const int64_t max = 0xffff;
+ int64_t value;
+
+ if (!visit_type_int(v, name, &value, errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
+ env->cpuid_brand_id = value;
+}
+
+
static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
@@ -5085,6 +5169,8 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model)
&error_abort);
object_property_set_str(OBJECT(cpu), "model-id", def->model_id,
&error_abort);
+ object_property_set_int(OBJECT(cpu), "brand-id", def->brand_id,
+ &error_abort);
for (w = 0; w < FEATURE_WORDS; w++) {
env->features[w] = def->features[w];
}
@@ -5691,7 +5777,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
break;
case 0x80000001:
*eax = env->cpuid_version;
- *ebx = 0;
+ *ebx = env->cpuid_brand_id;
*ecx = env->features[FEAT_8000_0001_ECX];
*edx = env->features[FEAT_8000_0001_EDX];
@@ -7158,6 +7244,9 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
object_class_property_add(oc, "stepping", "int",
x86_cpuid_version_get_stepping,
x86_cpuid_version_set_stepping, NULL, NULL);
+ object_class_property_add(oc, "brand-id", "int",
+ x86_cpuid_version_get_brand_id,
+ x86_cpuid_version_set_brand_id, NULL, NULL);
object_class_property_add_str(oc, "vendor",
x86_cpuid_get_vendor,
x86_cpuid_set_vendor);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index d4bc19577a..a8eff25d92 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1749,6 +1749,7 @@ typedef struct CPUArchState {
uint32_t cpuid_vendor2;
uint32_t cpuid_vendor3;
uint32_t cpuid_version;
+ uint32_t cpuid_brand_id;
FeatureWordArray features;
/* Features that were explicitly enabled/disabled */
FeatureWordArray user_features;