Compare commits

...

11 Commits

Author SHA1 Message Date
Drew Galbraith fb458e6fd4 [Teton] Draw a green square into the framebuffer. 2023-11-15 19:20:52 -08:00
Drew Galbraith 28719ac726 [Glacier] Format LinkedList code. 2023-11-15 18:59:12 -08:00
Drew Galbraith e4deca716c [Zion] Use range based for loop on LinkedList as POC. 2023-11-15 18:50:58 -08:00
Drew Galbraith 569945f06d [Glacier] Cleanup formatting for Array and Vector. 2023-11-15 18:43:35 -08:00
Drew Galbraith 1c7eacd977 [Build] Separate 'ninja && ninja install' so the script exits if they fail. 2023-11-15 18:38:31 -08:00
Drew Galbraith 84d3caaba5 [Teton] Get framebuffer info from yellowstone. 2023-11-15 16:42:00 -08:00
Drew Galbraith 0ced0032ff Move qemu startup to its own script.
This causes us to reinstall and rebuild the image each time
we run qemu. This necessary now that we are loading files
from the disk because cmake makes it tricky (impossible?) to
have a command rely on a different target being "installed".

Because of this, updates to the teton executable were not being
picked up on the image.
2023-11-15 16:39:36 -08:00
Drew Galbraith 46d02e5eae [Zion] Remove sleeping messages. 2023-11-15 16:27:09 -08:00
Drew Galbraith 1ccbf5e12e [Yellowstone] Disable most log messages in yellowstone. 2023-11-15 16:26:15 -08:00
Drew Galbraith c080c61398 [Denali] Reduce noise on AHCI interrupt. 2023-11-15 16:21:19 -08:00
Drew Galbraith a3defbba53 [Mammoth] Fix formatting in init debug message. 2023-11-15 16:20:56 -08:00
19 changed files with 243 additions and 169 deletions

View File

@ -16,28 +16,3 @@ add_subdirectory(zion)
add_subdirectory(lib)
add_subdirectory(yunq)
add_subdirectory(sys)
# Use machine q35 to access PCI devices.
set(QEMU_CMD qemu-system-x86_64 -machine q35 -d guest_errors -m 1G -serial stdio -hda disk.img)
add_custom_command(
OUTPUT disk.img
COMMAND sudo sh ../scripts/build_image.sh disk.img
DEPENDS zion yellowstone denali victoriafalls
USES_TERMINAL
)
add_custom_target(qemu
COMMAND ${QEMU_CMD}
DEPENDS disk.img
USES_TERMINAL)
add_custom_target(qemu-dbg
COMMAND ${QEMU_CMD} -S -s
DEPENDS disk.img
USES_TERMINAL)
add_custom_target(qemu-int
COMMAND ${QEMU_CMD} -d int
DEPENDS disk.img
USES_TERMINAL)

View File

