From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-28.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65F3AC64E7B for ; Mon, 30 Nov 2020 22:48:45 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8F85920725 for ; Mon, 30 Nov 2020 22:48:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="v2smGPX3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8F85920725 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:50700 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kjryN-0006Gc-3k for qemu-devel@archiver.kernel.org; Mon, 30 Nov 2020 17:48:43 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:43930) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kjrwz-0005Q2-75 for qemu-devel@nongnu.org; Mon, 30 Nov 2020 17:47:17 -0500 Received: from mail-il1-x144.google.com ([2607:f8b0:4864:20::144]:39510) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kjrwr-0001fh-QW for qemu-devel@nongnu.org; Mon, 30 Nov 2020 17:47:15 -0500 Received: by mail-il1-x144.google.com with SMTP id q1so12989434ilt.6 for ; Mon, 30 Nov 2020 14:47:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=G5rjaftI6dY6s88IAQeEYVzVpVvd0lWvwcEiTSEvMaw=; b=v2smGPX3uuh3JWivUXNFNjbLaROAJL8dKJdECHnb2HQ2/L15B+njswoYcM1FpRIWhg 2CECwJLcir4IicwMIDQFHVoFf+OnnV3W4i0fY8YKIoJik1vyqjY4/wdw+WUXOU1Em/Aj BUJhSALt2YFl/p05RX2ccS0q3GBOYeee1rrcAhNNXi9kELNgN8jHoXY774KTy0MwgVWo Bs/SVYqGBVoPGdcWuifphMQF+q+aZBKF/Mysohl8Pbka3KuKo0cm81kJuDy4KcBVG925 j92wmwdU/VgwoXRdaMuKNzf/DD2MIvl+aKyhAHPDuFEyG2yQuPS0j86J1s++yrSXrfl3 Et2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=G5rjaftI6dY6s88IAQeEYVzVpVvd0lWvwcEiTSEvMaw=; b=nWr0xASyf0KlebZQtWKpIoy6zktiKcZzB8dejp3iJXvt13homO6NnPkqkn0gGcypHJ eh4Sal9fD3Hd81ucefGwAwfTXPhK1Je4c5/RtBQ3WxI7N7OqWEtcFxTaPcMsL50fHhBM 57awQLy/Vpjw0jvqI7mQxIl1wti6vpKcRENasxi+O0JsAmWVveFRyA/ECiBg+jypEu1g XEL4/Rjx6PlwPUYgKm2g0MQ+QFkV39KyetWi0MNifsVSbOuPTLBjz00QUZdsG32wZ6bw HfrrTDrf9sIfIilm+AZc+2CHMsOG5+wydOHwkEZF40ZaW8pPM9GxR7PanUgEt8L29dOH PeNw== X-Gm-Message-State: AOAM531u4jzHMlJtpLJLR7no3qRR7ffveM6lnjVOGaKYCS3Nf06vyKtd qmrpM0/w3pTKmiO84YDiqAqSi7NoxOSHkcJ81Fxotg== X-Google-Smtp-Source: ABdhPJwKH7UMnuEKLnD76GFS/5iBbWcwvocvqQp0iDq/FtoEwt1lG+Ggpy4njLEk5CjBZPgQO/1mnhRk0ajFYAWZkfU= X-Received: by 2002:a05:6e02:13e5:: with SMTP id w5mr20626728ilj.56.1606776427998; Mon, 30 Nov 2020 14:47:07 -0800 (PST) MIME-Version: 1.0 References: <20201126215017.41156-1-agraf@csgraf.de> <20201126215017.41156-3-agraf@csgraf.de> <20201127200054.GC56950@SPB-NB-133.local> <392c2465-157e-e15a-0a2c-2e3faa166d22@csgraf.de> In-Reply-To: From: Peter Collingbourne Date: Mon, 30 Nov 2020 14:46:56 -0800 Message-ID: Subject: Re: [PATCH 2/8] hvf: Move common code out To: Frank Yang Cc: Alexander Graf , Roman Bolshakov , Peter Maydell , Eduardo Habkost , Richard Henderson , qemu-devel , Cameron Esfahani , qemu-arm@nongnu.org, Claudio Fontana , Paolo Bonzini Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass client-ip=2607:f8b0:4864:20::144; envelope-from=pcc@google.com; helo=mail-il1-x144.google.com X-Spam_score_int: -175 X-Spam_score: -17.6 X-Spam_bar: ----------------- X-Spam_report: (-17.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, ENV_AND_HDR_SPF_MATCH=-0.5, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5, USER_IN_DEF_SPF_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" On Mon, Nov 30, 2020 at 12:56 PM Frank Yang wrote: > > > > On Mon, Nov 30, 2020 at 12:34 PM Alexander Graf wrote: >> >> Hi Frank, >> >> Thanks for the update :). Your previous email nudged me into the right d= irection. I previously had implemented WFI through the internal timer frame= work which performed way worse. > > Cool, glad it's helping. Also, Peter found out that the main thing keepin= g us from just using cntpct_el0 on the host directly and compare with cval = is that if we sleep, cval is going to be much < cntpct_el0 by the sleep tim= e. If we can get either the architecture or macos to read out the sleep tim= e then we might be able to not have to use a poll interval either! We tracked down the discrepancies between CNTPCT_EL0 on the guest vs on the host to the fact that CNTPCT_EL0 on the guest does not increment while the system is asleep and as such corresponds to mach_absolute_time() on the host (if you read the XNU sources you will see that mach_absolute_time() is implemented as CNTPCT_EL0 plus a constant representing the time spent asleep) while CNTPCT_EL0 on the host does increment while asleep. This patch switches the implementation over to using mach_absolute_time() instead of reading CNTPCT_EL0 directly: https://android-review.googlesource.com/c/platform/external/qemu/+/1514870 Peter >> >> Along the way, I stumbled over a few issues though. For starters, the si= gnal mask for SIG_IPI was not set correctly, so while pselect() would exit,= the signal would never get delivered to the thread! For a fix, check out >> >> https://patchew.org/QEMU/20201130030723.78326-1-agraf@csgraf.de/202011= 30030723.78326-4-agraf@csgraf.de/ >> > > Thanks, we'll take a look :) > >> >> Please also have a look at my latest stab at WFI emulation. It doesn't h= andle WFE (that's only relevant in overcommitted scenarios). But it does ha= ndle WFI and even does something similar to hlt polling, albeit not with an= adaptive threshold. >> >> Also, is there a particular reason you're working on this super interest= ing and useful code in a random downstream fork of QEMU? Wouldn't it be mor= e helpful to contribute to the upstream code base instead? > > We'd actually like to contribute upstream too :) We do want to maintain o= ur own downstream though; Android Emulator codebase needs to work solidly o= n macos and windows which has made keeping up with upstream difficult, and = staying on a previous version (2.12) with known quirks easier. (theres also= some android related customization relating to Qt Ui + different set of vi= rtual devices and snapshot support (incl. snapshots of graphics devices wit= h OpenGLES state tracking), which we hope to separate into other libraries/= processes, but its not insignificant) >> >> >> Alex >> >> >> On 30.11.20 21:15, Frank Yang wrote: >> >> Update: We're not quite sure how to compare the CNTV_CVAL and CNTVCT. Bu= t the high CPU usage seems to be mitigated by having a poll interval (like = KVM does) in handling WFI: >> >> https://android-review.googlesource.com/c/platform/external/qemu/+/15125= 01 >> >> This is loosely inspired by https://elixir.bootlin.com/linux/v5.10-rc6/s= ource/virt/kvm/kvm_main.c#L2766 which does seem to specify a poll interval. >> >> It would be cool if we could have a lightweight way to enter sleep and r= estart the vcpus precisely when CVAL passes, though. >> >> Frank >> >> >> On Fri, Nov 27, 2020 at 3:30 PM Frank Yang wrote: >>> >>> Hi all, >>> >>> +Peter Collingbourne >>> >>> I'm a developer on the Android Emulator, which is in a fork of QEMU. >>> >>> Peter and I have been working on an HVF Apple Silicon backend with an e= ye toward Android guests. >>> >>> We have gotten things to basically switch to Android userspace already = (logcat/shell and graphics available at least) >>> >>> Our strategy so far has been to import logic from the KVM implementatio= n and hook into QEMU's software devices that previously assumed to only wor= k with TCG, or have KVM-specific paths. >>> >>> Thanks to Alexander for the tip on the 36-bit address space limitation = btw; our way of addressing this is to still allow highmem but not put pci h= igh mmio so high. >>> >>> Also, note we have a sleep/signal based mechanism to deal with WFx, whi= ch might be worth looking into in Alexander's implementation as well: >>> >>> https://android-review.googlesource.com/c/platform/external/qemu/+/1512= 551 >>> >>> Patches so far, FYI: >>> >>> https://android-review.googlesource.com/c/platform/external/qemu/+/1513= 429/1 >>> https://android-review.googlesource.com/c/platform/external/qemu/+/1512= 554/3 >>> https://android-review.googlesource.com/c/platform/external/qemu/+/1512= 553/3 >>> https://android-review.googlesource.com/c/platform/external/qemu/+/1512= 552/3 >>> https://android-review.googlesource.com/c/platform/external/qemu/+/1512= 551/3 >>> >>> https://android.googlesource.com/platform/external/qemu/+/c17eb6a3ffd50= 047e9646aff6640b710cb8ff48a >>> https://android.googlesource.com/platform/external/qemu/+/74bed16de1afb= 41b7a7ab8da1d1861226c9db63b >>> https://android.googlesource.com/platform/external/qemu/+/eccd9e47ab2cc= b9003455e3bb721f57f9ebc3c01 >>> https://android.googlesource.com/platform/external/qemu/+/54fe3d67ed469= 8e85826537a4f49b2b9074b2228 >>> https://android.googlesource.com/platform/external/qemu/+/82ef91a6fede1= d1000f36be037ad4d58fbe0d102 >>> https://android.googlesource.com/platform/external/qemu/+/c28147aa7c74d= 98b858e99623d2fe46e74a379f6 >>> >>> Peter's also noticed that there are extra steps needed for M1's to allo= w TCG to work, as it involves JIT: >>> >>> https://android.googlesource.com/platform/external/qemu/+/740e3fe47f889= 26c6bda9abb22ee6eae1bc254a9 >>> >>> We'd appreciate any feedback/comments :) >>> >>> Best, >>> >>> Frank >>> >>> On Fri, Nov 27, 2020 at 1:57 PM Alexander Graf wrote: >>>> >>>> >>>> On 27.11.20 21:00, Roman Bolshakov wrote: >>>> > On Thu, Nov 26, 2020 at 10:50:11PM +0100, Alexander Graf wrote: >>>> >> Until now, Hypervisor.framework has only been available on x86_64 s= ystems. >>>> >> With Apple Silicon shipping now, it extends its reach to aarch64. T= o >>>> >> prepare for support for multiple architectures, let's move common c= ode out >>>> >> into its own accel directory. >>>> >> >>>> >> Signed-off-by: Alexander Graf >>>> >> --- >>>> >> MAINTAINERS | 9 +- >>>> >> accel/hvf/hvf-all.c | 56 +++++ >>>> >> accel/hvf/hvf-cpus.c | 468 +++++++++++++++++++++++++++++++= +++++ >>>> >> accel/hvf/meson.build | 7 + >>>> >> accel/meson.build | 1 + >>>> >> include/sysemu/hvf_int.h | 69 ++++++ >>>> >> target/i386/hvf/hvf-cpus.c | 131 ---------- >>>> >> target/i386/hvf/hvf-cpus.h | 25 -- >>>> >> target/i386/hvf/hvf-i386.h | 48 +--- >>>> >> target/i386/hvf/hvf.c | 360 +-------------------------- >>>> >> target/i386/hvf/meson.build | 1 - >>>> >> target/i386/hvf/x86hvf.c | 11 +- >>>> >> target/i386/hvf/x86hvf.h | 2 - >>>> >> 13 files changed, 619 insertions(+), 569 deletions(-) >>>> >> create mode 100644 accel/hvf/hvf-all.c >>>> >> create mode 100644 accel/hvf/hvf-cpus.c >>>> >> create mode 100644 accel/hvf/meson.build >>>> >> create mode 100644 include/sysemu/hvf_int.h >>>> >> delete mode 100644 target/i386/hvf/hvf-cpus.c >>>> >> delete mode 100644 target/i386/hvf/hvf-cpus.h >>>> >> >>>> >> diff --git a/MAINTAINERS b/MAINTAINERS >>>> >> index 68bc160f41..ca4b6d9279 100644 >>>> >> --- a/MAINTAINERS >>>> >> +++ b/MAINTAINERS >>>> >> @@ -444,9 +444,16 @@ M: Cameron Esfahani >>>> >> M: Roman Bolshakov >>>> >> W: https://wiki.qemu.org/Features/HVF >>>> >> S: Maintained >>>> >> -F: accel/stubs/hvf-stub.c >>>> > There was a patch for that in the RFC series from Claudio. >>>> >>>> >>>> Yeah, I'm not worried about this hunk :). >>>> >>>> >>>> > >>>> >> F: target/i386/hvf/ >>>> >> + >>>> >> +HVF >>>> >> +M: Cameron Esfahani >>>> >> +M: Roman Bolshakov >>>> >> +W: https://wiki.qemu.org/Features/HVF >>>> >> +S: Maintained >>>> >> +F: accel/hvf/ >>>> >> F: include/sysemu/hvf.h >>>> >> +F: include/sysemu/hvf_int.h >>>> >> >>>> >> WHPX CPUs >>>> >> M: Sunil Muthuswamy >>>> >> diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c >>>> >> new file mode 100644 >>>> >> index 0000000000..47d77a472a >>>> >> --- /dev/null >>>> >> +++ b/accel/hvf/hvf-all.c >>>> >> @@ -0,0 +1,56 @@ >>>> >> +/* >>>> >> + * QEMU Hypervisor.framework support >>>> >> + * >>>> >> + * This work is licensed under the terms of the GNU GPL, version 2= . See >>>> >> + * the COPYING file in the top-level directory. >>>> >> + * >>>> >> + * Contributions after 2012-01-13 are licensed under the terms of = the >>>> >> + * GNU GPL, version 2 or (at your option) any later version. >>>> >> + */ >>>> >> + >>>> >> +#include "qemu/osdep.h" >>>> >> +#include "qemu-common.h" >>>> >> +#include "qemu/error-report.h" >>>> >> +#include "sysemu/hvf.h" >>>> >> +#include "sysemu/hvf_int.h" >>>> >> +#include "sysemu/runstate.h" >>>> >> + >>>> >> +#include "qemu/main-loop.h" >>>> >> +#include "sysemu/accel.h" >>>> >> + >>>> >> +#include >>>> >> + >>>> >> +bool hvf_allowed; >>>> >> +HVFState *hvf_state; >>>> >> + >>>> >> +void assert_hvf_ok(hv_return_t ret) >>>> >> +{ >>>> >> + if (ret =3D=3D HV_SUCCESS) { >>>> >> + return; >>>> >> + } >>>> >> + >>>> >> + switch (ret) { >>>> >> + case HV_ERROR: >>>> >> + error_report("Error: HV_ERROR"); >>>> >> + break; >>>> >> + case HV_BUSY: >>>> >> + error_report("Error: HV_BUSY"); >>>> >> + break; >>>> >> + case HV_BAD_ARGUMENT: >>>> >> + error_report("Error: HV_BAD_ARGUMENT"); >>>> >> + break; >>>> >> + case HV_NO_RESOURCES: >>>> >> + error_report("Error: HV_NO_RESOURCES"); >>>> >> + break; >>>> >> + case HV_NO_DEVICE: >>>> >> + error_report("Error: HV_NO_DEVICE"); >>>> >> + break; >>>> >> + case HV_UNSUPPORTED: >>>> >> + error_report("Error: HV_UNSUPPORTED"); >>>> >> + break; >>>> >> + default: >>>> >> + error_report("Unknown Error"); >>>> >> + } >>>> >> + >>>> >> + abort(); >>>> >> +} >>>> >> diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c >>>> >> new file mode 100644 >>>> >> index 0000000000..f9bb5502b7 >>>> >> --- /dev/null >>>> >> +++ b/accel/hvf/hvf-cpus.c >>>> >> @@ -0,0 +1,468 @@ >>>> >> +/* >>>> >> + * Copyright 2008 IBM Corporation >>>> >> + * 2008 Red Hat, Inc. >>>> >> + * Copyright 2011 Intel Corporation >>>> >> + * Copyright 2016 Veertu, Inc. >>>> >> + * Copyright 2017 The Android Open Source Project >>>> >> + * >>>> >> + * QEMU Hypervisor.framework support >>>> >> + * >>>> >> + * This program is free software; you can redistribute it and/or >>>> >> + * modify it under the terms of version 2 of the GNU General Publi= c >>>> >> + * License as published by the Free Software Foundation. >>>> >> + * >>>> >> + * This program is distributed in the hope that it will be useful, >>>> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >>>> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the G= NU >>>> >> + * General Public License for more details. >>>> >> + * >>>> >> + * You should have received a copy of the GNU General Public Licen= se >>>> >> + * along with this program; if not, see . >>>> >> + * >>>> >> + * This file contain code under public domain from the hvdos proje= ct: >>>> >> + * https://github.com/mist64/hvdos >>>> >> + * >>>> >> + * Parts Copyright (c) 2011 NetApp, Inc. >>>> >> + * All rights reserved. >>>> >> + * >>>> >> + * Redistribution and use in source and binary forms, with or with= out >>>> >> + * modification, are permitted provided that the following conditi= ons >>>> >> + * are met: >>>> >> + * 1. Redistributions of source code must retain the above copyrig= ht >>>> >> + * notice, this list of conditions and the following disclaimer= . >>>> >> + * 2. Redistributions in binary form must reproduce the above copy= right >>>> >> + * notice, this list of conditions and the following disclaimer= in the >>>> >> + * documentation and/or other materials provided with the distr= ibution. >>>> >> + * >>>> >> + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND >>>> >> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED T= O, THE >>>> >> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICU= LAR PURPOSE >>>> >> + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS = BE LIABLE >>>> >> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CO= NSEQUENTIAL >>>> >> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU= TE GOODS >>>> >> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRU= PTION) >>>> >> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTR= ACT, STRICT >>>> >> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING = IN ANY WAY >>>> >> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBI= LITY OF >>>> >> + * SUCH DAMAGE. >>>> >> + */ >>>> >> + >>>> >> +#include "qemu/osdep.h" >>>> >> +#include "qemu/error-report.h" >>>> >> +#include "qemu/main-loop.h" >>>> >> +#include "exec/address-spaces.h" >>>> >> +#include "exec/exec-all.h" >>>> >> +#include "sysemu/cpus.h" >>>> >> +#include "sysemu/hvf.h" >>>> >> +#include "sysemu/hvf_int.h" >>>> >> +#include "sysemu/runstate.h" >>>> >> +#include "qemu/guest-random.h" >>>> >> + >>>> >> +#include >>>> >> + >>>> >> +/* Memory slots */ >>>> >> + >>>> >> +struct mac_slot { >>>> >> + int present; >>>> >> + uint64_t size; >>>> >> + uint64_t gpa_start; >>>> >> + uint64_t gva; >>>> >> +}; >>>> >> + >>>> >> +hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size) >>>> >> +{ >>>> >> + hvf_slot *slot; >>>> >> + int x; >>>> >> + for (x =3D 0; x < hvf_state->num_slots; ++x) { >>>> >> + slot =3D &hvf_state->slots[x]; >>>> >> + if (slot->size && start < (slot->start + slot->size) && >>>> >> + (start + size) > slot->start) { >>>> >> + return slot; >>>> >> + } >>>> >> + } >>>> >> + return NULL; >>>> >> +} >>>> >> + >>>> >> +struct mac_slot mac_slots[32]; >>>> >> + >>>> >> +static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t fla= gs) >>>> >> +{ >>>> >> + struct mac_slot *macslot; >>>> >> + hv_return_t ret; >>>> >> + >>>> >> + macslot =3D &mac_slots[slot->slot_id]; >>>> >> + >>>> >> + if (macslot->present) { >>>> >> + if (macslot->size !=3D slot->size) { >>>> >> + macslot->present =3D 0; >>>> >> + ret =3D hv_vm_unmap(macslot->gpa_start, macslot->size)= ; >>>> >> + assert_hvf_ok(ret); >>>> >> + } >>>> >> + } >>>> >> + >>>> >> + if (!slot->size) { >>>> >> + return 0; >>>> >> + } >>>> >> + >>>> >> + macslot->present =3D 1; >>>> >> + macslot->gpa_start =3D slot->start; >>>> >> + macslot->size =3D slot->size; >>>> >> + ret =3D hv_vm_map(slot->mem, slot->start, slot->size, flags); >>>> >> + assert_hvf_ok(ret); >>>> >> + return 0; >>>> >> +} >>>> >> + >>>> >> +static void hvf_set_phys_mem(MemoryRegionSection *section, bool ad= d) >>>> >> +{ >>>> >> + hvf_slot *mem; >>>> >> + MemoryRegion *area =3D section->mr; >>>> >> + bool writeable =3D !area->readonly && !area->rom_device; >>>> >> + hv_memory_flags_t flags; >>>> >> + >>>> >> + if (!memory_region_is_ram(area)) { >>>> >> + if (writeable) { >>>> >> + return; >>>> >> + } else if (!memory_region_is_romd(area)) { >>>> >> + /* >>>> >> + * If the memory device is not in romd_mode, then we a= ctually want >>>> >> + * to remove the hvf memory slot so all accesses will = trap. >>>> >> + */ >>>> >> + add =3D false; >>>> >> + } >>>> >> + } >>>> >> + >>>> >> + mem =3D hvf_find_overlap_slot( >>>> >> + section->offset_within_address_space, >>>> >> + int128_get64(section->size)); >>>> >> + >>>> >> + if (mem && add) { >>>> >> + if (mem->size =3D=3D int128_get64(section->size) && >>>> >> + mem->start =3D=3D section->offset_within_address_space= && >>>> >> + mem->mem =3D=3D (memory_region_get_ram_ptr(area) + >>>> >> + section->offset_within_region)) { >>>> >> + return; /* Same region was attempted to register, go a= way. */ >>>> >> + } >>>> >> + } >>>> >> + >>>> >> + /* Region needs to be reset. set the size to 0 and remap it. *= / >>>> >> + if (mem) { >>>> >> + mem->size =3D 0; >>>> >> + if (do_hvf_set_memory(mem, 0)) { >>>> >> + error_report("Failed to reset overlapping slot"); >>>> >> + abort(); >>>> >> + } >>>> >> + } >>>> >> + >>>> >> + if (!add) { >>>> >> + return; >>>> >> + } >>>> >> + >>>> >> + if (area->readonly || >>>> >> + (!memory_region_is_ram(area) && memory_region_is_romd(area= ))) { >>>> >> + flags =3D HV_MEMORY_READ | HV_MEMORY_EXEC; >>>> >> + } else { >>>> >> + flags =3D HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXE= C; >>>> >> + } >>>> >> + >>>> >> + /* Now make a new slot. */ >>>> >> + int x; >>>> >> + >>>> >> + for (x =3D 0; x < hvf_state->num_slots; ++x) { >>>> >> + mem =3D &hvf_state->slots[x]; >>>> >> + if (!mem->size) { >>>> >> + break; >>>> >> + } >>>> >> + } >>>> >> + >>>> >> + if (x =3D=3D hvf_state->num_slots) { >>>> >> + error_report("No free slots"); >>>> >> + abort(); >>>> >> + } >>>> >> + >>>> >> + mem->size =3D int128_get64(section->size); >>>> >> + mem->mem =3D memory_region_get_ram_ptr(area) + section->offset= _within_region; >>>> >> + mem->start =3D section->offset_within_address_space; >>>> >> + mem->region =3D area; >>>> >> + >>>> >> + if (do_hvf_set_memory(mem, flags)) { >>>> >> + error_report("Error registering new memory slot"); >>>> >> + abort(); >>>> >> + } >>>> >> +} >>>> >> + >>>> >> +static void hvf_set_dirty_tracking(MemoryRegionSection *section, b= ool on) >>>> >> +{ >>>> >> + hvf_slot *slot; >>>> >> + >>>> >> + slot =3D hvf_find_overlap_slot( >>>> >> + section->offset_within_address_space, >>>> >> + int128_get64(section->size)); >>>> >> + >>>> >> + /* protect region against writes; begin tracking it */ >>>> >> + if (on) { >>>> >> + slot->flags |=3D HVF_SLOT_LOG; >>>> >> + hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size, >>>> >> + HV_MEMORY_READ); >>>> >> + /* stop tracking region*/ >>>> >> + } else { >>>> >> + slot->flags &=3D ~HVF_SLOT_LOG; >>>> >> + hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size, >>>> >> + HV_MEMORY_READ | HV_MEMORY_WRITE); >>>> >> + } >>>> >> +} >>>> >> + >>>> >> +static void hvf_log_start(MemoryListener *listener, >>>> >> + MemoryRegionSection *section, int old, i= nt new) >>>> >> +{ >>>> >> + if (old !=3D 0) { >>>> >> + return; >>>> >> + } >>>> >> + >>>> >> + hvf_set_dirty_tracking(section, 1); >>>> >> +} >>>> >> + >>>> >> +static void hvf_log_stop(MemoryListener *listener, >>>> >> + MemoryRegionSection *section, int old, in= t new) >>>> >> +{ >>>> >> + if (new !=3D 0) { >>>> >> + return; >>>> >> + } >>>> >> + >>>> >> + hvf_set_dirty_tracking(section, 0); >>>> >> +} >>>> >> + >>>> >> +static void hvf_log_sync(MemoryListener *listener, >>>> >> + MemoryRegionSection *section) >>>> >> +{ >>>> >> + /* >>>> >> + * sync of dirty pages is handled elsewhere; just make sure we= keep >>>> >> + * tracking the region. >>>> >> + */ >>>> >> + hvf_set_dirty_tracking(section, 1); >>>> >> +} >>>> >> + >>>> >> +static void hvf_region_add(MemoryListener *listener, >>>> >> + MemoryRegionSection *section) >>>> >> +{ >>>> >> + hvf_set_phys_mem(section, true); >>>> >> +} >>>> >> + >>>> >> +static void hvf_region_del(MemoryListener *listener, >>>> >> + MemoryRegionSection *section) >>>> >> +{ >>>> >> + hvf_set_phys_mem(section, false); >>>> >> +} >>>> >> + >>>> >> +static MemoryListener hvf_memory_listener =3D { >>>> >> + .priority =3D 10, >>>> >> + .region_add =3D hvf_region_add, >>>> >> + .region_del =3D hvf_region_del, >>>> >> + .log_start =3D hvf_log_start, >>>> >> + .log_stop =3D hvf_log_stop, >>>> >> + .log_sync =3D hvf_log_sync, >>>> >> +}; >>>> >> + >>>> >> +static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu= _data arg) >>>> >> +{ >>>> >> + if (!cpu->vcpu_dirty) { >>>> >> + hvf_get_registers(cpu); >>>> >> + cpu->vcpu_dirty =3D true; >>>> >> + } >>>> >> +} >>>> >> + >>>> >> +static void hvf_cpu_synchronize_state(CPUState *cpu) >>>> >> +{ >>>> >> + if (!cpu->vcpu_dirty) { >>>> >> + run_on_cpu(cpu, do_hvf_cpu_synchronize_state, RUN_ON_CPU_N= ULL); >>>> >> + } >>>> >> +} >>>> >> + >>>> >> +static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu, >>>> >> + run_on_cpu_data arg) >>>> >> +{ >>>> >> + hvf_put_registers(cpu); >>>> >> + cpu->vcpu_dirty =3D false; >>>> >> +} >>>> >> + >>>> >> +static void hvf_cpu_synchronize_post_reset(CPUState *cpu) >>>> >> +{ >>>> >> + run_on_cpu(cpu, do_hvf_cpu_synchronize_post_reset, RUN_ON_CPU_= NULL); >>>> >> +} >>>> >> + >>>> >> +static void do_hvf_cpu_synchronize_post_init(CPUState *cpu, >>>> >> + run_on_cpu_data arg) >>>> >> +{ >>>> >> + hvf_put_registers(cpu); >>>> >> + cpu->vcpu_dirty =3D false; >>>> >> +} >>>> >> + >>>> >> +static void hvf_cpu_synchronize_post_init(CPUState *cpu) >>>> >> +{ >>>> >> + run_on_cpu(cpu, do_hvf_cpu_synchronize_post_init, RUN_ON_CPU_N= ULL); >>>> >> +} >>>> >> + >>>> >> +static void do_hvf_cpu_synchronize_pre_loadvm(CPUState *cpu, >>>> >> + run_on_cpu_data arg) >>>> >> +{ >>>> >> + cpu->vcpu_dirty =3D true; >>>> >> +} >>>> >> + >>>> >> +static void hvf_cpu_synchronize_pre_loadvm(CPUState *cpu) >>>> >> +{ >>>> >> + run_on_cpu(cpu, do_hvf_cpu_synchronize_pre_loadvm, RUN_ON_CPU_= NULL); >>>> >> +} >>>> >> + >>>> >> +static void hvf_vcpu_destroy(CPUState *cpu) >>>> >> +{ >>>> >> + hv_return_t ret =3D hv_vcpu_destroy(cpu->hvf_fd); >>>> >> + assert_hvf_ok(ret); >>>> >> + >>>> >> + hvf_arch_vcpu_destroy(cpu); >>>> >> +} >>>> >> + >>>> >> +static void dummy_signal(int sig) >>>> >> +{ >>>> >> +} >>>> >> + >>>> >> +static int hvf_init_vcpu(CPUState *cpu) >>>> >> +{ >>>> >> + int r; >>>> >> + >>>> >> + /* init cpu signals */ >>>> >> + sigset_t set; >>>> >> + struct sigaction sigact; >>>> >> + >>>> >> + memset(&sigact, 0, sizeof(sigact)); >>>> >> + sigact.sa_handler =3D dummy_signal; >>>> >> + sigaction(SIG_IPI, &sigact, NULL); >>>> >> + >>>> >> + pthread_sigmask(SIG_BLOCK, NULL, &set); >>>> >> + sigdelset(&set, SIG_IPI); >>>> >> + >>>> >> +#ifdef __aarch64__ >>>> >> + r =3D hv_vcpu_create(&cpu->hvf_fd, (hv_vcpu_exit_t **)&cpu->hv= f_exit, NULL); >>>> >> +#else >>>> >> + r =3D hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFA= ULT); >>>> >> +#endif >>>> > I think the first __aarch64__ bit fits better to arm part of the ser= ies. >>>> >>>> >>>> Oops. Thanks for catching it! Yes, absolutely. It should be part of th= e >>>> ARM enablement. >>>> >>>> >>>> > >>>> >> + cpu->vcpu_dirty =3D 1; >>>> >> + assert_hvf_ok(r); >>>> >> + >>>> >> + return hvf_arch_init_vcpu(cpu); >>>> >> +} >>>> >> + >>>> >> +/* >>>> >> + * The HVF-specific vCPU thread function. This one should only run= when the host >>>> >> + * CPU supports the VMX "unrestricted guest" feature. >>>> >> + */ >>>> >> +static void *hvf_cpu_thread_fn(void *arg) >>>> >> +{ >>>> >> + CPUState *cpu =3D arg; >>>> >> + >>>> >> + int r; >>>> >> + >>>> >> + assert(hvf_enabled()); >>>> >> + >>>> >> + rcu_register_thread(); >>>> >> + >>>> >> + qemu_mutex_lock_iothread(); >>>> >> + qemu_thread_get_self(cpu->thread); >>>> >> + >>>> >> + cpu->thread_id =3D qemu_get_thread_id(); >>>> >> + cpu->can_do_io =3D 1; >>>> >> + current_cpu =3D cpu; >>>> >> + >>>> >> + hvf_init_vcpu(cpu); >>>> >> + >>>> >> + /* signal CPU creation */ >>>> >> + cpu_thread_signal_created(cpu); >>>> >> + qemu_guest_random_seed_thread_part2(cpu->random_seed); >>>> >> + >>>> >> + do { >>>> >> + if (cpu_can_run(cpu)) { >>>> >> + r =3D hvf_vcpu_exec(cpu); >>>> >> + if (r =3D=3D EXCP_DEBUG) { >>>> >> + cpu_handle_guest_debug(cpu); >>>> >> + } >>>> >> + } >>>> >> + qemu_wait_io_event(cpu); >>>> >> + } while (!cpu->unplug || cpu_can_run(cpu)); >>>> >> + >>>> >> + hvf_vcpu_destroy(cpu); >>>> >> + cpu_thread_signal_destroyed(cpu); >>>> >> + qemu_mutex_unlock_iothread(); >>>> >> + rcu_unregister_thread(); >>>> >> + return NULL; >>>> >> +} >>>> >> + >>>> >> +static void hvf_start_vcpu_thread(CPUState *cpu) >>>> >> +{ >>>> >> + char thread_name[VCPU_THREAD_NAME_SIZE]; >>>> >> + >>>> >> + /* >>>> >> + * HVF currently does not support TCG, and only runs in >>>> >> + * unrestricted-guest mode. >>>> >> + */ >>>> >> + assert(hvf_enabled()); >>>> >> + >>>> >> + cpu->thread =3D g_malloc0(sizeof(QemuThread)); >>>> >> + cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); >>>> >> + qemu_cond_init(cpu->halt_cond); >>>> >> + >>>> >> + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", >>>> >> + cpu->cpu_index); >>>> >> + qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn= , >>>> >> + cpu, QEMU_THREAD_JOINABLE); >>>> >> +} >>>> >> + >>>> >> +static const CpusAccel hvf_cpus =3D { >>>> >> + .create_vcpu_thread =3D hvf_start_vcpu_thread, >>>> >> + >>>> >> + .synchronize_post_reset =3D hvf_cpu_synchronize_post_reset, >>>> >> + .synchronize_post_init =3D hvf_cpu_synchronize_post_init, >>>> >> + .synchronize_state =3D hvf_cpu_synchronize_state, >>>> >> + .synchronize_pre_loadvm =3D hvf_cpu_synchronize_pre_loadvm, >>>> >> +}; >>>> >> + >>>> >> +static int hvf_accel_init(MachineState *ms) >>>> >> +{ >>>> >> + int x; >>>> >> + hv_return_t ret; >>>> >> + HVFState *s; >>>> >> + >>>> >> + ret =3D hv_vm_create(HV_VM_DEFAULT); >>>> >> + assert_hvf_ok(ret); >>>> >> + >>>> >> + s =3D g_new0(HVFState, 1); >>>> >> + >>>> >> + s->num_slots =3D 32; >>>> >> + for (x =3D 0; x < s->num_slots; ++x) { >>>> >> + s->slots[x].size =3D 0; >>>> >> + s->slots[x].slot_id =3D x; >>>> >> + } >>>> >> + >>>> >> + hvf_state =3D s; >>>> >> + memory_listener_register(&hvf_memory_listener, &address_space_= memory); >>>> >> + cpus_register_accel(&hvf_cpus); >>>> >> + return 0; >>>> >> +} >>>> >> + >>>> >> +static void hvf_accel_class_init(ObjectClass *oc, void *data) >>>> >> +{ >>>> >> + AccelClass *ac =3D ACCEL_CLASS(oc); >>>> >> + ac->name =3D "HVF"; >>>> >> + ac->init_machine =3D hvf_accel_init; >>>> >> + ac->allowed =3D &hvf_allowed; >>>> >> +} >>>> >> + >>>> >> +static const TypeInfo hvf_accel_type =3D { >>>> >> + .name =3D TYPE_HVF_ACCEL, >>>> >> + .parent =3D TYPE_ACCEL, >>>> >> + .class_init =3D hvf_accel_class_init, >>>> >> +}; >>>> >> + >>>> >> +static void hvf_type_init(void) >>>> >> +{ >>>> >> + type_register_static(&hvf_accel_type); >>>> >> +} >>>> >> + >>>> >> +type_init(hvf_type_init); >>>> >> diff --git a/accel/hvf/meson.build b/accel/hvf/meson.build >>>> >> new file mode 100644 >>>> >> index 0000000000..dfd6b68dc7 >>>> >> --- /dev/null >>>> >> +++ b/accel/hvf/meson.build >>>> >> @@ -0,0 +1,7 @@ >>>> >> +hvf_ss =3D ss.source_set() >>>> >> +hvf_ss.add(files( >>>> >> + 'hvf-all.c', >>>> >> + 'hvf-cpus.c', >>>> >> +)) >>>> >> + >>>> >> +specific_ss.add_all(when: 'CONFIG_HVF', if_true: hvf_ss) >>>> >> diff --git a/accel/meson.build b/accel/meson.build >>>> >> index b26cca227a..6de12ce5d5 100644 >>>> >> --- a/accel/meson.build >>>> >> +++ b/accel/meson.build >>>> >> @@ -1,5 +1,6 @@ >>>> >> softmmu_ss.add(files('accel.c')) >>>> >> >>>> >> +subdir('hvf') >>>> >> subdir('qtest') >>>> >> subdir('kvm') >>>> >> subdir('tcg') >>>> >> diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h >>>> >> new file mode 100644 >>>> >> index 0000000000..de9bad23a8 >>>> >> --- /dev/null >>>> >> +++ b/include/sysemu/hvf_int.h >>>> >> @@ -0,0 +1,69 @@ >>>> >> +/* >>>> >> + * QEMU Hypervisor.framework (HVF) support >>>> >> + * >>>> >> + * This work is licensed under the terms of the GNU GPL, version 2= or later. >>>> >> + * See the COPYING file in the top-level directory. >>>> >> + * >>>> >> + */ >>>> >> + >>>> >> +/* header to be included in HVF-specific code */ >>>> >> + >>>> >> +#ifndef HVF_INT_H >>>> >> +#define HVF_INT_H >>>> >> + >>>> >> +#include >>>> >> + >>>> >> +#define HVF_MAX_VCPU 0x10 >>>> >> + >>>> >> +extern struct hvf_state hvf_global; >>>> >> + >>>> >> +struct hvf_vm { >>>> >> + int id; >>>> >> + struct hvf_vcpu_state *vcpus[HVF_MAX_VCPU]; >>>> >> +}; >>>> >> + >>>> >> +struct hvf_state { >>>> >> + uint32_t version; >>>> >> + struct hvf_vm *vm; >>>> >> + uint64_t mem_quota; >>>> >> +}; >>>> >> + >>>> >> +/* hvf_slot flags */ >>>> >> +#define HVF_SLOT_LOG (1 << 0) >>>> >> + >>>> >> +typedef struct hvf_slot { >>>> >> + uint64_t start; >>>> >> + uint64_t size; >>>> >> + uint8_t *mem; >>>> >> + int slot_id; >>>> >> + uint32_t flags; >>>> >> + MemoryRegion *region; >>>> >> +} hvf_slot; >>>> >> + >>>> >> +typedef struct hvf_vcpu_caps { >>>> >> + uint64_t vmx_cap_pinbased; >>>> >> + uint64_t vmx_cap_procbased; >>>> >> + uint64_t vmx_cap_procbased2; >>>> >> + uint64_t vmx_cap_entry; >>>> >> + uint64_t vmx_cap_exit; >>>> >> + uint64_t vmx_cap_preemption_timer; >>>> >> +} hvf_vcpu_caps; >>>> >> + >>>> >> +struct HVFState { >>>> >> + AccelState parent; >>>> >> + hvf_slot slots[32]; >>>> >> + int num_slots; >>>> >> + >>>> >> + hvf_vcpu_caps *hvf_caps; >>>> >> +}; >>>> >> +extern HVFState *hvf_state; >>>> >> + >>>> >> +void assert_hvf_ok(hv_return_t ret); >>>> >> +int hvf_get_registers(CPUState *cpu); >>>> >> +int hvf_put_registers(CPUState *cpu); >>>> >> +int hvf_arch_init_vcpu(CPUState *cpu); >>>> >> +void hvf_arch_vcpu_destroy(CPUState *cpu); >>>> >> +int hvf_vcpu_exec(CPUState *cpu); >>>> >> +hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); >>>> >> + >>>> >> +#endif >>>> >> diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/hvf/hvf-cpus.= c >>>> >> deleted file mode 100644 >>>> >> index 817b3d7452..0000000000 >>>> >> --- a/target/i386/hvf/hvf-cpus.c >>>> >> +++ /dev/null >>>> >> @@ -1,131 +0,0 @@ >>>> >> -/* >>>> >> - * Copyright 2008 IBM Corporation >>>> >> - * 2008 Red Hat, Inc. >>>> >> - * Copyright 2011 Intel Corporation >>>> >> - * Copyright 2016 Veertu, Inc. >>>> >> - * Copyright 2017 The Android Open Source Project >>>> >> - * >>>> >> - * QEMU Hypervisor.framework support >>>> >> - * >>>> >> - * This program is free software; you can redistribute it and/or >>>> >> - * modify it under the terms of version 2 of the GNU General Publi= c >>>> >> - * License as published by the Free Software Foundation. >>>> >> - * >>>> >> - * This program is distributed in the hope that it will be useful, >>>> >> - * but WITHOUT ANY WARRANTY; without even the implied warranty of >>>> >> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the G= NU >>>> >> - * General Public License for more details. >>>> >> - * >>>> >> - * You should have received a copy of the GNU General Public Licen= se >>>> >> - * along with this program; if not, see . >>>> >> - * >>>> >> - * This file contain code under public domain from the hvdos proje= ct: >>>> >> - * https://github.com/mist64/hvdos >>>> >> - * >>>> >> - * Parts Copyright (c) 2011 NetApp, Inc. >>>> >> - * All rights reserved. >>>> >> - * >>>> >> - * Redistribution and use in source and binary forms, with or with= out >>>> >> - * modification, are permitted provided that the following conditi= ons >>>> >> - * are met: >>>> >> - * 1. Redistributions of source code must retain the above copyrig= ht >>>> >> - * notice, this list of conditions and the following disclaimer= . >>>> >> - * 2. Redistributions in binary form must reproduce the above copy= right >>>> >> - * notice, this list of conditions and the following disclaimer= in the >>>> >> - * documentation and/or other materials provided with the distr= ibution. >>>> >> - * >>>> >> - * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND >>>> >> - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED T= O, THE >>>> >> - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICU= LAR PURPOSE >>>> >> - * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS = BE LIABLE >>>> >> - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CO= NSEQUENTIAL >>>> >> - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU= TE GOODS >>>> >> - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRU= PTION) >>>> >> - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTR= ACT, STRICT >>>> >> - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING = IN ANY WAY >>>> >> - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBI= LITY OF >>>> >> - * SUCH DAMAGE. >>>> >> - */ >>>> >> - >>>> >> -#include "qemu/osdep.h" >>>> >> -#include "qemu/error-report.h" >>>> >> -#include "qemu/main-loop.h" >>>> >> -#include "sysemu/hvf.h" >>>> >> -#include "sysemu/runstate.h" >>>> >> -#include "target/i386/cpu.h" >>>> >> -#include "qemu/guest-random.h" >>>> >> - >>>> >> -#include "hvf-cpus.h" >>>> >> - >>>> >> -/* >>>> >> - * The HVF-specific vCPU thread function. This one should only run= when the host >>>> >> - * CPU supports the VMX "unrestricted guest" feature. >>>> >> - */ >>>> >> -static void *hvf_cpu_thread_fn(void *arg) >>>> >> -{ >>>> >> - CPUState *cpu =3D arg; >>>> >> - >>>> >> - int r; >>>> >> - >>>> >> - assert(hvf_enabled()); >>>> >> - >>>> >> - rcu_register_thread(); >>>> >> - >>>> >> - qemu_mutex_lock_iothread(); >>>> >> - qemu_thread_get_self(cpu->thread); >>>> >> - >>>> >> - cpu->thread_id =3D qemu_get_thread_id(); >>>> >> - cpu->can_do_io =3D 1; >>>> >> - current_cpu =3D cpu; >>>> >> - >>>> >> - hvf_init_vcpu(cpu); >>>> >> - >>>> >> - /* signal CPU creation */ >>>> >> - cpu_thread_signal_created(cpu); >>>> >> - qemu_guest_random_seed_thread_part2(cpu->random_seed); >>>> >> - >>>> >> - do { >>>> >> - if (cpu_can_run(cpu)) { >>>> >> - r =3D hvf_vcpu_exec(cpu); >>>> >> - if (r =3D=3D EXCP_DEBUG) { >>>> >> - cpu_handle_guest_debug(cpu); >>>> >> - } >>>> >> - } >>>> >> - qemu_wait_io_event(cpu); >>>> >> - } while (!cpu->unplug || cpu_can_run(cpu)); >>>> >> - >>>> >> - hvf_vcpu_destroy(cpu); >>>> >> - cpu_thread_signal_destroyed(cpu); >>>> >> - qemu_mutex_unlock_iothread(); >>>> >> - rcu_unregister_thread(); >>>> >> - return NULL; >>>> >> -} >>>> >> - >>>> >> -static void hvf_start_vcpu_thread(CPUState *cpu) >>>> >> -{ >>>> >> - char thread_name[VCPU_THREAD_NAME_SIZE]; >>>> >> - >>>> >> - /* >>>> >> - * HVF currently does not support TCG, and only runs in >>>> >> - * unrestricted-guest mode. >>>> >> - */ >>>> >> - assert(hvf_enabled()); >>>> >> - >>>> >> - cpu->thread =3D g_malloc0(sizeof(QemuThread)); >>>> >> - cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); >>>> >> - qemu_cond_init(cpu->halt_cond); >>>> >> - >>>> >> - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", >>>> >> - cpu->cpu_index); >>>> >> - qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn= , >>>> >> - cpu, QEMU_THREAD_JOINABLE); >>>> >> -} >>>> >> - >>>> >> -const CpusAccel hvf_cpus =3D { >>>> >> - .create_vcpu_thread =3D hvf_start_vcpu_thread, >>>> >> - >>>> >> - .synchronize_post_reset =3D hvf_cpu_synchronize_post_reset, >>>> >> - .synchronize_post_init =3D hvf_cpu_synchronize_post_init, >>>> >> - .synchronize_state =3D hvf_cpu_synchronize_state, >>>> >> - .synchronize_pre_loadvm =3D hvf_cpu_synchronize_pre_loadvm, >>>> >> -}; >>>> >> diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-cpus.= h >>>> >> deleted file mode 100644 >>>> >> index ced31b82c0..0000000000 >>>> >> --- a/target/i386/hvf/hvf-cpus.h >>>> >> +++ /dev/null >>>> >> @@ -1,25 +0,0 @@ >>>> >> -/* >>>> >> - * Accelerator CPUS Interface >>>> >> - * >>>> >> - * Copyright 2020 SUSE LLC >>>> >> - * >>>> >> - * This work is licensed under the terms of the GNU GPL, version 2= or later. >>>> >> - * See the COPYING file in the top-level directory. >>>> >> - */ >>>> >> - >>>> >> -#ifndef HVF_CPUS_H >>>> >> -#define HVF_CPUS_H >>>> >> - >>>> >> -#include "sysemu/cpus.h" >>>> >> - >>>> >> -extern const CpusAccel hvf_cpus; >>>> >> - >>>> >> -int hvf_init_vcpu(CPUState *); >>>> >> -int hvf_vcpu_exec(CPUState *); >>>> >> -void hvf_cpu_synchronize_state(CPUState *); >>>> >> -void hvf_cpu_synchronize_post_reset(CPUState *); >>>> >> -void hvf_cpu_synchronize_post_init(CPUState *); >>>> >> -void hvf_cpu_synchronize_pre_loadvm(CPUState *); >>>> >> -void hvf_vcpu_destroy(CPUState *); >>>> >> - >>>> >> -#endif /* HVF_CPUS_H */ >>>> >> diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/hvf/hvf-i386.= h >>>> >> index e0edffd077..6d56f8f6bb 100644 >>>> >> --- a/target/i386/hvf/hvf-i386.h >>>> >> +++ b/target/i386/hvf/hvf-i386.h >>>> >> @@ -18,57 +18,11 @@ >>>> >> >>>> >> #include "sysemu/accel.h" >>>> >> #include "sysemu/hvf.h" >>>> >> +#include "sysemu/hvf_int.h" >>>> >> #include "cpu.h" >>>> >> #include "x86.h" >>>> >> >>>> >> -#define HVF_MAX_VCPU 0x10 >>>> >> - >>>> >> -extern struct hvf_state hvf_global; >>>> >> - >>>> >> -struct hvf_vm { >>>> >> - int id; >>>> >> - struct hvf_vcpu_state *vcpus[HVF_MAX_VCPU]; >>>> >> -}; >>>> >> - >>>> >> -struct hvf_state { >>>> >> - uint32_t version; >>>> >> - struct hvf_vm *vm; >>>> >> - uint64_t mem_quota; >>>> >> -}; >>>> >> - >>>> >> -/* hvf_slot flags */ >>>> >> -#define HVF_SLOT_LOG (1 << 0) >>>> >> - >>>> >> -typedef struct hvf_slot { >>>> >> - uint64_t start; >>>> >> - uint64_t size; >>>> >> - uint8_t *mem; >>>> >> - int slot_id; >>>> >> - uint32_t flags; >>>> >> - MemoryRegion *region; >>>> >> -} hvf_slot; >>>> >> - >>>> >> -typedef struct hvf_vcpu_caps { >>>> >> - uint64_t vmx_cap_pinbased; >>>> >> - uint64_t vmx_cap_procbased; >>>> >> - uint64_t vmx_cap_procbased2; >>>> >> - uint64_t vmx_cap_entry; >>>> >> - uint64_t vmx_cap_exit; >>>> >> - uint64_t vmx_cap_preemption_timer; >>>> >> -} hvf_vcpu_caps; >>>> >> - >>>> >> -struct HVFState { >>>> >> - AccelState parent; >>>> >> - hvf_slot slots[32]; >>>> >> - int num_slots; >>>> >> - >>>> >> - hvf_vcpu_caps *hvf_caps; >>>> >> -}; >>>> >> -extern HVFState *hvf_state; >>>> >> - >>>> >> -void hvf_set_phys_mem(MemoryRegionSection *, bool); >>>> >> void hvf_handle_io(CPUArchState *, uint16_t, void *, int, int, in= t); >>>> >> -hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); >>>> >> >>>> >> #ifdef NEED_CPU_H >>>> >> /* Functions exported to host specific mode */ >>>> >> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c >>>> >> index ed9356565c..8b96ecd619 100644 >>>> >> --- a/target/i386/hvf/hvf.c >>>> >> +++ b/target/i386/hvf/hvf.c >>>> >> @@ -51,6 +51,7 @@ >>>> >> #include "qemu/error-report.h" >>>> >> >>>> >> #include "sysemu/hvf.h" >>>> >> +#include "sysemu/hvf_int.h" >>>> >> #include "sysemu/runstate.h" >>>> >> #include "hvf-i386.h" >>>> >> #include "vmcs.h" >>>> >> @@ -72,171 +73,6 @@ >>>> >> #include "sysemu/accel.h" >>>> >> #include "target/i386/cpu.h" >>>> >> >>>> >> -#include "hvf-cpus.h" >>>> >> - >>>> >> -HVFState *hvf_state; >>>> >> - >>>> >> -static void assert_hvf_ok(hv_return_t ret) >>>> >> -{ >>>> >> - if (ret =3D=3D HV_SUCCESS) { >>>> >> - return; >>>> >> - } >>>> >> - >>>> >> - switch (ret) { >>>> >> - case HV_ERROR: >>>> >> - error_report("Error: HV_ERROR"); >>>> >> - break; >>>> >> - case HV_BUSY: >>>> >> - error_report("Error: HV_BUSY"); >>>> >> - break; >>>> >> - case HV_BAD_ARGUMENT: >>>> >> - error_report("Error: HV_BAD_ARGUMENT"); >>>> >> - break; >>>> >> - case HV_NO_RESOURCES: >>>> >> - error_report("Error: HV_NO_RESOURCES"); >>>> >> - break; >>>> >> - case HV_NO_DEVICE: >>>> >> - error_report("Error: HV_NO_DEVICE"); >>>> >> - break; >>>> >> - case HV_UNSUPPORTED: >>>> >> - error_report("Error: HV_UNSUPPORTED"); >>>> >> - break; >>>> >> - default: >>>> >> - error_report("Unknown Error"); >>>> >> - } >>>> >> - >>>> >> - abort(); >>>> >> -} >>>> >> - >>>> >> -/* Memory slots */ >>>> >> -hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size) >>>> >> -{ >>>> >> - hvf_slot *slot; >>>> >> - int x; >>>> >> - for (x =3D 0; x < hvf_state->num_slots; ++x) { >>>> >> - slot =3D &hvf_state->slots[x]; >>>> >> - if (slot->size && start < (slot->start + slot->size) && >>>> >> - (start + size) > slot->start) { >>>> >> - return slot; >>>> >> - } >>>> >> - } >>>> >> - return NULL; >>>> >> -} >>>> >> - >>>> >> -struct mac_slot { >>>> >> - int present; >>>> >> - uint64_t size; >>>> >> - uint64_t gpa_start; >>>> >> - uint64_t gva; >>>> >> -}; >>>> >> - >>>> >> -struct mac_slot mac_slots[32]; >>>> >> - >>>> >> -static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t fla= gs) >>>> >> -{ >>>> >> - struct mac_slot *macslot; >>>> >> - hv_return_t ret; >>>> >> - >>>> >> - macslot =3D &mac_slots[slot->slot_id]; >>>> >> - >>>> >> - if (macslot->present) { >>>> >> - if (macslot->size !=3D slot->size) { >>>> >> - macslot->present =3D 0; >>>> >> - ret =3D hv_vm_unmap(macslot->gpa_start, macslot->size)= ; >>>> >> - assert_hvf_ok(ret); >>>> >> - } >>>> >> - } >>>> >> - >>>> >> - if (!slot->size) { >>>> >> - return 0; >>>> >> - } >>>> >> - >>>> >> - macslot->present =3D 1; >>>> >> - macslot->gpa_start =3D slot->start; >>>> >> - macslot->size =3D slot->size; >>>> >> - ret =3D hv_vm_map((hv_uvaddr_t)slot->mem, slot->start, slot->s= ize, flags); >>>> >> - assert_hvf_ok(ret); >>>> >> - return 0; >>>> >> -} >>>> >> - >>>> >> -void hvf_set_phys_mem(MemoryRegionSection *section, bool add) >>>> >> -{ >>>> >> - hvf_slot *mem; >>>> >> - MemoryRegion *area =3D section->mr; >>>> >> - bool writeable =3D !area->readonly && !area->rom_device; >>>> >> - hv_memory_flags_t flags; >>>> >> - >>>> >> - if (!memory_region_is_ram(area)) { >>>> >> - if (writeable) { >>>> >> - return; >>>> >> - } else if (!memory_region_is_romd(area)) { >>>> >> - /* >>>> >> - * If the memory device is not in romd_mode, then we a= ctually want >>>> >> - * to remove the hvf memory slot so all accesses will = trap. >>>> >> - */ >>>> >> - add =3D false; >>>> >> - } >>>> >> - } >>>> >> - >>>> >> - mem =3D hvf_find_overlap_slot( >>>> >> - section->offset_within_address_space, >>>> >> - int128_get64(section->size)); >>>> >> - >>>> >> - if (mem && add) { >>>> >> - if (mem->size =3D=3D int128_get64(section->size) && >>>> >> - mem->start =3D=3D section->offset_within_address_space= && >>>> >> - mem->mem =3D=3D (memory_region_get_ram_ptr(area) + >>>> >> - section->offset_within_region)) { >>>> >> - return; /* Same region was attempted to register, go a= way. */ >>>> >> - } >>>> >> - } >>>> >> - >>>> >> - /* Region needs to be reset. set the size to 0 and remap it. *= / >>>> >> - if (mem) { >>>> >> - mem->size =3D 0; >>>> >> - if (do_hvf_set_memory(mem, 0)) { >>>> >> - error_report("Failed to reset overlapping slot"); >>>> >> - abort(); >>>> >> - } >>>> >> - } >>>> >> - >>>> >> - if (!add) { >>>> >> - return; >>>> >> - } >>>> >> - >>>> >> - if (area->readonly || >>>> >> - (!memory_region_is_ram(area) && memory_region_is_romd(area= ))) { >>>> >> - flags =3D HV_MEMORY_READ | HV_MEMORY_EXEC; >>>> >> - } else { >>>> >> - flags =3D HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXE= C; >>>> >> - } >>>> >> - >>>> >> - /* Now make a new slot. */ >>>> >> - int x; >>>> >> - >>>> >> - for (x =3D 0; x < hvf_state->num_slots; ++x) { >>>> >> - mem =3D &hvf_state->slots[x]; >>>> >> - if (!mem->size) { >>>> >> - break; >>>> >> - } >>>> >> - } >>>> >> - >>>> >> - if (x =3D=3D hvf_state->num_slots) { >>>> >> - error_report("No free slots"); >>>> >> - abort(); >>>> >> - } >>>> >> - >>>> >> - mem->size =3D int128_get64(section->size); >>>> >> - mem->mem =3D memory_region_get_ram_ptr(area) + section->offset= _within_region; >>>> >> - mem->start =3D section->offset_within_address_space; >>>> >> - mem->region =3D area; >>>> >> - >>>> >> - if (do_hvf_set_memory(mem, flags)) { >>>> >> - error_report("Error registering new memory slot"); >>>> >> - abort(); >>>> >> - } >>>> >> -} >>>> >> - >>>> >> void vmx_update_tpr(CPUState *cpu) >>>> >> { >>>> >> /* TODO: need integrate APIC handling */ >>>> >> @@ -276,56 +112,6 @@ void hvf_handle_io(CPUArchState *env, uint16_t= port, void *buffer, >>>> >> } >>>> >> } >>>> >> >>>> >> -static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu= _data arg) >>>> >> -{ >>>> >> - if (!cpu->vcpu_dirty) { >>>> >> - hvf_get_registers(cpu); >>>> >> - cpu->vcpu_dirty =3D true; >>>> >> - } >>>> >> -} >>>> >> - >>>> >> -void hvf_cpu_synchronize_state(CPUState *cpu) >>>> >> -{ >>>> >> - if (!cpu->vcpu_dirty) { >>>> >> - run_on_cpu(cpu, do_hvf_cpu_synchronize_state, RUN_ON_CPU_N= ULL); >>>> >> - } >>>> >> -} >>>> >> - >>>> >> -static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu, >>>> >> - run_on_cpu_data arg) >>>> >> -{ >>>> >> - hvf_put_registers(cpu); >>>> >> - cpu->vcpu_dirty =3D false; >>>> >> -} >>>> >> - >>>> >> -void hvf_cpu_synchronize_post_reset(CPUState *cpu) >>>> >> -{ >>>> >> - run_on_cpu(cpu, do_hvf_cpu_synchronize_post_reset, RUN_ON_CPU_= NULL); >>>> >> -} >>>> >> - >>>> >> -static void do_hvf_cpu_synchronize_post_init(CPUState *cpu, >>>> >> - run_on_cpu_data arg) >>>> >> -{ >>>> >> - hvf_put_registers(cpu); >>>> >> - cpu->vcpu_dirty =3D false; >>>> >> -} >>>> >> - >>>> >> -void hvf_cpu_synchronize_post_init(CPUState *cpu) >>>> >> -{ >>>> >> - run_on_cpu(cpu, do_hvf_cpu_synchronize_post_init, RUN_ON_CPU_N= ULL); >>>> >> -} >>>> >> - >>>> >> -static void do_hvf_cpu_synchronize_pre_loadvm(CPUState *cpu, >>>> >> - run_on_cpu_data arg) >>>> >> -{ >>>> >> - cpu->vcpu_dirty =3D true; >>>> >> -} >>>> >> - >>>> >> -void hvf_cpu_synchronize_pre_loadvm(CPUState *cpu) >>>> >> -{ >>>> >> - run_on_cpu(cpu, do_hvf_cpu_synchronize_pre_loadvm, RUN_ON_CPU_= NULL); >>>> >> -} >>>> >> - >>>> >> static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uin= t64_t ept_qual) >>>> >> { >>>> >> int read, write; >>>> >> @@ -370,109 +156,19 @@ static bool ept_emulation_fault(hvf_slot *sl= ot, uint64_t gpa, uint64_t ept_qual) >>>> >> return false; >>>> >> } >>>> >> >>>> >> -static void hvf_set_dirty_tracking(MemoryRegionSection *section, b= ool on) >>>> >> -{ >>>> >> - hvf_slot *slot; >>>> >> - >>>> >> - slot =3D hvf_find_overlap_slot( >>>> >> - section->offset_within_address_space, >>>> >> - int128_get64(section->size)); >>>> >> - >>>> >> - /* protect region against writes; begin tracking it */ >>>> >> - if (on) { >>>> >> - slot->flags |=3D HVF_SLOT_LOG; >>>> >> - hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size= , >>>> >> - HV_MEMORY_READ); >>>> >> - /* stop tracking region*/ >>>> >> - } else { >>>> >> - slot->flags &=3D ~HVF_SLOT_LOG; >>>> >> - hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size= , >>>> >> - HV_MEMORY_READ | HV_MEMORY_WRITE); >>>> >> - } >>>> >> -} >>>> >> - >>>> >> -static void hvf_log_start(MemoryListener *listener, >>>> >> - MemoryRegionSection *section, int old, i= nt new) >>>> >> -{ >>>> >> - if (old !=3D 0) { >>>> >> - return; >>>> >> - } >>>> >> - >>>> >> - hvf_set_dirty_tracking(section, 1); >>>> >> -} >>>> >> - >>>> >> -static void hvf_log_stop(MemoryListener *listener, >>>> >> - MemoryRegionSection *section, int old, in= t new) >>>> >> -{ >>>> >> - if (new !=3D 0) { >>>> >> - return; >>>> >> - } >>>> >> - >>>> >> - hvf_set_dirty_tracking(section, 0); >>>> >> -} >>>> >> - >>>> >> -static void hvf_log_sync(MemoryListener *listener, >>>> >> - MemoryRegionSection *section) >>>> >> -{ >>>> >> - /* >>>> >> - * sync of dirty pages is handled elsewhere; just make sure we= keep >>>> >> - * tracking the region. >>>> >> - */ >>>> >> - hvf_set_dirty_tracking(section, 1); >>>> >> -} >>>> >> - >>>> >> -static void hvf_region_add(MemoryListener *listener, >>>> >> - MemoryRegionSection *section) >>>> >> -{ >>>> >> - hvf_set_phys_mem(section, true); >>>> >> -} >>>> >> - >>>> >> -static void hvf_region_del(MemoryListener *listener, >>>> >> - MemoryRegionSection *section) >>>> >> -{ >>>> >> - hvf_set_phys_mem(section, false); >>>> >> -} >>>> >> - >>>> >> -static MemoryListener hvf_memory_listener =3D { >>>> >> - .priority =3D 10, >>>> >> - .region_add =3D hvf_region_add, >>>> >> - .region_del =3D hvf_region_del, >>>> >> - .log_start =3D hvf_log_start, >>>> >> - .log_stop =3D hvf_log_stop, >>>> >> - .log_sync =3D hvf_log_sync, >>>> >> -}; >>>> >> - >>>> >> -void hvf_vcpu_destroy(CPUState *cpu) >>>> >> +void hvf_arch_vcpu_destroy(CPUState *cpu) >>>> >> { >>>> >> X86CPU *x86_cpu =3D X86_CPU(cpu); >>>> >> CPUX86State *env =3D &x86_cpu->env; >>>> >> >>>> >> - hv_return_t ret =3D hv_vcpu_destroy((hv_vcpuid_t)cpu->hvf_fd); >>>> >> g_free(env->hvf_mmio_buf); >>>> >> - assert_hvf_ok(ret); >>>> >> -} >>>> >> - >>>> >> -static void dummy_signal(int sig) >>>> >> -{ >>>> >> } >>>> >> >>>> >> -int hvf_init_vcpu(CPUState *cpu) >>>> >> +int hvf_arch_init_vcpu(CPUState *cpu) >>>> >> { >>>> >> >>>> >> X86CPU *x86cpu =3D X86_CPU(cpu); >>>> >> CPUX86State *env =3D &x86cpu->env; >>>> >> - int r; >>>> >> - >>>> >> - /* init cpu signals */ >>>> >> - sigset_t set; >>>> >> - struct sigaction sigact; >>>> >> - >>>> >> - memset(&sigact, 0, sizeof(sigact)); >>>> >> - sigact.sa_handler =3D dummy_signal; >>>> >> - sigaction(SIG_IPI, &sigact, NULL); >>>> >> - >>>> >> - pthread_sigmask(SIG_BLOCK, NULL, &set); >>>> >> - sigdelset(&set, SIG_IPI); >>>> >> >>>> >> init_emu(); >>>> >> init_decoder(); >>>> >> @@ -480,10 +176,6 @@ int hvf_init_vcpu(CPUState *cpu) >>>> >> hvf_state->hvf_caps =3D g_new0(struct hvf_vcpu_caps, 1); >>>> >> env->hvf_mmio_buf =3D g_new(char, 4096); >>>> >> >>>> >> - r =3D hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFA= ULT); >>>> >> - cpu->vcpu_dirty =3D 1; >>>> >> - assert_hvf_ok(r); >>>> >> - >>>> >> if (hv_vmx_read_capability(HV_VMX_CAP_PINBASED, >>>> >> &hvf_state->hvf_caps->vmx_cap_pinbased)) { >>>> >> abort(); >>>> >> @@ -865,49 +557,3 @@ int hvf_vcpu_exec(CPUState *cpu) >>>> >> >>>> >> return ret; >>>> >> } >>>> >> - >>>> >> -bool hvf_allowed; >>>> >> - >>>> >> -static int hvf_accel_init(MachineState *ms) >>>> >> -{ >>>> >> - int x; >>>> >> - hv_return_t ret; >>>> >> - HVFState *s; >>>> >> - >>>> >> - ret =3D hv_vm_create(HV_VM_DEFAULT); >>>> >> - assert_hvf_ok(ret); >>>> >> - >>>> >> - s =3D g_new0(HVFState, 1); >>>> >> - >>>> >> - s->num_slots =3D 32; >>>> >> - for (x =3D 0; x < s->num_slots; ++x) { >>>> >> - s->slots[x].size =3D 0; >>>> >> - s->slots[x].slot_id =3D x; >>>> >> - } >>>> >> - >>>> >> - hvf_state =3D s; >>>> >> - memory_listener_register(&hvf_memory_listener, &address_space_= memory); >>>> >> - cpus_register_accel(&hvf_cpus); >>>> >> - return 0; >>>> >> -} >>>> >> - >>>> >> -static void hvf_accel_class_init(ObjectClass *oc, void *data) >>>> >> -{ >>>> >> - AccelClass *ac =3D ACCEL_CLASS(oc); >>>> >> - ac->name =3D "HVF"; >>>> >> - ac->init_machine =3D hvf_accel_init; >>>> >> - ac->allowed =3D &hvf_allowed; >>>> >> -} >>>> >> - >>>> >> -static const TypeInfo hvf_accel_type =3D { >>>> >> - .name =3D TYPE_HVF_ACCEL, >>>> >> - .parent =3D TYPE_ACCEL, >>>> >> - .class_init =3D hvf_accel_class_init, >>>> >> -}; >>>> >> - >>>> >> -static void hvf_type_init(void) >>>> >> -{ >>>> >> - type_register_static(&hvf_accel_type); >>>> >> -} >>>> >> - >>>> >> -type_init(hvf_type_init); >>>> >> diff --git a/target/i386/hvf/meson.build b/target/i386/hvf/meson.bu= ild >>>> >> index 409c9a3f14..c8a43717ee 100644 >>>> >> --- a/target/i386/hvf/meson.build >>>> >> +++ b/target/i386/hvf/meson.build >>>> >> @@ -1,6 +1,5 @@ >>>> >> i386_softmmu_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files( >>>> >> 'hvf.c', >>>> >> - 'hvf-cpus.c', >>>> >> 'x86.c', >>>> >> 'x86_cpuid.c', >>>> >> 'x86_decode.c', >>>> >> diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c >>>> >> index bbec412b6c..89b8e9d87a 100644 >>>> >> --- a/target/i386/hvf/x86hvf.c >>>> >> +++ b/target/i386/hvf/x86hvf.c >>>> >> @@ -20,6 +20,9 @@ >>>> >> #include "qemu/osdep.h" >>>> >> >>>> >> #include "qemu-common.h" >>>> >> +#include "sysemu/hvf.h" >>>> >> +#include "sysemu/hvf_int.h" >>>> >> +#include "sysemu/hw_accel.h" >>>> >> #include "x86hvf.h" >>>> >> #include "vmx.h" >>>> >> #include "vmcs.h" >>>> >> @@ -32,8 +35,6 @@ >>>> >> #include >>>> >> #include >>>> >> >>>> >> -#include "hvf-cpus.h" >>>> >> - >>>> >> void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vm= x_seg, >>>> >> SegmentCache *qseg, bool is_tr) >>>> >> { >>>> >> @@ -437,7 +438,7 @@ int hvf_process_events(CPUState *cpu_state) >>>> >> env->eflags =3D rreg(cpu_state->hvf_fd, HV_X86_RFLAGS); >>>> >> >>>> >> if (cpu_state->interrupt_request & CPU_INTERRUPT_INIT) { >>>> >> - hvf_cpu_synchronize_state(cpu_state); >>>> >> + cpu_synchronize_state(cpu_state); >>>> >> do_cpu_init(cpu); >>>> >> } >>>> >> >>>> >> @@ -451,12 +452,12 @@ int hvf_process_events(CPUState *cpu_state) >>>> >> cpu_state->halted =3D 0; >>>> >> } >>>> >> if (cpu_state->interrupt_request & CPU_INTERRUPT_SIPI) { >>>> >> - hvf_cpu_synchronize_state(cpu_state); >>>> >> + cpu_synchronize_state(cpu_state); >>>> >> do_cpu_sipi(cpu); >>>> >> } >>>> >> if (cpu_state->interrupt_request & CPU_INTERRUPT_TPR) { >>>> >> cpu_state->interrupt_request &=3D ~CPU_INTERRUPT_TPR; >>>> >> - hvf_cpu_synchronize_state(cpu_state); >>>> >> + cpu_synchronize_state(cpu_state); >>>> > The changes from hvf_cpu_*() to cpu_*() are cleanup and perhaps shou= ld >>>> > be a separate patch. It follows cpu/accel cleanups Claudio was doing= the >>>> > summer. >>>> >>>> >>>> The only reason they're in here is because we no longer have access to >>>> the hvf_ functions from the file. I am perfectly happy to rebase the >>>> patch on top of Claudio's if his goes in first. I'm sure it'll be >>>> trivial for him to rebase on top of this too if my series goes in firs= t. >>>> >>>> >>>> > >>>> > Phillipe raised the idea that the patch might go ahead of ARM-specif= ic >>>> > part (which might involve some discussions) and I agree with that. >>>> > >>>> > Some sync between Claudio series (CC'd him) and the patch might be n= eed. >>>> >>>> >>>> I would prefer not to hold back because of the sync. Claudio's cleanup >>>> is trivial enough to adjust for if it gets merged ahead of this. >>>> >>>> >>>> Alex >>>> >>>> >>>>