To expand on what solidpixel said:
Most OS' configuration of the control registers and page flags are limited to the kernel, but they often still expose some of that functionality to userland.
For instance, on Windows, you have functions like VirtualAlloc, VirtualAlloc2, VirtualProtect where you can set your own access flags. This is how JIT languages like Java, C#, Javascript, etc, allocate executable memory (or more accurately, using VirtualProtect, change memory to executable). There are a whole load of protection constants available in windows: https://learn.microsoft.com/en-us/windows/win32/Memory/memory-protection-constants. Some other fun ones include PAGE_GUARD which is useful for debugging memory overruns. Notable here are the flags PAGE_NOCACHE and PAGE_WRITECOMBINE. In general, you rarely use these, except when communicating with specific devices.
But as solidpixel said, the user mode GPU driver doesn't actually use these. Instead they call D3DKMTCreateAllocation (or pfnAllocateCb when running in D3D10 or greater) and pass some driver specific information. In the kernel, those calls both get passed to DxgkDdiCreateAllocation where the Kernel Mode Display Miniport Driver decodes the private data, and sets members in the allocation info structures, namely pCreateAllocation->pAllocationInfo[i].Flags to indicate the page protections and memory access flags. After DxgkDdiCreateAllocation returns, VidMM will take the information about the allocation and work to secure regions of memory on the CPU and GPU as needed. For CPU memory VidMM is in complete control. For GPU memory, VidMM gets broad control over the protection flags and location (including to some degree, paging structure), but asks the Display Miniport Driver to handle the implementation details on how its paging structure works.