Hi Gustavo,

>  From: Gustavo Romero <gustavo.rom...@linaro.org>
>  Sent: Monday, October 21, 2024 3:10 AM
>  To: Salil Mehta <salil.me...@huawei.com>; qemu-devel@nongnu.org;
>  qemu-...@nongnu.org; m...@redhat.com
>  
>  Hi Salil,
>  
>  On 10/14/24 16:22, Salil Mehta wrote:
>  > Reflect the ACPI CPU hotplug `is_{present, enabled}` states in the
>  > `_STA.PRES`
>  > (presence) and `_STA.ENA` (enabled) bits when the guest kernel
>  > evaluates the ACPI `_STA` method during initialization, as well as
>  > when vCPUs are hot-plugged or hot-unplugged. The presence of
>  unplugged
>  > vCPUs may need to be deliberately
>  > *simulated* at the ACPI level to maintain a *persistent* view of vCPUs
>  > for the guest kernel.
>  >
>  > Signed-off-by: Salil Mehta <salil.me...@huawei.com>
>  > ---
>  >   hw/acpi/cpu.c | 26 ++++++++++++++++++++++----
>  >   1 file changed, 22 insertions(+), 4 deletions(-)
>  >
>  > diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index
>  > 700aa855e9..23ea2b9c70 100644
>  > --- a/hw/acpi/cpu.c
>  > +++ b/hw/acpi/cpu.c
>  > @@ -63,10 +63,11 @@ static uint64_t cpu_hotplug_rd(void *opaque,
>  hwaddr addr, unsigned size)
>  >       cdev = &cpu_st->devs[cpu_st->selector];
>  >       switch (addr) {
>  >       case ACPI_CPU_FLAGS_OFFSET_RW: /* pack and return is_* fields */
>  > -        val |= cdev->cpu ? 1 : 0;
>  > +        val |= cdev->is_enabled ? 1 : 0;
>  >           val |= cdev->is_inserting ? 2 : 0;
>  >           val |= cdev->is_removing  ? 4 : 0;
>  >           val |= cdev->fw_remove  ? 16 : 0;
>  > +        val |= cdev->is_present ? 32 : 0;
>  >           trace_cpuhp_acpi_read_flags(cpu_st->selector, val);
>  >           break;
>  >       case ACPI_CPU_CMD_DATA_OFFSET_RW:
>  > @@ -376,6 +377,7 @@ const VMStateDescription vmstate_cpu_hotplug =
>  {
>  >   #define CPU_REMOVE_EVENT  "CRMV"
>  >   #define CPU_EJECT_EVENT   "CEJ0"
>  >   #define CPU_FW_EJECT_EVENT "CEJF"
>  > +#define CPU_PRESENT       "CPRS"
>  >
>  >   void build_cpus_aml(Aml *table, MachineState *machine,
>  CPUHotplugFeatures opts,
>  >                       build_madt_cpu_fn build_madt_cpu, hwaddr
>  > base_addr, @@ -436,7 +438,9 @@ void build_cpus_aml(Aml *table,
>  MachineState *machine, CPUHotplugFeatures opts,
>  >           aml_append(field, aml_named_field(CPU_EJECT_EVENT, 1));
>  >           /* tell firmware to do device eject, write only */
>  >           aml_append(field, aml_named_field(CPU_FW_EJECT_EVENT, 1));
>  > -        aml_append(field, aml_reserved_field(3));
>  > +        /* 1 if present, read only */
>  > +        aml_append(field, aml_named_field(CPU_PRESENT, 1));
>  > +        aml_append(field, aml_reserved_field(2));
>  >           aml_append(field, aml_named_field(CPU_COMMAND, 8));
>  >           aml_append(cpu_ctrl_dev, field);
>  >
>  > @@ -466,6 +470,7 @@ void build_cpus_aml(Aml *table, MachineState
>  *machine, CPUHotplugFeatures opts,
>  >           Aml *ctrl_lock = aml_name("%s.%s", cphp_res_path, CPU_LOCK);
>  >           Aml *cpu_selector = aml_name("%s.%s", cphp_res_path,
>  CPU_SELECTOR);
>  >           Aml *is_enabled = aml_name("%s.%s", cphp_res_path,
>  > CPU_ENABLED);
>  > +        Aml *is_present = aml_name("%s.%s", cphp_res_path,
>  > + CPU_PRESENT);
>  >           Aml *cpu_cmd = aml_name("%s.%s", cphp_res_path,
>  CPU_COMMAND);
>  >           Aml *cpu_data = aml_name("%s.%s", cphp_res_path, CPU_DATA);
>  >           Aml *ins_evt = aml_name("%s.%s", cphp_res_path,
>  > CPU_INSERT_EVENT); @@ -494,13 +499,26 @@ void build_cpus_aml(Aml
>  *table, MachineState *machine, CPUHotplugFeatures opts,
>  >           {
>  >               Aml *idx = aml_arg(0);
>  >               Aml *sta = aml_local(0);
>  > +            Aml *ifctx2;
>  > +            Aml *else_ctx;
>  >
>  >               aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
>  >               aml_append(method, aml_store(idx, cpu_selector));
>  >               aml_append(method, aml_store(zero, sta));
>  > -            ifctx = aml_if(aml_equal(is_enabled, one));
>  > +            ifctx = aml_if(aml_equal(is_present, one));
>  >               {
>  > -                aml_append(ifctx, aml_store(aml_int(0xF), sta));
>  > +                ifctx2 = aml_if(aml_equal(is_enabled, one));
>  > +                {
>  > +                    /* cpu is present and enabled */
>  > +                    aml_append(ifctx2, aml_store(aml_int(0xF), sta));
>  > +                }
>  > +                aml_append(ifctx, ifctx2);
>  > +                else_ctx = aml_else();
>  > +                {
>  > +                    /* cpu is present but disabled */
>  > +                    aml_append(else_ctx, aml_store(aml_int(0xD),
>  > + sta));
>  
>  Here, the return value for _STA method is set to reflect the state of
>  CPU_PRESENT and CPU_ENABLED fields. I can't see these two fields being
>  mapped to AcpiCpuStatus.{is_present,is_enabled}. They look to be mapped
>  to the MMIO region (base_addr), which doesn't mapped to AcpiCpuStatus
>  afaics. So where CPU_PRESENT and CPU_ENABLED are set and where
>  exactly they reside?


You don’t set _STA field from guest for CPUs. We only fetch values being
reflected by the VMM. In general, ACPI _STA method is for fetching status
of a device. Please check below:

https://uefi.org/specs/ACPI/6.5/06_Device_Configuration.html?highlight=_sta#sta-device-status


We are banking on below status bits:

Bit [0] - Set if the device is present.
Bit [1] - Set if the device is enabled and decoding its resources.

Hence, AcpiCpuStatus::(is_present, is_enabled} are set in the VMM
and their status is shared to the guest kernel when the ACPI _STA
method is evaluated by the OSPM.


Patch 3/4: 
https://lore.kernel.org/qemu-devel/20241014192205.253479-4-salil.me...@huawei.com/
#HUNK

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 700aa855e9..23ea2b9c70 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -63,10 +63,11 @@ static uint64_t cpu_hotplug_rd(void *opaque, hwaddr addr, 
unsigned size)
     cdev = &cpu_st->devs[cpu_st->selector];---------> check this code excerpt
     switch (addr) {
     case ACPI_CPU_FLAGS_OFFSET_RW: /* pack and return is_* fields */
-        val |= cdev->cpu ? 1 : 0;
+        val |= cdev->is_enabled ? 1 : 0;---------------> this change
         val |= cdev->is_inserting ? 2 : 0;
         val |= cdev->is_removing  ? 4 : 0;
         val |= cdev->fw_remove  ? 16 : 0;
+        val |= cdev->is_present ? 32 : 0;-------------> and this change
         trace_cpuhp_acpi_read_flags(cpu_st->selector, val);
         break;
     case ACPI_CPU_CMD_DATA_OFFSET_RW:


Thanks

>  
>  
>  Cheers,
>  Gustavo
>  
>  > +                }
>  > +                aml_append(ifctx, else_ctx);
>  >               }
>  >               aml_append(method, ifctx);
>  >               aml_append(method, aml_release(ctrl_lock));

Reply via email to