[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/include/kernel/debug.h b/src/bsp/lk/include/kernel/debug.h
new file mode 100644
index 0000000..3677caf
--- /dev/null
+++ b/src/bsp/lk/include/kernel/debug.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012-2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_DEBUG_H
+#define __KERNEL_DEBUG_H
+
+#include <compiler.h>
+
+__BEGIN_CDECLS;
+
+#include <debug.h>
+
+/* kernel event log */
+#if WITH_KERNEL_EVLOG
+
+#include <lib/evlog.h>
+
+#ifndef KERNEL_EVLOG_LEN
+#define KERNEL_EVLOG_LEN 1024
+#endif
+
+void kernel_evlog_init(void);
+
+void kernel_evlog_add(uintptr_t id, uintptr_t arg0, uintptr_t arg1);
+void kernel_evlog_dump(void);
+
+#else // !WITH_KERNEL_EVLOG
+
+/* do nothing versions */
+static inline void kernel_evlog_init(void) {}
+static inline void kernel_evlog_add(uintptr_t id, uintptr_t arg0, uintptr_t arg1) {}
+static inline void kernel_evlog_dump(void) {}
+
+#endif
+
+enum {
+ KERNEL_EVLOG_NULL = 0,
+ KERNEL_EVLOG_CONTEXT_SWITCH,
+ KERNEL_EVLOG_PREEMPT,
+ KERNEL_EVLOG_TIMER_TICK,
+ KERNEL_EVLOG_TIMER_CALL,
+ KERNEL_EVLOG_IRQ_ENTER,
+ KERNEL_EVLOG_IRQ_EXIT,
+};
+
+#define KEVLOG_THREAD_SWITCH(from, to) kernel_evlog_add(KERNEL_EVLOG_CONTEXT_SWITCH, (uintptr_t)from, (uintptr_t)to)
+#define KEVLOG_THREAD_PREEMPT(thread) kernel_evlog_add(KERNEL_EVLOG_PREEMPT, (uintptr_t)thread, 0)
+#define KEVLOG_TIMER_TICK() kernel_evlog_add(KERNEL_EVLOG_TIMER_TICK, 0, 0)
+#define KEVLOG_TIMER_CALL(ptr, arg) kernel_evlog_add(KERNEL_EVLOG_TIMER_CALL, (uintptr_t)ptr, (uintptr_t)arg)
+#define KEVLOG_IRQ_ENTER(irqn) kernel_evlog_add(KERNEL_EVLOG_IRQ_ENTER, (uintptr_t)irqn, 0)
+#define KEVLOG_IRQ_EXIT(irqn) kernel_evlog_add(KERNEL_EVLOG_IRQ_EXIT, (uintptr_t)irqn, 0)
+
+__END_CDECLS;
+
+#endif
+
diff --git a/src/bsp/lk/include/kernel/event.h b/src/bsp/lk/include/kernel/event.h
new file mode 100644
index 0000000..65074ca
--- /dev/null
+++ b/src/bsp/lk/include/kernel/event.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2008-2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_EVENT_H
+#define __KERNEL_EVENT_H
+
+#include <compiler.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <kernel/thread.h>
+
+__BEGIN_CDECLS;
+
+#define EVENT_MAGIC 'evnt'
+
+typedef struct event {
+ int magic;
+ bool signalled;
+ uint flags;
+ wait_queue_t wait;
+} event_t;
+
+#define EVENT_FLAG_AUTOUNSIGNAL 1
+
+#define EVENT_INITIAL_VALUE(e, initial, _flags) \
+{ \
+ .magic = EVENT_MAGIC, \
+ .signalled = initial, \
+ .flags = _flags, \
+ .wait = WAIT_QUEUE_INITIAL_VALUE((e).wait), \
+}
+
+/* Rules for Events:
+ * - Events may be signaled from interrupt context *but* the reschedule
+ * parameter must be false in that case.
+ * - Events may not be waited upon from interrupt context.
+ * - Events without FLAG_AUTOUNSIGNAL:
+ * - Wake up any waiting threads when signaled.
+ * - Continue to do so (no threads will wait) until unsignaled.
+ * - Events with FLAG_AUTOUNSIGNAL:
+ * - If one or more threads are waiting when signaled, one thread will
+ * be woken up and return. The signaled state will not be set.
+ * - If no threads are waiting when signaled, the Event will remain
+ * in the signaled state until a thread attempts to wait (at which
+ * time it will unsignal atomicly and return immediately) or
+ * event_unsignal() is called.
+*/
+
+void event_init(event_t *, bool initial, uint flags);
+void event_destroy(event_t *);
+status_t event_wait_timeout(event_t *, lk_time_t); /* wait on the event with a timeout */
+status_t event_signal(event_t *, bool reschedule);
+status_t event_unsignal(event_t *);
+
+static inline bool event_initialized(event_t *e) {
+ return e->magic == EVENT_MAGIC;
+}
+
+static inline status_t event_wait(event_t *e) {
+ return event_wait_timeout(e, INFINITE_TIME);
+}
+
+__END_CDECLS;
+
+#endif
+
diff --git a/src/bsp/lk/include/kernel/mp.h b/src/bsp/lk/include/kernel/mp.h
new file mode 100644
index 0000000..a015ebd
--- /dev/null
+++ b/src/bsp/lk/include/kernel/mp.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <compiler.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <kernel/thread.h>
+
+__BEGIN_CDECLS;
+
+typedef uint32_t mp_cpu_mask_t;
+
+#define MP_CPU_ALL_BUT_LOCAL (UINT32_MAX)
+
+/* by default, mp_mbx_reschedule does not signal to cpus that are running realtime
+ * threads. Override this behavior.
+ */
+#define MP_RESCHEDULE_FLAG_REALTIME (0x1)
+
+typedef enum {
+ MP_IPI_GENERIC,
+ MP_IPI_RESCHEDULE,
+} mp_ipi_t;
+
+#ifdef WITH_SMP
+void mp_init(void);
+
+void mp_reschedule(mp_cpu_mask_t target, uint flags);
+void mp_set_curr_cpu_active(bool active);
+
+/* called from arch code during reschedule irq */
+enum handler_return mp_mbx_reschedule_irq(void);
+
+/* global mp state to track what the cpus are up to */
+struct mp_state {
+ volatile mp_cpu_mask_t active_cpus;
+
+ /* only safely accessible with thread lock held */
+ mp_cpu_mask_t idle_cpus;
+ mp_cpu_mask_t realtime_cpus;
+};
+
+extern struct mp_state mp;
+
+static inline int mp_is_cpu_active(uint cpu)
+{
+ return mp.active_cpus & (1 << cpu);
+}
+
+static inline int mp_is_cpu_idle(uint cpu)
+{
+ return mp.idle_cpus & (1 << cpu);
+}
+
+/* must be called with the thread lock held */
+static inline void mp_set_cpu_idle(uint cpu)
+{
+ mp.idle_cpus |= 1UL << cpu;
+}
+
+static inline void mp_set_cpu_busy(uint cpu)
+{
+ mp.idle_cpus &= ~(1UL << cpu);
+}
+
+static inline mp_cpu_mask_t mp_get_idle_mask(void)
+{
+ return mp.idle_cpus;
+}
+
+static inline void mp_set_cpu_realtime(uint cpu)
+{
+ mp.realtime_cpus |= 1UL << cpu;
+}
+
+static inline void mp_set_cpu_non_realtime(uint cpu)
+{
+ mp.realtime_cpus &= ~(1UL << cpu);
+}
+
+static inline mp_cpu_mask_t mp_get_realtime_mask(void)
+{
+ return mp.realtime_cpus;
+}
+#else
+static inline void mp_init(void) {}
+static inline void mp_reschedule(mp_cpu_mask_t target, uint flags) {}
+static inline void mp_set_curr_cpu_active(bool active) {}
+
+static inline enum handler_return mp_mbx_reschedule_irq(void) { return 0; }
+
+// only one cpu exists in UP and if you're calling these functions, it's active...
+static inline int mp_is_cpu_active(uint cpu) { return 1; }
+static inline int mp_is_cpu_idle(uint cpu) { return 0; }
+
+static inline void mp_set_cpu_idle(uint cpu) {}
+static inline void mp_set_cpu_busy(uint cpu) {}
+
+static inline mp_cpu_mask_t mp_get_idle_mask(void) { return 0; }
+
+static inline void mp_set_cpu_realtime(uint cpu) {}
+static inline void mp_set_cpu_non_realtime(uint cpu) {}
+
+static inline mp_cpu_mask_t mp_get_realtime_mask(void) { return 0; }
+#endif
+
+__END_CDECLS;
diff --git a/src/bsp/lk/include/kernel/mutex.h b/src/bsp/lk/include/kernel/mutex.h
new file mode 100644
index 0000000..ae7e233
--- /dev/null
+++ b/src/bsp/lk/include/kernel/mutex.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2008-2014 Travis Geiselbrecht
+ * Copyright (c) 2012 Shantanu Gupta
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_MUTEX_H
+#define __KERNEL_MUTEX_H
+
+#include <compiler.h>
+#include <debug.h>
+#include <stdint.h>
+#include <kernel/thread.h>
+
+__BEGIN_CDECLS;
+
+#define MUTEX_MAGIC 'mutx'
+
+typedef struct mutex {
+ uint32_t magic;
+ thread_t *holder;
+ int count;
+ wait_queue_t wait;
+} mutex_t;
+
+#define MUTEX_INITIAL_VALUE(m) \
+{ \
+ .magic = MUTEX_MAGIC, \
+ .holder = NULL, \
+ .count = 0, \
+ .wait = WAIT_QUEUE_INITIAL_VALUE((m).wait), \
+}
+
+/* Rules for Mutexes:
+ * - Mutexes are only safe to use from thread context.
+ * - Mutexes are non-recursive.
+*/
+
+void mutex_init(mutex_t *);
+void mutex_destroy(mutex_t *);
+status_t mutex_acquire_timeout(mutex_t *, lk_time_t); /* try to acquire the mutex with a timeout value */
+status_t mutex_release(mutex_t *);
+
+static inline status_t mutex_acquire(mutex_t *m) {
+ return mutex_acquire_timeout(m, INFINITE_TIME);
+}
+
+/* does the current thread hold the mutex? */
+static bool is_mutex_held(mutex_t *m) {
+ return m->holder == get_current_thread();
+}
+
+__END_CDECLS;
+#endif
+
diff --git a/src/bsp/lk/include/kernel/novm.h b/src/bsp/lk/include/kernel/novm.h
new file mode 100644
index 0000000..c55c320
--- /dev/null
+++ b/src/bsp/lk/include/kernel/novm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 Google, Inc. All rights reserved
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_NOVM_H
+#define __KERNEL_NOVM_H
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <arch.h>
+
+#define PAGE_ALIGN(x) ALIGN(x, PAGE_SIZE)
+#define IS_PAGE_ALIGNED(x) IS_ALIGNED(x, PAGE_SIZE)
+
+// arena bitmaps for novm_alloc_pages
+#define NOVM_ARENA_ANY (UINT32_MAX)
+#define NOVM_ARENA_MAIN (1<<0)
+#define NOVM_ARENA_SECONDARY (~NOVM_ARENA_MAIN)
+
+void *novm_alloc_pages(size_t pages, uint32_t arena_bitmap);
+void novm_free_pages(void* address, size_t pages);
+status_t novm_alloc_specific_pages(void *address, size_t pages);
+
+// You can call this once and it will give you some possibly unaligned memory
+// that would otherwise go to waste. The memory can't be freed.
+void *novm_alloc_unaligned(size_t *size_return);
+
+void novm_add_arena(const char *name, uintptr_t arena_start, uintptr_t arena_size);
+
+#endif
diff --git a/src/bsp/lk/include/kernel/port.h b/src/bsp/lk/include/kernel/port.h
new file mode 100644
index 0000000..347125e
--- /dev/null
+++ b/src/bsp/lk/include/kernel/port.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015 Carlos Pizano-Uribe cpu@chromium.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_PORT_H
+#define __KERNEL_PORT_H
+
+#include <sys/types.h>
+#include <compiler.h>
+
+
+__BEGIN_CDECLS;
+
+/* Ports are named, opaque objects and come in tree flavors, the
+ * write-side, the read-side and a port group which is a collection
+ * of read-side ports.
+ */
+
+#define PORT_NAME_LEN 12
+
+typedef void* port_t;
+
+typedef struct {
+ char value[8];
+} port_packet_t;
+
+typedef struct {
+ void* ctx;
+ port_packet_t packet;
+} port_result_t;
+
+typedef enum {
+ PORT_MODE_BROADCAST = 0,
+ PORT_MODE_UNICAST = 1,
+ PORT_MODE_BIG_BUFFER = 2,
+} port_mode_t;
+
+/* Inits the port subsystem
+ */
+void port_init(void);
+
+/* Make a named write-side port. broadcast ports can be opened by any
+ * number of read-clients. |name| can be up to PORT_NAME_LEN chars. If
+ * the write port exists it is returned even if the |mode| does not match.
+ */
+status_t port_create(const char* name, port_mode_t mode, port_t* port);
+
+/* Make a read-side port. Only non-destroyed existing write ports can
+ * be opened with this api. Unicast ports can only be opened once. For
+ * broadcast ports, each call if successful returns a new port.
+ */
+status_t port_open(const char* name, void* ctx, port_t* port);
+
+/* Creates a read-side port group which behaves just like a regular
+ * read-side port. A given port can only be assoicated with one port group.
+ */
+status_t port_group(port_t* ports, size_t count, port_t* group);
+
+/* Write to a port |count| packets, non-blocking, all or none atomic success.
+ */
+status_t port_write(port_t port, const port_packet_t* pk, size_t count);
+
+/* Read one packet from the port or port group, blocking. The |result| contains
+ * the port that the message was read from. If |timeout| is zero the call
+ * does not block.
+ */
+status_t port_read(port_t port, lk_time_t timeout, port_result_t* result);
+
+/* Destroy the write-side port, flush queued packets and release all resources,
+ * all calls will now fail on that port. Only a closed port can be destroyed.
+ */
+status_t port_destroy(port_t port);
+
+/* Close the read-side port or the write side port. A closed write side port
+ * can be opened and the pending packets read. closing a port group does not
+ * close the included ports.
+ */
+status_t port_close(port_t port);
+
+__END_CDECLS;
+
+#endif
+
diff --git a/src/bsp/lk/include/kernel/semaphore.h b/src/bsp/lk/include/kernel/semaphore.h
new file mode 100644
index 0000000..99d9a20
--- /dev/null
+++ b/src/bsp/lk/include/kernel/semaphore.h
@@ -0,0 +1,49 @@
+/* semaphore.h
+ *
+ * Copyright 2012 Christopher Anderson <chris@nullcode.org>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KERNEL_SEMAPHORE_H
+#define __KERNEL_SEMAPHORE_H
+
+#include <compiler.h>
+#include <kernel/thread.h>
+#include <kernel/mutex.h>
+
+__BEGIN_CDECLS;
+
+#define SEMAPHORE_MAGIC 'sema'
+
+typedef struct semaphore {
+ int magic;
+ int count;
+ wait_queue_t wait;
+} semaphore_t;
+
+#define SEMAPHORE_INITIAL_VALUE(s, _count) \
+{ \
+ .magic = SEMAPHORE_MAGIC, \
+ .count = _count, \
+ .wait = WAIT_QUEUE_INITIAL_VALUE((s).wait), \
+}
+
+void sem_init(semaphore_t *, unsigned int);
+void sem_destroy(semaphore_t *);
+int sem_post(semaphore_t *, bool resched);
+status_t sem_wait(semaphore_t *);
+status_t sem_trywait(semaphore_t *);
+status_t sem_timedwait(semaphore_t *, lk_time_t);
+
+__END_CDECLS;
+#endif
diff --git a/src/bsp/lk/include/kernel/spinlock.h b/src/bsp/lk/include/kernel/spinlock.h
new file mode 100644
index 0000000..b9bf246
--- /dev/null
+++ b/src/bsp/lk/include/kernel/spinlock.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <compiler.h>
+#include <arch/spinlock.h>
+
+__BEGIN_CDECLS
+
+/* interrupts should already be disabled */
+static inline void spin_lock(spin_lock_t *lock)
+{
+ arch_spin_lock(lock);
+}
+
+ /* Returns 0 on success, non-0 on failure */
+static inline int spin_trylock(spin_lock_t *lock)
+{
+ return arch_spin_trylock(lock);
+}
+
+/* interrupts should already be disabled */
+static inline void spin_unlock(spin_lock_t *lock)
+{
+ arch_spin_unlock(lock);
+}
+
+static inline void spin_lock_init(spin_lock_t *lock)
+{
+ arch_spin_lock_init(lock);
+}
+
+static inline bool spin_lock_held(spin_lock_t *lock)
+{
+ return arch_spin_lock_held(lock);
+}
+
+/* spin lock irq save flags: */
+
+/* Possible future flags:
+ * SPIN_LOCK_FLAG_PMR_MASK = 0x000000ff
+ * SPIN_LOCK_FLAG_PREEMPTION = 0x00000100
+ * SPIN_LOCK_FLAG_SET_PMR = 0x00000200
+ */
+
+/* Generic flags */
+#define SPIN_LOCK_FLAG_INTERRUPTS ARCH_DEFAULT_SPIN_LOCK_FLAG_INTERRUPTS
+
+/* same as spin lock, but save disable and save interrupt state first */
+static inline void spin_lock_save(
+ spin_lock_t *lock,
+ spin_lock_saved_state_t *statep,
+ spin_lock_save_flags_t flags)
+{
+ arch_interrupt_save(statep, flags);
+ spin_lock(lock);
+}
+
+/* restore interrupt state before unlocking */
+static inline void spin_unlock_restore(
+ spin_lock_t *lock,
+ spin_lock_saved_state_t old_state,
+ spin_lock_save_flags_t flags)
+{
+ spin_unlock(lock);
+ arch_interrupt_restore(old_state, flags);
+}
+
+/* hand(ier) routines */
+#define spin_lock_irqsave(lock, statep) spin_lock_save(lock, &(statep), SPIN_LOCK_FLAG_INTERRUPTS)
+#define spin_unlock_irqrestore(lock, statep) spin_unlock_restore(lock, statep, SPIN_LOCK_FLAG_INTERRUPTS)
+
+__END_CDECLS
diff --git a/src/bsp/lk/include/kernel/thread.h b/src/bsp/lk/include/kernel/thread.h
new file mode 100644
index 0000000..7ddbf21
--- /dev/null
+++ b/src/bsp/lk/include/kernel/thread.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2008-2015 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_THREAD_H
+#define __KERNEL_THREAD_H
+
+#include <sys/types.h>
+#include <list.h>
+#include <compiler.h>
+#include <arch/defines.h>
+#include <arch/ops.h>
+#include <arch/thread.h>
+#include <kernel/wait.h>
+#include <kernel/spinlock.h>
+#include <debug.h>
+
+__BEGIN_CDECLS;
+
+/* debug-enable runtime checks */
+#if LK_DEBUGLEVEL > 1
+#define THREAD_STATS 1
+#define THREAD_STACK_BOUNDS_CHECK 1
+#ifndef THREAD_STACK_PADDING_SIZE
+#define THREAD_STACK_PADDING_SIZE 256
+#endif
+#endif
+
+enum thread_state {
+ THREAD_SUSPENDED = 0,
+ THREAD_READY,
+ THREAD_RUNNING,
+ THREAD_BLOCKED,
+ THREAD_SLEEPING,
+ THREAD_DEATH,
+};
+
+typedef int (*thread_start_routine)(void *arg);
+
+/* thread local storage */
+enum thread_tls_list {
+#ifdef WITH_LIB_UTHREAD
+ TLS_ENTRY_UTHREAD,
+#endif
+#ifdef WITH_LIB_LKUSER
+ TLS_ENTRY_LKUSER,
+#endif
+ MAX_TLS_ENTRY
+};
+
+#define THREAD_FLAG_DETACHED (1<<0)
+#define THREAD_FLAG_FREE_STACK (1<<1)
+#define THREAD_FLAG_FREE_STRUCT (1<<2)
+#define THREAD_FLAG_REAL_TIME (1<<3)
+#define THREAD_FLAG_IDLE (1<<4)
+#define THREAD_FLAG_DEBUG_STACK_BOUNDS_CHECK (1<<5)
+
+#define THREAD_MAGIC 'thrd'
+
+typedef struct thread {
+ int magic;
+ struct list_node thread_list_node;
+
+ /* active bits */
+ struct list_node queue_node;
+ int priority;
+ enum thread_state state;
+ int remaining_quantum;
+ unsigned int flags;
+#if WITH_SMP
+ int curr_cpu;
+ int pinned_cpu; /* only run on pinned_cpu if >= 0 */
+#endif
+
+ /* if blocked, a pointer to the wait queue */
+ struct wait_queue *blocking_wait_queue;
+ status_t wait_queue_block_ret;
+
+ /* architecture stuff */
+ struct arch_thread arch;
+
+ /* stack stuff */
+ void *stack;
+ size_t stack_size;
+
+ /* entry point */
+ thread_start_routine entry;
+ void *arg;
+
+ /* return code */
+ int retcode;
+ struct wait_queue retcode_wait_queue;
+
+ /* thread local storage */
+ uintptr_t tls[MAX_TLS_ENTRY];
+
+ char name[32];
+} thread_t;
+
+#if WITH_SMP
+#define thread_curr_cpu(t) ((t)->curr_cpu)
+#define thread_pinned_cpu(t) ((t)->pinned_cpu)
+#define thread_set_curr_cpu(t,c) ((t)->curr_cpu = (c))
+#define thread_set_pinned_cpu(t, c) ((t)->pinned_cpu = (c))
+#else
+#define thread_curr_cpu(t) (0)
+#define thread_pinned_cpu(t) (-1)
+#define thread_set_curr_cpu(t,c) do {} while(0)
+#define thread_set_pinned_cpu(t, c) do {} while(0)
+#endif
+
+/* thread priority */
+#define NUM_PRIORITIES 32
+#define LOWEST_PRIORITY 0
+#define HIGHEST_PRIORITY (NUM_PRIORITIES - 1)
+#define DPC_PRIORITY (NUM_PRIORITIES - 2)
+#define IDLE_PRIORITY LOWEST_PRIORITY
+#define LOW_PRIORITY (NUM_PRIORITIES / 4)
+#define DEFAULT_PRIORITY (NUM_PRIORITIES / 2)
+#define HIGH_PRIORITY ((NUM_PRIORITIES / 4) * 3)
+
+/* stack size */
+#ifdef CUSTOM_DEFAULT_STACK_SIZE
+#define DEFAULT_STACK_SIZE CUSTOM_DEFAULT_STACK_SIZE
+#else
+#define DEFAULT_STACK_SIZE ARCH_DEFAULT_STACK_SIZE
+#endif
+
+/* functions */
+void thread_init_early(void);
+void thread_init(void);
+void thread_become_idle(void) __NO_RETURN;
+void thread_secondary_cpu_init_early(void);
+void thread_secondary_cpu_entry(void) __NO_RETURN;
+void thread_set_name(const char *name);
+void thread_set_priority(int priority);
+thread_t *thread_create(const char *name, thread_start_routine entry, void *arg, int priority, size_t stack_size);
+thread_t *thread_create_etc(thread_t *t, const char *name, thread_start_routine entry, void *arg, int priority, void *stack, size_t stack_size);
+status_t thread_resume(thread_t *);
+void thread_exit(int retcode) __NO_RETURN;
+void thread_sleep(lk_time_t delay);
+status_t thread_detach(thread_t *t);
+status_t thread_join(thread_t *t, int *retcode, lk_time_t timeout);
+status_t thread_detach_and_resume(thread_t *t);
+status_t thread_set_real_time(thread_t *t);
+
+void dump_thread(thread_t *t);
+void arch_dump_thread(thread_t *t);
+void dump_all_threads(void);
+
+/* scheduler routines */
+void thread_yield(void); /* give up the cpu voluntarily */
+void thread_preempt(void); /* get preempted (inserted into head of run queue) */
+void thread_block(void); /* block on something and reschedule */
+void thread_unblock(thread_t *t, bool resched); /* go back in the run queue */
+
+#ifdef WITH_LIB_UTHREAD
+void uthread_context_switch(thread_t *oldthread, thread_t *newthread);
+#endif
+
+/* called on every timer tick for the scheduler to do quantum expiration */
+struct timer;
+enum handler_return thread_timer_tick(struct timer *, lk_time_t now, void *arg);
+
+/* the current thread */
+thread_t *get_current_thread(void);
+void set_current_thread(thread_t *);
+
+/* scheduler lock */
+extern spin_lock_t thread_lock;
+
+#define THREAD_LOCK(state) spin_lock_saved_state_t state; spin_lock_irqsave(&thread_lock, state)
+#define THREAD_UNLOCK(state) spin_unlock_irqrestore(&thread_lock, state)
+
+/* thread local storage */
+static inline __ALWAYS_INLINE uintptr_t tls_get(uint entry)
+{
+ return get_current_thread()->tls[entry];
+}
+
+static inline __ALWAYS_INLINE uintptr_t __tls_set(uint entry, uintptr_t val)
+{
+ uintptr_t oldval = get_current_thread()->tls[entry];
+ get_current_thread()->tls[entry] = val;
+ return oldval;
+}
+
+#define tls_set(e,v) \
+ ({ \
+ STATIC_ASSERT((e) < MAX_TLS_ENTRY); \
+ __tls_set(e, v); \
+ })
+
+/* thread level statistics */
+#if THREAD_STATS
+struct thread_stats {
+ lk_bigtime_t idle_time;
+ lk_bigtime_t last_idle_timestamp;
+ ulong reschedules;
+ ulong context_switches;
+ ulong preempts;
+ ulong yields;
+ ulong interrupts; /* platform code increment this */
+ ulong timer_ints; /* timer code increment this */
+ ulong timers; /* timer code increment this */
+
+#if WITH_SMP
+ ulong reschedule_ipis;
+#endif
+};
+
+extern struct thread_stats thread_stats[SMP_MAX_CPUS];
+
+#define THREAD_STATS_INC(name) do { thread_stats[arch_curr_cpu_num()].name++; } while(0)
+
+#else
+
+#define THREAD_STATS_INC(name) do { } while (0)
+
+#endif
+
+__END_CDECLS;
+
+#endif
+
+/* vim: set ts=4 sw=4 noexpandtab: */
diff --git a/src/bsp/lk/include/kernel/timer.h b/src/bsp/lk/include/kernel/timer.h
new file mode 100644
index 0000000..bd1d8af
--- /dev/null
+++ b/src/bsp/lk/include/kernel/timer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2008-2009 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_TIMER_H
+#define __KERNEL_TIMER_H
+
+#include <compiler.h>
+#include <list.h>
+#include <sys/types.h>
+
+__BEGIN_CDECLS;
+
+void timer_init(void);
+
+struct timer;
+typedef enum handler_return (*timer_callback)(struct timer *, lk_time_t now, void *arg);
+
+#define TIMER_MAGIC 'timr'
+
+typedef struct timer {
+ int magic;
+ struct list_node node;
+
+ lk_time_t scheduled_time;
+ lk_time_t periodic_time;
+
+ timer_callback callback;
+ void *arg;
+} timer_t;
+
+#define TIMER_INITIAL_VALUE(t) \
+{ \
+ .magic = TIMER_MAGIC, \
+ .node = LIST_INITIAL_CLEARED_VALUE, \
+ .scheduled_time = 0, \
+ .periodic_time = 0, \
+ .callback = NULL, \
+ .arg = NULL, \
+}
+
+/* Rules for Timers:
+ * - Timer callbacks occur from interrupt context
+ * - Timers may be programmed or canceled from interrupt or thread context
+ * - Timers may be canceled or reprogrammed from within their callback
+ * - Timers currently are dispatched from a 10ms periodic tick
+*/
+void timer_initialize(timer_t *);
+void timer_set_oneshot(timer_t *, lk_time_t delay, timer_callback, void *arg);
+void timer_set_periodic(timer_t *, lk_time_t period, timer_callback, void *arg);
+void timer_cancel(timer_t *);
+
+__END_CDECLS;
+
+#endif
+
diff --git a/src/bsp/lk/include/kernel/vm.h b/src/bsp/lk/include/kernel/vm.h
new file mode 100644
index 0000000..552e7e8
--- /dev/null
+++ b/src/bsp/lk/include/kernel/vm.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+/* some assembly #defines, need to match the structure below */
+#if IS_64BIT
+#define __MMU_INITIAL_MAPPING_PHYS_OFFSET 0
+#define __MMU_INITIAL_MAPPING_VIRT_OFFSET 8
+#define __MMU_INITIAL_MAPPING_SIZE_OFFSET 16
+#define __MMU_INITIAL_MAPPING_FLAGS_OFFSET 24
+#define __MMU_INITIAL_MAPPING_SIZE 40
+#else
+#define __MMU_INITIAL_MAPPING_PHYS_OFFSET 0
+#define __MMU_INITIAL_MAPPING_VIRT_OFFSET 4
+#define __MMU_INITIAL_MAPPING_SIZE_OFFSET 8
+#define __MMU_INITIAL_MAPPING_FLAGS_OFFSET 12
+#define __MMU_INITIAL_MAPPING_SIZE 20
+#endif
+
+/* flags for initial mapping struct */
+#define MMU_INITIAL_MAPPING_TEMPORARY (0x1)
+#define MMU_INITIAL_MAPPING_FLAG_UNCACHED (0x2)
+#define MMU_INITIAL_MAPPING_FLAG_DEVICE (0x4)
+#define MMU_INITIAL_MAPPING_FLAG_DYNAMIC (0x8) /* entry has to be patched up by platform_reset */
+
+#ifndef ASSEMBLY
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <compiler.h>
+#include <list.h>
+#include <stdlib.h>
+#include <arch.h>
+#include <arch/mmu.h>
+
+__BEGIN_CDECLS
+
+#define PAGE_ALIGN(x) ALIGN(x, PAGE_SIZE)
+#define IS_PAGE_ALIGNED(x) IS_ALIGNED(x, PAGE_SIZE)
+
+struct mmu_initial_mapping {
+ paddr_t phys;
+ vaddr_t virt;
+ size_t size;
+ unsigned int flags;
+ const char *name;
+};
+
+/* Assert that the assembly macros above match this struct. */
+STATIC_ASSERT(__offsetof(struct mmu_initial_mapping, phys) == __MMU_INITIAL_MAPPING_PHYS_OFFSET);
+STATIC_ASSERT(__offsetof(struct mmu_initial_mapping, virt) == __MMU_INITIAL_MAPPING_VIRT_OFFSET);
+STATIC_ASSERT(__offsetof(struct mmu_initial_mapping, size) == __MMU_INITIAL_MAPPING_SIZE_OFFSET);
+STATIC_ASSERT(__offsetof(struct mmu_initial_mapping, flags) == __MMU_INITIAL_MAPPING_FLAGS_OFFSET);
+STATIC_ASSERT(sizeof(struct mmu_initial_mapping) == __MMU_INITIAL_MAPPING_SIZE);
+
+/* Platform or target must fill out one of these to set up the initial memory map
+ * for kernel and enough IO space to boot.
+ */
+extern struct mmu_initial_mapping mmu_initial_mappings[];
+
+/* core per page structure */
+typedef struct vm_page {
+ struct list_node node;
+
+ uint flags : 8;
+ uint ref : 24;
+} vm_page_t;
+
+#define VM_PAGE_FLAG_NONFREE (0x1)
+
+/* kernel address space */
+#ifndef KERNEL_ASPACE_BASE
+#define KERNEL_ASPACE_BASE ((vaddr_t)0x80000000UL)
+#endif
+#ifndef KERNEL_ASPACE_SIZE
+#define KERNEL_ASPACE_SIZE ((vaddr_t)0x80000000UL)
+#endif
+
+STATIC_ASSERT(KERNEL_ASPACE_BASE + (KERNEL_ASPACE_SIZE - 1) > KERNEL_ASPACE_BASE);
+
+static inline bool is_kernel_address(vaddr_t va)
+{
+ return (va >= KERNEL_ASPACE_BASE && va <= (KERNEL_ASPACE_BASE + KERNEL_ASPACE_SIZE - 1));
+}
+
+/* user address space, defaults to below kernel space with a 16MB guard gap on either side */
+#ifndef USER_ASPACE_BASE
+#define USER_ASPACE_BASE ((vaddr_t)0x01000000UL)
+#endif
+#ifndef USER_ASPACE_SIZE
+#define USER_ASPACE_SIZE ((vaddr_t)KERNEL_ASPACE_BASE - USER_ASPACE_BASE - 0x01000000UL)
+#endif
+
+STATIC_ASSERT(USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1) > USER_ASPACE_BASE);
+
+static inline bool is_user_address(vaddr_t va)
+{
+ return (va >= USER_ASPACE_BASE && va <= (USER_ASPACE_BASE + USER_ASPACE_SIZE - 1));
+}
+
+
+/* physical allocator */
+typedef struct pmm_arena {
+ struct list_node node;
+ const char *name;
+
+ uint flags;
+ uint priority;
+
+ paddr_t base;
+ size_t size;
+
+ size_t free_count;
+
+ struct vm_page *page_array;
+ struct list_node free_list;
+} pmm_arena_t;
+
+#define PMM_ARENA_FLAG_KMAP (0x1) /* this arena is already mapped and useful for kallocs */
+
+/* Add a pre-filled memory arena to the physical allocator. */
+status_t pmm_add_arena(pmm_arena_t *arena);
+
+/* Allocate count pages of physical memory, adding to the tail of the passed list.
+ * The list must be initialized.
+ * Returns the number of pages allocated.
+ */
+size_t pmm_alloc_pages(uint count, struct list_node *list);
+
+/* Allocate a specific range of physical pages, adding to the tail of the passed list.
+ * The list must be initialized.
+ * Returns the number of pages allocated.
+ */
+size_t pmm_alloc_range(paddr_t address, uint count, struct list_node *list);
+
+/* Free a list of physical pages.
+ * Returns the number of pages freed.
+ */
+size_t pmm_free(struct list_node *list);
+
+/* Helper routine for the above. */
+size_t pmm_free_page(vm_page_t *page);
+
+/* Allocate a run of contiguous pages, aligned on log2 byte boundary (0-31)
+ * If the optional physical address pointer is passed, return the address.
+ * If the optional list is passed, append the allocate page structures to the tail of the list.
+ */
+size_t pmm_alloc_contiguous(uint count, uint8_t align_log2, paddr_t *pa, struct list_node *list);
+
+/* Allocate a run of pages out of the kernel area and return the pointer in kernel space.
+ * If the optional list is passed, append the allocate page structures to the tail of the list.
+ */
+void *pmm_alloc_kpages(uint count, struct list_node *list);
+
+/* Helper routine for pmm_alloc_kpages. */
+static inline void *pmm_alloc_kpage(void) { return pmm_alloc_kpages(1, NULL); }
+
+size_t pmm_free_kpages(void *ptr, uint count);
+
+/* physical to virtual */
+void *paddr_to_kvaddr(paddr_t pa);
+
+/* virtual to physical */
+paddr_t kvaddr_to_paddr(void *va);
+
+/* virtual allocator */
+typedef struct vmm_aspace {
+ struct list_node node;
+ char name[32];
+
+ uint flags;
+
+ vaddr_t base;
+ size_t size;
+
+ struct list_node region_list;
+} vmm_aspace_t;
+
+typedef struct vmm_region {
+ struct list_node node;
+ char name[32];
+
+ uint flags;
+ uint arch_mmu_flags;
+
+ vaddr_t base;
+ size_t size;
+
+ struct list_node page_list;
+} vmm_region_t;
+
+#define VMM_REGION_FLAG_RESERVED 0x1
+#define VMM_REGION_FLAG_PHYSICAL 0x2
+
+/* grab a handle to the kernel address space */
+extern vmm_aspace_t _kernel_aspace;
+static inline vmm_aspace_t *vmm_get_kernel_aspace(void) {
+ return &_kernel_aspace;
+}
+
+/* reserve a chunk of address space to prevent allocations from that space */
+status_t vmm_reserve_space(vmm_aspace_t *aspace, const char *name, size_t size, vaddr_t vaddr);
+
+/* allocate a region of virtual space that maps a physical piece of address space.
+ the physical pages that back this are not allocated from the pmm. */
+status_t vmm_alloc_physical_etc(vmm_aspace_t *aspace, const char *name, size_t size, void **ptr, uint8_t align_log2, paddr_t *paddr, uint paddr_count, uint vmm_flags, uint arch_mmu_flags);
+
+/* allocate a region of virtual space that maps a physical piece of address space.
+ the physical pages that back this are not allocated from the pmm. */
+status_t vmm_alloc_physical(vmm_aspace_t *aspace, const char *name, size_t size, void **ptr, uint8_t align_log2, paddr_t paddr, uint vmm_flags, uint arch_mmu_flags);
+
+/* allocate a region of memory backed by newly allocated contiguous physical memory */
+status_t vmm_alloc_contiguous(vmm_aspace_t *aspace, const char *name, size_t size, void **ptr, uint8_t align_log2, uint vmm_flags, uint arch_mmu_flags);
+
+/* allocate a region of memory backed by newly allocated physical memory */
+status_t vmm_alloc(vmm_aspace_t *aspace, const char *name, size_t size, void **ptr, uint8_t align_log2, uint vmm_flags, uint arch_mmu_flags);
+
+/* Unmap previously allocated region and free physical memory pages backing it (if any) */
+status_t vmm_free_region(vmm_aspace_t *aspace, vaddr_t va);
+
+ /* For the above region creation routines. Allocate virtual space at the passed in pointer. */
+#define VMM_FLAG_VALLOC_SPECIFIC 0x1
+
+/* allocate a new address space */
+status_t vmm_create_aspace(vmm_aspace_t **aspace, const char *name, uint flags);
+
+/* destroy everything in the address space */
+status_t vmm_free_aspace(vmm_aspace_t *aspace);
+
+#define VMM_FLAG_ASPACE_KERNEL 0x1
+
+__END_CDECLS
+
+#endif // !ASSEMBLY
diff --git a/src/bsp/lk/include/kernel/wait.h b/src/bsp/lk/include/kernel/wait.h
new file mode 100644
index 0000000..d0fa2f0
--- /dev/null
+++ b/src/bsp/lk/include/kernel/wait.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2008-2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __KERNEL_WAIT_H
+#define __KERNEL_WAIT_H
+
+#include <sys/types.h>
+#include <list.h>
+#include <compiler.h>
+#include <arch/defines.h>
+#include <arch/ops.h>
+#include <arch/thread.h>
+
+__BEGIN_CDECLS;
+
+/* wait queue stuff */
+#define WAIT_QUEUE_MAGIC 'wait'
+
+typedef struct wait_queue {
+ int magic;
+ struct list_node list;
+ int count;
+} wait_queue_t;
+
+#define WAIT_QUEUE_INITIAL_VALUE(q) \
+{ \
+ .magic = WAIT_QUEUE_MAGIC, \
+ .list = LIST_INITIAL_VALUE((q).list), \
+ .count = 0 \
+}
+
+/* wait queue primitive */
+/* NOTE: must be inside critical section when using these */
+void wait_queue_init(wait_queue_t *wait);
+
+/*
+ * release all the threads on this wait queue with a return code of ERR_OBJECT_DESTROYED.
+ * the caller must assure that no other threads are operating on the wait queue during or
+ * after the call.
+ */
+void wait_queue_destroy(wait_queue_t *, bool reschedule);
+
+/*
+ * block on a wait queue.
+ * return status is whatever the caller of wait_queue_wake_*() specifies.
+ * a timeout other than INFINITE_TIME will set abort after the specified time
+ * and return ERR_TIMED_OUT. a timeout of 0 will immediately return.
+ */
+status_t wait_queue_block(wait_queue_t *, lk_time_t timeout);
+
+/*
+ * release one or more threads from the wait queue.
+ * reschedule = should the system reschedule if any is released.
+ * wait_queue_error = what wait_queue_block() should return for the blocking thread.
+ */
+int wait_queue_wake_one(wait_queue_t *, bool reschedule, status_t wait_queue_error);
+int wait_queue_wake_all(wait_queue_t *, bool reschedule, status_t wait_queue_error);
+
+/*
+ * remove the thread from whatever wait queue it's in.
+ * return an error if the thread is not currently blocked (or is the current thread)
+ */
+status_t thread_unblock_from_wait_queue(struct thread *t, status_t wait_queue_error);
+
+__END_CDECLS;
+
+#endif
+