From 48c6e5b3a47491ccdda5f07c2e393c68a14af064 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Tue, 1 Aug 2023 17:46:26 -0700 Subject: [PATCH] [zion] Add a method for duplicating and scoping down VMMOs. Use the AHCI section of the PCI config as an example POC of this. We can now pass a memory capability instead of just the physical address. --- sys/yellowstone/hw/pcie.cpp | 7 +++++-- sys/yellowstone/hw/pcie.h | 10 +++++++--- sys/yellowstone/include/yellowstone.h | 2 +- sys/yellowstone/stub/yellowstone_stub.cpp | 14 ++++---------- sys/yellowstone/yellowstone_server.cpp | 7 +++++-- zion/include/zcall.h | 3 +++ zion/include/ztypes.h | 2 ++ zion/object/memory_object.cpp | 10 ++++++++++ zion/object/memory_object.h | 10 ++++++++++ zion/syscall/memory_object.cpp | 13 +++++++++++++ zion/syscall/memory_object.h | 1 + zion/syscall/syscall.cpp | 1 + 12 files changed, 62 insertions(+), 18 deletions(-) diff --git a/sys/yellowstone/hw/pcie.cpp b/sys/yellowstone/hw/pcie.cpp index 9f08ab5..19b2c8d 100644 --- a/sys/yellowstone/hw/pcie.cpp +++ b/sys/yellowstone/hw/pcie.cpp @@ -27,8 +27,11 @@ PciReader::PciReader() { header_ = PciHeader(vaddr, 0, 0, 0); } -uint64_t PciReader::GetAhciPhysical() { - return phys_mem_offset_ + achi_device_offset_; +z_cap_t PciReader::GetAhciVmmo() { + uint64_t new_cap; + check(ZMemoryObjectDuplicate(gBootPciVmmoCap, achi_device_offset_, + kPcieConfigurationSize, &new_cap)); + return new_cap; } void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, diff --git a/sys/yellowstone/hw/pcie.h b/sys/yellowstone/hw/pcie.h index 0f9c268..d9e5778 100644 --- a/sys/yellowstone/hw/pcie.h +++ b/sys/yellowstone/hw/pcie.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct PciDeviceHeader { uint16_t vendor_id; @@ -17,16 +18,19 @@ struct PciDeviceHeader { uint8_t bist; } __attribute__((packed)); +// TODO: Figure out if it safe to hardcode this. +// For the memory mapped access to PCI, it may be true that +// each configuration item is always the size of a single page. +const uint64_t kPcieConfigurationSize = 0x1000; + class PciReader { public: PciReader(); - uint64_t GetAhciPhysical(); + z_cap_t GetAhciVmmo(); private: PciDeviceHeader* header_; - // FIXME: Don't hardcode this (It is available from ACPI). - uint64_t phys_mem_offset_ = 0xB000'0000; uint64_t achi_device_offset_ = 0; diff --git a/sys/yellowstone/include/yellowstone.h b/sys/yellowstone/include/yellowstone.h index 5ea6c62..ba1bb78 100644 --- a/sys/yellowstone/include/yellowstone.h +++ b/sys/yellowstone/include/yellowstone.h @@ -13,7 +13,7 @@ struct YellowstoneGetReq { struct YellowstoneGetRegistrationResp {}; struct YellowstoneGetAhciResp { uint64_t type; - uint64_t ahci_phys_offset; + uint64_t ahci_length; }; // Has a denali cap attached. diff --git a/sys/yellowstone/stub/yellowstone_stub.cpp b/sys/yellowstone/stub/yellowstone_stub.cpp index 9cec8c5..27b5ae7 100644 --- a/sys/yellowstone/stub/yellowstone_stub.cpp +++ b/sys/yellowstone/stub/yellowstone_stub.cpp @@ -4,12 +4,6 @@ #include "include/yellowstone.h" -namespace { - -const uint64_t kPciSize = 0x1000; - -} // namespace - YellowstoneStub::YellowstoneStub(z_cap_t yellowstone_cap) : yellowstone_stub_(EndpointClient::AdoptEndpoint(yellowstone_cap)) {} @@ -18,10 +12,10 @@ glcr::ErrorOr YellowstoneStub::GetAhciConfig() { .type = kYellowstoneGetAhci, }; ASSIGN_OR_RETURN( - YellowstoneGetAhciResp resp, - (yellowstone_stub_ - ->CallEndpoint(req))); - return MappedMemoryRegion::DirectPhysical(resp.ahci_phys_offset, kPciSize); + auto resp_cap_pair, + (yellowstone_stub_->CallEndpointGetCap(req))); + return MappedMemoryRegion::FromCapability(resp_cap_pair.second()); } glcr::ErrorOr YellowstoneStub::GetDenali() { diff --git a/sys/yellowstone/yellowstone_server.cpp b/sys/yellowstone/yellowstone_server.cpp index e1d965f..78f4d8c 100644 --- a/sys/yellowstone/yellowstone_server.cpp +++ b/sys/yellowstone/yellowstone_server.cpp @@ -8,6 +8,7 @@ #include #include "hw/gpt.h" +#include "hw/pcie.h" #include "include/yellowstone.h" namespace { @@ -55,9 +56,11 @@ glcr::ErrorCode YellowstoneServer::HandleRequest(RequestContext& request, dbgln("Yellowstone::GetAHCI"); YellowstoneGetAhciResp resp{ .type = kYellowstoneGetAhci, - .ahci_phys_offset = pci_reader_.GetAhciPhysical(), + .ahci_length = kPcieConfigurationSize, }; - RET_ERR(response.WriteStruct(resp)); + z_cap_t vmmo_cap = pci_reader_.GetAhciVmmo(); + RET_ERR( + response.WriteStructWithCap(resp, vmmo_cap)); break; } case kYellowstoneGetRegistration: { diff --git a/zion/include/zcall.h b/zion/include/zcall.h index bce4bd8..4ac2748 100644 --- a/zion/include/zcall.h +++ b/zion/include/zcall.h @@ -107,6 +107,9 @@ SYS3(MemoryObjectCreatePhysical, uint64_t, paddr, uint64_t, size, z_cap_t*, SYS3(MemoryObjectCreateContiguous, uint64_t, size, z_cap_t*, vmmo_cap, uint64_t*, paddr); +SYS4(MemoryObjectDuplicate, z_cap_t, vmmo_cap, uint64_t, base_offset, uint64_t, + length, z_cap_t*, new_vmmo_cap); + SYS2(ChannelCreate, z_cap_t*, channel1, z_cap_t*, channel2); SYS5(ChannelSend, z_cap_t, chan_cap, uint64_t, num_bytes, const void*, data, uint64_t, num_caps, z_cap_t*, caps); diff --git a/zion/include/ztypes.h b/zion/include/ztypes.h index c8ddaeb..f6f124b 100644 --- a/zion/include/ztypes.h +++ b/zion/include/ztypes.h @@ -27,6 +27,8 @@ const uint64_t kZionMemoryObjectCreate = 0x30; const uint64_t kZionMemoryObjectCreatePhysical = 0x31; const uint64_t kZionMemoryObjectCreateContiguous = 0x32; +const uint64_t kZionMemoryObjectDuplicate = 0x38; + // IPC Calls const uint64_t kZionChannelCreate = 0x40; const uint64_t kZionChannelSend = 0x41; diff --git a/zion/object/memory_object.cpp b/zion/object/memory_object.cpp index 46a51ac..1149a2d 100644 --- a/zion/object/memory_object.cpp +++ b/zion/object/memory_object.cpp @@ -67,3 +67,13 @@ uint64_t MemoryObject::PageNumberToPhysAddr(uint64_t page_num) { } return *iter; } + +glcr::ErrorOr> FixedMemoryObject::Duplicate( + uint64_t offset, uint64_t length) { + if (offset + length > size()) { + return glcr::INVALID_ARGUMENT; + } + + return glcr::StaticCastRefPtr( + glcr::MakeRefCounted(physical_addr_ + offset, length)); +} diff --git a/zion/object/memory_object.h b/zion/object/memory_object.h index b2fdc29..aa63c77 100644 --- a/zion/object/memory_object.h +++ b/zion/object/memory_object.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include "object/kernel_object.h" @@ -28,6 +30,11 @@ class MemoryObject : public KernelObject { void CopyBytesToObject(uint64_t source, uint64_t length); + virtual glcr::ErrorOr> Duplicate(uint64_t offset, + uint64_t length) { + return glcr::UNIMPLEMENTED; + } + protected: // Hacky to avoid linked_list creation. MemoryObject(uint64_t size, bool) : size_(size) {} @@ -47,6 +54,9 @@ class FixedMemoryObject : public MemoryObject { FixedMemoryObject(uint64_t physical_addr, uint64_t size) : MemoryObject(size, true), physical_addr_(physical_addr) {} + virtual glcr::ErrorOr> Duplicate( + uint64_t offset, uint64_t length) override; + private: uint64_t physical_addr_; diff --git a/zion/syscall/memory_object.cpp b/zion/syscall/memory_object.cpp index c61c50d..6e58afc 100644 --- a/zion/syscall/memory_object.cpp +++ b/zion/syscall/memory_object.cpp @@ -29,3 +29,16 @@ z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req) { *req->paddr = paddr; return glcr::OK; } + +z_err_t MemoryObjectDuplicate(ZMemoryObjectDuplicateReq* req) { + auto& curr_proc = gScheduler->CurrentProcess(); + auto vmmo_cap = curr_proc.GetCapability(req->vmmo_cap); + // FIXME: Check a duplication permission here. + RET_ERR(ValidateCapability(vmmo_cap, ZC_WRITE)); + + ASSIGN_OR_RETURN( + glcr::RefPtr new_vmmo, + vmmo_cap->obj()->Duplicate(req->base_offset, req->length)); + *req->new_vmmo_cap = curr_proc.AddNewCapability(new_vmmo, ZC_WRITE | ZC_READ); + return glcr::OK; +} diff --git a/zion/syscall/memory_object.h b/zion/syscall/memory_object.h index 3938eea..155be97 100644 --- a/zion/syscall/memory_object.h +++ b/zion/syscall/memory_object.h @@ -5,3 +5,4 @@ z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req); z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req); z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req); +z_err_t MemoryObjectDuplicate(ZMemoryObjectDuplicateReq* req); diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index 0a23048..7007cfc 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -63,6 +63,7 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req) { CASE(MemoryObjectCreate); CASE(MemoryObjectCreatePhysical); CASE(MemoryObjectCreateContiguous); + CASE(MemoryObjectDuplicate); // syscall/ipc.h CASE(ChannelCreate); CASE(ChannelSend);