genode/dde_linux/src/lib/lxip/lxc_emul.c

394 lines
7.5 KiB
C

/**
* \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 <linux/netdevice.h>
#include <net/ip_fib.h>
#include <uapi/linux/rtnetlink.h>
#include <dde_kit/memory.h>
#include <net/route.h>
#include <net/tcp.h>
/********************
** 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;
}