diff mbox series

hw/i386/acpi-build: Return a pre-computed _PRT table

Message ID 20240417135608.2613586-1-ribalda@chromium.org
State New
Headers show
Series hw/i386/acpi-build: Return a pre-computed _PRT table | expand

Commit Message

Ricardo Ribalda April 17, 2024, 1:53 p.m. UTC
When qemu runs without kvm acceleration the ACPI executions take a great
amount of time. If they take more than the default time (30sec), the
ACPI calls fail and the system might not behave correctly.

Now the _PRT table is computed on the fly. We can drastically reduce the
execution of the _PRT method if we return a pre-computed table.

Without this patch:
[   51.343484] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
[   51.527032] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
[   51.530049] virtio-pci 0000:00:02.0: can't derive routing for PCI INT A
[   51.530797] virtio-pci 0000:00:02.0: PCI INT A: no GSI
[   81.922901] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
[   82.103534] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
[   82.106088] virtio-pci 0000:00:04.0: can't derive routing for PCI INT A
[   82.106761] virtio-pci 0000:00:04.0: PCI INT A: no GSI
[  112.192568] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
[  112.486687] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
[  112.489554] virtio-pci 0000:00:05.0: can't derive routing for PCI INT A
[  112.490027] virtio-pci 0000:00:05.0: PCI INT A: no GSI
[  142.559448] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
[  142.718596] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
[  142.722889] virtio-pci 0000:00:06.0: can't derive routing for PCI INT A
[  142.724578] virtio-pci 0000:00:06.0: PCI INT A: no GSI

With this patch:
[   22.938076] ACPI: \_SB_.LNKB: Enabled at IRQ 10
[   24.214002] ACPI: \_SB_.LNKD: Enabled at IRQ 11
[   25.465170] ACPI: \_SB_.LNKA: Enabled at IRQ 10
[   27.944920] ACPI: \_SB_.LNKC: Enabled at IRQ 11

