NetBSD-Bugs archive

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

kern/59521: Fix arm64 32bit pcc for cpu-freq scaling



>Number:         59521
>Category:       kern
>Synopsis:       Fix arm64 32bit pcc for cpu-freq scaling
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jul 09 00:15:00 +0000 2025
>Originator:     zhuge
>Release:        10.1
>Organization:
cherry-embedded
>Environment:
NetBSD arm64 10.1_STABLE NetBSD 10.1_STABLE (GENERIC64) #14: Tue Jul  8 06:26:17 CST 2025
>Description:
This PR is to fix cpu frequency scaling in some arm64 platform

1): the current acpi_pcc.c do not handle for reg->BitWidth = 32 case,therefore some arm64 platform failed with Data aligment abort when init cppc
2): the current acpi_pcc.c mis-use mask when write new cpu freq into pcc channel
>How-To-Repeat:
boot 32-bit pcc channel ARM64 PC with CPPC enabled
>Fix:
diff --git a/sys/dev/acpi/acpi_pcc.c b/sys/dev/acpi/acpi_pcc.c
index 0d9c0c618..b3afcb11a 100644
--- a/sys/dev/acpi/acpi_pcc.c
+++ b/sys/dev/acpi/acpi_pcc.c
@@ -265,7 +265,6 @@ pcc_send_command(struct pcc_subspace *ss, ACPI_GENERIC_ADDRESS *reg,
 {
 	volatile ACPI_PCCT_SHARED_MEMORY *shmem = ss->ss_data;
 	uint8_t *data = __UNVOLATILE(shmem + 1);
-	UINT64 tmp, mask;
 
 	KASSERT(ss->ss_type == ACPI_PCCT_TYPE_GENERIC_SUBSPACE ||
 	        ss->ss_type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE ||
@@ -274,12 +273,27 @@ pcc_send_command(struct pcc_subspace *ss, ACPI_GENERIC_ADDRESS *reg,
 	shmem->Signature = PCC_SIGNATURE(ss->ss_id);
 	shmem->Command = command & 0xff;
 	if ((flags & PCC_WRITE) != 0) {
-		mask = __BITS(reg->BitOffset + reg->BitWidth - 1,
-			      reg->BitOffset);
-		ACPI_MOVE_64_TO_64(&tmp, data + reg->Address);
-		tmp &= mask;
-		tmp |= __SHIFTIN(val, mask);
-		ACPI_MOVE_64_TO_64(data + reg->Address, &tmp);
+		if (reg->BitWidth == 32U) {
+			UINT32 tmp32, mask32, val32;
+			val32 = (UINT32)val;
+			mask32 = __BITS(reg->BitOffset + reg->BitWidth - 1,
+					reg->BitOffset);
+			ACPI_MOVE_32_TO_32(&tmp32, data + reg->Address);
+			tmp32 &= ~mask32;
+			tmp32 |= __SHIFTIN(val32, mask32);
+			aprint_normal("%s PCC32 write %d %ld mask 0x%x\n", __func__, tmp32, val, mask32);
+			ACPI_MOVE_32_TO_32(data + reg->Address, &tmp32);
+		} else if (reg->BitWidth == 64U) {
+			UINT64 tmp, mask;
+			mask = __BITS(reg->BitOffset + reg->BitWidth - 1,
+					reg->BitOffset);
+			ACPI_MOVE_64_TO_64(&tmp, data + reg->Address);
+			tmp &= ~mask;
+			tmp |= __SHIFTIN(val, mask);
+			ACPI_MOVE_64_TO_64(data + reg->Address, &tmp);
+		} else {
+			panic("PCC %d bit not support\n", reg->BitWidth);
+		}
 	}
 	PCC_MEMORY_BARRIER();
 	shmem->Status &= ~(PCC_STATUS_COMMAND_COMPLETE |
@@ -300,7 +314,6 @@ pcc_receive_response(struct pcc_subspace *ss, ACPI_GENERIC_ADDRESS *reg,
 {
 	volatile ACPI_PCCT_SHARED_MEMORY *shmem = ss->ss_data;
 	const uint8_t *data = __UNVOLATILE(shmem + 1);
-	UINT64 tmp, mask;
 
 	KASSERT(ss->ss_type == ACPI_PCCT_TYPE_GENERIC_SUBSPACE ||
 	        ss->ss_type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE ||
@@ -313,10 +326,23 @@ pcc_receive_response(struct pcc_subspace *ss, ACPI_GENERIC_ADDRESS *reg,
 	}
 
 	if ((flags & PCC_READ) != 0) {
-		mask = __BITS(reg->BitOffset + reg->BitWidth - 1,
-			      reg->BitOffset);
-		ACPI_MOVE_64_TO_64(&tmp, data + reg->Address);
-		*val = __SHIFTOUT(tmp, mask);
+		if (reg->BitWidth == 32U) {
+			UINT32 tmp32, mask32, val32;
+			mask32 = __BITS(reg->BitOffset + reg->BitWidth - 1,
+					reg->BitOffset);
+			ACPI_MOVE_32_TO_32(&tmp32, data + reg->Address);
+			val32 = __SHIFTOUT(tmp32, mask32);
+			*val = (UINT64)val32;
+			aprint_normal("%s PCC32 read %d %ld mask 0x%x\n", __func__, tmp32, *val, mask32);
+		} else if (reg->BitWidth == 64U) {
+			UINT64 tmp, mask;
+			mask = __BITS(reg->BitOffset + reg->BitWidth - 1,
+					reg->BitOffset);
+			ACPI_MOVE_64_TO_64(&tmp, data + reg->Address);
+			*val = __SHIFTOUT(tmp, mask);
+		} else {
+			panic("PCC %d bit not support\n", reg->BitWidth);
+		}
 	}
 
 	return AE_OK;



Home | Main Index | Thread Index | Old Index