Compare commits

..

15 Commits

Author SHA1 Message Date
chloe de191c15df sp1: mu: Add memory mapped I/O helpers
Signed-off-by: Chloe M. <chloe@mirocom.org>
2026-05-04 21:28:52 -04:00
chloe e1b8ae10a3 sp1/amd64: irqchip: Add IRQ chip descriptor lists
Signed-off-by: Chloe M. <chloe@mirocom.org>
2026-04-30 19:05:02 -04:00
chloe fd7889da13 mm: vm: Always cast pointer offsets to uintptr_t
Signed-off-by: Chloe M. <chloe@mirocom.org>
2026-04-30 19:04:39 -04:00
chloe e4f47af722 tools: Update toolchain repository
Signed-off-by: Chloe M. <chloe@mirocom.org>
2026-04-30 13:17:37 -04:00
chloe 8b4e7395f5 docs: Update README
Signed-off-by: Chloe M. <chloe@mirocom.org>
2026-04-30 13:05:53 -04:00
chloe b34bfdbf63 sp1: vm: Fix ups
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-26 00:24:15 -04:00
chloe 336d6e2c52 sp1: vm: Add function to unmap vm regions
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-26 00:22:01 -04:00
chloe 9fb213cc41 sp1: vm: Remove redundant length assignment
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-26 00:21:40 -04:00
chloe bd354fed8c sp1/amd64: mmu: Add function to unmap regions
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-26 00:21:19 -04:00
chloe a7577d1921 sp1/amd64: io: Add IRQ chip manager groundwork
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-23 22:28:24 -04:00
chloe d63c88259f sp1: mm: Add MI virtual memory management
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-22 23:56:01 -04:00
chloe 37fc085646 sp1: mmu: Clean up header
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-22 23:22:23 -04:00
chloe 353a8465a3 sp1/amd64: mmu: Use PAGESIZE instead of hardcoding
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-22 23:08:44 -04:00
chloe 8c650daf69 sp1/amd64: mmu: Remove redundant whitespace
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-22 23:07:53 -04:00
chloe 1bff60c27a sp1/amd64: mmu: Add page mapping implementation
Signed-off-by: Ian Moffett <ian@mirocom.org>
2026-04-21 21:48:13 -04:00
10 changed files with 644 additions and 5 deletions
+3 -3
View File
@@ -5,7 +5,7 @@ their work (or fun! >:3) done while having their machine resources managed clean
scenes. SPx is architected by a fluffy kitty cat who likes eating bugs and mice and RATS NOM scenes. SPx is architected by a fluffy kitty cat who likes eating bugs and mice and RATS NOM
NOM NOM !!!! This kitty will protect your wittle den, don't worry critter! NOM NOM !!!! This kitty will protect your wittle den, don't worry critter!
-- Confidentiality of implementation -- -- Open source --
This repository and its sources as of Thu Apr 16 is CONFIDENTIAL and PROPRIETARY. This system software has been open sourced, all confidentiality notices have been preserved
Unauthorized distribution or modification is strictly prohibited. for historical purposes.
+1 -1
View File
@@ -34,7 +34,7 @@ check_deps() {
# #
get_toolchain() { get_toolchain() {
if [ ! -d var/cc/toolchain ]; then if [ ! -d var/cc/toolchain ]; then
git clone https://git.mirocom.org/Mirocom/mirocom-toolchain --depth=1 var/cc/toolchain git clone https://git.mirocom.org/chloe/mirocom-toolchain --depth=1 var/cc/toolchain
cd var/cc/toolchain cd var/cc/toolchain
tar -xzvf toolchain.tar.gz tar -xzvf toolchain.tar.gz
mv public/* .; rm -rf public/ mv public/* .; rm -rf public/
+199
View File
@@ -9,10 +9,16 @@
* consent from Mirocom Laboratories. * consent from Mirocom Laboratories.
*/ */
#include <sys/param.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <sys/status.h>
#include <mu/mmu.h> #include <mu/mmu.h>
#include <mm/vm.h> #include <mm/vm.h>
#include <mm/physmem.h> #include <mm/physmem.h>
#include <machine/tlb.h>
#include <machine/param.h>
#include <stdbool.h>
#include <string.h>
/* /*
* Page-Table Entry (PTE) flags * Page-Table Entry (PTE) flags
@@ -31,6 +37,154 @@
#define PTE_GLOBAL BIT(8) /* Global; sticky */ #define PTE_GLOBAL BIT(8) /* Global; sticky */
#define PTE_NX BIT(63) /* Execute-disable */ #define PTE_NX BIT(63) /* Execute-disable */
/* 57-bit linear addresses */
#define CR4_LA57 BIT(12)
/*
* Represents valid pagemap levels
*/
typedef enum {
PAGELVL_PML1,
PAGELVL_PML2,
PAGELVL_PML3,
PAGELVL_PML4,
PAGELVL_PML5
} pagelvl_t;
/*
* Obtain page table flags from protection flags
*
* @prot: Protection flags to extract from
*/
static size_t
mmu_prot_to_pte(int prot)
{
size_t pte_flags = PTE_P | PTE_NX;
if (ISSET(prot, PROT_WRITE))
pte_flags |= PTE_RW;
if (ISSET(prot, PROT_EXEC))
pte_flags &= ~PTE_NX;
return pte_flags;
}
/*
* Verify if a pagesize is valid
*
* @ps: Pagesize to verify
*/
static bool
mmu_ps_valid(pagelvl_t ps)
{
switch (ps) {
case PAGESIZE_4K:
return true;
}
return false;
}
/*
* Obtain the top-level in use for the current machine
* configuration.
*/
static inline pagelvl_t
mmu_get_level(void)
{
uint64_t cr4;
__asmv(
"mov %%cr4, %0"
: "=r" (cr4)
:
: "memory"
);
return ISSET(cr4, CR4_LA57)
? PAGELVL_PML5
: PAGELVL_PML4;
}
/*
* This function extracts those cute 9 bit segments that
* function as indices into pagemap levels.
*
* @vma: Virtual memory address used as key
* @lvl: Level to extract
*/
static inline size_t
mmu_extract_index(uintptr_t vma, pagelvl_t lvl)
{
switch (lvl) {
case PAGELVL_PML1:
return (vma >> 12) & 0x1FF;
case PAGELVL_PML2:
return (vma >> 21) & 0x1FF;
case PAGELVL_PML3:
return (vma >> 30) & 0x1FF;
case PAGELVL_PML4:
return (vma >> 39) & 0x1FF;
case PAGELVL_PML5:
return (vma >> 48) & 0x1FF;
}
return (size_t)-1;
}
/*
* Extract a pagemap index
*
* @vfr: Virtual fuck region
* @vma: Virtual memory address
* @lvl: Pagemap level to extract
* @alloc: If true, allocate new entries
*/
static uint64_t *
mmu_extract_level(struct mmu_vfr *vfr, uintptr_t vma, pagelvl_t lvl, bool alloc)
{
uintptr_t *pmap, pma;
void *tmp_p;
size_t index;
pagelvl_t cur_level;
if (vfr == NULL || lvl > PAGELVL_PML5) {
return NULL;
}
cur_level = mmu_get_level();
pmap = pma_to_vma((vfr->cr3 & PTE_ADDR_MASK));
while (cur_level > lvl) {
index = mmu_extract_index(vma, cur_level);
/* Is this entry present? */
if (ISSET(pmap[index], PTE_P)) {
pmap = pma_to_vma((pmap[index] & PTE_ADDR_MASK));
--cur_level;
continue;
}
if (!alloc) {
return NULL;
}
pma = mm_physmem_alloc(1);
if (pma == 0) {
return NULL;
}
tmp_p = pma_to_vma(pma);
memset(tmp_p, 0, PAGESIZE);
pmap[index] = pma | (PTE_P | PTE_RW | PTE_US);
pmap = tmp_p;
--cur_level;
}
return pmap;
}
void void
mu_mmu_readvfr(struct mmu_vfr *res) mu_mmu_readvfr(struct mmu_vfr *res)
{ {
@@ -89,3 +243,48 @@ mu_mmu_forkvfr(struct mmu_vfr *vfr, struct mmu_vfr *res)
res->cr3 = dest; res->cr3 = dest;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
status_t
mu_mmu_map(struct mmu_vfr *vfr, uintptr_t vma, uintptr_t pma,
int prot, pagesize_t ps)
{
uintptr_t *tbl;
size_t index, flags;
if (vfr == NULL || !mmu_ps_valid(ps)) {
return STATUS_INVALID_PARAM;
}
tbl = mmu_extract_level(vfr, vma, PAGELVL_PML1, true);
if (tbl == NULL) {
return STATUS_NO_MEMORY;
}
index = mmu_extract_index(vma, PAGELVL_PML1);
flags = mmu_prot_to_pte(prot);
tbl[index] = pma | flags;
md_tlb_flush(vma);
return STATUS_SUCCESS;
}
status_t
mu_mmu_unmap(struct mmu_vfr *vfr, uintptr_t vma, pagesize_t ps)
{
uintptr_t *tbl;
size_t index;
if (vfr == NULL) {
return STATUS_INVALID_PARAM;
}
tbl = mmu_extract_level(vfr, vma, PAGELVL_PML1, false);
if (tbl == NULL) {
return STATUS_NOT_FOUND;
}
index = mmu_extract_index(vma, PAGELVL_PML1);
tbl[index] = 0;
md_tlb_flush(vma);
return STATUS_SUCCESS;
}
+160
View File
@@ -0,0 +1,160 @@
/*
* Copyright (c) 2026, Mirocom Laboratories
* All rights reserved.
*
* The following sources are CONFIDENTIAL and PROPRIETARY
* property of Mirocom Laboratories. Unauthorized copying,
* use, distribution or modification of this file, in whole
* and in part, is strictly prohibited without the prior written
* consent from Mirocom Laboratories.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <os/knot.h>
#include <lib/printf.h>
#include <machine/irqchip.h>
#include <io/acpi/acpi.h>
#include <io/acpi/tables.h>
#include <mm/vm.h>
#define pr_trace(fmt, ...) \
printf("irqchip: " fmt, ##__VA_ARGS__)
/* Online capable */
#define LAPIC_ONLCAP BIT(1)
/* I/O APIC */
static struct irqchip ioapic_list[MAX_IOAPIC];
static size_t ioapic_count = 0;
/* Local APIC */
static struct irqchip lapic_list[MAX_LAPIC];
static size_t lapic_count = 0;
/*
* Add a Local APIC descriptor
*/
static inline void
irqchip_lapic_append(const struct irqchip *irqchip)
{
if (lapic_count >= MAX_LAPIC) {
return;
}
lapic_list[lapic_count++] = *irqchip;
}
/*
* Add an I/O APIC descriptor
*/
static inline void
irqchip_ioapic_append(const struct irqchip *irqchip)
{
if (ioapic_count >= MAX_IOAPIC) {
return;
}
ioapic_list[ioapic_count++] = *irqchip;
}
/*
* Print information about a Local APIC unit
*/
static inline void
irqchip_print_lapic(struct local_apic *lapic)
{
static uint16_t log_count = 0;
if (lapic == NULL) {
return;
}
if ((log_count++) >= 4) {
pr_trace("....\n");
return;
}
pr_trace("lapic(%d).cpu : %d\n",
lapic->apic_id, lapic->processor_id);
}
/*
* Print information about an I/O APIC unit
*/
static inline void
irqchip_print_ioapic(struct ioapic *ioapic)
{
if (ioapic == NULL) {
return;
}
pr_trace("ioapic(%d).gsi_base : %d\n",
ioapic->ioapic_id, ioapic->gsi_base);
pr_trace("ioapic(%d).mmio : %p\n",
ioapic->ioapic_id, ioapic->ioapic_addr);
}
status_t
md_irqchip_init(void)
{
struct irqchip chip;
struct acpi_madt *madt;
struct local_apic *lapic;
struct ioapic *ioapic;
struct apic_header *hdr;
char *cur, *end;
madt = acpi_query("APIC");
if (madt == NULL) {
knot("could not query acpi madt table\n");
}
cur = (char *)(madt + 1);
end = (char *)madt + madt->hdr.length;
while (cur < end) {
hdr = (struct apic_header *)cur;
switch (hdr->type) {
case APIC_TYPE_LOCAL_APIC:
lapic = (struct local_apic *)hdr;
irqchip_print_lapic(lapic);
chip.mmio = pma_to_vma(madt->lapic_addr);
chip.apic_id = lapic->apic_id;
irqchip_lapic_append(&chip);
break;
case APIC_TYPE_IO_APIC:
ioapic = (struct ioapic *)hdr;
irqchip_print_ioapic(ioapic);
chip.mmio = pma_to_vma(ioapic->ioapic_addr);
chip.apic_id = ioapic->ioapic_id;
irqchip_lapic_append(&chip);
break;
}
cur += hdr->length;
}
}
struct irqchip *
md_ioapic_index(size_t index)
{
if (index >= ioapic_count) {
return NULL;
}
return &ioapic_list[index];
}
struct irqchip *
md_lapic_index(size_t index)
{
if (index >= lapic_count) {
return NULL;
}
return &lapic_list[index];
}
+3
View File
@@ -16,6 +16,7 @@
#include <os/bpt.h> #include <os/bpt.h>
#include <mm/vm.h> #include <mm/vm.h>
#include <string.h> #include <string.h>
#include <machine/irqchip.h> /* shared */
#define pr_trace(fmt, ...) \ #define pr_trace(fmt, ...) \
printf("acpi: " fmt, ##__VA_ARGS__) printf("acpi: " fmt, ##__VA_ARGS__)
@@ -101,4 +102,6 @@ acpi_init(void)
root_sdt = pma_to_vma((uintptr_t)rsdp->xsdt_addr); root_sdt = pma_to_vma((uintptr_t)rsdp->xsdt_addr);
root_sdt_entries = (root_sdt->hdr.length - sizeof(root_sdt->hdr)) / 8; root_sdt_entries = (root_sdt->hdr.length - sizeof(root_sdt->hdr)) / 8;
} }
md_irqchip_init();
} }
+87
View File
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2026, Mirocom Laboratories
* All rights reserved.
*
* The following sources are CONFIDENTIAL and PROPRIETARY
* property of Mirocom Laboratories. Unauthorized copying,
* use, distribution or modification of this file, in whole
* and in part, is strictly prohibited without the prior written
* consent from Mirocom Laboratories.
*/
#include <sys/units.h>
#include <sys/param.h>
#include <lib/printf.h>
#include <mu/mmu.h>
#include <mu/param.h>
#include <mm/vm.h>
#define pr_trace(fmt, ...) \
printf("vm_map: " fmt, ##__VA_ARGS__)
/* Used to safely convert pagesize constants */
#define GRAN(ps) \
((ps) <= PAGESIZE_1G) \
? pstab[(ps)] \
: pstab[PAGESIZE_4K]
/* Pagesize constant to length table */
static size_t pstab[] = {
[PAGESIZE_4K] = 0x1000,
[PAGESIZE_2M] = UNIT_MIB * 2,
[PAGESIZE_1G] = UNIT_GIB
};
status_t
mm_vm_map(struct mmu_vfr *vfr, struct vm_map *mapping, int prot)
{
size_t len, gran;
uintptr_t vma, pma;
status_t status;
if (vfr == NULL || mapping == NULL) {
return STATUS_INVALID_PARAM;
}
gran = GRAN(mapping->ps);
vma = ALIGN_DOWN(mapping->vma_base, gran);
pma = ALIGN_DOWN(mapping->pma_base, gran);
len = mapping->length;
len = ALIGN_UP(len + (len & (gran - 1)), gran);
for (size_t i = 0; i < len; i += gran) {
status = mu_mmu_map(vfr, vma + i, pma + i, prot, mapping->ps);
/* Destroy what we created on failure */
if (status != STATUS_SUCCESS) {
mm_vm_unmap(vfr, mapping);
return status;
}
}
return STATUS_SUCCESS;
}
status_t
mm_vm_unmap(struct mmu_vfr *vfr, struct vm_map *mapping)
{
size_t gran, len;
uintptr_t vma;
if (vfr == NULL || mapping == NULL) {
return STATUS_INVALID_PARAM;
}
gran = GRAN(mapping->ps);
vma = ALIGN_DOWN(mapping->vma_base, gran);
len = mapping->length;
len = ALIGN_UP(len + (len & (gran - 1)), gran);
for (size_t i = 0; i < len; i += gran) {
mu_mmu_unmap(vfr, vma + i, mapping->ps);
}
return STATUS_SUCCESS;
}
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2026, Mirocom Laboratories
* All rights reserved.
*
* The following sources are CONFIDENTIAL and PROPRIETARY
* property of Mirocom Laboratories. Unauthorized copying,
* use, distribution or modification of this file, in whole
* and in part, is strictly prohibited without the prior written
* consent from Mirocom Laboratories.
*/
#ifndef _MACHINE_IRQCHIP_H_
#define _MACHINE_IRQCHIP_H_ 1
#include <sys/status.h>
#define MAX_IOAPIC 8
#define MAX_LAPIC 64
/*
* @IRQCHIP_NONE: This IRQ chip has no type
* @IRQCHIP_LAPIC: This IRQ chip is a Local APIC
* @IRQCHIP_IOAPIC: This IRQ chip is an I/O APIC
*/
typedef enum {
IRQCHIP_NONE,
IRQCHIP_LAPIC,
IRQCHIP_IOAPIC
} irqchip_type_t;
/*
* Represents a platform interrupt controller
* chip
*
* @type: IRQ chip type
* @apic_id: APIC ID
* @mmio: Memory mapped I/O address
*/
struct irqchip {
irqchip_type_t type;
uint8_t apic_id;
void *mmio;
};
/*
* Initialize platform interrupt controller chips
*/
status_t md_irqchip_init(void);
/*
* Obtain an I/O APIC descriptor by index
*
* @index: Index of entry to obtain
*/
struct irqchip *md_ioapic_index(size_t index);
/*
* Obtain an Local APIC descriptor by index
*
* @index: Index of entry to obtain
*/
struct irqchip *md_lapic_index(size_t index);
#endif /* !_MACHINE_IRQCHIP_H_ */
+36 -1
View File
@@ -12,18 +12,53 @@
#ifndef _MM_VM_H_ #ifndef _MM_VM_H_
#define _MM_VM_H_ 1 #define _MM_VM_H_ 1
#include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
#include <os/bpt.h> #include <os/bpt.h>
#include <mu/mmu.h>
/*
* Represents a virtual memory mapping that can be made
*
* @ps: Pagesize
* @vma_base: Virtual memory base
* @pma_base: Physical memory base
* @length: Number of bytes to map
*
* XXX: `pma_base' is unused when unmapping regions
*/
struct vm_map {
pagesize_t ps;
uintptr_t vma_base;
uintptr_t pma_base;
size_t length;
};
/* /*
* Macros used to convert physical to virtual addresses * Macros used to convert physical to virtual addresses
* and vice versa. * and vice versa.
*/ */
#define pma_to_vma(pma) \ #define pma_to_vma(pma) \
PTR_OFFSET((void *)pma, bpt_kload_base()) PTR_OFFSET((void *)((uintptr_t)pma), bpt_kload_base())
#define vma_to_pma(vma) \ #define vma_to_pma(vma) \
(uintptr_t)PTR_NOFFSET(vma, bpt_kload_base()) (uintptr_t)PTR_NOFFSET(vma, bpt_kload_base())
/*
* Create a virtual memory mapping
*
* @vfr: Virtual fuck region to map within
* @mapping: Mapping to create
*/
status_t mm_vm_map(struct mmu_vfr *vfr, struct vm_map *mapping, int prot);
/*
* Destroy a virtual memory mapping
*
* @vfr: Virtual fuck region to unmap within
* @mapping: Mapping to destroy
*/
status_t mm_vm_unmap(struct mmu_vfr *vfr, struct vm_map *mapping);
/* /*
* Initialize the virtual memory management * Initialize the virtual memory management
*/ */
+51
View File
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2026, Mirocom Laboratories
* All rights reserved.
*
* The following sources are CONFIDENTIAL and PROPRIETARY
* property of Mirocom Laboratories. Unauthorized copying,
* use, distribution or modification of this file, in whole
* and in part, is strictly prohibited without the prior written
* consent from Mirocom Laboratories.
*/
#ifndef _MU_MMIO_H_
#define _MU_MMIO_H_ 1
#include <sys/cdefs.h>
/* Builds mmio_write<n> functions */
#define _MMIO_WRITE_BUILDER(NAME, TYPE) \
static inline void \
mmio_##NAME(TYPE *ptr, TYPE val) \
{ \
__barrier(); \
*(volatile TYPE *)ptr = val; \
}
/* Builds mmio_read<n> functions */
#define _MMIO_READ_BUILDER(NAME, TYPE) \
static inline TYPE \
mmio_##NAME(TYPE *ptr) \
{ \
__barrier(); \
return *(volatile TYPE *)ptr; \
}
/* mmio_write<n> */
_MMIO_WRITE_BUILDER(write8, uint8_t);
_MMIO_WRITE_BUILDER(write16, uint16_t);
_MMIO_WRITE_BUILDER(write32, uint32_t);
#if __SIZEOF_SIZE_T__ == 8
_MMIO_WRITE_BUILDER(write64, uint64_t);
#endif
/* Builds mmio_read<n> functions */
_MMIO_READ_BUILDER(read8, uint8_t);
_MMIO_READ_BUILDER(read16, uint16_t);
_MMIO_READ_BUILDER(read32, uint32_t);
#if __SIZEOF_SIZE_T__ == 8
_MMIO_READ_BUILDER(read64, uint64_t);
#endif
#endif /* !_MU_MMIO_H_ */
+40
View File
@@ -13,6 +13,7 @@
#define _MU_MMU_H_ 1 #define _MU_MMU_H_ 1
#include <sys/status.h> #include <sys/status.h>
#include <sys/mman.h>
/* /*
* Each running SP1 process is to have a virtual fuck region * Each running SP1 process is to have a virtual fuck region
@@ -21,6 +22,16 @@
*/ */
#include <machine/vfr.h> /* shared; virtual fuck region~ */ #include <machine/vfr.h> /* shared; virtual fuck region~ */
/*
* Represents valid page sizes that can be used when
* creating mappings
*/
typedef enum {
PAGESIZE_4K,
PAGESIZE_2M,
PAGESIZE_1G
} pagesize_t;
/* /*
* Obtain the current VFR in-use * Obtain the current VFR in-use
* *
@@ -35,6 +46,35 @@ void mu_mmu_readvfr(struct mmu_vfr *res);
*/ */
void mu_mmu_writevfr(struct mmu_vfr *vfr); void mu_mmu_writevfr(struct mmu_vfr *vfr);
/*
* Create a virtual to physical mapping within a
* specific virtual fuck region
*
* @vfr: Virtual fuck region to map within
* @vma: Virtual memory address to map
* @pma: Physical memory address to map to
* @prot: Protection flags
* @pagesize_t: Pagesize to map
*/
status_t mu_mmu_map(
struct mmu_vfr *vfr, uintptr_t vma,
uintptr_t pma, int prot,
pagesize_t ps
);
/*
* Destroy a virtual memory mapping in the virtual
* fuck region
*
* @vfr: Virtual fuck region to unmap within
* @vma: Virtual memory address to unmap
* @ps: Pagesize of address to unmap
*/
status_t mu_mmu_unmap(
struct mmu_vfr *vfr, uintptr_t vma,
pagesize_t ps
);
/* /*
* Fork a VFR and clear out the lower half * Fork a VFR and clear out the lower half
* *