ACPI disassembly:
        Scope (PCI0)
        {
            Method (_PRT, 0, NotSerialized)  // _PRT: PCI Routing Table
            {
                Return (Package (0x80)
                {
                    Package (0x04)
                    {
                        0xFFFF,
                        Zero,
                        LNKD,
                        Zero
                    },

                    Package (0x04)
                    {
                        0xFFFF,
                        One,
                        LNKA,
                        Zero
                    },

                    Package (0x04)
                    {
                        0xFFFF,
                        0x02,
                        LNKB,
                        Zero
                    },

                    Package (0x04)
                    {
                        0xFFFF,
                        0x03,
                        LNKC,
                        Zero
                    },

                    Package (0x04)
                    {
                        0x0001FFFF,
                        Zero,
                        LNKS,
                        Zero
                    },
Context: https://lore.kernel.org/virtualization/20240417145544.38d7b482@imammedo.users.ipa.redhat.com/T/#t

Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
---
 hw/i386/acpi-build.c | 118 ++++++++-----------------------------------
 1 file changed, 21 insertions(+), 97 deletions(-)

Comments

Ricardo Ribalda May 3, 2024, 9:09 a.m. UTC | #1
Friendly ping

On Wed, 17 Apr 2024 at 15:56, Ricardo Ribalda <ribalda@chromium.org> wrote:
>
> When qemu runs without kvm acceleration the ACPI executions take a great
> amount of time. If they take more than the default time (30sec), the
> ACPI calls fail and the system might not behave correctly.
>
> Now the _PRT table is computed on the fly. We can drastically reduce the
> execution of the _PRT method if we return a pre-computed table.
>
> Without this patch:
> [   51.343484] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> [   51.527032] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> [   51.530049] virtio-pci 0000:00:02.0: can't derive routing for PCI INT A
> [   51.530797] virtio-pci 0000:00:02.0: PCI INT A: no GSI
> [   81.922901] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> [   82.103534] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> [   82.106088] virtio-pci 0000:00:04.0: can't derive routing for PCI INT A
> [   82.106761] virtio-pci 0000:00:04.0: PCI INT A: no GSI
> [  112.192568] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> [  112.486687] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> [  112.489554] virtio-pci 0000:00:05.0: can't derive routing for PCI INT A
> [  112.490027] virtio-pci 0000:00:05.0: PCI INT A: no GSI
> [  142.559448] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> [  142.718596] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> [  142.722889] virtio-pci 0000:00:06.0: can't derive routing for PCI INT A
> [  142.724578] virtio-pci 0000:00:06.0: PCI INT A: no GSI
>
> With this patch:
> [   22.938076] ACPI: \_SB_.LNKB: Enabled at IRQ 10
> [   24.214002] ACPI: \_SB_.LNKD: Enabled at IRQ 11
> [   25.465170] ACPI: \_SB_.LNKA: Enabled at IRQ 10
> [   27.944920] ACPI: \_SB_.LNKC: Enabled at IRQ 11
>
> ACPI disassembly:
>         Scope (PCI0)
>         {
>             Method (_PRT, 0, NotSerialized)  // _PRT: PCI Routing Table
>             {
>                 Return (Package (0x80)
>                 {
>                     Package (0x04)
>                     {
>                         0xFFFF,
>                         Zero,
>                         LNKD,
>                         Zero
>                     },
>
>                     Package (0x04)
>                     {
>                         0xFFFF,
>                         One,
>                         LNKA,
>                         Zero
>                     },
>
>                     Package (0x04)
>                     {
>                         0xFFFF,
>                         0x02,
>                         LNKB,
>                         Zero
>                     },
>
>                     Package (0x04)
>                     {
>                         0xFFFF,
>                         0x03,
>                         LNKC,
>                         Zero
>                     },
>
>                     Package (0x04)
>                     {
>                         0x0001FFFF,
>                         Zero,
>                         LNKS,
>                         Zero
>                     },
> Context: https://lore.kernel.org/virtualization/20240417145544.38d7b482@imammedo.users.ipa.redhat.com/T/#t
>
> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
> ---
>  hw/i386/acpi-build.c | 118 ++++++++-----------------------------------
>  1 file changed, 21 insertions(+), 97 deletions(-)
>
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 53f804ac16..4c14d39173 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -725,40 +725,7 @@ static Aml *aml_pci_pdsm(void)
>      return method;
>  }
>
> -/**
> - * build_prt_entry:
> - * @link_name: link name for PCI route entry
> - *
> - * build AML package containing a PCI route entry for @link_name
> - */
> -static Aml *build_prt_entry(const char *link_name)
> -{
> -    Aml *a_zero = aml_int(0);
> -    Aml *pkg = aml_package(4);
> -    aml_append(pkg, a_zero);
> -    aml_append(pkg, a_zero);
> -    aml_append(pkg, aml_name("%s", link_name));
> -    aml_append(pkg, a_zero);
> -    return pkg;
> -}
> -
> -/*
> - * initialize_route - Initialize the interrupt routing rule
> - * through a specific LINK:
> - *  if (lnk_idx == idx)
> - *      route using link 'link_name'
> - */
> -static Aml *initialize_route(Aml *route, const char *link_name,
> -                             Aml *lnk_idx, int idx)
> -{
> -    Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
> -    Aml *pkg = build_prt_entry(link_name);
> -
> -    aml_append(if_ctx, aml_store(pkg, route));
> -
> -    return if_ctx;
> -}
> -
> +#define N_ROUTES 128
>  /*
>   * build_prt - Define interrupt rounting rules
>   *
> @@ -771,74 +738,31 @@ static Aml *initialize_route(Aml *route, const char *link_name,
>   */
>  static Aml *build_prt(bool is_pci0_prt)
>  {
> -    Aml *method, *while_ctx, *pin, *res;
> +    Aml *rt_pkg, *method;
> +    const char link_name[][2] = {"D", "A", "B", "C"};
> +    int i;
>
>      method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
> -    res = aml_local(0);
> -    pin = aml_local(1);
> -    aml_append(method, aml_store(aml_package(128), res));
> -    aml_append(method, aml_store(aml_int(0), pin));
> +    rt_pkg = aml_varpackage(N_ROUTES);
>
> -    /* while (pin < 128) */
> -    while_ctx = aml_while(aml_lless(pin, aml_int(128)));
> -    {
> -        Aml *slot = aml_local(2);
> -        Aml *lnk_idx = aml_local(3);
> -        Aml *route = aml_local(4);
> -
> -        /* slot = pin >> 2 */
> -        aml_append(while_ctx,
> -                   aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
> -        /* lnk_idx = (slot + pin) & 3 */
> -        aml_append(while_ctx,
> -            aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
> -                      lnk_idx));
> -
> -        /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3  */
> -        aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
> -        if (is_pci0_prt) {
> -            Aml *if_device_1, *if_pin_4, *else_pin_4;
> -
> -            /* device 1 is the power-management device, needs SCI */
> -            if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
> -            {
> -                if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
> -                {
> -                    aml_append(if_pin_4,
> -                        aml_store(build_prt_entry("LNKS"), route));
> -                }
> -                aml_append(if_device_1, if_pin_4);
> -                else_pin_4 = aml_else();
> -                {
> -                    aml_append(else_pin_4,
> -                        aml_store(build_prt_entry("LNKA"), route));
> -                }
> -                aml_append(if_device_1, else_pin_4);
> -            }
> -            aml_append(while_ctx, if_device_1);
> -        } else {
> -            aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
> +    for (i = 0; i < N_ROUTES; i++) {
> +        Aml *pkg = aml_package(4);
> +        const char *name;
> +
> +        name = link_name[((i >> 2) + i) & 3];
> +
> +        if (is_pci0_prt && i == 4) {
> +            name = "S";
>          }
> -        aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
> -        aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
> -
> -        /* route[0] = 0x[slot]FFFF */
> -        aml_append(while_ctx,
> -            aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
> -                             NULL),
> -                      aml_index(route, aml_int(0))));
> -        /* route[1] = pin & 3 */
> -        aml_append(while_ctx,
> -            aml_store(aml_and(pin, aml_int(3), NULL),
> -                      aml_index(route, aml_int(1))));
> -        /* res[pin] = route */
> -        aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
> -        /* pin++ */
> -        aml_append(while_ctx, aml_increment(pin));
> +
> +        aml_append(pkg, aml_int((i << 14) | 0xFFFF));
> +        aml_append(pkg, aml_int(i & 3));
> +        aml_append(pkg, aml_name("LNK%s", name));
> +        aml_append(pkg, aml_int(0));
> +        aml_append(rt_pkg, pkg);
>      }
> -    aml_append(method, while_ctx);
> -    /* return res*/
> -    aml_append(method, aml_return(res));
> +
> +    aml_append(method, aml_return(rt_pkg));
>
>      return method;
>  }
> --
> 2.44.0.683.g7961c838ac-goog
>
Igor Mammedov May 30, 2024, 1:50 p.m. UTC | #2
On Fri, 3 May 2024 11:09:47 +0200
Ricardo Ribalda <ribalda@chromium.org> wrote:

> Friendly ping
> 
> On Wed, 17 Apr 2024 at 15:56, Ricardo Ribalda <ribalda@chromium.org> wrote:
> >
> > When qemu runs without kvm acceleration the ACPI executions take a great
> > amount of time. If they take more than the default time (30sec), the
> > ACPI calls fail and the system might not behave correctly.
> >
> > Now the _PRT table is computed on the fly. We can drastically reduce the
> > execution of the _PRT method if we return a pre-computed table.

It's heavily depends on used hw or resources if it's running inside VM,
one can always find a slow enough environment where above stated limit
will not be sufficient regardless of what QEMU does.
Correct approach would be to fix guest OS timeout issue so it won't
timeout if there is a progress.

As for the patch, question is what DSDT size difference is between
static _PRT version and the current dynamic one?
(if it shrinks _PRT, I'm all for it)

Also see tests/qtest/bios-tables-test.c
In the top of process to follow when one touches ACPI tables
to avoid breaking tests. 



> > Without this patch:
> > [   51.343484] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> > [   51.527032] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> > [   51.530049] virtio-pci 0000:00:02.0: can't derive routing for PCI INT A
> > [   51.530797] virtio-pci 0000:00:02.0: PCI INT A: no GSI
> > [   81.922901] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> > [   82.103534] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> > [   82.106088] virtio-pci 0000:00:04.0: can't derive routing for PCI INT A
> > [   82.106761] virtio-pci 0000:00:04.0: PCI INT A: no GSI
> > [  112.192568] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> > [  112.486687] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> > [  112.489554] virtio-pci 0000:00:05.0: can't derive routing for PCI INT A
> > [  112.490027] virtio-pci 0000:00:05.0: PCI INT A: no GSI
> > [  142.559448] ACPI Error: Aborting method \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/psparse-529)
> > [  142.718596] ACPI Error: Method execution failed \_SB.PCI0._PRT due to previous error (AE_AML_LOOP_TIMEOUT) (20230628/uteval-68)
> > [  142.722889] virtio-pci 0000:00:06.0: can't derive routing for PCI INT A
> > [  142.724578] virtio-pci 0000:00:06.0: PCI INT A: no GSI
> >
> > With this patch:
> > [   22.938076] ACPI: \_SB_.LNKB: Enabled at IRQ 10
> > [   24.214002] ACPI: \_SB_.LNKD: Enabled at IRQ 11
> > [   25.465170] ACPI: \_SB_.LNKA: Enabled at IRQ 10
> > [   27.944920] ACPI: \_SB_.LNKC: Enabled at IRQ 11
> >
> > ACPI disassembly:
> >         Scope (PCI0)
> >         {
> >             Method (_PRT, 0, NotSerialized)  // _PRT: PCI Routing Table
> >             {
> >                 Return (Package (0x80)
> >                 {
> >                     Package (0x04)
> >                     {
> >                         0xFFFF,
> >                         Zero,
> >                         LNKD,
> >                         Zero
> >                     },
> >
> >                     Package (0x04)
> >                     {
> >                         0xFFFF,
> >                         One,
> >                         LNKA,
> >                         Zero
> >                     },
> >
> >                     Package (0x04)
> >                     {
> >                         0xFFFF,
> >                         0x02,
> >                         LNKB,
> >                         Zero
> >                     },
> >
> >                     Package (0x04)
> >                     {
> >                         0xFFFF,
> >                         0x03,
> >                         LNKC,
> >                         Zero
> >                     },
> >
> >                     Package (0x04)
> >                     {
> >                         0x0001FFFF,
> >                         Zero,
> >                         LNKS,
> >                         Zero
> >                     },
> > Context: https://lore.kernel.org/virtualization/20240417145544.38d7b482@imammedo.users.ipa.redhat.com/T/#t
> >
> > Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
> > ---
> >  hw/i386/acpi-build.c | 118 ++++++++-----------------------------------
> >  1 file changed, 21 insertions(+), 97 deletions(-)
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 53f804ac16..4c14d39173 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -725,40 +725,7 @@ static Aml *aml_pci_pdsm(void)
> >      return method;
> >  }
> >
> > -/**
> > - * build_prt_entry:
> > - * @link_name: link name for PCI route entry
> > - *
> > - * build AML package containing a PCI route entry for @link_name
> > - */
> > -static Aml *build_prt_entry(const char *link_name)
> > -{
> > -    Aml *a_zero = aml_int(0);
> > -    Aml *pkg = aml_package(4);
> > -    aml_append(pkg, a_zero);
> > -    aml_append(pkg, a_zero);
> > -    aml_append(pkg, aml_name("%s", link_name));
> > -    aml_append(pkg, a_zero);
> > -    return pkg;
> > -}
> > -
> > -/*
> > - * initialize_route - Initialize the interrupt routing rule
> > - * through a specific LINK:
> > - *  if (lnk_idx == idx)
> > - *      route using link 'link_name'
> > - */
> > -static Aml *initialize_route(Aml *route, const char *link_name,
> > -                             Aml *lnk_idx, int idx)
> > -{
> > -    Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
> > -    Aml *pkg = build_prt_entry(link_name);
> > -
> > -    aml_append(if_ctx, aml_store(pkg, route));
> > -
> > -    return if_ctx;
> > -}
> > -
> > +#define N_ROUTES 128
> >  /*
> >   * build_prt - Define interrupt rounting rules
> >   *
> > @@ -771,74 +738,31 @@ static Aml *initialize_route(Aml *route, const char *link_name,
> >   */
> >  static Aml *build_prt(bool is_pci0_prt)
> >  {
> > -    Aml *method, *while_ctx, *pin, *res;
> > +    Aml *rt_pkg, *method;
> > +    const char link_name[][2] = {"D", "A", "B", "C"};
> > +    int i;
> >
> >      method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
> > -    res = aml_local(0);
> > -    pin = aml_local(1);
> > -    aml_append(method, aml_store(aml_package(128), res));
> > -    aml_append(method, aml_store(aml_int(0), pin));
> > +    rt_pkg = aml_varpackage(N_ROUTES);
> >
> > -    /* while (pin < 128) */
> > -    while_ctx = aml_while(aml_lless(pin, aml_int(128)));
> > -    {
> > -        Aml *slot = aml_local(2);
> > -        Aml *lnk_idx = aml_local(3);
> > -        Aml *route = aml_local(4);
> > -
> > -        /* slot = pin >> 2 */
> > -        aml_append(while_ctx,
> > -                   aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
> > -        /* lnk_idx = (slot + pin) & 3 */
> > -        aml_append(while_ctx,
> > -            aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
> > -                      lnk_idx));
> > -
> > -        /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3  */
> > -        aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
> > -        if (is_pci0_prt) {
> > -            Aml *if_device_1, *if_pin_4, *else_pin_4;
> > -
> > -            /* device 1 is the power-management device, needs SCI */
> > -            if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
> > -            {
> > -                if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
> > -                {
> > -                    aml_append(if_pin_4,
> > -                        aml_store(build_prt_entry("LNKS"), route));
> > -                }
> > -                aml_append(if_device_1, if_pin_4);
> > -                else_pin_4 = aml_else();
> > -                {
> > -                    aml_append(else_pin_4,
> > -                        aml_store(build_prt_entry("LNKA"), route));
> > -                }
> > -                aml_append(if_device_1, else_pin_4);
> > -            }
> > -            aml_append(while_ctx, if_device_1);
> > -        } else {
> > -            aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
> > +    for (i = 0; i < N_ROUTES; i++) {
> > +        Aml *pkg = aml_package(4);
> > +        const char *name;
> > +
> > +        name = link_name[((i >> 2) + i) & 3];
> > +
> > +        if (is_pci0_prt && i == 4) {
> > +            name = "S";
> >          }
> > -        aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
> > -        aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
> > -
> > -        /* route[0] = 0x[slot]FFFF */
> > -        aml_append(while_ctx,
> > -            aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
> > -                             NULL),
> > -                      aml_index(route, aml_int(0))));
> > -        /* route[1] = pin & 3 */
> > -        aml_append(while_ctx,
> > -            aml_store(aml_and(pin, aml_int(3), NULL),
> > -                      aml_index(route, aml_int(1))));
> > -        /* res[pin] = route */
> > -        aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
> > -        /* pin++ */
> > -        aml_append(while_ctx, aml_increment(pin));
> > +
> > +        aml_append(pkg, aml_int((i << 14) | 0xFFFF));
> > +        aml_append(pkg, aml_int(i & 3));
> > +        aml_append(pkg, aml_name("LNK%s", name));
> > +        aml_append(pkg, aml_int(0));
> > +        aml_append(rt_pkg, pkg);
> >      }
> > -    aml_append(method, while_ctx);
> > -    /* return res*/
> > -    aml_append(method, aml_return(res));
> > +
> > +    aml_append(method, aml_return(rt_pkg));
> >
> >      return method;
> >  }
> > --
> > 2.44.0.683.g7961c838ac-goog
> >  
> 
>
diff mbox series

Patch

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 53f804ac16..4c14d39173 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -725,40 +725,7 @@  static Aml *aml_pci_pdsm(void)
     return method;
 }
 
-/**
- * build_prt_entry:
- * @link_name: link name for PCI route entry
- *
- * build AML package containing a PCI route entry for @link_name
- */
-static Aml *build_prt_entry(const char *link_name)
-{
-    Aml *a_zero = aml_int(0);
-    Aml *pkg = aml_package(4);
-    aml_append(pkg, a_zero);
-    aml_append(pkg, a_zero);
-    aml_append(pkg, aml_name("%s", link_name));
-    aml_append(pkg, a_zero);
-    return pkg;
-}
-
-/*
- * initialize_route - Initialize the interrupt routing rule
- * through a specific LINK:
- *  if (lnk_idx == idx)
- *      route using link 'link_name'
- */
-static Aml *initialize_route(Aml *route, const char *link_name,
-                             Aml *lnk_idx, int idx)
-{
-    Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
-    Aml *pkg = build_prt_entry(link_name);
-
-    aml_append(if_ctx, aml_store(pkg, route));
-
-    return if_ctx;
-}
-
+#define N_ROUTES 128
 /*
  * build_prt - Define interrupt rounting rules
  *
@@ -771,74 +738,31 @@  static Aml *initialize_route(Aml *route, const char *link_name,
  */
 static Aml *build_prt(bool is_pci0_prt)
 {
-    Aml *method, *while_ctx, *pin, *res;
+    Aml *rt_pkg, *method;
+    const char link_name[][2] = {"D", "A", "B", "C"};
+    int i;
 
     method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
-    res = aml_local(0);
-    pin = aml_local(1);
-    aml_append(method, aml_store(aml_package(128), res));
-    aml_append(method, aml_store(aml_int(0), pin));
+    rt_pkg = aml_varpackage(N_ROUTES);
 
-    /* while (pin < 128) */
-    while_ctx = aml_while(aml_lless(pin, aml_int(128)));
-    {
-        Aml *slot = aml_local(2);
-        Aml *lnk_idx = aml_local(3);
-        Aml *route = aml_local(4);
-
-        /* slot = pin >> 2 */
-        aml_append(while_ctx,
-                   aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
-        /* lnk_idx = (slot + pin) & 3 */
-        aml_append(while_ctx,
-            aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
-                      lnk_idx));
-
-        /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3  */
-        aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
-        if (is_pci0_prt) {
-            Aml *if_device_1, *if_pin_4, *else_pin_4;
-
-            /* device 1 is the power-management device, needs SCI */
-            if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
-            {
-                if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
-                {
-                    aml_append(if_pin_4,
-                        aml_store(build_prt_entry("LNKS"), route));
-                }
-                aml_append(if_device_1, if_pin_4);
-                else_pin_4 = aml_else();
-                {
-                    aml_append(else_pin_4,
-                        aml_store(build_prt_entry("LNKA"), route));
-                }
-                aml_append(if_device_1, else_pin_4);
-            }
-            aml_append(while_ctx, if_device_1);
-        } else {
-            aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
+    for (i = 0; i < N_ROUTES; i++) {
+        Aml *pkg = aml_package(4);
+        const char *name;
+
+        name = link_name[((i >> 2) + i) & 3];
+
+        if (is_pci0_prt && i == 4) {
+            name = "S";
         }
-        aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
-        aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
-
-        /* route[0] = 0x[slot]FFFF */
-        aml_append(while_ctx,
-            aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
-                             NULL),
-                      aml_index(route, aml_int(0))));
-        /* route[1] = pin & 3 */
-        aml_append(while_ctx,
-            aml_store(aml_and(pin, aml_int(3), NULL),
-                      aml_index(route, aml_int(1))));
-        /* res[pin] = route */
-        aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
-        /* pin++ */
-        aml_append(while_ctx, aml_increment(pin));
+
+        aml_append(pkg, aml_int((i << 14) | 0xFFFF));
+        aml_append(pkg, aml_int(i & 3));
+        aml_append(pkg, aml_name("LNK%s", name));
+        aml_append(pkg, aml_int(0));
+        aml_append(rt_pkg, pkg);
     }
-    aml_append(method, while_ctx);
-    /* return res*/
-    aml_append(method, aml_return(res));
+
+    aml_append(method, aml_return(rt_pkg));
 
     return method;
 }