Merge pull request #934 from rianquinn/master

add support for more than 64 cores
This commit is contained in:
Rian Quinn 2021-02-24 08:23:52 -07:00 committed by GitHub
commit b4af35e31b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 81 deletions

View file

@ -441,12 +441,13 @@ namespace mk
// [x] implement error on VMX instructions on Intel
// [x] implement error on SVM instructions on AMD
// [ ] implement fix for vmexit first crash (vmxoff and check state)
// [x] implement fix for 128 cores on Windows
// [x] implement alloc page
// [ ] implement free page
// [x] implement virt_to_phys
// [ ] implement make ack
// [ ] implement debugging mutex/transaction support
// [ ] implement Windows support
// [x] implement Windows support
// [ ] implement UEFI support
// [ ] implement huge_pool
// [ ] implement huge

View file

@ -166,7 +166,6 @@ alloc_and_start_the_vmm(struct start_vmm_args_t const *const args)
}
g_vmm_status = VMM_STATUS_RUNNING;
return LOADER_SUCCESS;
start_vmm_per_cpu_failed:

View file

@ -59,7 +59,6 @@
#include <map_root_vp_state.h>
#include <platform.h>
#include <send_command_report_on.h>
#include <serial_write.h>
#include <types.h>
/**

View file

@ -43,46 +43,6 @@
#include <pto.h>
#include <types.h>
/**
* <!-- description -->
* @brief The microkernel needs to be able to walk its own page tables and
* to do that, it expects the that all of the page tables are mapped in
* the direct map (allowing the microkernel to look up a virtual address
* given a physical address). When the map function maps a virtual address,
* it might be required to allocate new page tables. These newly allocated
* page tables are recorded and mapped once the map function is complete
* using this function.
*
* <!-- inputs/outputs -->
* @param virt the virtual address of the page table
* @param pml4t the root page table to place the resulting map
* @return 0 on success, LOADER_FAILURE on failure.
*/
int64_t
map_4k_page_table(void const *const virt, struct pml4t_t *const pml4t)
{
uint64_t phys;
uint64_t const base_virt = HYPERVISOR_DIRECT_MAP_ADDR;
bfelf_elf64_word const rw = bfelf_pf_w | bfelf_pf_r;
if (((void *)0) == virt) {
return LOADER_SUCCESS;
}
phys = platform_virt_to_phys(virt);
if (((uint64_t)0) == phys) {
BFERROR("platform_virt_to_phys failed\n");
return LOADER_FAILURE;
}
if (map_4k_page(phys + base_virt, phys, rw, pml4t)) {
BFERROR("map_4k_page failed\n");
return LOADER_FAILURE;
}
return LOADER_SUCCESS;
}
/**
* <!-- description -->
* @brief This function maps a 4k page given a physical address into a
@ -112,9 +72,21 @@ map_4k_page(
struct pt_t *pt = ((void *)0);
struct pte_t *pte = ((void *)0);
void *pdpt_to_map = ((void *)0);
void *pdt_to_map = ((void *)0);
void *pt_to_map = ((void *)0);
/**
* TODO:
* - We need to map in any page tables that we allocate. The problem is,
* we cannot use a recursive function to do this as it could result
* in a stack overflow in the kernel. Likely, the best option would
* be to convert this function into a private _impl, and provide it
* with a queue that we can push allocated pages to so that the wrapper
* can map any pages that are pushed. This way, as we map, we can
* continue to push pages until the process finally stops. Since this
* code is common between Windows/Linux/UEFI, we will need to implement
* this queue from scratch. For now, we seem to be ok without this
* additional logic, but it is possible that the microkernel could end
* up with a page fault while it is trying to walk page tables as it
* wouldn't have all of the memory properly mapped.
*/
if ((virt & (HYPERVISOR_PAGE_SIZE - ((uint64_t)1))) != ((uint64_t)0)) {
BFERROR("virt is not page aligned: 0x%" PRIx64 "\n", virt);
@ -137,24 +109,22 @@ map_4k_page(
pdpt = pml4t->tables[pml4to(virt)];
if (((void *)0) == pdpt) {
pdpt = alloc_pdpt(pml4t, virt);
pdpt_to_map = pdpt;
}
pdt = pdpt->tables[pdpto(virt)];
if (((void *)0) == pdt) {
pdt = alloc_pdt(pdpt, virt);
pdt_to_map = pdt;
}
pt = pdt->tables[pdto(virt)];
if (((void *)0) == pt) {
pt = alloc_pt(pdt, virt);
pt_to_map = pt;
}
pte = &pt->entires[pto(virt)];
if (pte->p != ((uint64_t)0)) {
goto SUCCESS;
BFERROR("virt already mapped: 0x%" PRIx64 "\n", virt);
return LOADER_FAILURE;
}
pte->phys = (phys >> HYPERVISOR_PAGE_SHIFT);
@ -169,22 +139,5 @@ map_4k_page(
pte->nx = ((uint64_t)1);
}
SUCCESS:
if (map_4k_page_table(pdpt_to_map, pml4t)) {
BFERROR("map_4k_page_table failed\n");
return LOADER_FAILURE;
}
if (map_4k_page_table(pdt_to_map, pml4t)) {
BFERROR("map_4k_page_table failed\n");
return LOADER_FAILURE;
}
if (map_4k_page_table(pt_to_map, pml4t)) {
BFERROR("map_4k_page_table failed\n");
return LOADER_FAILURE;
}
return LOADER_SUCCESS;
}

View file

@ -303,8 +303,7 @@ platform_copy_to_user(
uint32_t
platform_num_online_cpus(void)
{
KAFFINITY k_affin;
return KeQueryActiveProcessorCount(&k_affin);
return KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
}
/**
@ -324,17 +323,30 @@ platform_num_online_cpus(void)
static int64_t
platform_on_each_cpu_forward(platform_per_cpu_func const func)
{
(void)func;
int64_t ret = 0;
uint32_t cpu;
for (cpu = 0; cpu < platform_num_online_cpus(); ++cpu) {
KAFFINITY old = KeSetSystemAffinityThreadEx(1ULL << cpu);
ret = func(cpu);
KeRevertToUserAffinityThreadEx(old);
ULONG Count;
ULONG ProcIndex;
PROCESSOR_NUMBER ProcNumber;
Count = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
for (ProcIndex = 0; ProcIndex < Count; ++ProcIndex) {
GROUP_AFFINITY affinity = {0};
GROUP_AFFINITY previous = {0};
KeGetProcessorNumberFromIndex(ProcIndex, &ProcNumber);
affinity.Mask = (1ULL << ProcNumber.Number);
affinity.Group = ProcNumber.Group;
KeSetSystemGroupAffinityThread(&affinity, &previous);
ret = func(ProcIndex);
KeRevertToUserGroupAffinityThread(&previous);
if (ret) {
BFERROR("platform_per_cpu_func failed\n");
break;
return ret;
}
}
@ -359,16 +371,28 @@ static int64_t
platform_on_each_cpu_reverse(platform_per_cpu_func const func)
{
int64_t ret = 0;
uint32_t cpu;
for (cpu = platform_num_online_cpus(); cpu > 0U; --cpu) {
KAFFINITY old = KeSetSystemAffinityThreadEx(1ULL << (cpu - 1U));
ret = func(cpu - 1U);
KeRevertToUserAffinityThreadEx(old);
ULONG Count;
ULONG ProcIndex;
PROCESSOR_NUMBER ProcNumber;
Count = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
for (ProcIndex = Count; ProcIndex > 0; --ProcIndex) {
GROUP_AFFINITY affinity = {0};
GROUP_AFFINITY previous = {0};
KeGetProcessorNumberFromIndex(ProcIndex - 1, &ProcNumber);
affinity.Mask = (1ULL << ProcNumber.Number);
affinity.Group = ProcNumber.Group;
KeSetSystemGroupAffinityThread(&affinity, &previous);
ret = func(ProcIndex - 1);
KeRevertToUserGroupAffinityThread(&previous);
if (ret) {
BFERROR("platform_per_cpu_func failed\n");
break;
return ret;
}
}