summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/Makefile11
-rw-r--r--sys/arch/amd64/boot/apboot.asm38
-rw-r--r--sys/arch/amd64/conf/link.ld4
-rw-r--r--sys/arch/amd64/cpu/mp.c134
4 files changed, 184 insertions, 3 deletions
diff --git a/sys/arch/amd64/Makefile b/sys/arch/amd64/Makefile
index 3430e48..ba821ae 100644
--- a/sys/arch/amd64/Makefile
+++ b/sys/arch/amd64/Makefile
@@ -4,16 +4,17 @@ override PROMPT := printf "%s\t\t%s\n"
CC =
LD =
SYS_CFLAGS =
-ASMFILES = $(shell find . -name "*.S")
+ASMFILES = $(shell find . -name "*.S" | grep -v "boot/")
CFILES = $(shell find . -name "*.c")
ASMOBJS = $(ASMFILES:.S=.S.o)
COBJ = $(CFILES:.c=.o)
DFILES = $(CFILES:.c=.d)
-MISC_OFILES = $(shell find ../../ -name "*.o")
+MISC_OFILES = $(shell find ../../ -name "*.o" | grep -v "boot/")
.PHONY: all
-all: $(ASMOBJS) $(COBJ)
+all: boot $(ASMOBJS) $(COBJ)
$(LD) -Tconf/link.ld $(MISC_OFILES) -o ../../rv7
+ objcopy --update-section .trampoline=boot/apboot.bin ../../rv7
%.S.o: %.S
$(PROMPT) " [AS] " $<
@@ -24,6 +25,10 @@ all: $(ASMOBJS) $(COBJ)
$(PROMPT) " [CC] " $<
$(CC) -c -MMD -I../../target/inc/ -I../../inc/ $(SYS_CFLAGS) $< -o $@
+.PHONY: boot
+boot:
+ nasm -fbin boot/apboot.asm -o boot/apboot.bin
+
.PHONY: clean
clean:
rm $(MISC_OFILES)
diff --git a/sys/arch/amd64/boot/apboot.asm b/sys/arch/amd64/boot/apboot.asm
new file mode 100644
index 0000000..b9c3ad7
--- /dev/null
+++ b/sys/arch/amd64/boot/apboot.asm
@@ -0,0 +1,38 @@
+;;
+;; Copyright (c) 2025 Ian Marco Moffett and the Osmora Team.
+;; All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions are met:
+;;
+;; 1. Redistributions of source code must retain the above copyright notice,
+;; this list of conditions and the following disclaimer.
+;; 2. Redistributions in binary form must reproduce the above copyright
+;; notice, this list of conditions and the following disclaimer in the
+;; documentation and/or other materials provided with the distribution.
+;; 3. Neither the name of Hyra nor the names of its
+;; contributors may be used to endorse or promote products derived from
+;; this software without specific prior written permission.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPKERNE
+;; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+;; SUBSTITUTE GOODS OR SERVICES; LKERNS OF USE, DATA, OR PROFITS; OR BUSINESS
+;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+;; PKERNSIBILITY OF SUCH DAMAGE.
+;;
+
+[bits 16]
+[org 0x1000]
+
+_start:
+ cli
+ hlt
+ jmp _start
+
+times 4096 - ($ - $$) db 0
diff --git a/sys/arch/amd64/conf/link.ld b/sys/arch/amd64/conf/link.ld
index 92222b0..9ae1a01 100644
--- a/sys/arch/amd64/conf/link.ld
+++ b/sys/arch/amd64/conf/link.ld
@@ -23,6 +23,10 @@ SECTIONS
*(.rodata .rodata.*)
} :rodata
+ .trampoline : ALIGN(8) {
+ *(.trampoline.*)
+ }
+
. += CONSTANT(MAXPAGESIZE);
.data : {
diff --git a/sys/arch/amd64/cpu/mp.c b/sys/arch/amd64/cpu/mp.c
new file mode 100644
index 0000000..09c824e
--- /dev/null
+++ b/sys/arch/amd64/cpu/mp.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <acpi/acpi.h>
+#include <os/trace.h>
+#include <kern/panic.h>
+#include <dev/clkdev/hpet.h>
+#include <lib/string.h>
+#include <md/lapic.h>
+#include <mu/cpu.h>
+#include <vm/vm.h>
+
+#define dtrace(fmt, ...) trace("mp: " fmt, ##__VA_ARGS__)
+
+/*
+ * The startup code is copied to the processor bring up area
+ * to which it is executed in real mode. This area must fit
+ * within a page and be no larger and no smaller.
+ */
+#define AP_BUA_LEN 0x1000 /* Bring up area length in bytes */
+#define AP_BUA_PADDR 0x1000 /* Bring up area [physical] */
+#define AP_BUA_VADDR PHYS_TO_VIRT(AP_BUA_PADDR) /* Bring up area [virtual] */
+
+__section(".trampoline") static char ap_code[4096];
+
+static int
+cpu_lapic_cb(struct apic_header *h, size_t arg)
+{
+ struct local_apic *lapic;
+ struct cpu_info *self;
+ struct mcb *mcb;
+ struct lapic_ipi ipi;
+ int error;
+
+ self = cpu_self();
+ if (self == NULL) {
+ panic("mp: could not get self\n");
+ }
+
+ mcb = &self->mcb;
+
+ /* Skip ourselves */
+ lapic = (struct local_apic *)h;
+ if (lapic->apic_id == arg) {
+ return -1;
+ }
+
+ /* Prepare the IPI packet */
+ ipi.dest_id = lapic->apic_id;
+ ipi.vector = 0;
+ ipi.delmod = IPI_DELMOD_INIT;
+ ipi.shorthand = IPI_SHAND_NONE;
+ ipi.logical_dest = 0;
+ error = lapic_send_ipi(mcb, &ipi);
+ if (error < 0) {
+ panic("mp: failed to send INIT IPI\n");
+ }
+
+ /* Give it 20ms then prep a STARTUP */
+ hpet_msleep(20);
+ ipi.delmod = IPI_DELMOD_STARTUP;
+ ipi.vector = (AP_BUA_PADDR >> 12);
+
+ /* The MPSpec says to send two */
+ for (uint8_t i = 0; i < 2; ++i) {
+ error = lapic_send_ipi(mcb, &ipi);
+ if (error != 0) {
+ panic("mp: failed to send STARTUP IPI\n");
+ }
+ hpet_msleep(2);
+ }
+
+ dtrace("bootstrapping lapic %d\n", lapic->apic_id);
+ return -1; /* Keep going */
+}
+
+void
+cpu_start_aps(struct cpu_info *ci)
+{
+ struct cpu_info *self;
+ struct mcb *mcb;
+ size_t bua_len;
+ uint8_t *bua;
+
+ if (ci == NULL) {
+ return;
+ }
+
+ self = cpu_self();
+ if (self == NULL) {
+ panic("mp: could not get current processor\n");
+ }
+
+ /* Copy the bring up code to the BUA */
+ bua = AP_BUA_VADDR;
+ memcpy(bua, ap_code, AP_BUA_LEN);
+
+ /* Start up the APs */
+ mcb = &self->mcb;
+ dtrace("bringing up application processors...\n");
+ acpi_read_madt(
+ APIC_TYPE_LOCAL_APIC,
+ cpu_lapic_cb,
+ lapic_read_id(mcb)
+ );
+}