ZenStates-Core icon indicating copy to clipboard operation
ZenStates-Core copied to clipboard

ccdDisableMap / coreDisableMap invalid

Open GamePP opened this issue 1 month ago • 10 comments

Hi 7950X3D 9950X3D

CCD fuses Core fuses

When I turn off a CCD in BIOS or software, the software cannot obtain the status of the shutdown, but the status can be obtained in Ryzen Master.

--- fix --- This is not the state of the CCD being softly disabled in the BIOS; it is the state of the CPU being physically isolated.

GamePP avatar Oct 24 '25 03:10 GamePP

That's correct, there's a workaround but I don't think it was ever implemented

mann1x avatar Oct 24 '25 03:10 mann1x

That's correct, there's a workaround but I don't think it was ever implemented

Do I need to modify ccdFuse or coreFuse? Can you give me some reference functions? Thank you @mann1x

GamePP avatar Oct 24 '25 06:10 GamePP

Sorry I still have to finish the upgrade of my own version of the DLL which is quite old, too many changes, so it's not on GitHub

It's a bit complex, I do things a little different. I create a coreLayout during Cpu() initialization method Later I check if it's valid with CheckCoreLayout and there I verify if the core answers correctly to a CO request which is the only way to understand if a core is soft disabled, this way I can fix the coreLayout


        // End of Cpu() init
        info.topology = GetCpuTopology(info.family, info.codeName, info.model);
        info.topology.coreLayout = CheckCoreLayout(info.topology.coreLayoutInit);
        if (Utils.CountSetBits(info.topology.coreEnabledMap) != Utils.CountSetBits(info.topology.coreLayout))
            info.topology.coreLayout = CheckCoreLayout(info.topology.coreLayoutInit);
        
        // Functions
        public bool IsValidPsmCheck(int coreIndex)
        {
            SMUCommands.CmdResult result;
            bool psmCheck = false;

            int highlimit = 30;
            int lowlimit = info.codeName == CodeName.Raphael ? -16959 : -30;

            for (int r = 0; r < 10; r++)
            {
                Thread.Sleep(15);
                result = new SMUCommands.GetPsmMarginSingleCore(smu).Execute(GetCoreMask(coreIndex));
                if (result.status == SMU.Status.FAILED) { psmCheck = false; r = 10; }
                if (result.status == SMU.Status.OK)
                {
                    psmCheck = (int)result.args[0] > highlimit || (int)result.args[0] < lowlimit ? false : true;
                    r = 10;
                }
            }

            return psmCheck;
        }
        public uint CheckCoreLayout(uint oldCoreLayout)
        {
            try
            {
                if (info.codeName != CodeName.Raphael) return oldCoreLayout;

                uint newCoreLayout = 0;
                uint setbit;

                for (int ccd = 0; ccd < info.topology.ccds; ccd++)
                {
                    int p = 0;
                    bool psmCheck = false;

                    uint _oldCoreLayout = (oldCoreLayout >> ccd * 8) & 0xff;

                    for (int i = 0; i < 8; _oldCoreLayout >>= 1, ++i)
                    {
                        setbit = (_oldCoreLayout & 1) == 1 ? (uint)1 : 0;

                        if (setbit == 1)
                        {
                            while (true)
                            {
                                psmCheck = IsValidPsmCheck(p + (ccd * 8));
                                if (psmCheck) break;
                                p++;
                            }
                        }
                        newCoreLayout |= (uint)setbit << p + (ccd * 8);
                        p++;
                        i = p < 8 ? i : 8;
                    }

                }
                return newCoreLayout;
            }
            catch
            {
                return 0;
            }
        }

mann1x avatar Oct 24 '25 07:10 mann1x

Sorry I still have to finish the upgrade of my own version of the DLL which is quite old, too many changes, so it's not on GitHub

