From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Leonard Subject: [PATCH ARM v5 17/20] mini-os: headers for ARM Date: Thu, 26 Jun 2014 12:28:34 +0100 Message-ID: <1403782117-15125-18-git-send-email-talex5@gmail.com> References: <1403782117-15125-1-git-send-email-talex5@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1X07rh-0004bR-FD for xen-devel@lists.xenproject.org; Thu, 26 Jun 2014 11:29:17 +0000 Received: by mail-we0-f169.google.com with SMTP id t60so3515251wes.28 for ; Thu, 26 Jun 2014 04:29:14 -0700 (PDT) In-Reply-To: <1403782117-15125-1-git-send-email-talex5@gmail.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xenproject.org Cc: Thomas Leonard , Dave.Scott@eu.citrix.com, anil@recoil.org, stefano.stabellini@eu.citrix.com, samuel.thibault@ens-lyon.org List-Id: xen-devel@lists.xenproject.org From: Karim Raslan Adds header files for future ARM support. Signed-off-by: Karim Allah Ahmed [talex5@gmail.com: split into multiple patches] [talex5@gmail.com: include hypervisor.h from os.h, as on x86] [talex5@gmail.com: implemented bitops for ARM] [talex5@gmail.com: added arch_endian.h for ARM] [talex5@gmail.com: removed unused hypercalls and inlines] [talex5@gmail.com: renamed hypercall-arm32 to just hypercall-arm] [talex5@gmail.com: moved GIC driver to arm directory] [talex5@gmail.com: added HYPERVISOR_xsm_op] [talex5@gmail.com: fixes suggested by Julien Grall: - Removed old x86 comment from arm/arch_spinlock.h. - Removed unimplemented _raw_spin_lock_flags. - Renamed __cli/__sti to local_irq_disable/local_irq_enable. - Cleaned up interrupt macros. - Avoid disabling the Asynchronous Abort exception. - Added memory clobber to barriers. - Enable barriers on __aarch64__ too. - Use compiler.h for likely/unlikely macros. - Replaced dmb with slower but safer dsb for now.] [talex5@gmail.com: made image relocatable] [talex5@gmail.com: added mfn_to_pfn and pfn_to_mfn] Signed-off-by: Thomas Leonard --- 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 | 35 ++++ 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 | 215 +++++++++++++++++++++++ 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, 450 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 + +#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..a19cb39 --- /dev/null +++ b/extras/mini-os/include/arm/arch_mm.h @@ -0,0 +1,35 @@ +#ifndef _ARCH_MM_H_ +#define _ARCH_MM_H_ + +extern char _text, _etext, _erodata, _edata, _end, __bss_start; +extern int stack[]; +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) ((unsigned long)(x)+physical_address_offset) +#define to_virt(x) ((void *)((unsigned long)(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 + * Jun Nakajima + * + * 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 +#include +#include +#include + +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..bde8796 --- /dev/null +++ b/extras/mini-os/include/arm/os.h @@ -0,0 +1,215 @@ +#ifndef _OS_H_ +#define _OS_H_ + +#ifndef __ASSEMBLY__ + +#include +#include +#include +#include + +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){} + +#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 #elif defined(__x86_64__) #include +#elif defined(__arm__) || defined(__aarch64__) +#include #else #error "Unsupported architecture" #endif diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h index a94cd6d..644c7de 100644 --- a/extras/mini-os/include/mm.h +++ b/extras/mini-os/include/mm.h @@ -29,6 +29,8 @@ #include #elif defined(__x86_64__) #include +#elif defined(__arm__) || defined(__aarch64__) +#include #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 #include #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.0