* ACPI endianness
@ 2021-10-10 13:24 BALATON Zoltan
2021-10-10 14:03 ` Michael S. Tsirkin
2021-10-11 5:52 ` Philippe Mathieu-Daudé
0 siblings, 2 replies; 14+ messages in thread
From: BALATON Zoltan @ 2021-10-10 13:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Igor Mammedov, Philippe Mathieu-Daudé, Michael S. Tsirkin
Hello,
I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as part
of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c) and
found that the guest writes to ACPI PM1aCNT register come out with wrong
endianness but not shure why. I have this:
$ qemu-system-ppc -M pegasos2 -monitor stdio
(qemu) info mtree
[...]
memory-region: pci1-io
0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
[...]
0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
memory-region: system
0000000000000000-ffffffffffffffff (prio 0, i/o): system
0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win @pci1-mem 0000000080000000-00000000bfffffff
00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win @pci0-mem 00000000c0000000-00000000dfffffff
00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win @pci0-io 0000000000000000-0000000000ffffff
00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win @pci0-mem 0000000000000000-0000000000ffffff
00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win @pci1-mem 0000000000000000-0000000000ffffff
00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win @pci1-io 0000000000000000-0000000000ffffff
00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win @pci1-mem 00000000ff800000-00000000ffffffff
00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
The guest (which is big endian PPC and I think wotks on real hardware)
writes to 0xf05 in the io region which should be the high byte of the
little endian register but in the acpi code it comes out wrong, instead
of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
The memory regions involved are:
acpi-cnt (hw/acpi/core.c):
static const MemoryRegionOps acpi_pm_cnt_ops = {
.read = acpi_pm_cnt_read,
.write = acpi_pm_cnt_write,
.impl.min_access_size = 2,
.valid.min_access_size = 1,
.valid.max_access_size = 2,
.endianness = DEVICE_LITTLE_ENDIAN,
};
via-pm (hw/isa/vt82c686.c):
static const MemoryRegionOps pm_io_ops = {
.read = pm_io_read,
.write = pm_io_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl = {
.min_access_size = 1,
.max_access_size = 1,
},
};
Also tried removing .impl from pm_io_ops but that does not help. Changing
acpi_pm_cnt_ops to DEVICE_NATIVE_ENDIAN fixes it but not sure what else
could that break. Should these ACPI regions be native endian or how else
to fix this for the vt82xx case?
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-10 13:24 ACPI endianness BALATON Zoltan
@ 2021-10-10 14:03 ` Michael S. Tsirkin
2021-10-10 14:26 ` BALATON Zoltan
2021-10-11 5:52 ` Philippe Mathieu-Daudé
1 sibling, 1 reply; 14+ messages in thread
From: Michael S. Tsirkin @ 2021-10-10 14:03 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel
On Sun, Oct 10, 2021 at 03:24:32PM +0200, BALATON Zoltan wrote:
> Hello,
>
> I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as part of
> the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c) and found
> that the guest writes to ACPI PM1aCNT register come out with wrong
> endianness but not shure why. I have this:
>
> $ qemu-system-ppc -M pegasos2 -monitor stdio
> (qemu) info mtree
> [...]
> memory-region: pci1-io
> 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
> [...]
> 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
> 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
> 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
> 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
>
> memory-region: system
> 0000000000000000-ffffffffffffffff (prio 0, i/o): system
> 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
> 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win @pci1-mem 0000000080000000-00000000bfffffff
> 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win @pci0-mem 00000000c0000000-00000000dfffffff
> 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
> 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win @pci0-io 0000000000000000-0000000000ffffff
> 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win @pci0-mem 0000000000000000-0000000000ffffff
> 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win @pci1-mem 0000000000000000-0000000000ffffff
> 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win @pci1-io 0000000000000000-0000000000ffffff
> 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win @pci1-mem 00000000ff800000-00000000ffffffff
> 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
>
> The guest (which is big endian PPC and I think wotks on real hardware)
> writes to 0xf05 in the io region which should be the high byte of the little
> endian register but in the acpi code it comes out wrong, instead of 0x2800 I
> get in acpi_pm1_cnt_write: val=0x28
>
> The memory regions involved are:
>
> acpi-cnt (hw/acpi/core.c):
>
> static const MemoryRegionOps acpi_pm_cnt_ops = {
> .read = acpi_pm_cnt_read,
> .write = acpi_pm_cnt_write,
> .impl.min_access_size = 2,
> .valid.min_access_size = 1,
> .valid.max_access_size = 2,
> .endianness = DEVICE_LITTLE_ENDIAN,
> };
>
> via-pm (hw/isa/vt82c686.c):
>
> static const MemoryRegionOps pm_io_ops = {
> .read = pm_io_read,
> .write = pm_io_write,
> .endianness = DEVICE_NATIVE_ENDIAN,
> .impl = {
> .min_access_size = 1,
> .max_access_size = 1,
> },
> };
>
> Also tried removing .impl from pm_io_ops but that does not help. Changing
> acpi_pm_cnt_ops to DEVICE_NATIVE_ENDIAN fixes it but not sure what else
> could that break. Should these ACPI regions be native endian or how else to
> fix this for the vt82xx case?
>
> Regards,
> BALATON Zoltan
Does it help if you change via to DEVICE_LITTLE_ENDIAN?
--
MST
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-10 14:03 ` Michael S. Tsirkin
@ 2021-10-10 14:26 ` BALATON Zoltan
0 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2021-10-10 14:26 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel
On Sun, 10 Oct 2021, Michael S. Tsirkin wrote:
> On Sun, Oct 10, 2021 at 03:24:32PM +0200, BALATON Zoltan wrote:
>> Hello,
>>
>> I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as part of
>> the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c) and found
>> that the guest writes to ACPI PM1aCNT register come out with wrong
>> endianness but not shure why. I have this:
>>
>> $ qemu-system-ppc -M pegasos2 -monitor stdio
>> (qemu) info mtree
>> [...]
>> memory-region: pci1-io
>> 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
>> [...]
>> 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
>> 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
>> 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
>> 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
>>
>> memory-region: system
>> 0000000000000000-ffffffffffffffff (prio 0, i/o): system
>> 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
>> 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win @pci1-mem 0000000080000000-00000000bfffffff
>> 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win @pci0-mem 00000000c0000000-00000000dfffffff
>> 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
>> 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win @pci0-io 0000000000000000-0000000000ffffff
>> 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win @pci0-mem 0000000000000000-0000000000ffffff
>> 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win @pci1-mem 0000000000000000-0000000000ffffff
>> 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win @pci1-io 0000000000000000-0000000000ffffff
>> 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win @pci1-mem 00000000ff800000-00000000ffffffff
>> 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
>>
>> The guest (which is big endian PPC and I think wotks on real hardware)
>> writes to 0xf05 in the io region which should be the high byte of the little
>> endian register but in the acpi code it comes out wrong, instead of 0x2800 I
>> get in acpi_pm1_cnt_write: val=0x28
>>
>> The memory regions involved are:
>>
>> acpi-cnt (hw/acpi/core.c):
>>
>> static const MemoryRegionOps acpi_pm_cnt_ops = {
>> .read = acpi_pm_cnt_read,
>> .write = acpi_pm_cnt_write,
>> .impl.min_access_size = 2,
>> .valid.min_access_size = 1,
>> .valid.max_access_size = 2,
>> .endianness = DEVICE_LITTLE_ENDIAN,
>> };
>>
>> via-pm (hw/isa/vt82c686.c):
>>
>> static const MemoryRegionOps pm_io_ops = {
>> .read = pm_io_read,
>> .write = pm_io_write,
>> .endianness = DEVICE_NATIVE_ENDIAN,
>> .impl = {
>> .min_access_size = 1,
>> .max_access_size = 1,
>> },
>> };
>>
>> Also tried removing .impl from pm_io_ops but that does not help. Changing
>> acpi_pm_cnt_ops to DEVICE_NATIVE_ENDIAN fixes it but not sure what else
>> could that break. Should these ACPI regions be native endian or how else to
>> fix this for the vt82xx case?
>>
>> Regards,
>> BALATON Zoltan
>
> Does it help if you change via to DEVICE_LITTLE_ENDIAN?
No. That region is just acting as a container for the ACPI regions so they
can be moved together to the base address settable by the guest (and maybe
implementing some other regs later if needed but we don't do that now) but
looks like it's not involved in read/write to acpi regs as its ops are not
called and the write goes through to the acpi-cnt region. So it also does
not matter if I change endianness or impl in pm_io_ops in vt82c686.c.
These acpi bits only seem to be used on piix4 and ich9 apart from vt82xx
and those are probably used on little endian hosts while vt8231 is used on
pegasos2 which is big endian PPC and vt82c686b on fullong2e which I think
is little endian MIPS. What does NATIVE_ENDIAN actually mean? It does not
seem to be documented anywhere. Would it change anything if the ACPI
regions are changed ro NATIVE_ENDIAN for little endian machines that are
all the other usages? If not then maybe that's the way to go.
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-10 13:24 ACPI endianness BALATON Zoltan
2021-10-10 14:03 ` Michael S. Tsirkin
@ 2021-10-11 5:52 ` Philippe Mathieu-Daudé
2021-10-11 10:13 ` BALATON Zoltan
1 sibling, 1 reply; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-10-11 5:52 UTC (permalink / raw)
To: BALATON Zoltan, qemu-devel; +Cc: Igor Mammedov, Michael S. Tsirkin
On 10/10/21 15:24, BALATON Zoltan wrote:
> Hello,
>
> I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
> part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
> and found that the guest writes to ACPI PM1aCNT register come out with
> wrong endianness but not shure why. I have this:
>
> $ qemu-system-ppc -M pegasos2 -monitor stdio
> (qemu) info mtree
> [...]
> memory-region: pci1-io
> 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
> [...]
> 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
> 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
> 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
> 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
>
> memory-region: system
> 0000000000000000-ffffffffffffffff (prio 0, i/o): system
> 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
> 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
> @pci1-mem 0000000080000000-00000000bfffffff
> 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
> @pci0-mem 00000000c0000000-00000000dfffffff
> 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
> 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
> @pci0-io 0000000000000000-0000000000ffffff
> 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
> @pci0-mem 0000000000000000-0000000000ffffff
> 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
> @pci1-mem 0000000000000000-0000000000ffffff
> 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
> @pci1-io 0000000000000000-0000000000ffffff
> 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
> @pci1-mem 00000000ff800000-00000000ffffffff
> 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
>
> The guest (which is big endian PPC and I think wotks on real hardware)
> writes to 0xf05 in the io region which should be the high byte of the
> little endian register but in the acpi code it comes out wrong, instead
> of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
Looks like a northbridge issue (MV64340).
Does Pegasos2 enables bus swapping?
See hw/pci-host/mv64361.c:585:
static void warn_swap_bit(uint64_t val)
{
if ((val & 0x3000000ULL) >> 24 != 1) {
qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
}
}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 5:52 ` Philippe Mathieu-Daudé
@ 2021-10-11 10:13 ` BALATON Zoltan
2021-10-11 12:19 ` Michael S. Tsirkin
0 siblings, 1 reply; 14+ messages in thread
From: BALATON Zoltan @ 2021-10-11 10:13 UTC (permalink / raw)
To: Philippe Mathieu-Daudé; +Cc: Igor Mammedov, qemu-devel, Michael S. Tsirkin
[-- Attachment #1: Type: text/plain, Size: 3424 bytes --]
On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
> On 10/10/21 15:24, BALATON Zoltan wrote:
>> Hello,
>>
>> I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
>> part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
>> and found that the guest writes to ACPI PM1aCNT register come out with
>> wrong endianness but not shure why. I have this:
>>
>> $ qemu-system-ppc -M pegasos2 -monitor stdio
>> (qemu) info mtree
>> [...]
>> memory-region: pci1-io
>> 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
>> [...]
>> 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
>> 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
>> 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
>> 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
>>
>> memory-region: system
>> 0000000000000000-ffffffffffffffff (prio 0, i/o): system
>> 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
>> 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
>> @pci1-mem 0000000080000000-00000000bfffffff
>> 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
>> @pci0-mem 00000000c0000000-00000000dfffffff
>> 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
>> 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
>> @pci0-io 0000000000000000-0000000000ffffff
>> 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
>> @pci0-mem 0000000000000000-0000000000ffffff
>> 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
>> @pci1-mem 0000000000000000-0000000000ffffff
>> 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
>> @pci1-io 0000000000000000-0000000000ffffff
>> 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
>> @pci1-mem 00000000ff800000-00000000ffffffff
>> 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
>>
>> The guest (which is big endian PPC and I think wotks on real hardware)
>> writes to 0xf05 in the io region which should be the high byte of the
>> little endian register but in the acpi code it comes out wrong, instead
>> of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
>
> Looks like a northbridge issue (MV64340).
> Does Pegasos2 enables bus swapping?
> See hw/pci-host/mv64361.c:585:
>
> static void warn_swap_bit(uint64_t val)
> {
> if ((val & 0x3000000ULL) >> 24 != 1) {
> qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
> }
> }
No, guests don't use this feature just byteswap themselves and write
little endian values to the mapped io region. (Or in this case just write
one byte of the 16 bit value, it specifically writes 0x28 to 0xf05.)
That's why I think the device model should not byteswap itself so the acpi
regions should be declared native endian and let the guest handle it. Some
mentions I've found say that native endian means don't byteswap, little
endian means byteswap if vcpu is big endian and big endian means byteswap
if vcpu is little endian. Since guests already account for this and write
little endian values to these regions there's no need to byteswap in
device model and changing to native endian should not affect little endian
machines so unless there's a better argument I'll try sending a patch.
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 10:13 ` BALATON Zoltan
@ 2021-10-11 12:19 ` Michael S. Tsirkin
2021-10-11 13:14 ` Jonathan Cameron
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Michael S. Tsirkin @ 2021-10-11 12:19 UTC (permalink / raw)
To: BALATON Zoltan
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
On Mon, Oct 11, 2021 at 12:13:55PM +0200, BALATON Zoltan wrote:
> On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
> > On 10/10/21 15:24, BALATON Zoltan wrote:
> > > Hello,
> > >
> > > I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
> > > part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
> > > and found that the guest writes to ACPI PM1aCNT register come out with
> > > wrong endianness but not shure why. I have this:
> > >
> > > $ qemu-system-ppc -M pegasos2 -monitor stdio
> > > (qemu) info mtree
> > > [...]
> > > memory-region: pci1-io
> > > 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
> > > [...]
> > > 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
> > > 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
> > > 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
> > > 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
> > >
> > > memory-region: system
> > > 0000000000000000-ffffffffffffffff (prio 0, i/o): system
> > > 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
> > > 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
> > > @pci1-mem 0000000080000000-00000000bfffffff
> > > 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
> > > @pci0-mem 00000000c0000000-00000000dfffffff
> > > 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
> > > 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
> > > @pci0-io 0000000000000000-0000000000ffffff
> > > 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
> > > @pci0-mem 0000000000000000-0000000000ffffff
> > > 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
> > > @pci1-mem 0000000000000000-0000000000ffffff
> > > 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
> > > @pci1-io 0000000000000000-0000000000ffffff
> > > 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
> > > @pci1-mem 00000000ff800000-00000000ffffffff
> > > 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
> > >
> > > The guest (which is big endian PPC and I think wotks on real hardware)
> > > writes to 0xf05 in the io region which should be the high byte of the
> > > little endian register but in the acpi code it comes out wrong, instead
> > > of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
> >
> > Looks like a northbridge issue (MV64340).
> > Does Pegasos2 enables bus swapping?
> > See hw/pci-host/mv64361.c:585:
> >
> > static void warn_swap_bit(uint64_t val)
> > {
> > if ((val & 0x3000000ULL) >> 24 != 1) {
> > qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
> > }
> > }
>
> No, guests don't use this feature just byteswap themselves and write little
> endian values to the mapped io region. (Or in this case just write one byte
> of the 16 bit value, it specifically writes 0x28 to 0xf05.) That's why I
> think the device model should not byteswap itself so the acpi regions should
> be declared native endian and let the guest handle it. Some mentions I've
> found say that native endian means don't byteswap, little endian means
> byteswap if vcpu is big endian and big endian means byteswap if vcpu is
> little endian. Since guests already account for this and write little endian
> values to these regions there's no need to byteswap in device model and
> changing to native endian should not affect little endian machines so unless
> there's a better argument I'll try sending a patch.
>
> Regards,
> BALATON Zoltan
native endian means endian-ness is open-coded in the device handler
itself. I think you just found a bug in memory core.
static const MemoryRegionOps acpi_pm_cnt_ops = {
.read = acpi_pm_cnt_read,
.write = acpi_pm_cnt_write,
.impl.min_access_size = 2,
.valid.min_access_size = 1,
.valid.max_access_size = 2,
.endianness = DEVICE_LITTLE_ENDIAN,
};
Because of that .impl.min_access_size = 2,
the 1 byte write should be converted to a 2 byte
read+2 byte write.
docs/devel/memory.rst just says:
- .impl.min_access_size, .impl.max_access_size define the access sizes
(in bytes) supported by the *implementation*; other access sizes will be
emulated using the ones available. For example a 4-byte write will be
emulated using four 1-byte writes, if .impl.max_access_size = 1.
Instead what we have is:
MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
hwaddr addr,
uint64_t data,
MemOp op,
MemTxAttrs attrs)
{
unsigned size = memop_size(op);
if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
unassigned_mem_write(mr, addr, data, size);
return MEMTX_DECODE_ERROR;
}
adjust_endianness(mr, &data, op);
---
static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)
{
if ((op & MO_BSWAP) != devend_memop(mr->ops->endianness)) {
switch (op & MO_SIZE) {
case MO_8:
break;
case MO_16:
*data = bswap16(*data);
break;
case MO_32:
*data = bswap32(*data);
break;
case MO_64:
*data = bswap64(*data);
break;
default:
g_assert_not_reached();
}
}
}
so the byte swap is based on size before extending it to
.impl.min_access_size, not after.
Also, no read happens which I suspect is also a bug,
but could be harmless ...
Paolo, any feedback here?
--
MST
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 12:19 ` Michael S. Tsirkin
@ 2021-10-11 13:14 ` Jonathan Cameron
2021-10-11 13:27 ` BALATON Zoltan
2021-10-25 15:05 ` BALATON Zoltan
2 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2021-10-11 13:14 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Igor Mammedov, pbonzini, Philippe Mathieu-Daudé, qemu-devel
On Mon, 11 Oct 2021 08:19:01 -0400
"Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Mon, Oct 11, 2021 at 12:13:55PM +0200, BALATON Zoltan wrote:
> > On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
> > > On 10/10/21 15:24, BALATON Zoltan wrote:
> > > > Hello,
> > > >
> > > > I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
> > > > part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
> > > > and found that the guest writes to ACPI PM1aCNT register come out with
> > > > wrong endianness but not shure why. I have this:
> > > >
> > > > $ qemu-system-ppc -M pegasos2 -monitor stdio
> > > > (qemu) info mtree
> > > > [...]
> > > > memory-region: pci1-io
> > > > 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
> > > > [...]
> > > > 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
> > > > 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
> > > > 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
> > > > 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
> > > >
> > > > memory-region: system
> > > > 0000000000000000-ffffffffffffffff (prio 0, i/o): system
> > > > 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
> > > > 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
> > > > @pci1-mem 0000000080000000-00000000bfffffff
> > > > 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
> > > > @pci0-mem 00000000c0000000-00000000dfffffff
> > > > 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
> > > > 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
> > > > @pci0-io 0000000000000000-0000000000ffffff
> > > > 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
> > > > @pci0-mem 0000000000000000-0000000000ffffff
> > > > 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
> > > > @pci1-mem 0000000000000000-0000000000ffffff
> > > > 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
> > > > @pci1-io 0000000000000000-0000000000ffffff
> > > > 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
> > > > @pci1-mem 00000000ff800000-00000000ffffffff
> > > > 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
> > > >
> > > > The guest (which is big endian PPC and I think wotks on real hardware)
> > > > writes to 0xf05 in the io region which should be the high byte of the
> > > > little endian register but in the acpi code it comes out wrong, instead
> > > > of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
> > >
> > > Looks like a northbridge issue (MV64340).
> > > Does Pegasos2 enables bus swapping?
> > > See hw/pci-host/mv64361.c:585:
> > >
> > > static void warn_swap_bit(uint64_t val)
> > > {
> > > if ((val & 0x3000000ULL) >> 24 != 1) {
> > > qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
> > > }
> > > }
> >
> > No, guests don't use this feature just byteswap themselves and write little
> > endian values to the mapped io region. (Or in this case just write one byte
> > of the 16 bit value, it specifically writes 0x28 to 0xf05.) That's why I
> > think the device model should not byteswap itself so the acpi regions should
> > be declared native endian and let the guest handle it. Some mentions I've
> > found say that native endian means don't byteswap, little endian means
> > byteswap if vcpu is big endian and big endian means byteswap if vcpu is
> > little endian. Since guests already account for this and write little endian
> > values to these regions there's no need to byteswap in device model and
> > changing to native endian should not affect little endian machines so unless
> > there's a better argument I'll try sending a patch.
> >
> > Regards,
> > BALATON Zoltan
>
> native endian means endian-ness is open-coded in the device handler
> itself. I think you just found a bug in memory core.
>
> static const MemoryRegionOps acpi_pm_cnt_ops = {
> .read = acpi_pm_cnt_read,
> .write = acpi_pm_cnt_write,
> .impl.min_access_size = 2,
> .valid.min_access_size = 1,
> .valid.max_access_size = 2,
> .endianness = DEVICE_LITTLE_ENDIAN,
> };
>
>
> Because of that .impl.min_access_size = 2,
> the 1 byte write should be converted to a 2 byte
> read+2 byte write.
>
> docs/devel/memory.rst just says:
> - .impl.min_access_size, .impl.max_access_size define the access sizes
> (in bytes) supported by the *implementation*; other access sizes will be
> emulated using the ones available. For example a 4-byte write will be
> emulated using four 1-byte writes, if .impl.max_access_size = 1.
>
>
>
> Instead what we have is:
>
> MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
> hwaddr addr,
> uint64_t data,
> MemOp op,
> MemTxAttrs attrs)
> {
> unsigned size = memop_size(op);
>
> if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
> unassigned_mem_write(mr, addr, data, size);
> return MEMTX_DECODE_ERROR;
> }
>
> adjust_endianness(mr, &data, op);
>
>
> ---
>
>
> static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)
> {
> if ((op & MO_BSWAP) != devend_memop(mr->ops->endianness)) {
> switch (op & MO_SIZE) {
> case MO_8:
> break;
> case MO_16:
> *data = bswap16(*data);
> break;
> case MO_32:
> *data = bswap32(*data);
> break;
> case MO_64:
> *data = bswap64(*data);
> break;
> default:
> g_assert_not_reached();
> }
> }
> }
>
> so the byte swap is based on size before extending it to
> .impl.min_access_size, not after.
>
> Also, no read happens which I suspect is also a bug,
> but could be harmless ...
The lack of read modify write looks like this again:
https://lore.kernel.org/qemu-devel/20210513124737.00002b2d@Huawei.com/
byte swap part is new to me though...
>
> Paolo, any feedback here?
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 12:19 ` Michael S. Tsirkin
2021-10-11 13:14 ` Jonathan Cameron
@ 2021-10-11 13:27 ` BALATON Zoltan
2021-10-11 13:34 ` Michael S. Tsirkin
2021-10-25 15:05 ` BALATON Zoltan
2 siblings, 1 reply; 14+ messages in thread
From: BALATON Zoltan @ 2021-10-11 13:27 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
[-- Attachment #1: Type: text/plain, Size: 6518 bytes --]
On Mon, 11 Oct 2021, Michael S. Tsirkin wrote:
> On Mon, Oct 11, 2021 at 12:13:55PM +0200, BALATON Zoltan wrote:
>> On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
>>> On 10/10/21 15:24, BALATON Zoltan wrote:
>>>> Hello,
>>>>
>>>> I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
>>>> part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
>>>> and found that the guest writes to ACPI PM1aCNT register come out with
>>>> wrong endianness but not shure why. I have this:
>>>>
>>>> $ qemu-system-ppc -M pegasos2 -monitor stdio
>>>> (qemu) info mtree
>>>> [...]
>>>> memory-region: pci1-io
>>>> 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
>>>> [...]
>>>> 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
>>>> 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
>>>> 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
>>>> 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
>>>>
>>>> memory-region: system
>>>> 0000000000000000-ffffffffffffffff (prio 0, i/o): system
>>>> 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
>>>> 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
>>>> @pci1-mem 0000000080000000-00000000bfffffff
>>>> 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
>>>> @pci0-mem 00000000c0000000-00000000dfffffff
>>>> 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
>>>> 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
>>>> @pci0-io 0000000000000000-0000000000ffffff
>>>> 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
>>>> @pci0-mem 0000000000000000-0000000000ffffff
>>>> 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
>>>> @pci1-mem 0000000000000000-0000000000ffffff
>>>> 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
>>>> @pci1-io 0000000000000000-0000000000ffffff
>>>> 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
>>>> @pci1-mem 00000000ff800000-00000000ffffffff
>>>> 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
>>>>
>>>> The guest (which is big endian PPC and I think wotks on real hardware)
>>>> writes to 0xf05 in the io region which should be the high byte of the
>>>> little endian register but in the acpi code it comes out wrong, instead
>>>> of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
>>>
>>> Looks like a northbridge issue (MV64340).
>>> Does Pegasos2 enables bus swapping?
>>> See hw/pci-host/mv64361.c:585:
>>>
>>> static void warn_swap_bit(uint64_t val)
>>> {
>>> if ((val & 0x3000000ULL) >> 24 != 1) {
>>> qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
>>> }
>>> }
>>
>> No, guests don't use this feature just byteswap themselves and write little
>> endian values to the mapped io region. (Or in this case just write one byte
>> of the 16 bit value, it specifically writes 0x28 to 0xf05.) That's why I
>> think the device model should not byteswap itself so the acpi regions should
>> be declared native endian and let the guest handle it. Some mentions I've
>> found say that native endian means don't byteswap, little endian means
>> byteswap if vcpu is big endian and big endian means byteswap if vcpu is
>> little endian. Since guests already account for this and write little endian
>> values to these regions there's no need to byteswap in device model and
>> changing to native endian should not affect little endian machines so unless
>> there's a better argument I'll try sending a patch.
>>
>> Regards,
>> BALATON Zoltan
>
> native endian means endian-ness is open-coded in the device handler
> itself. I think you just found a bug in memory core.
>
> static const MemoryRegionOps acpi_pm_cnt_ops = {
> .read = acpi_pm_cnt_read,
> .write = acpi_pm_cnt_write,
> .impl.min_access_size = 2,
> .valid.min_access_size = 1,
> .valid.max_access_size = 2,
> .endianness = DEVICE_LITTLE_ENDIAN,
> };
>
>
> Because of that .impl.min_access_size = 2,
> the 1 byte write should be converted to a 2 byte
> read+2 byte write.
>
> docs/devel/memory.rst just says:
> - .impl.min_access_size, .impl.max_access_size define the access sizes
> (in bytes) supported by the *implementation*; other access sizes will be
> emulated using the ones available. For example a 4-byte write will be
> emulated using four 1-byte writes, if .impl.max_access_size = 1.
>
>
>
> Instead what we have is:
>
> MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
> hwaddr addr,
> uint64_t data,
> MemOp op,
> MemTxAttrs attrs)
> {
> unsigned size = memop_size(op);
>
> if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
> unassigned_mem_write(mr, addr, data, size);
> return MEMTX_DECODE_ERROR;
> }
>
> adjust_endianness(mr, &data, op);
>
>
> ---
>
>
> static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)
> {
> if ((op & MO_BSWAP) != devend_memop(mr->ops->endianness)) {
> switch (op & MO_SIZE) {
> case MO_8:
> break;
> case MO_16:
> *data = bswap16(*data);
> break;
> case MO_32:
> *data = bswap32(*data);
> break;
> case MO_64:
> *data = bswap64(*data);
> break;
> default:
> g_assert_not_reached();
> }
> }
> }
>
> so the byte swap is based on size before extending it to
> .impl.min_access_size, not after.
OK thanks for the analysis, I'll wait what comes out of this.
> Also, no read happens which I suspect is also a bug,
> but could be harmless ...
I did not check if a read happens or not but generally I think that may be
another source of bugs if the memory core changes writes to read + write
because for some devices a read might have side effects (like changing
bits, clearing interrupt status, whatever) so the emulation would behave
differently than real hardware if a guest tries to write such a register.
So this may have problems either way even if this particular case is not
affected by that and could just be "fixed" by declaring the regions native
endian to disable this part of memory core or fixing that up to do byte
swapping back and forth. I don't mind either way as long as it works.
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 13:27 ` BALATON Zoltan
@ 2021-10-11 13:34 ` Michael S. Tsirkin
2021-10-11 13:51 ` BALATON Zoltan
0 siblings, 1 reply; 14+ messages in thread
From: Michael S. Tsirkin @ 2021-10-11 13:34 UTC (permalink / raw)
To: BALATON Zoltan
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
On Mon, Oct 11, 2021 at 03:27:44PM +0200, BALATON Zoltan wrote:
> On Mon, 11 Oct 2021, Michael S. Tsirkin wrote:
> > On Mon, Oct 11, 2021 at 12:13:55PM +0200, BALATON Zoltan wrote:
> > > On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
> > > > On 10/10/21 15:24, BALATON Zoltan wrote:
> > > > > Hello,
> > > > >
> > > > > I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
> > > > > part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
> > > > > and found that the guest writes to ACPI PM1aCNT register come out with
> > > > > wrong endianness but not shure why. I have this:
> > > > >
> > > > > $ qemu-system-ppc -M pegasos2 -monitor stdio
> > > > > (qemu) info mtree
> > > > > [...]
> > > > > memory-region: pci1-io
> > > > > 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
> > > > > [...]
> > > > > 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
> > > > > 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
> > > > > 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
> > > > > 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
> > > > >
> > > > > memory-region: system
> > > > > 0000000000000000-ffffffffffffffff (prio 0, i/o): system
> > > > > 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
> > > > > 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
> > > > > @pci1-mem 0000000080000000-00000000bfffffff
> > > > > 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
> > > > > @pci0-mem 00000000c0000000-00000000dfffffff
> > > > > 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
> > > > > 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
> > > > > @pci0-io 0000000000000000-0000000000ffffff
> > > > > 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
> > > > > @pci0-mem 0000000000000000-0000000000ffffff
> > > > > 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
> > > > > @pci1-mem 0000000000000000-0000000000ffffff
> > > > > 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
> > > > > @pci1-io 0000000000000000-0000000000ffffff
> > > > > 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
> > > > > @pci1-mem 00000000ff800000-00000000ffffffff
> > > > > 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
> > > > >
> > > > > The guest (which is big endian PPC and I think wotks on real hardware)
> > > > > writes to 0xf05 in the io region which should be the high byte of the
> > > > > little endian register but in the acpi code it comes out wrong, instead
> > > > > of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
> > > >
> > > > Looks like a northbridge issue (MV64340).
> > > > Does Pegasos2 enables bus swapping?
> > > > See hw/pci-host/mv64361.c:585:
> > > >
> > > > static void warn_swap_bit(uint64_t val)
> > > > {
> > > > if ((val & 0x3000000ULL) >> 24 != 1) {
> > > > qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
> > > > }
> > > > }
> > >
> > > No, guests don't use this feature just byteswap themselves and write little
> > > endian values to the mapped io region. (Or in this case just write one byte
> > > of the 16 bit value, it specifically writes 0x28 to 0xf05.) That's why I
> > > think the device model should not byteswap itself so the acpi regions should
> > > be declared native endian and let the guest handle it. Some mentions I've
> > > found say that native endian means don't byteswap, little endian means
> > > byteswap if vcpu is big endian and big endian means byteswap if vcpu is
> > > little endian. Since guests already account for this and write little endian
> > > values to these regions there's no need to byteswap in device model and
> > > changing to native endian should not affect little endian machines so unless
> > > there's a better argument I'll try sending a patch.
> > >
> > > Regards,
> > > BALATON Zoltan
> >
> > native endian means endian-ness is open-coded in the device handler
> > itself. I think you just found a bug in memory core.
> >
> > static const MemoryRegionOps acpi_pm_cnt_ops = {
> > .read = acpi_pm_cnt_read,
> > .write = acpi_pm_cnt_write,
> > .impl.min_access_size = 2,
> > .valid.min_access_size = 1,
> > .valid.max_access_size = 2,
> > .endianness = DEVICE_LITTLE_ENDIAN,
> > };
> >
> >
> > Because of that .impl.min_access_size = 2,
> > the 1 byte write should be converted to a 2 byte
> > read+2 byte write.
> >
> > docs/devel/memory.rst just says:
> > - .impl.min_access_size, .impl.max_access_size define the access sizes
> > (in bytes) supported by the *implementation*; other access sizes will be
> > emulated using the ones available. For example a 4-byte write will be
> > emulated using four 1-byte writes, if .impl.max_access_size = 1.
> >
> >
> >
> > Instead what we have is:
> >
> > MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
> > hwaddr addr,
> > uint64_t data,
> > MemOp op,
> > MemTxAttrs attrs)
> > {
> > unsigned size = memop_size(op);
> >
> > if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
> > unassigned_mem_write(mr, addr, data, size);
> > return MEMTX_DECODE_ERROR;
> > }
> >
> > adjust_endianness(mr, &data, op);
> >
> >
> > ---
> >
> >
> > static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)
> > {
> > if ((op & MO_BSWAP) != devend_memop(mr->ops->endianness)) {
> > switch (op & MO_SIZE) {
> > case MO_8:
> > break;
> > case MO_16:
> > *data = bswap16(*data);
> > break;
> > case MO_32:
> > *data = bswap32(*data);
> > break;
> > case MO_64:
> > *data = bswap64(*data);
> > break;
> > default:
> > g_assert_not_reached();
> > }
> > }
> > }
> >
> > so the byte swap is based on size before extending it to
> > .impl.min_access_size, not after.
>
> OK thanks for the analysis, I'll wait what comes out of this.
>
> > Also, no read happens which I suspect is also a bug,
> > but could be harmless ...
>
> I did not check if a read happens or not but generally I think that may be
> another source of bugs if the memory core changes writes to read + write
> because for some devices a read might have side effects
IMHO if reads have side effects then devices should not set .impl.min_access_size
... but given we did not previously do the read, maybe we should keep
it that way at least for the time being.
> (like changing bits,
> clearing interrupt status, whatever) so the emulation would behave
> differently than real hardware if a guest tries to write such a register. So
> this may have problems either way even if this particular case is not
> affected by that and could just be "fixed" by declaring the regions native
> endian to disable this part of memory core or fixing that up to do byte
> swapping back and forth. I don't mind either way as long as it works.
>
> Regards,
> BALATON Zoltan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 13:34 ` Michael S. Tsirkin
@ 2021-10-11 13:51 ` BALATON Zoltan
2021-10-11 15:55 ` Michael S. Tsirkin
0 siblings, 1 reply; 14+ messages in thread
From: BALATON Zoltan @ 2021-10-11 13:51 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
[-- Attachment #1: Type: text/plain, Size: 7461 bytes --]
On Mon, 11 Oct 2021, Michael S. Tsirkin wrote:
> On Mon, Oct 11, 2021 at 03:27:44PM +0200, BALATON Zoltan wrote:
>> On Mon, 11 Oct 2021, Michael S. Tsirkin wrote:
>>> On Mon, Oct 11, 2021 at 12:13:55PM +0200, BALATON Zoltan wrote:
>>>> On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
>>>>> On 10/10/21 15:24, BALATON Zoltan wrote:
>>>>>> Hello,
>>>>>>
>>>>>> I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
>>>>>> part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
>>>>>> and found that the guest writes to ACPI PM1aCNT register come out with
>>>>>> wrong endianness but not shure why. I have this:
>>>>>>
>>>>>> $ qemu-system-ppc -M pegasos2 -monitor stdio
>>>>>> (qemu) info mtree
>>>>>> [...]
>>>>>> memory-region: pci1-io
>>>>>> 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
>>>>>> [...]
>>>>>> 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
>>>>>> 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
>>>>>> 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
>>>>>> 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
>>>>>>
>>>>>> memory-region: system
>>>>>> 0000000000000000-ffffffffffffffff (prio 0, i/o): system
>>>>>> 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
>>>>>> 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
>>>>>> @pci1-mem 0000000080000000-00000000bfffffff
>>>>>> 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
>>>>>> @pci0-mem 00000000c0000000-00000000dfffffff
>>>>>> 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
>>>>>> 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
>>>>>> @pci0-io 0000000000000000-0000000000ffffff
>>>>>> 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
>>>>>> @pci0-mem 0000000000000000-0000000000ffffff
>>>>>> 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
>>>>>> @pci1-mem 0000000000000000-0000000000ffffff
>>>>>> 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
>>>>>> @pci1-io 0000000000000000-0000000000ffffff
>>>>>> 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
>>>>>> @pci1-mem 00000000ff800000-00000000ffffffff
>>>>>> 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
>>>>>>
>>>>>> The guest (which is big endian PPC and I think wotks on real hardware)
>>>>>> writes to 0xf05 in the io region which should be the high byte of the
>>>>>> little endian register but in the acpi code it comes out wrong, instead
>>>>>> of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
>>>>>
>>>>> Looks like a northbridge issue (MV64340).
>>>>> Does Pegasos2 enables bus swapping?
>>>>> See hw/pci-host/mv64361.c:585:
>>>>>
>>>>> static void warn_swap_bit(uint64_t val)
>>>>> {
>>>>> if ((val & 0x3000000ULL) >> 24 != 1) {
>>>>> qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
>>>>> }
>>>>> }
>>>>
>>>> No, guests don't use this feature just byteswap themselves and write little
>>>> endian values to the mapped io region. (Or in this case just write one byte
>>>> of the 16 bit value, it specifically writes 0x28 to 0xf05.) That's why I
>>>> think the device model should not byteswap itself so the acpi regions should
>>>> be declared native endian and let the guest handle it. Some mentions I've
>>>> found say that native endian means don't byteswap, little endian means
>>>> byteswap if vcpu is big endian and big endian means byteswap if vcpu is
>>>> little endian. Since guests already account for this and write little endian
>>>> values to these regions there's no need to byteswap in device model and
>>>> changing to native endian should not affect little endian machines so unless
>>>> there's a better argument I'll try sending a patch.
>>>>
>>>> Regards,
>>>> BALATON Zoltan
>>>
>>> native endian means endian-ness is open-coded in the device handler
>>> itself. I think you just found a bug in memory core.
>>>
>>> static const MemoryRegionOps acpi_pm_cnt_ops = {
>>> .read = acpi_pm_cnt_read,
>>> .write = acpi_pm_cnt_write,
>>> .impl.min_access_size = 2,
>>> .valid.min_access_size = 1,
>>> .valid.max_access_size = 2,
>>> .endianness = DEVICE_LITTLE_ENDIAN,
>>> };
>>>
>>>
>>> Because of that .impl.min_access_size = 2,
>>> the 1 byte write should be converted to a 2 byte
>>> read+2 byte write.
>>>
>>> docs/devel/memory.rst just says:
>>> - .impl.min_access_size, .impl.max_access_size define the access sizes
>>> (in bytes) supported by the *implementation*; other access sizes will be
>>> emulated using the ones available. For example a 4-byte write will be
>>> emulated using four 1-byte writes, if .impl.max_access_size = 1.
>>>
>>>
>>>
>>> Instead what we have is:
>>>
>>> MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
>>> hwaddr addr,
>>> uint64_t data,
>>> MemOp op,
>>> MemTxAttrs attrs)
>>> {
>>> unsigned size = memop_size(op);
>>>
>>> if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
>>> unassigned_mem_write(mr, addr, data, size);
>>> return MEMTX_DECODE_ERROR;
>>> }
>>>
>>> adjust_endianness(mr, &data, op);
>>>
>>>
>>> ---
>>>
>>>
>>> static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)
>>> {
>>> if ((op & MO_BSWAP) != devend_memop(mr->ops->endianness)) {
>>> switch (op & MO_SIZE) {
>>> case MO_8:
>>> break;
>>> case MO_16:
>>> *data = bswap16(*data);
>>> break;
>>> case MO_32:
>>> *data = bswap32(*data);
>>> break;
>>> case MO_64:
>>> *data = bswap64(*data);
>>> break;
>>> default:
>>> g_assert_not_reached();
>>> }
>>> }
>>> }
>>>
>>> so the byte swap is based on size before extending it to
>>> .impl.min_access_size, not after.
>>
>> OK thanks for the analysis, I'll wait what comes out of this.
>>
>>> Also, no read happens which I suspect is also a bug,
>>> but could be harmless ...
>>
>> I did not check if a read happens or not but generally I think that may be
>> another source of bugs if the memory core changes writes to read + write
>> because for some devices a read might have side effects
>
>
> IMHO if reads have side effects then devices should not set .impl.min_access_size
If all this was documented somewhere then you could expect people know how
to use it. I could not find any info on how to correctly use these so had
to guess most of the time. Maybe it's somewhere there but not an obvious
place. The code implementing this is not something that most people read
just expect it to work. Could be useful to make a section about it in the
docs. Maybe some words about it might help in here:
https://www.qemu.org/docs/master/devel/memory.html
> ... but given we did not previously do the read, maybe we should keep
> it that way at least for the time being.
How do you know there was no read before this write? Did you check it?
I've only added a printf in the write method and saw the value was swapped
but did not check if there was a read before that. There are no traces in
these methods so maybe I would not see it unless adding a printf there too.
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 13:51 ` BALATON Zoltan
@ 2021-10-11 15:55 ` Michael S. Tsirkin
2021-10-11 17:47 ` BALATON Zoltan
0 siblings, 1 reply; 14+ messages in thread
From: Michael S. Tsirkin @ 2021-10-11 15:55 UTC (permalink / raw)
To: BALATON Zoltan
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
On Mon, Oct 11, 2021 at 03:51:01PM +0200, BALATON Zoltan wrote:
> > ... but given we did not previously do the read, maybe we should keep
> > it that way at least for the time being.
>
> How do you know there was no read before this write? Did you check it? I've
> only added a printf in the write method and saw the value was swapped but
> did not check if there was a read before that. There are no traces in these
> methods so maybe I would not see it unless adding a printf there too.
All I am saying is that qemu did not convert a write into
a read+write.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 15:55 ` Michael S. Tsirkin
@ 2021-10-11 17:47 ` BALATON Zoltan
0 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2021-10-11 17:47 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
On Mon, 11 Oct 2021, Michael S. Tsirkin wrote:
> On Mon, Oct 11, 2021 at 03:51:01PM +0200, BALATON Zoltan wrote:
>>> ... but given we did not previously do the read, maybe we should keep
>>> it that way at least for the time being.
>>
>> How do you know there was no read before this write? Did you check it? I've
>> only added a printf in the write method and saw the value was swapped but
>> did not check if there was a read before that. There are no traces in these
>> methods so maybe I would not see it unless adding a printf there too.
>
> All I am saying is that qemu did not convert a write into
> a read+write.
OK confirmed that by disabling pm_io_space_update() in hw/isa/vt82c686.c
so the via-pm region is never mapped and then modifying the log messages
for invalid accesses (patch sent separately) I get:
~ # poweroff
Sent SIGKILL to all processes
Requesting system poweroff
pci_cfg_write vt82c686b-usb-uhci 12:3 @0xc0 <- 0x8f00
pci_cfg_write vt82c686b-usb-uhci 12:2 @0xc0 <- 0x8f00
[ 16.498465] reboot: Power down
Invalid write at addr 0xFE000F05, size 1, region '(null)', reason: rejected
Invalid write at addr 0xF05, size 1, region '(null)', reason: rejected
So the guest only tries to write one byte but not sure if the read
generated within memory.c would show up in these logs. I suspect if you
fixed that you'd get all sorts of problems with other device models so the
less likely to break anything fix would be to go back to native endian for
acpi but I wait for what you come up with. I'd like this to be fixed one
way or another for 6.2 and fixing endianness would probably be enough for
that.
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-11 12:19 ` Michael S. Tsirkin
2021-10-11 13:14 ` Jonathan Cameron
2021-10-11 13:27 ` BALATON Zoltan
@ 2021-10-25 15:05 ` BALATON Zoltan
2021-10-25 17:10 ` Michael S. Tsirkin
2 siblings, 1 reply; 14+ messages in thread
From: BALATON Zoltan @ 2021-10-25 15:05 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
[-- Attachment #1: Type: text/plain, Size: 6013 bytes --]
On Mon, 11 Oct 2021, Michael S. Tsirkin wrote:
> On Mon, Oct 11, 2021 at 12:13:55PM +0200, BALATON Zoltan wrote:
>> On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
>>> On 10/10/21 15:24, BALATON Zoltan wrote:
>>>> Hello,
>>>>
>>>> I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
>>>> part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
>>>> and found that the guest writes to ACPI PM1aCNT register come out with
>>>> wrong endianness but not shure why. I have this:
>>>>
>>>> $ qemu-system-ppc -M pegasos2 -monitor stdio
>>>> (qemu) info mtree
>>>> [...]
>>>> memory-region: pci1-io
>>>> 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
>>>> [...]
>>>> 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
>>>> 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
>>>> 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
>>>> 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
>>>>
>>>> memory-region: system
>>>> 0000000000000000-ffffffffffffffff (prio 0, i/o): system
>>>> 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
>>>> 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
>>>> @pci1-mem 0000000080000000-00000000bfffffff
>>>> 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
>>>> @pci0-mem 00000000c0000000-00000000dfffffff
>>>> 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
>>>> 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
>>>> @pci0-io 0000000000000000-0000000000ffffff
>>>> 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
>>>> @pci0-mem 0000000000000000-0000000000ffffff
>>>> 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
>>>> @pci1-mem 0000000000000000-0000000000ffffff
>>>> 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
>>>> @pci1-io 0000000000000000-0000000000ffffff
>>>> 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
>>>> @pci1-mem 00000000ff800000-00000000ffffffff
>>>> 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
>>>>
>>>> The guest (which is big endian PPC and I think wotks on real hardware)
>>>> writes to 0xf05 in the io region which should be the high byte of the
>>>> little endian register but in the acpi code it comes out wrong, instead
>>>> of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
>>>
>>> Looks like a northbridge issue (MV64340).
>>> Does Pegasos2 enables bus swapping?
>>> See hw/pci-host/mv64361.c:585:
>>>
>>> static void warn_swap_bit(uint64_t val)
>>> {
>>> if ((val & 0x3000000ULL) >> 24 != 1) {
>>> qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
>>> }
>>> }
>>
>> No, guests don't use this feature just byteswap themselves and write little
>> endian values to the mapped io region. (Or in this case just write one byte
>> of the 16 bit value, it specifically writes 0x28 to 0xf05.) That's why I
>> think the device model should not byteswap itself so the acpi regions should
>> be declared native endian and let the guest handle it. Some mentions I've
>> found say that native endian means don't byteswap, little endian means
>> byteswap if vcpu is big endian and big endian means byteswap if vcpu is
>> little endian. Since guests already account for this and write little endian
>> values to these regions there's no need to byteswap in device model and
>> changing to native endian should not affect little endian machines so unless
>> there's a better argument I'll try sending a patch.
>>
>> Regards,
>> BALATON Zoltan
Ping? Should I submit a patch changing these acpi regions to NATIVE_ENDIAN
for now as a work around for 6.2 or is there a chance this could be fixed
in some other way before the freeze?
Regards,
BALATON Zoltan
> native endian means endian-ness is open-coded in the device handler
> itself. I think you just found a bug in memory core.
>
> static const MemoryRegionOps acpi_pm_cnt_ops = {
> .read = acpi_pm_cnt_read,
> .write = acpi_pm_cnt_write,
> .impl.min_access_size = 2,
> .valid.min_access_size = 1,
> .valid.max_access_size = 2,
> .endianness = DEVICE_LITTLE_ENDIAN,
> };
>
>
> Because of that .impl.min_access_size = 2,
> the 1 byte write should be converted to a 2 byte
> read+2 byte write.
>
> docs/devel/memory.rst just says:
> - .impl.min_access_size, .impl.max_access_size define the access sizes
> (in bytes) supported by the *implementation*; other access sizes will be
> emulated using the ones available. For example a 4-byte write will be
> emulated using four 1-byte writes, if .impl.max_access_size = 1.
>
>
>
> Instead what we have is:
>
> MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
> hwaddr addr,
> uint64_t data,
> MemOp op,
> MemTxAttrs attrs)
> {
> unsigned size = memop_size(op);
>
> if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
> unassigned_mem_write(mr, addr, data, size);
> return MEMTX_DECODE_ERROR;
> }
>
> adjust_endianness(mr, &data, op);
>
>
> ---
>
>
> static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)
> {
> if ((op & MO_BSWAP) != devend_memop(mr->ops->endianness)) {
> switch (op & MO_SIZE) {
> case MO_8:
> break;
> case MO_16:
> *data = bswap16(*data);
> break;
> case MO_32:
> *data = bswap32(*data);
> break;
> case MO_64:
> *data = bswap64(*data);
> break;
> default:
> g_assert_not_reached();
> }
> }
> }
>
> so the byte swap is based on size before extending it to
> .impl.min_access_size, not after.
>
> Also, no read happens which I suspect is also a bug,
> but could be harmless ...
>
> Paolo, any feedback here?
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: ACPI endianness
2021-10-25 15:05 ` BALATON Zoltan
@ 2021-10-25 17:10 ` Michael S. Tsirkin
0 siblings, 0 replies; 14+ messages in thread
From: Michael S. Tsirkin @ 2021-10-25 17:10 UTC (permalink / raw)
To: BALATON Zoltan
Cc: Igor Mammedov, Philippe Mathieu-Daudé, qemu-devel, pbonzini
On Mon, Oct 25, 2021 at 05:05:46PM +0200, BALATON Zoltan wrote:
> On Mon, 11 Oct 2021, Michael S. Tsirkin wrote:
> > On Mon, Oct 11, 2021 at 12:13:55PM +0200, BALATON Zoltan wrote:
> > > On Mon, 11 Oct 2021, Philippe Mathieu-Daudé wrote:
> > > > On 10/10/21 15:24, BALATON Zoltan wrote:
> > > > > Hello,
> > > > >
> > > > > I'm trying to fix shutdown and reboot on pegasos2 which uses ACPI as
> > > > > part of the VIA VT8231 (similar to and modelled in hw/isa/vt82c686b.c)
> > > > > and found that the guest writes to ACPI PM1aCNT register come out with
> > > > > wrong endianness but not shure why. I have this:
> > > > >
> > > > > $ qemu-system-ppc -M pegasos2 -monitor stdio
> > > > > (qemu) info mtree
> > > > > [...]
> > > > > memory-region: pci1-io
> > > > > 0000000000000000-000000000000ffff (prio 0, i/o): pci1-io
> > > > > [...]
> > > > > 0000000000000f00-0000000000000f7f (prio 0, i/o): via-pm
> > > > > 0000000000000f00-0000000000000f03 (prio 0, i/o): acpi-evt
> > > > > 0000000000000f04-0000000000000f05 (prio 0, i/o): acpi-cnt
> > > > > 0000000000000f08-0000000000000f0b (prio 0, i/o): acpi-tmr
> > > > >
> > > > > memory-region: system
> > > > > 0000000000000000-ffffffffffffffff (prio 0, i/o): system
> > > > > 0000000000000000-000000001fffffff (prio 0, ram): pegasos2.ram
> > > > > 0000000080000000-00000000bfffffff (prio 0, i/o): alias pci1-mem0-win
> > > > > @pci1-mem 0000000080000000-00000000bfffffff
> > > > > 00000000c0000000-00000000dfffffff (prio 0, i/o): alias pci0-mem0-win
> > > > > @pci0-mem 00000000c0000000-00000000dfffffff
> > > > > 00000000f1000000-00000000f100ffff (prio 0, i/o): mv64361
> > > > > 00000000f8000000-00000000f8ffffff (prio 0, i/o): alias pci0-io-win
> > > > > @pci0-io 0000000000000000-0000000000ffffff
> > > > > 00000000f9000000-00000000f9ffffff (prio 0, i/o): alias pci0-mem1-win
> > > > > @pci0-mem 0000000000000000-0000000000ffffff
> > > > > 00000000fd000000-00000000fdffffff (prio 0, i/o): alias pci1-mem1-win
> > > > > @pci1-mem 0000000000000000-0000000000ffffff
> > > > > 00000000fe000000-00000000feffffff (prio 0, i/o): alias pci1-io-win
> > > > > @pci1-io 0000000000000000-0000000000ffffff
> > > > > 00000000ff800000-00000000ffffffff (prio 0, i/o): alias pci1-mem3-win
> > > > > @pci1-mem 00000000ff800000-00000000ffffffff
> > > > > 00000000fff00000-00000000fff7ffff (prio 0, rom): pegasos2.rom
> > > > >
> > > > > The guest (which is big endian PPC and I think wotks on real hardware)
> > > > > writes to 0xf05 in the io region which should be the high byte of the
> > > > > little endian register but in the acpi code it comes out wrong, instead
> > > > > of 0x2800 I get in acpi_pm1_cnt_write: val=0x28
> > > >
> > > > Looks like a northbridge issue (MV64340).
> > > > Does Pegasos2 enables bus swapping?
> > > > See hw/pci-host/mv64361.c:585:
> > > >
> > > > static void warn_swap_bit(uint64_t val)
> > > > {
> > > > if ((val & 0x3000000ULL) >> 24 != 1) {
> > > > qemu_log_mask(LOG_UNIMP, "%s: Data swap not implemented", __func__);
> > > > }
> > > > }
> > >
> > > No, guests don't use this feature just byteswap themselves and write little
> > > endian values to the mapped io region. (Or in this case just write one byte
> > > of the 16 bit value, it specifically writes 0x28 to 0xf05.) That's why I
> > > think the device model should not byteswap itself so the acpi regions should
> > > be declared native endian and let the guest handle it. Some mentions I've
> > > found say that native endian means don't byteswap, little endian means
> > > byteswap if vcpu is big endian and big endian means byteswap if vcpu is
> > > little endian. Since guests already account for this and write little endian
> > > values to these regions there's no need to byteswap in device model and
> > > changing to native endian should not affect little endian machines so unless
> > > there's a better argument I'll try sending a patch.
> > >
> > > Regards,
> > > BALATON Zoltan
>
> Ping? Should I submit a patch changing these acpi regions to NATIVE_ENDIAN
> for now as a work around for 6.2 or is there a chance this could be fixed in
> some other way before the freeze?
>
> Regards,
> BALATON Zoltan
Paolo, did you say you will look into fixing this?
We don't want more NATIVE_ENDIAN things, do we?
> > native endian means endian-ness is open-coded in the device handler
> > itself. I think you just found a bug in memory core.
> >
> > static const MemoryRegionOps acpi_pm_cnt_ops = {
> > .read = acpi_pm_cnt_read,
> > .write = acpi_pm_cnt_write,
> > .impl.min_access_size = 2,
> > .valid.min_access_size = 1,
> > .valid.max_access_size = 2,
> > .endianness = DEVICE_LITTLE_ENDIAN,
> > };
> >
> >
> > Because of that .impl.min_access_size = 2,
> > the 1 byte write should be converted to a 2 byte
> > read+2 byte write.
> >
> > docs/devel/memory.rst just says:
> > - .impl.min_access_size, .impl.max_access_size define the access sizes
> > (in bytes) supported by the *implementation*; other access sizes will be
> > emulated using the ones available. For example a 4-byte write will be
> > emulated using four 1-byte writes, if .impl.max_access_size = 1.
> >
> >
> >
> > Instead what we have is:
> >
> > MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
> > hwaddr addr,
> > uint64_t data,
> > MemOp op,
> > MemTxAttrs attrs)
> > {
> > unsigned size = memop_size(op);
> >
> > if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
> > unassigned_mem_write(mr, addr, data, size);
> > return MEMTX_DECODE_ERROR;
> > }
> >
> > adjust_endianness(mr, &data, op);
> >
> >
> > ---
> >
> >
> > static void adjust_endianness(MemoryRegion *mr, uint64_t *data, MemOp op)
> > {
> > if ((op & MO_BSWAP) != devend_memop(mr->ops->endianness)) {
> > switch (op & MO_SIZE) {
> > case MO_8:
> > break;
> > case MO_16:
> > *data = bswap16(*data);
> > break;
> > case MO_32:
> > *data = bswap32(*data);
> > break;
> > case MO_64:
> > *data = bswap64(*data);
> > break;
> > default:
> > g_assert_not_reached();
> > }
> > }
> > }
> >
> > so the byte swap is based on size before extending it to
> > .impl.min_access_size, not after.
> >
> > Also, no read happens which I suspect is also a bug,
> > but could be harmless ...
> >
> > Paolo, any feedback here?
> >
> >
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2021-10-25 17:11 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-10 13:24 ACPI endianness BALATON Zoltan
2021-10-10 14:03 ` Michael S. Tsirkin
2021-10-10 14:26 ` BALATON Zoltan
2021-10-11 5:52 ` Philippe Mathieu-Daudé
2021-10-11 10:13 ` BALATON Zoltan
2021-10-11 12:19 ` Michael S. Tsirkin
2021-10-11 13:14 ` Jonathan Cameron
2021-10-11 13:27 ` BALATON Zoltan
2021-10-11 13:34 ` Michael S. Tsirkin
2021-10-11 13:51 ` BALATON Zoltan
2021-10-11 15:55 ` Michael S. Tsirkin
2021-10-11 17:47 ` BALATON Zoltan
2021-10-25 15:05 ` BALATON Zoltan
2021-10-25 17:10 ` Michael S. Tsirkin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.