From: Corey Minyard <cminyard@mvista.com>
To: Ilya Chichkov <ilya.chichkov.dev@gmail.com>
Cc: "Cédric Le Goater" <clg@redhat.com>,
qemu-devel@nongnu.org,
"Pierrick Bouvier" <pierrick.bouvier@oss.qualcomm.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Daniel P . Berrangé" <berrange@redhat.com>,
"Eric Blake" <eblake@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Fabiano Rosas" <farosas@suse.de>,
"Laurent Vivier" <lvivier@redhat.com>
Subject: Re: [PATCH v5] hw/i2c: Add remote I2C master with host CUSE bridge
Date: Fri, 24 Jul 2026 10:15:11 -0500 [thread overview]
Message-ID: <amOBf20vEO1dteit@mail.minyard.net> (raw)
In-Reply-To: <CADgQP8yisWh1RBbxvahf9n46_phnjDxhQeCwxUEfx8+En0LNhA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 11669 bytes --]
On Fri, Jul 24, 2026 at 05:49:02PM +0300, Ilya Chichkov wrote:
> Hi Corey, Cédric,
>
> On Fri, 24 Jul 2026 08:30:58 -0500, Corey Minyard <cminyard@mvista.com> wrote:
> > I think what Cédric is saying here is that if you provided a generic
> > QMP interface that allowed these sorts of operations and wrote an
> > external program that used said interface to provide a fuse interface,
> > that would be better.
>
> I see your point about keeping the core emulator clean and minimizing
> dependencies.
>
> I am willing to pivot to this architectural direction. I can drop the CUSE
> backend from this patch series and instead implement the `i2c-transfer`
> QMP command, as Cédric originally suggested. I will handle the CUSE
> part externally.
>
> Before I send v6, are there any other concerns regarding the core FSM
> logic, or would replacing CUSE with a QMP backend be sufficient?
I didn't see anything, it looked clean and well written to me, but I am
not as much of a QEMU expert as others. I kind of happened into this as
I know a lot about IPMI and I2C.
-corey
>
> Best regards,
> Ilya
>
>
> пт, 24 июл. 2026 г. в 16:31, Corey Minyard <cminyard@mvista.com>:
> >
> > On Fri, Jul 24, 2026 at 11:19:17AM +0300, Ilya Chichkov wrote:
> > > Hi Cédric,
> > >
> > > On Wed, 22 Jul 2026 19:42:03 +0200, Cédric Le Goater <clg@redhat.com> wrote:
> > > > I think a lighter QMP-based approach would serve the same purpose,
> > > > maybe better, and fit in better in QEMU, without the dependency and
> > > > maintenance cost:
> > >
> > > As Corey and I discussed earlier in the thread, QMP doesn't cover the primary
> > > motivation for this patch: zero-code transparency for existing host software.
> > >
> > > An `i2c-transfer` QMP command would be a great addition for custom scripts,
> > > but the main goal here is to allow native Linux user-space binaries
> > > (like i2c-tools,
> > > lm-sensors) running on the host to talk to QEMU's I2C slaves unmodified, simply
> > > by opening /dev/i2c-N. Rewriting legacy test suites to speak QMP JSON over a
> > > socket is often not feasible.
> >
> > I think what Cédric is saying here is that if you provided a generic
> > QMP interface that allowed these sorts of operations and wrote an
> > external program that used said interface to provide a fuse interface,
> > that would be better. It has a number of advantages:
> >
> > * You add an interface to QEMU that others can easily use to test
> > devices.
> >
> > * You are not tied to QEMU when you want to extend the functions of
> > the fuse interface.
> >
> > * It's one less dependency in QEMU. QEMU has a *lot* of dependencies,
> > and the fewer the better.
> >
> > The only disadvantage I can think of is that it's one more piece of
> > software if you are setting this up.
> >
> > This is not a big piece of software, I agree, but from experience I
> > think you will be happier with this sort of design in the long run.
> > It puts you more in control of what you are doing.
> >
> > And, of course, it makes the QEMU maintainers happier :-).
> >
> > -corey
> >
> > >
> > > > The dependency cost seems high for the use case: libfuse3 + the cuse
> > > > kernel module pulled into the system emulator build. It's also ~3K
> > > > lines of new code, three QOM types, FUSE session management, etc.
> > >
> > > Regarding dependencies, `libfuse3` is actually not new to the project — it has
> > > been a supported QEMU dependency for a long time (already used by the block
> > > layer in `block/export/fuse.c`). Also, just to clarify the diff: the core
> > > implementation is roughly ~2K lines. The remaining ~900 lines are dedicated
> > > entirely to qtests and RST documentation.
> > >
> > > However, I agree about not polluting the core emulation build with
> > > Linux-specific
> > > headers and libfuse3. The maintenance cost must be minimized. To address this,
> > > I've refactored the architecture for v6 to ensure strict isolation:
> > >
> > > - All Linux and FUSE-specific headers are removed from public QEMU headers.
> > > The internal state structure is now opaque and hidden inside
> > > remote-i2c-cuse.c.
> > > - The CUSE backend is isolated behind its own
> > > CONFIG_REMOTE_I2C_BACKEND_CUSE in Kconfig and meson.build, strictly
> > > depending on LINUX and fuse3.
> > >
> > > On macOS, Windows, or minimalistic builds without libfuse, QEMU will build
> > > cleanly without pulling in this backend or any of its dependencies.
> > >
> > > Would making the CUSE transport a strictly optional, isolated Linux-only backend
> > > alleviate your concerns regarding the hardware emulation core?
> > >
> > > Best regards,
> > > Ilya
> > >
> > > ср, 22 июл. 2026 г. в 20:42, Cédric Le Goater <clg@redhat.com>:
> > > >
> > > > On 7/22/26 14:57, Ilya Chichkov wrote:
> > > > > Add a "remote-i2c-master" device that exposes a QEMU I2C bus to the
> > > > > host system through a FUSE/CUSE character device. This lets external
> > > > > host programs and standard i2c-tools interact with I2C slaves emulated
> > > > > inside QEMU as if they were real devices attached to the host.
> > > > >
> > > > > The implementation is split into three layers:
> > > > >
> > > > > - A non-blocking finite state machine that drives the QEMU I2C
> > > > > master. It is pumped by a QEMU Bottom Half and uses virtual timers
> > > > > to yield during long transfers and to model clock stretching for
> > > > > asynchronous slaves, so the main loop is never blocked. The FSM
> > > > > walks IDLE -> ADDR -> SEND/RECV -> WAIT_STRETCH -> END -> FINISHED
> > > > > and handles NACKs (ENXIO), lost arbitration (EBUSY, with optional
> > > > > back-off and retry), stretch timeouts, and manual abort/reset.
> > > > >
> > > > > - An abstract RemoteI2CBackend QOM base class that decouples the
> > > > > internal I2C hardware state machine (the frontend) from any
> > > > > host-specific transport, exposing on_tx_complete and on_tx_error
> > > > > virtual callbacks.
> > > > >
> > > > > - A concrete remote-i2c-backend-cuse backend implementing that
> > > > > transport over CUSE. It manages the FUSE session and integrates
> > > > > its file descriptors into QEMU's main AioContext event loop,
> > > > > translates Linux I2C_RDWR, I2C_SMBUS and I2C_SLAVE ioctls into
> > > > > generic byte streams for the FSM, and formats responses back into
> > > > > Linux I2C/SMBus structures for the FUSE driver. SMBus repeated
> > > > > start is supported for atomic write-then-read operations.
> > > > >
> > > > > Example usage:
> > > > >
> > > > > -device remote-i2c-master,i2cbus=i2c-bus.0,devname=i2c-33
> > > > > -object remote-i2c-backend-cuse,id=b0,devname=i2c-33
> > > > >
> > > > > This creates /dev/i2c-33 on the host, usable with i2c-tools:
> > > > >
> > > > > i2cdetect -y -l
> > > > > i2cget -y <bus_id> <addr> <reg>
> > > > >
> > > > > Acked-by: Markus Armbruster <armbru@redhat.com>
> > > > > Signed-off-by: Ilya Chichkov <ilya.chichkov.dev@gmail.com>
> > > > > ---
> > > > > v2:
> > > > > - docs/system/devices/remote-i2c-master.rst: Documented concurrent
> > > > > bus access details and the 'raise-arbitrage-lost' property.
> > > > > ---
> > > > > v3:
> > > > > - qapi/qom.json: Fix RemoteI2CBackendCuseProperties formatting and
> > > > > expand member documentation (devname, fuse-opts, debug).
> > > > > - tests/qtest: Add remote-i2c-cuse-test covering capabilities,
> > > > > functional smoke test, synchronous sensor read/write.
> > > > > ---
> > > > > v4:
> > > > > - qapi: reference the rst doc via :doc:
> > > > > - qapi: fuse-opts is now ['str'] instead of a space-separated string
> > > > > - qapi: drop redundant 'debug' property (pass -d via fuse-opts)
> > > > > ---
> > > > > v5:
> > > > > - docs/system/device-emulation.rst: add remote-i2c-master.rst to
> > > > > the toctree under "Emulated Devices"
> > > > > - qapi/qom.json: move RemoteI2CBackendCuseProperties definition
> > > > > before RemoteObjectProperties as requested; change "for usage
> > > > > information" to "for detailed usage information"
> > > > > ---
> > > > > ---
> > > > > docs/system/device-emulation.rst | 1 +
> > > > > docs/system/devices/remote-i2c-master.rst | 217 ++++
> > > > > hw/i2c/Kconfig | 5 +
> > > > > hw/i2c/meson.build | 6 +
> > > > > hw/i2c/remote-i2c-backend.c | 30 +
> > > > > hw/i2c/remote-i2c-cuse.c | 1173 +++++++++++++++++++++
> > > > > hw/i2c/remote-i2c-fsm.c | 521 +++++++++
> > > > > hw/i2c/remote-i2c-master.c | 145 +++
> > > > > hw/i2c/trace-events | 29 +
> > > > > include/hw/i2c/remote-i2c-backend.h | 70 ++
> > > > > include/hw/i2c/remote-i2c-cuse.h | 93 ++
> > > > > include/hw/i2c/remote-i2c-master.h | 77 ++
> > > > > qapi/qom.json | 29 +
> > > > > tests/qtest/meson.build | 2 +
> > > > > tests/qtest/remote-i2c-cuse-test.c | 326 ++++++
> > > > > 15 files changed, 2724 insertions(+)
> > > > > create mode 100644 docs/system/devices/remote-i2c-master.rst
> > > > > create mode 100644 hw/i2c/remote-i2c-backend.c
> > > > > create mode 100644 hw/i2c/remote-i2c-cuse.c
> > > > > create mode 100644 hw/i2c/remote-i2c-fsm.c
> > > > > create mode 100644 hw/i2c/remote-i2c-master.c
> > > > > create mode 100644 include/hw/i2c/remote-i2c-backend.h
> > > > > create mode 100644 include/hw/i2c/remote-i2c-cuse.h
> > > > > create mode 100644 include/hw/i2c/remote-i2c-master.h
> > > > > create mode 100644 tests/qtest/remote-i2c-cuse-test.c
> > > >
> > > > If I understand this proposal correctly, it lets host-side i2c
> > > > tools talk to emulated I2C devices. The example is i2cdetect/i2cget
> > > > against a tmp105 on an Aspeed bus.
> > > >
> > > > QEMU already has mechanisms for this though. qtest can read/write I2C
> > > > registers programmatically, QMP can query device state, and the guest
> > > > OS itself sees the I2C bus natively.
> > > >
> > > > The dependency cost seems high for the use case: libfuse3 + the cuse
> > > > kernel module pulled into the system emulator build. It's also ~3K
> > > > lines of new code, three QOM types, FUSE session management, etc.
> > > > The surface area for bugs is large. It's a heavy burden for what it
> > > > gives.
> > > >
> > > > I think a lighter QMP-based approach would serve the same purpose,
> > > > maybe better, and fit in better in QEMU, without the dependency and
> > > > maintenance cost:
> > > >
> > > > - No host kernel dependency
> > > > - Works remotely (QMP over socket)
> > > > - Fits QEMU's existing management model
> > > > - Much less code
> > > > - Testable without root or kernel modules
> > > >
> > > > Have you considered extending QMP with an I2C transaction command
> > > > instead? Something like:
> > > >
> > > > { 'command': 'i2c-transfer',
> > > > 'data': { 'bus': 'str',
> > > > 'address': 'uint8',
> > > > 'read': 'bool',
> > > > '*data': ['uint8'],
> > > > '*length': 'uint16' },
> > > > 'returns': { '*data': ['uint8'] } }
> > > >
> > > >
> > > > Thanks,
> > > >
> > > > C.
> > > >
[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 3365 bytes --]
next prev parent reply other threads:[~2026-07-24 15:16 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-22 12:57 [PATCH v5] hw/i2c: Add remote I2C master with host CUSE bridge Ilya Chichkov
2026-07-22 17:42 ` Cédric Le Goater
2026-07-24 8:19 ` Ilya Chichkov
2026-07-24 13:30 ` Corey Minyard
2026-07-24 14:49 ` Ilya Chichkov
2026-07-24 15:15 ` Corey Minyard [this message]
2026-08-11 10:05 ` Ilya Chichkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=amOBf20vEO1dteit@mail.minyard.net \
--to=cminyard@mvista.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=clg@redhat.com \
--cc=eblake@redhat.com \
--cc=farosas@suse.de \
--cc=ilya.chichkov.dev@gmail.com \
--cc=lvivier@redhat.com \
--cc=pbonzini@redhat.com \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox