mirror of
https://github.com/Bareflank/hypervisor
synced 2026-08-17 06:23:04 -04:00
Merge pull request #934 from rianquinn/master
add support for more than 64 cores
This commit is contained in:
commit
b4af35e31b
5 changed files with 57 additions and 81 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue