Browse Source

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* i386: fix -M isapc with ubsan
* i386: add sha512, sm3, sm4 feature bits
* eif: fix Coverity issues
* i386/hvf: x2APIC support
* i386/hvf: fixes
* i386/tcg: fix 2-stage page walk
* eif: fix coverity issues
* rust: fix subproject warnings with new rust, avoid useless cmake fallback

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmcvEHYUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroNn4AgAl+GaD/fHHU+9TCyKRg1Ux/iTSkqh
# PBs76H2w879TDeuPkKZlnYqc7n85rlh1cJwQz01X79OFEeXP6oHiI9Q6qyflSxF0
# V+DrJhZc1CtZBChx9ZUMWUAWjYJFFjNwYA7/LLuLl6RfOm8bIJUWIhDjliJ4Bcea
# 5VI13OtTvYvVurRLUBXWU0inh9KLHIw4RlNgi8Pmb2wNXkPxENpWjsGqWH0jlKS5
# ZUNgTPx/eY5MDwKoAyif2gsdfJlxGxgkpz3Mic4EGE9cw1cRASI3tKb3KH61hNTE
# K21UI0+/+kv27cPnpZzYMDSkrJs7PEgVJ/70NRmAJySA76IG3XSsb5+xZg==
# =pI4/
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 09 Nov 2024 07:34:14 GMT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu:
  hw/i386/pc: Don't try to init PCI NICs if there is no PCI bus
  rust: qemu-api-macros: always process subprojects before dependencies
  i386/hvf: Removes duplicate/shadowed variables in hvf_vcpu_exec
  i386/hvf: Raise exception on error setting APICBASE
  i386/hvf: Fixes startup memory leak (vmcs caps)
  i386/hvf: Fix for UB in handling CPUID function 0xD
  i386/hvf: Integrates x2APIC support with hvf accel
  eif: cope with huge section sizes
  eif: cope with huge section offsets
  target/i386: Fix legacy page table walk
  rust: add meson_version to all subprojects
  target/i386/hvf: fix clang compilation warning
  target/i386: add sha512, sm3, sm4 feature bits

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Peter Maydell 9 months ago
parent
commit
f0cfd06786

+ 45 - 7
hw/core/eif.c

