From patchwork Sat Jan 25 12:51:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950337 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 5895DC0218D for ; Sat, 25 Jan 2025 12:35:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLE-0008Gj-Bf; Sat, 25 Jan 2025 07:32:48 -0500 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 1tbfKy-0008BM-DW; Sat, 25 Jan 2025 07:32:33 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfKv-0005TB-0m; Sat, 25 Jan 2025 07:32:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808349; x=1769344349; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aBNXUK51XTb5h+RZylc8ESD+bwtNxYy97oEksRtg0Sk=; b=PSkz1y/0l4t268RjkRQWi+puHKnG1HhDbGfseda3iQEt7Kfz1L3y1cIl ZmwSOct5s99X3t+K6xqC0sXYSfQvYjxQzPVPJ51Kw1Ejc3om0LJqJmCro +OPkQ/biTgudxpEGN5U2EbAfGbJYcESCgeC53+gNhhTLctOyWe+LS39Bi Hz47K3iyqGwpWTkmSNNwNXf/P/FA+umfdHl1reYftpfEIELC+ny+LKfWp ECY7NmDHN6RHI86PE2hhUu03uk9QZRb9aUS6AkDDydNIS3V3WNCc3Xiat fkuGWKuioU0txMMObLBvZdj+p8ycd43REHN9DpiHoYDuZ1ou6ct/d3WH6 A==; X-CSE-ConnectionGUID: dOzJujxPQo+LvQsDTTByaQ== X-CSE-MsgGUID: LH3ZoiiURKqokSwOfTDksA== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434697" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434697" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:27 -0800 X-CSE-ConnectionGUID: it/u1kMrQG2UInClstZ4Fg== X-CSE-MsgGUID: kzOQkwweR2SSqVl4klD0XQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897640" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:24 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 01/10] i386/fw_cfg: move hpet_cfg definition to hpet.c Date: Sat, 25 Jan 2025 20:51:28 +0800 Message-Id: <20250125125137.1223277-2-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org HPET device needs to access and update hpet_cfg variable, but now it is defined in hw/i386/fw_cfg.c and Rust code can't access it. Move hpet_cfg definition to hpet.c (and rename it to hpet_fw_cfg). This allows Rust HPET device implements its own global hpet_fw_cfg variable, and will further reduce the use of unsafe C code access and calls in the Rust HPET implementation. Signed-off-by: Zhao Liu --- hw/i386/fw_cfg.c | 4 +--- hw/timer/hpet.c | 14 ++++++++------ include/hw/timer/hpet.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index d2cb08715a21..546de63123e6 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -26,8 +26,6 @@ #include CONFIG_DEVICES #include "target/i386/cpu.h" -struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; - const char *fw_cfg_arch_key_name(uint16_t key) { static const struct { @@ -153,7 +151,7 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, PCMachineState *pcms = (PCMachineState *)object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE); if (pcms && pcms->hpet_enabled) { - fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg)); + fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_fw_cfg, sizeof(hpet_fw_cfg)); } #endif diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 92b6d509edda..f2e2d83a3f67 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -40,6 +40,8 @@ #include "qom/object.h" #include "trace.h" +struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX}; + #define HPET_MSI_SUPPORT 0 OBJECT_DECLARE_SIMPLE_TYPE(HPETState, HPET) @@ -655,8 +657,8 @@ static void hpet_reset(DeviceState *d) s->hpet_counter = 0ULL; s->hpet_offset = 0ULL; s->config = 0ULL; - hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability; - hpet_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr; + hpet_fw_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability; + hpet_fw_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr; /* to document that the RTC lowers its output on reset as well */ s->rtc_irq_level = 0; @@ -698,17 +700,17 @@ static void hpet_realize(DeviceState *dev, Error **errp) if (!s->intcap) { warn_report("Hpet's intcap not initialized"); } - if (hpet_cfg.count == UINT8_MAX) { + if (hpet_fw_cfg.count == UINT8_MAX) { /* first instance */ - hpet_cfg.count = 0; + hpet_fw_cfg.count = 0; } - if (hpet_cfg.count == 8) { + if (hpet_fw_cfg.count == 8) { error_setg(errp, "Only 8 instances of HPET is allowed"); return; } - s->hpet_id = hpet_cfg.count++; + s->hpet_id = hpet_fw_cfg.count++; for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) { sysbus_init_irq(sbd, &s->irqs[i]); diff --git a/include/hw/timer/hpet.h b/include/hw/timer/hpet.h index 71e8c62453d1..c2656f7f0bef 100644 --- a/include/hw/timer/hpet.h +++ b/include/hw/timer/hpet.h @@ -73,7 +73,7 @@ struct hpet_fw_config struct hpet_fw_entry hpet[8]; } QEMU_PACKED; -extern struct hpet_fw_config hpet_cfg; +extern struct hpet_fw_config hpet_fw_cfg; #define TYPE_HPET "hpet" From patchwork Sat Jan 25 12:51:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950330 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 5ED8CC0218C for ; Sat, 25 Jan 2025 12:33:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLA-0008Dq-UF; Sat, 25 Jan 2025 07:32:44 -0500 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 1tbfL0-0008BP-AM; Sat, 25 Jan 2025 07:32:35 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfKy-0005TJ-1X; Sat, 25 Jan 2025 07:32:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808352; x=1769344352; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Y5lOC7itXdhtdQbuxxpKxG5odZWwd5vj2vFriJDCYUw=; b=dSYKUEThJQldZ+OXg15zJgiNoxZbiFOAV+qqPAdrzLWPlvDE6zFT6Q2Y /CmUnIROxsPbcVQnN+Gd9dZMEeFe1MSTvvuUIxwaJlUqrYpsFoPqWnql5 rpjeUD4t6mYBNyV3KlRU9XunmNVBj7RAKRmpFlvRqwa9cbAdIzwju5Qgn z7B1ECiYygc70KOE9qyEz7i0QnZKCh5AY6+SGf8tURowHQl0mb482PGTm N9ugDPpyNm9evNa1HqLRb5/T4CzRPCJvi4lkVfg964Wpy+TUdAPGmpGO3 iqYBV2RkLXU7P0jUbE2+JdhXwlt+dd4d1lL/8vo3ne1lu2YWDQsRaUNLq A==; X-CSE-ConnectionGUID: uAM7Wb+CRIy8nj7C4kk+fQ== X-CSE-MsgGUID: gjEYxZQVSsiaQ6j0q3eWmA== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434702" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434702" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:30 -0800 X-CSE-ConnectionGUID: oBuYJ4s6SJKukxDGJdDOuQ== X-CSE-MsgGUID: KqpmlBRwSWOvjDiIhqv8MQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897654" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:27 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 02/10] rust/qdev: add the macro to define bit property Date: Sat, 25 Jan 2025 20:51:29 +0800 Message-Id: <20250125125137.1223277-3-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org HPET device (Rust device) needs to define the bit type property. Add a variant of define_property macro to define bit type property. Signed-off-by: Zhao Liu --- rust/qemu-api/src/qdev.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index b348f2f4ce71..32740c873604 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -166,6 +166,18 @@ fn class_init(dc: &mut DeviceClass) { #[macro_export] macro_rules! define_property { + ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty, bit = $bitnr:expr, default = $defval:expr$(,)*) => { + $crate::bindings::Property { + // use associated function syntax for type checking + name: ::std::ffi::CStr::as_ptr($name), + info: $prop, + offset: $crate::offset_of!($state, $field) as isize, + bitnr: $bitnr, + set_default: true, + defval: $crate::bindings::Property__bindgen_ty_1 { u: $defval as u64 }, + ..$crate::zeroable::Zeroable::ZERO + } + }; ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty, default = $defval:expr$(,)*) => { $crate::bindings::Property { // use associated function syntax for type checking From patchwork Sat Jan 25 12:51:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950331 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 2B5B4C0218C for ; Sat, 25 Jan 2025 12:33:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLC-0008FC-1F; Sat, 25 Jan 2025 07:32:46 -0500 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 1tbfL2-0008DB-F2; Sat, 25 Jan 2025 07:32:37 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfKz-0005Tn-Tn; Sat, 25 Jan 2025 07:32:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808354; x=1769344354; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=g2Nb+4+IFvjo/YNhUOjtEgb72fVfBiMk6M52lBhjmVA=; b=iNzXPL/UHa2WH/USw/k54QGSlMVmp/0Y1kHNDkX6cAUNe9GGRe8JvqIR jdnNsGTz6qvt5gCTr4nOoXa31ipAu+0CG+QCKAjyLcxrH28ACdSy+kRpV hg0v4KIjtHZLlTsepLENol5IzNy4ubnDyZLI5JAPtlF9axgv5qXym/k/A SqxyCK+FSzgjUe6Iz864s1C+2pRioGMu4oqzq8Ac2uJyqWej7YkYNLxMW JxJK+vbU15LvSW98Kr65YoFkawY+tySZf24d8D6BAZcki8Qx04OxCeILe XjCo+u0WQq88dVtd/1X+55TLARMo28UHry6qMsgnPEd4w1v2LPYW0yyxc Q==; X-CSE-ConnectionGUID: 18ODjvVRRsat0x5mdvkdbw== X-CSE-MsgGUID: KENYnHVGRMSd943nIIh1oA== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434706" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434706" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:32 -0800 X-CSE-ConnectionGUID: 1jKWWoHKQPu2yQGtfejnPw== X-CSE-MsgGUID: SfP/7m22RgWE/3NXrvmXUQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897660" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:30 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 03/10] rust/irq: Add a helper to convert [InterruptSource] to [*mut IRQState] Date: Sat, 25 Jan 2025 20:51:30 +0800 Message-Id: <20250125125137.1223277-4-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This is useful to hanlde InterruptSource slice and pass it to C bindings. Suggested-by: Paolo Bonzini Signed-off-by: Zhao Liu --- Changes since RFC: * New commit. --- rust/qemu-api/src/irq.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/rust/qemu-api/src/irq.rs b/rust/qemu-api/src/irq.rs index 638545c3a649..7dca3b9ee5a8 100644 --- a/rust/qemu-api/src/irq.rs +++ b/rust/qemu-api/src/irq.rs @@ -5,12 +5,10 @@ //! Bindings for interrupt sources use core::ptr; -use std::{marker::PhantomData, os::raw::c_int}; +use std::{marker::PhantomData, os::raw::c_int, slice}; -use crate::{ - bindings::{qemu_set_irq, IRQState}, - prelude::*, -}; +pub(crate) use crate::bindings::IRQState; +use crate::{bindings::qemu_set_irq, prelude::*}; /// Interrupt sources are used by devices to pass changes to a value (typically /// a boolean). The interrupt sink is usually an interrupt controller or @@ -81,6 +79,16 @@ pub fn set(&self, level: T) { pub(crate) const fn as_ptr(&self) -> *mut *mut IRQState { self.cell.as_ptr() } + + #[allow(dead_code)] + pub(crate) fn as_slice_of_qemu_irq(slice: &[Self]) -> &[*mut IRQState] { + unsafe { + // SAFETY: InterruptSource has the same memory layout as *mut IRQState. + // Additionally, the slice parameter itself, as a reference to a slice type, + // can be converted into a valid pointer and has a valid length. + slice::from_raw_parts(slice.as_ptr().cast::<*mut IRQState>(), slice.len()) + } + } } impl Default for InterruptSource { From patchwork Sat Jan 25 12:51:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950333 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 E9D81C0218D for ; Sat, 25 Jan 2025 12:34:21 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLC-0008FQ-AN; Sat, 25 Jan 2025 07:32:46 -0500 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 1tbfL5-0008Dc-7I; Sat, 25 Jan 2025 07:32:42 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfL2-0005TJ-IR; Sat, 25 Jan 2025 07:32:37 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808356; x=1769344356; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uG8yPSeRPHsZyPZ+Zad72ZfjphYl5oyDQSD5QikG5aM=; b=TnBuRoVIiBHsypTvR7FSrG6g9qIKmlWYHA8P3/mLdXlOKjLtR7useWEn fvYEil4H65Z6RIFD7a+SHc5qu9uCH7t8oYvFzKA+poRphcBTmhyzTd8ev 1wcah65iUPrzkpZc1V+SWwL1qe9Ri2/PtgTQ1XXj8wc/8f0xGFrewDOox hED4Y0bXc9eWrCUV1jHdUZQoWRfVJOmhsiBtezYI0VJcnpO+YDiSMrmhD bN+KIZuAKkTtJlvNY/PZJMfdXnq+MCKpoIK7sYo4GvLh0CSndepcCk3Oo xXKsfxSqcZIfhd0jy0Fa6i81TmwVFqtc74MYHSLK80yjVZ9zrZfd7ZCz+ w==; X-CSE-ConnectionGUID: MBTQvNuBTJOFKlfUE7u42A== X-CSE-MsgGUID: CGaHuT2jTMesHmRJe5EHIg== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434711" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434711" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:35 -0800 X-CSE-ConnectionGUID: gHZ4qDm7TEiGsE4fzd9baQ== X-CSE-MsgGUID: kqtPSj9YRfS4kuRIzKraOw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897670" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:32 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 04/10] rust: add bindings for gpio_{in|out} initialization Date: Sat, 25 Jan 2025 20:51:31 +0800 Message-Id: <20250125125137.1223277-5-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Wrap qdev_init_gpio_{in|out} as methods in DeviceMethods. And for qdev_init_gpio_in, based on FnCall, it can support idiomatic Rust callback without the need for C style wrapper. Signed-off-by: Zhao Liu --- Changes since RFC: * Use FnCall to support gpio in callback. * Place gpio_{in|out} in DeviceMethods. * Accept &[InterruptSource] as the parameter of gpio_out. --- rust/qemu-api/src/qdev.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 32740c873604..96ca8b8aa9ad 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -6,16 +6,17 @@ use std::{ ffi::{CStr, CString}, - os::raw::c_void, + os::raw::{c_int, c_void}, ptr::NonNull, }; pub use bindings::{Clock, ClockEvent, DeviceClass, DeviceState, Property, ResetType}; use crate::{ - bindings::{self, Error, ResettableClass}, + bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, Error, ResettableClass}, callbacks::FnCall, cell::bql_locked, + irq::{IRQState, InterruptSource}, prelude::*, qom::{ClassInitImpl, ObjectClass, ObjectImpl, Owned}, vmstate::VMStateDescription, @@ -278,6 +279,38 @@ fn do_init_clock_in( // IsA bound. do_init_clock_in(unsafe { self.as_mut_ptr() }, name, cb, events) } + + fn init_gpio_in FnCall<(&'a Self::Target, u32, u32)>>(&self, num_lines: u32, _f: F) { + unsafe extern "C" fn rust_irq_handler FnCall<(&'a T, u32, u32)>>( + opaque: *mut c_void, + line: c_int, + level: c_int, + ) { + // SAFETY: the opaque was passed as a reference to `T` + F::call((unsafe { &*(opaque.cast::()) }, line as u32, level as u32)) + } + + let gpio_in_cb: unsafe extern "C" fn(*mut c_void, c_int, c_int) = + rust_irq_handler::; + + unsafe { + qdev_init_gpio_in( + self.as_mut_ptr::(), + Some(gpio_in_cb), + num_lines as c_int, + ); + } + } + + fn init_gpio_out(&self, pins: &[InterruptSource]) { + unsafe { + qdev_init_gpio_out( + self.as_mut_ptr::(), + InterruptSource::as_slice_of_qemu_irq(pins).as_ptr() as *mut *mut IRQState, + pins.len() as c_int, + ); + } + } } impl DeviceMethods for R where R::Target: IsA {} From patchwork Sat Jan 25 12:51:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950340 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 0FC76C0218C for ; Sat, 25 Jan 2025 12:35:15 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLD-0008G0-4J; Sat, 25 Jan 2025 07:32:47 -0500 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 1tbfL7-0008Dm-3h; Sat, 25 Jan 2025 07:32:42 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfL5-0005Tn-ES; Sat, 25 Jan 2025 07:32:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808359; x=1769344359; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Bv9++MIdsioOarcOj78lH/SZyI4MnsCAuILQhxiMHgE=; b=l/nE541tlCJwtNiTvWhu5yD7VsQuQqEgbMsbB6h/fIaaExsvoayxy3yV kAGFFeCHE4NAqhVh7aQkcY7kdUzzEEBr1PzyCrdQRovhoAy11T1cfucZW xh/4Bqs73m6NCQf8y6Lvb+g0ytb3ArGEdA6MsW2LdnhZzzlI2qJbjDicD fJNzGRZ5OTtgryZJVmP3ZeBHif2VqxsqnIMIHoGYydFSpmTTjFfoe8OGP 4qLXKCgnzZIIQyIpuAOF7yNXObyfqqP+USqa7mi4krCxvN/w6a6A3ogW+ aAqsXP3kt2Y/vLtayjW7TaahE5KH1fp/1JbNFASqUNgAq7rFHGX9RV0Qm Q==; X-CSE-ConnectionGUID: Em5MPB/aTfaYzrVqlkJ29w== X-CSE-MsgGUID: CGZEneUzSwyUscbmTIYfqg== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434716" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434716" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:38 -0800 X-CSE-ConnectionGUID: NbjuRh2QQ8GuGU+/G6HELw== X-CSE-MsgGUID: VaWIrpoPR5CiKHCDoDyUFQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897684" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:35 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 05/10] rust: add bindings for memattrs Date: Sat, 25 Jan 2025 20:51:32 +0800 Message-Id: <20250125125137.1223277-6-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The MemTxAttrs structure contains bitfield members, and bindgen is unable to generate an equivalent macro definition for MEMTXATTRS_UNSPECIFIED. Therefore, manually define a global constant variable MEMTXATTRS_UNSPECIFIED to support calls from Rust code. Signed-off-by: Zhao Liu --- Changes since RFC: * With a boolean type unspecified field, no need to add once_cell. * Merge memattrs binding to memory.rs. --- rust/qemu-api/src/memory.rs | 16 ++++++++++++++-- rust/qemu-api/src/zeroable.rs | 1 + rust/wrapper.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/rust/qemu-api/src/memory.rs b/rust/qemu-api/src/memory.rs index 963d689c27d4..fff92508c68f 100644 --- a/rust/qemu-api/src/memory.rs +++ b/rust/qemu-api/src/memory.rs @@ -2,7 +2,7 @@ // Author(s): Paolo Bonzini // SPDX-License-Identifier: GPL-2.0-or-later -//! Bindings for `MemoryRegion` and `MemoryRegionOps` +//! Bindings for `MemoryRegion`, `MemoryRegionOps` and `MemTxAttrs` use std::{ ffi::{CStr, CString}, @@ -11,7 +11,7 @@ ptr::addr_of, }; -pub use bindings::hwaddr; +pub use bindings::{hwaddr, MemTxAttrs}; use crate::{ bindings::{self, device_endian, memory_region_init_io}, @@ -189,3 +189,15 @@ unsafe impl ObjectType for MemoryRegion { unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_MEMORY_REGION) }; } qom_isa!(MemoryRegion: Object); + +/// A special `MemTxAttrs` constant, used to indicate that no memary +/// attributes are specified. +/// +/// Bus masters which don't specify any attributes will get this, +/// which has all attribute bits clear except the topmost one +/// (so that we can distinguish "all attributes deliberately clear" +/// from "didn't specify" if necessary). +pub const MEMTXATTRS_UNSPECIFIED: MemTxAttrs = MemTxAttrs { + unspecified: true, + ..Zeroable::ZERO +}; diff --git a/rust/qemu-api/src/zeroable.rs b/rust/qemu-api/src/zeroable.rs index 75742b50d4e3..9f009606b1ab 100644 --- a/rust/qemu-api/src/zeroable.rs +++ b/rust/qemu-api/src/zeroable.rs @@ -101,3 +101,4 @@ fn default() -> Self { impl_zeroable!(crate::bindings::MemoryRegionOps__bindgen_ty_1); impl_zeroable!(crate::bindings::MemoryRegionOps__bindgen_ty_2); impl_zeroable!(crate::bindings::MemoryRegionOps); +impl_zeroable!(crate::bindings::MemTxAttrs); diff --git a/rust/wrapper.h b/rust/wrapper.h index a9bc67af0d5f..54839ce0f510 100644 --- a/rust/wrapper.h +++ b/rust/wrapper.h @@ -62,3 +62,4 @@ typedef enum memory_order { #include "qapi/error.h" #include "migration/vmstate.h" #include "chardev/char-serial.h" +#include "exec/memattrs.h" From patchwork Sat Jan 25 12:51:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950334 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 EF24DC0218D for ; Sat, 25 Jan 2025 12:34:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLH-0008Ii-DV; Sat, 25 Jan 2025 07:32:51 -0500 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 1tbfLA-0008EM-Cw; Sat, 25 Jan 2025 07:32:44 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfL8-0005Un-KY; Sat, 25 Jan 2025 07:32:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808362; x=1769344362; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=CG+zEQTxRSGBCyngVJmO+rcdFlbWKDTPQVhDRFOBO2E=; b=TnxMTzsLcPDPloB0sdpxIksLoIwVS051bHq69c5UvpHBHwNL29taCR+F pnCS84qUW5vucHl2NtbB+PmnbjA//ZHfQdPF5vpH4Tt6d8pC7tDJh4HWe 5wmR9P8ehLSO7t/lc+2jCL8ySuZbTLUqIH+Uj8h0GNgNEQA4YhxKySgRy iM5y63w4cLWh+vvYvSAB09zQhdyhJh2l4h5hz3wcxjv/yljwpL5869dz4 j+PAKbp3HmhtWqbCzfjFLhNoh9oVF7eNnN+wU6Co+RMx71iXWILbCCuCm 5uJEWQPoUlU+j9rVpSzVREpD6bLayGXBO9fSm2UctT1R92WBthM/ahNto A==; X-CSE-ConnectionGUID: xqULjQZrSdarcVbhB/zF2g== X-CSE-MsgGUID: dnupu+TfSVS381pRfu+tvw== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434720" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434720" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:41 -0800 X-CSE-ConnectionGUID: BmSnw5WQQ9+FXMXJEeL7tw== X-CSE-MsgGUID: 3xo0NBwBQPG2KrEgKNBfug== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897697" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:38 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 06/10] rust: add bindings for timer Date: Sat, 25 Jan 2025 20:51:33 +0800 Message-Id: <20250125125137.1223277-7-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add timer bindings to help handle idiomatic Rust callbacks. Additionally, wrap QEMUClockType in ClockType binding to avoid unsafe calls in device code. Signed-off-by: Zhao Liu --- Changes since RFC: * Use FnCall to support timer callback. * Only add timer_init_full() binding. timer_new() is unnecessary since device (HPET) could create and allocate QEMUTimer. * Implement Drop for QEMUTimer. * Add ClockType binding. --- meson.build | 7 +++ rust/qemu-api/meson.build | 1 + rust/qemu-api/src/lib.rs | 1 + rust/qemu-api/src/timer.rs | 92 ++++++++++++++++++++++++++++++++++++++ rust/wrapper.h | 1 + 5 files changed, 102 insertions(+) create mode 100644 rust/qemu-api/src/timer.rs diff --git a/meson.build b/meson.build index da91b47be48b..1ec88770a60a 100644 --- a/meson.build +++ b/meson.build @@ -4079,6 +4079,13 @@ if have_rust foreach enum : c_bitfields bindgen_args += ['--bitfield-enum', enum] endforeach + c_nocopy = [ + 'QEMUTimer', + ] + # Used to customize Drop trait + foreach struct : c_nocopy + bindgen_args += ['--no-copy', struct] + endforeach # TODO: Remove this comment when the clang/libclang mismatch issue is solved. # diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index 80eafc7f6bd8..caed2b233991 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -29,6 +29,7 @@ _qemu_api_rs = static_library( 'src/qdev.rs', 'src/qom.rs', 'src/sysbus.rs', + 'src/timer.rs', 'src/vmstate.rs', 'src/zeroable.rs', ], diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 8cc095b13f6f..88825b69cff8 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -24,6 +24,7 @@ pub mod qdev; pub mod qom; pub mod sysbus; +pub mod timer; pub mod vmstate; pub mod zeroable; diff --git a/rust/qemu-api/src/timer.rs b/rust/qemu-api/src/timer.rs new file mode 100644 index 000000000000..a1c7c7b4d9e6 --- /dev/null +++ b/rust/qemu-api/src/timer.rs @@ -0,0 +1,92 @@ +// Copyright (C) 2024 Intel Corporation. +// Author(s): Zhao Liu +// SPDX-License-Identifier: GPL-2.0-or-later + +use std::os::raw::{c_int, c_void}; + +pub use bindings::QEMUTimer; + +use crate::{ + bindings::{ + self, qemu_clock_get_ns, timer_del, timer_init_full, timer_mod, QEMUClockType, + QEMUTimerListGroup, + }, + callbacks::FnCall, +}; + +impl QEMUTimer { + pub fn new() -> Self { + Default::default() + } + + pub fn timer_init_full<'timer, 'opaque: 'timer, T, F>( + &'timer mut self, + timer_list_group: Option<&QEMUTimerListGroup>, + clk_type: QEMUClockType, + scale: u32, + attributes: u32, + _f: F, + opaque: &'opaque T, + ) where + F: for<'a> FnCall<(&'a T,)>, + { + /// timer expiration callback + unsafe extern "C" fn rust_timer_handler FnCall<(&'a T,)>>( + opaque: *mut c_void, + ) { + // SAFETY: the opaque was passed as a reference to `T`. + F::call((unsafe { &*(opaque.cast::()) },)) + } + + let timer_cb: unsafe extern "C" fn(*mut c_void) = rust_timer_handler::; + + // SAFETY: the opaque outlives the timer + unsafe { + timer_init_full( + self, + if let Some(g) = timer_list_group { + g as *const QEMUTimerListGroup as *mut QEMUTimerListGroup + } else { + ::core::ptr::null_mut() + }, + clk_type, + scale as c_int, + attributes as c_int, + Some(timer_cb), + (opaque as *const T).cast::() as *mut c_void, + ) + } + } + + pub fn timer_mod(&mut self, expire_time: u64) { + unsafe { timer_mod(self as *mut QEMUTimer, expire_time as i64) } + } +} + +impl Drop for QEMUTimer { + fn drop(&mut self) { + unsafe { timer_del(self as *mut QEMUTimer) } + } +} + +pub fn qemu_clock_get_virtual_ns() -> u64 { + // SAFETY: + // Valid parameter. + (unsafe { qemu_clock_get_ns(QEMUClockType::QEMU_CLOCK_VIRTUAL) }) as u64 +} + +pub struct ClockType { + pub id: QEMUClockType, +} + +impl ClockType { + pub fn get_ns(&self) -> u64 { + // SAFETY: cannot be created outside this module, therefore id + // is valid + (unsafe { qemu_clock_get_ns(self.id) }) as u64 + } +} + +pub const CLOCK_VIRTUAL: ClockType = ClockType { + id: QEMUClockType::QEMU_CLOCK_VIRTUAL, +}; diff --git a/rust/wrapper.h b/rust/wrapper.h index 54839ce0f510..a35bfbd1760d 100644 --- a/rust/wrapper.h +++ b/rust/wrapper.h @@ -63,3 +63,4 @@ typedef enum memory_order { #include "migration/vmstate.h" #include "chardev/char-serial.h" #include "exec/memattrs.h" +#include "qemu/timer.h" From patchwork Sat Jan 25 12:51:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950335 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 C9209C0218C for ; Sat, 25 Jan 2025 12:34:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLI-0008JS-3B; Sat, 25 Jan 2025 07:32:52 -0500 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 1tbfLD-0008GK-PX; Sat, 25 Jan 2025 07:32:48 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfLB-0005Un-Lz; Sat, 25 Jan 2025 07:32:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808366; x=1769344366; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0nXwWEhLsDw+8Ie1OJwaMypor/NsANl1OODd2nJcphU=; b=I42LRqkVNFb8vOshaE6s1JYZ5/2fM/MUExBzLhkfYB5xgZdHvJvxGfAq e5R/6cmuG5zJGj5Jj+zm7gBnz86/ddthrf3SqsyhYaR14n34WiRToYbMd /A5ilEI/WaXfS3TBtysQYiLRrv0P4TQIfL9LheGyePM8mHHWTKoTjxVsN S5bGn+3PxKlepUaSZB9zcM+L3GnNVl8FJnPZJ5H5N4JJIwExiZiP0aGzR eUfFYsv1G5GrDC4822lqtACQCq+/ICOkox2lihuW5lvicfWPP9zJEDpcu dm41NnbFFS0c6VoxXGaTZQgqnHmID2Q+HQjoWvuHLwbqgmJ0UyMx3E8Wv Q==; X-CSE-ConnectionGUID: cOx2GZg5RMqqW3INYCqEEA== X-CSE-MsgGUID: d7p+bvG5SDe0qa5ZSKHl9w== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434725" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434725" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:44 -0800 X-CSE-ConnectionGUID: EcFtQ4aJQGyuOk10x8f6XQ== X-CSE-MsgGUID: mzPlCT5iQZm53oV7nMC5rw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897734" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:41 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 07/10] rust/timer/hpet: define hpet_cfg Date: Sat, 25 Jan 2025 20:51:34 +0800 Message-Id: <20250125125137.1223277-8-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Define HPETFwEntry structure with the same memory layout as hpet_fw_entry in C. Further, define the global hpet_cfg variable in Rust which is the same as the C version. This hpet_cfg variable in Rust will replace the C version one and allows both Rust code and C code to access it. The Rust version of hpet_cfg is self-contained, avoiding unsafe access to C code. Signed-off-by: Zhao Liu --- Changes since RFC: * hpet_fw_cfg doesn't need a BqlRefCell. --- rust/Cargo.lock | 8 +++ rust/Cargo.toml | 1 + rust/hw/meson.build | 1 + rust/hw/timer/hpet/Cargo.toml | 14 +++++ rust/hw/timer/hpet/meson.build | 18 +++++++ rust/hw/timer/hpet/src/fw_cfg.rs | 87 ++++++++++++++++++++++++++++++++ rust/hw/timer/hpet/src/lib.rs | 13 +++++ rust/hw/timer/meson.build | 1 + rust/qemu-api/src/zeroable.rs | 6 ++- 9 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 rust/hw/timer/hpet/Cargo.toml create mode 100644 rust/hw/timer/hpet/meson.build create mode 100644 rust/hw/timer/hpet/src/fw_cfg.rs create mode 100644 rust/hw/timer/hpet/src/lib.rs create mode 100644 rust/hw/timer/meson.build diff --git a/rust/Cargo.lock b/rust/Cargo.lock index c0c6069247a8..79e142723b83 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -37,6 +37,14 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +[[package]] +name = "hpet" +version = "0.1.0" +dependencies = [ + "qemu_api", + "qemu_api_macros", +] + [[package]] name = "itertools" version = "0.11.0" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 5b6b6ca43825..9265d30f46a2 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -4,6 +4,7 @@ members = [ "qemu-api-macros", "qemu-api", "hw/char/pl011", + "hw/timer/hpet", ] [workspace.lints.rust] diff --git a/rust/hw/meson.build b/rust/hw/meson.build index 860196645e71..9749d4adfc96 100644 --- a/rust/hw/meson.build +++ b/rust/hw/meson.build @@ -1 +1,2 @@ subdir('char') +subdir('timer') diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml new file mode 100644 index 000000000000..db2ef4642b4f --- /dev/null +++ b/rust/hw/timer/hpet/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "hpet" +version = "0.1.0" +edition = "2021" +authors = ["Zhao Liu "] +license = "GPL-2.0-or-later" +description = "IA-PC High Precision Event Timer emulation in Rust" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +qemu_api = { path = "../../../qemu-api" } +qemu_api_macros = { path = "../../../qemu-api-macros" } diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build new file mode 100644 index 000000000000..c2d7c0532ca4 --- /dev/null +++ b/rust/hw/timer/hpet/meson.build @@ -0,0 +1,18 @@ +_libhpet_rs = static_library( + 'hpet', + files('src/lib.rs'), + override_options: ['rust_std=2021', 'build.rust_std=2021'], + rust_abi: 'rust', + dependencies: [ + qemu_api, + qemu_api_macros, + ], +) + +rust_devices_ss.add(when: 'CONFIG_X_HPET_RUST', if_true: [declare_dependency( + link_whole: [_libhpet_rs], + # Putting proc macro crates in `dependencies` is necessary for Meson to find + # them when compiling the root per-target static rust lib. + dependencies: [qemu_api_macros], + variables: {'crate': 'hpet'}, +)]) diff --git a/rust/hw/timer/hpet/src/fw_cfg.rs b/rust/hw/timer/hpet/src/fw_cfg.rs new file mode 100644 index 000000000000..2f72bf854a66 --- /dev/null +++ b/rust/hw/timer/hpet/src/fw_cfg.rs @@ -0,0 +1,87 @@ +// Copyright (C) 2024 Intel Corporation. +// Author(s): Zhao Liu +// SPDX-License-Identifier: GPL-2.0-or-later + +#![allow(dead_code)] + +use qemu_api::{cell::bql_locked, impl_zeroable, zeroable::Zeroable}; + +// Each HPETState represents a Event Timer Block. The v1 spec supports +// up to 8 blocks. QEMU only uses 1 block (in PC machine). +const HPET_MAX_NUM_EVENT_TIMER_BLOCK: usize = 8; + +#[repr(C, packed)] +#[derive(Copy, Clone, Default)] +pub struct HPETFwEntry { + pub event_timer_block_id: u32, + pub address: u64, + pub min_tick: u16, + pub page_prot: u8, +} + +unsafe impl Zeroable for HPETFwEntry { + const ZERO: Self = Self { + event_timer_block_id: 0, + address: 0, + min_tick: 0, + page_prot: 0, + }; +} + +#[repr(C, packed)] +#[derive(Copy, Clone, Default)] +pub struct HPETFwConfig { + pub count: u8, + pub hpet: [HPETFwEntry; HPET_MAX_NUM_EVENT_TIMER_BLOCK], +} + +impl_zeroable!(HPETFwConfig); + +#[allow(non_upper_case_globals)] +#[no_mangle] +pub static mut hpet_fw_cfg: HPETFwConfig = HPETFwConfig { + count: u8::MAX, + ..Zeroable::ZERO +}; + +impl HPETFwConfig { + pub(crate) fn assign_hpet_id() -> usize { + assert!(bql_locked()); + // SAFETY: all accesses go through these methods, which guarantee + // that the accesses are protected by the BQL. + let fw_cfg = unsafe { &mut hpet_fw_cfg }; + + if fw_cfg.count == u8::MAX { + // first instance + fw_cfg.count = 0; + } + + if fw_cfg.count == 8 { + // TODO: Add error binding: error_setg() + panic!("Only 8 instances of HPET is allowed"); + } + + let id: usize = fw_cfg.count.into(); + fw_cfg.count += 1; + id + } + + pub(crate) fn update_hpet_cfg( + hpet_id: usize, + event_timer_block_id: Option, + address: Option, + ) { + assert!(bql_locked()); + // SAFETY: all accesses go through these methods, which guarantee + // that the accesses are protected by the BQL. + let fw_cfg = unsafe { &mut hpet_fw_cfg }; + + if let Some(e) = event_timer_block_id { + fw_cfg.hpet[hpet_id].event_timer_block_id = e; + } + + if let Some(a) = address { + fw_cfg.hpet[hpet_id].address = a; + } + } +} diff --git a/rust/hw/timer/hpet/src/lib.rs b/rust/hw/timer/hpet/src/lib.rs new file mode 100644 index 000000000000..c2b9c64d0bfe --- /dev/null +++ b/rust/hw/timer/hpet/src/lib.rs @@ -0,0 +1,13 @@ +// Copyright (C) 2024 Intel Corporation. +// Author(s): Zhao Liu +// SPDX-License-Identifier: GPL-2.0-or-later +// +// HPET QEMU Device Model +// +// This library implements a device model for the IA-PC HPET (High +// Precision Event Timers) device in QEMU. +// + +#![deny(unsafe_op_in_unsafe_fn)] + +pub mod fw_cfg; diff --git a/rust/hw/timer/meson.build b/rust/hw/timer/meson.build new file mode 100644 index 000000000000..22a84f15536b --- /dev/null +++ b/rust/hw/timer/meson.build @@ -0,0 +1 @@ +subdir('hpet') diff --git a/rust/qemu-api/src/zeroable.rs b/rust/qemu-api/src/zeroable.rs index 9f009606b1ab..cd424e6ea050 100644 --- a/rust/qemu-api/src/zeroable.rs +++ b/rust/qemu-api/src/zeroable.rs @@ -56,6 +56,7 @@ pub unsafe trait Zeroable: Default { /// ## Differences with `core::mem::zeroed` /// /// `const_zero` zeroes padding bits, while `core::mem::zeroed` doesn't +#[macro_export] macro_rules! const_zero { // This macro to produce a type-generic zero constant is taken from the // const_zero crate (v0.1.1): @@ -77,10 +78,11 @@ union TypeAsBytes { } /// A wrapper to implement the `Zeroable` trait through the `const_zero` macro. +#[macro_export] macro_rules! impl_zeroable { ($type:ty) => { - unsafe impl Zeroable for $type { - const ZERO: Self = unsafe { const_zero!($type) }; + unsafe impl $crate::zeroable::Zeroable for $type { + const ZERO: Self = unsafe { $crate::const_zero!($type) }; } }; } From patchwork Sat Jan 25 12:51:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950332 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 8670FC0218C for ; Sat, 25 Jan 2025 12:34:10 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLI-0008Js-TF; Sat, 25 Jan 2025 07:32:53 -0500 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 1tbfLH-0008Ih-Ci; Sat, 25 Jan 2025 07:32:51 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfLE-0005Un-Gu; Sat, 25 Jan 2025 07:32:51 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808368; x=1769344368; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=fqfSLQpyG5tZ78FAZYRkF+oxY5k+vZ+Sgwe8jmgI7p4=; b=cw6K4/PWn4lzsfMkXDLdM+3GOUqabS2p/L+t+npO3oMsCdeb35PT01T9 LHdh2QAKkxtu2far8+yuHQDKfZ/eg5tCHhFIf5D1bXVNFPUcfsly5dt44 l/rzYTDfeAeLkhBzhnFqsALXvrb/ah8k5esKwjrKevXgqS7LFXbi48HXg Jd8X4GZciLfC++Ivre0ZFfRuddvEnGpcS/Jx+v44CxD8vL1T1RTv30jli bn1lICKJXI72do5fk5MDD/hsKf1MlEOiC9I8FnHUC1e6ZjpfofliWnQdF wlZL6+OZknYo52jO8PuyPRBrXRWv8Ey7u6z6MWxkv6RfJ+wJFQ3Wzosoz g==; X-CSE-ConnectionGUID: lLLSd/0WScCej9tnqJJjPw== X-CSE-MsgGUID: KRhJziZrQTyM+wdYHHtkAw== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434730" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434730" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:47 -0800 X-CSE-ConnectionGUID: x4Hlx754QeWhVCOblbiTpQ== X-CSE-MsgGUID: R8j0cuhMS9Wv/d+2eRTDKQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897756" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:44 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 08/10] rust/timer/hpet: add basic HPET timer and HPETState Date: Sat, 25 Jan 2025 20:51:35 +0800 Message-Id: <20250125125137.1223277-9-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add the HPETTimer and HPETState (HPET timer block), along with their basic methods and register definitions. This is in preparation for supporting the QAPI interfaces. Note, wrap all items in HPETState that may be changed in the callback called by C code into the BqlCell/BqlRefCell. Signed-off-by: Zhao Liu --- Changes since RFC: * Don't wrap HPETState.flags in a BqlCell. * Consolidate inmutable &self and QOM casting. * Prefer timer iterator over loop. * Use BqlRefCell directly to store timers in HPETState. --- rust/hw/timer/hpet/src/hpet.rs | 633 +++++++++++++++++++++++++++++++++ rust/hw/timer/hpet/src/lib.rs | 1 + rust/wrapper.h | 1 + 3 files changed, 635 insertions(+) create mode 100644 rust/hw/timer/hpet/src/hpet.rs diff --git a/rust/hw/timer/hpet/src/hpet.rs b/rust/hw/timer/hpet/src/hpet.rs new file mode 100644 index 000000000000..0884a2ac73c4 --- /dev/null +++ b/rust/hw/timer/hpet/src/hpet.rs @@ -0,0 +1,633 @@ +// Copyright (C) 2024 Intel Corporation. +// Author(s): Zhao Liu +// SPDX-License-Identifier: GPL-2.0-or-later + +#![allow(dead_code)] + +use core::ptr::{null_mut, NonNull}; + +use qemu_api::{ + bindings::{address_space_memory, address_space_stl_le, MemoryRegion, SCALE_NS}, + cell::{BqlCell, BqlRefCell}, + irq::InterruptSource, + memory::MEMTXATTRS_UNSPECIFIED, + prelude::*, + qom::ParentField, + sysbus::SysBusDevice, + timer::{QEMUTimer, CLOCK_VIRTUAL}, +}; + +// Register space for each timer block. (HPET_BASE isn't defined here.) +const HPET_REG_SPACE_LEN: u64 = 0x400; // 1024 bytes + +const HPET_MIN_TIMERS: usize = 3; // Minimum recommended hardware implementation. +const HPET_MAX_TIMERS: usize = 32; // Maximum timers in each timer block. + +// Flags that HPETState.flags supports. +const HPET_FLAG_MSI_SUPPORT_SHIFT: usize = 0; + +const HPET_NUM_IRQ_ROUTES: usize = 32; +const HPET_LEGACY_PIT_INT: u32 = 0; // HPET_LEGACY_RTC_INT isn't defined here. +const RTC_ISA_IRQ: usize = 8; + +const HPET_CLK_PERIOD: u64 = 10; // 10 ns +const FS_PER_NS: u64 = 1000000; // 1000000 femtoseconds == 1 ns + +// General Capabilities and ID Register +const HPET_CAP_REG: u64 = 0x000; +// Revision ID (bits 0:7) +const HPET_CAP_REV_ID_VALUE: u64 = 0x1; // Revision 1 is implemented (refer to v1.0a spec). +const HPET_CAP_REV_ID_SHIFT: usize = 0; +// Number of Timers (bits 8:12) +const HPET_CAP_NUM_TIM_SHIFT: usize = 8; +// Counter Size (bit 13) +const HPET_CAP_COUNT_SIZE_CAP_SHIFT: usize = 13; +// LegacyReplacement Route Capable (bit 15) +const HPET_CAP_LEG_RT_CAP_SHIFT: usize = 15; +// Vendor ID (bits 16:31) +const HPET_CAP_VENDER_ID_VALUE: u64 = 0x8086; +const HPET_CAP_VENDER_ID_SHIFT: usize = 16; +// Main Counter Tick Period (bits 32:63) +const HPET_CAP_CNT_CLK_PERIOD_SHIFT: usize = 32; + +// General Configuration Register +const HPET_CFG_REG: u64 = 0x010; +// Overall Enable (bit 0) +const HPET_CFG_ENABLE_SHIFT: usize = 0; +// LegacyReplacement Route (bit 1) +const HPET_CFG_LEG_RT_SHIFT: usize = 1; +// Other bits are reserved. +const HPET_CFG_WRITE_MASK: u64 = 0x003; + +// General Interrupt Status Register +const HPET_INT_STATUS_REG: u64 = 0x020; + +// Main Counter Value Register +const HPET_COUNTER_REG: u64 = 0x0f0; + +// Timer N Configuration and Capability Register (masked by 0x18) +const HPET_TN_CFG_REG: u64 = 0x000; +// bit 0, 7, and bits 16:31 are reserved. +// bit 4, 5, 15, and bits 32:64 are read-only. +const HPET_TN_CFG_WRITE_MASK: u64 = 0x7f4e; +// Timer N Interrupt Type (bit 1) +const HPET_TN_CFG_INT_TYPE_SHIFT: usize = 1; +// Timer N Interrupt Enable (bit 2) +const HPET_TN_CFG_INT_ENABLE_SHIFT: usize = 2; +// Timer N Type (Periodic enabled or not, bit 3) +const HPET_TN_CFG_PERIODIC_SHIFT: usize = 3; +// Timer N Periodic Interrupt Capable (support Periodic or not, bit 4) +const HPET_TN_CFG_PERIODIC_CAP_SHIFT: usize = 4; +// Timer N Size (timer size is 64-bits or 32 bits, bit 5) +const HPET_TN_CFG_SIZE_CAP_SHIFT: usize = 5; +// Timer N Value Set (bit 6) +const HPET_TN_CFG_SETVAL_SHIFT: usize = 6; +// Timer N 32-bit Mode (bit 8) +const HPET_TN_CFG_32BIT_SHIFT: usize = 8; +// Timer N Interrupt Rout (bits 9:13) +const HPET_TN_CFG_INT_ROUTE_MASK: u64 = 0x3e00; +const HPET_TN_CFG_INT_ROUTE_SHIFT: usize = 9; +// Timer N FSB Interrupt Enable (bit 14) +const HPET_TN_CFG_FSB_ENABLE_SHIFT: usize = 14; +// Timer N FSB Interrupt Delivery (bit 15) +const HPET_TN_CFG_FSB_CAP_SHIFT: usize = 15; +// Timer N Interrupt Routing Capability (bits 32:63) +const HPET_TN_CFG_INT_ROUTE_CAP_SHIFT: usize = 32; + +// Timer N Comparator Value Register (masked by 0x18) +const HPET_TN_CMP_REG: u64 = 0x008; + +// Timer N FSB Interrupt Route Register (masked by 0x18) +const HPET_TN_FSB_ROUTE_REG: u64 = 0x010; + +fn hpet_next_wrap(cur_tick: u64) -> u64 { + (cur_tick | 0xffffffff) + 1 +} + +fn hpet_time_after(a: u64, b: u64) -> bool { + ((b - a) as i64) < 0 +} + +fn ticks_to_ns(value: u64) -> u64 { + value * HPET_CLK_PERIOD +} + +fn ns_to_ticks(value: u64) -> u64 { + value / HPET_CLK_PERIOD +} + +// Avoid touching the bits that cannot be written. +fn hpet_fixup_reg(new: u64, old: u64, mask: u64) -> u64 { + (new & mask) | (old & !mask) +} + +fn activating_bit(old: u64, new: u64, shift: usize) -> bool { + let mask: u64 = 1 << shift; + (old & mask == 0) && (new & mask != 0) +} + +fn deactivating_bit(old: u64, new: u64, shift: usize) -> bool { + let mask: u64 = 1 << shift; + (old & mask != 0) && (new & mask == 0) +} + +fn timer_handler(timer_cell: &BqlRefCell) { + timer_cell.borrow_mut().callback() +} + +/// HPET Timer Abstraction +#[repr(C)] +#[derive(Debug, Default, qemu_api_macros::offsets)] +pub struct HPETTimer { + /// timer N index within the timer block (HPETState) + #[doc(alias = "tn")] + index: usize, + qemu_timer: Option>, + /// timer block abstraction containing this timer + state: Option>, + + /// Memory-mapped, software visible timer registers + + /// Timer N Configuration and Capability Register + config: u64, + /// Timer N Comparator Value Register + cmp: u64, + /// Timer N FSB Interrupt Route Register + fsb: u64, + + /// Hidden register state + + /// comparator (extended to counter width) + cmp64: u64, + /// Last value written to comparator + period: u64, + /// timer pop will indicate wrap for one-shot 32-bit + /// mode. Next pop will be actual timer expiration. + wrap_flag: u8, + /// last value armed, to avoid timer storms + last: u64, +} + +impl HPETTimer { + fn init(&mut self, index: usize, state_ptr: *mut HPETState) -> &mut Self { + *self = HPETTimer::default(); + self.index = index; + self.state = NonNull::new(state_ptr); + self + } + + fn init_timer_with_state(&mut self) { + self.qemu_timer = Some(Box::new({ + let mut t = QEMUTimer::new(); + t.timer_init_full( + None, + CLOCK_VIRTUAL.id, + SCALE_NS, + 0, + timer_handler, + &self.get_state().timers[self.index], + ); + t + })); + } + + fn get_state(&self) -> &HPETState { + // SAFETY: + // the pointer is convertible to a reference + unsafe { self.state.unwrap().as_ref() } + } + + fn is_int_active(&self) -> bool { + self.get_state().is_timer_int_active(self.index) + } + + fn is_fsb_route_enabled(&self) -> bool { + self.config & 1 << HPET_TN_CFG_FSB_ENABLE_SHIFT != 0 + } + + fn is_periodic(&self) -> bool { + self.config & 1 << HPET_TN_CFG_PERIODIC_SHIFT != 0 + } + + fn is_int_enabled(&self) -> bool { + self.config & 1 << HPET_TN_CFG_INT_ENABLE_SHIFT != 0 + } + + fn is_32bit_mod(&self) -> bool { + self.config & 1 << HPET_TN_CFG_32BIT_SHIFT != 0 + } + + fn is_valset_enabled(&self) -> bool { + self.config & 1 << HPET_TN_CFG_SETVAL_SHIFT != 0 + } + + fn clear_valset(&mut self) { + self.config &= !(1 << HPET_TN_CFG_SETVAL_SHIFT); + } + + /// True if timer interrupt is level triggered; otherwise, edge triggered. + fn is_int_level_triggered(&self) -> bool { + self.config & 1 << HPET_TN_CFG_INT_TYPE_SHIFT != 0 + } + + /// calculate next value of the general counter that matches the + /// target (either entirely, or the low 32-bit only depending on + /// the timer mode). + fn calculate_cmp64(&self, cur_tick: u64, target: u64) -> u64 { + if self.is_32bit_mod() { + let mut result: u64 = cur_tick.deposit(0, 32, target); + if result < cur_tick { + result += 0x100000000; + } + result + } else { + target + } + } + + fn get_individual_route(&self) -> usize { + ((self.config & HPET_TN_CFG_INT_ROUTE_MASK) >> HPET_TN_CFG_INT_ROUTE_SHIFT) as usize + } + + fn get_int_route(&self) -> usize { + if self.index <= 1 && self.get_state().is_legacy_mode() { + // If LegacyReplacement Route bit is set, HPET specification requires + // timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC, + // timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. + // + // If the LegacyReplacement Route bit is set, the individual routing + // bits for timers 0 and 1 (APIC or FSB) will have no impact. + // + // FIXME: Consider I/O APIC case. + if self.index == 0 { + 0 + } else { + RTC_ISA_IRQ + } + } else { + // (If the LegacyReplacement Route bit is set) Timer 2-n will be + // routed as per the routing in the timer n config registers. + // ... + // If the LegacyReplacement Route bit is not set, the individual + // routing bits for each of the timers are used. + self.get_individual_route() + } + } + + fn set_irq(&mut self, set: bool) { + let route = self.get_int_route(); + + if set && self.is_int_enabled() && self.get_state().is_hpet_enabled() { + if self.is_fsb_route_enabled() { + // SAFETY: + // the parameters are valid. + unsafe { + address_space_stl_le( + &mut address_space_memory, + self.fsb >> 32, // Timer N FSB int addr + self.fsb as u32, // Timer N FSB int value, truncate! + MEMTXATTRS_UNSPECIFIED, + null_mut(), + ); + } + } else if self.is_int_level_triggered() { + self.get_state().irqs[route].raise(); + } else { + self.get_state().irqs[route].pulse(); + } + } else if !self.is_fsb_route_enabled() { + self.get_state().irqs[route].lower(); + } + } + + fn update_irq(&mut self, set: bool) { + // If Timer N Interrupt Enable bit is 0, "the timer will + // still operate and generate appropriate status bits, but + // will not cause an interrupt" + self.get_state() + .update_int_status(self.index as u32, set && self.is_int_level_triggered()); + self.set_irq(set); + } + + fn arm_timer(&mut self, tick: u64) { + let mut ns = self.get_state().get_ns(tick); + + // Clamp period to reasonable min value (1 us) + if self.is_periodic() && ns - self.last < 1000 { + ns = self.last + 1000; + } + + self.last = ns; + if let Some(timer) = self.qemu_timer.as_mut() { + timer.timer_mod(self.last); + } + } + + fn set_timer(&mut self) { + let cur_tick: u64 = self.get_state().get_ticks(); + + self.wrap_flag = 0; + self.cmp64 = self.calculate_cmp64(cur_tick, self.cmp); + if self.is_32bit_mod() { + // HPET spec says in one-shot 32-bit mode, generate an interrupt when + // counter wraps in addition to an interrupt with comparator match. + if !self.is_periodic() && self.cmp64 > hpet_next_wrap(cur_tick) { + self.wrap_flag = 1; + self.arm_timer(hpet_next_wrap(cur_tick)); + return; + } + } + self.arm_timer(self.cmp64); + } + + fn del_timer(&mut self) { + if let Some(timer) = self.qemu_timer.take() { + std::mem::drop(timer); + } + + if self.is_int_active() { + // For level-triggered interrupt, this leaves interrupt status + // register set but lowers irq. + self.update_irq(true); + } + } + + // Configuration and Capability Register + fn set_tn_cfg_reg(&mut self, shift: u32, len: u32, val: u64) { + // TODO: Add trace point - trace_hpet_ram_write_tn_cfg(addr & 4) + let old_val: u64 = self.config; + let mut new_val: u64 = old_val.deposit(shift, len, val); + new_val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK); + + // Switch level-type interrupt to edge-type. + if deactivating_bit(old_val, new_val, HPET_TN_CFG_INT_TYPE_SHIFT) { + // Do this before changing timer.config; otherwise, if + // HPET_TN_FSB is set, update_irq will not lower the qemu_irq. + self.update_irq(false); + } + + self.config = new_val; + + if activating_bit(old_val, new_val, HPET_TN_CFG_INT_ENABLE_SHIFT) && self.is_int_active() { + self.update_irq(true); + } + + if self.is_32bit_mod() { + self.cmp = self.cmp as u32 as u64; // truncate! + self.period = self.period as u32 as u64; // truncate! + } + + if self.get_state().is_hpet_enabled() { + self.set_timer(); + } + } + + /// Comparator Value Register + fn set_tn_cmp_reg(&mut self, shift: u32, len: u32, val: u64) { + let mut length = len; + let mut value = val; + + // TODO: Add trace point - trace_hpet_ram_write_tn_cmp(addr & 4) + if self.is_32bit_mod() { + // High 32-bits are zero, leave them untouched. + if shift != 0 { + // TODO: Add trace point - trace_hpet_ram_write_invalid_tn_cmp() + return; + } + length = 64; + value = value as u32 as u64; // truncate! + } + + if !self.is_periodic() || self.is_valset_enabled() { + self.cmp = self.cmp.deposit(shift, length, value); + } + + if self.is_periodic() { + self.period = self.period.deposit(shift, length, value); + } + + self.clear_valset(); + if self.get_state().is_hpet_enabled() { + self.set_timer(); + } + } + + /// FSB Interrupt Route Register + fn set_tn_fsb_route_reg(&mut self, shift: u32, len: u32, val: u64) { + self.fsb = self.fsb.deposit(shift, len, val); + } + + fn reset(&mut self) { + self.del_timer(); + self.cmp = u64::MAX; // Comparator Match Registers reset to all 1's. + self.config = 1 << HPET_TN_CFG_PERIODIC_CAP_SHIFT | 1 << HPET_TN_CFG_SIZE_CAP_SHIFT; + if self.get_state().has_msi_flag() { + self.config |= 1 << HPET_TN_CFG_FSB_CAP_SHIFT; + } + // advertise availability of ioapic int + self.config |= (self.get_state().int_route_cap as u64) << HPET_TN_CFG_INT_ROUTE_CAP_SHIFT; + self.period = 0; + self.wrap_flag = 0; + } + + /// timer expiration callback + fn callback(&mut self) { + let period: u64 = self.period; + let cur_tick: u64 = self.get_state().get_ticks(); + + if self.is_periodic() && period != 0 { + while hpet_time_after(cur_tick, self.cmp64) { + self.cmp64 += period; + } + if self.is_32bit_mod() { + self.cmp = self.cmp64 as u32 as u64; + } else { + self.cmp = self.cmp64; + } + self.arm_timer(self.cmp64); + } else if self.wrap_flag != 0 { + self.wrap_flag = 0; + self.arm_timer(self.cmp64); + } + self.update_irq(true); + } +} + +/// HPET Event Timer Block Abstraction +/// Note: Wrap all items that may be changed in the callback called by C +/// into the BqlCell/BqlRefCell. +#[repr(C)] +#[derive(qemu_api_macros::offsets)] +pub struct HPETState { + parent_obj: ParentField, + iomem: MemoryRegion, + + /// HPET block Registers: Memory-mapped, software visible registers + + /// General Capabilities and ID Register + capability: BqlCell, + /// General Configuration Register + config: BqlCell, + /// General Interrupt Status Register + #[doc(alias = "isr")] + int_status: BqlCell, + /// Main Counter Value Register + #[doc(alias = "hpet_counter")] + counter: BqlCell, + + /// Internal state + + /// Capabilities that QEMU HPET supports. + /// bit 0: MSI (or FSB) support. + flags: u32, + + /// Offset of main counter relative to qemu clock. + hpet_offset: BqlCell, + hpet_offset_saved: bool, + + irqs: [InterruptSource; HPET_NUM_IRQ_ROUTES], + rtc_irq_level: BqlCell, + pit_enabled: InterruptSource, + + /// Interrupt Routing Capability. + /// This field indicates to which interrupts in the I/O (x) APIC + /// the timers' interrupt can be routed, and is encoded in the + /// bits 32:64 of timer N's config register: + #[doc(alias = "intcap")] + int_route_cap: u32, + + /// HPET timer array managed by this timer block. + #[doc(alias = "timer")] + timers: [BqlRefCell; HPET_MAX_TIMERS], + num_timers: BqlCell, + + /// Instance id (HPET timer block ID). + hpet_id: BqlCell, +} + +impl HPETState { + fn has_msi_flag(&self) -> bool { + self.flags & 1 << HPET_FLAG_MSI_SUPPORT_SHIFT != 0 + } + + fn is_legacy_mode(&self) -> bool { + self.config.get() & 1 << HPET_CFG_LEG_RT_SHIFT != 0 + } + + fn is_hpet_enabled(&self) -> bool { + self.config.get() & 1 << HPET_CFG_ENABLE_SHIFT != 0 + } + + fn is_timer_int_active(&self, index: usize) -> bool { + self.int_status.get() & 1 << index != 0 + } + + fn get_ticks(&self) -> u64 { + ns_to_ticks(CLOCK_VIRTUAL.get_ns() + self.hpet_offset.get()) + } + + fn get_ns(&self, tick: u64) -> u64 { + ticks_to_ns(tick) - self.hpet_offset.get() + } + + fn handle_legacy_irq(&self, irq: u32, level: u32) { + if irq == HPET_LEGACY_PIT_INT { + if !self.is_legacy_mode() { + self.irqs[0].set(level != 0); + } + } else { + self.rtc_irq_level.set(level); + if !self.is_legacy_mode() { + self.irqs[RTC_ISA_IRQ].set(level != 0); + } + } + } + + fn init_timer(&self) { + let raw_ptr: *mut HPETState = self as *const HPETState as *mut HPETState; + + for (index, timer) in self.timers.iter().enumerate() { + timer + .borrow_mut() + .init(index, raw_ptr) + .init_timer_with_state(); + } + } + + fn update_int_status(&self, index: u32, level: bool) { + self.int_status + .set(self.int_status.get().deposit(index, 1, level as u64)); + } + + /// General Configuration Register + fn set_cfg_reg(&self, shift: u32, len: u32, val: u64) { + let old_val = self.config.get(); + let mut new_val = old_val.deposit(shift, len, val); + + new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK); + self.config.set(new_val); + + if activating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { + // Enable main counter and interrupt generation. + self.hpet_offset + .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns()); + + for timer in self.timers.iter().take(self.num_timers.get()) { + let mut t = timer.borrow_mut(); + + if t.is_int_enabled() && t.is_int_active() { + t.update_irq(true); + } + t.set_timer(); + } + } else if deactivating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { + // Halt main counter and disable interrupt generation. + self.counter.set(self.get_ticks()); + + for timer in self.timers.iter().take(self.num_timers.get()) { + timer.borrow_mut().del_timer(); + } + } + + // i8254 and RTC output pins are disabled when HPET is in legacy mode + if activating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { + self.pit_enabled.set(false); + self.irqs[0].lower(); + self.irqs[RTC_ISA_IRQ].lower(); + } else if deactivating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { + // TODO: Add irq binding: qemu_irq_lower(s->irqs[0]) + self.irqs[0].lower(); + self.pit_enabled.set(true); + self.irqs[RTC_ISA_IRQ].set(self.rtc_irq_level.get() != 0); + } + } + + /// General Interrupt Status Register: Read/Write Clear + fn set_int_status_reg(&self, shift: u32, _len: u32, val: u64) { + let new_val = val << shift; + let cleared = new_val & self.int_status.get(); + + for (index, timer) in self.timers.iter().take(self.num_timers.get()).enumerate() { + if cleared & 1 << index != 0 { + timer.borrow_mut().update_irq(false); + } + } + } + + /// Main Counter Value Register + fn set_counter_reg(&self, shift: u32, len: u32, val: u64) { + if self.is_hpet_enabled() { + // TODO: Add trace point - + // trace_hpet_ram_write_counter_write_while_enabled() + // + // HPET spec says that writes to this register should only be + // done while the counter is halted. So this is an undefined + // behavior. There's no need to forbid it, but when HPET is + // enabled, the changed counter value will not affect the + // tick count (i.e., the previously calculated offset will + // not be changed as well). + } + self.counter + .set(self.counter.get().deposit(shift, len, val)); + } +} diff --git a/rust/hw/timer/hpet/src/lib.rs b/rust/hw/timer/hpet/src/lib.rs index c2b9c64d0bfe..027f7f83349a 100644 --- a/rust/hw/timer/hpet/src/lib.rs +++ b/rust/hw/timer/hpet/src/lib.rs @@ -11,3 +11,4 @@ #![deny(unsafe_op_in_unsafe_fn)] pub mod fw_cfg; +pub mod hpet; diff --git a/rust/wrapper.h b/rust/wrapper.h index a35bfbd1760d..d927ad6799da 100644 --- a/rust/wrapper.h +++ b/rust/wrapper.h @@ -64,3 +64,4 @@ typedef enum memory_order { #include "chardev/char-serial.h" #include "exec/memattrs.h" #include "qemu/timer.h" +#include "exec/address-spaces.h" From patchwork Sat Jan 25 12:51:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950339 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 EB68FC0218F for ; Sat, 25 Jan 2025 12:35:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLL-0008L9-WF; Sat, 25 Jan 2025 07:32:56 -0500 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 1tbfLJ-0008KN-Tq; Sat, 25 Jan 2025 07:32:53 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfLH-0005VT-Ik; Sat, 25 Jan 2025 07:32:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808371; x=1769344371; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eFUwjFzTVKRhcXepiDbF+oaPA8AdihqKAnBWplXvQ+w=; b=McCltVUfXb4rwccz74FyqoMw8jVwoM/d5VLdZ/RHMAlCzO8RyUgt1y+8 kA6rALbYWUs03CpYvNc0+gr27IWk/G/ZlFUL8hPTmwQaXWxuxaPUzGPuk rjRLOsdM0Dt6aAxJ9XTed4ySOYtN/TKNJ9D/8DcFIYda0j7COkllY8vhk hbr2btg5UAz6wZyC18dzbwx+6xdq70Zl0wh83QfhhGaKBBdTh+fWqdCAI GvuN1ANiv0Ulwd5rkwkoBUlPyeTBTycIM7IN0+FBXZCIu6X1H2KHTRiRL Nvb1V6Xd1exogws02u7kHnUyqzVD1z2XX5fU/NCXPtxcu0LJwS1/JmLDt A==; X-CSE-ConnectionGUID: 99fOIYOiTkKwKbwxv+Gl2w== X-CSE-MsgGUID: lqdt4CXxT7OPG8lRlgQlRQ== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434736" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434736" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:50 -0800 X-CSE-ConnectionGUID: pFpXTXrUQeO7CueiiuKVDw== X-CSE-MsgGUID: CRrONNDBSlObCBeu6wrQ2w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897778" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:47 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 09/10] rust/timer/hpet: add qom and qdev APIs support Date: Sat, 25 Jan 2025 20:51:36 +0800 Message-Id: <20250125125137.1223277-10-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Implement QOM & QAPI support for HPET device. Signed-off-by: Zhao Liu --- Changes since RFC: * Merge qdev.rs to hpet.rs. * Apply memory and Resettable bindings. * Consolidate inmutable &self and QOM casting. * Prefer timer iterator over loop. * Move init_mmio() and init_irq() to post_init(). --- rust/hw/timer/hpet/src/fw_cfg.rs | 2 - rust/hw/timer/hpet/src/hpet.rs | 283 ++++++++++++++++++++++++++++++- rust/hw/timer/hpet/src/lib.rs | 4 + 3 files changed, 279 insertions(+), 10 deletions(-) diff --git a/rust/hw/timer/hpet/src/fw_cfg.rs b/rust/hw/timer/hpet/src/fw_cfg.rs index 2f72bf854a66..5223629576a1 100644 --- a/rust/hw/timer/hpet/src/fw_cfg.rs +++ b/rust/hw/timer/hpet/src/fw_cfg.rs @@ -2,8 +2,6 @@ // Author(s): Zhao Liu // SPDX-License-Identifier: GPL-2.0-or-later -#![allow(dead_code)] - use qemu_api::{cell::bql_locked, impl_zeroable, zeroable::Zeroable}; // Each HPETState represents a Event Timer Block. The v1 spec supports diff --git a/rust/hw/timer/hpet/src/hpet.rs b/rust/hw/timer/hpet/src/hpet.rs index 0884a2ac73c4..7a717dbcfdd0 100644 --- a/rust/hw/timer/hpet/src/hpet.rs +++ b/rust/hw/timer/hpet/src/hpet.rs @@ -2,21 +2,30 @@ // Author(s): Zhao Liu // SPDX-License-Identifier: GPL-2.0-or-later -#![allow(dead_code)] - -use core::ptr::{null_mut, NonNull}; +use core::ptr::{addr_of_mut, null_mut, NonNull}; +use std::{ffi::CStr, slice::from_ref}; use qemu_api::{ - bindings::{address_space_memory, address_space_stl_le, MemoryRegion, SCALE_NS}, + bindings::{ + address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_prop_bool, + qdev_prop_uint32, qdev_prop_uint8, SCALE_NS, + }, + c_str, cell::{BqlCell, BqlRefCell}, irq::InterruptSource, - memory::MEMTXATTRS_UNSPECIFIED, + memory::{ + hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder, MEMTXATTRS_UNSPECIFIED, + }, prelude::*, - qom::ParentField, - sysbus::SysBusDevice, + qdev::{DeviceImpl, DeviceMethods, DeviceState, Property, ResetType, ResettablePhasesImpl}, + qom::{ClassInitImpl, ObjectImpl, ObjectType, ParentField}, + qom_isa, + sysbus::{SysBusDevice, SysBusDeviceClass}, timer::{QEMUTimer, CLOCK_VIRTUAL}, }; +use crate::fw_cfg::HPETFwConfig; + // Register space for each timer block. (HPET_BASE isn't defined here.) const HPET_REG_SPACE_LEN: u64 = 0x400; // 1024 bytes @@ -451,13 +460,43 @@ fn callback(&mut self) { } self.update_irq(true); } + + fn read(&mut self, addr: hwaddr, _size: u32) -> u64 { + let shift: u64 = (addr & 4) * 8; + + match addr { + HPET_TN_CFG_REG => self.config >> shift, // including interrupt capabilities + HPET_TN_CMP_REG => self.cmp >> shift, // comparator register + HPET_TN_FSB_ROUTE_REG => self.fsb >> shift, + _ => { + // TODO: Add trace point - trace_hpet_ram_read_invalid() + // Reserved. + 0 + } + } + } + + fn write(&mut self, addr: hwaddr, value: u64, size: u32) { + let shift = ((addr & 4) * 8) as u32; + let len = std::cmp::min(size * 8, 64 - shift); + + match addr { + HPET_TN_CFG_REG => self.set_tn_cfg_reg(shift, len, value), + HPET_TN_CMP_REG => self.set_tn_cmp_reg(shift, len, value), + HPET_TN_FSB_ROUTE_REG => self.set_tn_fsb_route_reg(shift, len, value), + _ => { + // TODO: Add trace point - trace_hpet_ram_write_invalid() + // Reserved. + } + } + } } /// HPET Event Timer Block Abstraction /// Note: Wrap all items that may be changed in the callback called by C /// into the BqlCell/BqlRefCell. #[repr(C)] -#[derive(qemu_api_macros::offsets)] +#[derive(qemu_api_macros::Object, qemu_api_macros::offsets)] pub struct HPETState { parent_obj: ParentField, iomem: MemoryRegion, @@ -630,4 +669,232 @@ fn set_counter_reg(&self, shift: u32, len: u32, val: u64) { self.counter .set(self.counter.get().deposit(shift, len, val)); } + + unsafe fn init(&mut self) { + static HPET_RAM_OPS: MemoryRegionOps = + MemoryRegionOpsBuilder::::new() + .read(&HPETState::read) + .write(&HPETState::write) + .native_endian() + .valid_sizes(4, 8) + .impl_sizes(4, 8) + .build(); + + // SAFETY: + // self and self.iomem are guaranteed to be valid at this point since callers + // must make sure the `self` reference is valid. + MemoryRegion::init_io( + unsafe { &mut *addr_of_mut!(self.iomem) }, + addr_of_mut!(*self), + &HPET_RAM_OPS, + "hpet", + HPET_REG_SPACE_LEN, + ); + } + + fn post_init(&self) { + self.init_mmio(&self.iomem); + for irq in self.irqs.iter() { + self.init_irq(irq); + } + } + + fn realize(&self) { + if self.int_route_cap == 0 { + // TODO: Add error binding: warn_report() + println!("Hpet's hpet-intcap property not initialized"); + } + + self.hpet_id.set(HPETFwConfig::assign_hpet_id()); + + if self.num_timers.get() < HPET_MIN_TIMERS { + self.num_timers.set(HPET_MIN_TIMERS); + } else if self.num_timers.get() > HPET_MAX_TIMERS { + self.num_timers.set(HPET_MAX_TIMERS); + } + + self.init_timer(); + // 64-bit General Capabilities and ID Register; LegacyReplacementRoute. + self.capability.set( + HPET_CAP_REV_ID_VALUE << HPET_CAP_REV_ID_SHIFT | + 1 << HPET_CAP_COUNT_SIZE_CAP_SHIFT | + 1 << HPET_CAP_LEG_RT_CAP_SHIFT | + HPET_CAP_VENDER_ID_VALUE << HPET_CAP_VENDER_ID_SHIFT | + ((self.num_timers.get() - 1) as u64) << HPET_CAP_NUM_TIM_SHIFT | // indicate the last timer + (HPET_CLK_PERIOD * FS_PER_NS) << HPET_CAP_CNT_CLK_PERIOD_SHIFT, // 10 ns + ); + + self.init_gpio_in(2, HPETState::handle_legacy_irq); + self.init_gpio_out(from_ref(&self.pit_enabled)); + } + + fn reset_hold(&self, _type: ResetType) { + let sbd = self.upcast::(); + + for timer in self.timers.iter().take(self.num_timers.get()) { + timer.borrow_mut().reset(); + } + + self.counter.set(0); + self.config.set(0); + self.pit_enabled.set(true); + self.hpet_offset.set(0); + + HPETFwConfig::update_hpet_cfg( + self.hpet_id.get(), + Some(self.capability.get() as u32), + Some((*sbd).mmio[0].addr), + ); + + // to document that the RTC lowers its output on reset as well + self.rtc_irq_level.set(0); + } + + fn timer_and_addr(&self, addr: hwaddr) -> Option<(&BqlRefCell, hwaddr)> { + let timer_id: usize = ((addr - 0x100) / 0x20) as usize; + + // TODO: Add trace point - trace_hpet_ram_[read|write]_timer_id(timer_id) + if timer_id > self.num_timers.get() { + // TODO: Add trace point - trace_hpet_timer_id_out_of_range(timer_id) + None + } else { + Some((&self.timers[timer_id], addr & 0x18)) + } + } + + fn read(&self, addr: hwaddr, size: u32) -> u64 { + let shift: u64 = (addr & 4) * 8; + + // address range of all TN regs + // TODO: Add trace point - trace_hpet_ram_read(addr) + if (0x100..=0x3ff).contains(&addr) { + match self.timer_and_addr(addr) { + None => 0, // Reserved, + Some((timer, addr)) => timer.borrow_mut().read(addr, size), + } + } else { + match addr & !4 { + HPET_CAP_REG => self.capability.get() >> shift, /* including HPET_PERIOD 0x004 */ + // (CNT_CLK_PERIOD field) + HPET_CFG_REG => self.config.get() >> shift, + HPET_COUNTER_REG => { + let cur_tick: u64 = if self.is_hpet_enabled() { + self.get_ticks() + } else { + self.counter.get() + }; + + // TODO: Add trace point - trace_hpet_ram_read_reading_counter(addr & 4, + // cur_tick) + cur_tick >> shift + } + HPET_INT_STATUS_REG => self.int_status.get() >> shift, + _ => { + // TODO: Add trace point- trace_hpet_ram_read_invalid() + // Reserved. + 0 + } + } + } + } + + fn write(&self, addr: hwaddr, value: u64, size: u32) { + let shift = ((addr & 4) * 8) as u32; + let len = std::cmp::min(size * 8, 64 - shift); + + // TODO: Add trace point - trace_hpet_ram_write(addr, value) + if (0x100..=0x3ff).contains(&addr) { + match self.timer_and_addr(addr) { + None => return, // Reserved. + Some((timer, addr)) => timer.borrow_mut().write(addr, value, size), + } + } else { + match addr & !0x4 { + HPET_CAP_REG => {} // General Capabilities and ID Register: Read Only + HPET_CFG_REG => self.set_cfg_reg(shift, len, value), + HPET_INT_STATUS_REG => self.set_int_status_reg(shift, len, value), + HPET_COUNTER_REG => self.set_counter_reg(shift, len, value), + _ => { + // TODO: Add trace point - trace_hpet_ram_write_invalid() + // Reserved. + } + } + } + } +} + +qom_isa!(HPETState: SysBusDevice, DeviceState, Object); + +// TODO: add OBJECT_DECLARE_SIMPLE_TYPE. +#[repr(C)] +pub struct HPETClass { + parent_class: ::Class, +} + +unsafe impl ObjectType for HPETState { + type Class = HPETClass; + const TYPE_NAME: &'static CStr = crate::TYPE_HPET; +} + +impl ClassInitImpl for HPETState { + fn class_init(klass: &mut HPETClass) { + >::class_init(&mut klass.parent_class); + } +} + +impl ObjectImpl for HPETState { + type ParentType = SysBusDevice; + + const INSTANCE_INIT: Option = Some(Self::init); + const INSTANCE_POST_INIT: Option = Some(Self::post_init); +} + +// TODO: Make these properties user-configurable! +qemu_api::declare_properties! { + HPET_PROPERTIES, + qemu_api::define_property!( + c_str!("timers"), + HPETState, + num_timers, + unsafe { &qdev_prop_uint8 }, + u8, + default = HPET_MIN_TIMERS + ), + qemu_api::define_property!( + c_str!("msi"), + HPETState, + flags, + unsafe { &qdev_prop_bit }, + u32, + bit = HPET_FLAG_MSI_SUPPORT_SHIFT as u8, + default = false, + ), + qemu_api::define_property!( + c_str!("hpet-intcap"), + HPETState, + int_route_cap, + unsafe { &qdev_prop_uint32 }, + u32, + default = 0 + ), + qemu_api::define_property!( + c_str!("hpet-offset-saved"), + HPETState, + hpet_offset_saved, + unsafe { &qdev_prop_bool }, + bool, + default = true + ), +} + +impl DeviceImpl for HPETState { + fn properties() -> &'static [Property] { + &HPET_PROPERTIES + } + + const REALIZE: Option = Some(Self::realize); +} + +impl ResettablePhasesImpl for HPETState { + const HOLD: Option = Some(Self::reset_hold); } diff --git a/rust/hw/timer/hpet/src/lib.rs b/rust/hw/timer/hpet/src/lib.rs index 027f7f83349a..25251112a86d 100644 --- a/rust/hw/timer/hpet/src/lib.rs +++ b/rust/hw/timer/hpet/src/lib.rs @@ -10,5 +10,9 @@ #![deny(unsafe_op_in_unsafe_fn)] +use qemu_api::c_str; + pub mod fw_cfg; pub mod hpet; + +pub const TYPE_HPET: &::std::ffi::CStr = c_str!("hpet"); From patchwork Sat Jan 25 12:51:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13950336 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 93E32C0218C for ; Sat, 25 Jan 2025 12:34:40 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tbfLN-0008NS-UE; Sat, 25 Jan 2025 07:32:57 -0500 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 1tbfLL-0008LB-RF; Sat, 25 Jan 2025 07:32:55 -0500 Received: from mgamail.intel.com ([198.175.65.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tbfLK-0005Un-72; Sat, 25 Jan 2025 07:32:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1737808374; x=1769344374; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ngo80kE7rdcQaPMVlhyywcWW9dcxu3fWW0S2k8Zk7ic=; b=dXq/BK82zL3OWUJvdydzxZMJceyg65Ox4Iq3xo9wXiXS6u5yKUUybCnj YkZ6AUwSl3N/npiTogLH467RoHonuVpG/RoWYImzEvh+TUmazA2UuvFZJ pdxwyTvnrGzjG+X3WOhsArd+BstHotANn1lw1oX2YVD5aHWLF4FtxJ0yz iOYNsdxHQMb/pJlWh5bLY0yd6DoMgacwkTp0NumUnlJ3R8EjyV1DF3HEe aVOg8adMKKKEem86h0Sd34HzYDxzgng9BWnUIQOD97VVopttWV7xZ4bvr XtfEFJquN6C1PTaVqaMD0xmMeOUVpm6NYKZAHAFeSWWDbhKBBJXQtz+xk Q==; X-CSE-ConnectionGUID: vXFvvfwqQ5mnLHuqdpF1lg== X-CSE-MsgGUID: SWOjgJBpQW2DMxrUTJPmkA== X-IronPort-AV: E=McAfee;i="6700,10204,11314"; a="38434740" X-IronPort-AV: E=Sophos;i="6.12,310,1728975600"; d="scan'208";a="38434740" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2025 04:32:53 -0800 X-CSE-ConnectionGUID: crK7dXFeRk68l3QCaBbnYg== X-CSE-MsgGUID: wqSB+Gn2Tdy+Q9CUgdH6pA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,234,1732608000"; d="scan'208";a="107897789" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa007.fm.intel.com with ESMTP; 25 Jan 2025 04:32:50 -0800 From: Zhao Liu To: Paolo Bonzini , Manos Pitsidianakis , Junjie Mao , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , =?utf-8?q?Daniel_P_=2E_Berrang?= =?utf-8?q?=C3=A9?= Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Zhao Liu Subject: [PATCH 10/10] i386: enable rust hpet for pc when rust is enabled Date: Sat, 25 Jan 2025 20:51:37 +0800 Message-Id: <20250125125137.1223277-11-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250125125137.1223277-1-zhao1.liu@intel.com> References: <20250125125137.1223277-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=198.175.65.18; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -73 X-Spam_score: -7.4 X-Spam_bar: ------- X-Spam_report: (-7.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.996, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add HPET configuration in PC's Kconfig options, and select HPET device (Rust version) if Rust is supported. Signed-off-by: Zhao Liu --- Changes since RFC: * Fix rust hpet not being optional. * Fix bios-tables-test missing rust hpet. --- configs/devices/i386-softmmu/default.mak | 1 + hw/i386/fw_cfg.c | 2 +- hw/i386/pc.c | 2 +- hw/timer/Kconfig | 6 +++++- rust/hw/Kconfig | 1 + rust/hw/timer/Kconfig | 2 ++ tests/qtest/meson.build | 3 ++- 7 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 rust/hw/timer/Kconfig diff --git a/configs/devices/i386-softmmu/default.mak b/configs/devices/i386-softmmu/default.mak index 4faf2f0315e2..9ef343cace06 100644 --- a/configs/devices/i386-softmmu/default.mak +++ b/configs/devices/i386-softmmu/default.mak @@ -6,6 +6,7 @@ #CONFIG_APPLESMC=n #CONFIG_FDC=n #CONFIG_HPET=n +#CONFIG_X_HPET_RUST=n #CONFIG_HYPERV=n #CONFIG_ISA_DEBUG=n #CONFIG_ISA_IPMI_BT=n diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index 546de63123e6..a7d69a49edbf 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -147,7 +147,7 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, #endif fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1); -#ifdef CONFIG_HPET +#if defined(CONFIG_HPET) || defined(CONFIG_X_HPET_RUST) PCMachineState *pcms = (PCMachineState *)object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE); if (pcms && pcms->hpet_enabled) { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b46975c8a4db..04554817e021 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1701,7 +1701,7 @@ static void pc_machine_initfn(Object *obj) pcms->sata_enabled = true; pcms->i8042_enabled = true; pcms->max_fw_size = 8 * MiB; -#ifdef CONFIG_HPET +#if defined(CONFIG_HPET) || defined(CONFIG_X_HPET_RUST) pcms->hpet_enabled = true; #endif pcms->fd_bootchk = true; diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index c96fd5d97ae8..c051597180f4 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -11,7 +11,11 @@ config A9_GTIMER config HPET bool - default y if PC + default y if PC && !HAVE_RUST + +config X_HPET_RUST + bool + default y if PC && HAVE_RUST config I8254 bool diff --git a/rust/hw/Kconfig b/rust/hw/Kconfig index 4d934f30afe1..36f92ec02874 100644 --- a/rust/hw/Kconfig +++ b/rust/hw/Kconfig @@ -1,2 +1,3 @@ # devices Kconfig source char/Kconfig +source timer/Kconfig diff --git a/rust/hw/timer/Kconfig b/rust/hw/timer/Kconfig new file mode 100644 index 000000000000..afd980335037 --- /dev/null +++ b/rust/hw/timer/Kconfig @@ -0,0 +1,2 @@ +config X_HPET_RUST + bool diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 94b28e5a5347..0268c657cc8f 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -102,7 +102,8 @@ qtests_i386 = \ config_all_devices.has_key('CONFIG_VIRTIO_PCI') and \ slirp.found() ? ['virtio-net-failover'] : []) + \ (unpack_edk2_blobs and \ - config_all_devices.has_key('CONFIG_HPET') and \ + (config_all_devices.has_key('CONFIG_HPET') or \ + config_all_devices.has_key('CONFIG_X_HPET_RUST')) and \ config_all_devices.has_key('CONFIG_PARALLEL') ? ['bios-tables-test'] : []) + \ qtests_pci + \ qtests_cxl + \