@ -9,24 +9,47 @@ namespace glcr {
template <typename T>
class Array {
public:
// Constructors.
Array() : data_(nullptr), size_(0) {}
explicit Array(uint64_t size) : data_(new T[size]), size_(size) {}
Array(const ArrayView<T> view) : Array(view.size()) {
for (uint64_t i = 0; i < size_; i++) {
data_[i] = view[i];
}
}
Array(const Array&) = delete;
Array& operator=(const Array&) = delete;
Array(Array&& other) : data_(other.data_), size_(other.size_) {
Array(Array&&);
Array& operator=(Array&&);
explicit Array(uint64_t size) : data_(new T[size]), size_(size) {}
Array(const ArrayView<T>& view);
~Array() {
if (data_) {
delete[] data_;
}
}
// Accessors.
T& operator[](uint64_t index) { return data_[index]; }
const T& operator[](uint64_t index) const { return data_[index]; }
T* RawPtr() { return data_; }
const T* RawPtr() const { return data_; }
uint64_t size() const { return size_; }
bool empty() const { return size_ == 0; }
private:
T* data_;
uint64_t size_;
};
template <typename T>
Array<T>::Array(Array&& other) : data_(other.data_), size_(other.size_) {
other.data_ = nullptr;
other.size_ = 0;
}
Array& operator=(Array&& other) {
template <typename T>
Array<T>& Array<T>::operator=(Array&& other) {
if (data_) {
delete[] data_;
}
@ -37,23 +60,11 @@ class Array {
return *this;
}
~Array() {
if (data_) {
delete[] data_;
template <typename T>
Array<T>::Array(const ArrayView<T>& view) : Array(view.size()) {
for (uint64_t i = 0; i < size_; i++) {
data_[i] = view[i];
}
}
T* RawPtr() { return data_; }
const T* RawPtr() const { return data_; }
uint64_t size() const { return size_; }
T& operator[](uint64_t index) { return data_[index]; }
const T& operator[](uint64_t index) const { return data_[index]; }
private:
T* data_;
uint64_t size_;
};
} // namespace glcr

View File

@ -8,16 +8,21 @@ template <typename T>
class ArrayView {
public:
ArrayView() : data_(nullptr), size_(0) {}
ArrayView(const ArrayView&) = default;
ArrayView(ArrayView&&) = default;
ArrayView(T* data, uint64_t size) : data_(data), size_(size) {}
// Accessors.
T& operator[](uint64_t index) { return data_[index]; }
const T& operator[](uint64_t index) const { return data_[index]; }
T* RawPtr() { return data_; }
const T* RawPtr() const { return data_; }
uint64_t size() const { return size_; }
T& operator[](uint64_t index) { return data_[index]; }
const T& operator[](uint64_t index) const { return data_[index]; }
bool empty() const { return size_; }
private:
T* data_;

View File

@ -12,56 +12,23 @@ class LinkedList {
LinkedList() {}
LinkedList(const LinkedList&) = delete;
LinkedList(LinkedList&&) = delete;
// Accessors.
bool empty() const { return size_ == 0; }
uint64_t size() const { return size_; }
void PushFront(const T& item) {
ListItem* new_item = new ListItem{
.item = item,
.next = front_,
};
front_ = new_item;
size_++;
}
void PushFront(T&& item) {
ListItem* new_item = new ListItem{
.item = glcr::Move(item),
.next = front_,
};
front_ = new_item;
size_++;
}
void PushBack(const T& item) {
ListItem* new_item = new ListItem{
.item = item,
.next = nullptr,
};
PushBackInternal(new_item);
}
void PushBack(T&& item) {
ListItem* new_item = new ListItem{
.item = glcr::Move(item),
.next = nullptr,
};
PushBackInternal(new_item);
}
T PopFront() {
size_--;
ListItem* old_front = front_;
front_ = front_->next;
T ret = glcr::Move(old_front->item);
delete old_front;
return ret;
}
T& PeekFront() { return front_->item; }
const T& PeekFront() const { return front_->item; }
T PopFront();
void PushFront(const T& item);
void PushFront(T&& item);
void PushBack(const T& item);
void PushBack(T&& item);
struct ListItem {
T item;
ListItem* next;
@ -107,4 +74,53 @@ class LinkedList {
}
};
template <typename T>
void LinkedList<T>::PushFront(const T& item) {
ListItem* new_item = new ListItem{
.item = item,
.next = front_,
};
front_ = new_item;
size_++;
}
template <typename T>
void LinkedList<T>::PushFront(T&& item) {
ListItem* new_item = new ListItem{
.item = glcr::Move(item),
.next = front_,
};
front_ = new_item;
size_++;
}
template <typename T>
void LinkedList<T>::PushBack(const T& item) {
ListItem* new_item = new ListItem{
.item = item,
.next = nullptr,
};
PushBackInternal(new_item);
}
template <typename T>
void LinkedList<T>::PushBack(T&& item) {
ListItem* new_item = new ListItem{
.item = glcr::Move(item),
.next = nullptr,
};
PushBackInternal(new_item);
}
template <typename T>
T LinkedList<T>::PopFront() {
size_--;
ListItem* old_front = front_;
front_ = front_->next;
T ret = Move(old_front->item);
delete old_front;
return Move(ret);
}
} // namespace glcr

View File

@ -8,16 +8,61 @@ namespace glcr {
template <typename T>
class Vector {
public:
// Constructors.
Vector() : data_(nullptr), size_(0), capacity_(0) {}
Vector(const Vector&) = delete;
Vector(Vector&& other)
Vector& operator=(const Vector&) = delete;
Vector(Vector&& other);
Vector& operator=(Vector&& other);
~Vector() {
if (data_) {
delete[] data_;
}
}
// Accessors.
T& operator[](uint64_t index) { return data_[index]; }
const T& operator[](uint64_t index) const { return data_[index]; }
T& at(uint64_t index) { return data_[index]; }
const T& at(uint64_t index) const { return data_[index]; }
uint64_t size() const { return size_; }
bool empty() const { return size_ == 0; }
uint64_t capacity() const { return capacity_; }
const T* RawPtr() const { return data_; }
// Setters.
// FIXME: Handle downsizing.
void Resize(uint64_t capacity);
void PushBack(const T& item);
void PushBack(T&& item);
template <typename... Args>
void EmplaceBack(Args&&... args);
private:
T* data_;
uint64_t size_;
uint64_t capacity_;
void Expand();
}; // namespace glcr
template <typename T>
Vector<T>::Vector(Vector&& other)
: data_(other.data_), size_(other.size_), capacity_(other.capacity_) {
other.data_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
}
Vector& operator=(Vector&& other) {
template <typename T>
Vector<T>& Vector<T>::operator=(Vector&& other) {
if (data_) {
delete[] data_;
}
@ -33,40 +78,6 @@ class Vector {
return *this;
}
~Vector() {
if (data_) {
delete[] data_;
}
}
// FIXME: Handle downsizing.
void Resize(uint64_t capacity);
// Setters.
void PushBack(const T& item);
void PushBack(T&& item);
template <typename... Args>
void EmplaceBack(Args... args);
// Accessors.
T& operator[](uint64_t index);
const T& operator[](uint64_t index) const;
T& at(uint64_t index);
const T& at(uint64_t index) const;
uint64_t size() const { return size_; }
uint64_t capacity() const { return capacity_; }
const T* RawPtr() const { return data_; }
private:
T* data_;
uint64_t size_;
uint64_t capacity_;
void Expand();
};
template <typename T>
void Vector<T>::Resize(uint64_t capacity) {
T* new_data = new T[capacity];
@ -100,7 +111,7 @@ void Vector<T>::PushBack(T&& item) {
template <typename T>
template <typename... Args>
void Vector<T>::EmplaceBack(Args... args) {
void Vector<T>::EmplaceBack(Args&&... args) {
if (size_ >= capacity_) {
Expand();
}
@ -108,26 +119,6 @@ void Vector<T>::EmplaceBack(Args... args) {
data_[size_++] = T(args...);
}
template <typename T>
T& Vector<T>::operator[](uint64_t index) {
return data_[index];
}
template <typename T>
const T& Vector<T>::operator[](uint64_t index) const {
return data_[index];
}
template <typename T>
T& Vector<T>::at(uint64_t index) {
return data_[index];
}
template <typename T>
const T& Vector<T>::at(uint64_t index) const {
return data_[index];
}
template <typename T>
void Vector<T>::Expand() {
uint64_t new_capacity = capacity_ == 0 ? 1 : capacity_ * 2;

View File

@ -44,7 +44,7 @@ z_err_t ParseInitPort(uint64_t init_port_cap) {
case Z_BOOT_FRAMEBUFFER_INFO_VMMO:
gBootFramebufferVmmoCap = init_cap;
default:
dbgln("Unexpected init type {}, continuing.", init_sig);
dbgln("Unexpected init type {x}, continuing.", init_sig);
}
}

24
scripts/qemu.sh Executable file
View File

@ -0,0 +1,24 @@
#! /bin/bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo $DIR
BUILD_DIR="${DIR}/../builddbg"
pushd $BUILD_DIR
ninja
ninja install
sudo sh ${DIR}/build_image.sh disk.img
# Use machine q35 to access PCI devices.
qemu-system-x86_64 -machine q35 -d guest_errors -m 1G -serial stdio -hda disk.img
popd
# Extra options to add to this script in the future.
# Debug opts: -S -s
# Interrupt opts: -d int

View File

@ -143,7 +143,6 @@ void AhciDriver::InterruptLoop() {
for (uint64_t i = 0; i < 32; i++) {
if (devices_[i] != nullptr && devices_[i]->IsInit() &&
(ahci_hba_->interrupt_status & (1 << i))) {
dbgln("Interrupt for {}", i);
devices_[i]->HandleIrq();
ahci_hba_->interrupt_status &= ~(1 << i);
}

View File

@ -1,4 +1,5 @@
add_executable(teton
framebuffer/framebuffer.cpp
teton.cpp
)

View File

@ -0,0 +1,15 @@
#include "framebuffer/framebuffer.h"
#include <mammoth/memory_region.h>
Framebuffer::Framebuffer(const FramebufferInfo& info) : fb_info_(info) {
uint64_t buff_size_bytes = fb_info_.height() * fb_info_.pitch();
MappedMemoryRegion region = MappedMemoryRegion::DirectPhysical(
fb_info_.address_phys(), buff_size_bytes);
fb_ = reinterpret_cast<uint32_t*>(region.vaddr());
}
void Framebuffer::DrawPixel(uint32_t row, uint32_t col, uint32_t pixel) {
// Div by 4 because pitch is in bytes and fb_ is a 32bit array.
fb_[(row * fb_info_.pitch() / 4) + col] = pixel;
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <yellowstone/yellowstone.yunq.h>
class Framebuffer {
public:
Framebuffer(const FramebufferInfo& info);
void DrawPixel(uint32_t row, uint32_t col, uint32_t pixel);
private:
// FIXME: Implement Yunq copy or move so we
// don't have to store a reference here.
const FramebufferInfo& fb_info_;
uint32_t* fb_;
};

View File

@ -1,11 +1,30 @@
#include <mammoth/debug.h>
#include <mammoth/init.h>
#include <yellowstone/yellowstone.yunq.client.h>
#include "framebuffer/framebuffer.h"
uint64_t main(uint64_t init_port) {
ParseInitPort(init_port);
dbgln("Teton Starting");
// 1. Set up framebuffer.
YellowstoneClient client(gInitEndpointCap);
FramebufferInfo framebuffer;
RET_ERR(client.GetFramebufferInfo({}, framebuffer));
dbgln("FB addr {x}, bpp {}, width {} , height {}, pitch {}",
framebuffer.address_phys(), framebuffer.bpp(), framebuffer.width(),
framebuffer.height(), framebuffer.pitch());
Framebuffer fbuf(framebuffer);
for (uint64_t r = 0; r < 20; r++) {
for (uint64_t c = 0; c < 20; c++) {
fbuf.DrawPixel(r, c, 0x0000FF00);
}
}
// 2. Parse a font file.

View File

@ -7,6 +7,8 @@
#include <zcall.h>
#include <zglobal.h>
#define GPT_DEBUG 0
const uint64_t kSectorSize = 512;
const uint64_t kGptPartitionSignature = 0x54524150'20494645;
@ -79,23 +81,26 @@ glcr::ErrorCode GptReader::ParsePartitionTables() {
dbgln("Incorrect OS type: {x}", first_partition->os_type);
return glcr::FAILED_PRECONDITION;
}
#if GPT_DEBUG
dbgln("LBAs: ({x}, {x})", first_partition->starting_lba,
first_partition->ending_lba);
#endif
// FIXME: Don't hardcode sector size.
ParititionHeader* header =
reinterpret_cast<ParititionHeader*>(lba_1_and_2.vaddr() + 512);
dbgln("signature {}", header->signature);
uint64_t num_partitions = header->num_partitions;
uint64_t entry_size = header->parition_entry_size;
uint64_t num_blocks = (num_partitions * entry_size) / 512;
#if GPT_DEBUG
dbgln("signature {}", header->signature);
dbgln("lba_partition_entries {x}", header->lba_partition_entries);
dbgln("num_partitions: {x}", num_partitions);
dbgln("partition_entry_size: {x}", entry_size);
dbgln("Num blocks: {x}", num_blocks);
#endif
req.set_device_id(0);
req.set_lba(header->lba_partition_entries);
@ -103,16 +108,17 @@ glcr::ErrorCode GptReader::ParsePartitionTables() {
RET_ERR(denali_->Read(req, resp));
MappedMemoryRegion part_table =
MappedMemoryRegion::FromCapability(resp.memory());
dbgln("Entries");
for (uint64_t i = 0; i < num_partitions; i++) {
PartitionEntry* entry = reinterpret_cast<PartitionEntry*>(
part_table.vaddr() + (i * entry_size));
if (entry->type_guid_low != 0 || entry->type_guid_high != 0) {
#if GPT_DEBUG
dbgln("Entry {}", i);
dbgln("T Guid: {x}-{x}", entry->type_guid_high, entry->type_guid_low);
dbgln("P Guid: {x}-{x}", entry->part_guid_high, entry->part_guid_low);
dbgln("LBA: {x}, {x}", entry->lba_start, entry->lba_end);
dbgln("Attrs: {x}", entry->attributes);
#endif
// For now we hardcode these values to the type that is
// created in our setup script.
// FIXME: Set up our own root partition type guid at some

View File

@ -4,6 +4,8 @@
#include <mammoth/init.h>
#include <zcall.h>
#define PCI_DEBUG 0
namespace {
PciDeviceHeader* PciHeader(uint64_t base, uint64_t bus, uint64_t dev,
@ -15,14 +17,10 @@ PciDeviceHeader* PciHeader(uint64_t base, uint64_t bus, uint64_t dev,
} // namespace
PciReader::PciReader() {
dbgln("Creating addr space");
uint64_t vaddr;
check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootPciVmmoCap, &vaddr));
dbgln("Addr {x}", vaddr);
dbgln("Dumping PCI");
PciDump(vaddr);
dbgln("Done");
header_ = PciHeader(vaddr, 0, 0, 0);
}
@ -40,17 +38,21 @@ void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev,
if (hdr->vendor_id == 0xFFFF) {
return;
}
#if PCI_DEBUG
dbgln(
"[{}.{}.{}] (Vendor, Device): ({x}, {x}), (Type, Class, Sub, PIF): ({}, "
"{x}, {x}, {x})",
bus, dev, fun, hdr->vendor_id, hdr->device_id, hdr->header_type,
hdr->class_code, hdr->subclass, hdr->prog_interface);
#endif
if ((hdr->class_code == 0x6) && (hdr->subclass == 0x4)) {
dbgln("FIXME: Handle PCI to PCI bridge.");
}
if (hdr->class_code == 0x1) {
#if PCI_DEBUG
dbgln("SATA Device at: {x}", reinterpret_cast<uint64_t>(hdr) - base);
#endif
achi_device_offset_ = reinterpret_cast<uint64_t>(hdr) - base;
}
}

View File

@ -54,7 +54,6 @@ glcr::ErrorCode YellowstoneServer::HandleGetAhciInfo(const Empty&,
AhciInfo& info) {
info.set_ahci_region(pci_reader_.GetAhciVmmo());
info.set_region_length(kPcieConfigurationSize);
dbgln("Resp ahci");
return glcr::OK;
}
@ -88,13 +87,12 @@ glcr::ErrorCode YellowstoneServer::HandleGetDenali(const Empty&,
info.set_denali_endpoint(new_denali);
info.set_device_id(device_id_);
info.set_lba_offset(lba_offset_);
dbgln("Resp denali");
return glcr::OK;
}
glcr::ErrorCode YellowstoneServer::HandleRegisterEndpoint(
const RegisterEndpointRequest& req, Empty&) {
dbgln("Registering.");
dbgln("Registering {}.", req.endpoint_name());
if (req.endpoint_name() == "denali") {
// FIXME: Rather than blocking and calling the denali service
// immediately we should signal the main thread that it can continue init.

View File

@ -154,7 +154,6 @@ extern "C" void interrupt_apic_timer(InterruptFrame*) {
glcr::RefPtr<Port> pci1_port;
extern "C" void isr_pci1();
extern "C" void interrupt_pci1(InterruptFrame*) {
dbgln("Interrupt PCI line 1");
pci1_port->Send({});
gApic->SignalEOI();
}

View File

@ -114,9 +114,8 @@ class PhysicalMemoryManager {
uint64_t AvailablePages() {
uint64_t available = 0;
for (auto iter = memory_blocks.begin(); iter != memory_blocks.end();
iter = iter.next()) {
available += iter->num_pages;
for (const auto& mem_block : memory_blocks) {
available += mem_block.num_pages;
}
return available;
}

View File

@ -83,7 +83,6 @@ void Scheduler::Yield() {
} else {
if (runnable_threads_.size() == 0) {
current_thread_ = sleep_thread_;
dbgln("Sleeping");
} else {
current_thread_ = runnable_threads_.PopFront();
}

View File

@ -58,7 +58,6 @@ extern "C" void zion() {
gScheduler->Enable();
gScheduler->Yield();
dbgln("Sleeping!");
while (1)
;
}