diff --git a/src/runtime/lfstack_64bit.go b/src/runtime/lfstack_64bit.go
index 154130cf63b87619dbd97e3525cdcdbb9fe6f305..88cbd3bcc7e4ac187e920ec70dab9fa959fa26be 100644
--- a/src/runtime/lfstack_64bit.go
+++ b/src/runtime/lfstack_64bit.go
@@ -36,12 +36,21 @@ const (
 	// We use one bit to distinguish between the two ranges.
 	aixAddrBits = 57
 	aixCntBits  = 64 - aixAddrBits + 3
+
+	// riscv64 SV57 mode gives 56 bits of userspace VA.
+	// lfstack code supports it, but broader support for SV57 mode is incomplete,
+	// and there may be other issues (see #54104).
+	riscv64AddrBits = 56
+	riscv64CntBits  = 64 - riscv64AddrBits + 3
 )
 
 func lfstackPack(node *lfnode, cnt uintptr) uint64 {
 	if GOARCH == "ppc64" && GOOS == "aix" {
 		return uint64(uintptr(unsafe.Pointer(node)))<<(64-aixAddrBits) | uint64(cnt&(1<<aixCntBits-1))
 	}
+	if GOARCH == "riscv64" {
+		return uint64(uintptr(unsafe.Pointer(node)))<<(64-riscv64AddrBits) | uint64(cnt&(1<<riscv64CntBits-1))
+	}
 	return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
 }
 
@@ -54,5 +63,8 @@ func lfstackUnpack(val uint64) *lfnode {
 	if GOARCH == "ppc64" && GOOS == "aix" {
 		return (*lfnode)(unsafe.Pointer(uintptr((val >> aixCntBits << 3) | 0xa<<56)))
 	}
+	if GOARCH == "riscv64" {
+		return (*lfnode)(unsafe.Pointer(uintptr(val >> riscv64CntBits << 3)))
+	}
 	return (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
 }