qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 04/13] vt82c686: Fix up power management io base and confi


From: Philippe Mathieu-Daudé
Subject: Re: [PATCH v2 04/13] vt82c686: Fix up power management io base and config
Date: Sat, 20 Feb 2021 19:58:23 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.7.0

On 1/9/21 9:16 PM, BALATON Zoltan wrote:
> Similar to the SMBus io registers there is a power management io range
> that is set via similar base address reg and enable bit. Some handling
> of this was already there but with several problems: using the wrong
> registers and bits, wrong size range, not acually updating mapping and
> handling reset correctly, nor emulating any of the actual io
> registers. Some of these errors are fixed up here.
> 
> After this patch we use the correct base address register, enable bit
> and region size and allow guests to map/unmap this region and
> correctly reset all registers to default values on reset but we still
> don't emulate any of the registers in this range.

^^ One change,

vv Another change.

> Previously just an empty RAM region was mapped on realize, now we add
> an empty io range logging access instead. I think the pm timer should
> be hooked up here but not sure guests need it. PMON on fuloong2e sets
> a base address but does not seem to enable region; the pegasos2
> firmware pokes some regs but continues anyway so don't know if
> anything would make use of these facilities. Therefore this is just a
> clean up of previous state for now and not intending to fully
> implement missing functionality which could be done later if some
> guests need it.

I split your patch in 2.

> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/isa/trace-events |  2 ++
>  hw/isa/vt82c686.c   | 56 ++++++++++++++++++++++++++++++++-------------
>  2 files changed, 42 insertions(+), 16 deletions(-)
> 
> diff --git a/hw/isa/trace-events b/hw/isa/trace-events
> index d267d3e652..641d69eedf 100644
> --- a/hw/isa/trace-events
> +++ b/hw/isa/trace-events
> @@ -17,5 +17,7 @@ apm_io_write(uint8_t addr, uint8_t val) "write addr=0x%x 
> val=0x%02x"
>  # vt82c686.c
>  via_isa_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 
> 0x%x"
>  via_pm_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 
> 0x%x"
> +via_pm_io_read(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 
> 0x%x"
> +via_pm_io_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x 
> len 0x%x"
>  via_superio_read(uint8_t addr, uint8_t val) "addr 0x%x val 0x%x"
>  via_superio_write(uint8_t addr, uint32_t val) "addr 0x%x val 0x%x"
> diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
> index 9c4d153022..fc2a1f4430 100644
> --- a/hw/isa/vt82c686.c
> +++ b/hw/isa/vt82c686.c
> @@ -39,14 +39,11 @@ struct VT686PMState {
>  
>  static void pm_io_space_update(VT686PMState *s)
>  {
> -    uint32_t pm_io_base;
> -
> -    pm_io_base = pci_get_long(s->dev.config + 0x40);
> -    pm_io_base &= 0xffc0;
> +    uint32_t pmbase = pci_get_long(s->dev.config + 0x48) & 0xff80UL;

0x48 is Power Management I/O Base,
0xff80UL is mask for Power Management I/O Register Base Address,
OK.

>      memory_region_transaction_begin();
> -    memory_region_set_enabled(&s->io, s->dev.config[0x80] & 1);
> -    memory_region_set_address(&s->io, pm_io_base);
> +    memory_region_set_address(&s->io, pmbase);
> +    memory_region_set_enabled(&s->io, s->dev.config[0x41] & BIT(7));

0x41 is General Configuration 1,
bit 7 is I/O Enable for ACPI I/O Base,
OK.

>      memory_region_transaction_commit();
>  }
>  
> @@ -92,6 +89,13 @@ static void pm_write_config(PCIDevice *d, uint32_t addr, 
> uint32_t val, int len)
>  
>      trace_via_pm_write(addr, val, len);
>      pci_default_write_config(d, addr, val, len);
> +    if (ranges_overlap(addr, len, 0x48, 4)) {
> +        uint32_t v = pci_get_long(s->dev.config + 0x48);
> +        pci_set_long(s->dev.config + 0x48, (v & 0xff80UL) | 1);

bit 0 is always set, OK.

> +    }
> +    if (range_covers_byte(addr, len, 0x41)) {

Access to General Configuration. Why not use both registers?

       if (ranges_overlap(addr, len, 0x40, 2)) {

> +        pm_io_space_update(s);
> +    }
>      if (ranges_overlap(addr, len, 0x90, 4)) {
>          uint32_t v = pci_get_long(s->dev.config + 0x90);
>          pci_set_long(s->dev.config + 0x90, (v & 0xfff0UL) | 1);
> @@ -102,6 +106,27 @@ static void pm_write_config(PCIDevice *d, uint32_t addr, 
> uint32_t val, int len)
>      }
>  }
>  
> +static void pm_io_write(void *op, hwaddr addr, uint64_t data, unsigned size)
> +{
> +    trace_via_pm_io_write(addr, data, size);
> +}
> +
> +static uint64_t pm_io_read(void *op, hwaddr addr, unsigned size)
> +{
> +    trace_via_pm_io_read(addr, 0, size);
> +    return 0;
> +}
> +
> +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,
> +    },
> +};
> +
>  static void pm_update_sci(VT686PMState *s)
>  {
>      int sci_level, pmsts;
> @@ -128,35 +153,34 @@ static void vt82c686b_pm_reset(DeviceState *d)
>  {
>      VT686PMState *s = VT82C686B_PM(d);
>  
> +    memset(s->dev.config + PCI_CONFIG_HEADER_SIZE, 0,
> +           PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE);
> +    /* Power Management IO base */
> +    pci_set_long(s->dev.config + 0x48, 1);

bit 1 always set, OK.

>      /* SMBus IO base */
>      pci_set_long(s->dev.config + 0x90, 1);
> -    s->dev.config[0xd2] = 0;
>  
> +    pm_io_space_update(s);
>      smb_io_space_update(s);
>  }
>  
>  static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp)
>  {
>      VT686PMState *s = VT82C686B_PM(dev);
> -    uint8_t *pci_conf;
>  
> -    pci_conf = s->dev.config;
> -    pci_set_word(pci_conf + PCI_COMMAND, 0);
> -    pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK |
> +    pci_set_word(dev->config + PCI_STATUS, PCI_STATUS_FAST_BACK |
>                   PCI_STATUS_DEVSEL_MEDIUM);
>  
> -    /* 0x48-0x4B is Power Management I/O Base */
> -    pci_set_long(pci_conf + 0x48, 0x00000001);
> -
>      pm_smbus_init(DEVICE(s), &s->smb, false);
>      memory_region_add_subregion(pci_address_space_io(dev), 0, &s->smb.io);
>      memory_region_set_enabled(&s->smb.io, false);
>  
>      apm_init(dev, &s->apm, NULL, s);
>  
> -    memory_region_init(&s->io, OBJECT(dev), "vt82c686-pm", 64);
> +    memory_region_init_io(&s->io, OBJECT(dev), &pm_io_ops, s,
> +                          "vt82c686-pm", 0x100);

Section "Configuration Space Power Management Registers" describes:

  4B-48: Power Mgmt I/O Base (256 Bytes)

Section "Offset 4B-48 – Power Management I/O Base" describes:

  Port Address for the base of the 128-byte Power
  Management I/O Register block, corresponding to
  AD[15:7].

At least we are sure 64 bytes isn't enough indeed, but is it 128 or 256?

> +    memory_region_add_subregion(pci_address_space_io(dev), 0, &s->io);
>      memory_region_set_enabled(&s->io, false);
> -    memory_region_add_subregion(get_system_io(), 0, &s->io);
>  
>      acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
>      acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);

TBH it took me almost 1h to review this single patch.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]