From patchwork Wed Aug 30 16:14:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370340 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 151DAC83F01 for ; Wed, 30 Aug 2023 16:18:25 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNq7-0002xv-MI; Wed, 30 Aug 2023 12:14:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNq6-0002xd-5y; Wed, 30 Aug 2023 12:14:42 -0400 Received: from smtp-fw-80007.amazon.com ([99.78.197.218]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNq3-0003af-6f; Wed, 30 Aug 2023 12:14:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412079; x=1724948079; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zfECsNuRUa9iSGp4Kx54IVbh1qkcDQSJ2bh50q8NsAg=; b=d62vGvz4frI7Q9A7l4HVBOcfEygVg4yuXqEvP4nNhD7Q9PnDGTE0G6dm UMsD4j0PIXJKmi3l/s2GVG52SOqbmHJqaIodBbAmcq2zcq3XKIZiQ7jgP pgGxi9m9oUi2r0Upbh5WRuUj2etsKERUdxnlPNcpeinX3Q40kAyxH14x4 k=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="236197144" Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO email-inbound-relay-pdx-2c-m6i4x-b1c0e1d0.us-west-2.amazon.com) ([10.25.36.210]) by smtp-border-fw-80007.pdx80.corp.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:14:33 +0000 Received: from EX19MTAUWB002.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan2.pdx.amazon.com [10.236.137.194]) by email-inbound-relay-pdx-2c-m6i4x-b1c0e1d0.us-west-2.amazon.com (Postfix) with ESMTPS id 17407878F5; Wed, 30 Aug 2023 16:14:33 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWB002.ant.amazon.com (10.250.64.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:32 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:29 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 01/12] build: Only define OS_OBJECT_USE_OBJC with gcc Date: Wed, 30 Aug 2023 16:14:14 +0000 Message-ID: <20230830161425.91946-2-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D036UWC003.ant.amazon.com (10.13.139.214) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=99.78.197.218; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-80007.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org Recent versions of macOS use clang instead of gcc. The OS_OBJECT_USE_OBJC define is only necessary when building with gcc. Let's not define it when building with clang. With this patch, I can successfully include GCD headers in QEMU when building with clang. Signed-off-by: Alexander Graf Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Akihiko Odaki --- meson.build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 98e68ef0b1..0d6a0015a1 100644 --- a/meson.build +++ b/meson.build @@ -224,7 +224,9 @@ qemu_ldflags = [] if targetos == 'darwin' # Disable attempts to use ObjectiveC features in os/object.h since they # won't work when we're compiling with gcc as a C compiler. - qemu_common_flags += '-DOS_OBJECT_USE_OBJC=0' + if compiler.get_id() == 'gcc' + qemu_common_flags += '-DOS_OBJECT_USE_OBJC=0' + endif elif targetos == 'solaris' # needed for CMSG_ macros in sys/socket.h qemu_common_flags += '-D_XOPEN_SOURCE=600' From patchwork Wed Aug 30 16:14:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370335 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 8DBE4C83F17 for ; Wed, 30 Aug 2023 16:17:56 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNqA-0002zk-DF; Wed, 30 Aug 2023 12:14:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNq8-0002yd-9A; Wed, 30 Aug 2023 12:14:44 -0400 Received: from smtp-fw-52005.amazon.com ([52.119.213.156]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNq5-0003bL-Eh; Wed, 30 Aug 2023 12:14:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412081; x=1724948081; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=60CfxM2CnF/paVsMzJ4VPvu4hWJW8Jp9HkIT4YXTfP0=; b=XIk2jKliT0KTT4gQvqKbD6yK1B8wshh3VnvH32gWTx3TzFQoNtWLwsBd Asb+fm5FZnRZHvZ6qSCUl0QCvAPKk8wq9bD203X0GXI4rGOdv7Ges7bhn ZQ+Dw7ZGk83xeZxP1ZcpcGclPiplPoNPZS9YRGsGy2ltVy+VJWvNyd0UE 4=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="601819024" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-iad-1d-m6i4x-f05d30a1.us-east-1.amazon.com) ([10.43.8.6]) by smtp-border-fw-52005.iad7.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:14:39 +0000 Received: from EX19MTAUWA002.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1d-m6i4x-f05d30a1.us-east-1.amazon.com (Postfix) with ESMTPS id 0EDDB80629; Wed, 30 Aug 2023 16:14:35 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWA002.ant.amazon.com (10.250.64.202) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:34 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:32 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 02/12] hw/misc/pvpanic: Add MMIO interface Date: Wed, 30 Aug 2023 16:14:15 +0000 Message-ID: <20230830161425.91946-3-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D036UWC003.ant.amazon.com (10.13.139.214) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=52.119.213.156; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-52005.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org In addition to the ISA and PCI variants of pvpanic, let's add an MMIO platform device that we can use in embedded arm environments. Signed-off-by: Alexander Graf Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- v1 -> v2: - Use SPDX header - Remove useless includes - Adapt to new meson.build target (system_ss) --- include/hw/misc/pvpanic.h | 1 + hw/misc/pvpanic-mmio.c | 61 +++++++++++++++++++++++++++++++++++++++ hw/misc/Kconfig | 4 +++ hw/misc/meson.build | 1 + 4 files changed, 67 insertions(+) create mode 100644 hw/misc/pvpanic-mmio.c diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h index fab94165d0..f9e7c1ea17 100644 --- a/include/hw/misc/pvpanic.h +++ b/include/hw/misc/pvpanic.h @@ -20,6 +20,7 @@ #define TYPE_PVPANIC_ISA_DEVICE "pvpanic" #define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci" +#define TYPE_PVPANIC_MMIO_DEVICE "pvpanic-mmio" #define PVPANIC_IOPORT_PROP "ioport" diff --git a/hw/misc/pvpanic-mmio.c b/hw/misc/pvpanic-mmio.c new file mode 100644 index 0000000000..99a24f104c --- /dev/null +++ b/hw/misc/pvpanic-mmio.c @@ -0,0 +1,61 @@ +/* + * QEMU simulated pvpanic device (MMIO frontend) + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "hw/qdev-properties.h" +#include "hw/misc/pvpanic.h" +#include "hw/sysbus.h" +#include "standard-headers/linux/pvpanic.h" + +OBJECT_DECLARE_SIMPLE_TYPE(PVPanicMMIOState, PVPANIC_MMIO_DEVICE) + +#define PVPANIC_MMIO_SIZE 0x2 + +struct PVPanicMMIOState { + SysBusDevice parent_obj; + + PVPanicState pvpanic; +}; + +static void pvpanic_mmio_initfn(Object *obj) +{ + PVPanicMMIOState *s = PVPANIC_MMIO_DEVICE(obj); + + pvpanic_setup_io(&s->pvpanic, DEVICE(s), PVPANIC_MMIO_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->pvpanic.mr); +} + +static Property pvpanic_mmio_properties[] = { + DEFINE_PROP_UINT8("events", PVPanicMMIOState, pvpanic.events, + PVPANIC_PANICKED | PVPANIC_CRASH_LOADED), + DEFINE_PROP_END_OF_LIST(), +}; + +static void pvpanic_mmio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + device_class_set_props(dc, pvpanic_mmio_properties); + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo pvpanic_mmio_info = { + .name = TYPE_PVPANIC_MMIO_DEVICE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PVPanicMMIOState), + .instance_init = pvpanic_mmio_initfn, + .class_init = pvpanic_mmio_class_init, +}; + +static void pvpanic_register_types(void) +{ + type_register_static(&pvpanic_mmio_info); +} + +type_init(pvpanic_register_types) diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 6996d265e4..b69746a60a 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -125,6 +125,10 @@ config PVPANIC_ISA depends on ISA_BUS select PVPANIC_COMMON +config PVPANIC_MMIO + bool + select PVPANIC_COMMON + config AUX bool select I2C diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 892f8b91c5..63821d6040 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -116,6 +116,7 @@ system_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c')) system_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c')) system_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c')) +system_ss.add(when: 'CONFIG_PVPANIC_MMIO', if_true: files('pvpanic-mmio.c')) system_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c')) system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_hace.c', From patchwork Wed Aug 30 16:14:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370343 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 85277C83F01 for ; Wed, 30 Aug 2023 16:18:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNsL-0004lY-1Y; Wed, 30 Aug 2023 12:17:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqg-0003J5-7G; Wed, 30 Aug 2023 12:15:18 -0400 Received: from smtp-fw-9103.amazon.com ([207.171.188.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqd-0003sd-Qo; Wed, 30 Aug 2023 12:15:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412115; x=1724948115; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=fULBujyPlQf2dUsEIaA2XAQI1K5vJQP8bEkwjEx3xeE=; b=OoInMejkNgaRX/1/3ksUfrV6AtHyL0dq02GF4i8tDa8iuQ6QiL/jRqhz 5NepIavhez3CIiv/j9RKz6xXX5EMUL/hTRZrW3wZGYy1YYo8hv6xzf6Lk Swe3XKdCJnFHKDdGo6cMPc12F6PNNBL/knRlSP1JbdRRLJWxxjDEnV+mx w=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="1151585335" Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO email-inbound-relay-pdx-2b-m6i4x-ed19f671.us-west-2.amazon.com) ([10.25.36.210]) by smtp-border-fw-9103.sea19.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:14:41 +0000 Received: from EX19MTAUWB001.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan2.pdx.amazon.com [10.236.137.194]) by email-inbound-relay-pdx-2b-m6i4x-ed19f671.us-west-2.amazon.com (Postfix) with ESMTPS id 4559080EB2; Wed, 30 Aug 2023 16:14:40 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWB001.ant.amazon.com (10.250.64.248) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:39 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:36 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 03/12] hvf: Increase number of possible memory slots Date: Wed, 30 Aug 2023 16:14:16 +0000 Message-ID: <20230830161425.91946-4-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D038UWC003.ant.amazon.com (10.13.139.209) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=207.171.188.200; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-9103.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org For PVG we will need more than the current 32 possible memory slots. Bump the limit to 512 instead. Signed-off-by: Alexander Graf --- v1 -> v2: - Move max slot number to define --- include/sysemu/hvf_int.h | 4 +++- accel/hvf/hvf-accel-ops.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h index 718beddcdd..36aa9b4eff 100644 --- a/include/sysemu/hvf_int.h +++ b/include/sysemu/hvf_int.h @@ -17,6 +17,8 @@ #include #endif +#define HVF_MAX_SLOTS 512 + /* hvf_slot flags */ #define HVF_SLOT_LOG (1 << 0) @@ -40,7 +42,7 @@ typedef struct hvf_vcpu_caps { struct HVFState { AccelState parent; - hvf_slot slots[32]; + hvf_slot slots[HVF_MAX_SLOTS]; int num_slots; hvf_vcpu_caps *hvf_caps; diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c index 3c94c79747..7aee0d6f72 100644 --- a/accel/hvf/hvf-accel-ops.c +++ b/accel/hvf/hvf-accel-ops.c @@ -88,7 +88,7 @@ struct mac_slot { uint64_t gva; }; -struct mac_slot mac_slots[32]; +struct mac_slot mac_slots[HVF_MAX_SLOTS]; static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags) { From patchwork Wed Aug 30 16:14:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370330 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 0E39BC6FA8F for ; Wed, 30 Aug 2023 16:15:43 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNqF-00031C-8V; Wed, 30 Aug 2023 12:14:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqD-00030O-Ln; Wed, 30 Aug 2023 12:14:49 -0400 Received: from smtp-fw-80006.amazon.com ([99.78.197.217]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqB-0003cP-Fp; Wed, 30 Aug 2023 12:14:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412088; x=1724948088; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=jkd/TbKF4zKphwA63UObWx34SP0PZ7brpUplZxBqtQA=; b=KXG38Hzlaq3WUFxHhyRGwHQEpWW1ikFKcDQnxAFoHCr9ap/GV6ntW9fV Qn3WiS4/gDn68N2bdVNUKVVWbWPiTJD/6uWA9MLz3uPPoJg27iUAFzBHd pBKmQyZD5vqWoWCxXwkmr9fZP5q3TzBQecawKu0YzY8l3lfm7RRk9BPJ3 s=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="235835012" Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-pdx-2a-m6i4x-1cca8d67.us-west-2.amazon.com) ([10.25.36.214]) by smtp-border-fw-80006.pdx80.corp.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:14:46 +0000 Received: from EX19MTAUWC002.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan2.pdx.amazon.com [10.236.137.194]) by email-inbound-relay-pdx-2a-m6i4x-1cca8d67.us-west-2.amazon.com (Postfix) with ESMTPS id 9C55C8AA6C; Wed, 30 Aug 2023 16:14:44 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWC002.ant.amazon.com (10.250.64.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:41 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:39 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 04/12] hvf: arm: Ignore writes to CNTP_CTL_EL0 Date: Wed, 30 Aug 2023 16:14:17 +0000 Message-ID: <20230830161425.91946-5-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D038UWC003.ant.amazon.com (10.13.139.209) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=99.78.197.217; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-80006.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org MacOS unconditionally disables interrupts of the physical timer on boot and then continues to use the virtual one. We don't really want to support a full physical timer emulation, so let's just ignore those writes. Signed-off-by: Alexander Graf Reviewed-by: Philippe Mathieu-Daudé --- v1 -> v2: - Add log message on write --- target/arm/hvf/hvf.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 486f90be1d..02db3dc908 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qemu/log.h" #include "sysemu/runstate.h" #include "sysemu/hvf.h" @@ -179,6 +180,7 @@ void hvf_arm_init_debug(void) #define SYSREG_OSLSR_EL1 SYSREG(2, 0, 1, 1, 4) #define SYSREG_OSDLR_EL1 SYSREG(2, 0, 1, 3, 4) #define SYSREG_CNTPCT_EL0 SYSREG(3, 3, 14, 0, 1) +#define SYSREG_CNTP_CTL_EL0 SYSREG(3, 3, 14, 2, 1) #define SYSREG_PMCR_EL0 SYSREG(3, 3, 9, 12, 0) #define SYSREG_PMUSERENR_EL0 SYSREG(3, 3, 9, 14, 0) #define SYSREG_PMCNTENSET_EL0 SYSREG(3, 3, 9, 12, 1) @@ -1551,6 +1553,13 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val) case SYSREG_OSLAR_EL1: env->cp15.oslsr_el1 = val & 1; break; + case SYSREG_CNTP_CTL_EL0: + /* + * Guests should not rely on the physical counter, but macOS emits + * disable writes to it. Let it do so, but ignore the requests. + */ + qemu_log_mask(LOG_UNIMP, "Unsupported write to CNTP_CTL_EL0\n"); + break; case SYSREG_OSDLR_EL1: /* Dummy register */ break; From patchwork Wed Aug 30 16:14:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370331 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id B9803C6FA8F for ; Wed, 30 Aug 2023 16:16:04 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNqb-0003Fe-FF; Wed, 30 Aug 2023 12:15:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqX-0003A6-Tb; Wed, 30 Aug 2023 12:15:11 -0400 Received: from smtp-fw-2101.amazon.com ([72.21.196.25]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqS-0003lU-SA; Wed, 30 Aug 2023 12:15:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412105; x=1724948105; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BN7p1+nUod5Kl7QmNTLv0efgM3fiYIGpIgiSI9p6Knw=; b=hwDsCCzQCdnAsEBmzSLvpuS35oC7SBXVU3Czhyc+Ybqm2Ovz+gYe2pdA OJd1yANQXKtTsH540tKEXLr9xTF8kcigVhXgZkwBH3FLzSQi4Ag0zYVbh qdpdHhcQLV7e2ELramYiceTQKSysbOKw1XIWpLy+ASITztpq1aAkKdjxk s=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="348536778" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-iad-1a-m6i4x-96feee09.us-east-1.amazon.com) ([10.43.8.6]) by smtp-border-fw-2101.iad2.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:01 +0000 Received: from EX19MTAUWC001.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1a-m6i4x-96feee09.us-east-1.amazon.com (Postfix) with ESMTPS id BE3A547A29; Wed, 30 Aug 2023 16:14:55 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWC001.ant.amazon.com (10.250.64.174) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:44 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:41 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 05/12] hw: Add vmapple subdir Date: Wed, 30 Aug 2023 16:14:18 +0000 Message-ID: <20230830161425.91946-6-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D038UWC003.ant.amazon.com (10.13.139.209) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=72.21.196.25; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-2101.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org We will introduce a number of devices that are specific to the vmapple target machine. To keep them all tidily together, let's put them into a single target directory. Signed-off-by: Alexander Graf --- MAINTAINERS | 6 ++++++ meson.build | 1 + hw/vmapple/trace.h | 1 + hw/Kconfig | 1 + hw/meson.build | 1 + hw/vmapple/Kconfig | 1 + hw/vmapple/meson.build | 0 hw/vmapple/trace-events | 2 ++ 8 files changed, 13 insertions(+) create mode 100644 hw/vmapple/trace.h create mode 100644 hw/vmapple/Kconfig create mode 100644 hw/vmapple/meson.build create mode 100644 hw/vmapple/trace-events diff --git a/MAINTAINERS b/MAINTAINERS index 6111b6b4d9..3104e58eff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2573,6 +2573,12 @@ F: hw/usb/canokey.c F: hw/usb/canokey.h F: docs/system/devices/canokey.rst +VMapple +M: Alexander Graf +S: Maintained +F: hw/vmapple/* +F: include/hw/vmapple/* + Subsystems ---------- Overall Audio backends diff --git a/meson.build b/meson.build index 0d6a0015a1..dc5242a5f4 100644 --- a/meson.build +++ b/meson.build @@ -3282,6 +3282,7 @@ if have_system 'hw/usb', 'hw/vfio', 'hw/virtio', + 'hw/vmapple', 'hw/watchdog', 'hw/xen', 'hw/gpio', diff --git a/hw/vmapple/trace.h b/hw/vmapple/trace.h new file mode 100644 index 0000000000..572adbefe0 --- /dev/null +++ b/hw/vmapple/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_vmapple.h" diff --git a/hw/Kconfig b/hw/Kconfig index ba62ff6417..d99854afdd 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -41,6 +41,7 @@ source tpm/Kconfig source usb/Kconfig source virtio/Kconfig source vfio/Kconfig +source vmapple/Kconfig source xen/Kconfig source watchdog/Kconfig diff --git a/hw/meson.build b/hw/meson.build index c7ac7d3d75..e156a6618f 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -40,6 +40,7 @@ subdir('tpm') subdir('usb') subdir('vfio') subdir('virtio') +subdir('vmapple') subdir('watchdog') subdir('xen') subdir('xenpv') diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/hw/vmapple/Kconfig @@ -0,0 +1 @@ + diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/hw/vmapple/trace-events b/hw/vmapple/trace-events new file mode 100644 index 0000000000..9ccc579048 --- /dev/null +++ b/hw/vmapple/trace-events @@ -0,0 +1,2 @@ +# See docs/devel/tracing.rst for syntax documentation. + From patchwork Wed Aug 30 16:14:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370332 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id F268BC6FA8F for ; Wed, 30 Aug 2023 16:16:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNqi-0003KF-Am; Wed, 30 Aug 2023 12:15:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqX-0003A7-Tg; Wed, 30 Aug 2023 12:15:11 -0400 Received: from smtp-fw-52003.amazon.com ([52.119.213.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqT-0003lY-3z; Wed, 30 Aug 2023 12:15:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412106; x=1724948106; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xM8SYxgkFilli2xl9g9SY/su9GFYjVRaVc+YuhdgKcM=; b=ldHosSUaYwZ0A1AClgxFORbfXYhSZPUKMRbVTUbgA/QAp3ps2rsP2JSi 8VZJiTj8g4SfiWOpymdyEKxOMYc+eAD4cEHu7Llt1zNJTz7VeTgySTxfw EPU9r9TcDh/Adv4Vw5dXH76vncmKUWcnPpDzs+McR3n8ke7Ugq4phdZR6 c=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="605192742" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-pdx-2c-m6i4x-b1c0e1d0.us-west-2.amazon.com) ([10.43.8.6]) by smtp-border-fw-52003.iad7.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:00 +0000 Received: from EX19MTAUWB002.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan2.pdx.amazon.com [10.236.137.194]) by email-inbound-relay-pdx-2c-m6i4x-b1c0e1d0.us-west-2.amazon.com (Postfix) with ESMTPS id E06A28A430; Wed, 30 Aug 2023 16:14:57 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWB002.ant.amazon.com (10.250.64.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:48 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:45 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 06/12] gpex: Allow more than 4 legacy IRQs Date: Wed, 30 Aug 2023 16:14:19 +0000 Message-ID: <20230830161425.91946-7-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D044UWA002.ant.amazon.com (10.13.139.11) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=52.119.213.152; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-52003.amazon.com X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org Some boards such as vmapple don't do real legacy PCI IRQ swizzling. Instead, they just keep allocating more board IRQ lines for each new legacy IRQ. Let's support that mode by giving instantiators a new "nr_irqs" property they can use to support more than 4 legacy IRQ lines. In this mode, GPEX will export more IRQ lines, one for each device. Signed-off-by: Alexander Graf --- include/hw/pci-host/gpex.h | 7 +++---- hw/arm/sbsa-ref.c | 2 +- hw/arm/virt.c | 2 +- hw/i386/microvm.c | 2 +- hw/loongarch/virt.c | 2 +- hw/mips/loongson3_virt.c | 2 +- hw/openrisc/virt.c | 12 ++++++------ hw/pci-host/gpex.c | 36 +++++++++++++++++++++++++++++++----- hw/riscv/virt.c | 12 ++++++------ hw/xtensa/virt.c | 2 +- 10 files changed, 52 insertions(+), 27 deletions(-) diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h index b0240bd768..098dc4d1cc 100644 --- a/include/hw/pci-host/gpex.h +++ b/include/hw/pci-host/gpex.h @@ -32,8 +32,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(GPEXHost, GPEX_HOST) #define TYPE_GPEX_ROOT_DEVICE "gpex-root" OBJECT_DECLARE_SIMPLE_TYPE(GPEXRootState, GPEX_ROOT_DEVICE) -#define GPEX_NUM_IRQS 4 - struct GPEXRootState { /*< private >*/ PCIDevice parent_obj; @@ -51,8 +49,9 @@ struct GPEXHost { MemoryRegion io_mmio; MemoryRegion io_ioport_window; MemoryRegion io_mmio_window; - qemu_irq irq[GPEX_NUM_IRQS]; - int irq_num[GPEX_NUM_IRQS]; + uint32_t nr_irqs; + qemu_irq *irq; + int *irq_num; bool allow_unmapped_accesses; }; diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index bc89eb4806..a786849238 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -681,7 +681,7 @@ static void create_pcie(SBSAMachineState *sms) /* Map IO port space */ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio); - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, qdev_get_gpio_in(sms->gic, irq + i)); gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index a13c658bbf..3a4ef3adc2 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1467,7 +1467,7 @@ static void create_pcie(VirtMachineState *vms) /* Map IO port space */ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio); - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, qdev_get_gpio_in(vms->gic, irq + i)); gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 7227a2156c..9ca007b870 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -139,7 +139,7 @@ static void create_gpex(MicrovmMachineState *mms) mms->gpex.mmio64.base, mmio64_alias); } - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, x86ms->gsi[mms->gpex.irq + i]); } diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 2629128aed..36bfcea53b 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -533,7 +533,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE, pio_alias); - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { sysbus_connect_irq(d, i, qdev_get_gpio_in(pch_pic, 16 + i)); gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i); diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index b74b358874..6d54f679eb 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -437,7 +437,7 @@ static inline void loongson3_virt_devices_init(MachineState *machine, virt_memmap[VIRT_PCIE_PIO].base, s->pio_alias); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base); - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i); sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq); gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i); diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c index f8a68a6a6b..16a5676c4b 100644 --- a/hw/openrisc/virt.c +++ b/hw/openrisc/virt.c @@ -318,7 +318,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base, { int pin, dev; uint32_t irq_map_stride = 0; - uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * 6] = {}; + uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS * 6] = {}; uint32_t *irq_map = full_irq_map; /* @@ -330,11 +330,11 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base, * possible slot) seeing the interrupt-map-mask will allow the table * to wrap to any number of devices. */ - for (dev = 0; dev < GPEX_NUM_IRQS; dev++) { + for (dev = 0; dev < PCI_NUM_PINS; dev++) { int devfn = dev << 3; - for (pin = 0; pin < GPEX_NUM_IRQS; pin++) { - int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS); + for (pin = 0; pin < PCI_NUM_PINS; pin++) { + int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS); int i = 0; /* Fill PCI address cells */ @@ -357,7 +357,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base, } qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map, - GPEX_NUM_IRQS * GPEX_NUM_IRQS * + PCI_NUM_PINS * PCI_NUM_PINS * irq_map_stride * sizeof(uint32_t)); qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask", @@ -409,7 +409,7 @@ static void openrisc_virt_pcie_init(OR1KVirtState *state, memory_region_add_subregion(get_system_memory(), pio_base, alias); /* Connect IRQ lines. */ - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { pcie_irq = get_per_cpu_irq(cpus, num_cpus, irq_base + i); sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pcie_irq); diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index a6752fac5e..7d5d996f34 100644 --- a/hw/pci-host/gpex.c +++ b/hw/pci-host/gpex.c @@ -32,6 +32,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/irq.h" +#include "hw/pci/pci_bus.h" #include "hw/pci-host/gpex.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" @@ -50,7 +51,7 @@ static void gpex_set_irq(void *opaque, int irq_num, int level) int gpex_set_irq_num(GPEXHost *s, int index, int gsi) { - if (index >= GPEX_NUM_IRQS) { + if (index >= s->nr_irqs) { return -EINVAL; } @@ -74,14 +75,29 @@ static PCIINTxRoute gpex_route_intx_pin_to_irq(void *opaque, int pin) return route; } +static int gpex_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin) +{ + PCIBus *bus = pci_device_root_bus(pci_dev); + + return (PCI_SLOT(pci_dev->devfn) + pin) % bus->nirq; +} + static void gpex_host_realize(DeviceState *dev, Error **errp) { PCIHostState *pci = PCI_HOST_BRIDGE(dev); GPEXHost *s = GPEX_HOST(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev); + pci_map_irq_fn map_irq_fn = pci_swizzle_map_irq_fn; int i; + s->irq = g_malloc0(s->nr_irqs * sizeof(*s->irq)); + s->irq_num = g_malloc0(s->nr_irqs * sizeof(*s->irq_num)); + + if (s->nr_irqs != PCI_NUM_PINS) { + map_irq_fn = gpex_swizzle_map_irq_fn; + } + pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX); sysbus_init_mmio(sbd, &pex->mmio); @@ -128,19 +144,27 @@ static void gpex_host_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->io_ioport); } - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < s->nr_irqs; i++) { sysbus_init_irq(sbd, &s->irq[i]); s->irq_num[i] = -1; } - pci->bus = pci_register_root_bus(dev, "pcie.0", gpex_set_irq, - pci_swizzle_map_irq_fn, s, &s->io_mmio, - &s->io_ioport, 0, 4, TYPE_PCIE_BUS); + pci->bus = pci_register_root_bus(dev, "pcie.0", gpex_set_irq, map_irq_fn, + s, &s->io_mmio, &s->io_ioport, 0, + s->nr_irqs, TYPE_PCIE_BUS); pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq); qdev_realize(DEVICE(&s->gpex_root), BUS(pci->bus), &error_fatal); } +static void gpex_host_unrealize(DeviceState *dev) +{ + GPEXHost *s = GPEX_HOST(dev); + + g_free(s->irq); + g_free(s->irq_num); +} + static const char *gpex_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) { @@ -154,6 +178,7 @@ static Property gpex_host_properties[] = { */ DEFINE_PROP_BOOL("allow-unmapped-accesses", GPEXHost, allow_unmapped_accesses, true), + DEFINE_PROP_UINT32("nr-irqs", GPEXHost, nr_irqs, PCI_NUM_PINS), DEFINE_PROP_END_OF_LIST(), }; @@ -164,6 +189,7 @@ static void gpex_host_class_init(ObjectClass *klass, void *data) hc->root_bus_path = gpex_host_root_bus_path; dc->realize = gpex_host_realize; + dc->unrealize = gpex_host_unrealize; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->fw_name = "pci"; device_class_set_props(dc, gpex_host_properties); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 99c4e6314b..c13e8c8142 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -175,7 +175,7 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename, { int pin, dev; uint32_t irq_map_stride = 0; - uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * + uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS * FDT_MAX_INT_MAP_WIDTH] = {}; uint32_t *irq_map = full_irq_map; @@ -187,11 +187,11 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename, * possible slot) seeing the interrupt-map-mask will allow the table * to wrap to any number of devices. */ - for (dev = 0; dev < GPEX_NUM_IRQS; dev++) { + for (dev = 0; dev < PCI_NUM_PINS; dev++) { int devfn = dev * 0x8; - for (pin = 0; pin < GPEX_NUM_IRQS; pin++) { - int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS); + for (pin = 0; pin < PCI_NUM_PINS; pin++) { + int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS); int i = 0; /* Fill PCI address cells */ @@ -217,7 +217,7 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename, } qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map, - GPEX_NUM_IRQS * GPEX_NUM_IRQS * + PCI_NUM_PINS * PCI_NUM_PINS * irq_map_stride * sizeof(uint32_t)); qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask", @@ -1106,7 +1106,7 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, pio_base); - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { irq = qdev_get_gpio_in(irqchip, PCIE_IRQ + i); sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq); diff --git a/hw/xtensa/virt.c b/hw/xtensa/virt.c index a6cf646e99..c23c540e87 100644 --- a/hw/xtensa/virt.c +++ b/hw/xtensa/virt.c @@ -93,7 +93,7 @@ static void create_pcie(MachineState *ms, CPUXtensaState *env, int irq_base, /* Connect IRQ lines. */ extints = xtensa_get_extints(env); - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { void *q = extints[irq_base + i]; sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, q); From patchwork Wed Aug 30 16:14:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370341 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C79D5C83F18 for ; Wed, 30 Aug 2023 16:18:26 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNss-0005dG-B9; Wed, 30 Aug 2023 12:17:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqh-0003KP-Kf; Wed, 30 Aug 2023 12:15:20 -0400 Received: from smtp-fw-80008.amazon.com ([99.78.197.219]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqe-0003sn-4Y; Wed, 30 Aug 2023 12:15:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412116; x=1724948116; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yiablZyiOuBHvx3Axq0p9kHXfcqyfYTUGh0aRc6sg9Y=; b=TceYyyNU3Eq7t/YN8p20vc1t0Wwj8NEbVY6GzNKH5/I4KoMneti7u+YY 8rbsz/n0bhkVYK3A/XcKy223uIPdXRDFdl073eekWFX0/C31yCvT18Uxe kOG0OIDdHNE/RXBnr/i91PcoINevMDpCMujvcbhvfVNrJ9CzVRsMYpQk3 M=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="26014942" Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1a-m6i4x-93c3b254.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-80008.pdx80.corp.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:10 +0000 Received: from EX19MTAUWA002.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1a-m6i4x-93c3b254.us-east-1.amazon.com (Postfix) with ESMTPS id EEFBEE3A81; Wed, 30 Aug 2023 16:15:04 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWA002.ant.amazon.com (10.250.64.202) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:51 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:48 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 07/12] hw/vmapple/aes: Introduce aes engine Date: Wed, 30 Aug 2023 16:14:20 +0000 Message-ID: <20230830161425.91946-8-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D044UWA002.ant.amazon.com (10.13.139.11) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=99.78.197.219; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-80008.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org VMApple contains an "aes" engine device that it uses to encrypt and decrypt its nvram. It has trivial hard coded keys it uses for that purpose. Add device emulation for this device model. Signed-off-by: Alexander Graf --- hw/vmapple/aes.c | 583 ++++++++++++++++++++++++++++++++++++++++ hw/vmapple/Kconfig | 2 + hw/vmapple/meson.build | 1 + hw/vmapple/trace-events | 18 ++ 4 files changed, 604 insertions(+) create mode 100644 hw/vmapple/aes.c diff --git a/hw/vmapple/aes.c b/hw/vmapple/aes.c new file mode 100644 index 0000000000..eaf1e26abe --- /dev/null +++ b/hw/vmapple/aes.c @@ -0,0 +1,583 @@ +/* + * QEMU Apple AES device emulation + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "trace.h" +#include "hw/sysbus.h" +#include "crypto/hash.h" +#include "crypto/aes.h" +#include "crypto/cipher.h" + +#define TYPE_AES "apple-aes" +#define MAX_FIFO_SIZE 9 + +#define CMD_KEY 0x1 +#define CMD_KEY_CONTEXT_SHIFT 27 +#define CMD_KEY_CONTEXT_MASK (0x1 << CMD_KEY_CONTEXT_SHIFT) +#define CMD_KEY_SELECT_SHIFT 24 +#define CMD_KEY_SELECT_MASK (0x7 << CMD_KEY_SELECT_SHIFT) +#define CMD_KEY_KEY_LEN_SHIFT 22 +#define CMD_KEY_KEY_LEN_MASK (0x3 << CMD_KEY_KEY_LEN_SHIFT) +#define CMD_KEY_ENCRYPT_SHIFT 20 +#define CMD_KEY_ENCRYPT_MASK (0x1 << CMD_KEY_ENCRYPT_SHIFT) +#define CMD_KEY_BLOCK_MODE_SHIFT 16 +#define CMD_KEY_BLOCK_MODE_MASK (0x3 << CMD_KEY_BLOCK_MODE_SHIFT) +#define CMD_IV 0x2 +#define CMD_IV_CONTEXT_SHIFT 26 +#define CMD_IV_CONTEXT_MASK (0x3 << CMD_KEY_CONTEXT_SHIFT) +#define CMD_DSB 0x3 +#define CMD_SKG 0x4 +#define CMD_DATA 0x5 +#define CMD_DATA_KEY_CTX_SHIFT 27 +#define CMD_DATA_KEY_CTX_MASK (0x1 << CMD_DATA_KEY_CTX_SHIFT) +#define CMD_DATA_IV_CTX_SHIFT 25 +#define CMD_DATA_IV_CTX_MASK (0x3 << CMD_DATA_IV_CTX_SHIFT) +#define CMD_DATA_LEN_MASK 0xffffff +#define CMD_STORE_IV 0x6 +#define CMD_STORE_IV_ADDR_MASK 0xffffff +#define CMD_WRITE_REG 0x7 +#define CMD_FLAG 0x8 +#define CMD_FLAG_STOP_MASK BIT(26) +#define CMD_FLAG_RAISE_IRQ_MASK BIT(27) +#define CMD_FLAG_INFO_MASK 0xff +#define CMD_MAX 0x10 + +#define CMD_SHIFT 28 + +#define REG_STATUS 0xc +#define REG_STATUS_DMA_READ_RUNNING BIT(0) +#define REG_STATUS_DMA_READ_PENDING BIT(1) +#define REG_STATUS_DMA_WRITE_RUNNING BIT(2) +#define REG_STATUS_DMA_WRITE_PENDING BIT(3) +#define REG_STATUS_BUSY BIT(4) +#define REG_STATUS_EXECUTING BIT(5) +#define REG_STATUS_READY BIT(6) +#define REG_STATUS_TEXT_DPA_SEEDED BIT(7) +#define REG_STATUS_UNWRAP_DPA_SEEDED BIT(8) + +#define REG_IRQ_STATUS 0x18 +#define REG_IRQ_STATUS_INVALID_CMD BIT(2) +#define REG_IRQ_STATUS_FLAG BIT(5) +#define REG_IRQ_ENABLE 0x1c +#define REG_WATERMARK 0x20 +#define REG_Q_STATUS 0x24 +#define REG_FLAG_INFO 0x30 +#define REG_FIFO 0x200 + +static const uint32_t key_lens[4] = { + [0] = 16, + [1] = 24, + [2] = 32, + [3] = 64, +}; + +struct key { + uint32_t key_len; + uint32_t key[8]; +}; + +struct iv { + uint32_t iv[4]; +}; + +struct context { + struct key key; + struct iv iv; +}; + +static struct key builtin_keys[7] = { + [1] = { + .key_len = 32, + .key = { 0x1 }, + }, + [2] = { + .key_len = 32, + .key = { 0x2 }, + }, + [3] = { + .key_len = 32, + .key = { 0x3 }, + } +}; + +typedef struct AESState { + /* Private */ + SysBusDevice parent_obj; + + /* Public */ + qemu_irq irq; + MemoryRegion iomem1; + MemoryRegion iomem2; + + uint32_t status; + uint32_t q_status; + uint32_t irq_status; + uint32_t irq_enable; + uint32_t watermark; + uint32_t flag_info; + uint32_t fifo[MAX_FIFO_SIZE]; + uint32_t fifo_idx; + struct key key[2]; + struct iv iv[4]; + bool is_encrypt; + QCryptoCipherMode block_mode; +} AESState; + +OBJECT_DECLARE_SIMPLE_TYPE(AESState, AES) + +static void aes_update_irq(AESState *s) +{ + qemu_set_irq(s->irq, !!(s->irq_status & s->irq_enable)); +} + +static uint64_t aes1_read(void *opaque, hwaddr offset, unsigned size) +{ + AESState *s = opaque; + uint64_t res = 0; + + switch (offset) { + case REG_STATUS: + res = s->status; + break; + case REG_IRQ_STATUS: + res = s->irq_status; + break; + case REG_IRQ_ENABLE: + res = s->irq_enable; + break; + case REG_WATERMARK: + res = s->watermark; + break; + case REG_Q_STATUS: + res = s->q_status; + break; + case REG_FLAG_INFO: + res = s->flag_info; + break; + + default: + trace_aes_read_unknown(offset); + break; + } + + trace_aes_read(offset, res); + + return res; +} + +static void fifo_append(AESState *s, uint64_t val) +{ + if (s->fifo_idx == MAX_FIFO_SIZE) { + /* Exceeded the FIFO. Bail out */ + return; + } + + s->fifo[s->fifo_idx++] = val; +} + +static bool has_payload(AESState *s, uint32_t elems) +{ + return s->fifo_idx >= (elems + 1); +} + +static bool cmd_key(AESState *s) +{ + uint32_t cmd = s->fifo[0]; + uint32_t key_select = (cmd & CMD_KEY_SELECT_MASK) >> CMD_KEY_SELECT_SHIFT; + uint32_t ctxt = (cmd & CMD_KEY_CONTEXT_MASK) >> CMD_KEY_CONTEXT_SHIFT; + uint32_t key_len; + + switch ((cmd & CMD_KEY_BLOCK_MODE_MASK) >> CMD_KEY_BLOCK_MODE_SHIFT) { + case 0: + s->block_mode = QCRYPTO_CIPHER_MODE_ECB; + break; + case 1: + s->block_mode = QCRYPTO_CIPHER_MODE_CBC; + break; + default: + return false; + } + + s->is_encrypt = !!((cmd & CMD_KEY_ENCRYPT_MASK) >> CMD_KEY_ENCRYPT_SHIFT); + key_len = key_lens[((cmd & CMD_KEY_KEY_LEN_MASK) >> CMD_KEY_KEY_LEN_SHIFT)]; + + if (key_select) { + trace_aes_cmd_key_select_builtin(ctxt, key_select, + s->is_encrypt ? "en" : "de", + QCryptoCipherMode_str(s->block_mode)); + s->key[ctxt] = builtin_keys[key_select]; + } else { + trace_aes_cmd_key_select_new(ctxt, key_len, + s->is_encrypt ? "en" : "de", + QCryptoCipherMode_str(s->block_mode)); + if (key_len > sizeof(s->key[ctxt].key)) { + return false; + } + if (!has_payload(s, key_len / sizeof(uint32_t))) { + /* wait for payload */ + return false; + } + memcpy(&s->key[ctxt].key, &s->fifo[1], key_len); + s->key[ctxt].key_len = key_len; + } + + return true; +} + +static bool cmd_iv(AESState *s) +{ + uint32_t cmd = s->fifo[0]; + uint32_t ctxt = (cmd & CMD_IV_CONTEXT_MASK) >> CMD_IV_CONTEXT_SHIFT; + + if (!has_payload(s, 4)) { + /* wait for payload */ + return false; + } + memcpy(&s->iv[ctxt].iv, &s->fifo[1], sizeof(s->iv[ctxt].iv)); + trace_aes_cmd_iv(ctxt, s->fifo[1], s->fifo[2], s->fifo[3], s->fifo[4]); + + return true; +} + +static char hexdigit2str(uint8_t val) +{ + g_assert(val < 0x10); + if (val >= 0xa) { + return 'a' + (val - 0xa); + } else { + return '0' + val; + } +} + +static void dump_data(const char *desc, const void *p, size_t len) +{ + char hex[(len * 2) + 1]; + const uint8_t *data = p; + char *hexp = hex; + size_t i; + + if (len > 0x1000) { + /* Too large buffer, let's bail out */ + return; + } + + for (i = 0; i < len; i++) { + uint8_t val = data[i]; + *(hexp++) = hexdigit2str(val >> 4); + *(hexp++) = hexdigit2str(val & 0xf); + } + *hexp = '\0'; + + trace_aes_dump_data(desc, hex); +} + +static bool cmd_data(AESState *s) +{ + uint32_t cmd = s->fifo[0]; + uint32_t ctxt_iv = 0; + uint32_t ctxt_key = (cmd & CMD_DATA_KEY_CTX_MASK) >> CMD_DATA_KEY_CTX_SHIFT; + uint32_t len = cmd & CMD_DATA_LEN_MASK; + uint64_t src_addr = s->fifo[2]; + uint64_t dst_addr = s->fifo[3]; + QCryptoCipherAlgorithm alg; + QCryptoCipher *cipher; + char *src; + char *dst; + + src_addr |= ((uint64_t)s->fifo[1] << 16) & 0xffff00000000ULL; + dst_addr |= ((uint64_t)s->fifo[1] << 32) & 0xffff00000000ULL; + + trace_aes_cmd_data(ctxt_key, ctxt_iv, src_addr, dst_addr, len); + + if (!has_payload(s, 3)) { + /* wait for payload */ + trace_aes_cmd_data_error("No payload"); + return false; + } + + if (ctxt_key >= ARRAY_SIZE(s->key) || + ctxt_iv >= ARRAY_SIZE(s->iv)) { + /* Invalid input */ + trace_aes_cmd_data_error("Invalid key or iv"); + return false; + } + + src = g_malloc0(len); + dst = g_malloc0(len); + + cpu_physical_memory_read(src_addr, src, len); + + dump_data("cmd_data(): src_data=", src, len); + + switch (s->key[ctxt_key].key_len) { + case 128 / 8: + alg = QCRYPTO_CIPHER_ALG_AES_128; + break; + case 192 / 8: + alg = QCRYPTO_CIPHER_ALG_AES_192; + break; + case 256 / 8: + alg = QCRYPTO_CIPHER_ALG_AES_256; + break; + default: + trace_aes_cmd_data_error("Invalid key len"); + goto err_free; + } + cipher = qcrypto_cipher_new(alg, s->block_mode, + (void *)s->key[ctxt_key].key, + s->key[ctxt_key].key_len, NULL); + g_assert(cipher != NULL); + if (s->block_mode != QCRYPTO_CIPHER_MODE_ECB) { + if (qcrypto_cipher_setiv(cipher, (void *)s->iv[ctxt_iv].iv, + sizeof(s->iv[ctxt_iv].iv), NULL) != 0) { + trace_aes_cmd_data_error("Failed to set IV"); + goto err_free_cipher; + } + } + if (s->is_encrypt) { + if (qcrypto_cipher_encrypt(cipher, src, dst, len, NULL) != 0) { + trace_aes_cmd_data_error("Encrypt failed"); + goto err_free_cipher; + } + } else { + if (qcrypto_cipher_decrypt(cipher, src, dst, len, NULL) != 0) { + trace_aes_cmd_data_error("Decrypt failed"); + goto err_free_cipher; + } + } + qcrypto_cipher_free(cipher); + + dump_data("cmd_data(): dst_data=", dst, len); + cpu_physical_memory_write(dst_addr, dst, len); + g_free(src); + g_free(dst); + + return true; + +err_free_cipher: + qcrypto_cipher_free(cipher); +err_free: + g_free(src); + g_free(dst); + return false; +} + +static bool cmd_store_iv(AESState *s) +{ + uint32_t cmd = s->fifo[0]; + uint32_t ctxt = (cmd & CMD_IV_CONTEXT_MASK) >> CMD_IV_CONTEXT_SHIFT; + uint64_t addr = s->fifo[1]; + + if (!has_payload(s, 1)) { + /* wait for payload */ + return false; + } + + if (ctxt >= ARRAY_SIZE(s->iv)) { + /* Invalid context selected */ + return false; + } + + addr |= ((uint64_t)cmd << 32) & 0xff00000000ULL; + cpu_physical_memory_write(addr, &s->iv[ctxt].iv, sizeof(s->iv[ctxt].iv)); + + trace_aes_cmd_store_iv(ctxt, addr, s->iv[ctxt].iv[0], s->iv[ctxt].iv[1], + s->iv[ctxt].iv[2], s->iv[ctxt].iv[3]); + + return true; +} + +static bool cmd_flag(AESState *s) +{ + uint32_t cmd = s->fifo[0]; + uint32_t raise_irq = cmd & CMD_FLAG_RAISE_IRQ_MASK; + + /* We always process data when it's coming in, so fire an IRQ immediately */ + if (raise_irq) { + s->irq_status |= REG_IRQ_STATUS_FLAG; + } + + s->flag_info = cmd & CMD_FLAG_INFO_MASK; + + trace_aes_cmd_flag(!!raise_irq, s->flag_info); + + return true; +} + +static void fifo_process(AESState *s) +{ + uint32_t cmd = s->fifo[0] >> CMD_SHIFT; + bool success = false; + + if (!s->fifo_idx) { + return; + } + + switch (cmd) { + case CMD_KEY: + success = cmd_key(s); + break; + case CMD_IV: + success = cmd_iv(s); + break; + case CMD_DATA: + success = cmd_data(s); + break; + case CMD_STORE_IV: + success = cmd_store_iv(s); + break; + case CMD_FLAG: + success = cmd_flag(s); + break; + default: + s->irq_status |= REG_IRQ_STATUS_INVALID_CMD; + break; + } + + if (success) { + s->fifo_idx = 0; + } + + trace_aes_fifo_process(cmd, success ? 1 : 0); +} + +static void aes1_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) +{ + AESState *s = opaque; + + trace_aes_write(offset, val); + + switch (offset) { + case REG_IRQ_STATUS: + s->irq_status &= ~val; + break; + case REG_IRQ_ENABLE: + s->irq_enable = val; + break; + case REG_FIFO: + fifo_append(s, val); + fifo_process(s); + break; + default: + trace_aes_write_unknown(offset); + return; + } + + aes_update_irq(s); +} + +static const MemoryRegionOps aes1_ops = { + .read = aes1_read, + .write = aes1_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static uint64_t aes2_read(void *opaque, hwaddr offset, unsigned size) +{ + uint64_t res = 0; + + switch (offset) { + case 0: + res = 0; + break; + default: + trace_aes_2_read_unknown(offset); + break; + } + + trace_aes_2_read(offset, res); + + return res; +} + +static void aes2_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) +{ + trace_aes_2_write(offset, val); + + switch (offset) { + default: + trace_aes_2_write_unknown(offset); + return; + } +} + +static const MemoryRegionOps aes2_ops = { + .read = aes2_read, + .write = aes2_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static void aes_reset(DeviceState *d) +{ + AESState *s = AES(d); + + s->status = 0x3f80; + s->q_status = 2; + s->irq_status = 0; + s->irq_enable = 0; + s->watermark = 0; +} + +static void aes_init(Object *obj) +{ + AESState *s = AES(obj); + + memory_region_init_io(&s->iomem1, obj, &aes1_ops, s, TYPE_AES, 0x4000); + memory_region_init_io(&s->iomem2, obj, &aes2_ops, s, TYPE_AES, 0x4000); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem1); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem2); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); +} + +static void aes_realize(DeviceState *dev, Error **errp) +{ +} + +static void aes_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = aes_reset; + dc->realize = aes_realize; +} + +static const TypeInfo aes_info = { + .name = TYPE_AES, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AESState), + .class_init = aes_class_init, + .instance_init = aes_init, +}; + +static void aes_register_types(void) +{ + type_register_static(&aes_info); +} + +type_init(aes_register_types) diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig index 8b13789179..a73504d599 100644 --- a/hw/vmapple/Kconfig +++ b/hw/vmapple/Kconfig @@ -1 +1,3 @@ +config VMAPPLE_AES + bool diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build index e69de29bb2..bcd4dcb28d 100644 --- a/hw/vmapple/meson.build +++ b/hw/vmapple/meson.build @@ -0,0 +1 @@ +system_ss.add(when: 'CONFIG_VMAPPLE_AES', if_true: files('aes.c')) diff --git a/hw/vmapple/trace-events b/hw/vmapple/trace-events index 9ccc579048..03585cdf0f 100644 --- a/hw/vmapple/trace-events +++ b/hw/vmapple/trace-events @@ -1,2 +1,20 @@ # See docs/devel/tracing.rst for syntax documentation. +# aes.c +aes_read_unknown(uint64_t offset) "offset=0x%"PRIx64 +aes_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64 +aes_cmd_key_select_builtin(uint32_t ctx, uint32_t key_id, const char *direction, const char *cipher) "[%d] Selecting builtin key %d to %scrypt with %s" +aes_cmd_key_select_new(uint32_t ctx, uint32_t key_len, const char *direction, const char *cipher) "[%d] Selecting new key size=%d to %scrypt with %s" +aes_cmd_iv(uint32_t ctx, uint32_t iv0, uint32_t iv1, uint32_t iv2, uint32_t iv3) "[%d] 0x%08x 0x%08x 0x%08x 0x%08x" +aes_cmd_data(uint32_t key, uint32_t iv, uint64_t src, uint64_t dst, uint32_t len) "[key=%d iv=%d] src=0x%"PRIx64" dst=0x%"PRIx64" len=0x%x" +aes_cmd_data_error(const char *reason) "reason=%s" +aes_cmd_store_iv(uint32_t ctx, uint64_t addr, uint32_t iv0, uint32_t iv1, uint32_t iv2, uint32_t iv3) "[%d] addr=0x%"PRIx64"x -> 0x%08x 0x%08x 0x%08x 0x%08x" +aes_cmd_flag(uint32_t raise, uint32_t flag_info) "raise=%d flag_info=0x%x" +aes_fifo_process(uint32_t cmd, uint32_t success) "cmd=%d success=%d" +aes_write_unknown(uint64_t offset) "offset=0x%"PRIx64 +aes_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64 +aes_2_read_unknown(uint64_t offset) "offset=0x%"PRIx64 +aes_2_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64 +aes_2_write_unknown(uint64_t offset) "offset=0x%"PRIx64 +aes_2_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64 +aes_dump_data(const char *desc, const char *hex) "%s%s" From patchwork Wed Aug 30 16:14:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370333 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 26B7AC83F01 for ; Wed, 30 Aug 2023 16:16:46 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNre-0004Ai-Om; Wed, 30 Aug 2023 12:16:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqf-0003IK-DQ; Wed, 30 Aug 2023 12:15:18 -0400 Received: from smtp-fw-2101.amazon.com ([72.21.196.25]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqc-0003lU-MP; Wed, 30 Aug 2023 12:15:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412115; x=1724948115; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PjBOs9GHZ8ulIk2A27xkdzM4rbnTalGiZF/fuDz1ROw=; b=DaQ611Z5LTeZiQAwcsXFVZC6nViqPjT/1k/p6mswbVLvxbkc7XWYz86r zc6ACOoPU8VH9PD16ZID4VpD/t7HRfQAAQTvEBSTCZvjTOs4CDcbmx5sl 0n+CJIL/XSavPpO0cOKUG+GhA2z9leHf6QTILMgznzs2B9Dcb20YP4UIS U=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="348536869" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-iad-1e-m6i4x-9694bb9e.us-east-1.amazon.com) ([10.43.8.6]) by smtp-border-fw-2101.iad2.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:14 +0000 Received: from EX19MTAUWB001.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1e-m6i4x-9694bb9e.us-east-1.amazon.com (Postfix) with ESMTPS id 2E23680C6B; Wed, 30 Aug 2023 16:15:08 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWB001.ant.amazon.com (10.250.64.248) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:53 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:51 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 08/12] hw/vmapple/bdif: Introduce vmapple backdoor interface Date: Wed, 30 Aug 2023 16:14:21 +0000 Message-ID: <20230830161425.91946-9-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D044UWA002.ant.amazon.com (10.13.139.11) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=72.21.196.25; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-2101.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org The VMApple machine exposes AUX and ROOT block devices (as well as USB OTG emulation) via virtio-pci as well as a special, simple backdoor platform device. This patch implements this backdoor platform device to the best of my understanding. I left out any USB OTG parts; they're only needed for guest recovery and I don't understand the protocol yet. Signed-off-by: Alexander Graf Reviewed-by: Stefan Hajnoczi --- v1 -> v2: - Adapt to system_ss meson.build target --- include/hw/vmapple/bdif.h | 31 +++++ hw/vmapple/bdif.c | 245 ++++++++++++++++++++++++++++++++++++++ hw/vmapple/Kconfig | 2 + hw/vmapple/meson.build | 1 + hw/vmapple/trace-events | 5 + 5 files changed, 284 insertions(+) create mode 100644 include/hw/vmapple/bdif.h create mode 100644 hw/vmapple/bdif.c diff --git a/include/hw/vmapple/bdif.h b/include/hw/vmapple/bdif.h new file mode 100644 index 0000000000..65ee43457b --- /dev/null +++ b/include/hw/vmapple/bdif.h @@ -0,0 +1,31 @@ +/* + * VMApple Backdoor Interface + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 HW_VMAPPLE_BDIF_H +#define HW_VMAPPLE_BDIF_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_VMAPPLE_BDIF "vmapple-bdif" +OBJECT_DECLARE_SIMPLE_TYPE(VMAppleBdifState, VMAPPLE_BDIF) + +struct VMAppleBdifState { + /* */ + SysBusDevice parent_obj; + + /* */ + BlockBackend *aux; + BlockBackend *root; + MemoryRegion mmio; +}; + +#define VMAPPLE_BDIF_SIZE 0x00200000 + +#endif /* HW_VMAPPLE_BDIF_H */ diff --git a/hw/vmapple/bdif.c b/hw/vmapple/bdif.c new file mode 100644 index 0000000000..36b5915ff3 --- /dev/null +++ b/hw/vmapple/bdif.c @@ -0,0 +1,245 @@ +/* + * VMApple Backdoor Interface + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/vmapple/bdif.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qapi/error.h" +#include "trace.h" +#include "hw/block/block.h" +#include "sysemu/block-backend.h" + +#define REG_DEVID_MASK 0xffff0000 +#define DEVID_ROOT 0x00000000 +#define DEVID_AUX 0x00010000 +#define DEVID_USB 0x00100000 + +#define REG_STATUS 0x0 +#define REG_STATUS_ACTIVE BIT(0) +#define REG_CFG 0x4 +#define REG_CFG_ACTIVE BIT(1) +#define REG_UNK1 0x8 +#define REG_BUSY 0x10 +#define REG_BUSY_READY BIT(0) +#define REG_UNK2 0x400 +#define REG_CMD 0x408 +#define REG_NEXT_DEVICE 0x420 +#define REG_UNK3 0x434 + +typedef struct vblk_sector { + uint32_t pad; + uint32_t pad2; + uint32_t sector; + uint32_t pad3; +} VblkSector; + +typedef struct vblk_req_cmd { + uint64_t addr; + uint32_t len; + uint32_t flags; +} VblkReqCmd; + +typedef struct vblk_req { + VblkReqCmd sector; + VblkReqCmd data; + VblkReqCmd retval; +} VblkReq; + +#define VBLK_DATA_FLAGS_READ 0x00030001 +#define VBLK_DATA_FLAGS_WRITE 0x00010001 + +#define VBLK_RET_SUCCESS 0 +#define VBLK_RET_FAILED 1 + +static uint64_t bdif_read(void *opaque, hwaddr offset, unsigned size) +{ + uint64_t ret = -1; + uint64_t devid = (offset & REG_DEVID_MASK); + + switch (offset & ~REG_DEVID_MASK) { + case REG_STATUS: + ret = REG_STATUS_ACTIVE; + break; + case REG_CFG: + ret = REG_CFG_ACTIVE; + break; + case REG_UNK1: + ret = 0x420; + break; + case REG_BUSY: + ret = REG_BUSY_READY; + break; + case REG_UNK2: + ret = 0x1; + break; + case REG_UNK3: + ret = 0x0; + break; + case REG_NEXT_DEVICE: + switch (devid) { + case DEVID_ROOT: + ret = 0x8000000; + break; + case DEVID_AUX: + ret = 0x10000; + break; + } + break; + } + + trace_bdif_read(offset, size, ret); + return ret; +} + +static void le2cpu_sector(VblkSector *sector) +{ + sector->sector = le32_to_cpu(sector->sector); +} + +static void le2cpu_reqcmd(VblkReqCmd *cmd) +{ + cmd->addr = le64_to_cpu(cmd->addr); + cmd->len = le32_to_cpu(cmd->len); + cmd->flags = le32_to_cpu(cmd->flags); +} + +static void le2cpu_req(VblkReq *req) +{ + le2cpu_reqcmd(&req->sector); + le2cpu_reqcmd(&req->data); + le2cpu_reqcmd(&req->retval); +} + +static void vblk_cmd(uint64_t devid, BlockBackend *blk, uint64_t value, + uint64_t static_off) +{ + VblkReq req; + VblkSector sector; + uint64_t off = 0; + char *buf = NULL; + uint8_t ret = VBLK_RET_FAILED; + int r; + + cpu_physical_memory_read(value, &req, sizeof(req)); + le2cpu_req(&req); + + if (req.sector.len != sizeof(sector)) { + ret = VBLK_RET_FAILED; + goto out; + } + + /* Read the vblk command */ + cpu_physical_memory_read(req.sector.addr, §or, sizeof(sector)); + le2cpu_sector(§or); + + off = sector.sector * 512ULL + static_off; + + /* Sanity check that we're not allocating bogus sizes */ + if (req.data.len > (128 * 1024 * 1024)) { + goto out; + } + + buf = g_malloc0(req.data.len); + switch (req.data.flags) { + case VBLK_DATA_FLAGS_READ: + r = blk_pread(blk, off, req.data.len, buf, 0); + trace_bdif_vblk_read(devid == DEVID_AUX ? "aux" : "root", + req.data.addr, off, req.data.len, r); + if (r < 0) { + goto out; + } + cpu_physical_memory_write(req.data.addr, buf, req.data.len); + ret = VBLK_RET_SUCCESS; + break; + case VBLK_DATA_FLAGS_WRITE: + /* Not needed, iBoot only reads */ + break; + default: + break; + } + +out: + g_free(buf); + cpu_physical_memory_write(req.retval.addr, &ret, 1); +} + +static void bdif_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + VMAppleBdifState *s = opaque; + uint64_t devid = (offset & REG_DEVID_MASK); + + trace_bdif_write(offset, size, value); + + switch (offset & ~REG_DEVID_MASK) { + case REG_CMD: + switch (devid) { + case DEVID_ROOT: + vblk_cmd(devid, s->root, value, 0x0); + break; + case DEVID_AUX: + vblk_cmd(devid, s->aux, value, 0x0); + break; + } + break; + } +} + +static const MemoryRegionOps bdif_ops = { + .read = bdif_read, + .write = bdif_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 8, + }, +}; + +static void bdif_init(Object *obj) +{ + VMAppleBdifState *s = VMAPPLE_BDIF(obj); + + memory_region_init_io(&s->mmio, obj, &bdif_ops, obj, + "VMApple Backdoor Interface", VMAPPLE_BDIF_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); +} + +static Property bdif_properties[] = { + DEFINE_PROP_DRIVE("aux", VMAppleBdifState, aux), + DEFINE_PROP_DRIVE("root", VMAppleBdifState, root), + DEFINE_PROP_END_OF_LIST(), +}; + +static void bdif_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "VMApple Backdoor Interface"; + device_class_set_props(dc, bdif_properties); +} + +static const TypeInfo bdif_info = { + .name = TYPE_VMAPPLE_BDIF, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(VMAppleBdifState), + .instance_init = bdif_init, + .class_init = bdif_class_init, +}; + +static void bdif_register_types(void) +{ + type_register_static(&bdif_info); +} + +type_init(bdif_register_types) diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig index a73504d599..388a2bc60c 100644 --- a/hw/vmapple/Kconfig +++ b/hw/vmapple/Kconfig @@ -1,3 +1,5 @@ config VMAPPLE_AES bool +config VMAPPLE_BDIF + bool diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build index bcd4dcb28d..d4624713de 100644 --- a/hw/vmapple/meson.build +++ b/hw/vmapple/meson.build @@ -1 +1,2 @@ system_ss.add(when: 'CONFIG_VMAPPLE_AES', if_true: files('aes.c')) +system_ss.add(when: 'CONFIG_VMAPPLE_BDIF', if_true: files('bdif.c')) diff --git a/hw/vmapple/trace-events b/hw/vmapple/trace-events index 03585cdf0f..45c69de2e0 100644 --- a/hw/vmapple/trace-events +++ b/hw/vmapple/trace-events @@ -18,3 +18,8 @@ aes_2_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64 aes_2_write_unknown(uint64_t offset) "offset=0x%"PRIx64 aes_2_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64 aes_dump_data(const char *desc, const char *hex) "%s%s" + +# bdif.c +bdif_read(uint64_t offset, uint32_t size, uint64_t value) "offset=0x%"PRIx64" size=0x%x value=0x%"PRIx64 +bdif_write(uint64_t offset, uint32_t size, uint64_t value) "offset=0x%"PRIx64" size=0x%x value=0x%"PRIx64 +bdif_vblk_read(const char *dev, uint64_t addr, uint64_t offset, uint32_t len, int r) "dev=%s addr=0x%"PRIx64" off=0x%"PRIx64" size=0x%x r=%d" From patchwork Wed Aug 30 16:14:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370336 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 80566C6FA8F for ; Wed, 30 Aug 2023 16:17:56 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNqc-0003Fn-2e; Wed, 30 Aug 2023 12:15:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqZ-0003Bj-UA; Wed, 30 Aug 2023 12:15:11 -0400 Received: from smtp-fw-80009.amazon.com ([99.78.197.220]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqV-0003qT-3V; Wed, 30 Aug 2023 12:15:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412107; x=1724948107; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FTij6Th0b1XMbAz1VN0jhKHdck3eoMUD7WrD28z5R4s=; b=U4XaKOhyV4X5DwC67aoW6KUajB/vlUhTN6thEoj/JOKGYd+HzixHlIIt 2VQwyVvd3MM6/9TbNsjWhdKnA8l8DARdNH/vLjyP5ZVyS+RGUgUHQt5R6 VZ4noCfaJYWqfsg2m+LP7PjvvJDullOf+xuO1bwYGcvGTWisAhnBYwlOQ 0=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="25940770" Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO email-inbound-relay-pdx-2a-m6i4x-af372327.us-west-2.amazon.com) ([10.25.36.210]) by smtp-border-fw-80009.pdx80.corp.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:00 +0000 Received: from EX19MTAUWC002.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan3.pdx.amazon.com [10.236.137.198]) by email-inbound-relay-pdx-2a-m6i4x-af372327.us-west-2.amazon.com (Postfix) with ESMTPS id 24C0260B41; Wed, 30 Aug 2023 16:14:59 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWC002.ant.amazon.com (10.250.64.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:57 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:55 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 09/12] hw/vmapple/cfg: Introduce vmapple cfg region Date: Wed, 30 Aug 2023 16:14:22 +0000 Message-ID: <20230830161425.91946-10-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D040UWA002.ant.amazon.com (10.13.139.113) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=99.78.197.220; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-80009.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org Instead of device tree or other more standardized means, VMApple passes platform configuration to the first stage boot loader in a binary encoded format that resides at a dedicated RAM region in physical address space. This patch models this configuration space as a qdev device which we can then map at the fixed location in the address space. That way, we can influence and annotate all configuration fields easily. Signed-off-by: Alexander Graf --- v1 -> v2: - Adapt to system_ss meson.build target --- include/hw/vmapple/cfg.h | 68 +++++++++++++++++++++++++ hw/vmapple/cfg.c | 105 +++++++++++++++++++++++++++++++++++++++ hw/vmapple/Kconfig | 3 ++ hw/vmapple/meson.build | 1 + 4 files changed, 177 insertions(+) create mode 100644 include/hw/vmapple/cfg.h create mode 100644 hw/vmapple/cfg.c diff --git a/include/hw/vmapple/cfg.h b/include/hw/vmapple/cfg.h new file mode 100644 index 0000000000..3337064e44 --- /dev/null +++ b/include/hw/vmapple/cfg.h @@ -0,0 +1,68 @@ +/* + * VMApple Configuration Region + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 HW_VMAPPLE_CFG_H +#define HW_VMAPPLE_CFG_H + +#include "hw/sysbus.h" +#include "qom/object.h" +#include "net/net.h" + +typedef struct VMAppleCfg { + uint32_t version; /* 0x000 */ + uint32_t nr_cpus; /* 0x004 */ + uint32_t unk1; /* 0x008 */ + uint32_t unk2; /* 0x00c */ + uint32_t unk3; /* 0x010 */ + uint32_t unk4; /* 0x014 */ + uint64_t ecid; /* 0x018 */ + uint64_t ram_size; /* 0x020 */ + uint32_t run_installer1; /* 0x028 */ + uint32_t unk5; /* 0x02c */ + uint32_t unk6; /* 0x030 */ + uint32_t run_installer2; /* 0x034 */ + uint32_t rnd; /* 0x038 */ + uint32_t unk7; /* 0x03c */ + MACAddr mac_en0; /* 0x040 */ + uint8_t pad1[2]; + MACAddr mac_en1; /* 0x048 */ + uint8_t pad2[2]; + MACAddr mac_wifi0; /* 0x050 */ + uint8_t pad3[2]; + MACAddr mac_bt0; /* 0x058 */ + uint8_t pad4[2]; + uint8_t reserved[0xa0]; /* 0x060 */ + uint32_t cpu_ids[0x80]; /* 0x100 */ + uint8_t scratch[0x200]; /* 0x180 */ + char serial[32]; /* 0x380 */ + char unk8[32]; /* 0x3a0 */ + char model[32]; /* 0x3c0 */ + uint8_t unk9[32]; /* 0x3e0 */ + uint32_t unk10; /* 0x400 */ + char soc_name[32]; /* 0x404 */ +} VMAppleCfg; + +#define TYPE_VMAPPLE_CFG "vmapple-cfg" +OBJECT_DECLARE_SIMPLE_TYPE(VMAppleCfgState, VMAPPLE_CFG) + +struct VMAppleCfgState { + /* */ + SysBusDevice parent_obj; + VMAppleCfg cfg; + + /* */ + MemoryRegion mem; + char *serial; + char *model; + char *soc_name; +}; + +#define VMAPPLE_CFG_SIZE 0x00010000 + +#endif /* HW_VMAPPLE_CFG_H */ diff --git a/hw/vmapple/cfg.c b/hw/vmapple/cfg.c new file mode 100644 index 0000000000..d48e3c3afa --- /dev/null +++ b/hw/vmapple/cfg.c @@ -0,0 +1,105 @@ +/* + * VMApple Configuration Region + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/vmapple/cfg.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qapi/error.h" + +static void vmapple_cfg_reset(DeviceState *dev) +{ + VMAppleCfgState *s = VMAPPLE_CFG(dev); + VMAppleCfg *cfg; + + cfg = memory_region_get_ram_ptr(&s->mem); + memset((void *)cfg, 0, VMAPPLE_CFG_SIZE); + *cfg = s->cfg; +} + +static void vmapple_cfg_realize(DeviceState *dev, Error **errp) +{ + VMAppleCfgState *s = VMAPPLE_CFG(dev); + uint32_t i; + + strncpy(s->cfg.serial, s->serial, sizeof(s->cfg.serial)); + strncpy(s->cfg.model, s->model, sizeof(s->cfg.model)); + strncpy(s->cfg.soc_name, s->soc_name, sizeof(s->cfg.soc_name)); + strncpy(s->cfg.unk8, "D/A", sizeof(s->cfg.soc_name)); + s->cfg.ecid = cpu_to_be64(s->cfg.ecid); + s->cfg.version = 2; + s->cfg.unk1 = 1; + s->cfg.unk2 = 1; + s->cfg.unk3 = 0x20; + s->cfg.unk4 = 0; + s->cfg.unk5 = 1; + s->cfg.unk6 = 1; + s->cfg.unk7 = 0; + s->cfg.unk10 = 1; + + g_assert(s->cfg.nr_cpus < ARRAY_SIZE(s->cfg.cpu_ids)); + for (i = 0; i < s->cfg.nr_cpus; i++) { + s->cfg.cpu_ids[i] = i; + } +} + +static void vmapple_cfg_init(Object *obj) +{ + VMAppleCfgState *s = VMAPPLE_CFG(obj); + + memory_region_init_ram(&s->mem, obj, "VMApple Config", VMAPPLE_CFG_SIZE, + &error_fatal); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mem); + + s->serial = (char *)"1234"; + s->model = (char *)"VM0001"; + s->soc_name = (char *)"Apple M1 (Virtual)"; +} + +static Property vmapple_cfg_properties[] = { + DEFINE_PROP_UINT32("nr-cpus", VMAppleCfgState, cfg.nr_cpus, 1), + DEFINE_PROP_UINT64("ecid", VMAppleCfgState, cfg.ecid, 0), + DEFINE_PROP_UINT64("ram-size", VMAppleCfgState, cfg.ram_size, 0), + DEFINE_PROP_UINT32("run_installer1", VMAppleCfgState, cfg.run_installer1, 0), + DEFINE_PROP_UINT32("run_installer2", VMAppleCfgState, cfg.run_installer2, 0), + DEFINE_PROP_UINT32("rnd", VMAppleCfgState, cfg.rnd, 0), + DEFINE_PROP_MACADDR("mac-en0", VMAppleCfgState, cfg.mac_en0), + DEFINE_PROP_MACADDR("mac-en1", VMAppleCfgState, cfg.mac_en1), + DEFINE_PROP_MACADDR("mac-wifi0", VMAppleCfgState, cfg.mac_wifi0), + DEFINE_PROP_MACADDR("mac-bt0", VMAppleCfgState, cfg.mac_bt0), + DEFINE_PROP_STRING("serial", VMAppleCfgState, serial), + DEFINE_PROP_STRING("model", VMAppleCfgState, model), + DEFINE_PROP_STRING("soc_name", VMAppleCfgState, soc_name), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vmapple_cfg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = vmapple_cfg_realize; + dc->desc = "VMApple Configuration Region"; + device_class_set_props(dc, vmapple_cfg_properties); + dc->reset = vmapple_cfg_reset; +} + +static const TypeInfo vmapple_cfg_info = { + .name = TYPE_VMAPPLE_CFG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(VMAppleCfgState), + .instance_init = vmapple_cfg_init, + .class_init = vmapple_cfg_class_init, +}; + +static void vmapple_cfg_register_types(void) +{ + type_register_static(&vmapple_cfg_info); +} + +type_init(vmapple_cfg_register_types) diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig index 388a2bc60c..542426a740 100644 --- a/hw/vmapple/Kconfig +++ b/hw/vmapple/Kconfig @@ -3,3 +3,6 @@ config VMAPPLE_AES config VMAPPLE_BDIF bool + +config VMAPPLE_CFG + bool diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build index d4624713de..64b78693a3 100644 --- a/hw/vmapple/meson.build +++ b/hw/vmapple/meson.build @@ -1,2 +1,3 @@ system_ss.add(when: 'CONFIG_VMAPPLE_AES', if_true: files('aes.c')) system_ss.add(when: 'CONFIG_VMAPPLE_BDIF', if_true: files('bdif.c')) +system_ss.add(when: 'CONFIG_VMAPPLE_CFG', if_true: files('cfg.c')) From patchwork Wed Aug 30 16:14:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370339 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id AEF1DC6FA8F for ; Wed, 30 Aug 2023 16:18:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNsr-0005Ov-2w; Wed, 30 Aug 2023 12:17:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqe-0003H1-PU; Wed, 30 Aug 2023 12:15:18 -0400 Received: from smtp-fw-52005.amazon.com ([52.119.213.156]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqb-0003sA-75; Wed, 30 Aug 2023 12:15:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412113; x=1724948113; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3e1K/TjjV3tcSIlIyQdU0K6xREaE5PTfl9+CbjDOZ9A=; b=k1lSh4l4PFfoCj9lEa8RZWrsjzOdHapVhJFNLwtTXLLvNVL9JI6ul2xF ADofy6YMgHg8VR7LuELyn0lurNc+e/PeG/YJmWu6Lt2uj/90SHlOzjhzc VUCy+9bygsHYKei8G4DFQ34q79vIr4HwSh13HWr1KoPGZiDoSP5eB4Bon 0=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="601819211" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-iad-1e-m6i4x-7dc0ecf1.us-east-1.amazon.com) ([10.43.8.6]) by smtp-border-fw-52005.iad7.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:11 +0000 Received: from EX19MTAUWC001.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1e-m6i4x-7dc0ecf1.us-east-1.amazon.com (Postfix) with ESMTPS id 22750808EF; Wed, 30 Aug 2023 16:15:07 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWC001.ant.amazon.com (10.250.64.174) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:15:00 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:14:57 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 10/12] hw/vmapple/apple-gfx: Introduce ParavirtualizedGraphics.Framework support Date: Wed, 30 Aug 2023 16:14:23 +0000 Message-ID: <20230830161425.91946-11-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D040UWA002.ant.amazon.com (10.13.139.113) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=52.119.213.156; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-52005.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org MacOS provides a framework (library) that allows any vmm to implement a paravirtualized 3d graphics passthrough to the host metal stack called ParavirtualizedGraphics.Framework (PVG). The library abstracts away almost every aspect of the paravirtualized device model and only provides and receives callbacks on MMIO access as well as to share memory address space between the VM and PVG. This patch implements a QEMU device that drives PVG for the VMApple variant of it. Signed-off-by: Alexander Graf Tested-by: Phil Dennis-Jordan --- v1 -> v2: - Adapt to system_ss meson.build target --- meson.build | 4 + hw/vmapple/Kconfig | 3 + hw/vmapple/apple-gfx.m | 578 ++++++++++++++++++++++++++++++++++++++++ hw/vmapple/meson.build | 1 + hw/vmapple/trace-events | 22 ++ 5 files changed, 608 insertions(+) create mode 100644 hw/vmapple/apple-gfx.m diff --git a/meson.build b/meson.build index dc5242a5f4..d34310b5eb 100644 --- a/meson.build +++ b/meson.build @@ -607,6 +607,8 @@ socket = [] version_res = [] coref = [] iokit = [] +pvg = [] +metal = [] emulator_link_args = [] nvmm =not_found hvf = not_found @@ -630,6 +632,8 @@ elif targetos == 'darwin' coref = dependency('appleframeworks', modules: 'CoreFoundation') iokit = dependency('appleframeworks', modules: 'IOKit', required: false) host_dsosuf = '.dylib' + pvg = dependency('appleframeworks', modules: 'ParavirtualizedGraphics') + metal = dependency('appleframeworks', modules: 'Metal') elif targetos == 'sunos' socket = [cc.find_library('socket'), cc.find_library('nsl'), diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig index 542426a740..ba37fc5b81 100644 --- a/hw/vmapple/Kconfig +++ b/hw/vmapple/Kconfig @@ -6,3 +6,6 @@ config VMAPPLE_BDIF config VMAPPLE_CFG bool + +config VMAPPLE_PVG + bool diff --git a/hw/vmapple/apple-gfx.m b/hw/vmapple/apple-gfx.m new file mode 100644 index 0000000000..97dd2cd9ae --- /dev/null +++ b/hw/vmapple/apple-gfx.m @@ -0,0 +1,578 @@ +/* + * QEMU Apple ParavirtualizedGraphics.framework device + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * ParavirtualizedGraphics.framework is a set of libraries that macOS provides + * which implements 3d graphics passthrough to the host as well as a + * proprietary guest communication channel to drive it. This device model + * implements support to drive that library from within QEMU. + */ + +#include "qemu/osdep.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "trace.h" +#include "hw/sysbus.h" +#include "hw/pci/msi.h" +#include "crypto/hash.h" +#include "sysemu/cpus.h" +#include "ui/console.h" +#include "monitor/monitor.h" +#import + +#define TYPE_APPLE_GFX "apple-gfx" + +#define MAX_MRS 512 + +static const PGDisplayCoord_t apple_gfx_modes[] = { + { .x = 1440, .y = 1080 }, + { .x = 1280, .y = 1024 }, +}; + +/* + * We have to map PVG memory into our address space. Use the one below + * as base start address. In normal linker setups it points to a free + * memory range. + */ +#define APPLE_GFX_BASE_VA ((void *)(uintptr_t)0x500000000000UL) + +/* + * ParavirtualizedGraphics.Framework only ships header files for the x86 + * variant which does not include IOSFC descriptors and host devices. We add + * their definitions here so that we can also work with the ARM version. + */ +typedef bool(^IOSFCRaiseInterrupt)(uint32_t vector); +typedef bool(^IOSFCUnmapMemory)(void *a, void *b, void *c, void *d, void *e, void *f); +typedef bool(^IOSFCMapMemory)(uint64_t phys, uint64_t len, bool ro, void **va, void *e, void *f); + +@interface PGDeviceDescriptorExt : PGDeviceDescriptor +@property (readwrite, nonatomic) bool usingIOSurfaceMapper; +@end + +@interface PGIOSurfaceHostDeviceDescriptor : NSObject +-(PGIOSurfaceHostDeviceDescriptor *)init; +@property (readwrite, nonatomic, copy, nullable) IOSFCMapMemory mapMemory; +@property (readwrite, nonatomic, copy, nullable) IOSFCUnmapMemory unmapMemory; +@property (readwrite, nonatomic, copy, nullable) IOSFCRaiseInterrupt raiseInterrupt; +@end + +@interface PGIOSurfaceHostDevice : NSObject +-(void)initWithDescriptor:(PGIOSurfaceHostDeviceDescriptor *) desc; +-(uint32_t)mmioReadAtOffset:(size_t) offset; +-(void)mmioWriteAtOffset:(size_t) offset value:(uint32_t)value; +@end + +typedef struct AppleGFXMR { + QTAILQ_ENTRY(AppleGFXMR) node; + hwaddr pa; + void *va; + uint64_t len; +} AppleGFXMR; + +typedef QTAILQ_HEAD(, AppleGFXMR) AppleGFXMRList; + +typedef struct AppleGFXTask { + QTAILQ_ENTRY(AppleGFXTask) node; + void *mem; + uint64_t len; +} AppleGFXTask; + +typedef QTAILQ_HEAD(, AppleGFXTask) AppleGFXTaskList; + +typedef struct AppleGFXState { + /* Private */ + SysBusDevice parent_obj; + + /* Public */ + qemu_irq irq_gfx; + qemu_irq irq_iosfc; + MemoryRegion iomem_gfx; + MemoryRegion iomem_iosfc; + id pgdev; + id pgdisp; + PGIOSurfaceHostDevice *pgiosfc; + AppleGFXMRList mrs; + AppleGFXTaskList tasks; + QemuConsole *con; + void *vram; + id mtl; + id texture; + bool handles_frames; + bool new_frame; + bool cursor_show; + DisplaySurface *surface; + QEMUCursor *cursor; +} AppleGFXState; + + +OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXState, APPLE_GFX) + +static AppleGFXTask *apple_gfx_new_task(AppleGFXState *s, uint64_t len) +{ + void *base = APPLE_GFX_BASE_VA; + AppleGFXTask *task; + + QTAILQ_FOREACH(task, &s->tasks, node) { + if ((task->mem + task->len) > base) { + base = task->mem + task->len; + } + } + + task = g_new0(AppleGFXTask, 1); + + task->len = len; + task->mem = base; + QTAILQ_INSERT_TAIL(&s->tasks, task, node); + + return task; +} + +static AppleGFXMR *apple_gfx_mapMemory(AppleGFXState *s, AppleGFXTask *task, + uint64_t voff, uint64_t phys, uint64_t len) +{ + AppleGFXMR *mr = g_new0(AppleGFXMR, 1); + + mr->pa = phys; + mr->len = len; + mr->va = task->mem + voff; + QTAILQ_INSERT_TAIL(&s->mrs, mr, node); + + return mr; +} + +static uint64_t apple_gfx_read(void *opaque, hwaddr offset, unsigned size) +{ + AppleGFXState *s = opaque; + uint64_t res = 0; + + switch (offset) { + default: + res = [s->pgdev mmioReadAtOffset:offset]; + break; + } + + trace_apple_gfx_read(offset, res); + + return res; +} + +static void apple_gfx_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) +{ + AppleGFXState *s = opaque; + + trace_apple_gfx_write(offset, val); + + qemu_mutex_unlock_iothread(); + [s->pgdev mmioWriteAtOffset:offset value:val]; + qemu_mutex_lock_iothread(); +} + +static const MemoryRegionOps apple_gfx_ops = { + .read = apple_gfx_read, + .write = apple_gfx_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static uint64_t apple_iosfc_read(void *opaque, hwaddr offset, unsigned size) +{ + AppleGFXState *s = opaque; + uint64_t res = 0; + + qemu_mutex_unlock_iothread(); + res = [s->pgiosfc mmioReadAtOffset:offset]; + qemu_mutex_lock_iothread(); + + trace_apple_iosfc_read(offset, res); + + return res; +} + +static void apple_iosfc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) +{ + AppleGFXState *s = opaque; + + trace_apple_iosfc_write(offset, val); + + [s->pgiosfc mmioWriteAtOffset:offset value:val]; +} + +static const MemoryRegionOps apple_iosfc_ops = { + .read = apple_iosfc_read, + .write = apple_iosfc_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 8, + }, +}; + +static void apple_gfx_fb_update_display(void *opaque) +{ + AppleGFXState *s = opaque; + + if (!s->new_frame || !s->handles_frames) { + return; + } + + s->new_frame = false; + + BOOL r; + uint32_t width = surface_width(s->surface); + uint32_t height = surface_height(s->surface); + MTLRegion region = MTLRegionMake2D(0, 0, width, height); + id commandQueue = [s->mtl newCommandQueue]; + id mipmapCommandBuffer = [commandQueue commandBuffer]; + + r = [s->pgdisp encodeCurrentFrameToCommandBuffer:mipmapCommandBuffer + texture:s->texture + region:region]; + + if (r != YES) { + return; + } + + id blitCommandEncoder = [mipmapCommandBuffer blitCommandEncoder]; + [blitCommandEncoder generateMipmapsForTexture:s->texture]; + [blitCommandEncoder endEncoding]; + [mipmapCommandBuffer commit]; + [mipmapCommandBuffer waitUntilCompleted]; + [s->texture getBytes:s->vram bytesPerRow:(width * 4) + bytesPerImage: (width * height * 4) + fromRegion: region + mipmapLevel: 0 + slice: 0]; + + /* Need to render cursor manually if not supported by backend */ + if (!dpy_cursor_define_supported(s->con) && s->cursor && s->cursor_show) { + pixman_image_t *image = + pixman_image_create_bits(PIXMAN_a8r8g8b8, + s->cursor->width, + s->cursor->height, + (uint32_t *)s->cursor->data, + s->cursor->width * 4); + + pixman_image_composite(PIXMAN_OP_OVER, + image, NULL, s->surface->image, + 0, 0, 0, 0, s->pgdisp.cursorPosition.x, + s->pgdisp.cursorPosition.y, s->cursor->width, + s->cursor->height); + + pixman_image_unref(image); + } + + dpy_gfx_update_full(s->con); + + [commandQueue release]; +} + +static const GraphicHwOps apple_gfx_fb_ops = { + .gfx_update = apple_gfx_fb_update_display, +}; + +static void update_cursor(AppleGFXState *s) +{ + dpy_mouse_set(s->con, s->pgdisp.cursorPosition.x, s->pgdisp.cursorPosition.y, s->cursor_show); + + /* Need to render manually if cursor is not natively supported */ + if (!dpy_cursor_define_supported(s->con)) { + s->new_frame = true; + } +} + +static void set_mode(AppleGFXState *s, uint32_t width, uint32_t height) +{ + void *vram = g_malloc0(width * height * 4); + void *old_vram = s->vram; + DisplaySurface *surface; + MTLTextureDescriptor *textureDescriptor; + id old_texture = s->texture; + + if (s->surface && + width == surface_width(s->surface) && + height == surface_height(s->surface)) { + return; + } + surface = qemu_create_displaysurface_from(width, height, PIXMAN_LE_a8r8g8b8, + width * 4, vram); + s->surface = surface; + dpy_gfx_replace_surface(s->con, surface); + s->vram = vram; + g_free(old_vram); + + textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm + width:width + height:height + mipmapped:NO]; + textureDescriptor.usage = s->pgdisp.minimumTextureUsage; + s->texture = [s->mtl newTextureWithDescriptor:textureDescriptor]; + + if (old_texture) { + [old_texture release]; + } +} + +static void create_fb(AppleGFXState *s) +{ + + s->con = graphic_console_init(NULL, 0, &apple_gfx_fb_ops, s); + set_mode(s, 1440, 1080); + + s->cursor_show = true; +} + +static void apple_gfx_reset(DeviceState *d) +{ +} + +static void apple_gfx_init(Object *obj) +{ + AppleGFXState *s = APPLE_GFX(obj); + + memory_region_init_io(&s->iomem_gfx, obj, &apple_gfx_ops, s, TYPE_APPLE_GFX, 0x4000); + memory_region_init_io(&s->iomem_iosfc, obj, &apple_iosfc_ops, s, TYPE_APPLE_GFX, 0x10000); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem_gfx); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem_iosfc); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_gfx); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_iosfc); +} + +static void apple_gfx_realize(DeviceState *dev, Error **errp) +{ + AppleGFXState *s = APPLE_GFX(dev); + PGDeviceDescriptor *desc = [PGDeviceDescriptor new]; + PGDisplayDescriptor *disp_desc = [PGDisplayDescriptor new]; + PGIOSurfaceHostDeviceDescriptor *iosfc_desc = [PGIOSurfaceHostDeviceDescriptor new]; + PGDeviceDescriptorExt *desc_ext = (PGDeviceDescriptorExt *)desc; + PGDisplayMode *modes[ARRAY_SIZE(apple_gfx_modes)]; + int i; + + for (i = 0; i < ARRAY_SIZE(apple_gfx_modes); i++) { + modes[i] = [PGDisplayMode new]; + [modes[i] initWithSizeInPixels:apple_gfx_modes[i] refreshRateInHz:60.]; + } + + s->mtl = MTLCreateSystemDefaultDevice(); + + desc.device = s->mtl; + desc_ext.usingIOSurfaceMapper = true; + + desc.createTask = ^(uint64_t vmSize, void * _Nullable * _Nonnull baseAddress) { + AppleGFXTask *task = apple_gfx_new_task(s, vmSize); + *baseAddress = task->mem; + trace_apple_gfx_create_task(vmSize, *baseAddress); + return (PGTask_t *)task; + }; + + desc.destroyTask = ^(PGTask_t * _Nonnull _task) { + AppleGFXTask *task = (AppleGFXTask *)_task; + trace_apple_gfx_destroy_task(task); + QTAILQ_REMOVE(&s->tasks, task, node); + g_free(task); + }; + + desc.mapMemory = ^(PGTask_t * _Nonnull _task, uint32_t rangeCount, uint64_t virtualOffset, bool readOnly, PGPhysicalMemoryRange_t * _Nonnull ranges) { + AppleGFXTask *task = (AppleGFXTask*)_task; + mach_port_t mtask = mach_task_self(); + trace_apple_gfx_map_memory(task, rangeCount, virtualOffset, readOnly); + for (int i = 0; i < rangeCount; i++) { + PGPhysicalMemoryRange_t *range = &ranges[i]; + MemoryRegion *tmp_mr; + /* TODO: Bounds checks? r/o? */ + qemu_mutex_lock_iothread(); + AppleGFXMR *mr = apple_gfx_mapMemory(s, task, virtualOffset, + range->physicalAddress, + range->physicalLength); + + trace_apple_gfx_map_memory_range(i, range->physicalAddress, range->physicalLength, mr->va); + + vm_address_t target = (vm_address_t)mr->va; + uint64_t mask = 0; + bool anywhere = false; + vm_address_t source = (vm_address_t)gpa2hva(&tmp_mr, mr->pa, mr->len, NULL); + vm_prot_t cur_protection = 0; + vm_prot_t max_protection = 0; + kern_return_t retval = vm_remap(mtask, &target, mr->len, mask, + anywhere, mtask, source, false, + &cur_protection, &max_protection, + VM_INHERIT_DEFAULT); + trace_apple_gfx_remap(retval, source, target); + g_assert(retval == KERN_SUCCESS); + + qemu_mutex_unlock_iothread(); + + virtualOffset += mr->len; + } + return (bool)true; + }; + + desc.unmapMemory = ^(PGTask_t * _Nonnull _task, uint64_t virtualOffset, uint64_t length) { + AppleGFXTask *task = (AppleGFXTask *)_task; + AppleGFXMR *mr, *next; + + trace_apple_gfx_unmap_memory(task, virtualOffset, length); + qemu_mutex_lock_iothread(); + QTAILQ_FOREACH_SAFE(mr, &s->mrs, node, next) { + if (mr->va >= (task->mem + virtualOffset) && + (mr->va + mr->len) <= (task->mem + virtualOffset + length)) { + vm_address_t addr = (vm_address_t)mr->va; + vm_deallocate(mach_task_self(), addr, mr->len); + QTAILQ_REMOVE(&s->mrs, mr, node); + g_free(mr); + } + } + qemu_mutex_unlock_iothread(); + return (bool)true; + }; + + desc.readMemory = ^(uint64_t physicalAddress, uint64_t length, void * _Nonnull dst) { + trace_apple_gfx_read_memory(physicalAddress, length, dst); + cpu_physical_memory_read(physicalAddress, dst, length); + return (bool)true; + }; + + desc.raiseInterrupt = ^(uint32_t vector) { + bool locked; + + trace_apple_gfx_raise_irq(vector); + locked = qemu_mutex_iothread_locked(); + if (!locked) { + qemu_mutex_lock_iothread(); + } + qemu_irq_pulse(s->irq_gfx); + if (!locked) { + qemu_mutex_unlock_iothread(); + } + }; + + desc.addTraceRange = ^(PGPhysicalMemoryRange_t * _Nonnull range, PGTraceRangeHandler _Nonnull handler) { + /* Never saw this called. Return a bogus pointer so we catch access. */ + return (PGTraceRange_t *)(void *)(uintptr_t)0x4242; + }; + + desc.removeTraceRange = ^(PGTraceRange_t * _Nonnull range) { + /* Never saw this called. Nothing to do. */ + }; + s->pgdev = PGNewDeviceWithDescriptor(desc); + + [disp_desc init]; + disp_desc.name = @"QEMU display"; + disp_desc.sizeInMillimeters = NSMakeSize(400., 300.); /* A 20" display */ + disp_desc.queue = dispatch_get_main_queue(); + disp_desc.newFrameEventHandler = ^(void) { + trace_apple_gfx_new_frame(); + + /* Tell QEMU gfx stack that a new frame arrived */ + s->handles_frames = true; + s->new_frame = true; + }; + disp_desc.modeChangeHandler = ^(PGDisplayCoord_t sizeInPixels, OSType pixelFormat) { + trace_apple_gfx_mode_change(sizeInPixels.x, sizeInPixels.y); + set_mode(s, sizeInPixels.x, sizeInPixels.y); + }; + disp_desc.cursorGlyphHandler = ^(NSBitmapImageRep *glyph, PGDisplayCoord_t hotSpot) { + uint32_t bpp = glyph.bitsPerPixel; + uint64_t width = glyph.pixelsWide; + uint64_t height = glyph.pixelsHigh; + + trace_apple_gfx_cursor_set(bpp, width, height); + + if (s->cursor) { + cursor_unref(s->cursor); + } + s->cursor = cursor_alloc(width, height); + + /* TODO handle different bpp */ + if (bpp == 32) { + memcpy(s->cursor->data, glyph.bitmapData, glyph.bytesPerPlane); + dpy_cursor_define(s->con, s->cursor); + update_cursor(s); + } + }; + disp_desc.cursorShowHandler = ^(BOOL show) { + trace_apple_gfx_cursor_show(show); + s->cursor_show = show; + update_cursor(s); + }; + disp_desc.cursorMoveHandler = ^(void) { + trace_apple_gfx_cursor_move(); + update_cursor(s); + }; + + s->pgdisp = [s->pgdev newDisplayWithDescriptor:disp_desc port:0 serialNum:1234]; + s->pgdisp.modeList = [NSArray arrayWithObjects:modes count:ARRAY_SIZE(apple_gfx_modes)]; + + [iosfc_desc init]; + iosfc_desc.mapMemory = ^(uint64_t phys, uint64_t len, bool ro, void **va, void *e, void *f) { + trace_apple_iosfc_map_memory(phys, len, ro, va, e, f); + MemoryRegion *tmp_mr; + *va = gpa2hva(&tmp_mr, phys, len, NULL); + return (bool)true; + }; + + iosfc_desc.unmapMemory = ^(void *a, void *b, void *c, void *d, void *e, void *f) { + trace_apple_iosfc_unmap_memory(a, b, c, d, e, f); + return (bool)true; + }; + + iosfc_desc.raiseInterrupt = ^(uint32_t vector) { + trace_apple_iosfc_raise_irq(vector); + bool locked = qemu_mutex_iothread_locked(); + if (!locked) { + qemu_mutex_lock_iothread(); + } + qemu_irq_pulse(s->irq_iosfc); + if (!locked) { + qemu_mutex_unlock_iothread(); + } + return (bool)true; + }; + + s->pgiosfc = [PGIOSurfaceHostDevice new]; + [s->pgiosfc initWithDescriptor:iosfc_desc]; + + QTAILQ_INIT(&s->mrs); + QTAILQ_INIT(&s->tasks); + + create_fb(s); +} + +static void apple_gfx_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = apple_gfx_reset; + dc->realize = apple_gfx_realize; +} + +static TypeInfo apple_gfx_info = { + .name = TYPE_APPLE_GFX, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AppleGFXState), + .class_init = apple_gfx_class_init, + .instance_init = apple_gfx_init, +}; + +static void apple_gfx_register_types(void) +{ + type_register_static(&apple_gfx_info); +} + +type_init(apple_gfx_register_types) diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build index 64b78693a3..74a0d7a5f1 100644 --- a/hw/vmapple/meson.build +++ b/hw/vmapple/meson.build @@ -1,3 +1,4 @@ system_ss.add(when: 'CONFIG_VMAPPLE_AES', if_true: files('aes.c')) system_ss.add(when: 'CONFIG_VMAPPLE_BDIF', if_true: files('bdif.c')) system_ss.add(when: 'CONFIG_VMAPPLE_CFG', if_true: files('cfg.c')) +system_ss.add(when: 'CONFIG_VMAPPLE_PVG', if_true: [files('apple-gfx.m'), pvg, metal]) diff --git a/hw/vmapple/trace-events b/hw/vmapple/trace-events index 45c69de2e0..078e679560 100644 --- a/hw/vmapple/trace-events +++ b/hw/vmapple/trace-events @@ -23,3 +23,25 @@ aes_dump_data(const char *desc, const char *hex) "%s%s" bdif_read(uint64_t offset, uint32_t size, uint64_t value) "offset=0x%"PRIx64" size=0x%x value=0x%"PRIx64 bdif_write(uint64_t offset, uint32_t size, uint64_t value) "offset=0x%"PRIx64" size=0x%x value=0x%"PRIx64 bdif_vblk_read(const char *dev, uint64_t addr, uint64_t offset, uint32_t len, int r) "dev=%s addr=0x%"PRIx64" off=0x%"PRIx64" size=0x%x r=%d" + +# apple-gfx.m +apple_gfx_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64 +apple_gfx_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64 +apple_gfx_create_task(uint32_t vm_size, void *va) "vm_size=0x%x base_addr=%p" +apple_gfx_destroy_task(void *task) "task=%p" +apple_gfx_map_memory(void *task, uint32_t range_count, uint64_t virtual_offset, uint32_t read_only) "task=%p range_count=0x%x virtual_offset=0x%"PRIx64" read_only=%d" +apple_gfx_map_memory_range(uint32_t i, uint64_t phys_addr, uint64_t phys_len, void *va) "[%d] phys_addr=0x%"PRIx64" phys_len=0x%"PRIx64" va=%p" +apple_gfx_remap(uint64_t retval, uint64_t source, uint64_t target) "retval=%"PRId64" source=0x%"PRIx64" target=0x%"PRIx64 +apple_gfx_unmap_memory(void *task, uint64_t virtual_offset, uint64_t length) "task=%p virtual_offset=0x%"PRIx64" length=0x%"PRIx64 +apple_gfx_read_memory(uint64_t phys_address, uint64_t length, void *dst) "phys_addr=0x%"PRIx64" length=0x%"PRIx64" dest=%p" +apple_gfx_raise_irq(uint32_t vector) "vector=0x%x" +apple_gfx_new_frame(void) "" +apple_gfx_mode_change(uint64_t x, uint64_t y) "x=%"PRId64" y=%"PRId64 +apple_gfx_cursor_set(uint32_t bpp, uint64_t width, uint64_t height) "bpp=%d width=%"PRId64" height=0x%"PRId64 +apple_gfx_cursor_show(uint32_t show) "show=%d" +apple_gfx_cursor_move(void) "" +apple_iosfc_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64 +apple_iosfc_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64 +apple_iosfc_map_memory(uint64_t phys, uint64_t len, uint32_t ro, void *va, void *e, void *f) "phys=0x%"PRIx64" len=0x%"PRIx64" ro=%d va=%p e=%p f=%p" +apple_iosfc_unmap_memory(void *a, void *b, void *c, void *d, void *e, void *f) "a=%p b=%p c=%p d=%p e=%p f=%p" +apple_iosfc_raise_irq(uint32_t vector) "vector=0x%x" From patchwork Wed Aug 30 16:14:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370334 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 13C13C83F01 for ; Wed, 30 Aug 2023 16:17:14 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNrF-0003lS-OD; Wed, 30 Aug 2023 12:15:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqc-0003GS-M6; Wed, 30 Aug 2023 12:15:16 -0400 Received: from smtp-fw-52004.amazon.com ([52.119.213.154]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqY-0003rC-Ge; Wed, 30 Aug 2023 12:15:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412111; x=1724948111; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HjBlQeN1Y1+S0cLeAYRYcUWhTSG9q28X6IWlXsIuh7k=; b=FcTOKX84SCbTao4YNO6pSyF8Goo/ZQn+dgxjoLtPgO4ZfDKtuevrAihE 8C+PYQH+sUP83LkL4IJzvHlmS84bfxoVFGFQ9/UlgZWWttAHa+N19Umau TiFguIV1GzwXNqdCInDUhv2stF0F738xEAs+S6qb7F5p+wzUrXTM+cE0H k=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="151694715" Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-pdx-2c-m6i4x-5eae960a.us-west-2.amazon.com) ([10.43.8.2]) by smtp-border-fw-52004.iad7.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:05 +0000 Received: from EX19MTAUWB002.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan3.pdx.amazon.com [10.236.137.198]) by email-inbound-relay-pdx-2c-m6i4x-5eae960a.us-west-2.amazon.com (Postfix) with ESMTPS id 2C6FB40DCB; Wed, 30 Aug 2023 16:15:03 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWB002.ant.amazon.com (10.250.64.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:15:02 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:15:00 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 11/12] hw/vmapple/virtio-blk: Add support for apple virtio-blk Date: Wed, 30 Aug 2023 16:14:24 +0000 Message-ID: <20230830161425.91946-12-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D040UWA002.ant.amazon.com (10.13.139.113) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=52.119.213.154; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-52004.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org Apple has its own virtio-blk PCI device ID where it deviates from the official virtio-pci spec slightly: It puts a new "apple type" field at a static offset in config space and introduces a new barrier command. This patch first creates a mechanism for virtio-blk downstream classes to handle unknown commands. It then creates such a downstream class and a new vmapple-virtio-blk-pci class which support the additional apple type config identifier as well as the barrier command. It then exposes 2 subclasses from that that we can use to expose root and aux virtio-blk devices: "vmapple-virtio-root" and "vmapple-virtio-aux". Signed-off-by: Alexander Graf Reviewed-by: Stefan Hajnoczi --- v1 -> v2: - Rework to make all vmapple virtio-blk logic a subclass --- include/hw/pci/pci_ids.h | 1 + include/hw/virtio/virtio-blk.h | 12 +- include/hw/vmapple/virtio-blk.h | 39 ++++++ hw/block/virtio-blk.c | 19 ++- hw/vmapple/virtio-blk.c | 212 ++++++++++++++++++++++++++++++++ hw/vmapple/Kconfig | 3 + hw/vmapple/meson.build | 1 + 7 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 include/hw/vmapple/virtio-blk.h create mode 100644 hw/vmapple/virtio-blk.c diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index e4386ebb20..74e589a298 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -188,6 +188,7 @@ #define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020 #define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021 +#define PCI_DEVICE_ID_APPLE_VIRTIO_BLK 0x1a00 #define PCI_VENDOR_ID_SUN 0x108e #define PCI_DEVICE_ID_SUN_EBUS 0x1000 diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index dafec432ce..381a906410 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -23,7 +23,7 @@ #include "qom/object.h" #define TYPE_VIRTIO_BLK "virtio-blk-device" -OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBlock, VIRTIO_BLK) +OBJECT_DECLARE_TYPE(VirtIOBlock, VirtIOBlkClass, VIRTIO_BLK) /* This is the last element of the write scatter-gather list */ struct virtio_blk_inhdr @@ -91,6 +91,16 @@ typedef struct MultiReqBuffer { bool is_write; } MultiReqBuffer; +typedef struct VirtIOBlkClass { + /*< private >*/ + VirtioDeviceClass parent; + /*< public >*/ + bool (*handle_unknown_request)(VirtIOBlockReq *req, MultiReqBuffer *mrb, + uint32_t type); +} VirtIOBlkClass; + void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); +void virtio_blk_free_request(VirtIOBlockReq *req); +void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status); #endif diff --git a/include/hw/vmapple/virtio-blk.h b/include/hw/vmapple/virtio-blk.h new file mode 100644 index 0000000000..b23106a3df --- /dev/null +++ b/include/hw/vmapple/virtio-blk.h @@ -0,0 +1,39 @@ +/* + * VMApple specific VirtIO Block implementation + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 HW_VMAPPLE_CFG_H +#define HW_VMAPPLE_CFG_H + +#include "hw/sysbus.h" +#include "qom/object.h" +#include "hw/virtio/virtio-pci.h" +#include "hw/virtio/virtio-blk.h" + +#define TYPE_VMAPPLE_VIRTIO_BLK "vmapple-virtio-blk" +#define TYPE_VMAPPLE_VIRTIO_ROOT "vmapple-virtio-root" +#define TYPE_VMAPPLE_VIRTIO_AUX "vmapple-virtio-aux" + +OBJECT_DECLARE_TYPE(VMAppleVirtIOBlk, VMAppleVirtIOBlkClass, VMAPPLE_VIRTIO_BLK) + +typedef struct VMAppleVirtIOBlkClass { + /*< private >*/ + VirtIOBlkClass parent; + /*< public >*/ + void (*get_config)(VirtIODevice *vdev, uint8_t *config); +} VMAppleVirtIOBlkClass; + +typedef struct VMAppleVirtIOBlk { + /* */ + VirtIOBlock parent_obj; + + /* */ + uint32_t apple_type; +} VMAppleVirtIOBlk; + +#endif /* HW_VMAPPLE_CFG_H */ diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 39e7f23fab..1645cdccbe 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -48,12 +48,12 @@ static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, req->mr_next = NULL; } -static void virtio_blk_free_request(VirtIOBlockReq *req) +void virtio_blk_free_request(VirtIOBlockReq *req) { g_free(req); } -static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) +void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) { VirtIOBlock *s = req->dev; VirtIODevice *vdev = VIRTIO_DEVICE(s); @@ -1121,8 +1121,18 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) break; } default: - virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); - virtio_blk_free_request(req); + { + /* + * Give subclasses a chance to handle unknown requests. This way the + * class lookup is not in the hot path. + */ + VirtIOBlkClass *vbk = VIRTIO_BLK_GET_CLASS(s); + if (!vbk->handle_unknown_request || + !vbk->handle_unknown_request(req, mrb, type)) { + virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); + virtio_blk_free_request(req); + } + } } return 0; } @@ -1764,6 +1774,7 @@ static const TypeInfo virtio_blk_info = { .instance_size = sizeof(VirtIOBlock), .instance_init = virtio_blk_instance_init, .class_init = virtio_blk_class_init, + .class_size = sizeof(VirtIOBlkClass), }; static void virtio_register_types(void) diff --git a/hw/vmapple/virtio-blk.c b/hw/vmapple/virtio-blk.c new file mode 100644 index 0000000000..720eaa61a8 --- /dev/null +++ b/hw/vmapple/virtio-blk.c @@ -0,0 +1,212 @@ +/* + * VMApple specific VirtIO Block implementation + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * VMApple uses almost standard VirtIO Block, but with a few key differences: + * + * - Different PCI device/vendor ID + * - An additional "type" identifier to differentiate AUX and Root volumes + * - An additional BARRIER command + */ + +#include "qemu/osdep.h" +#include "hw/vmapple/virtio-blk.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qapi/error.h" + +#define VIRTIO_BLK_T_APPLE_BARRIER 0x10000 + +#define VIRTIO_APPLE_TYPE_ROOT 1 +#define VIRTIO_APPLE_TYPE_AUX 2 + +static bool vmapple_virtio_blk_handle_unknown_request(VirtIOBlockReq *req, + MultiReqBuffer *mrb, + uint32_t type) +{ + switch (type) { + case VIRTIO_BLK_T_APPLE_BARRIER: + /* We ignore barriers for now. YOLO. */ + virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); + virtio_blk_free_request(req); + return true; + default: + return false; + } +} + +/* + * VMApple virtio-blk uses the same config format as normal virtio, with one + * exception: It adds an "apple type" specififer at the same location that + * the spec reserves for max_secure_erase_sectors. Let's hook into the + * get_config code path here, run it as usual and then patch in the apple type. + */ +static void vmapple_virtio_blk_get_config(VirtIODevice *vdev, uint8_t *config) +{ + VMAppleVirtIOBlk *dev = VMAPPLE_VIRTIO_BLK(vdev); + VMAppleVirtIOBlkClass *vvbk = VMAPPLE_VIRTIO_BLK_GET_CLASS(dev); + struct virtio_blk_config *blkcfg = (struct virtio_blk_config *)config; + + vvbk->get_config(vdev, config); + + g_assert(dev->parent_obj.config_size >= endof(struct virtio_blk_config, zoned)); + + /* Apple abuses the field for max_secure_erase_sectors as type id */ + blkcfg->max_secure_erase_sectors = dev->apple_type; +} + +static Property vmapple_virtio_blk_properties[] = { + DEFINE_PROP_UINT32("apple-type", VMAppleVirtIOBlk, apple_type, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vmapple_virtio_blk_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOBlkClass *vbk = VIRTIO_BLK_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + VMAppleVirtIOBlkClass *vvbk = VMAPPLE_VIRTIO_BLK_CLASS(klass); + + vbk->handle_unknown_request = vmapple_virtio_blk_handle_unknown_request; + vvbk->get_config = vdc->get_config; + vdc->get_config = vmapple_virtio_blk_get_config; + device_class_set_props(dc, vmapple_virtio_blk_properties); +} + +static const TypeInfo vmapple_virtio_blk_info = { + .name = TYPE_VMAPPLE_VIRTIO_BLK, + .parent = TYPE_VIRTIO_BLK, + .instance_size = sizeof(VMAppleVirtIOBlk), + .class_init = vmapple_virtio_blk_class_init, +}; + +/* PCI Devices */ + +typedef struct VMAppleVirtIOBlkPCI { + VirtIOPCIProxy parent_obj; + VMAppleVirtIOBlk vdev; + uint32_t apple_type; +} VMAppleVirtIOBlkPCI; + +/* + * vmapple-virtio-blk-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VMAPPLE_VIRTIO_BLK_PCI "vmapple-virtio-blk-pci-base" +DECLARE_INSTANCE_CHECKER(VMAppleVirtIOBlkPCI, VMAPPLE_VIRTIO_BLK_PCI, + TYPE_VMAPPLE_VIRTIO_BLK_PCI) + +static Property vmapple_virtio_blk_pci_properties[] = { + DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), + DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, + DEV_NVECTORS_UNSPECIFIED), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vmapple_virtio_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VMAppleVirtIOBlkPCI *dev = VMAPPLE_VIRTIO_BLK_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + VirtIOBlkConf *conf = &dev->vdev.parent_obj.conf; + + if (conf->num_queues == VIRTIO_BLK_AUTO_NUM_QUEUES) { + conf->num_queues = virtio_pci_optimal_num_queues(0); + } + + if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { + vpci_dev->nvectors = conf->num_queues + 1; + } + + /* + * We don't support zones, but we need the additional config space size. + * Let's just expose the feature so the rest of the virtio-blk logic + * allocates enough space for us. The guest will ignore zones anyway. + */ + virtio_add_feature(&dev->vdev.parent_obj.host_features, VIRTIO_BLK_F_ZONED); + /* Propagate the apple type down to the virtio-blk device */ + qdev_prop_set_uint32(DEVICE(&dev->vdev), "apple-type", dev->apple_type); + /* and spawn the virtio-blk device */ + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); + + /* + * The virtio-pci machinery adjusts its vendor/device ID based on whether + * we support modern or legacy virtio. Let's patch it back to the Apple + * identifiers here. + */ + pci_config_set_vendor_id(vpci_dev->pci_dev.config, PCI_VENDOR_ID_APPLE); + pci_config_set_device_id(vpci_dev->pci_dev.config, PCI_DEVICE_ID_APPLE_VIRTIO_BLK); +} + +static void vmapple_virtio_blk_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + device_class_set_props(dc, vmapple_virtio_blk_pci_properties); + k->realize = vmapple_virtio_blk_pci_realize; + pcidev_k->vendor_id = PCI_VENDOR_ID_APPLE; + pcidev_k->device_id = PCI_DEVICE_ID_APPLE_VIRTIO_BLK; + pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; + pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; +} + +static void vmapple_virtio_blk_pci_instance_init(Object *obj) +{ + VMAppleVirtIOBlkPCI *dev = VMAPPLE_VIRTIO_BLK_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VMAPPLE_VIRTIO_BLK); +} + +static const VirtioPCIDeviceTypeInfo vmapple_virtio_blk_pci_info = { + .base_name = TYPE_VMAPPLE_VIRTIO_BLK_PCI, + .generic_name = "vmapple-virtio-blk-pci", + .instance_size = sizeof(VMAppleVirtIOBlkPCI), + .instance_init = vmapple_virtio_blk_pci_instance_init, + .class_init = vmapple_virtio_blk_pci_class_init, +}; + +static void vmapple_virtio_root_instance_init(Object *obj) +{ + VMAppleVirtIOBlkPCI *dev = VMAPPLE_VIRTIO_BLK_PCI(obj); + + dev->apple_type = VIRTIO_APPLE_TYPE_ROOT; +} + +static const TypeInfo vmapple_virtio_root_info = { + .name = TYPE_VMAPPLE_VIRTIO_ROOT, + .parent = "vmapple-virtio-blk-pci", + .instance_size = sizeof(VMAppleVirtIOBlkPCI), + .instance_init = vmapple_virtio_root_instance_init, +}; + +static void vmapple_virtio_aux_instance_init(Object *obj) +{ + VMAppleVirtIOBlkPCI *dev = VMAPPLE_VIRTIO_BLK_PCI(obj); + + dev->apple_type = VIRTIO_APPLE_TYPE_AUX; +} + +static const TypeInfo vmapple_virtio_aux_info = { + .name = TYPE_VMAPPLE_VIRTIO_AUX, + .parent = "vmapple-virtio-blk-pci", + .instance_size = sizeof(VMAppleVirtIOBlkPCI), + .instance_init = vmapple_virtio_aux_instance_init, +}; + +static void vmapple_virtio_blk_register_types(void) +{ + type_register_static(&vmapple_virtio_blk_info); + virtio_pci_types_register(&vmapple_virtio_blk_pci_info); + type_register_static(&vmapple_virtio_root_info); + type_register_static(&vmapple_virtio_aux_info); +} + +type_init(vmapple_virtio_blk_register_types) diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig index ba37fc5b81..f06eae8039 100644 --- a/hw/vmapple/Kconfig +++ b/hw/vmapple/Kconfig @@ -9,3 +9,6 @@ config VMAPPLE_CFG config VMAPPLE_PVG bool + +config VMAPPLE_VIRTIO_BLK + bool diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build index 74a0d7a5f1..3b4a16f619 100644 --- a/hw/vmapple/meson.build +++ b/hw/vmapple/meson.build @@ -2,3 +2,4 @@ system_ss.add(when: 'CONFIG_VMAPPLE_AES', if_true: files('aes.c')) system_ss.add(when: 'CONFIG_VMAPPLE_BDIF', if_true: files('bdif.c')) system_ss.add(when: 'CONFIG_VMAPPLE_CFG', if_true: files('cfg.c')) system_ss.add(when: 'CONFIG_VMAPPLE_PVG', if_true: [files('apple-gfx.m'), pvg, metal]) +system_ss.add(when: 'CONFIG_VMAPPLE_VIRTIO_BLK', if_true: files('virtio-blk.c')) From patchwork Wed Aug 30 16:14:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 13370338 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id AC1C6C83F01 for ; Wed, 30 Aug 2023 16:17:56 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qbNsu-0005xN-3K; Wed, 30 Aug 2023 12:17:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqv-0003SL-6T; Wed, 30 Aug 2023 12:15:43 -0400 Received: from smtp-fw-52004.amazon.com ([52.119.213.154]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qbNqo-0003vr-FI; Wed, 30 Aug 2023 12:15:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1693412127; x=1724948127; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=m4YuPq/6IfPEweBu7RjQadCXUGMwuPtUwK/3gsWRNGc=; b=rPyHi3Z9Vle9886d6PQ6VtaBpOSnkRTFeH+nPGTqBRspezS2XLp8Gsz5 lgcnzB0MZP/XWJuT8i8faGV70JXlTQc4vXjQEkdOiaoQ07UnzqixzpqC+ FUkUC3NzJz2Fg76K85/L195y4u0KWgQSsRyChbPV6/Ro/5TrQ2pMJ/Zwr g=; X-IronPort-AV: E=Sophos;i="6.02,214,1688428800"; d="scan'208";a="151694850" Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-iad-1a-m6i4x-bbc6e425.us-east-1.amazon.com) ([10.43.8.2]) by smtp-border-fw-52004.iad7.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Aug 2023 16:15:26 +0000 Received: from EX19MTAUWB001.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1a-m6i4x-bbc6e425.us-east-1.amazon.com (Postfix) with ESMTPS id 6E54C80DE1; Wed, 30 Aug 2023 16:15:20 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWB001.ant.amazon.com (10.250.64.248) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:15:07 +0000 Received: from dev-dsk-graf-1a-5ce218e4.eu-west-1.amazon.com (10.253.83.51) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.37; Wed, 30 Aug 2023 16:15:04 +0000 From: Alexander Graf To: CC: , , Cameron Esfahani , Stefan Hajnoczi , "Michael S . Tsirkin" , Kevin Wolf , Hanna Reitz , Marcel Apfelbaum , "Paolo Bonzini" , Peter Maydell , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , Mads Ynddal , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Bernhard Beschow , Gerd Hoffmann Subject: [PATCH v2 12/12] hw/vmapple/vmapple: Add vmapple machine type Date: Wed, 30 Aug 2023 16:14:25 +0000 Message-ID: <20230830161425.91946-13-graf@amazon.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230830161425.91946-1-graf@amazon.com> References: <20230830161425.91946-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.253.83.51] X-ClientProxiedBy: EX19D038UWC001.ant.amazon.com (10.13.139.213) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Precedence: Bulk Received-SPF: pass client-ip=52.119.213.154; envelope-from=prvs=599fd62c5=graf@amazon.de; helo=smtp-fw-52004.amazon.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org Apple defines a new "vmapple" machine type as part of its proprietary macOS Virtualization.Framework vmm. This machine type is similar to the virt one, but with subtle differences in base devices, a few special vmapple device additions and a vastly different boot chain. This patch reimplements this machine type in QEMU. To use it, you have to have a readily installed version of macOS for VMApple, run on macOS with -accel hvf, pass the Virtualization.Framework boot rom (AVPBooter) in via -bios, pass the aux and root volume as pflash and pass aux and root volume as virtio drives. In addition, you also need to find the machine UUID and pass that as -M vmapple,uuid= parameter: $ qemu-system-aarch64 -accel hvf -M vmapple,uuid=0x1234 -m 4G \ -bios /System/Library/Frameworks/Virtualization.framework/Versions/A/Resources/AVPBooter.vmapple2.bin -drive file=aux,if=pflash,format=raw \ -drive file=root,if=pflash,format=raw \ -drive file=aux,if=none,id=aux,format=raw \ -device vmapple-virtio-aux,drive=aux \ -drive file=root,if=none,id=root,format=raw \ -device vmapple-virtio-root,drive=root With all these in place, you should be able to see macOS booting successfully. Signed-off-by: Alexander Graf --- v1 -> v2: - Adapt to system_ss meson.build target - Add documentation --- MAINTAINERS | 1 + docs/system/arm/vmapple.rst | 63 ++++ docs/system/target-arm.rst | 1 + hw/vmapple/vmapple.c | 661 ++++++++++++++++++++++++++++++++++++ hw/vmapple/Kconfig | 19 ++ hw/vmapple/meson.build | 1 + 6 files changed, 746 insertions(+) create mode 100644 docs/system/arm/vmapple.rst create mode 100644 hw/vmapple/vmapple.c diff --git a/MAINTAINERS b/MAINTAINERS index 3104e58eff..1d3b1e0034 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2578,6 +2578,7 @@ M: Alexander Graf S: Maintained F: hw/vmapple/* F: include/hw/vmapple/* +F: docs/system/arm/vmapple.rst Subsystems ---------- diff --git a/docs/system/arm/vmapple.rst b/docs/system/arm/vmapple.rst new file mode 100644 index 0000000000..c7486b21d9 --- /dev/null +++ b/docs/system/arm/vmapple.rst @@ -0,0 +1,63 @@ +VMApple machine emulation +======================================================================================== + +VMApple is the device model that the macOS built-in hypervisor called "Virtualization.framework" +exposes to Apple Silicon macOS guests. The "vmapple" machine model in QEMU implements the same +device model, but does not use any code from Virtualization.Framework. + +Prerequisites +------------- + +To run the vmapple machine model, you need to + + * Run on Apple Silicon + * Run on macOS 12.0 or above + * Have an already installed copy of a Virtualization.Framework macOS virtual machine. I will + assume that you installed it using the macosvm CLI. + +First, we need to extract the UUID from the virtual machine that you installed. You can do this +by running the following shell script: + +.. code-block:: bash + :caption: uuid.sh script to extract the UUID from a macosvm.json file + + #!/bin/bash + + MID=$(cat "$1" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["machineId"]);') + echo "$MID" | base64 -d | plutil -extract ECID raw - + +Now we also need to trim the aux partition. It contains metadata that we can just discard: + +.. code-block:: bash + :caption: Command to trim the aux file + + $ dd if="aux.img" of="aux.img.trimmed" bs=$(( 0x4000 )) skip=1 + +How to run +---------- + +Then, we can launch QEMU with the Virtualization.Framework pre-boot environment and the readily +installed target disk images. I recommend to port forward the VM's ssh and vnc ports to the host +to get better interactive access into the target system: + +.. code-block:: bash + :caption: Example execution command line + + $ UUID=$(uuid.sh macosvm.json) + $ AVPBOOTER=/System/Library/Frameworks/Virtualization.framework/Resources/AVPBooter.vmapple2.bin + $ AUX=aux.img.trimmed + $ DISK=disk.img + $ qemu-system-aarch64 \ + -serial mon:stdio \ + -m 4G \ + -accel hvf \ + -M vmapple,uuid=$UUID \ + -bios $AVPBOOTER \ + -drive file="$AUX",if=pflash,format=raw \ + -drive file="$DISK",if=pflash,format=raw \ + -drive file="$AUX",if=none,id=aux,format=raw \ + -drive file="$DISK",if=none,id=root,format=raw \ + -device vmapple-virtio-aux,drive=aux \ + -device vmapple-virtio-root,drive=root \ + -net user,ipv6=off,hostfwd=tcp::2222-:22,hostfwd=tcp::5901-:5900 \ + -net nic,model=virtio \ diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst index 790ac1b8a2..bf663df4a6 100644 --- a/docs/system/target-arm.rst +++ b/docs/system/target-arm.rst @@ -106,6 +106,7 @@ undocumented; you can get a complete list by running arm/stellaris arm/stm32 arm/virt + arm/vmapple arm/xlnx-versal-virt arm/xenpvh diff --git a/hw/vmapple/vmapple.c b/hw/vmapple/vmapple.c new file mode 100644 index 0000000000..5d3fe54b96 --- /dev/null +++ b/hw/vmapple/vmapple.c @@ -0,0 +1,661 @@ +/* + * VMApple machine emulation + * + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * VMApple is the device model that the macOS built-in hypervisor called + * "Virtualization.framework" exposes to Apple Silicon macOS guests. The + * machine model in this file implements the same device model in QEMU, but + * does not use any code from Virtualization.Framework. + */ + +#include "qemu/osdep.h" +#include "qemu/help-texts.h" +#include "qemu/datadir.h" +#include "qemu/units.h" +#include "qemu/option.h" +#include "monitor/qdev.h" +#include "qapi/error.h" +#include "hw/sysbus.h" +#include "hw/arm/boot.h" +#include "hw/arm/primecell.h" +#include "hw/boards.h" +#include "net/net.h" +#include "sysemu/sysemu.h" +#include "sysemu/runstate.h" +#include "sysemu/kvm.h" +#include "sysemu/hvf.h" +#include "hw/loader.h" +#include "qapi/error.h" +#include "qemu/bitops.h" +#include "qemu/error-report.h" +#include "qemu/module.h" +#include "hw/pci-host/gpex.h" +#include "hw/virtio/virtio-pci.h" +#include "hw/qdev-properties.h" +#include "hw/intc/arm_gic.h" +#include "hw/intc/arm_gicv3_common.h" +#include "hw/irq.h" +#include "qapi/visitor.h" +#include "qapi/qapi-visit-common.h" +#include "standard-headers/linux/input.h" +#include "target/arm/internals.h" +#include "target/arm/kvm_arm.h" +#include "hw/char/pl011.h" +#include "qemu/guest-random.h" +#include "sysemu/reset.h" +#include "qemu/log.h" +#include "hw/vmapple/cfg.h" +#include "hw/misc/pvpanic.h" +#include "hw/vmapple/bdif.h" + +struct VMAppleMachineClass { + MachineClass parent; +}; + +struct VMAppleMachineState { + MachineState parent; + Notifier machine_done; + struct arm_boot_info bootinfo; + MemMapEntry *memmap; + const int *irqmap; + DeviceState *gic; + DeviceState *cfg; + Notifier powerdown_notifier; + PCIBus *bus; + MemoryRegion fw_mr; + uint64_t uuid; +}; + +#define DEFINE_VMAPPLE_MACHINE_LATEST(major, minor, latest) \ + static void vmapple##major##_##minor##_class_init(ObjectClass *oc, \ + void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ + vmapple_machine_##major##_##minor##_options(mc); \ + mc->desc = "QEMU " # major "." # minor " Apple Virtual Machine"; \ + if (latest) { \ + mc->alias = "vmapple"; \ + } \ + } \ + static const TypeInfo machvmapple##major##_##minor##_info = { \ + .name = MACHINE_TYPE_NAME("vmapple-" # major "." # minor), \ + .parent = TYPE_VMAPPLE_MACHINE, \ + .class_init = vmapple##major##_##minor##_class_init, \ + }; \ + static void machvmapple_machine_##major##_##minor##_init(void) \ + { \ + type_register_static(&machvmapple##major##_##minor##_info); \ + } \ + type_init(machvmapple_machine_##major##_##minor##_init); + +#define DEFINE_VMAPPLE_MACHINE_AS_LATEST(major, minor) \ + DEFINE_VMAPPLE_MACHINE_LATEST(major, minor, true) +#define DEFINE_VMAPPLE_MACHINE(major, minor) \ + DEFINE_VMAPPLE_MACHINE_LATEST(major, minor, false) + +#define TYPE_VMAPPLE_MACHINE MACHINE_TYPE_NAME("vmapple") +OBJECT_DECLARE_TYPE(VMAppleMachineState, VMAppleMachineClass, VMAPPLE_MACHINE) + +/* Number of external interrupt lines to configure the GIC with */ +#define NUM_IRQS 256 + +enum { + VMAPPLE_FIRMWARE, + VMAPPLE_CONFIG, + VMAPPLE_MEM, + VMAPPLE_GIC_DIST, + VMAPPLE_GIC_REDIST, + VMAPPLE_UART, + VMAPPLE_RTC, + VMAPPLE_PCIE, + VMAPPLE_PCIE_MMIO, + VMAPPLE_PCIE_ECAM, + VMAPPLE_GPIO, + VMAPPLE_PVPANIC, + VMAPPLE_APV_GFX, + VMAPPLE_APV_IOSFC, + VMAPPLE_AES_1, + VMAPPLE_AES_2, + VMAPPLE_BDOOR, + VMAPPLE_MEMMAP_LAST, +}; + +static MemMapEntry memmap[] = { + [VMAPPLE_FIRMWARE] = { 0x00100000, 0x00100000 }, + [VMAPPLE_CONFIG] = { 0x00400000, 0x00010000 }, + + [VMAPPLE_GIC_DIST] = { 0x10000000, 0x00010000 }, + [VMAPPLE_GIC_REDIST] = { 0x10010000, 0x00400000 }, + + [VMAPPLE_UART] = { 0x20010000, 0x00010000 }, + [VMAPPLE_RTC] = { 0x20050000, 0x00001000 }, + [VMAPPLE_GPIO] = { 0x20060000, 0x00001000 }, + [VMAPPLE_PVPANIC] = { 0x20070000, 0x00000002 }, + [VMAPPLE_BDOOR] = { 0x30000000, 0x00200000 }, + [VMAPPLE_APV_GFX] = { 0x30200000, 0x00010000 }, + [VMAPPLE_APV_IOSFC] = { 0x30210000, 0x00010000 }, + [VMAPPLE_AES_1] = { 0x30220000, 0x00004000 }, + [VMAPPLE_AES_2] = { 0x30230000, 0x00004000 }, + [VMAPPLE_PCIE_ECAM] = { 0x40000000, 0x10000000 }, + [VMAPPLE_PCIE_MMIO] = { 0x50000000, 0x1fff0000 }, + + /* Actual RAM size depends on configuration */ + [VMAPPLE_MEM] = { 0x70000000ULL, GiB}, +}; + +static const int irqmap[] = { + [VMAPPLE_UART] = 1, + [VMAPPLE_RTC] = 2, + [VMAPPLE_GPIO] = 0x5, + [VMAPPLE_APV_IOSFC] = 0x10, + [VMAPPLE_APV_GFX] = 0x11, + [VMAPPLE_AES_1] = 0x12, + [VMAPPLE_PCIE] = 0x20, +}; + +#define GPEX_NUM_IRQS 16 + +static void create_bdif(VMAppleMachineState *vms, MemoryRegion *mem) +{ + DeviceState *bdif; + SysBusDevice *bdif_sb; + DriveInfo *di_aux = drive_get(IF_PFLASH, 0, 0); + DriveInfo *di_root = drive_get(IF_PFLASH, 0, 1); + + if (!di_aux) { + error_report("No AUX device found. Please specify one as pflash drive"); + exit(1); + } + + if (!di_root) { + /* Fall back to the first IF_VIRTIO device as root device */ + di_root = drive_get(IF_VIRTIO, 0, 0); + } + + if (!di_root) { + error_report("No root device found. Please specify one as virtio drive"); + exit(1); + } + + /* PV backdoor device */ + bdif = qdev_new(TYPE_VMAPPLE_BDIF); + bdif_sb = SYS_BUS_DEVICE(bdif); + sysbus_mmio_map(bdif_sb, 0, vms->memmap[VMAPPLE_BDOOR].base); + + qdev_prop_set_drive(DEVICE(bdif), "aux", blk_by_legacy_dinfo(di_aux)); + qdev_prop_set_drive(DEVICE(bdif), "root", blk_by_legacy_dinfo(di_root)); + + sysbus_realize_and_unref(bdif_sb, &error_fatal); +} + +static void create_pvpanic(VMAppleMachineState *vms, MemoryRegion *mem) +{ + SysBusDevice *cfg; + + vms->cfg = qdev_new(TYPE_PVPANIC_MMIO_DEVICE); + cfg = SYS_BUS_DEVICE(vms->cfg); + sysbus_mmio_map(cfg, 0, vms->memmap[VMAPPLE_PVPANIC].base); + + sysbus_realize_and_unref(cfg, &error_fatal); +} + +static void create_cfg(VMAppleMachineState *vms, MemoryRegion *mem) +{ + SysBusDevice *cfg; + MachineState *machine = MACHINE(vms); + uint32_t rnd = 1; + + vms->cfg = qdev_new(TYPE_VMAPPLE_CFG); + cfg = SYS_BUS_DEVICE(vms->cfg); + sysbus_mmio_map(cfg, 0, vms->memmap[VMAPPLE_CONFIG].base); + + qemu_guest_getrandom_nofail(&rnd, sizeof(rnd)); + + qdev_prop_set_uint32(vms->cfg, "nr-cpus", machine->smp.cpus); + qdev_prop_set_uint64(vms->cfg, "ecid", vms->uuid); + qdev_prop_set_uint64(vms->cfg, "ram-size", machine->ram_size); + qdev_prop_set_uint32(vms->cfg, "rnd", rnd); + + sysbus_realize_and_unref(cfg, &error_fatal); +} + +static void create_gfx(VMAppleMachineState *vms, MemoryRegion *mem) +{ + int irq_gfx = vms->irqmap[VMAPPLE_APV_GFX]; + int irq_iosfc = vms->irqmap[VMAPPLE_APV_IOSFC]; + SysBusDevice *aes; + + aes = SYS_BUS_DEVICE(qdev_new("apple-gfx")); + sysbus_mmio_map(aes, 0, vms->memmap[VMAPPLE_APV_GFX].base); + sysbus_mmio_map(aes, 1, vms->memmap[VMAPPLE_APV_IOSFC].base); + sysbus_connect_irq(aes, 0, qdev_get_gpio_in(vms->gic, irq_gfx)); + sysbus_connect_irq(aes, 1, qdev_get_gpio_in(vms->gic, irq_iosfc)); + sysbus_realize_and_unref(aes, &error_fatal); +} + +static void create_aes(VMAppleMachineState *vms, MemoryRegion *mem) +{ + int irq = vms->irqmap[VMAPPLE_AES_1]; + SysBusDevice *aes; + + aes = SYS_BUS_DEVICE(qdev_new("apple-aes")); + sysbus_mmio_map(aes, 0, vms->memmap[VMAPPLE_AES_1].base); + sysbus_mmio_map(aes, 1, vms->memmap[VMAPPLE_AES_2].base); + sysbus_connect_irq(aes, 0, qdev_get_gpio_in(vms->gic, irq)); + sysbus_realize_and_unref(aes, &error_fatal); +} + +static inline int arm_gic_ppi_index(int cpu_nr, int ppi_index) +{ + return NUM_IRQS + cpu_nr * GIC_INTERNAL + ppi_index; +} + +static void create_gic(VMAppleMachineState *vms, MemoryRegion *mem) +{ + MachineState *ms = MACHINE(vms); + /* We create a standalone GIC */ + SysBusDevice *gicbusdev; + int i; + unsigned int smp_cpus = ms->smp.cpus; + + vms->gic = qdev_new(gicv3_class_name()); + qdev_prop_set_uint32(vms->gic, "revision", 3); + qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus); + /* + * Note that the num-irq property counts both internal and external + * interrupts; there are always 32 of the former (mandated by GIC spec). + */ + qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32); + + uint32_t redist0_capacity = + vms->memmap[VMAPPLE_GIC_REDIST].size / GICV3_REDIST_SIZE; + uint32_t redist0_count = MIN(smp_cpus, redist0_capacity); + + qdev_prop_set_uint32(vms->gic, "len-redist-region-count", 1); + qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count); + + gicbusdev = SYS_BUS_DEVICE(vms->gic); + sysbus_realize_and_unref(gicbusdev, &error_fatal); + sysbus_mmio_map(gicbusdev, 0, vms->memmap[VMAPPLE_GIC_DIST].base); + sysbus_mmio_map(gicbusdev, 1, vms->memmap[VMAPPLE_GIC_REDIST].base); + + /* + * Wire the outputs from each CPU's generic timer and the GICv3 + * maintenance interrupt signal to the appropriate GIC PPI inputs, + * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. + */ + for (i = 0; i < smp_cpus; i++) { + DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); + + /* Map the virt timer to PPI 27 */ + qdev_connect_gpio_out(cpudev, GTIMER_VIRT, + qdev_get_gpio_in(vms->gic, + arm_gic_ppi_index(i, 27))); + + /* Map the GIC IRQ and FIQ lines to CPU */ + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); + sysbus_connect_irq(gicbusdev, i + smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); + } +} + +static void create_uart(const VMAppleMachineState *vms, int uart, + MemoryRegion *mem, Chardev *chr) +{ + hwaddr base = vms->memmap[uart].base; + int irq = vms->irqmap[uart]; + DeviceState *dev = qdev_new(TYPE_PL011); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + + qdev_prop_set_chr(dev, "chardev", chr); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + memory_region_add_subregion(mem, base, + sysbus_mmio_get_region(s, 0)); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq)); +} + +static void create_rtc(const VMAppleMachineState *vms) +{ + hwaddr base = vms->memmap[VMAPPLE_RTC].base; + int irq = vms->irqmap[VMAPPLE_RTC]; + + sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq)); +} + +static DeviceState *gpio_key_dev; +static void vmapple_powerdown_req(Notifier *n, void *opaque) +{ + /* use gpio Pin 3 for power button event */ + qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); +} + +static void create_gpio_devices(const VMAppleMachineState *vms, int gpio, + MemoryRegion *mem) +{ + DeviceState *pl061_dev; + hwaddr base = vms->memmap[gpio].base; + int irq = vms->irqmap[gpio]; + SysBusDevice *s; + + pl061_dev = qdev_new("pl061"); + /* Pull lines down to 0 if not driven by the PL061 */ + qdev_prop_set_uint32(pl061_dev, "pullups", 0); + qdev_prop_set_uint32(pl061_dev, "pulldowns", 0xff); + s = SYS_BUS_DEVICE(pl061_dev); + sysbus_realize_and_unref(s, &error_fatal); + memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq)); + gpio_key_dev = sysbus_create_simple("gpio-key", -1, + qdev_get_gpio_in(pl061_dev, 3)); +} + +static void vmapple_firmware_init(VMAppleMachineState *vms, + MemoryRegion *sysmem) +{ + hwaddr size = vms->memmap[VMAPPLE_FIRMWARE].size; + hwaddr base = vms->memmap[VMAPPLE_FIRMWARE].base; + const char *bios_name; + int image_size; + char *fname; + + bios_name = MACHINE(vms)->firmware; + if (!bios_name) { + error_report("No firmware specified"); + exit(1); + } + + fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (!fname) { + error_report("Could not find ROM image '%s'", bios_name); + exit(1); + } + + memory_region_init_ram(&vms->fw_mr, NULL, "firmware", size, NULL); + image_size = load_image_mr(fname, &vms->fw_mr); + + g_free(fname); + if (image_size < 0) { + error_report("Could not load ROM image '%s'", bios_name); + exit(1); + } + + memory_region_add_subregion(get_system_memory(), base, &vms->fw_mr); +} + +static void create_pcie(VMAppleMachineState *vms) +{ + hwaddr base_mmio = vms->memmap[VMAPPLE_PCIE_MMIO].base; + hwaddr size_mmio = vms->memmap[VMAPPLE_PCIE_MMIO].size; + hwaddr base_ecam = vms->memmap[VMAPPLE_PCIE_ECAM].base; + hwaddr size_ecam = vms->memmap[VMAPPLE_PCIE_ECAM].size; + int irq = vms->irqmap[VMAPPLE_PCIE]; + MemoryRegion *mmio_alias; + MemoryRegion *mmio_reg; + MemoryRegion *ecam_alias; + MemoryRegion *ecam_reg; + DeviceState *dev; + int i; + PCIHostState *pci; + DeviceState *virtio_tablet; + DeviceState *virtio_keyboard; + + dev = qdev_new(TYPE_GPEX_HOST); + qdev_prop_set_uint32(dev, "nr-irqs", GPEX_NUM_IRQS); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + /* Map only the first size_ecam bytes of ECAM space */ + ecam_alias = g_new0(MemoryRegion, 1); + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", + ecam_reg, 0, size_ecam); + memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias); + + /* + * Map the MMIO window from [0x50000000-0x7fff0000] in PCI space into + * system address space at [0x50000000-0x7fff0000]. + */ + mmio_alias = g_new0(MemoryRegion, 1); + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", + mmio_reg, base_mmio, size_mmio); + memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); + + for (i = 0; i < GPEX_NUM_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, + qdev_get_gpio_in(vms->gic, irq + i)); + gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); + } + + pci = PCI_HOST_BRIDGE(dev); + vms->bus = pci->bus; + if (vms->bus) { + for (i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + + if (!nd->model) { + nd->model = g_strdup("virtio"); + } + + pci_nic_init_nofail(nd, pci->bus, nd->model, NULL); + } + } + + virtio_tablet = qdev_new("virtio-tablet-pci"); + qdev_realize(virtio_tablet, BUS(pci->bus), &error_fatal); + object_unref(virtio_tablet); + + virtio_keyboard = qdev_new("virtio-keyboard-pci"); + qdev_realize(virtio_keyboard, BUS(pci->bus), &error_fatal); + object_unref(virtio_keyboard); +} + +static void vmapple_reset(void *opaque) +{ + VMAppleMachineState *vms = opaque; + hwaddr base = vms->memmap[VMAPPLE_FIRMWARE].base; + + cpu_set_pc(first_cpu, base); +} + +static void mach_vmapple_init(MachineState *machine) +{ + VMAppleMachineState *vms = VMAPPLE_MACHINE(machine); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus; + MemoryRegion *sysmem = get_system_memory(); + int n; + unsigned int smp_cpus = machine->smp.cpus; + unsigned int max_cpus = machine->smp.max_cpus; + + vms->memmap = memmap; + + possible_cpus = mc->possible_cpu_arch_ids(machine); + assert(possible_cpus->len == max_cpus); + for (n = 0; n < possible_cpus->len; n++) { + Object *cpu; + CPUState *cs; + + if (n >= smp_cpus) { + break; + } + + cpu = object_new(possible_cpus->cpus[n].type); + object_property_set_int(cpu, "mp-affinity", + possible_cpus->cpus[n].arch_id, NULL); + + cs = CPU(cpu); + cs->cpu_index = n; + + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpu), + &error_fatal); + + object_property_set_bool(cpu, "has_el3", false, NULL); + object_property_set_bool(cpu, "has_el2", false, NULL); + object_property_set_int(cpu, "psci-conduit", QEMU_PSCI_CONDUIT_HVC, + NULL); + + /* Secondary CPUs start in PSCI powered-down state */ + if (n > 0) { + object_property_set_bool(cpu, "start-powered-off", true, NULL); + } + + object_property_set_link(cpu, "memory", OBJECT(sysmem), &error_abort); + qdev_realize(DEVICE(cpu), NULL, &error_fatal); + object_unref(cpu); + } + + memory_region_add_subregion(sysmem, vms->memmap[VMAPPLE_MEM].base, + machine->ram); + + create_gic(vms, sysmem); + create_bdif(vms, sysmem); + create_pvpanic(vms, sysmem); + create_aes(vms, sysmem); + create_gfx(vms, sysmem); + create_uart(vms, VMAPPLE_UART, sysmem, serial_hd(0)); + create_rtc(vms); + create_pcie(vms); + + create_gpio_devices(vms, VMAPPLE_GPIO, sysmem); + + vmapple_firmware_init(vms, sysmem); + create_cfg(vms, sysmem); + + /* connect powerdown request */ + vms->powerdown_notifier.notify = vmapple_powerdown_req; + qemu_register_powerdown_notifier(&vms->powerdown_notifier); + + vms->bootinfo.ram_size = machine->ram_size; + vms->bootinfo.board_id = -1; + vms->bootinfo.loader_start = vms->memmap[VMAPPLE_MEM].base; + vms->bootinfo.skip_dtb_autoload = true; + vms->bootinfo.firmware_loaded = true; + arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo); + + qemu_register_reset(vmapple_reset, vms); +} + +static CpuInstanceProperties +vmapple_cpu_index_to_props(MachineState *ms, unsigned cpu_index) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + + assert(cpu_index < possible_cpus->len); + return possible_cpus->cpus[cpu_index].props; +} + + +static int64_t vmapple_get_default_cpu_node_id(const MachineState *ms, int idx) +{ + return idx % ms->numa_state->num_nodes; +} + +static const CPUArchIdList *vmapple_possible_cpu_arch_ids(MachineState *ms) +{ + int n; + unsigned int max_cpus = ms->smp.max_cpus; + + if (ms->possible_cpus) { + assert(ms->possible_cpus->len == max_cpus); + return ms->possible_cpus; + } + + ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + + sizeof(CPUArchId) * max_cpus); + ms->possible_cpus->len = max_cpus; + for (n = 0; n < ms->possible_cpus->len; n++) { + ms->possible_cpus->cpus[n].type = ms->cpu_type; + ms->possible_cpus->cpus[n].arch_id = + arm_cpu_mp_affinity(n, GICV3_TARGETLIST_BITS); + ms->possible_cpus->cpus[n].props.has_thread_id = true; + ms->possible_cpus->cpus[n].props.thread_id = n; + } + return ms->possible_cpus; +} + +static void vmapple_get_uuid(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + VMAppleMachineState *vms = VMAPPLE_MACHINE(obj); + uint64_t value = be64_to_cpu(vms->uuid); + + visit_type_uint64(v, name, &value, errp); +} + +static void vmapple_set_uuid(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + VMAppleMachineState *vms = VMAPPLE_MACHINE(obj); + Error *error = NULL; + uint64_t value; + + visit_type_uint64(v, name, &value, &error); + if (error) { + error_propagate(errp, error); + return; + } + + vms->uuid = cpu_to_be64(value); +} + +static void vmapple_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->init = mach_vmapple_init; + mc->max_cpus = 32; + mc->block_default_type = IF_VIRTIO; + mc->no_cdrom = 1; + mc->pci_allow_0_address = true; + mc->minimum_page_bits = 12; + mc->possible_cpu_arch_ids = vmapple_possible_cpu_arch_ids; + mc->cpu_index_to_instance_props = vmapple_cpu_index_to_props; + if (hvf_enabled()) { + mc->default_cpu_type = ARM_CPU_TYPE_NAME("host"); + } else { + mc->default_cpu_type = ARM_CPU_TYPE_NAME("max"); + } + mc->get_default_cpu_node_id = vmapple_get_default_cpu_node_id; + mc->default_ram_id = "mach-vmapple.ram"; + + object_register_sugar_prop(TYPE_VIRTIO_PCI, "disable-legacy", + "on", true); + + object_class_property_add(oc, "uuid", "uint64", vmapple_get_uuid, + vmapple_set_uuid, NULL, NULL); + object_class_property_set_description(oc, "uuid", "Machine UUID (SDOM)"); +} + +static void vmapple_instance_init(Object *obj) +{ + VMAppleMachineState *vms = VMAPPLE_MACHINE(obj); + + vms->irqmap = irqmap; +} + +static const TypeInfo vmapple_machine_info = { + .name = TYPE_VMAPPLE_MACHINE, + .parent = TYPE_MACHINE, + .abstract = true, + .instance_size = sizeof(VMAppleMachineState), + .class_size = sizeof(VMAppleMachineClass), + .class_init = vmapple_machine_class_init, + .instance_init = vmapple_instance_init, +}; + +static void machvmapple_machine_init(void) +{ + type_register_static(&vmapple_machine_info); +} +type_init(machvmapple_machine_init); + +static void vmapple_machine_8_1_options(MachineClass *mc) +{ +} +DEFINE_VMAPPLE_MACHINE_AS_LATEST(8, 1) + diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig index f06eae8039..920b590561 100644 --- a/hw/vmapple/Kconfig +++ b/hw/vmapple/Kconfig @@ -12,3 +12,22 @@ config VMAPPLE_PVG config VMAPPLE_VIRTIO_BLK bool + +config VMAPPLE + bool + depends on ARM && HVF + default y if ARM && HVF + imply PCI_DEVICES + select ARM_GIC + select PLATFORM_BUS + select PCI_EXPRESS + select PCI_EXPRESS_GENERIC_BRIDGE + select PL011 # UART + select PL031 # RTC + select PL061 # GPIO + select GPIO_PWR + select PVPANIC_MMIO + select VMAPPLE_AES + select VMAPPLE_BDIF + select VMAPPLE_CFG + select VMAPPLE_PVG diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build index 3b4a16f619..45201cbde5 100644 --- a/hw/vmapple/meson.build +++ b/hw/vmapple/meson.build @@ -3,3 +3,4 @@ system_ss.add(when: 'CONFIG_VMAPPLE_BDIF', if_true: files('bdif.c')) system_ss.add(when: 'CONFIG_VMAPPLE_CFG', if_true: files('cfg.c')) system_ss.add(when: 'CONFIG_VMAPPLE_PVG', if_true: [files('apple-gfx.m'), pvg, metal]) system_ss.add(when: 'CONFIG_VMAPPLE_VIRTIO_BLK', if_true: files('virtio-blk.c')) +specific_ss.add(when: 'CONFIG_VMAPPLE', if_true: files('vmapple.c'))