@@ -119,6 +119,10 @@ static bool read_eif_header(FILE *f, EifHeader *header, uint32_t *crc,
 
 
     for (int i = 0; i < MAX_SECTIONS; ++i) {
     for (int i = 0; i < MAX_SECTIONS; ++i) {
         header->section_sizes[i] = be64_to_cpu(header->section_sizes[i]);
         header->section_sizes[i] = be64_to_cpu(header->section_sizes[i]);
+        if (header->section_sizes[i] > SSIZE_MAX) {
+            error_setg(errp, "Invalid EIF image. Section size out of bounds");
+            return false;
+        }
     }
     }
 
 
     header->unused = be32_to_cpu(header->unused);
     header->unused = be32_to_cpu(header->unused);
@@ -278,7 +282,12 @@ static bool get_signature_fingerprint_sha384(FILE *eif, uint64_t size,
     struct cbor_load_result result;
     struct cbor_load_result result;
     bool ret = false;
     bool ret = false;
 
 
-    sig = g_malloc(size);
+    sig = g_try_malloc(size);
+    if (!sig) {
+        error_setg(errp, "Out of memory reading signature section");
+        goto cleanup;
+    }
+
     got = fread(sig, 1, size, eif);
     got = fread(sig, 1, size, eif);
     if ((uint64_t) got != size) {
     if ((uint64_t) got != size) {
         error_setg(errp, "Failed to read EIF signature section data");
         error_setg(errp, "Failed to read EIF signature section data");
@@ -320,7 +329,12 @@ static bool get_signature_fingerprint_sha384(FILE *eif, uint64_t size,
         error_setg(errp, "Invalid signature CBOR");
         error_setg(errp, "Invalid signature CBOR");
         goto cleanup;
         goto cleanup;
     }
     }
-    cert = g_malloc(len);
+    cert = g_try_malloc(len);
+    if (!cert) {
+        error_setg(errp, "Out of memory reading signature section");
+        goto cleanup;
+    }
+
     for (int i = 0; i < len; ++i) {
     for (int i = 0; i < len; ++i) {
         cbor_item_t *tmp = cbor_array_get(pair->value, i);
         cbor_item_t *tmp = cbor_array_get(pair->value, i);
         if (!tmp) {
         if (!tmp) {
@@ -466,6 +480,10 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
         EifSectionHeader hdr;
         EifSectionHeader hdr;
         uint16_t section_type;
         uint16_t section_type;
 
 
+        if (eif_header.section_offsets[i] > OFF_MAX) {
+            error_setg(errp, "Invalid EIF image. Section offset out of bounds");
+            goto cleanup;
+        }
         if (fseek(f, eif_header.section_offsets[i], SEEK_SET) != 0) {
         if (fseek(f, eif_header.section_offsets[i], SEEK_SET) != 0) {
             error_setg_errno(errp, errno, "Failed to offset to %" PRIu64 " in EIF file",
             error_setg_errno(errp, errno, "Failed to offset to %" PRIu64 " in EIF file",
                              eif_header.section_offsets[i]);
                              eif_header.section_offsets[i]);
@@ -499,7 +517,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
                 goto cleanup;
                 goto cleanup;
             }
             }
 
 
-            ptr = g_malloc(hdr.section_size);
+            ptr = g_try_malloc(hdr.section_size);
+            if (!ptr) {
+                error_setg(errp, "Out of memory reading kernel section");
+                goto cleanup;
+            }
 
 
             iov_ptr = g_malloc(sizeof(struct iovec));
             iov_ptr = g_malloc(sizeof(struct iovec));
             iov_ptr->iov_base = ptr;
             iov_ptr->iov_base = ptr;
@@ -524,7 +546,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
                 goto cleanup;
                 goto cleanup;
             }
             }
             size = hdr.section_size;
             size = hdr.section_size;
-            *cmdline = g_malloc(size + 1);
+            *cmdline = g_try_malloc(size + 1);
+            if (!*cmdline) {
+                error_setg(errp, "Out of memory reading command line section");
+                goto cleanup;
+            }
             if (!read_eif_cmdline(f, size, *cmdline, &crc, errp)) {
             if (!read_eif_cmdline(f, size, *cmdline, &crc, errp)) {
                 goto cleanup;
                 goto cleanup;
             }
             }
@@ -563,7 +589,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
                 }
                 }
             }
             }
 
 
-            ptr = g_malloc(hdr.section_size);
+            ptr = g_try_malloc(hdr.section_size);
+            if (!ptr) {
+                error_setg(errp, "Out of memory reading initrd section");
+                goto cleanup;
+            }
 
 
             iov_ptr = g_malloc(sizeof(struct iovec));
             iov_ptr = g_malloc(sizeof(struct iovec));
             iov_ptr->iov_base = ptr;
             iov_ptr->iov_base = ptr;
@@ -602,7 +632,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
             uint8_t *buf;
             uint8_t *buf;
             size_t got;
             size_t got;
             uint64_t size = hdr.section_size;
             uint64_t size = hdr.section_size;
-            buf = g_malloc(size);
+            buf = g_try_malloc(size);
+            if (!buf) {
+                error_setg(errp, "Out of memory reading unknown section");
+                goto cleanup;
+            }
             got = fread(buf, 1, size, f);
             got = fread(buf, 1, size, f);
             if ((uint64_t) got != size) {
             if ((uint64_t) got != size) {
                 g_free(buf);
                 g_free(buf);
@@ -658,7 +692,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
             goto cleanup;
             goto cleanup;
         }
         }
 
 
-        ptr = g_malloc(machine_initrd_size);
+        ptr = g_try_malloc(machine_initrd_size);
+        if (!ptr) {
+            error_setg(errp, "Out of memory reading initrd file");
+            goto cleanup;
+        }
 
 
         iov_ptr = g_malloc(sizeof(struct iovec));
         iov_ptr = g_malloc(sizeof(struct iovec));
         iov_ptr->iov_base = ptr;
         iov_ptr->iov_base = ptr;

+ 3 - 1
hw/i386/pc.c

@@ -1252,7 +1252,9 @@ void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus)
     }
     }
 
 
     /* Anything remaining should be a PCI NIC */
     /* Anything remaining should be a PCI NIC */
-    pci_init_nic_devices(pci_bus, mc->default_nic);
+    if (pci_bus) {
+        pci_init_nic_devices(pci_bus, mc->default_nic);
+    }
 
 
     rom_reset_order_override();
     rom_reset_order_override();
 }
 }

