BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 232d0f9e7dd31316a9b91cbdfec0174afce40c7e

// Related

Nucleus

Barry ACPI + APIC 232d0f9 (3 years, 3 months ago)
diff --git a/Makefile b/Makefile
index ac7a391..cb163ac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 PRODUCT=nucleus
 
 CC=i686-orion-gcc
-CFLAGS=-Iinclude/ -mgeneral-regs-only
+CFLAGS=-Iinclude/
 
 AS=i686-orion-as
 AFLAGS=
@@ -20,22 +20,28 @@ OBJS += $(sort $(subst ./,build/,$(subst .c,.o,$(C_SRC))))
 all: $(PRODUCT)
 
 clean:
-	@echo "REMOVING OBJECT FILES"
+	$(info Removing object files)
 	@mkdir -p build
 	@rm -rf build
 	@touch $(PRODUCT)
 	@rm $(PRODUCT)
 
 $(PRODUCT): $(OBJS)
-	@echo "LINKING $@"
+	$(info LD $@)
 	@$(LD) -o $@ $^ $(LFLAGS)
 
 build/%.o: %.c
-	@echo "COMPILING $<"
+	$(info CC $<)
 	@mkdir -p $(@D)
 	@$(CC) -c $< -o $@ $(CFLAGS)
 
 build/%.o: %.S
-	@echo "ASSEMBLING $<"
+	$(info AS $<)
 	@mkdir -p $(@D)
 	@$(AS) -c $< -o $@ $(AFLAGS)
+
+# Overrides
+build/kernel/idt.o: kernel/idt.c
+	$(info CC $<)
+	@mkdir -p $(@D)
+	@$(CC) -c $< -o $@ $(CFLAGS) -mgeneral-regs-only
diff --git a/include/nucleus/cpu.h b/include/nucleus/cpu.h
index 9192ea8..69ef379 100644
--- a/include/nucleus/cpu.h
+++ b/include/nucleus/cpu.h
@@ -6,7 +6,12 @@ struct InterruptFrame {
 	uint32_t eip, cs, eflags;
 };
 
-#define CPUID 0
-#define MAX_CPUS 1
+extern uintptr_t lapicPtr, ioapicPtr;
+#define LAPIC(off)  (*((uint32_t *) ((uint32_t)  lapicPtr + (off))))
+#define IOAPIC(off) (*((uint32_t *) ((uint32_t) ioapicPtr + (off))))
+
+extern uint8_t lapicNums[];
+#define CPUID lapicNums[(uint8_t) (LAPIC(0x20) >> 24)]
+#define MAX_CPUS 2
 
 #endif
