qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] hw/i386/acpi-build: Return a pre-computed _PRT table
@ 2024-04-17 13:53 Ricardo Ribalda
  2024-05-03  9:09 ` Ricardo Ribalda
  0 siblings, 1 reply; 3+ messages in thread
From: Ricardo Ribalda @ 2024-04-17 13:53 UTC (permalink / raw)
  To: Michael S. Tsirkin, Igor Mammedov, Ani Sinha, Marcel Apfelbaum,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost, qemu-devel
  Cc: Ricardo Ribalda

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



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] hw/i386/acpi-build: Return a pre-computed _PRT table
  2024-04-17 13:53 [PATCH] hw/i386/acpi-build: Return a pre-computed _PRT table Ricardo Ribalda
@ 2024-05-03  9:09 ` Ricardo Ribalda
  2024-05-30 13:50   ` Igor Mammedov
  0 siblings, 1 reply; 3+ messages in thread
From: Ricardo Ribalda @ 2024-05-03  9:09 UTC (permalink / raw)
  To: Michael S. Tsirkin, Igor Mammedov, Ani Sinha, Marcel Apfelbaum,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost, qemu-devel,
	Andrea Righi

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
>


-- 
Ricardo Ribalda


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] hw/i386/acpi-build: Return a pre-computed _PRT table
  2024-05-03  9:09 ` Ricardo Ribalda
@ 2024-05-30 13:50   ` Igor Mammedov
  0 siblings, 0 replies; 3+ messages in thread
From: Igor Mammedov @ 2024-05-30 13:50 UTC (permalink / raw)
  To: Ricardo Ribalda
  Cc: Michael S. Tsirkin, Ani Sinha, Marcel Apfelbaum, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, qemu-devel, Andrea Righi

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
> >  
> 
> 



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-05-30 13:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-17 13:53 [PATCH] hw/i386/acpi-build: Return a pre-computed _PRT table Ricardo Ribalda
2024-05-03  9:09 ` Ricardo Ribalda
2024-05-30 13:50   ` Igor Mammedov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).