Created attachment 202845 [details] dmesg Hi, we are running FreeBSD 11.2-RELEASE-p6 on a HP T620 Thin client. Trying to enable power saving through C states we noticed that the system presents different states for the cores: sysctl -a | grep cx_supported dev.cpu.3.cx_supported: C1/1/0 dev.cpu.2.cx_supported: C1/1/0 dev.cpu.1.cx_supported: C1/1/0 dev.cpu.0.cx_supported: C1/1/0 C2/2/400 Enabling C2 state on CPU shows that it seems to work quite well: sysctl -a | grep cx_usage: dev.cpu.3.cx_usage: 100.00% last 34923us dev.cpu.2.cx_usage: 100.00% last 10us dev.cpu.1.cx_usage: 100.00% last 3853us dev.cpu.0.cx_usage: 5.54% 94.45% last 33us CPU details: CPU: AMD GX-420CA SOC with Radeon(tm) HD Graphics (1996.29-MHz K8-class CPU) Origin="AuthenticAMD" Id=0x700f01 Family=0x16 Model=0x0 Stepping=1 Features=0x178bfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,MMX,FXSR,SSE,SSE2,HTT> Features2=0x3ed8220b<SSE3,PCLMULQDQ,MON,SSSE3,CX16,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,AVX,F16C> AMD Features=0x2e500800<SYSCALL,NX,MMX+,FFXSR,Page1GB,RDTSCP,LM> AMD Features2=0x154037ff<LAHF,CMP,SVM,ExtAPIC,CR8,ABM,SSE4A,MAS,Prefetch,OSVW,IBS,SKINIT,WDT,Topology,PNXC,DBE,PL2I> Structured Extended Features=0x8<BMI1> XSAVE Features=0x1<XSAVEOPT> SVM: (disabled in BIOS) NP,NRIP,AFlush,DAssist,NAsids=8 TSC: P-state invariant, performance statistics Is this the expected behaviour? dmesg log attached.
This is a Jaguar-class (Family 16h) AMD CPU. This information is probed automatically out of the ACPI information presented by your BIOS. That code hasn't changed appreciably in 4 years. It seems your BIOS does not provide a _CST for all 4 cores, or it is invalid. Do you see any logs in dmesg about "skipping invalid Cx state" or similar? Ah, it might be possible that your CPU is new enough to define the cores as Device objects rather than Processor, but you're running too old of FreeBSD to enumerate the Device objects and find appropriate C-states _CST tables? I don't know if r326956 has been MFCed to 11.x, but that change may address the issue. Early AP startup (present in 12.0, I think) may also affect this, but I'm not sure. C-state enumeration on Family 17h AMD CPUs seems to work just fine on CURRENT.
(In reply to Conrad Meyer from comment #1) > I don't know if r326956 has been MFCed to 11.x FWIW, that change is not present in 11.x, but is in 12.0. Please try running 12.0, if possible.
Thanks for the quick response. I'll give 12.0 a try and give feedback asap.
Speculative question in advance. If this situation does not change in 12.0: Might it be that the system only supports C2 state for the whole CPU package? And if yes: Shouldn't this be reflected in all cores?
Finally I got time to retest everything with 12.0-RELEASE. Situation is the same. Only the first CPU can go to C2 state. All other cores only show up with cx_lowest = C1. Only difference this time: It is the successor CPU AMD RX-427BB. Btw. The hardware in my tests is: First Time: HP Thin client T620 PLUS Second Time: HP Thin client T730
Created attachment 203049 [details] Screenshot dmesg
Just fired up a Fedora 29 on the HP T730. Running a cpu intensive task and looking at the powertop output I would say that C2 states are core independent. Conclusion: Linux kernel detects C2 states per core. So at least BIOS should not be broken. Screenshot attached.
Created attachment 203050 [details] Fedora powertop
Bug https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=189267 shows other occurences of CPUs where c states for the first core is C1+C2 while all other cores are C1 only.
Findings so far: acpi_cpu_cx_cst() runs fine for CPU core 0. With core 1 something is going wrong: 1. acpi_cpu_cx_cst() finds C2 state (WHAT WE EXPECT!) 2. in the function the valid states loop comes to this sequence: ... #endif { cx_ptr->res_rid = sc->cpu_cx_count; acpi_PkgGas(sc->cpu_dev, pkg, 0, &cx_ptr->res_type, &cx_ptr->res_rid, &cx_ptr->p_lvlx, RF_SHAREABLE); if (cx_ptr->p_lvlx) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: Got C%d - %d latency\n", ... 2a. acpi_PkgGas() is called 2b. sanity check in acpi_PkgGas() is ok 2c. acpi_PkgGas() calls acpi_bus_alloc_gas() that returns with rc=ENOMEM 2d. In main function cx_ptr->p_lvlx is NULL 2e. C2 is not added to the list of C states
Memo for myself: This can only occur if acpi_bus_alloc_gas() fails in bus_alloc_resource_any(): acpi_bus_alloc_gas() { ... error = ENOMEM; ... *res = bus_alloc_resource_any(dev, res_type, rid, RF_ACTIVE | flags); if (*res != NULL) { *type = res_type; error = 0; } else bus_delete_resource(dev, res_type, *rid); return (error); }
Has anyone attached an acpidump from an affected system yet?
Created attachment 203116 [details] dmesg of T620 FreeBSD 12 boot
Created attachment 203117 [details] acpudump -dt of T620
(In reply to Andriy Gapon from comment #12) Attached as requested
Created attachment 203120 [details] pciconf Output
Could you please also add devinfo -rv output?
Created attachment 203132 [details] devinfo -rv
(In reply to stockhausen from comment #18) Attached.
Memo for myself: Seems as if port 0x414 is only available for core0 and not the other ones. Maybe that is the source of the registration error. At least there are other devinfo outputs that show that a port can be bound to different cores: https://people.freebsd.org/~adrian/laptop/lenovo_x230/devinfo-rv.txt
And one OpenBSD evidence about an AMD mobile CPU that has exactly our setup: http://openbsd-archive.7691.n7.nabble.com/Disabled-USB-port-td328343.html acpicpu0 at acpi0: C2(0@400 io@0x414), C1(@1 halt!), PSS acpicpu1 at acpi0: C2(0@400 io@0x414), C1(@1 halt!), PSS acpicpu2 at acpi0: C2(0@400 io@0x414), C1(@1 halt!), PSS acpicpu3 at acpi0: C2(0@400 io@0x414), C1(@1 halt!), PSS
After a lot of investigation it seems to boil down to some kind of timing problem. acpi_resource.c:acpi_res_set_ioport() is called for the ACPI defined ressources. In our case there are several IO ports according to acpidump: 0xcf8, 8 ports 0x0, 944 ports 0x3e0, 2328 ports ... and so on ... Somewhere inside it calls acpi.c:acpi_set_resource(). But this silently fails exactly here: /* Don't reserve resources until the system resources are allocated. */ if (!sc->acpi_resources_reserved) return (0); Must be some kind of concurrency. Don't know yet where it comes from.
ok. ignore comment #22 i try to explain it once again. The problem seems to be the other way round. CPU wants to register port 0x414 for C state handling. This should be covered by BIOS ACPI tables starting at port 0x3e0 with a total of 2328 (0x918) ports. Due to misconfiguaration this port range is attached to the PCIe bridge. acpi_set_resource() simply ignores this registration /* * Ignore most resources for PCI root bridges. Some BIOSes * incorrectly enumerate the memory ranges they decode as plain * memory resources instead of as ResourceProducer ranges. Other * BIOSes incorrectly list system resource entries for I/O ranges * under the PCI bridge. Do allow the one known-correct case on * x86 of a PCI bridge claiming the I/O ports used for PCI config * access. */ #if defined(__i386__) || defined(__amd64__) if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { if (ACPI_SUCCESS(AcpiGetObjectInfo(ad->ad_handle, &devinfo))) { if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { if (!(type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT)) { printf("ADBG: acpi_set_resource(%lx,%lu) inside root bridge\n", start,count); AcpiOsFree(devinfo); return (0); } } AcpiOsFree(devinfo); } } #endif So we are left without port 0x414. This gets registered later under CPU0. See devinfo: cpu0 pnpinfo _HID=none _UID=0 at handle=\_PR_.P000 I/O ports: 0x414 If registragtion works fine this should read "ACPI I/o port" and port 0x414 should be visible below acpi0 node. To fix that situation in a clean way acpi_cpu_cx_cst() should re-register the port below acpi0 just for safety. No idea how to do that...
One step further: The wrong ACPI definitions are indeed the culprit of the wrong C2 state registration. I implemented a lousy patch in acpi.c: /* * Pre-allocate/manage all memory and IO resources. Since rman can't handle * duplicates, we merge any in the sysresource attach routine. */ static int acpi_sysres_alloc(device_t dev) { ... rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); STAILQ_FOREACH(rle, rl, link) { if (rle->res != NULL) { device_printf(dev, "duplicate resource for %jx\n", rle->start); continue; } if (rle->start == 0x40b && rle->count == 1 && rle->type == SYS_RES_IOPORT) { printf("ACPI: fake IO port range 0x40b/1 -> 0x400/32\n"); rle->start = 0x400; rle->count = 32; } So when ACPI wants to register a single port 0x40b we expand the range to 0x400-0x420. With that devinfo -rv shows: nexus0 ... acpi0 Interrupt request lines: 0x9 I/O ports: ... 0x400-0x41f ... cpu0 pnpinfo _HID=none _UID=0 at handle=\_PR_.P000 ACPI I/O ports: 0x414 acpi_perf0 acpi_throttle0 hwpstate0 cpufreq0 cpu1 pnpinfo _HID=none _UID=0 at handle=\_PR_.P001 ACPI I/O ports: 0x414 acpi_perf1 acpi_throttle1 hwpstate1 Yeah! The second and following cores can register I/O port 0x414. And finally sysctl shows all C2 states: # sysctl -a | grep cx_suppo dev.cpu.3.cx_supported: C1/1/0 C2/2/400 dev.cpu.2.cx_supported: C1/1/0 C2/2/400 dev.cpu.1.cx_supported: C1/1/0 C2/2/400 dev.cpu.0.cx_supported: C1/1/0 C2/2/400 Now I need some assistance: 1. Either patch the BIOS. But how? 2. Implement a workaround in CPU registration if port is not yet registered. But how? Thanks in advance.
(In reply to stockhausen from comment #24) I still don't understand the problem. How does that 0x40b 1-byte port interfere with 0x414 port? Or is it the other way around? Are you abusing the system resource for 0x40b to compensate for something wrong with 0x414? It would be helpful [to me] to understand precisely why, on the unpatched system, setting and allocating 0x414 port seems to work fine for cpu0 but not for the other cpus? That includes the order of acpi cpu devices attachment (relative to each other and to other acpi "things"). An exact place in the code where setting or allocating the resource fails and a reason why.
(In reply to Andriy Gapon from comment #25) Sorry for the confusion. I'm totally new to the topic and try to do my best to explain my observations more clear. The thin clients I'm talking about have a C2 power saving state that is controlled by port 0x414. This port is the same for all 4 cores. Due to the ACPI cpu startup logic the port reservation must work for each individual core. If it fails C2 is not available for a core. In the buggy case we can see: 1. System registers all known ports in acpi_sysres_alloc() in resource manager. Port 0x414 is skipped because it is not correctly defined. There exists a BIOS range 0x3e0 with 2328 ports but it is located directly under the PCI bridge. 2. So we have no range under acpi0 > I/O ports that covers port 0x414. 3. CPUs are fired up and do their initialization. The first CPU wants to register port 0x414. As it is not yet managed the registration process hangs the port as "I/O port" below CPU0. 4. The second CPU tries to do the same but it fails. For whatever reason Result: nexus0 acpi0 I/O ports: cpu0 pnpinfo _HID=none _UID=0 at handle=\_PR_.P000 I/O ports: <-- Notice no type ACPI! 0x414 Now to the fixed case: 1. I found a port range 0x40B-0x40B in the ACPI tables that registers fine in acpi_sysres_alloc() just before the CPUs. 2. I modified the ACPI tables and extended the range to something larger that also covers port 0x414 3. After a restart with the modified table port 0x414 is now covered by a range under acpi0 > I/O ports. 4. During CPU startup all CPUs can correctly allocate port 0x414 and a "copy" named "ACPI I/O port" is placed under each CPU core. Result: nexus0 acpi0 I/O ports: 0x400-0x41f cpu0 pnpinfo _HID=none _UID=0 at handle=\_PR_.P000 ACPI I/O ports: <-- Notice type ACPI! 0x414
Created attachment 203191 [details] Original (buggy) ACPIDUMP of HP T620 Plus
Created attachment 203192 [details] Modified (working) ACPIDUMP of HP T620 Plus
Memo for myself T730: AMD BIOS Developer Guide (Family=0x15 Model=0x30) https://www.amd.com/system/files/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf T620: AMD BIOS Developer Guide (Family=0x16 Model=0x0) https://www.amd.com/system/files/TechDocs/48751_16h_bkdg.pdf
(In reply to stockhausen from comment #26) So, I am mostly interested in point 4 of the buggy case. The rest was already clear. Specifically, why something that works for cpu0 does not work for the rest. The resource is allocated as RF_SHARED, so my expectation is that all cores should be able to set and allocate it. But apparently not so.
I think I am starting to see what you've been saying. So, first of all, as you discovered, your BIOS indeed provides a buggy ACPI table. But I am not sure where exactly the bug is. It could be that the table does not provide a system resource for I/O port 0x414 by mistake. Alternatively, it could be that 0x414 is a wrong value and it should be something else (e.g., 0x814). In that case, even when you get C2 state to appear it actually would not do its job. The other problem, as you noted, that if 0x414 is not defined as a system resource, then only cpu0 is able to allocate it. All other cpu devices fail to do it. I haven't fully understood yet why that happens. And also I am not sure if that is what should really happen. The best way to fix this problem is to fix the BIOS / ACPI, of course. But I wonder if there is anything that FreeBSD could do to work around or "quirk up" such a problem. P.S. 0x814 I mentioned is not an arbitrary port. I see it on some AMD systems, although with different processors. Also, all other processor related ACPI IO ports seem to be in the 0x800 area. And it seems that PMBS and PMLN constants are supposed to define the processor power management I/O region as a system resource. The relevant section of the BKDG document for your processor is 3.25.15.5. So, I guess the only way to learn the true value of PLvl2 register is to somehow read what's in PMx66 register. P.P.S. The PCI root bridge settings appear to be correct and I do not see them contributing to the problem.
Thanks for the helpful discussion. I think I'm getting a better knowledge about it all. Reading across the AMD documents I think everything works as expected. Or at least quite close. Comparing the T620 plus and the T730 I noticed that the C2 state port is different. 0x1771 and not 0x414. Reason is simple - this port is arbitrary set by BIOS. Explanation comes from the AMD family 0x15 models 0x30-0x03F developer guide 2.5.3.2.7 BIOS Requirements for Initialization: 1. Initialize MSRC001_0073[CstateAddr] with an available IO address. See 2.5.3.2.6.3 [_CRS]. -> HP chose port 0x1770 for the T730 and 0x413 for the T620 as can be seen from cpucontrol output root@freebsd:~ # cpucontrol -m 0xC0010073 /dev/cpuctl0 MSR 0xc0010073: 0x00000000 0x00001770 2. Initialize D18F4x11[C:8]. -> I don't know how to read that indexed register 3. Generate ACPI objects as follows 3.a The _CST object should be generated for each core as follows: - Count = 1. - Register = MSRC001_0073[CstateAddr] + 1. - Type = 2. - Latency = 400. - Power = 0. -> We can see that in the decoded ACPI dump ResourceTemplate () { Register (SystemIO, 0x08, // Bit Width 0x00, // Bit Offset 0x0000000000001771, // Address 0x01, // Access Size ) }, 3.b The _CSD object should be generated for each core as follows: - NumberOfEntries = 6. - Revision = 0. - Domain = CPUID Fn0000_0001_EBX[LocalApicId[7:1]]. - CoordType = FEh. (HW_ALL) - NumProcessors = 2. - Index = 0. -> Also inside the ACPI dump Name (_CSD, Package (0x01) // _CSD: C-State Dependencies { Package (0x06) { 0x06, 0x00, 0x00000000, 0x000000FE, 0x00000002, 0x00000000 } }) 3.b BIOS must declare in the root host bridge _CRS object that the IO address range from MSRC001_0073[CstateAddr] to MSRC001_0073[CstateAddr]+7 is consumed by the host bridge. -> This is missing in the ACPI tables. We need an entry for 8 ports starting from 0x1770. 4. Fixed ACPI Description Table (FADT) Entries -> Should not bee neded as FreeBSD is hopefully ACPI 2.0 aware and can read the _CST object from above. So two question remain A. Is the current ACPI code able to compensate for the missing port allocation ranges in BIOS? If you say yes we have found an error. B. My stupid fix may be totally wrong. Where should I place the port registration in the ACPI tables?
Btw. I found a sample with C2 state port 0x814 https://mail-index.netbsd.org/current-users/2010/07/21/msg013890.html
(In reply to stockhausen from comment #32) 1. Ah, you are right, I forgot that modern processors intercept C-state I/O accesses at a core level. Just to clarify, I assume that on your T620 cpucontrol -m 0xC0010073 /dev/cpuctl0 gives 0x414? 3.b(2) The root bridge has a range that covers 0x414, so that's okay. A. I do not think so. I think that the code currently expects BIOS to set up everything correctly. We could try to think about how FreeBSD ACPI code could work around not having Cx I/O ports in the system resources... By the way, I see why acpi cpu devices cannot share a resource if it's not an acpi system resource. If a resource is a system resource then it is allocated from the nexus (very early) and the acpi bus manages it on its own. That means that acpi_set_resource() -> resource_list_reserve(flags=0) -> resource_list_alloc() -> BUS_ALLOC_RESOURCE() -> nexus_alloc_resource() -> rman_reserve_resource(flags=0) would always fail. But that's okay, because acpi_alloc_resource() has a fallback to acpi_alloc_sysres(). And if the resource is consistently allocated with RF_SHARED, then all allocations of it succeed. If a resource is _not_ a system resource, then the resource is not allocated by the acpi bus in the nexus as the acpi bus is unaware of it. Then, when the first cpu calls acpi_PkgGas() -> acpi_bus_alloc_gas() -> bus_set_resource() -> acpi_set_resource() -> resource_list_reserve(flags=0) -> resource_list_alloc(flags=0) -> BUS_ALLOC_RESOURCE(flags=0) -> nexus_alloc_resource(flags=0) -> rman_reserve_resource(flags=0), the resource is allocated in the nexus and it is allocated without RF_SHARED flag. Because the allocation is successful, the resource is added to the device's resource list. After bus_set_resource(), acpi_bus_alloc_gas() calls bus_alloc_resource_any() -> acpi_alloc_resource(flags=RF_ACTIVE|RF_SHARED) -> resource_list_alloc(). Because the resource already exists in the device's resource list, resource_list_alloc() would simply activate it and return. So, for the first cpu acpi_bus_alloc_gas() is successful. For any subsequent cpu, this call chain acpi_PkgGas() -> acpi_bus_alloc_gas() -> bus_set_resource() -> acpi_set_resource() -> resource_list_reserve(flags=0) -> resource_list_alloc(flags=0) -> BUS_ALLOC_RESOURCE(flags=0) -> nexus_alloc_resource(flags=0) -> rman_reserve_resource(flags=0) would fail because the resource is already allocated in nexus and it is not shared. Thus, the resource would not be created in the device's resource list. Thus, the subsequent call to bus_alloc_resource_any() -> acpi_alloc_resource(flags=RF_ACTIVE|RF_SHARED) -> resource_list_alloc() would not find that resource and it would have to call BUS_ALLOC_RESOURCE() -> nexus_alloc_resource() -> rman_reserve_resource() and that would fail again for the same reason. And, in this case, acpi_alloc_resource()'s fallback to acpi_alloc_sysres() would also fail, because the resource is not a system resource. In the end, acpi_PkgGas() -> acpi_bus_alloc_gas() fails just as you have seen. B. I would add 0x414 to CRS of Device S900. E.g. using 0x040B as an example, I would add this just after it: IO (Decode16, 0x0414, // Range Minimum 0x0414, // Range Maximum 0x00, // Alignment 0x04, // Length )
Phew, I see you found the culprit. Although I do not know every single function I saw a lot of the names during my code analysis. Regarding HP T620 settings: cpucontrol -m 0xC0010073 /dev/cpuctl0 gives 0x413 (The CPU gets Port+1 from BIOS). So the ACPI tables need: For T620: IO (Decode16, 0x0413, // Range Minimum 0x0413, // Range Maximum 0x00, // Alignment 0x08, // Length ) For T730: IO (Decode16, 0x1770, // Range Minimum 0x1770, // Range Maximum 0x00, // Alignment 0x08, // Length ) With these settings C2 states come up fine on both machines. I will check if all of this hard work at least gives some power saving effects.
It may be that we need to fix the RF_SHAREABLE to propagate up when the resource is first allocated by resource_list_reserve, etc. That might fix this without requiring the BIOS to be patched. I haven't looked to see what that would involve though.
Created attachment 203218 [details] shareable_acpi_set_resource.patch This is an untested hack that uses RF_SHAREABLE when reserving resources for CPUs. The other approach is we could just not reserve resources for CPU devices which might be safer as it would then always honor the flags passed to bus_alloc_resource().
Sorry not quite yet... The only call to acpi_set_resource() during _CST port setup has the following input: class of dev: "acpi" class of child: "cpu" A slight modification gives: if (device_get_devclass(child) == devclass_find("cpu")) { flags = RF_SHAREABLE; } else { flags = 0; } Ports are now registered per CPU (which is fine), but devinfo gives different output: nexus0 I/O ports: < no port 0x1771 here ...> cpu0 pnpinfo _HID=none _UID=0 at handle=\_PR_.P000 I/O ports: <---- Port without ACPI flag 0x1771 acpi_perf0 acpi_throttle0 hwpstate0 cpufreq0 cpu1 pnpinfo _HID=none _UID=0 at handle=\_PR_.P001 I/O ports: 0x1771 Nevertheless CPU C states seem to register correctly: root@freebsd:~ # sysctl -a | grep cx_supp dev.cpu.3.cx_supported: C1/1/0 C2/2/400 dev.cpu.2.cx_supported: C1/1/0 C2/2/400 dev.cpu.1.cx_supported: C1/1/0 C2/2/400 dev.cpu.0.cx_supported: C1/1/0 C2/2/400
Yes, having the resources be per-CPU in devinfo is the expected effect of this patch. I think though that I want to modify this a bit more so that we just don't reserve resources for CPU devices rather than forcing RF_SHAREABLE. This will then honor whatever is passed to bus_alloc_resource().
Created attachment 203244 [details] acpi_cpu_noreserve.patch This is the new patch that doesn't try to force shareable but skips reserving. This is more consistent with other workarounds in this function that generally just skip reserving when that has problems.
The new patch only works if we use child instead of dev. old: device_get_devclass(dev) new: device_get_devclass(child)
(In reply to stockhausen from comment #41) Correct, it should be 'child' as 'dev' in that context is the acpi bus itself.
(In reply to John Baldwin from comment #40) John, this is a great simple patch. I tried to come up with a way to achieve this effect, but didn't think about this approach.
(In reply to Andriy Gapon from comment #43) I can confirm that the patch works fine (with child instead of dev) devinfo -rv cpu0 pnpinfo _HID=none _UID=0 at handle=\_PR_.P000 I/O ports: 0x1771 acpi_perf0 acpi_throttle0 hwpstate0 cpufreq0 cpu1 pnpinfo _HID=none _UID=0 at handle=\_PR_.P001 I/O ports: 0x1771 acpi_perf1 acpi_throttle1 hwpstate1 root@freebsd:~ # sysctl -a | grep cx_supp dev.cpu.3.cx_supported: C1/1/0 C2/2/400 dev.cpu.2.cx_supported: C1/1/0 C2/2/400 dev.cpu.1.cx_supported: C1/1/0 C2/2/400 dev.cpu.0.cx_supported: C1/1/0 C2/2/400
Is there anything I can do, to mainline this patch?
I was just wanting to test it locally first, sorry.
A commit references this bug: Author: jhb Date: Tue Apr 9 19:22:09 UTC 2019 New revision: 346063 URL: https://svnweb.freebsd.org/changeset/base/346063 Log: Don't pre-reserve resources for CPU devices when they are set. CPUs can use shared (RF_SHAREABLE) resources for the I/O port used for entering and exiting C states. If this I/O port is included in an ACPI system resource device, then this happens to still work, but if the port wasn't part of a system resource device, only the first CPU could allocate the I/O port and use C states since resource_list_reserve() was always allocating the resource from nexus0 without RF_SHAREABLE. By avoiding the reservation, the flags from the bus_alloc_resource() in the CPU driver (which include RF_SHAREABLE) are honored. PR: 236513 Reported by: stockhausen@collogia.de Sleuthing by: avg Reviewed by: avg MFC after: 2 weeks Changes: head/sys/dev/acpica/acpi.c
A commit references this bug: Author: jhb Date: Wed May 1 17:30:14 UTC 2019 New revision: 346999 URL: https://svnweb.freebsd.org/changeset/base/346999 Log: MFC 346063: Don't pre-reserve resources for CPU devices when they are set. CPUs can use shared (RF_SHAREABLE) resources for the I/O port used for entering and exiting C states. If this I/O port is included in an ACPI system resource device, then this happens to still work, but if the port wasn't part of a system resource device, only the first CPU could allocate the I/O port and use C states since resource_list_reserve() was always allocating the resource from nexus0 without RF_SHAREABLE. By avoiding the reservation, the flags from the bus_alloc_resource() in the CPU driver (which include RF_SHAREABLE) are honored. PR: 236513 Changes: _U stable/11/ stable/11/sys/dev/acpica/acpi.c _U stable/12/ stable/12/sys/dev/acpica/acpi.c
Just a note that I had the same problem on an APU2C4 box that I recently received. And this change fixed it, of course.