diff --git a/kernel/acpi/acpi.c b/kernel/acpi/acpi.c
new file mode 100644
index 0000000..c30fde8
--- /dev/null
+++ b/kernel/acpi/acpi.c
@@ -0,0 +1,74 @@
+/*
+ * This file controls the ACPI
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <nucleus/panic.h>
+#include "acpi.h"
+
+/* Root System Descriptor Pointer */
+struct RSDPDesc {
+	char signature[8];
+	uint8_t checksum;
+	char oem[6];
+	uint8_t revision;
+	uint32_t rsdt;
+} __attribute__((packed));
+
+void init_apic(struct SDTHeader *);
+
+/* Table handlers */
+struct TableHandler {
+	char *sig;
+	void (*handler)(struct SDTHeader *);
+} handlers[] = {
+	{"APIC", init_apic},
+};
+
+/* Calculate the ACPI checksum */
+static uint32_t
+checksum(struct SDTHeader *header)
+{
+	char *byte = (void *) header;
+	uint32_t i, check = 0;
+	for (i = 0; i < header->length; i++)
+		check += byte[i];
+	return ((check % 0x100) == 0);
+}
+
+/* Initialise ACPI */
+void
+init_acpi(void *ebda)
+{
+	/* Search for Root System Descriptor Table */
+	char *sig;
+	for (sig = ebda; sig < (char *) 0x100000; sig++) {
+		if (!memcmp(sig, "RSD PTR ", 8))
+			break;
+	}
+	if (sig == (char *) 0x100000)
+		return;
+
+	/* RSDT checksum */
+	uint32_t i, check = 0;
+	for (i = 0; i < sizeof(struct RSDPDesc); i++)
+		check += sig[i];
+	if (check % 0x100)
+		return;
+
+	/* Iterate tables */
+	uint32_t j;
+	struct SDTHeader *rsdt = (void *) ((struct RSDPDesc *) sig)->rsdt;
+	struct SDTHeader **table = (void *) (rsdt + 1);
+	for (i = 0; i < (rsdt->length - sizeof(struct SDTHeader)) / 4; i++) {
+		if (!checksum(table[i]))
+			continue;
+		/* Try to match to a handler */
+		for (j = 0; j < sizeof(handlers)/sizeof(handlers[0]); j++) {
+			if (memcmp(table[i]->signature, handlers[j].sig, 4))
+				continue;
+			handlers[j].handler(table[i]);
+		}
+	}
+}
diff --git a/kernel/acpi/acpi.h b/kernel/acpi/acpi.h
new file mode 100644
index 0000000..9821960
--- /dev/null
+++ b/kernel/acpi/acpi.h
@@ -0,0 +1,19 @@
+#ifndef KERNEL_ACPI_H
+#define KERNEL_ACPI_H
+
+/* System Descriptor Table Header */
+struct SDTHeader {
+	char signature[4];
+	uint32_t length;
+	uint8_t revision;
+	uint8_t checksum;
+	char oem[6];
+	char oemTable[8];
+	uint32_t oemRevision;
+	uint32_t creator;
+	uint32_t creatorRevision;
+};
+
+void init_acpi(void *ebda);
+
+#endif
diff --git a/kernel/acpi/apic.c b/kernel/acpi/apic.c
new file mode 100644
index 0000000..2e786c0
--- /dev/null
+++ b/kernel/acpi/apic.c
@@ -0,0 +1,222 @@
+/*
+ * This file contains code dealing with the Advanced Programmable Interrupt
+ * Controller system.  It should provide a drop-in replacement for the standard
+ * PIC system, abstracting it in the same way.  It should also be able to handle
+ * a non-SMP system, and fall back on the PIC.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <nucleus/memory.h>
+#include <nucleus/cpu.h>
+#include <io.h>
+#include "acpi.h"
+
+void cpu_load(void);
+extern void ap_trampoline(void);
+
+/* Entry types */
+enum EntryType {
+	ENTRY_LAPIC,
+	ENTRY_IOAPIC,
+	ENTRY_IOAPIC_ISO,
+	ENTRY_IOAPIC_NMI,
+	ENTRY_LAPIC_NMI,
+	ENTRY_LAPIC_ADDR,
+	ENTRY_X2APIC = 9,
+};
+
+/* Generic Entry */
+struct EntryHeader {
+	uint8_t type, length;
+};
+
+/* Local APIC */
+struct LAPICEntry {
+	uint8_t type, length;
+	uint8_t procId, id;
+	uint32_t flags;
+};
+
+/* I/O APIC */
+struct IOAPICEntry {
+	uint8_t type, length;
+	uint8_t id, reserved;
+	uint32_t addr, gsiBase;
+};
+
+/* IOAPIC Interrupt Source Override */
+struct ISOEntry {
+	uint8_t type, length;
+	uint8_t bus, irq;
+	uint8_t gsi, flags;
+};
+
+size_t numCores = 1;
+uintptr_t lapicPtr, ioapicPtr;
+uint8_t lapicIds[MAX_CPUS], lapicNums[MAX_CPUS];
+
+/* Enable APIC */
+static void
+enable_apic(void)
+{
+	LAPIC(0xF0) = 0x1FF;
+	LAPIC(0x80) = 0;
+}
+
+/* Read from the IOAPIC */
+static uint32_t
+read_io_apic(uint32_t reg)
+{
+	uint32_t volatile *ioapic = (uint32_t volatile *) ioapicPtr;
+	ioapic[0] = (reg & 0xFF);
+	return ioapic[4];
+}
+
+/* Write to the IOAPIC */
+static void
+write_io_apic(uint32_t reg, uint32_t value)
+{
+	uint32_t volatile *ioapic = (uint32_t volatile *) ioapicPtr;
+	ioapic[0] = (reg & 0xFF);
+	ioapic[4] = value;
+}
+
+/* Delay in gaps of 100 microseconds */
+static void
+delay(uint32_t time)
+{
+	float calc = (1193182 / 10000) * time;
+	uint32_t div = (uint32_t) calc;
+	outb(0x43, 0x30);
+	outb(0x40, div & 0xFF);
+	outb(0x40, (div >> 8) & 0xFF);
+	do outb(0x43, 0xE2); while (!(inb(0x40) & (1 << 7)));
+}
+
+/* Start the APIC timer */
+static void
+apic_start_timer(void)
+{
+	/* Wait for this processor's "turn" */
+	static uint8_t c = 0;
+	while (c != CPUID);
+
+	/* Start LAPIC countdown from -1 */
+	LAPIC(0x3E0) = 3;
+	LAPIC(0x380) = 0xFFFFFFFF;
+	delay(10);
+
+	/* Stop after PIT fires, count LAPIC ticks */
+	LAPIC(0x320) = 0x10000;
+	uint32_t ticks = 0xFFFFFFFF - LAPIC(0x390);
+
+	/* Tick every 1ms */
+	LAPIC(0x320) = 0x20000 | 32;
+	LAPIC(0x3E0) = 3;
+	LAPIC(0x380) = ticks;
+
+	/* Signal next processor */
+	c++;
+}
+
+/* Initialise SMP (RSDT method) */
+void
+init_apic(struct SDTHeader *header)
+{
+	numCores = 0;
+
+	uint8_t overrides[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+	/* Iterate the entries */
+	lapicPtr = *(uint32_t *) (header + 1);
+	struct EntryHeader *entry = (void *) (header + 1) + 8;
+	struct LAPICEntry *lapic;
+	struct IOAPICEntry *ioapic;
+	struct ISOEntry *iso;
+	while ((void *) entry < (((void *) header) + header->length)) {
+		switch (entry->type) {
+		case ENTRY_LAPIC:
+			if (numCores >= MAX_CPUS)
+				break;
+			lapic = (void *) entry;
+			if (!(lapic->flags & 1))
+				break;
+			lapicNums[lapic->id] = numCores;
+			lapicIds[numCores] = lapic->id;
+			numCores++;
+			break;
+		case ENTRY_IOAPIC:
+			ioapic = (void *) entry;
+			ioapicPtr = ioapic->addr;
+			break;
+		case ENTRY_IOAPIC_ISO:
+			iso = (void *) entry;
+			overrides[iso->irq] = iso->gsi;
+			break;
+		}
+		entry = (void *) entry + entry->length;
+	}
+
+	/* Send INT#1 to IRQ#33 on CPU#0 */
+	write_io_apic(0x10 + (2 * overrides[1] + 0), 33);
+	write_io_apic(0x10 + (2 * overrides[1] + 1), lapicIds[0]);
+
+	/* Initialise APs */
+	uint32_t i, j;
+	uintptr_t apTrampoline = 0x1000, stack;
+	memcpy((void *) apTrampoline, &ap_trampoline, PAGE_SIZE);
+	for (i = 1; i < numCores; i++) {
+		/* Give each processor a separate stack */
+		stack = alloc_frame() + PAGE_SIZE - sizeof(uintptr_t);
+		*((uint32_t *) (apTrampoline + 0xF00 + i)) = stack;
+		/* Send INIT IPI */
+		LAPIC(0x280) = 0;
+		LAPIC(0x310) = (LAPIC(0x310) & 0x00FFFFFF)
+		             | (lapicIds[i] << 24);
+		LAPIC(0x300) = (LAPIC(0x300) & 0xFFF00000)
+		             | 0xC500;
+		do asm("pause":::"memory"); while (LAPIC(0x300) & (1 << 12));
+		LAPIC(0x310) = (LAPIC(0x310) & 0x00FFFFFF)
+		             | (lapicIds[i] << 24);
+		LAPIC(0x300) = (LAPIC(0x300) & 0xFFF00000)
+		             | 0x8500;
+		do asm("pause":::"memory"); while (LAPIC(0x300) & (1 << 12));
+		delay(100);
+		/* Send STARTUP IPI (twice) */
+		for (j = 0; j < 2; j++) {
+			LAPIC(0x280) = 0;
+			LAPIC(0x310) = (LAPIC(0x310) & 0x00FFFFFF)
+			             | (lapicIds[i] << 24);
+			LAPIC(0x300) = (LAPIC(0x300) & 0xFFF0F800)
+			             | (0x600 + ((apTrampoline >> 12) & 0xFF));
+			delay(2);
+			do
+				asm("pause":::"memory");
+			while (LAPIC(0x300) & (1 << 12));
+		}
+	}
+
+	/* Enable APIC */
+	enable_apic();
+	/* Disable PIC */
+	outb(0x21, 0xFF);
+	outb(0xA1, 0xFF);
+
+	apic_start_timer();
+}
+
+/* AP initialisation routine */
+_Noreturn void
+ap_startup(void)
+{
+	enable_apic();
+	cpu_load();
+	apic_start_timer();
+
+	/* Do nothing */
+	asm volatile("cli");
+	while (1)
+		asm volatile("hlt");
+}
diff --git a/kernel/acpi/trampoline.S b/kernel/acpi/trampoline.S
new file mode 100644
index 0000000..5438967
--- /dev/null
+++ b/kernel/acpi/trampoline.S
@@ -0,0 +1,79 @@
+/*
+ * This file contains the AP trampoline code to bounce it back into protected
+ * mode and run the kernel on them.  The location of the stack is set by the
+ * calling code.  This code runs initially in real mode, at 0x1000 in physical
+ * memory.
+ */
+
+.extern ap_startup
+.type ap_startup, @function
+
+.global ap_trampoline
+.type ap_trampoline, @function
+.align 4
+ap_trampoline:
+.code16
+	cli
+	jmp $0x100, $(1f - ap_trampoline)
+1:
+	mov %cs, %ax
+	mov %ax, %ds
+
+	xor %ax, %ax
+	mov %ax, %sp
+
+	/* Load the GDT */
+	lgdt (ap_gdt_desc - ap_trampoline)
+
+	/* Enable PM */
+	movl %cr0, %eax
+	orl $1, %eax
+	movl %eax, %cr0
+
+	ljmpl $8, $(ap_pm - ap_trampoline + 0x1000)
+
+ap_pm:
+.code32
+	mov $0x10, %ax
+	mov %ax, %ss
+	mov %ax, %ds
+	mov %ax, %es
+	mov %ax, %fs
+	mov %ax, %gs
+
+	movl $0x1000, %ebp
+	movl %ebp, %esp
+
+	movl ap_id, %eax
+	incl %eax
+	movl %eax, ap_id
+
+	movl $0x1F00, %esi
+	movl (%esi,%eax), %ebx
+	movl %ebx, %esp
+	movl %esp, %ebp
+
+	sti
+	jmp $8, $(ap_startup)
+
+	cli
+1:
+	hlt
+	jmp 1b
+
+.align 4
+ap_gdt_start:
+	/* Null */
+	.4byte 0x00000000
+	.4byte 0x00000000
+	/* Code */
+	.4byte 0x0000FFFF
+	.4byte 0x00CF9A00
+	/* Data */
+	.4byte 0x0000FFFF
+	.4byte 0x00CF9200
+ap_gdt_desc:
+	.2byte ap_gdt_desc - ap_gdt_start - 1
+	.4byte (ap_gdt_start - ap_trampoline) + 0x1000
+ap_id:
+	.4byte 0
diff --git a/kernel/desc.h b/kernel/desc.h
index 616deab..307ebbd 100644
--- a/kernel/desc.h
+++ b/kernel/desc.h
@@ -10,8 +10,8 @@ struct DescRecord {
 } __attribute__((packed));
 
 void init_idt(void);
-void init_gdt(void);
 void cpu_load_idt(void);
 void cpu_load_gdt(void);
+void init_pic(void);
 
 #endif
diff --git a/kernel/gdt.c b/kernel/gdt.c
index 943ffa4..21fcc14 100644
--- a/kernel/gdt.c
+++ b/kernel/gdt.c
@@ -19,7 +19,7 @@
 static struct GDTEntry {
 	uint16_t limitLower, baseLower;
 	uint8_t baseMiddle, access, gran, baseHigher;
-} __attribute__((packed)) *GDT[MAX_CPUS]; /* Per CPU */
+} __attribute__((packed)) *gdt[MAX_CPUS]; /* Per CPU */
 
 /* Structure for a TSS Entry */
 static struct TSSEntry {
@@ -33,26 +33,20 @@ static struct TSSEntry {
 	uint32_t es, cs, ss, ds, fs, gs;
 	uint32_t ldt;
 	uint16_t trap, iomapBase;
-} __attribute__((packed)) *TSS[MAX_CPUS]; /* Per CPU */
+} __attribute__((packed)) *tss[MAX_CPUS]; /* Per CPU */
 
 /* Set a gate of the GDT */
 static void
 gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access,
              uint8_t gran)
 {
-	GDT[CPUID][num].baseLower = (base & 0xFFFF);
-	GDT[CPUID][num].baseMiddle = (base >> 16) & 0xFF;
-	GDT[CPUID][num].baseHigher = (base >> 24) & 0xFF;
-	GDT[CPUID][num].limitLower = (limit & 0xFFFF);
-	GDT[CPUID][num].gran = (limit >> 16) & 0x0F;
-	GDT[CPUID][num].gran |= gran & 0xF0;
-	GDT[CPUID][num].access = access;
-}
-
-/* Initialise the GDT */
-void
-init_gdt(void)
-{
+	gdt[CPUID][num].baseLower = (base & 0xFFFF);
+	gdt[CPUID][num].baseMiddle = (base >> 16) & 0xFF;
+	gdt[CPUID][num].baseHigher = (base >> 24) & 0xFF;
+	gdt[CPUID][num].limitLower = (limit & 0xFFFF);
+	gdt[CPUID][num].gran = (limit >> 16) & 0x0F;
+	gdt[CPUID][num].gran |= gran & 0xF0;
+	gdt[CPUID][num].access = access;
 }
 
 /* Load the GDT */
@@ -68,11 +62,11 @@ cpu_load_gdt(void)
 	off_t idx = CPUID % (PAGE_SIZE / size);
 	off_t block = (CPUID / (PAGE_SIZE / size)) * (PAGE_SIZE / size);
 	if (idx == 0)
-		GDT[CPUID] = (void *) alloc_frame();
+		gdt[CPUID] = (void *) alloc_frame();
 	else
-		GDT[CPUID] = (void *) GDT[block] + (size * idx);
+		gdt[CPUID] = (void *) gdt[block] + (size * idx);
 
-	memset(GDT[CPUID], 0, size);
+	memset(gdt[CPUID], 0, size);
 
 	gdt_set_gate(0, 0x00000000, 0x00000000, 0x00, 0x00); /* Null */
 	/* Ring 0 */
@@ -82,20 +76,20 @@ cpu_load_gdt(void)
 	gdt_set_gate(3, 0x00000000, 0xFFFFFFFF, 0xFA, 0xCF); /* Code */
 	gdt_set_gate(4, 0x00000000, 0xFFFFFFFF, 0xF2, 0xCF); /* Data */
 
-	uint32_t addr = (uint32_t) GDT[CPUID] + (sizeof(struct GDTEntry) * 6);
+	uint32_t addr = (uint32_t) gdt[CPUID] + (sizeof(struct GDTEntry) * 6);
 	gdt_set_gate(5, addr, sizeof(struct TSSEntry) - 1, 0xE9, 0);
 
