diff --git a/init/init.c b/init/init.c index 9e58855..6c446a5 100644 --- a/init/init.c +++ b/init/init.c @@ -8,11 +8,11 @@ void app_main (void) { uintptr_t out_paddr; int mem_rid = m_proc_create_resource_mem (16, RV_PRIVATE, &out_paddr); - m_proc_map (out_paddr, M_PROC_MAP_BASE, 16, PM_PRESENT | PM_RW | PM_USER); + /* m_proc_map (out_paddr, M_PROC_MAP_BASE, 16, PM_PRESENT | PM_RW | PM_USER); */ - memset ((void*)M_PROC_MAP_BASE, 0, M_PAGE_SIZE * 16); + /* memset ((void*)M_PROC_MAP_BASE, 0, M_PAGE_SIZE * 16); */ - m_proc_unmap (M_PROC_MAP_BASE, 16); + /* m_proc_unmap (M_PROC_MAP_BASE, 16); */ - m_proc_drop_resource (mem_rid); + /* m_proc_drop_resource (mem_rid); */ } diff --git a/kernel/amd64/apic.c b/kernel/amd64/apic.c index 3a8410c..f8184fe 100644 --- a/kernel/amd64/apic.c +++ b/kernel/amd64/apic.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -33,8 +34,14 @@ /* Divide config register */ #define LAPIC_DCR 0x3E0 +struct ioapic { + struct acpi_madt_ioapic table_data; + spin_lock_t lock; + uintptr_t mmio_base; +}; + /* Table of IOAPICS */ -static struct acpi_madt_ioapic apics[IOAPICS_MAX]; +static struct ioapic ioapics[IOAPICS_MAX]; /* Table of interrupt source overrides */ /* clang-format off */ static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_SRC_OVERRIDES_MAX]; @@ -43,33 +50,39 @@ static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_S static size_t ioapic_entries = 0; /* Count of actual interrupt source overrides */ static size_t intr_src_override_entries = 0; -/* Local APIC MMIO base address. It comes from MSR_APIC_BASE */ -static uintptr_t lapic_mmio_base = 0; + +static uint64_t lapic_ticks; /* Read IOAPIC */ -static uint32_t amd64_ioapic_read (uintptr_t vaddr, uint32_t reg) { - *(volatile uint32_t*)vaddr = reg; - return *(volatile uint32_t*)(vaddr + 0x10); +static uint32_t amd64_ioapic_read (struct ioapic* ioapic, uint32_t reg) { + spin_lock (&ioapic->lock); + *(volatile uint32_t*)ioapic->mmio_base = reg; + uint32_t ret = *(volatile uint32_t*)(ioapic->mmio_base + 0x10); + spin_unlock (&ioapic->lock); + return ret; } /* Write IOAPIC */ -static void amd64_ioapic_write (uintptr_t vaddr, uint32_t reg, uint32_t value) { - *(volatile uint32_t*)vaddr = reg; - *(volatile uint32_t*)(vaddr + 0x10) = value; +static void amd64_ioapic_write (struct ioapic* ioapic, uint32_t reg, uint32_t value) { + spin_lock (&ioapic->lock); + *(volatile uint32_t*)ioapic->mmio_base = reg; + *(volatile uint32_t*)(ioapic->mmio_base + 0x10) = value; + spin_unlock (&ioapic->lock); } /* Find an IOAPIC corresposting to provided IRQ */ -static struct acpi_madt_ioapic* amd64_ioapic_find (uint8_t irq) { - struct acpi_madt_ioapic* apic = NULL; - struct limine_hhdm_response* hhdm = limine_hhdm_request.response; +static struct ioapic* amd64_ioapic_find (uint8_t irq) { + struct ioapic* ioapic = NULL; for (size_t i = 0; i < ioapic_entries; i++) { - apic = &apics[i]; - uint32_t version = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, 1); + ioapic = &ioapics[i]; + /* uint32_t version = amd64_ioapic_read ((uintptr_t)hhdm->offset + + * (uintptr_t)ioapic->table_data.address, 1); */ + uint32_t version = amd64_ioapic_read (ioapic, 1); uint32_t max = ((version >> 16) & 0xFF); - if ((irq >= apic->gsi_base) && (irq <= (apic->gsi_base + max))) - return apic; + if ((irq >= ioapic->table_data.gsi_base) && (irq <= (ioapic->table_data.gsi_base + max))) + return ioapic; } return NULL; @@ -85,10 +98,9 @@ static struct acpi_madt_ioapic* amd64_ioapic_find (uint8_t irq) { * lapic_id - Local APIC that will receive the interrupt. */ void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id) { - struct acpi_madt_ioapic* apic = NULL; + struct ioapic* ioapic = NULL; struct acpi_madt_interrupt_source_override* override; bool found_override = false; - struct limine_hhdm_response* hhdm = limine_hhdm_request.response; for (size_t i = 0; i < intr_src_override_entries; i++) { override = &intr_src_overrides[i]; @@ -111,52 +123,15 @@ void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t calc_flags |= flags; } - apic = amd64_ioapic_find (irq); + ioapic = amd64_ioapic_find (irq); - if (apic == NULL) + if (ioapic == NULL) return; - uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10; + uint32_t irq_reg = ((irq - ioapic->table_data.gsi_base) * 2) + 0x10; - amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg, - (uint32_t)calc_flags); - - amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg + 1, - (uint32_t)(calc_flags >> 32)); -} - -/* Mask a given IRQ */ -void amd64_ioapic_mask (uint8_t irq) { - struct acpi_madt_ioapic* apic; - struct limine_hhdm_response* hhdm = limine_hhdm_request.response; - - apic = amd64_ioapic_find (irq); - - if (apic == NULL) - return; - - uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10; - - uint32_t value = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg); - amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg, - value | (1 << 16)); -} - -/* Unmask a given IRQ */ -void amd64_ioapic_unmask (uint8_t irq) { - struct acpi_madt_ioapic* apic; - struct limine_hhdm_response* hhdm = limine_hhdm_request.response; - - apic = amd64_ioapic_find (irq); - - if (apic == NULL) - return; - - uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10; - - uint32_t value = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg); - amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg, - value & ~(1 << 16)); + amd64_ioapic_write (ioapic, irq_reg + 1, (uint32_t)(calc_flags >> 32)); + amd64_ioapic_write (ioapic, irq_reg, (uint32_t)calc_flags); } /* Find and initialize the IOAPIC */ @@ -180,11 +155,15 @@ void amd64_ioapic_init (void) { switch (current->type) { case ACPI_MADT_ENTRY_TYPE_IOAPIC: { - struct acpi_madt_ioapic* ioapic = (struct acpi_madt_ioapic*)current; - mm_map_kernel_page ((uintptr_t)ioapic->address, - (uintptr_t)hhdm->offset + (uintptr_t)ioapic->address, + struct acpi_madt_ioapic* ioapic_table_data = (struct acpi_madt_ioapic*)current; + mm_map_kernel_page ((uintptr_t)ioapic_table_data->address, + (uintptr_t)hhdm->offset + (uintptr_t)ioapic_table_data->address, MM_PG_PRESENT | MM_PG_RW | MM_PD_RELOAD); - apics[ioapic_entries++] = *ioapic; + ioapics[ioapic_entries++] = (struct ioapic){ + .lock = SPIN_LOCK_INIT, + .table_data = *ioapic_table_data, + .mmio_base = ((uintptr_t)hhdm->offset + (uintptr_t)ioapic_table_data->address), + }; } break; case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: { struct acpi_madt_interrupt_source_override* override = @@ -198,7 +177,7 @@ void amd64_ioapic_init (void) { } /* Get MMIO base of Local APIC */ -static uintptr_t amd64_lapic_base (void) { return lapic_mmio_base; } +static uintptr_t amd64_lapic_base (void) { return thiscpu->lapic_mmio_base; } /* Write Local APIC */ static void amd64_lapic_write (uint32_t reg, uint32_t value) { @@ -216,9 +195,6 @@ uint32_t amd64_lapic_id (void) { return amd64_lapic_read (LAPIC_ID) >> 24; } /* Send End of interrupt command to Local APIC */ void amd64_lapic_eoi (void) { amd64_lapic_write (LAPIC_EOI, 0); } -/* Set initial counter value in Local APIC timer */ -void amd64_lapic_tick (uint32_t tick) { amd64_lapic_write (LAPIC_TIMICT, tick); } - /* * Calibrate Local APIC to send interrupts in a set interval. * @@ -255,24 +231,24 @@ static void amd64_lapic_start (uint32_t ticks) { * Initialize Local APIC, configure to send timer interrupts at a given period. See * amd64_lapic_calibrate and amd64_lapic_start. */ -uint64_t amd64_lapic_init (uint32_t us) { +void amd64_lapic_init (uint32_t us) { struct limine_hhdm_response* hhdm = limine_hhdm_request.response; amd64_wrmsr (MSR_APIC_BASE, amd64_rdmsr (MSR_APIC_BASE) | (1 << 11)); uintptr_t lapic_paddr = amd64_rdmsr (MSR_APIC_BASE) & 0xFFFFF000; - lapic_mmio_base = lapic_paddr + (uintptr_t)hhdm->offset; + thiscpu->lapic_mmio_base = lapic_paddr + (uintptr_t)hhdm->offset; - mm_map_kernel_page (lapic_paddr, lapic_mmio_base, + mm_map_kernel_page (lapic_paddr, thiscpu->lapic_mmio_base, MM_PG_PRESENT | MM_PG_RW | MM_PD_LOCK | MM_PD_RELOAD); amd64_lapic_write (LAPIC_SIVR, 0xFF | (1 << 8)); - uint32_t ticks = amd64_lapic_calibrate (us); + if (thiscpu->id == 0) { + lapic_ticks = amd64_lapic_calibrate (us); + } - amd64_lapic_start (ticks); - - return ticks; + amd64_lapic_start (lapic_ticks); } /* @@ -282,6 +258,11 @@ uint64_t amd64_lapic_init (uint32_t us) { * vec - Interrupt vector/IDT stub, which will be invoked by the IPI. */ void amd64_lapic_ipi (uint8_t lapic_id, uint8_t vec) { + /* wait for previous IPI to finish */ + while (amd64_lapic_read (LAPIC_ICR) & (1 << 12)) { + __asm__ volatile ("pause"); + } + amd64_lapic_write (LAPIC_ICR + 0x10, (lapic_id << 24)); amd64_lapic_write (LAPIC_ICR, vec); } diff --git a/kernel/amd64/apic.h b/kernel/amd64/apic.h index a026b5e..2d3f6b3 100644 --- a/kernel/amd64/apic.h +++ b/kernel/amd64/apic.h @@ -4,14 +4,11 @@ #include void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id); -void amd64_ioapic_mask (uint8_t irq); -void amd64_ioapic_unmask (uint8_t irq); void amd64_ioapic_init (void); uint32_t amd64_lapic_id (void); -void amd64_lapic_tick (uint32_t tick); void amd64_lapic_eoi (void); void amd64_lapic_ipi (uint8_t lapic_id, uint8_t vec); -uint64_t amd64_lapic_init (uint32_t us); +void amd64_lapic_init (uint32_t us); #endif // _KERNEL_AMD64_APIC_H diff --git a/kernel/amd64/smp.c b/kernel/amd64/smp.c index 166b5e5..da614cc 100644 --- a/kernel/amd64/smp.c +++ b/kernel/amd64/smp.c @@ -61,8 +61,7 @@ static void amd64_smp_bootstrap (struct limine_mp_info* mp_info) { amd64_init (cpu, true); /* gdt + idt */ syscall_init (); - thiscpu->lapic_ticks = amd64_lapic_init (10000); - amd64_lapic_tick (thiscpu->lapic_ticks); + amd64_lapic_init (0); DEBUG ("CPU %u is online!\n", thiscpu->id); @@ -76,7 +75,7 @@ static void amd64_smp_bootstrap (struct limine_mp_info* mp_info) { /// Initialize SMP subsystem for AMD64. Start AP CPUs void smp_init (void) { - thiscpu->lapic_ticks = amd64_lapic_init (10000); + amd64_lapic_init (10000); struct limine_mp_response* mp = limine_mp_request.response; diff --git a/kernel/amd64/smp.h b/kernel/amd64/smp.h index e3acd70..01cf9d5 100644 --- a/kernel/amd64/smp.h +++ b/kernel/amd64/smp.h @@ -21,7 +21,7 @@ struct cpu { volatile struct gdt_extended gdt ALIGNED (16); volatile struct tss tss; - uint64_t lapic_ticks; + uintptr_t lapic_mmio_base; uint32_t id; struct { diff --git a/kernel/proc/resource.c b/kernel/proc/resource.c index 5e730cc..0b5c999 100644 --- a/kernel/proc/resource.c +++ b/kernel/proc/resource.c @@ -26,6 +26,8 @@ void proc_cleanup_resources (struct proc* proc) { } void proc_drop_resource (struct proc* proc, struct proc_resource* resource) { + DEBUG ("resource=%p, type=%d, rid=%d\n", resource, resource->type, resource->rid); + if (atomic_fetch_sub (&resource->refs, 1) == 1) { spin_lock (&proc->lock); rbtree_delete (&proc->resource_tree, &resource->proc_resource_tree_link); @@ -47,7 +49,6 @@ static bool proc_create_resource_mem (struct proc_resource_mem* mem, mem->paddr = paddr; mem->pages = init->pages; - DEBUG ("paddr=%p, pages=%zu\n", mem->paddr, mem->pages); return true; } @@ -82,6 +83,8 @@ struct proc_resource* proc_create_resource (struct proc* proc, int rid, int type struct proc_resource_mem_init* mem_init = data; proc_create_resource_mem (&resource->u.mem, mem_init); resource->ops.cleanup = &proc_cleanup_resource_mem; + DEBUG ("resource=%p paddr=%p, pages=%zu\n", resource, resource->u.mem.paddr, + resource->u.mem.pages); } break; default: { free (resource);