get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2080606/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2080606,
    "url": "http://patchwork.ozlabs.org/api/patches/2080606/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20250503075858.277375-7-pbonzini@redhat.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20250503075858.277375-7-pbonzini@redhat.com>",
    "list_archive_url": null,
    "date": "2025-05-03T07:58:51",
    "name": "[PULL,06/13] rust/hpet: Support migration",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "35c3957fd470148f58c1e483adb5929899cb16a1",
    "submitter": {
        "id": 2701,
        "url": "http://patchwork.ozlabs.org/api/people/2701/?format=api",
        "name": "Paolo Bonzini",
        "email": "pbonzini@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20250503075858.277375-7-pbonzini@redhat.com/mbox/",
    "series": [
        {
            "id": 455199,
            "url": "http://patchwork.ozlabs.org/api/series/455199/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=455199",
            "date": "2025-05-03T07:58:51",
            "name": "[PULL,01/13] rust/vmstate: Add support for field_exists checks",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/455199/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2080606/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2080606/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=gbG+iVvr;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4ZqKvD2cBVz1yX9\n\tfor <incoming@patchwork.ozlabs.org>; Sat,  3 May 2025 17:59:34 +1000 (AEST)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1uB7mU-00086Y-Rk; Sat, 03 May 2025 03:59:31 -0400",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <pbonzini@redhat.com>)\n id 1uB7mO-00085g-Ng\n for qemu-devel@nongnu.org; Sat, 03 May 2025 03:59:26 -0400",
            "from us-smtp-delivery-124.mimecast.com ([170.10.133.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <pbonzini@redhat.com>)\n id 1uB7mM-0006en-BK\n for qemu-devel@nongnu.org; Sat, 03 May 2025 03:59:24 -0400",
            "from mail-wm1-f70.google.com (mail-wm1-f70.google.com\n [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-620-UwYcyAVCOHW4H3cInofZ5g-1; Sat, 03 May 2025 03:59:20 -0400",
            "by mail-wm1-f70.google.com with SMTP id\n 5b1f17b1804b1-43efa869b19so16354015e9.2\n for <qemu-devel@nongnu.org>; Sat, 03 May 2025 00:59:19 -0700 (PDT)",
            "from [192.168.10.48] ([151.95.54.106])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-441b89cc441sm67909535e9.3.2025.05.03.00.59.15\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sat, 03 May 2025 00:59:15 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1746259161;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=toxRje+xxVT+nxJgLRSzPIeanmmnkchIayeKIhpjgVE=;\n b=gbG+iVvrjPH2DbZcqIzSv4R96BCmAaE4xMOwsMDczk5KAq0W2nqvIrSGS1R0pOH3rnIHw7\n /cADgOYVjZDoEsQWNcF0XT9X6RA7EOniYocHg1kVZvqYmxGyuBbcAMtRM/r1pdJrV5sUAn\n rEGhPvWK0aNDA2OrPbv7jpTNE4X7kms=",
        "X-MC-Unique": "UwYcyAVCOHW4H3cInofZ5g-1",
        "X-Mimecast-MFC-AGG-ID": "UwYcyAVCOHW4H3cInofZ5g_1746259159",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1746259158; x=1746863958;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=toxRje+xxVT+nxJgLRSzPIeanmmnkchIayeKIhpjgVE=;\n b=Ni+5x6lnq1TFNuJc3nl8oU2izVf0VC10R99ucDZnryEd1vt/dcmLfgqAQu+cOVLsZL\n SrQNRoVCLzRpkY8RodRiAADXxptlIShUhejdmhFAood53UV2pdelYFyMLlohWkubCjay\n aZKYiMlFIfBL42doh3uLLOBYfFR9+5cE7wZoUFo4q2mYXGDsIQiEOdZsTtSkww6nG73Z\n MgjiGTnYlDmsrUg0uxwIoRVH3ZuqZk3Z2DirNdaFleFAi9TN5S3cUy5KVjqNRTvBm1io\n 0hjC2JbPr4QQiPawckg7cTMex/N9yQy0V9pdvX+KnH7mGSIZEHoLnup8HhBkks+bQS4Q\n DwTg==",
        "X-Gm-Message-State": "AOJu0Yw3REZ1owP1oWMNC5Db8AiH5Xn6tfHCLjb//BPzJTxYfUoBfqyI\n SGIj+sboGK9vFrwzphNef6Q8zGVX/BFAmjdeJEThtftfoKarx3DY211jpw0YOerAq3rsZ+VEyM/\n o3Ks/ObDz8dTRjrUnRF6rKvvLtS6RZ6Jfk3ojGDmru2kIuDbjUh80E2F1o8KT/UjAv9lKge5JIt\n h4IQ9hfqQO8x9pfeEhjDpJyutw+n2L0LU93qlw",
        "X-Gm-Gg": "ASbGnctjPl0RaoOz0MW/r/RM3O3Q8FtNugptlz2iY82aWPugzAO6xA2lRfqnmzKZZri\n L7p3xSAt9cj2pa9048LH9vzcgh08iCUSvLWvICtEsCMsYMIiG8fRpkhKdodCxVmLDDc3/xecpUm\n MxNvTENOXhk6Qs53wFE9iLPHcWluLVeUo9BoXUqIuSECJE82fFVanU+pvW9DisVpa7IAD/4/g1Z\n rlEgixpXxcvQxW1QU1+Kbo6vdGYd3kD2ipFaCJOuNQRWeIq6/kzg84PLJ60Szux2vxzZj4PPECl\n WJjs6SJDTYsXKJs=",
        "X-Received": [
            "by 2002:a05:600c:45d1:b0:43c:f3e4:d6f7 with SMTP id\n 5b1f17b1804b1-441c4938d58mr1919835e9.31.1746259157812;\n Sat, 03 May 2025 00:59:17 -0700 (PDT)",
            "by 2002:a05:600c:45d1:b0:43c:f3e4:d6f7 with SMTP id\n 5b1f17b1804b1-441c4938d58mr1919615e9.31.1746259157328;\n Sat, 03 May 2025 00:59:17 -0700 (PDT)"
        ],
        "X-Google-Smtp-Source": "\n AGHT+IHLP8J9soxClfcOJZJGIONXqNi6lgTLOv5Z5EHIbB1ofzavcdoAtrpbUiIS48do9iA6JnwnRg==",
        "From": "Paolo Bonzini <pbonzini@redhat.com>",
        "To": "qemu-devel@nongnu.org",
        "Cc": "Zhao Liu <zhao1.liu@intel.com>",
        "Subject": "[PULL 06/13] rust/hpet: Support migration",
        "Date": "Sat,  3 May 2025 09:58:51 +0200",
        "Message-ID": "<20250503075858.277375-7-pbonzini@redhat.com>",
        "X-Mailer": "git-send-email 2.49.0",
        "In-Reply-To": "<20250503075858.277375-1-pbonzini@redhat.com>",
        "References": "<20250503075858.277375-1-pbonzini@redhat.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Received-SPF": "pass client-ip=170.10.133.124;\n envelope-from=pbonzini@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com",
        "X-Spam_score_int": "-26",
        "X-Spam_score": "-2.7",
        "X-Spam_bar": "--",
        "X-Spam_report": "(-2.7 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.644,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,\n SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no",
        "X-Spam_action": "no action",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "<qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"
    },
    "content": "From: Zhao Liu <zhao1.liu@intel.com>\n\nBased on commit 1433e38cc8 (\"hpet: do not overwrite properties on\npost_load\"), add the basic migration support to Rust HPET.\n\nThe current migration implementation introduces multiple unsafe\ncallbacks. Before the vmstate builder, one possible cleanup approach is\nto wrap callbacks in the vmstate binding using a method similar to the\nvmstate_exist_fn macro.\n\nHowever, this approach would also create a lot of repetitive code (since\nvmstate has so many callbacks: pre_load, post_load, pre_save, post_save,\nneeded and dev_unplug_pending). Although it would be cleaner, it would\nsomewhat deviate from the path of the vmstate builder.\n\nTherefore, firstly focus on completing the functionality of HPET, and\nthose current unsafe callbacks can at least clearly indicate the needed\nfunctionality of vmstate. The next step is to consider refactoring\nvmstate to move towards the vmstate builder direction.\n\nAdditionally, update rust.rst about Rust HPET can support migration.\n\nSigned-off-by: Zhao Liu <zhao1.liu@intel.com>\nLink: https://lore.kernel.org/r/20250414144943.1112885-9-zhao1.liu@intel.com\nSigned-off-by: Paolo Bonzini <pbonzini@redhat.com>\n---\n docs/devel/rust.rst            |   3 +-\n rust/hw/timer/hpet/src/hpet.rs | 146 ++++++++++++++++++++++++++++++++-\n 2 files changed, 146 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/docs/devel/rust.rst b/docs/devel/rust.rst\nindex 88bdec1eb28..3cc2841d4d1 100644\n--- a/docs/devel/rust.rst\n+++ b/docs/devel/rust.rst\n@@ -153,8 +153,7 @@ QEMU includes four crates:\n \n .. [#issues] The ``pl011`` crate is synchronized with ``hw/char/pl011.c``\n    as of commit 02b1f7f61928.  The ``hpet`` crate is synchronized as of\n-   commit f32352ff9e.  Both are lacking tracing functionality; ``hpet``\n-   is also lacking support for migration.\n+   commit 1433e38cc8.  Both are lacking tracing functionality.\n \n This section explains how to work with them.\n \ndiff --git a/rust/hw/timer/hpet/src/hpet.rs b/rust/hw/timer/hpet/src/hpet.rs\nindex cbd2ed4f6bf..12de2ba59a1 100644\n--- a/rust/hw/timer/hpet/src/hpet.rs\n+++ b/rust/hw/timer/hpet/src/hpet.rs\n@@ -4,6 +4,7 @@\n \n use std::{\n     ffi::CStr,\n+    os::raw::{c_int, c_void},\n     pin::Pin,\n     ptr::{addr_of_mut, null_mut, NonNull},\n     slice::from_ref,\n@@ -25,7 +26,10 @@\n     qom::{ObjectImpl, ObjectType, ParentField},\n     qom_isa,\n     sysbus::{SysBusDevice, SysBusDeviceImpl},\n-    timer::{Timer, CLOCK_VIRTUAL},\n+    timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND},\n+    vmstate::VMStateDescription,\n+    vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_validate,\n+    zeroable::Zeroable,\n };\n \n use crate::fw_cfg::HPETFwConfig;\n@@ -561,6 +565,7 @@ pub struct HPETState {\n     #[doc(alias = \"timer\")]\n     timers: [BqlRefCell<HPETTimer>; HPET_MAX_TIMERS as usize],\n     num_timers: BqlCell<u8>,\n+    num_timers_save: BqlCell<u8>,\n \n     /// Instance id (HPET timer block ID).\n     hpet_id: BqlCell<usize>,\n@@ -839,6 +844,49 @@ fn write(&self, addr: hwaddr, value: u64, size: u32) {\n             }\n         }\n     }\n+\n+    fn pre_save(&self) -> i32 {\n+        if self.is_hpet_enabled() {\n+            self.counter.set(self.get_ticks());\n+        }\n+\n+        /*\n+         * The number of timers must match on source and destination, but it was\n+         * also added to the migration stream.  Check that it matches the value\n+         * that was configured.\n+         */\n+        self.num_timers_save.set(self.num_timers.get());\n+        0\n+    }\n+\n+    fn post_load(&self, _version_id: u8) -> i32 {\n+        for timer in self.timers.iter().take(self.get_num_timers()) {\n+            let mut t = timer.borrow_mut();\n+\n+            t.cmp64 = t.calculate_cmp64(t.get_state().counter.get(), t.cmp);\n+            t.last = CLOCK_VIRTUAL.get_ns() - NANOSECONDS_PER_SECOND;\n+        }\n+\n+        // Recalculate the offset between the main counter and guest time\n+        if !self.hpet_offset_saved {\n+            self.hpet_offset\n+                .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns());\n+        }\n+\n+        0\n+    }\n+\n+    fn is_rtc_irq_level_needed(&self) -> bool {\n+        self.rtc_irq_level.get() != 0\n+    }\n+\n+    fn is_offset_needed(&self) -> bool {\n+        self.is_hpet_enabled() && self.hpet_offset_saved\n+    }\n+\n+    fn validate_num_timers(&self, _version_id: u8) -> bool {\n+        self.num_timers.get() == self.num_timers_save.get()\n+    }\n }\n \n qom_isa!(HPETState: SysBusDevice, DeviceState, Object);\n@@ -895,11 +943,107 @@ impl ObjectImpl for HPETState {\n     ),\n }\n \n+unsafe extern \"C\" fn hpet_rtc_irq_level_needed(opaque: *mut c_void) -> bool {\n+    // SAFETY:\n+    // the pointer is convertible to a reference\n+    let state: &HPETState = unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_ref() };\n+    state.is_rtc_irq_level_needed()\n+}\n+\n+unsafe extern \"C\" fn hpet_offset_needed(opaque: *mut c_void) -> bool {\n+    // SAFETY:\n+    // the pointer is convertible to a reference\n+    let state: &HPETState = unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_ref() };\n+    state.is_offset_needed()\n+}\n+\n+unsafe extern \"C\" fn hpet_pre_save(opaque: *mut c_void) -> c_int {\n+    // SAFETY:\n+    // the pointer is convertible to a reference\n+    let state: &mut HPETState =\n+        unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_mut() };\n+    state.pre_save() as c_int\n+}\n+\n+unsafe extern \"C\" fn hpet_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {\n+    // SAFETY:\n+    // the pointer is convertible to a reference\n+    let state: &mut HPETState =\n+        unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_mut() };\n+    let version: u8 = version_id.try_into().unwrap();\n+    state.post_load(version) as c_int\n+}\n+\n+static VMSTATE_HPET_RTC_IRQ_LEVEL: VMStateDescription = VMStateDescription {\n+    name: c_str!(\"hpet/rtc_irq_level\").as_ptr(),\n+    version_id: 1,\n+    minimum_version_id: 1,\n+    needed: Some(hpet_rtc_irq_level_needed),\n+    fields: vmstate_fields! {\n+        vmstate_of!(HPETState, rtc_irq_level),\n+    },\n+    ..Zeroable::ZERO\n+};\n+\n+static VMSTATE_HPET_OFFSET: VMStateDescription = VMStateDescription {\n+    name: c_str!(\"hpet/offset\").as_ptr(),\n+    version_id: 1,\n+    minimum_version_id: 1,\n+    needed: Some(hpet_offset_needed),\n+    fields: vmstate_fields! {\n+        vmstate_of!(HPETState, hpet_offset),\n+    },\n+    ..Zeroable::ZERO\n+};\n+\n+static VMSTATE_HPET_TIMER: VMStateDescription = VMStateDescription {\n+    name: c_str!(\"hpet_timer\").as_ptr(),\n+    version_id: 1,\n+    minimum_version_id: 1,\n+    fields: vmstate_fields! {\n+        vmstate_of!(HPETTimer, index),\n+        vmstate_of!(HPETTimer, config),\n+        vmstate_of!(HPETTimer, cmp),\n+        vmstate_of!(HPETTimer, fsb),\n+        vmstate_of!(HPETTimer, period),\n+        vmstate_of!(HPETTimer, wrap_flag),\n+        vmstate_of!(HPETTimer, qemu_timer),\n+    },\n+    ..Zeroable::ZERO\n+};\n+\n+const VALIDATE_TIMERS_NAME: &CStr = c_str!(\"num_timers must match\");\n+\n+static VMSTATE_HPET: VMStateDescription = VMStateDescription {\n+    name: c_str!(\"hpet\").as_ptr(),\n+    version_id: 2,\n+    minimum_version_id: 1,\n+    pre_save: Some(hpet_pre_save),\n+    post_load: Some(hpet_post_load),\n+    fields: vmstate_fields! {\n+        vmstate_of!(HPETState, config),\n+        vmstate_of!(HPETState, int_status),\n+        vmstate_of!(HPETState, counter),\n+        vmstate_of!(HPETState, num_timers_save).with_version_id(2),\n+        vmstate_validate!(HPETState, VALIDATE_TIMERS_NAME, HPETState::validate_num_timers),\n+        vmstate_struct!(HPETState, timers[0 .. num_timers], &VMSTATE_HPET_TIMER, BqlRefCell<HPETTimer>, HPETState::validate_num_timers).with_version_id(0),\n+    },\n+    subsections: vmstate_subsections! {\n+        VMSTATE_HPET_RTC_IRQ_LEVEL,\n+        VMSTATE_HPET_OFFSET,\n+    },\n+    ..Zeroable::ZERO\n+};\n+\n impl DeviceImpl for HPETState {\n     fn properties() -> &'static [Property] {\n         &HPET_PROPERTIES\n     }\n \n+    fn vmsd() -> Option<&'static VMStateDescription> {\n+        Some(&VMSTATE_HPET)\n+    }\n+\n     const REALIZE: Option<fn(&Self)> = Some(Self::realize);\n }\n \n",
    "prefixes": [
        "PULL",
        "06/13"
    ]
}