-	TSS[CPUID] = (void *) addr;
-	TSS[CPUID]->ss0 = 0x10;
-	TSS[CPUID]->esp0 = 0xF0800000 - sizeof(uintptr_t);
-	TSS[CPUID]->cs = 0x08 | 0;
-	TSS[CPUID]->ds = TSS[CPUID]->es = TSS[CPUID]->ss = 0x10 | 0;
-	TSS[CPUID]->fs = TSS[CPUID]->gs = 0x10 | 3;
-	TSS[CPUID]->iomapBase = sizeof(struct TSSEntry);
+	tss[CPUID] = (void *) addr;
+	tss[CPUID]->ss0 = 0x10;
+	tss[CPUID]->esp0 = 0xF0800000 - sizeof(uintptr_t);
+	tss[CPUID]->cs = 0x08 | 0;
+	tss[CPUID]->ds = tss[CPUID]->es = tss[CPUID]->ss = 0x10 | 0;
+	tss[CPUID]->fs = tss[CPUID]->gs = 0x10 | 3;
+	tss[CPUID]->iomapBase = sizeof(struct TSSEntry);
 
 	struct DescRecord ptr = {
 		.limit = sizeof(struct GDTEntry) * 6,
-		.base = (uintptr_t) GDT[CPUID],
+		.base = (uintptr_t) gdt[CPUID],
 	};
 	asm volatile("lgdt %0" :: "m" (ptr));
 	asm volatile("ltr %w0" :: "q" (0x28 | 3));
