[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH ARM v6 04/14] mini-os: headers for ARM
From: Karim Raslan <karim.allah.ahmed@xxxxxxxxx> Adds header files for future ARM support. Based on work by Karim Allah Ahmed. Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@xxxxxxxxx> Signed-off-by: Thomas Leonard <talex5@xxxxxxxxx> --- Since v5: Define BUG to cause an undefined instruction fault. This will let us dump the registers. Renamed stack to _boot_stack for clarity. Include kernel.h from arm/os.h. This is for consistency with x86/os.h and is needed to compile with lwIP. Added paddr_t type to represent physical addresses (requested by Julien Grall). --- extras/mini-os/include/arm/arch_endian.h | 7 + extras/mini-os/include/arm/arch_limits.h | 9 + extras/mini-os/include/arm/arch_mm.h | 38 ++++ extras/mini-os/include/arm/arch_sched.h | 19 ++ extras/mini-os/include/arm/arch_spinlock.h | 36 ++++ extras/mini-os/include/arm/arm32/arch_wordsize.h | 1 + extras/mini-os/include/arm/gic.h | 1 + extras/mini-os/include/arm/hypercall-arm.h | 98 ++++++++++ extras/mini-os/include/arm/os.h | 216 +++++++++++++++++++++++ extras/mini-os/include/arm/traps.h | 20 +++ extras/mini-os/include/hypervisor.h | 2 + extras/mini-os/include/mm.h | 2 + extras/mini-os/include/types.h | 10 +- 13 files changed, 454 insertions(+), 5 deletions(-) create mode 100644 extras/mini-os/include/arm/arch_endian.h create mode 100644 extras/mini-os/include/arm/arch_limits.h create mode 100644 extras/mini-os/include/arm/arch_mm.h create mode 100644 extras/mini-os/include/arm/arch_sched.h create mode 100755 extras/mini-os/include/arm/arch_spinlock.h create mode 100644 extras/mini-os/include/arm/arm32/arch_wordsize.h create mode 100644 extras/mini-os/include/arm/gic.h create mode 100644 extras/mini-os/include/arm/hypercall-arm.h create mode 100644 extras/mini-os/include/arm/os.h create mode 100644 extras/mini-os/include/arm/traps.h diff --git a/extras/mini-os/include/arm/arch_endian.h b/extras/mini-os/include/arm/arch_endian.h new file mode 100644 index 0000000..0771683 --- /dev/null +++ b/extras/mini-os/include/arm/arch_endian.h @@ -0,0 +1,7 @@ +#ifndef ARCH_ENDIAN_H +#error "Do not include arch_endian by itself, include endian.h" +#else + +#define __BYTE_ORDER __LITTLE_ENDIAN + +#endif diff --git a/extras/mini-os/include/arm/arch_limits.h b/extras/mini-os/include/arm/arch_limits.h new file mode 100644 index 0000000..bae99e1 --- /dev/null +++ b/extras/mini-os/include/arm/arch_limits.h @@ -0,0 +1,9 @@ +#ifndef __ARCH_LIMITS_H__ +#define __ARCH_LIMITS_H__ + +#include <mm.h> + +#define __STACK_SIZE_PAGE_ORDER 2 +#define __STACK_SIZE (4 * PAGE_SIZE) + +#endif diff --git a/extras/mini-os/include/arm/arch_mm.h b/extras/mini-os/include/arm/arch_mm.h new file mode 100644 index 0000000..8e10e4b --- /dev/null +++ b/extras/mini-os/include/arm/arch_mm.h @@ -0,0 +1,38 @@ +#ifndef _ARCH_MM_H_ +#define _ARCH_MM_H_ + +typedef unsigned long paddr_t; + +extern char _text, _etext, _erodata, _edata, _end, __bss_start; +extern int _boot_stack[]; +extern int _boot_stack_end[]; +extern int physical_address_offset; /* Add this to a virtual address to get the physical address (wraps) */ + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#define L1_PAGETABLE_SHIFT 12 + +#define to_phys(x) ((paddr_t)(x)+physical_address_offset) +#define to_virt(x) ((void *)((paddr_t)(x)-physical_address_offset)) + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT) +#define PFN_DOWN(x) ((x) >> L1_PAGETABLE_SHIFT) +#define PFN_PHYS(x) ((uint64_t)(x) << L1_PAGETABLE_SHIFT) +#define PHYS_PFN(x) ((x) >> L1_PAGETABLE_SHIFT) + +#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt))) +#define virt_to_mfn(_virt) (PFN_DOWN(to_phys(_virt))) +#define mfn_to_virt(_mfn) (to_virt(PFN_PHYS(_mfn))) +#define pfn_to_virt(_pfn) (to_virt(PFN_PHYS(_pfn))) + +#define mfn_to_pfn(x) (x) +#define pfn_to_mfn(x) (x) + +#define virtual_to_mfn(_virt) virt_to_mfn(_virt) + +// FIXME +#define map_frames(f, n) (NULL) + +#endif diff --git a/extras/mini-os/include/arm/arch_sched.h b/extras/mini-os/include/arm/arch_sched.h new file mode 100644 index 0000000..de3ac02 --- /dev/null +++ b/extras/mini-os/include/arm/arch_sched.h @@ -0,0 +1,19 @@ +#ifndef __ARCH_SCHED_H__ +#define __ARCH_SCHED_H__ + +#include "arch_limits.h" + +static inline struct thread* get_current(void) +{ + struct thread **current; + unsigned long sp; + __asm__ __volatile__ ("mov %0, sp":"=r"(sp)); + current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1)); + return *current; +} + +void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx); + +#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp) + +#endif /* __ARCH_SCHED_H__ */ diff --git a/extras/mini-os/include/arm/arch_spinlock.h b/extras/mini-os/include/arm/arch_spinlock.h new file mode 100755 index 0000000..dccb9fc --- /dev/null +++ b/extras/mini-os/include/arm/arch_spinlock.h @@ -0,0 +1,36 @@ +#ifndef __ARCH_ASM_SPINLOCK_H +#define __ARCH_ASM_SPINLOCK_H + +#include "os.h" + +#define ARCH_SPIN_LOCK_UNLOCKED { 1 } + +/* + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * We make no fairness assumptions. They have a cost. + */ + +#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0) +#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) + +static inline void _raw_spin_unlock(spinlock_t *lock) +{ + xchg(&lock->slock, 1); +} + +static inline int _raw_spin_trylock(spinlock_t *lock) +{ + return xchg(&lock->slock, 0) != 0 ? 1 : 0; +} + +static inline void _raw_spin_lock(spinlock_t *lock) +{ + volatile int was_locked; + do { + was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0; + } while(was_locked); +} + +#endif diff --git a/extras/mini-os/include/arm/arm32/arch_wordsize.h b/extras/mini-os/include/arm/arm32/arch_wordsize.h new file mode 100644 index 0000000..b47eee9 --- /dev/null +++ b/extras/mini-os/include/arm/arm32/arch_wordsize.h @@ -0,0 +1 @@ +#define __WORDSIZE 32 diff --git a/extras/mini-os/include/arm/gic.h b/extras/mini-os/include/arm/gic.h new file mode 100644 index 0000000..cead2e5 --- /dev/null +++ b/extras/mini-os/include/arm/gic.h @@ -0,0 +1 @@ +void gic_init(void); diff --git a/extras/mini-os/include/arm/hypercall-arm.h b/extras/mini-os/include/arm/hypercall-arm.h new file mode 100644 index 0000000..6d862ff --- /dev/null +++ b/extras/mini-os/include/arm/hypercall-arm.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * hypercall-arm.h + * + * Copied from XenLinux. + * + * Copyright (c) 2002-2004, K A Fraser + * + * 64-bit updates: + * Benjamin Liu <benjamin.liu@xxxxxxxxx> + * Jun Nakajima <jun.nakajima@xxxxxxxxx> + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (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 __HYPERCALL_ARM_H__ +#define __HYPERCALL_ARM_H__ + +#include <xen/xen.h> +#include <xen/sched.h> +#include <xen/xsm/flask_op.h> +#include <mini-os/mm.h> + +int +HYPERVISOR_sched_op( + int cmd, void *arg); + +static inline int +HYPERVISOR_shutdown( + unsigned int reason) +{ + struct sched_shutdown shutdown = { .reason = reason }; + HYPERVISOR_sched_op(SCHEDOP_shutdown, &shutdown); +} + +int +HYPERVISOR_memory_op( + unsigned int cmd, void *arg); + +int +HYPERVISOR_event_channel_op( + int cmd, void *op); + +int +HYPERVISOR_xen_version( + int cmd, void *arg); + +int +HYPERVISOR_console_io( + int cmd, int count, char *str); + +int +HYPERVISOR_physdev_op( + void *physdev_op); + +int +HYPERVISOR_grant_table_op( + unsigned int cmd, void *uop, unsigned int count); + +int +HYPERVISOR_vcpu_op( + int cmd, int vcpuid, void *extra_args); + +int +HYPERVISOR_sysctl( + unsigned long op); + +int +HYPERVISOR_domctl( + unsigned long op); + +int +HYPERVISOR_hvm_op( + unsigned long op, void *arg); + +int +HYPERVISOR_xsm_op( + struct xen_flask_op *); + +#endif /* __HYPERCALL_ARM_H__ */ diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h new file mode 100644 index 0000000..6a1cc37 --- /dev/null +++ b/extras/mini-os/include/arm/os.h @@ -0,0 +1,216 @@ +#ifndef _OS_H_ +#define _OS_H_ + +#ifndef __ASSEMBLY__ + +#include <mini-os/hypervisor.h> +#include <mini-os/types.h> +#include <mini-os/compiler.h> +#include <mini-os/kernel.h> +#include <xen/xen.h> + +void arch_fini(void); +void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign); + +extern void *device_tree; + +#define BUG() while(1){asm volatile (".word 0xe7f000f0\n");} /* Undefined instruction; will call our fault handler. */ + +#define smp_processor_id() 0 + +#define barrier() __asm__ __volatile__("": : :"memory") + +extern shared_info_t *HYPERVISOR_shared_info; + +// disable interrupts +static inline void local_irq_disable(void) { + __asm__ __volatile__("cpsid i":::"memory"); +} + +// enable interrupts +static inline void local_irq_enable(void) { + __asm__ __volatile__("cpsie i":::"memory"); +} + +#define local_irq_save(x) { \ + __asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory"); \ +} + +#define local_irq_restore(x) { \ + __asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory"); \ +} + +#define local_save_flags(x) { \ + __asm__ __volatile__("mrs %0, cpsr":"=r"(x)::"memory"); \ +} + +static inline int irqs_disabled(void) { + int x; + local_save_flags(x); + return x & 0x80; +} + +/* We probably only need "dmb" here, but we'll start by being paranoid. */ +#define mb() __asm__("dsb":::"memory"); +#define rmb() __asm__("dsb":::"memory"); +#define wmb() __asm__("dsb":::"memory"); + +/************************** arm *******************************/ +#ifdef __INSIDE_MINIOS__ +#if defined (__arm__) +#define xchg(ptr,v) __atomic_exchange_n(ptr, v, __ATOMIC_SEQ_CST) + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + * + * This operation is atomic. + * If you need a memory barrier, use synch_test_and_clear_bit instead. + */ +static __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ + uint8_t *byte = ((uint8_t *)addr) + (nr >> 3); + uint8_t bit = 1 << (nr & 7); + uint8_t orig; + + orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_RELAXED); + + return (orig & bit) != 0; +} + +/** + * Atomically set a bit and return the old value. + * Similar to test_and_clear_bit. + */ +static __inline__ int test_and_set_bit(int nr, volatile void *base) +{ + uint8_t *byte = ((uint8_t *)base) + (nr >> 3); + uint8_t bit = 1 << (nr & 7); + uint8_t orig; + + orig = __atomic_fetch_or(byte, bit, __ATOMIC_RELAXED); + + return (orig & bit) != 0; +} + +/** + * Test whether a bit is set. */ +static __inline__ int test_bit(int nr, const volatile unsigned long *addr) +{ + const uint8_t *ptr = (const uint8_t *) addr; + return ((1 << (nr & 7)) & (ptr[nr >> 3])) != 0; +} + +/** + * Atomically set a bit in memory (like test_and_set_bit but discards result). + */ +static __inline__ void set_bit(int nr, volatile unsigned long *addr) +{ + test_and_set_bit(nr, addr); +} + +/** + * Atomically clear a bit in memory (like test_and_clear_bit but discards result). + */ +static __inline__ void clear_bit(int nr, volatile unsigned long *addr) +{ + test_and_clear_bit(nr, addr); +} + +/** + * __ffs - find first (lowest) set bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static __inline__ unsigned long __ffs(unsigned long word) +{ + int clz; + + /* xxxxx10000 = word + * xxxxx01111 = word - 1 + * 0000011111 = word ^ (word - 1) + * 4 = 31 - clz(word ^ (word - 1)) + */ + + __asm__ ( + "sub r0, %[word], #1\n" + "eor r0, r0, %[word]\n" + "clz %[clz], r0\n": + /* Outputs: */ + [clz] "=r"(clz): + /* Inputs: */ + [word] "r"(word): + /* Clobbers: */ + "r0"); + + return 31 - clz; +} + +#else /* ifdef __arm__ */ +#error "Unsupported architecture" +#endif +#endif /* ifdef __INSIDE_MINIOS */ + +/********************* common arm32 and arm64 ****************************/ + +/* If *ptr == old, then store new there (and return new). + * Otherwise, return the old value. + * Atomic. */ +#define synch_cmpxchg(ptr, old, new) \ +({ __typeof__(*ptr) stored = old; \ + __atomic_compare_exchange_n(ptr, &stored, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? new : old; \ +}) + +/* As test_and_clear_bit, but using __ATOMIC_SEQ_CST */ +static __inline__ int synch_test_and_clear_bit(int nr, volatile void *addr) +{ + uint8_t *byte = ((uint8_t *)addr) + (nr >> 3); + uint8_t bit = 1 << (nr & 7); + uint8_t orig; + + orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_SEQ_CST); + + return (orig & bit) != 0; +} + +/* As test_and_set_bit, but using __ATOMIC_SEQ_CST */ +static __inline__ int synch_test_and_set_bit(int nr, volatile void *base) +{ + uint8_t *byte = ((uint8_t *)base) + (nr >> 3); + uint8_t bit = 1 << (nr & 7); + uint8_t orig; + + orig = __atomic_fetch_or(byte, bit, __ATOMIC_SEQ_CST); + + return (orig & bit) != 0; +} + +/* As set_bit, but using __ATOMIC_SEQ_CST */ +static __inline__ void synch_set_bit(int nr, volatile void *addr) +{ + synch_test_and_set_bit(nr, addr); +} + +/* As clear_bit, but using __ATOMIC_SEQ_CST */ +static __inline__ void synch_clear_bit(int nr, volatile void *addr) +{ + synch_test_and_clear_bit(nr, addr); +} + +/* As test_bit, but with a following memory barrier. */ +static __inline__ int synch_test_bit(int nr, volatile void *addr) +{ + int result; + result = test_bit(nr, addr); + barrier(); + return result; +} + +#endif /* not assembly */ + +#endif diff --git a/extras/mini-os/include/arm/traps.h b/extras/mini-os/include/arm/traps.h new file mode 100644 index 0000000..704df22 --- /dev/null +++ b/extras/mini-os/include/arm/traps.h @@ -0,0 +1,20 @@ +#ifndef _TRAPS_H_ +#define _TRAPS_H_ + +struct pt_regs { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; +}; + +#endif diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h index a62cb78..21b3566 100644 --- a/extras/mini-os/include/hypervisor.h +++ b/extras/mini-os/include/hypervisor.h @@ -18,6 +18,8 @@ #include <hypercall-x86_32.h> #elif defined(__x86_64__) #include <hypercall-x86_64.h> +#elif defined(__arm__) || defined(__aarch64__) +#include <hypercall-arm.h> #else #error "Unsupported architecture" #endif diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h index a177251..f57d8ab 100644 --- a/extras/mini-os/include/mm.h +++ b/extras/mini-os/include/mm.h @@ -29,6 +29,8 @@ #include <xen/arch-x86_32.h> #elif defined(__x86_64__) #include <xen/arch-x86_64.h> +#elif defined(__arm__) || defined(__aarch64__) +#include <xen/arch-arm.h> #else #error "Unsupported architecture" #endif diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h index 93356fe..be9f1d3 100644 --- a/extras/mini-os/include/types.h +++ b/extras/mini-os/include/types.h @@ -27,7 +27,7 @@ typedef unsigned char u_char; typedef unsigned int u_int; typedef unsigned long u_long; #endif -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) typedef long long quad_t; typedef unsigned long long u_quad_t; #elif defined(__x86_64__) @@ -39,10 +39,10 @@ typedef unsigned long u_quad_t; #include <limits.h> #include <stdint.h> #else -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) typedef unsigned int uintptr_t; typedef int intptr_t; -#elif defined(__x86_64__) +#elif defined(__x86_64__) || defined(__aarch64__) typedef unsigned long uintptr_t; typedef long intptr_t; #endif /* __i386__ || __x86_64__ */ @@ -52,10 +52,10 @@ typedef unsigned short uint16_t; typedef signed short int16_t; typedef unsigned int uint32_t; typedef signed int int32_t; -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) typedef signed long long int64_t; typedef unsigned long long uint64_t; -#elif defined(__x86_64__) +#elif defined(__x86_64__) || defined(__aarch64__) typedef signed long int64_t; typedef unsigned long uint64_t; #endif -- 2.0.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |