[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.
This commit is contained in:
Drew Galbraith 2023-08-01 17:46:26 -07:00
parent 8f84f8c3ca
commit 48c6e5b3a4
12 changed files with 62 additions and 18 deletions

View File

@ -27,8 +27,11 @@ PciReader::PciReader() {
header_ = PciHeader(vaddr, 0, 0, 0); header_ = PciHeader(vaddr, 0, 0, 0);
} }
uint64_t PciReader::GetAhciPhysical() { z_cap_t PciReader::GetAhciVmmo() {
return phys_mem_offset_ + achi_device_offset_; 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, void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev,

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <ztypes.h>
struct PciDeviceHeader { struct PciDeviceHeader {
uint16_t vendor_id; uint16_t vendor_id;
@ -17,16 +18,19 @@ struct PciDeviceHeader {
uint8_t bist; uint8_t bist;
} __attribute__((packed)); } __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 { class PciReader {
public: public:
PciReader(); PciReader();
uint64_t GetAhciPhysical(); z_cap_t GetAhciVmmo();
private: private:
PciDeviceHeader* header_; 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; uint64_t achi_device_offset_ = 0;

View File

@ -13,7 +13,7 @@ struct YellowstoneGetReq {
struct YellowstoneGetRegistrationResp {}; struct YellowstoneGetRegistrationResp {};
struct YellowstoneGetAhciResp { struct YellowstoneGetAhciResp {
uint64_t type; uint64_t type;
uint64_t ahci_phys_offset; uint64_t ahci_length;
}; };
// Has a denali cap attached. // Has a denali cap attached.

View File

@ -4,12 +4,6 @@
#include "include/yellowstone.h" #include "include/yellowstone.h"
namespace {
const uint64_t kPciSize = 0x1000;
} // namespace
YellowstoneStub::YellowstoneStub(z_cap_t yellowstone_cap) YellowstoneStub::YellowstoneStub(z_cap_t yellowstone_cap)
: yellowstone_stub_(EndpointClient::AdoptEndpoint(yellowstone_cap)) {} : yellowstone_stub_(EndpointClient::AdoptEndpoint(yellowstone_cap)) {}
@ -18,10 +12,10 @@ glcr::ErrorOr<MappedMemoryRegion> YellowstoneStub::GetAhciConfig() {
.type = kYellowstoneGetAhci, .type = kYellowstoneGetAhci,
}; };
ASSIGN_OR_RETURN( ASSIGN_OR_RETURN(
YellowstoneGetAhciResp resp, auto resp_cap_pair,
(yellowstone_stub_ (yellowstone_stub_->CallEndpointGetCap<YellowstoneGetReq,
->CallEndpoint<YellowstoneGetReq, YellowstoneGetAhciResp>(req))); YellowstoneGetAhciResp>(req)));
return MappedMemoryRegion::DirectPhysical(resp.ahci_phys_offset, kPciSize); return MappedMemoryRegion::FromCapability(resp_cap_pair.second());
} }
glcr::ErrorOr<ScopedDenaliClient> YellowstoneStub::GetDenali() { glcr::ErrorOr<ScopedDenaliClient> YellowstoneStub::GetDenali() {

View File

@ -8,6 +8,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "hw/gpt.h" #include "hw/gpt.h"
#include "hw/pcie.h"
#include "include/yellowstone.h" #include "include/yellowstone.h"
namespace { namespace {
@ -55,9 +56,11 @@ glcr::ErrorCode YellowstoneServer::HandleRequest(RequestContext& request,
dbgln("Yellowstone::GetAHCI"); dbgln("Yellowstone::GetAHCI");
YellowstoneGetAhciResp resp{ YellowstoneGetAhciResp resp{
.type = kYellowstoneGetAhci, .type = kYellowstoneGetAhci,
.ahci_phys_offset = pci_reader_.GetAhciPhysical(), .ahci_length = kPcieConfigurationSize,
}; };
RET_ERR(response.WriteStruct<YellowstoneGetAhciResp>(resp)); z_cap_t vmmo_cap = pci_reader_.GetAhciVmmo();
RET_ERR(
response.WriteStructWithCap<YellowstoneGetAhciResp>(resp, vmmo_cap));
break; break;
} }
case kYellowstoneGetRegistration: { case kYellowstoneGetRegistration: {

View File

@ -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, SYS3(MemoryObjectCreateContiguous, uint64_t, size, z_cap_t*, vmmo_cap,
uint64_t*, paddr); 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); SYS2(ChannelCreate, z_cap_t*, channel1, z_cap_t*, channel2);
SYS5(ChannelSend, z_cap_t, chan_cap, uint64_t, num_bytes, const void*, data, SYS5(ChannelSend, z_cap_t, chan_cap, uint64_t, num_bytes, const void*, data,
uint64_t, num_caps, z_cap_t*, caps); uint64_t, num_caps, z_cap_t*, caps);

View File

@ -27,6 +27,8 @@ const uint64_t kZionMemoryObjectCreate = 0x30;
const uint64_t kZionMemoryObjectCreatePhysical = 0x31; const uint64_t kZionMemoryObjectCreatePhysical = 0x31;
const uint64_t kZionMemoryObjectCreateContiguous = 0x32; const uint64_t kZionMemoryObjectCreateContiguous = 0x32;
const uint64_t kZionMemoryObjectDuplicate = 0x38;
// IPC Calls // IPC Calls
const uint64_t kZionChannelCreate = 0x40; const uint64_t kZionChannelCreate = 0x40;
const uint64_t kZionChannelSend = 0x41; const uint64_t kZionChannelSend = 0x41;

View File

@ -67,3 +67,13 @@ uint64_t MemoryObject::PageNumberToPhysAddr(uint64_t page_num) {
} }
return *iter; return *iter;
} }
glcr::ErrorOr<glcr::RefPtr<MemoryObject>> FixedMemoryObject::Duplicate(
uint64_t offset, uint64_t length) {
if (offset + length > size()) {
return glcr::INVALID_ARGUMENT;
}
return glcr::StaticCastRefPtr<MemoryObject>(
glcr::MakeRefCounted<FixedMemoryObject>(physical_addr_ + offset, length));
}

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <glacier/container/linked_list.h> #include <glacier/container/linked_list.h>
#include <glacier/memory/ref_ptr.h>
#include <glacier/status/error_or.h>
#include "object/kernel_object.h" #include "object/kernel_object.h"
@ -28,6 +30,11 @@ class MemoryObject : public KernelObject {
void CopyBytesToObject(uint64_t source, uint64_t length); void CopyBytesToObject(uint64_t source, uint64_t length);
virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate(uint64_t offset,
uint64_t length) {
return glcr::UNIMPLEMENTED;
}
protected: protected:
// Hacky to avoid linked_list creation. // Hacky to avoid linked_list creation.
MemoryObject(uint64_t size, bool) : size_(size) {} MemoryObject(uint64_t size, bool) : size_(size) {}
@ -47,6 +54,9 @@ class FixedMemoryObject : public MemoryObject {
FixedMemoryObject(uint64_t physical_addr, uint64_t size) FixedMemoryObject(uint64_t physical_addr, uint64_t size)
: MemoryObject(size, true), physical_addr_(physical_addr) {} : MemoryObject(size, true), physical_addr_(physical_addr) {}
virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate(
uint64_t offset, uint64_t length) override;
private: private:
uint64_t physical_addr_; uint64_t physical_addr_;

View File

@ -29,3 +29,16 @@ z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req) {
*req->paddr = paddr; *req->paddr = paddr;
return glcr::OK; 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<MemoryObject>(vmmo_cap, ZC_WRITE));
ASSIGN_OR_RETURN(
glcr::RefPtr<MemoryObject> new_vmmo,
vmmo_cap->obj<MemoryObject>()->Duplicate(req->base_offset, req->length));
*req->new_vmmo_cap = curr_proc.AddNewCapability(new_vmmo, ZC_WRITE | ZC_READ);
return glcr::OK;
}

View File

@ -5,3 +5,4 @@
z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req); z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req);
z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req); z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req);
z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req); z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req);
z_err_t MemoryObjectDuplicate(ZMemoryObjectDuplicateReq* req);

View File

@ -63,6 +63,7 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req) {
CASE(MemoryObjectCreate); CASE(MemoryObjectCreate);
CASE(MemoryObjectCreatePhysical); CASE(MemoryObjectCreatePhysical);
CASE(MemoryObjectCreateContiguous); CASE(MemoryObjectCreateContiguous);
CASE(MemoryObjectDuplicate);
// syscall/ipc.h // syscall/ipc.h
CASE(ChannelCreate); CASE(ChannelCreate);
CASE(ChannelSend); CASE(ChannelSend);