diff --git a/kernel/main.c b/kernel/main.c
index 6f2011e..a343089 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -10,6 +10,7 @@
 #include <nucleus/panic.h>
 #include "multiboot.h"
 #include "desc.h"
+#include "acpi/acpi.h"
 
 extern char _bss[], _end[];
 
@@ -52,9 +53,9 @@ kmain(uint32_t esp, struct MultibootInfo *mbinfo)
 
 	/* Processor startup */
 	init_idt();
-	init_gdt();
-	//init_pic();
+	init_pic();
 	cpu_load();
+	init_acpi(ebda);
 
 	panic("End of kernel!");
 }
diff --git a/kernel/pic.c b/kernel/pic.c
new file mode 100644
index 0000000..566abb2
--- /dev/null
+++ b/kernel/pic.c
@@ -0,0 +1,42 @@
+/*
+ * This file deals with the Programmable Interrupt Controller.  It is usually
+ * disabled and replaced by the Advanced Programmable Interrupt Controller.  It
+ * is required to be enabled for the APIC to initialise, and can be used as a
+ * fallback if there is no APIC in the system.
+ */
+
+#include <stdint.h>
+#include <io.h>
+
+/* Initialise the PIT to a specified frequency */
+static void
+init_pit(uint32_t freq)
+{
+	uint32_t div = 1193182 / freq;
+	outb(0x43, 0x36);
+	outb(0x40, div & 0xFF);
+	outb(0x40, (div >> 8) & 0xFF);
+}
+
+/* Initialise the PIC */
+void
+init_pic(void)
+{
+	/*
+	 * By default interrupts and exceptions both start at IRQ#0.  To avoid
+	 * collision interrupts are mapped to start at IRQ#32.  Since lower
+	 * numbered IRQ lines are higher priority, exceptions have priority.
+	 */
+	outb(0x20, 0x11); io_wait();
+	outb(0xA0, 0x11); io_wait();
+	outb(0x21, 0x20); io_wait();
+	outb(0xA1, 0x28); io_wait();
+	outb(0x21, 0x04); io_wait();
+	outb(0xA1, 0x02); io_wait();
+	outb(0x21, 0x01); io_wait();
+	outb(0xA1, 0x01); io_wait();
+	outb(0x21, 0x00); io_wait();
+	outb(0xA1, 0x00); io_wait();
+
+	init_pit(1000);
+}
diff --git a/kernel/000.S b/kernel/start.S
similarity index 100%
rename from kernel/000.S
rename to kernel/start.S
diff --git a/lib/mem.c b/lib/mem.c
index a41ec26..7cf1815 100644
--- a/lib/mem.c
+++ b/lib/mem.c
@@ -11,3 +11,26 @@ memset(void *dest, int byte, size_t len)
 	}
 	return dest;
 }
+
+/* Copy one region of memory to another */
+int
+memcmp(void *s1, void *s2, size_t n)
+{
+	unsigned char *a = (unsigned char *) s1,
+	              *b = (unsigned char *) s2;
+	while (n-- > 0)
+			if (*a++ != *b++)
+				return a[-1] - b[-1];
+	return 0;
+}
+
+/* Copy one region of memory to another */
+void *
+memcpy(void *dest, void *src, size_t n)
+{
+	unsigned char *a = (unsigned char *) dest,
+	              *b = (unsigned char *) src;
+	while (n-- > 0)
+		*a++ = *b++;
+	return dest;
+}
diff --git a/memory/frame.c b/memory/frame.c
index 512c47d..8a868ea 100644
--- a/memory/frame.c
+++ b/memory/frame.c
@@ -140,7 +140,7 @@ init_frames(uint32_t size, void *addr)
 	int i, j;
 	struct E820Entry *memMap = addr;
 	struct FrameRegion *prev = NULL, *head = regions;
-	uintptr_t bumpAlloc = PAGE_SIZE;
+	uintptr_t bumpAlloc = PAGE_SIZE * 2; /* Leave room for AP trampoline */
 	for (i = 0; i < size / sizeof(struct E820Entry); i++) {
 		if (memMap[i].baseHigh > 0
 		 || memMap[i].base > 0xFFFFFFFF