For memory management, GRUB2 fetches the memory map from the firmware (e820 under BIOS, BootServices::GetMemoryMap under EFI), and hands the usable memory regions to its memory allocator to allocate from. GRUB2's memory allocator then provides malloc, memalign, and free. (It also has some special functions for things like allocating low memory, needed for some system operations such as the CPU setup mentioned below.)
In the BIOS version, GRUB2 is entered in 16-bit real mode, and it transitions to 32-bit protected mode; it then has its own memory map. In the 32-bit and 64-bit EFI versions, the firmware transitions to 32-bit or 64-bit protected mode before calling GRUB2. (In all cases, there's no actual protection and the segment bases are all 0, though 64-bit mode does actually require a page table.)
However, GRUB2 normally only runs on the boot CPU ("BSP", bootstrap processor). We have to initialize the non-boot CPUs ("APs", application processors) ourselves. To do that, we allocate an aligned region of low memory, copy some bootstrap code and data into that memory, and send each processor an INIT (to reset them) and a startup inter-processor interrupt (SIPI) that forces them to jump to that address in low memory. We then transition them from 16-bit real mode to either 32-bit or 64-bit protected mode ourselves. (In the case of 64-bit protected mode, we set up paging by using the same page-table address that the firmware set up on the BSP, so that they all have the same memory map.) With that done, the AP can then run C code. Then we put the AP to sleep using mwait, waiting for work to do. When we want them to do something, we hand them a function pointer and a pointer-sized parameter.
In the BIOS version, GRUB2 is entered in 16-bit real mode, and it transitions to 32-bit protected mode; it then has its own memory map. In the 32-bit and 64-bit EFI versions, the firmware transitions to 32-bit or 64-bit protected mode before calling GRUB2. (In all cases, there's no actual protection and the segment bases are all 0, though 64-bit mode does actually require a page table.)
However, GRUB2 normally only runs on the boot CPU ("BSP", bootstrap processor). We have to initialize the non-boot CPUs ("APs", application processors) ourselves. To do that, we allocate an aligned region of low memory, copy some bootstrap code and data into that memory, and send each processor an INIT (to reset them) and a startup inter-processor interrupt (SIPI) that forces them to jump to that address in low memory. We then transition them from 16-bit real mode to either 32-bit or 64-bit protected mode ourselves. (In the case of 64-bit protected mode, we set up paging by using the same page-table address that the firmware set up on the BSP, so that they all have the same memory map.) With that done, the AP can then run C code. Then we put the AP to sleep using mwait, waiting for work to do. When we want them to do something, we hand them a function pointer and a pointer-sized parameter.