It's a bit complex, I do things a little different. I create a coreLayout during Cpu() initialization method Later I check if it's valid with CheckCoreLayout and there I verify if the core answers correctly to a CO request which is the only way to understand if a core is soft disabled, this way I can fix the coreLayout

    // End of Cpu() init
    info.topology = GetCpuTopology(info.family, info.codeName, info.model);
    info.topology.coreLayout = CheckCoreLayout(info.topology.coreLayoutInit);
    if (Utils.CountSetBits(info.topology.coreEnabledMap) != Utils.CountSetBits(info.topology.coreLayout))
        info.topology.coreLayout = CheckCoreLayout(info.topology.coreLayoutInit);
    
    // Functions
    public bool IsValidPsmCheck(int coreIndex)
    {
        SMUCommands.CmdResult result;
        bool psmCheck = false;

        int highlimit = 30;
        int lowlimit = info.codeName == CodeName.Raphael ? -16959 : -30;

        for (int r = 0; r < 10; r++)
        {
            Thread.Sleep(15);
            result = new SMUCommands.GetPsmMarginSingleCore(smu).Execute(GetCoreMask(coreIndex));
            if (result.status == SMU.Status.FAILED) { psmCheck = false; r = 10; }
            if (result.status == SMU.Status.OK)
            {
                psmCheck = (int)result.args[0] > highlimit || (int)result.args[0] < lowlimit ? false : true;
                r = 10;
            }
        }

        return psmCheck;
    }
    public uint CheckCoreLayout(uint oldCoreLayout)
    {
        try
        {
            if (info.codeName != CodeName.Raphael) return oldCoreLayout;

            uint newCoreLayout = 0;
            uint setbit;

            for (int ccd = 0; ccd < info.topology.ccds; ccd++)
            {
                int p = 0;
                bool psmCheck = false;

                uint _oldCoreLayout = (oldCoreLayout >> ccd * 8) & 0xff;

                for (int i = 0; i < 8; _oldCoreLayout >>= 1, ++i)
                {
                    setbit = (_oldCoreLayout & 1) == 1 ? (uint)1 : 0;

                    if (setbit == 1)
                    {
                        while (true)
                        {
                            psmCheck = IsValidPsmCheck(p + (ccd * 8));
                            if (psmCheck) break;
                            p++;
                        }
                    }
                    newCoreLayout |= (uint)setbit << p + (ccd * 8);
                    p++;
                    i = p < 8 ? i : 8;
                }

            }
            return newCoreLayout;
        }
        catch
        {
            return 0;
        }
    }

Thank you for your idea. Use CO setting to determine whether the Core or CCD is closed. I'm planning to use GetLogicalProcessorInformationEx to retrieve RelationProcessorDie. Using your guidance, I can determine whether it's CCD0 or CCD1, and mark CCD0 or 1 as closed. @mann1x

GamePP avatar Oct 24 '25 07:10 GamePP

Good luck! I have my own custom interface for that in CPUDoc:

https://github.com/mann1x/CPUDoc/blob/master/Base/ProcessorInfo.cs

But it's still using GetLogicalProcessorInformation

mann1x avatar Oct 24 '25 07:10 mann1x

I never got the motivation to actually implement that idea with probing the cores for CO (it also need to be tested on different ryzen generations). The current disable map only detects factory fused cores and it only works for select cpus. I need to at least fix the APUs. The biggest priority now is replacing the driver, however at its current state most of the functionality in the dll can't be ported.

irusanov avatar Oct 24 '25 07:10 irusanov

Yes I only tested it on Zen4 desktop and would probably work the same on Zen5 but no idea about he APUs. I'm also not moving on with the porting of the latest version on mine cause of the driver. I also miss the CPPC part from ACPI in the mainline DLL and updating to the latest messed it up. Trying to read it from MSRs looking at amd_pstate driver in linux but I'm doing something wrong, not working as expected.

mann1x avatar Oct 24 '25 07:10 mann1x

I understand that it is indeed affected by Windows Defender. I look forward to your updates and thank you for your unremitting efforts. @irusanov

GamePP avatar Oct 24 '25 08:10 GamePP

After using the 9900X, I understood what this meant; it refers to the CPU's physically die-disabled core.

The 9900X has two CCDs.

CCD0:Core 1 2 3 4 7 8 valid,Core 5 6 blocked CCD1:Core 1 2 5 6 7 8 valid,Core 3 4 blocked

This is not the state of the CCD being softly disabled in the BIOS; it is the state of the CPU being physically isolated.

The other 9900X3D is in a different disabled state.

GamePP avatar Oct 29 '25 10:10 GamePP

Yes, these are the factory fused cores config. It is needed, because to set CO (for example), you need to address the actual physical index of the core and not the logical one. The software donwcore config needs to be added in addition to that, so the software can read soft disabled cores.

irusanov avatar Oct 29 '25 12:10 irusanov

Thank you for your contribution, which enabled PawnIO to support CO. @irusanov

GamePP avatar Nov 13 '25 06:11 GamePP

Hi, it does not support CO yet, even reading the values.

irusanov avatar Nov 13 '25 12:11 irusanov

We look forward to support read and write operations for RyzenSMU. This is a good start, thank you for your hard work.

GamePP avatar Nov 14 '25 03:11 GamePP