/** * \brief Linux emulation code * \author Sebastian Sumpf * \date 2013-08-30 */ /* * Copyright (C) 2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #include #include #include #include #include #include /******************** ** linux/slab.h ** ********************/ struct kmem_cache { const char *name; /* cache name */ unsigned size; /* object size */ }; struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long falgs, void (*ctor)(void *)) { dde_kit_log(DEBUG_SLAB, "\"%s\" obj_size=%zd", name, size); struct kmem_cache *cache; if (!name) { pr_info("kmem_cache name required\n"); return 0; } cache = (struct kmem_cache *)kmalloc(sizeof(*cache), 0); if (!cache) { pr_crit("No memory for slab cache\n"); return 0; } cache->name = name; cache->size = size; return cache; } void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t flags, int node) { dde_kit_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%zd", cache->name,cache->size); return kmalloc(cache->size, 0); } void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags) { dde_kit_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%zd", cache->name,cache->size); return kmalloc(cache->size, 0); } void kmem_cache_free(struct kmem_cache *cache, void *objp) { dde_kit_log(DEBUG_SLAB, "\"%s\" (%p)", cache->name, objp); kfree(objp); } void *alloc_large_system_hash(const char *tablename, unsigned long bucketsize, unsigned long numentries, int scale, int flags, unsigned int *_hash_shift, unsigned int *_hash_mask, unsigned long low_limit, unsigned long high_limit) { unsigned long elements = numentries ? numentries : high_limit; unsigned long nlog2 = ilog2(elements); nlog2 <<= (1 << nlog2) < elements ? 1 : 0; void *table = dde_kit_simple_malloc(elements * bucketsize); if (_hash_mask) *_hash_mask = (1 << nlog2) - 1; if (_hash_shift) *_hash_shift = nlog2; return table; } /******************** ** linux/bitmap.h ** ********************/ void bitmap_fill(unsigned long *dst, int nbits) { int count = nbits / (8 * sizeof (long)); int i; memset(dst, 0xff, count * sizeof(long)); dst += count; count = nbits % (8 * sizeof(long)); for (i = 0; i < count; i++) *dst |= (1 << i); } void bitmap_zero(unsigned long *dst, int nbits) { int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); memset(dst, 0, len); } /***************** ** linux/gfp.h ** *****************/ unsigned long get_zeroed_page(gfp_t gfp_mask) { return (unsigned long)kzalloc(PAGE_SIZE, 0); } /******************** ** linux/percpu.h ** ********************/ void *__alloc_percpu(size_t size, size_t align) { return kmalloc(size, 0); } /****************** ** linux/hash.h ** ******************/ u32 hash_32(u32 val, unsigned int bits) { enum { GOLDEN_RATIO_PRIME_32 = 0x9e370001UL }; u32 hash = val * GOLDEN_RATIO_PRIME_32; hash = hash >> (32 - bits); return hash; } /****************** ** linux/dcache ** ******************/ unsigned int full_name_hash(const unsigned char *name, unsigned int len) { unsigned hash = 0, i; for (i = 0; i < len; i++) hash += name[i]; return hash; } /****************************** * net/core/net/namespace.h ** ******************************/ int register_pernet_subsys(struct pernet_operations *ops) { if (ops->init) ops->init(&init_net); return 0; } int register_pernet_device(struct pernet_operations *ops) { return register_pernet_subsys(ops); } /************************* ** net/net_namespace.h ** *************************/ int rt_genid(struct net *net) { int ret = atomic_read(&net->rt_genid); return -1; } /********************** ** linx/rtnetlink.h ** **********************/ struct netdev_queue *dev_ingress_queue(struct net_device *dev) { return dev->ingress_queue; } /**************** ** linux/ip.h ** ****************/ struct iphdr *ip_hdr(const struct sk_buff *skb) { return (struct iphdr *)skb_network_header(skb); } /*********************** ** linux/netdevice.h ** ***********************/ struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) { return netdev_get_tx_queue(dev, 0); } /******************************* ** asm-generic/bitops/find.h ** *******************************/ unsigned long find_first_zero_bit(unsigned long const *addr, unsigned long size) { unsigned long i, j; for (i = 0; i < (size / BITS_PER_LONG); i++) if (addr[i] != ~0UL) break; if (i == size) return size; for (j = 0; j < BITS_PER_LONG; j++) if ((~addr[i]) & (1 << j)) break; return (i * BITS_PER_LONG) + j; } /**************************** ** asm-generic/getorder.h ** ****************************/ int get_order(unsigned long size) { int order; size--; size >>= PAGE_SHIFT; order = __builtin_ctzl(size); return order; } /********************* ** linux/jiffies.h ** *********************/ long time_after_eq(long a, long b) { return (a - b) >= 0; } long time_after(long a, long b) { return (b - a) < 0; } /********************* ** linux/utsname.h ** *********************/ struct uts_name init_uts_ns; struct new_utsname *init_utsname(void) { return &init_uts_ns.name; } struct new_utsname *utsname(void) { return init_utsname(); } /********************** ** linux/notifier.h ** **********************/ int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *n) { struct notifier_block *nl = nh->head; struct notifier_block *pr = 0; while (nl) { if (n->priority > nl->priority) break; pr = nl; nl = nl->next; } n->next = nl; if (pr) pr->next = n; else nh->head = n; return 0; } int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v) { int ret = NOTIFY_DONE; struct notifier_block *nb = nh->head; while (nb) { ret = nb->notifier_call(nb, val, v); if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) break; nb = nb->next; } return ret; } int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *n) { return raw_notifier_chain_register((struct raw_notifier_head *)nh, n); } int blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v) { return raw_notifier_call_chain((struct raw_notifier_head *)nh, val, v); } /**************************** ** asm-generic/checksum.h ** ****************************/ __sum16 csum_fold(__wsum csum) { u32 sum = (u32)csum; sum = (sum & 0xffff) + (sum >> 16); sum = (sum & 0xffff) + (sum >> 16); return (__sum16)~sum; } /******************* ** net/checksum.h ** ********************/ __wsum csum_add(__wsum csum, __wsum addend) { u32 res = (u32)csum; res += (u32)addend; return (__wsum)(res + (res < (u32)addend)); } __wsum csum_block_add(__wsum csum, __wsum csum2, int offset) { u32 sum = (u32)csum2; if (offset&1) sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF); return csum_add(csum, (__wsum)sum); } /** * Misc */ void set_sock_wait(struct socket *sock, unsigned long ptr) { sock->sk->sk_wq = (struct socket_wq *)ptr; }