From nobody Fri May 3 19:48:41 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1544556426497784.2981363546476; Tue, 11 Dec 2018 11:27:06 -0800 (PST) Received: from localhost ([::1]:41125 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gWngK-00066k-Vk for importer@patchew.org; Tue, 11 Dec 2018 14:27:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43375) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gWnew-0005NT-34 for qemu-devel@nongnu.org; Tue, 11 Dec 2018 14:25:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gWnes-0003J8-UR for qemu-devel@nongnu.org; Tue, 11 Dec 2018 14:25:34 -0500 Received: from mx1.redhat.com ([209.132.183.28]:43764) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gWnes-0003In-MM for qemu-devel@nongnu.org; Tue, 11 Dec 2018 14:25:30 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CFDA330D02E0; Tue, 11 Dec 2018 19:25:29 +0000 (UTC) Received: from localhost (ovpn-116-63.gru2.redhat.com [10.97.116.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id 493051001947; Tue, 11 Dec 2018 19:25:29 +0000 (UTC) From: Eduardo Habkost To: qemu-devel@nongnu.org Date: Tue, 11 Dec 2018 17:25:27 -0200 Message-Id: <20181211192527.13254-1-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Tue, 11 Dec 2018 19:25:29 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH] x86: host-phys-bits-limit option X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrea Arcangeli , Eduardo Habkost , paul.c.lai@intel.com, Bandan Das , Yu Zhang , Igor Mammedov , Paolo Bonzini , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Some downstream distributions of QEMU set host-phys-bits=3Don by default. This worked very well for most use cases, because phys-bits really didn't have huge consequences. The only difference was on the CPUID data seen by guests, and on the handling of reserved bits. This changed in KVM commit 855feb673640 ("KVM: MMU: Add 5 level EPT & Shadow page table support"). Now choosing a large phys-bits value for a VM has bigger impact: it will make KVM use 5-level EPT even when it's not really necessary. This means using the host phys-bits value may not be the best choice. Management software could address this problem by manually configuring phys-bits depending on the size of the VM and the amount of MMIO address space required for hotplug. But this is not trivial to implement. However, there's another workaround that would work for most cases: keep using the host phys-bits value, but only if it's smaller than 48. This patch makes this possible by introducing a new "-cpu" option: "host-phys-bits-limit". Management software or users can make sure they will always use 4-level EPT using: "host-phys-bits=3Don,host-phys-bits-limit=3D48". This behavior is still not enabled by default because QEMU doesn't enable host-phys-bits=3Don by default. But users, management software, or downstream distributions may choose to change their defaults using the new option. Signed-off-by: Eduardo Habkost --- target/i386/cpu.h | 3 ++ target/i386/cpu.c | 5 ++ tests/acceptance/x86-phys-bits.py | 81 +++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 tests/acceptance/x86-phys-bits.py diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 9c52d0cbeb..a545b77c2c 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1457,6 +1457,9 @@ struct X86CPU { /* if true override the phys_bits value with a value read from the hos= t */ bool host_phys_bits; =20 + /* if set, limit maximum value for phys_bits when host_phys_bits is tr= ue */ + uint8_t host_phys_bits_limit; + /* Stop SMI delivery for migration compatibility with old machines */ bool kvm_no_smi_migration; =20 diff --git a/target/i386/cpu.c b/target/i386/cpu.c index f81d35e1f9..df200754a2 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5152,6 +5152,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Erro= r **errp) if (cpu->host_phys_bits) { /* The user asked for us to use the host physical bits */ cpu->phys_bits =3D host_phys_bits; + if (cpu->host_phys_bits_limit && + cpu->phys_bits > cpu->host_phys_bits_limit) { + cpu->phys_bits =3D cpu->host_phys_bits_limit; + } } =20 /* Print a warning if the user set it to a value that's not the @@ -5739,6 +5743,7 @@ static Property x86_cpu_properties[] =3D { DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0), DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), + DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit= , 0), DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true), DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, UINT32_MAX), DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, UINT32_MAX), diff --git a/tests/acceptance/x86-phys-bits.py b/tests/acceptance/x86-phys-= bits.py new file mode 100644 index 0000000000..ae85d7e4e7 --- /dev/null +++ b/tests/acceptance/x86-phys-bits.py @@ -0,0 +1,81 @@ +# Test for host-phys-bits-limit option +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import re + +from avocado_qemu import Test + +class HostPhysbits(Test): + """ + Check if `host-phys-bits` and `host-phys-bits` options work. + + :avocado: enable + :avocado: tags=3Dx86_64 + """ + + def cpu_qom_get(self, prop): + qom_path =3D self.vm.command('query-cpus')[0]['qom_path'] + return self.vm.command('qom-get', path=3Dqom_path, property=3Dprop) + + def cpu_phys_bits(self): + return self.cpu_qom_get('phys-bits') + + def host_phys_bits(self): + cpuinfo =3D open('/proc/cpuinfo', 'rb').read() + m =3D re.search(b'([0-9]+) bits physical', cpuinfo) + if m is None: + self.cancel("Couldn't read phys-bits from /proc/cpuinfo") + return int(m.group(1)) + + def setUp(self): + super(HostPhysbits, self).setUp() + self.vm.add_args('-S', '-machine', 'accel=3Dkvm:tcg') + self.vm.launch() + if not self.vm.command('query-kvm')['enabled']: + self.cancel("Test case requires KVM") + self.vm.shutdown() + + + def test_no_host_phys_bits(self): + # default should be phys-bits=3D40 if host-phys-bits=3Doff + self.vm.add_args('-cpu', 'qemu64,host-phys-bits=3Doff') + self.vm.launch() + self.assertEqual(self.cpu_phys_bits(), 40) + + def test_manual_phys_bits(self): + self.vm.add_args('-cpu', 'qemu64,host-phys-bits=3Doff,phys-bits=3D= 35') + self.vm.launch() + self.assertEqual(self.cpu_phys_bits(), 35) + + def test_host_phys_bits(self): + host_phys_bits =3D self.host_phys_bits() + self.vm.add_args('-cpu', 'qemu64,host-phys-bits=3Don') + self.vm.launch() + self.assertEqual(self.cpu_phys_bits(), host_phys_bits) + + def test_host_phys_bits_limit_high(self): + hbits =3D self.host_phys_bits() + self.vm.add_args('-cpu', 'qemu64,host-phys-bits=3Don,' + 'host-phys-bits-limit=3D%d' % (hbits + 1)) + self.vm.launch() + self.assertEqual(self.cpu_phys_bits(), hbits) + + def test_host_phys_bits_limit_equal(self): + hbits =3D self.host_phys_bits() + self.vm.add_args('-cpu', 'qemu64,host-phys-bits=3Don,' + 'host-phys-bits-limit=3D%d' % (hbits)) + self.vm.launch() + self.assertEqual(self.cpu_phys_bits(), hbits) + + def test_host_phys_bits_limit_low(self): + hbits =3D self.host_phys_bits() + self.vm.add_args('-cpu', 'qemu64,host-phys-bits=3Don,' + 'host-phys-bits-limit=3D%d' % (hbits - 1)) + self.vm.launch() + self.assertEqual(self.cpu_phys_bits(), hbits - 1) --=20 2.18.0.rc1.1.g3f1ff2140