[app][uefi] Place linux kernel at identity mapped virtual memory addresses
This commit is contained in:
@@ -259,7 +259,7 @@ void vmm_context_switch(vmm_aspace_t *oldspace, vmm_aspace_t *newaspace);
|
||||
|
||||
/* set the current user aspace as active on the current thread.
|
||||
NULL is a valid argument, which unmaps the current user address space */
|
||||
void vmm_set_active_aspace(vmm_aspace_t *aspace);
|
||||
vmm_aspace_t* vmm_set_active_aspace(vmm_aspace_t *aspace);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <lk/err.h>
|
||||
#include <lk/trace.h>
|
||||
#include <string.h>
|
||||
#include "kernel/thread.h"
|
||||
#include "vm_priv.h"
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
@@ -751,21 +752,24 @@ void vmm_context_switch(vmm_aspace_t *oldspace, vmm_aspace_t *newaspace) {
|
||||
arch_mmu_context_switch(newaspace ? &newaspace->arch_aspace : NULL);
|
||||
}
|
||||
|
||||
void vmm_set_active_aspace(vmm_aspace_t *aspace) {
|
||||
vmm_aspace_t* vmm_set_active_aspace(vmm_aspace_t *aspace) {
|
||||
LTRACEF("aspace %p\n", aspace);
|
||||
|
||||
thread_t *t = get_current_thread();
|
||||
DEBUG_ASSERT(t);
|
||||
|
||||
if (aspace == t->aspace)
|
||||
return;
|
||||
return aspace;
|
||||
|
||||
/* grab the thread lock and switch to the new address space */
|
||||
THREAD_LOCK(state);
|
||||
vmm_aspace_t *old = t->aspace;
|
||||
t->aspace = aspace;
|
||||
vmm_context_switch(old, t->aspace);
|
||||
if (old != aspace) {
|
||||
t->aspace = aspace;
|
||||
vmm_context_switch(old, t->aspace);
|
||||
}
|
||||
THREAD_UNLOCK(state);
|
||||
return old;
|
||||
}
|
||||
|
||||
static void dump_region(const vmm_region_t *r) {
|
||||
|
||||
@@ -22,6 +22,79 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static vmm_aspace_t *old_aspace = nullptr;
|
||||
|
||||
vmm_aspace_t *set_boot_aspace() {
|
||||
static vmm_aspace_t *aspace = nullptr;
|
||||
if (aspace == nullptr) {
|
||||
auto err = vmm_create_aspace(&aspace, "linux_kernel", 0);
|
||||
if (err) {
|
||||
printf("Failed to create address space for linux kernel %d\n", err);
|
||||
return nullptr;
|
||||
}
|
||||
old_aspace = vmm_set_active_aspace(aspace);
|
||||
}
|
||||
return aspace;
|
||||
}
|
||||
|
||||
void restore_aspace() { vmm_set_active_aspace(old_aspace); }
|
||||
|
||||
void *identity_map(void *addr, size_t size) {
|
||||
size = ROUNDUP(size, PAGE_SIZE);
|
||||
auto vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||
paddr_t pa{};
|
||||
uint flags{};
|
||||
auto aspace = set_boot_aspace();
|
||||
auto err = arch_mmu_query(&aspace->arch_aspace, vaddr, &pa, &flags);
|
||||
if (err) {
|
||||
printf("Failed to query physical address for memory 0x%p\n", addr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
err = arch_mmu_unmap(&aspace->arch_aspace, vaddr, size / PAGE_SIZE);
|
||||
if (err) {
|
||||
printf("Failed to unmap virtual address 0x%lx\n", vaddr);
|
||||
return nullptr;
|
||||
}
|
||||
arch_mmu_map(&aspace->arch_aspace, pa, pa, size / PAGE_SIZE, flags);
|
||||
if (err) {
|
||||
printf("Failed to identity map physical address 0x%lx\n", pa);
|
||||
return nullptr;
|
||||
}
|
||||
printf("Identity mapped physical address 0x%lx flags 0x%x\n", pa, flags);
|
||||
|
||||
return reinterpret_cast<void *>(pa);
|
||||
}
|
||||
|
||||
void *alloc_page(size_t size, size_t align_log2) {
|
||||
auto aspace = set_boot_aspace();
|
||||
void *vptr{};
|
||||
status_t err = vmm_alloc_contiguous(aspace, "uefi_program", size, &vptr,
|
||||
align_log2, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed to allocate memory for uefi program %d\n", err);
|
||||
return nullptr;
|
||||
}
|
||||
return identity_map(vptr, size);
|
||||
}
|
||||
|
||||
void *alloc_page(void *addr, size_t size, size_t align_log2) {
|
||||
if (addr == nullptr) {
|
||||
return alloc_page(size, align_log2);
|
||||
}
|
||||
auto err =
|
||||
vmm_alloc_contiguous(set_boot_aspace(), "uefi_program", size, &addr,
|
||||
align_log2, VMM_FLAG_VALLOC_SPECIFIC, 0);
|
||||
if (err) {
|
||||
printf(
|
||||
"Failed to allocate memory for uefi program @ fixed address 0x%p %d , "
|
||||
"falling back to non-fixed allocation\n",
|
||||
addr, err);
|
||||
return alloc_page(size, align_log2);
|
||||
}
|
||||
return identity_map(addr, size);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
EfiStatus unload(EfiHandle handle) { return SUCCESS; }
|
||||
@@ -34,7 +107,7 @@ bool guid_eq(const EfiGuid *a, const EfiGuid &b) {
|
||||
return memcmp(a, &b, sizeof(*a)) == 0;
|
||||
}
|
||||
|
||||
EfiStatus handle_protocol(const EfiHandle handle, const EfiGuid *protocol,
|
||||
EfiStatus handle_protocol(EfiHandle handle, const EfiGuid *protocol,
|
||||
void **intf) {
|
||||
if (guid_eq(protocol, LOADED_IMAGE_PROTOCOL_GUID)) {
|
||||
printf("handle_protocol(%p, LOADED_IMAGE_PROTOCOL_GUID, %p);\n", handle,
|
||||
@@ -115,6 +188,13 @@ EfiStatus get_memory_map(size_t *memory_map_size,
|
||||
memory_map[i].virtual_start = region->base;
|
||||
memory_map[i].physical_start = memory_map[i].virtual_start;
|
||||
memory_map[i].number_of_pages = region->size / PAGE_SIZE;
|
||||
paddr_t pa{};
|
||||
uint flags{};
|
||||
status_t err =
|
||||
arch_mmu_query(&aspace->arch_aspace, region->base, &pa, &flags);
|
||||
if (err >= 0) {
|
||||
memory_map[i].physical_start = pa;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#ifndef __BOOT_SERVICE_PROVIDER_
|
||||
#define __BOOT_SERVICE_PROVIDER_
|
||||
|
||||
#include "arch/defines.h"
|
||||
#include "boot_service.h"
|
||||
#include "kernel/vm.h"
|
||||
#include "system_table.h"
|
||||
|
||||
void setup_boot_service_table(EfiBootService *service);
|
||||
@@ -90,5 +92,9 @@ struct EFI_LOADED_IMAGE_PROTOCOL {
|
||||
};
|
||||
|
||||
static constexpr size_t EFI_LOADED_IMAGE_PROTOCOL_REVISION = 0x1000;
|
||||
vmm_aspace_t *set_boot_aspace();
|
||||
|
||||
void *alloc_page(void *addr, size_t size, size_t align_log2 = PAGE_SIZE_SHIFT);
|
||||
void *alloc_page(size_t size, size_t align_log2 = PAGE_SIZE_SHIFT);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -64,7 +64,7 @@ using EfiTimerDelay = enum EFI_TIMER_DELAY {
|
||||
TIMER_RELATIVE
|
||||
};
|
||||
|
||||
using EFI_MEMORY_TYPE = enum {
|
||||
enum EFI_MEMORY_TYPE {
|
||||
RESERVED_MEMORY_TYPE,
|
||||
LOADER_CODE,
|
||||
LOADER_DATA,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "arch/mmu.h"
|
||||
#include "boot_service.h"
|
||||
#include "boot_service_provider.h"
|
||||
#include "defer.h"
|
||||
@@ -28,32 +29,6 @@ constexpr auto EFI_SYSTEM_TABLE_SIGNATURE =
|
||||
|
||||
using EfiEntry = int (*)(void *, struct EfiSystemTable *);
|
||||
|
||||
void *alloc_page(size_t size) {
|
||||
void *vptr{};
|
||||
status_t err =
|
||||
vmm_alloc(vmm_get_kernel_aspace(), "uefi_program", size, &vptr, 0, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed to allocate memory for uefi program %d\n", err);
|
||||
return nullptr;
|
||||
}
|
||||
return vptr;
|
||||
}
|
||||
|
||||
void *alloc_page(void *addr, size_t size) {
|
||||
if (addr == nullptr) {
|
||||
return alloc_page(size);
|
||||
}
|
||||
auto err = vmm_alloc(vmm_get_kernel_aspace(), "uefi_program", size, &addr,
|
||||
PAGE_SIZE_SHIFT, VMM_FLAG_VALLOC_SPECIFIC, 0);
|
||||
if (err) {
|
||||
printf("Failed to allocate memory for uefi program @ fixed address %p %d , "
|
||||
"falling back to non-fixed allocation\n",
|
||||
addr, err);
|
||||
return alloc_page(size);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
template <typename T> void fill(T *data, size_t skip, uint8_t begin = 0) {
|
||||
auto ptr = reinterpret_cast<char *>(data);
|
||||
for (size_t i = 0; i < sizeof(T); i++) {
|
||||
@@ -265,8 +240,9 @@ int load_sections_and_execute(bdev_t *dev,
|
||||
const auto &last_section = section_header[sections - 1];
|
||||
const auto virtual_size =
|
||||
last_section.VirtualAddress + last_section.Misc.VirtualSize;
|
||||
const auto image_base = reinterpret_cast<char *>(alloc_page(
|
||||
reinterpret_cast<void *>(optional_header->ImageBase), virtual_size));
|
||||
const auto image_base = reinterpret_cast<char *>(
|
||||
alloc_page(reinterpret_cast<void *>(optional_header->ImageBase),
|
||||
virtual_size, 21 /* Kernel requires 2MB alignment */));
|
||||
if (image_base == nullptr) {
|
||||
return -7;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user