diff --git a/Makefile b/Makefile index 0b866f65..9479c4d6 100644 --- a/Makefile +++ b/Makefile @@ -233,7 +233,7 @@ endif ifeq ($(HAVE_KVM), kvm) QEMU_PARAMS += -enable-kvm endif # HAVE_KVM -QEMU_PARAMS += -m 8192 +QEMU_PARAMS += -m 128 QEMU_PARAMS += -display none -vga none -vnc none QEMU_PARAMS += -serial stdio QEMU_PARAMS += -smp cpus=2 diff --git a/drivers/acpi/acpica/osl.c b/drivers/acpi/acpica/osl.c index fac4be24..66a74e25 100644 --- a/drivers/acpi/acpica/osl.c +++ b/drivers/acpi/acpica/osl.c @@ -36,17 +36,35 @@ #include "acpi.h" +struct mapped_frame { + struct list_head list; + mfn_t mfn; + uint64_t refcount; +}; +typedef struct mapped_frame mapped_frame_t; + +static list_head_t mapped_frames; + +static spinlock_t map_lock = SPINLOCK_INIT; + /* General OS functions */ ACPI_STATUS AcpiOsInitialize(void) { dprintk("ACPI OS Initialization:\n"); + list_init(&mapped_frames); return AE_OK; } ACPI_STATUS AcpiOsTerminate(void) { + mapped_frame_t *frame; + dprintk("ACPI OS Termination:\n"); + list_for_each_entry (frame, &mapped_frames, list) { + list_unlink(&frame->list); + kfree(frame); + } return AE_OK; } @@ -214,7 +232,7 @@ BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length) { for (mfn_t mfn = virt_to_mfn(Memory); mfn <= virt_to_mfn((char *) Memory + Length); ++mfn) { success = false; - mem = mfn_to_virt_kern(mfn); + mem = mfn_to_virt_map(mfn); asm volatile("1: movq ( %[mem] ), %%rax; movq $1, %[success];" "2:" ASM_EXTABLE(1b, 2b) : [ success ] "=m"(success) @@ -233,7 +251,7 @@ BOOLEAN AcpiOsWriteable(void *Memory, ACPI_SIZE Length) { for (mfn_t mfn = virt_to_mfn(Memory); mfn <= virt_to_mfn((char *) Memory + Length); ++mfn) { success = false; - mem = mfn_to_virt_kern(mfn); + mem = mfn_to_virt_map(mfn); asm volatile("1: orq $0, ( %[mem] ); movq $1, %[success];" "2:" ASM_EXTABLE(1b, 2b) : [ success ] "=m"(success), [ mem ] "=r"(mem) @@ -246,20 +264,52 @@ BOOLEAN AcpiOsWriteable(void *Memory, ACPI_SIZE Length) { return success; } +static inline mapped_frame_t *find_mapped_frame(mfn_t mfn) { + mapped_frame_t *frame; + + list_for_each_entry (frame, &mapped_frames, list) { + if (frame->mfn == mfn) + return frame; + } + + return NULL; +} + +static inline void new_mapped_frame(mfn_t mfn) { + mapped_frame_t *frame = kzalloc(sizeof(*frame)); + frame->mfn = mfn; + frame->refcount = 1; + list_add(&frame->list, &mapped_frames); +} + void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length) { unsigned offset = PhysicalAddress & ~PAGE_MASK; unsigned num_pages = ((offset + Length) / PAGE_SIZE) + 1; mfn_t mfn = paddr_to_mfn(PhysicalAddress); void *va = NULL; + spin_lock(&map_lock); for (unsigned i = 0; i < num_pages; i++, mfn++) { - void *_va = kmap_4k(mfn, L1_PROT); - if (!_va) - return NULL; + mapped_frame_t *frame = find_mapped_frame(mfn); + void *_va; + + if (!frame) { + _va = mmap_4k(mfn, L1_PROT); + if (!_va) { + spin_unlock(&map_lock); + return NULL; + } + new_mapped_frame(mfn); + } + else { + frame->refcount++; + _va = mfn_to_virt_map(mfn); + } if (!va) va = _ptr(_ul(_va) + offset); } + spin_unlock(&map_lock); return va; } @@ -269,8 +319,19 @@ void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length) { unsigned num_pages = ((offset + Length) / PAGE_SIZE) + 1; mfn_t mfn = virt_to_mfn(LogicalAddress); - for (unsigned i = 0; i < num_pages; i++, mfn++) - vunmap(mfn_to_virt_kern(mfn), PAGE_ORDER_4K); + spin_lock(&map_lock); + for (unsigned i = 0; i < num_pages; i++, mfn++) { + mapped_frame_t *frame = find_mapped_frame(mfn); + BUG_ON(!frame || frame->refcount == 0); + + if (--frame->refcount > 0) + continue; + + vunmap(mfn_to_virt_map(mfn), PAGE_ORDER_4K); + list_unlink(&frame->list); + kfree(frame); + } + spin_unlock(&map_lock); } /* Task management functions */