+ 4 - 0
include/qemu/osdep.h

@@ -297,6 +297,10 @@ void QEMU_ERROR("code path is reachable")
 #error building with G_DISABLE_ASSERT is not supported
 #error building with G_DISABLE_ASSERT is not supported
 #endif
 #endif
 
 
+#ifndef OFF_MAX
+#define OFF_MAX (sizeof (off_t) == 8 ? INT64_MAX : INT32_MAX)
+#endif
+
 #ifndef O_LARGEFILE
 #ifndef O_LARGEFILE
 #define O_LARGEFILE 0
 #define O_LARGEFILE 0
 #endif
 #endif

+ 4 - 0
rust/qemu-api-macros/meson.build

@@ -1,3 +1,7 @@
+subproject('proc-macro2-1-rs', required: true)
+subproject('quote-1-rs', required: true)
+subproject('syn-2-rs', required: true)
+
 quote_dep = dependency('quote-1-rs', native: true)
 quote_dep = dependency('quote-1-rs', native: true)
 syn_dep = dependency('syn-2-rs', native: true)
 syn_dep = dependency('syn-2-rs', native: true)
 proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)
 proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)

+ 1 - 0
subprojects/packagefiles/arbitrary-int-1-rs/meson.build

@@ -1,4 +1,5 @@
 project('arbitrary-int-1-rs', 'rust',
 project('arbitrary-int-1-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '1.2.7',
   version: '1.2.7',
   license: 'MIT',
   license: 'MIT',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/bilge-0.2-rs/meson.build

@@ -1,6 +1,7 @@
 project(
 project(
   'bilge-0.2-rs',
   'bilge-0.2-rs',
   'rust',
   'rust',
+  meson_version: '>=1.5.0',
   version : '0.2.0',
   version : '0.2.0',
   license : 'MIT or Apache-2.0',
   license : 'MIT or Apache-2.0',
 )
 )

+ 1 - 0
subprojects/packagefiles/bilge-impl-0.2-rs/meson.build

@@ -1,4 +1,5 @@
 project('bilge-impl-0.2-rs', 'rust',
 project('bilge-impl-0.2-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '0.2.0',
   version: '0.2.0',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/either-1-rs/meson.build

@@ -1,4 +1,5 @@
 project('either-1-rs', 'rust',
 project('either-1-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '1.12.0',
   version: '1.12.0',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/itertools-0.11-rs/meson.build

@@ -1,4 +1,5 @@
 project('itertools-0.11-rs', 'rust',
 project('itertools-0.11-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '0.11.0',
   version: '0.11.0',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/proc-macro-error-1-rs/meson.build

@@ -1,4 +1,5 @@
 project('proc-macro-error-1-rs', 'rust',
 project('proc-macro-error-1-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '1.0.4',
   version: '1.0.4',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build

@@ -1,4 +1,5 @@
 project('proc-macro-error-attr-1-rs', 'rust',
 project('proc-macro-error-attr-1-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '1.12.0',
   version: '1.12.0',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/proc-macro2-1-rs/meson.build

@@ -1,4 +1,5 @@
 project('proc-macro2-1-rs', 'rust',
 project('proc-macro2-1-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '1.0.84',
   version: '1.0.84',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/quote-1-rs/meson.build

@@ -1,4 +1,5 @@
 project('quote-1-rs', 'rust',
 project('quote-1-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '1.12.0',
   version: '1.12.0',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/syn-2-rs/meson.build

@@ -1,4 +1,5 @@
 project('syn-2-rs', 'rust',
 project('syn-2-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '2.0.66',
   version: '2.0.66',
   license: 'MIT OR Apache-2.0',
   license: 'MIT OR Apache-2.0',
   default_options: [])
   default_options: [])

+ 1 - 0
subprojects/packagefiles/unicode-ident-1-rs/meson.build

@@ -1,4 +1,5 @@
 project('unicode-ident-1-rs', 'rust',
 project('unicode-ident-1-rs', 'rust',
+  meson_version: '>=1.5.0',
   version: '1.0.12',
   version: '1.0.12',
   license: '(MIT OR Apache-2.0) AND Unicode-DFS-2016',
   license: '(MIT OR Apache-2.0) AND Unicode-DFS-2016',
   default_options: [])
   default_options: [])

+ 1 - 1
target/i386/cpu.c

@@ -1116,7 +1116,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
     [FEAT_7_1_EAX] = {
     [FEAT_7_1_EAX] = {
         .type = CPUID_FEATURE_WORD,
         .type = CPUID_FEATURE_WORD,
         .feat_names = {
         .feat_names = {
-            NULL, NULL, NULL, NULL,
+            "sha512", "sm3", "sm4", NULL,
             "avx-vnni", "avx512-bf16", NULL, "cmpccxadd",
             "avx-vnni", "avx512-bf16", NULL, "cmpccxadd",
             NULL, NULL, "fzrm", "fsrs",
             NULL, NULL, "fzrm", "fsrs",
             "fsrc", NULL, NULL, NULL,
             "fsrc", NULL, NULL, NULL,

+ 1 - 0
target/i386/cpu.h

@@ -346,6 +346,7 @@ typedef enum X86Seg {
 #define PG_MODE_PKE      (1 << 17)
 #define PG_MODE_PKE      (1 << 17)
 #define PG_MODE_PKS      (1 << 18)
 #define PG_MODE_PKS      (1 << 18)
 #define PG_MODE_SMEP     (1 << 19)
 #define PG_MODE_SMEP     (1 << 19)
+#define PG_MODE_PG       (1 << 20)
 
 
 #define MCG_CTL_P       (1ULL<<8)   /* MCG_CAP register available */
 #define MCG_CTL_P       (1ULL<<8)   /* MCG_CAP register available */
 #define MCG_SER_P       (1ULL<<24) /* MCA recovery/new status bits */
 #define MCG_SER_P       (1ULL<<24) /* MCA recovery/new status bits */

+ 3 - 4
target/i386/hvf/hvf.c

@@ -239,7 +239,9 @@ int hvf_arch_init_vcpu(CPUState *cpu)
     init_emu();
     init_emu();
     init_decoder();
     init_decoder();
 
 
-    hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
+    if (hvf_state->hvf_caps == NULL) {
+        hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
+    }
     env->hvf_mmio_buf = g_new(char, 4096);
     env->hvf_mmio_buf = g_new(char, 4096);
 
 
     if (x86cpu->vmware_cpuid_freq) {
     if (x86cpu->vmware_cpuid_freq) {
@@ -584,8 +586,6 @@ int hvf_vcpu_exec(CPUState *cpu)
             break;
             break;
         }
         }
         case EXIT_REASON_XSETBV: {
         case EXIT_REASON_XSETBV: {
-            X86CPU *x86_cpu = X86_CPU(cpu);
-            CPUX86State *env = &x86_cpu->env;
             uint32_t eax = (uint32_t)rreg(cpu->accel->fd, HV_X86_RAX);
             uint32_t eax = (uint32_t)rreg(cpu->accel->fd, HV_X86_RAX);
             uint32_t ecx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RCX);
             uint32_t ecx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RCX);
             uint32_t edx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RDX);
             uint32_t edx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RDX);
@@ -642,7 +642,6 @@ int hvf_vcpu_exec(CPUState *cpu)
                 break;
                 break;
             }
             }
             case 8: {
             case 8: {
-                X86CPU *x86_cpu = X86_CPU(cpu);
                 if (exit_qual & 0x10) {
                 if (exit_qual & 0x10) {
                     RRX(env, reg) = cpu_get_apic_tpr(x86_cpu->apic_state);
                     RRX(env, reg) = cpu_get_apic_tpr(x86_cpu->apic_state);
                 } else {
                 } else {

+ 4 - 4
target/i386/hvf/x86_cpuid.c

@@ -32,7 +32,7 @@
 static bool cached_xcr0;
 static bool cached_xcr0;
 static uint64_t supported_xcr0;
 static uint64_t supported_xcr0;
 
 
-static void cache_host_xcr0()
+static void cache_host_xcr0(void)
 {
 {
     if (cached_xcr0) {
     if (cached_xcr0) {
         return;
         return;
@@ -77,7 +77,7 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
         ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
         ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
              CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID |
              CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID |
              CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE |
              CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE |
-             CPUID_EXT_POPCNT | CPUID_EXT_AES |
+             CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_X2APIC |
              (supported_xcr0 ? CPUID_EXT_XSAVE : 0) |
              (supported_xcr0 ? CPUID_EXT_XSAVE : 0) |
              CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND;
              CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND;
         ecx |= CPUID_EXT_HYPERVISOR;
         ecx |= CPUID_EXT_HYPERVISOR;
@@ -119,8 +119,8 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
         eax = 0;
         eax = 0;
         break;
         break;
     case 0xD:
     case 0xD:
-        if (!supported_xcr0 ||
-            (idx > 1 && !(supported_xcr0 & (1 << idx)))) {
+        if (!supported_xcr0 || idx >= 63 ||
+            (idx > 1 && !(supported_xcr0 & (UINT64_C(1) << idx)))) {
             eax = ebx = ecx = edx = 0;
             eax = ebx = ecx = edx = 0;
             break;
             break;
         }
         }

+ 40 - 2
target/i386/hvf/x86_emu.c

@@ -663,6 +663,15 @@ static void exec_lods(CPUX86State *env, struct x86_decode *decode)
     env->eip += decode->len;
     env->eip += decode->len;
 }
 }
 
 
+static void raise_exception(CPUX86State *env, int exception_index,
+                            int error_code)
+{
+    env->exception_nr = exception_index;
+    env->error_code = error_code;
+    env->has_error_code = true;
+    env->exception_injected = 1;
+}
+
 void simulate_rdmsr(CPUX86State *env)
 void simulate_rdmsr(CPUX86State *env)
 {
 {
     X86CPU *cpu = env_archcpu(env);
     X86CPU *cpu = env_archcpu(env);
@@ -677,6 +686,17 @@ void simulate_rdmsr(CPUX86State *env)
     case MSR_IA32_APICBASE:
     case MSR_IA32_APICBASE:
         val = cpu_get_apic_base(cpu->apic_state);
         val = cpu_get_apic_base(cpu->apic_state);
         break;
         break;
+    case MSR_APIC_START ... MSR_APIC_END: {
+        int ret;
+        int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
+
+        ret = apic_msr_read(index, &val);
+        if (ret < 0) {
+            raise_exception(env, EXCP0D_GPF, 0);
+        }
+
+        break;
+    }
     case MSR_IA32_UCODE_REV:
     case MSR_IA32_UCODE_REV:
         val = cpu->ucode_rev;
         val = cpu->ucode_rev;
         break;
         break;
@@ -774,9 +794,27 @@ void simulate_wrmsr(CPUX86State *env)
     switch (msr) {
     switch (msr) {
     case MSR_IA32_TSC:
     case MSR_IA32_TSC:
         break;
         break;
-    case MSR_IA32_APICBASE:
-        cpu_set_apic_base(cpu->apic_state, data);
+    case MSR_IA32_APICBASE: {
+        int r;
+
+        r = cpu_set_apic_base(cpu->apic_state, data);
+        if (r < 0) {
+            raise_exception(env, EXCP0D_GPF, 0);
+        }
+
         break;
         break;
+    }
+    case MSR_APIC_START ... MSR_APIC_END: {
+        int ret;
+        int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
+
+        ret = apic_msr_write(index, data);
+        if (ret < 0) {
+            raise_exception(env, EXCP0D_GPF, 0);
+        }
+
+        break;
+    }
     case MSR_FSBASE:
     case MSR_FSBASE:
         wvmcs(cs->accel->fd, VMCS_GUEST_FS_BASE, data);
         wvmcs(cs->accel->fd, VMCS_GUEST_FS_BASE, data);
         break;
         break;

+ 1 - 1
target/i386/tcg/seg_helper.c

@@ -94,7 +94,7 @@ static uint32_t popl(StackAccess *sa)
 
 
 int get_pg_mode(CPUX86State *env)
 int get_pg_mode(CPUX86State *env)
 {
 {
-    int pg_mode = 0;
+    int pg_mode = PG_MODE_PG;
     if (!(env->cr[0] & CR0_PG_MASK)) {
     if (!(env->cr[0] & CR0_PG_MASK)) {
         return 0;
         return 0;
     }
     }

+ 1 - 1
target/i386/tcg/sysemu/excp_helper.c

@@ -298,7 +298,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
         /* combine pde and pte nx, user and rw protections */
         /* combine pde and pte nx, user and rw protections */
         ptep &= pte ^ PG_NX_MASK;
         ptep &= pte ^ PG_NX_MASK;
         page_size = 4096;
         page_size = 4096;
-    } else if (pg_mode) {
+    } else if (pg_mode & PG_MODE_PG) {
         /*
         /*
          * Page table level 2
          * Page table level 2
          */
          */