[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian valu
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state |
Date: |
Tue, 13 Dec 2022 09:22:10 +0100 |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.5.1 |
On 13/12/22 08:30, Philippe Mathieu-Daudé wrote:
On 13/12/22 01:14, Richard Henderson wrote:
On 12/12/22 17:05, Philippe Mathieu-Daudé wrote:
The device endianness doesn't change during runtime.
What are you talking about? Of course it does.
The host CPU certainly does, but the virtio device doesn't... Does it?
This check only consider the device, not the CPU:
bool virtio_access_is_big_endian(VirtIODevice *vdev)
{
#if defined(LEGACY_VIRTIO_IS_BIENDIAN)
return virtio_is_big_endian(vdev);
#elif TARGET_BIG_ENDIAN
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
/*Devices conforming to VIRTIO 1.0 or later are always LE.*/
return false;
}
return true;
#else
return false;
#endif
}
static inline bool virtio_is_big_endian(VirtIODevice *vdev)
{
if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG;
}
/* Devices conforming to VIRTIO 1.0 or later are always LE. */
return false;
}
and once the features are negotiated it doesn't seem to change.
Per the spec, if the device changes its endianness, it must set the
VIRTIO_CONFIG_S_NEEDS_RESET bit:
3.2.1 Notification of Device Configuration Changes
For devices where the device-specific configuration information
can be changed, a configuration change notification is sent when
a device-specific configuration change occurs.
In addition, this notification is triggered by the device setting
DEVICE_NEEDS_RESET
However QEMU doesn't read this bit, only sets it:
hw/virtio/virtio.c:3551: vdev->status = vdev->status |
VIRTIO_CONFIG_S_NEEDS_RESET;
include/standard-headers/linux/virtio_config.h:44:#define
VIRTIO_CONFIG_S_NEEDS_RESET 0x40
I mean, it doesn't often in practice, because the Linux kernel is
compiled for one endianness and doesn't keep toggling state, but the
hooks that you're replacing test for the *current* endianness state of
the cpu. So this is a behaviour change.
I agree. Note however currently the CPU endianness is only checked once
upon virtio device reset (or from a migration stream):
void virtio_reset(void *opaque)
{
VirtIODevice *vdev = opaque;
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
int i;
virtio_set_status(vdev, 0);
if (current_cpu) {
/* Guest initiated reset */
vdev->device_endian = virtio_current_cpu_endian();
} else {
/* System reset */
vdev->device_endian = virtio_default_endian();
}
bool cpu_virtio_is_big_endian(CPUState *cpu)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
if (cc->sysemu_ops->virtio_is_big_endian) {
return cc->sysemu_ops->virtio_is_big_endian(cpu);
}
return target_words_bigendian();
}
ARM being the single arch implementing a runtime endianness check:
static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
cpu_synchronize_state(cs);
return arm_cpu_data_is_big_endian(env);
}
virtio_reset() is only called by virtio_bus_reset().
$ git grep -w virtio_bus_reset
hw/s390x/virtio-ccw.c:256: virtio_bus_reset(&dev->bus);
hw/virtio/virtio-bus.c:102:void virtio_bus_reset(VirtioBusState *bus)
hw/virtio/virtio-mmio.c:75: virtio_bus_reset(&proxy->bus);
hw/virtio/virtio-pci.c:1998: virtio_bus_reset(bus);
So the result of virtio_access_is_big_endian() is only updated there,
after a virtio_bus_reset() call, and IIUC isn't dependent on the CPU
endianness state, thus can be cached in VirtIODevice. But maybe the
current implementation is incomplete and my change is simply making
it worst...
- [PATCH-for-8.0 03/10] hw/virtio: Constify qmp_virtio_feature_map_t[], (continued)
- [PATCH-for-8.0 03/10] hw/virtio: Constify qmp_virtio_feature_map_t[], Philippe Mathieu-Daudé, 2022/12/12
- [PATCH-for-8.0 04/10] hw/virtio: Extract config read/write accessors to virtio-config.c, Philippe Mathieu-Daudé, 2022/12/12
- [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state, Philippe Mathieu-Daudé, 2022/12/12
- Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state, Richard Henderson, 2022/12/12
- Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state, Philippe Mathieu-Daudé, 2022/12/13
- Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state, Thomas Huth, 2022/12/13
- Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state, Philippe Mathieu-Daudé, 2022/12/13
- Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state, Thomas Huth, 2022/12/13
- Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state,
Philippe Mathieu-Daudé <=
- Re: [RFC PATCH-for-8.0 06/10] hw/virtio: Cache access_is_big_endian value in VirtIODevice state, Richard Henderson, 2022/12/13
- [PATCH-for-8.0 05/10] hw/virtio: Extract QMP related code virtio-qmp.c, Philippe Mathieu-Daudé, 2022/12/12
- [RFC PATCH-for-8.0 07/10] hw/virtio: Directly access cached VirtIODevice::access_is_big_endian, Philippe Mathieu-Daudé, 2022/12/12
- [PATCH-for-8.0 08/10] hw/virtio: Un-inline virtio_access_is_big_endian(), Philippe Mathieu-Daudé, 2022/12/12
- [RFC PATCH-for-8.0 09/10] hw/virtio: Extract vhost_user_ram_slots_max() to vhost-user-target.c, Philippe Mathieu-Daudé, 2022/12/12
- [RFC PATCH-for-8.0 10/10] hw/virtio: Make most of virtio devices target-independent, Philippe Mathieu-Daudé, 2022/12/12