Hi Andre, On 2/18/21 11:48 AM, Andre Przywara wrote: > On Thu, 18 Feb 2021 11:17:58 +0000 > Alexandru Elisei <alexandru.elisei@xxxxxxx> wrote: > >> Hi Andre, >> >> On 2/18/21 10:34 AM, Andre Przywara wrote: >>> On Thu, 11 Feb 2021 17:23:13 +0000 >>> Alexandru Elisei <alexandru.elisei@xxxxxxx> wrote: >>> >>>> Hi Andre, >>>> >>>> On 12/10/20 2:28 PM, Andre Przywara wrote: >>>>> With the planned retirement of the special ioport emulation code, we >>>>> need to provide an emulation function compatible with the MMIO >>>>> prototype. >>>>> >>>>> Adjust the trap handler to use that new function, and provide shims to >>>>> implement the old ioport interface, for now. >>>>> >>>>> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> >>>>> --- >>>>> hw/i8042.c | 68 +++++++++++++++++++++++++++--------------------------- >>>>> 1 file changed, 34 insertions(+), 34 deletions(-) >>>>> >>>>> diff --git a/hw/i8042.c b/hw/i8042.c >>>>> index 36ee183f..eb1f9d28 100644 >>>>> --- a/hw/i8042.c >>>>> +++ b/hw/i8042.c >>>>> @@ -292,52 +292,52 @@ static void kbd_reset(void) >>>>> }; >>>>> } >>>>> >>>>> -/* >>>>> - * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64) >>>>> - */ >>>>> -static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) >>>>> +static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, >>>>> + u8 is_write, void *ptr) >>>>> { >>>>> - switch (port) { >>>>> - case I8042_COMMAND_REG: { >>>>> - u8 value = kbd_read_status(); >>>>> - ioport__write8(data, value); >>>>> + u8 value; >>>>> + >>>>> + if (is_write) >>>>> + value = ioport__read8(data); >>>>> + >>>>> + switch (addr) { >>>>> + case I8042_COMMAND_REG: >>>>> + if (is_write) >>>>> + kbd_write_command(vcpu->kvm, value); >>>>> + else >>>>> + value = kbd_read_status(); >>>>> break; >>>>> - } >>>>> - case I8042_DATA_REG: { >>>>> - u8 value = kbd_read_data(); >>>>> - ioport__write8(data, value); >>>>> + case I8042_DATA_REG: >>>>> + if (is_write) >>>>> + kbd_write_data(value); >>>>> + else >>>>> + value = kbd_read_data(); >>>>> break; >>>>> - } >>>>> - case I8042_PORT_B_REG: { >>>>> - ioport__write8(data, 0x20); >>>>> + case I8042_PORT_B_REG: >>>>> + if (!is_write) >>>>> + value = 0x20; >>>>> break; >>>>> - } >>>>> default: >>>>> - return false; >>>>> + return; >>>> Any particular reason for removing the false return value? I don't see it >>>> mentioned in the commit message. Otherwise this is identical to the two functions >>>> it replaces. >>> Because the MMIO handler prototype is void, in contrast to the PIO one. >>> Since on returning "false" we only seem to panic kvmtool, this is of >>> quite limited use, I'd say. >> Actually, in ioport.c::kvm__emulate_io(), if kvm->cfg.ioport_debug is true, it >> will print an error and then panic in kvm_cpu__start(); otherwise the error is >> silently ignored. serial.c is another device where an unknown register returns >> false. In rtc.c, the unknown register is ignored. cfi_flash.c prints debugging >> information. So I guess kvmtool implements all possible methods of handling an >> unknown register *at the same time*, so it's up to you how you want to handle it. > Well, the MMIO prototype we are going to use is void anyway, so it's > just one patch earlier that we get this new behaviour. > For handling MMIO errors: > - Hardware MMIO doesn't have a back channel: if the MMIO write triggers > some error condition, the device would need to deal with it (setting > internal error state, ignore, etc.). On some systems the device could > throw some kind of bus error or SError, but this is a rather drastic > measure, and is certainly not exercised by those ancient devices. > - Any kind of error reporting which can be triggered by a guest is > frowned upon: it could spam the console or some log file, and so > impact host operation. At the end an administrator can't do much about > it, anyway. > - Which leaves the only use to some kvmtool developer debugging some > device emulation or investigating weird guest behaviour. And in this > case we can more easily have a debug message *inside* the device > emulation code, can't we? That's what I had in mind, debugging messages in the device emulation. If the guest can access an unknown register offset this can mean one of two things in my opinion: the emulated device registered a memory region bigger that necessary or the emulated device is not handling all device registers. But that's a subject for another series. Thanks, Alex > > And since the MMIO handler prototype is void, we have no choice anyway, > at least not without another huge (and pointless) series to change > those user as well ;-) > > Cheers, > Andre > >>>>> } >>>>> >>>>> + if (!is_write) >>>>> + ioport__write8(data, value); >>>>> +} >>>>> + >>>>> +/* >>>>> + * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64) >>>>> + */ >>>>> +static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) >>>>> +{ >>>>> + kbd_io(vcpu, port, data, size, false, NULL); >>>> is_write is an u8, not a bool. >>> Right, will fix this. >>> >>>> I never could wrap my head around the ioport convention of "in" (read) and "out" >>>> (write). To be honest, changing is_write changed to an enum so it's crystal clear >>>> what is happening would help with that a lot, but I guess that's a separate patch. >>> "in" and "out" are the x86 assembly mnemonics, but it's indeed >>> confusing, because the device side has a different view (CPU "in" means >>> pushing data "out" of the device). I usually look at the code to see >>> what it's actually meant to do. >>> So yeah, I feel like a lot of those device emulations could use >>> some update. but that's indeed something for another day. >> Agreed. >> >> Thanks, >> >> Alex >> >>> Cheers, >>> Andre >>> >>>>> + >>>>> return true; >>>>> } >>>>> >>>>> static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) >>>>> { >>>>> - switch (port) { >>>>> - case I8042_COMMAND_REG: { >>>>> - u8 value = ioport__read8(data); >>>>> - kbd_write_command(vcpu->kvm, value); >>>>> - break; >>>>> - } >>>>> - case I8042_DATA_REG: { >>>>> - u8 value = ioport__read8(data); >>>>> - kbd_write_data(value); >>>>> - break; >>>>> - } >>>>> - case I8042_PORT_B_REG: { >>>>> - break; >>>>> - } >>>>> - default: >>>>> - return false; >>>>> - } >>>>> + kbd_io(vcpu, port, data, size, true, NULL); >>>>> >>>>> return true; >>>>> }