mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.1030 (40e1c7ecu4wKzzQZ32aoNCXtRj9smw)
Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk into scramble.cl.cam.ac.uk:/local/scratch/kaf24/hp.bk
This commit is contained in:
commit
1c94e4bb76
15 files changed
+709
-609
No files matched your search
@@ -454,18 +454,20 @@
|
||||
3ddb79c3Hgbb2g8CyWLMCK-6_ZVQSQ xen/include/asm-x86/smp.h
|
||||
3ddb79c3jn8ALV_S9W5aeTYUQRKBpg xen/include/asm-x86/smpboot.h
|
||||
3ddb79c3NiyQE2vQnyGiaBnNjBO1rA xen/include/asm-x86/spinlock.h
|
||||
3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/string.h
|
||||
40e1966akOHWvvunCED7x3HPv35QvQ xen/include/asm-x86/string.h
|
||||
3ddb79c3ezddh34MdelJpa5tNR00Dw xen/include/asm-x86/system.h
|
||||
3ddb79c4HugMq7IYGxcQKFBpKwKhzA xen/include/asm-x86/types.h
|
||||
40cf1596saFaHD5DC5zvrSn7CDCWGQ xen/include/asm-x86/uaccess.h
|
||||
3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/include/asm-x86/x86_32/current.h
|
||||
3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/ptrace.h
|
||||
3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h
|
||||
3ddb79c3M2n1ROZH6xk3HbyN4CPDqg xen/include/asm-x86/x86_32/uaccess.h
|
||||
404f1b9ceJeGVaPNIENm2FkK0AgEOQ xen/include/asm-x86/x86_64/current.h
|
||||
404f1b9fl6AQ_a-T1TDK3fuwTPXmHw xen/include/asm-x86/x86_64/desc.h
|
||||
404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86/x86_64/ldt.h
|
||||
404f1bb1LSCqrMDSfRAti5NdMQPJBQ xen/include/asm-x86/x86_64/page.h
|
||||
404f1bb86rAXB3aLS1vYdcqpJiEcyg xen/include/asm-x86/x86_64/ptrace.h
|
||||
40e1966azOJZfNI6Ilthe6Q-T3Hewg xen/include/asm-x86/x86_64/string.h
|
||||
404f1bc4tWkB9Qr8RkKtZGW5eMQzhw xen/include/asm-x86/x86_64/uaccess.h
|
||||
400304fcmRQmDdFYEzDh0wcBba9alg xen/include/hypervisor-ifs/COPYING
|
||||
404f1bc68SXxmv0zQpXBWGrCzSyp8w xen/include/hypervisor-ifs/arch-x86_32.h
|
||||
|
||||
@@ -28,12 +28,6 @@ static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
|
||||
static void net_rx_action(unsigned long unused);
|
||||
static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
|
||||
|
||||
typedef struct {
|
||||
u16 id;
|
||||
unsigned long old_mach_ptr;
|
||||
unsigned long new_mach_pfn;
|
||||
netif_t *netif;
|
||||
} rx_info_t;
|
||||
static struct sk_buff_head rx_queue;
|
||||
static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2];
|
||||
static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE*3];
|
||||
@@ -48,8 +42,10 @@ static unsigned long mmap_vstart;
|
||||
|
||||
#define PKT_PROT_LEN (ETH_HLEN + 20)
|
||||
|
||||
static u16 pending_id[MAX_PENDING_REQS];
|
||||
static netif_t *pending_netif[MAX_PENDING_REQS];
|
||||
static struct {
|
||||
netif_tx_request_t req;
|
||||
netif_t *netif;
|
||||
} pending_tx_info[MAX_PENDING_REQS];
|
||||
static u16 pending_ring[MAX_PENDING_REQS];
|
||||
typedef unsigned int PEND_RING_IDX;
|
||||
#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
|
||||
@@ -61,11 +57,6 @@ static u16 dealloc_ring[MAX_PENDING_REQS];
|
||||
static spinlock_t dealloc_lock = SPIN_LOCK_UNLOCKED;
|
||||
static PEND_RING_IDX dealloc_prod, dealloc_cons;
|
||||
|
||||
typedef struct {
|
||||
u16 idx;
|
||||
netif_tx_request_t req;
|
||||
netif_t *netif;
|
||||
} tx_info_t;
|
||||
static struct sk_buff_head tx_queue;
|
||||
static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
|
||||
|
||||
@@ -127,6 +118,8 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
netif_t *netif = (netif_t *)dev->priv;
|
||||
|
||||
ASSERT(skb->dev == dev);
|
||||
|
||||
/* Drop the packet if the target domain has no receive buffers. */
|
||||
if ( (netif->rx_req_cons == netif->rx->req_prod) ||
|
||||
((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) )
|
||||
@@ -152,15 +145,14 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
skb_reserve(nskb, hlen);
|
||||
__skb_put(nskb, skb->len);
|
||||
(void)skb_copy_bits(skb, -hlen, nskb->head, hlen + skb->len);
|
||||
nskb->dev = skb->dev;
|
||||
dev_kfree_skb(skb);
|
||||
skb = nskb;
|
||||
}
|
||||
|
||||
((rx_info_t *)&skb->cb[0])->id =
|
||||
netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_req_cons++)].req.id;
|
||||
((rx_info_t *)&skb->cb[0])->netif = netif;
|
||||
|
||||
__skb_queue_tail(&rx_queue, skb);
|
||||
netif->rx_req_cons++;
|
||||
|
||||
skb_queue_tail(&rx_queue, skb);
|
||||
tasklet_schedule(&net_rx_tasklet);
|
||||
|
||||
return 0;
|
||||
@@ -195,7 +187,7 @@ static void net_rx_action(unsigned long unused)
|
||||
netif_t *netif;
|
||||
s8 status;
|
||||
u16 size, id, evtchn;
|
||||
mmu_update_t *mmu = rx_mmu;
|
||||
mmu_update_t *mmu;
|
||||
multicall_entry_t *mcl;
|
||||
unsigned long vdata, mdata, new_mfn;
|
||||
struct sk_buff_head rxq;
|
||||
@@ -206,9 +198,10 @@ static void net_rx_action(unsigned long unused)
|
||||
skb_queue_head_init(&rxq);
|
||||
|
||||
mcl = rx_mcl;
|
||||
while ( (skb = __skb_dequeue(&rx_queue)) != NULL )
|
||||
mmu = rx_mmu;
|
||||
while ( (skb = skb_dequeue(&rx_queue)) != NULL )
|
||||
{
|
||||
netif = ((rx_info_t *)&skb->cb[0])->netif;
|
||||
netif = (netif_t *)skb->dev->priv;
|
||||
vdata = (unsigned long)skb->data;
|
||||
mdata = virt_to_machine(vdata);
|
||||
new_mfn = get_new_mfn();
|
||||
@@ -231,11 +224,9 @@ static void net_rx_action(unsigned long unused)
|
||||
mcl[1].args[1] = 3;
|
||||
mcl[1].args[2] = 0;
|
||||
|
||||
mmu += 3;
|
||||
mcl += 2;
|
||||
mmu += 3;
|
||||
|
||||
((rx_info_t *)&skb->cb[0])->old_mach_ptr = mdata;
|
||||
((rx_info_t *)&skb->cb[0])->new_mach_pfn = new_mfn;
|
||||
__skb_queue_tail(&rxq, skb);
|
||||
|
||||
/* Filled the batch queue? */
|
||||
@@ -250,14 +241,17 @@ static void net_rx_action(unsigned long unused)
|
||||
(void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
|
||||
|
||||
mcl = rx_mcl;
|
||||
mmu = rx_mmu;
|
||||
while ( (skb = __skb_dequeue(&rxq)) != NULL )
|
||||
{
|
||||
netif = ((rx_info_t *)&skb->cb[0])->netif;
|
||||
netif = (netif_t *)skb->dev->priv;
|
||||
size = skb->tail - skb->data;
|
||||
id = ((rx_info_t *)&skb->cb[0])->id;
|
||||
new_mfn = ((rx_info_t *)&skb->cb[0])->new_mach_pfn;
|
||||
mdata = ((rx_info_t *)&skb->cb[0])->old_mach_ptr;
|
||||
|
||||
/* Rederive the machine addresses. */
|
||||
new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
|
||||
mdata = ((mmu[2].ptr & PAGE_MASK) |
|
||||
((unsigned long)skb->data & ~PAGE_MASK));
|
||||
|
||||
/* Check the reassignment error code. */
|
||||
if ( unlikely(mcl[1].args[5] != 0) )
|
||||
{
|
||||
@@ -285,6 +279,7 @@ static void net_rx_action(unsigned long unused)
|
||||
}
|
||||
|
||||
evtchn = netif->evtchn;
|
||||
id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
|
||||
if ( make_rx_response(netif, id, status, mdata, size) &&
|
||||
(rx_notify[evtchn] == 0) )
|
||||
{
|
||||
@@ -295,6 +290,7 @@ static void net_rx_action(unsigned long unused)
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
mcl += 2;
|
||||
mmu += 3;
|
||||
}
|
||||
|
||||
while ( notify_nr != 0 )
|
||||
@@ -406,10 +402,11 @@ static void net_tx_action(unsigned long unused)
|
||||
{
|
||||
pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
|
||||
|
||||
netif = pending_netif[pending_idx];
|
||||
netif = pending_tx_info[pending_idx].netif;
|
||||
|
||||
spin_lock(&netif->tx_lock);
|
||||
make_tx_response(netif, pending_id[pending_idx], NETIF_RSP_OKAY);
|
||||
make_tx_response(netif, pending_tx_info[pending_idx].req.id,
|
||||
NETIF_RSP_OKAY);
|
||||
spin_unlock(&netif->tx_lock);
|
||||
|
||||
pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
|
||||
@@ -512,10 +509,11 @@ static void net_tx_action(unsigned long unused)
|
||||
mcl[0].args[2] = 0;
|
||||
mcl[0].args[3] = netif->domid;
|
||||
mcl++;
|
||||
|
||||
((tx_info_t *)&skb->cb[0])->idx = pending_idx;
|
||||
((tx_info_t *)&skb->cb[0])->netif = netif;
|
||||
memcpy(&((tx_info_t *)&skb->cb[0])->req, &txreq, sizeof(txreq));
|
||||
|
||||
memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq));
|
||||
pending_tx_info[pending_idx].netif = netif;
|
||||
*((u16 *)skb->data) = pending_idx;
|
||||
|
||||
__skb_queue_tail(&tx_queue, skb);
|
||||
|
||||
pending_cons++;
|
||||
@@ -533,9 +531,9 @@ static void net_tx_action(unsigned long unused)
|
||||
mcl = tx_mcl;
|
||||
while ( (skb = __skb_dequeue(&tx_queue)) != NULL )
|
||||
{
|
||||
pending_idx = ((tx_info_t *)&skb->cb[0])->idx;
|
||||
netif = ((tx_info_t *)&skb->cb[0])->netif;
|
||||
memcpy(&txreq, &((tx_info_t *)&skb->cb[0])->req, sizeof(txreq));
|
||||
pending_idx = *((u16 *)skb->data);
|
||||
netif = pending_tx_info[pending_idx].netif;
|
||||
memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq));
|
||||
|
||||
/* Check the remap error code. */
|
||||
if ( unlikely(mcl[0].args[5] != 0) )
|
||||
@@ -581,8 +579,6 @@ static void net_tx_action(unsigned long unused)
|
||||
*/
|
||||
page->mapping = (struct address_space *)netif_page_release;
|
||||
atomic_set(&page->count, 1);
|
||||
pending_id[pending_idx] = txreq.id;
|
||||
pending_netif[pending_idx] = netif;
|
||||
|
||||
netif->stats.tx_bytes += txreq.size;
|
||||
netif->stats.tx_packets++;
|
||||
|
||||
@@ -99,8 +99,6 @@ static struct net_device *find_dev_by_handle(unsigned int handle)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MULTIVIF
|
||||
|
||||
/** Network interface info. */
|
||||
struct netif_ctrl {
|
||||
/** Number of interfaces. */
|
||||
@@ -385,14 +383,8 @@ static void netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&np->tx_lock, flags);
|
||||
|
||||
if( !netif_carrier_ok(dev) )
|
||||
{
|
||||
spin_unlock_irqrestore(&np->tx_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
network_tx_buf_gc(dev);
|
||||
if ( likely(netif_carrier_ok(dev)) )
|
||||
network_tx_buf_gc(dev);
|
||||
spin_unlock_irqrestore(&np->tx_lock, flags);
|
||||
|
||||
if ( np->rx_resp_cons != np->rx->resp_prod )
|
||||
@@ -414,7 +406,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
|
||||
/* if the device is undergoing recovery then don't do anything */
|
||||
/* If the device is undergoing recovery then don't do anything. */
|
||||
if ( !netif_carrier_ok(dev) )
|
||||
{
|
||||
spin_unlock(&np->rx_lock);
|
||||
@@ -721,20 +713,17 @@ static void netif_status_change(netif_fe_interface_status_changed_t *status)
|
||||
|
||||
memcpy(dev->dev_addr, status->mac, ETH_ALEN);
|
||||
|
||||
if(netif_carrier_ok(dev)){
|
||||
if ( netif_carrier_ok(dev) )
|
||||
np->state = NETIF_STATE_CONNECTED;
|
||||
} else {
|
||||
else
|
||||
network_reconnect(dev, status);
|
||||
}
|
||||
|
||||
np->evtchn = status->evtchn;
|
||||
np->irq = bind_evtchn_to_irq(np->evtchn);
|
||||
(void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM,
|
||||
dev->name, dev);
|
||||
|
||||
#ifdef MULTIVIF
|
||||
netctrl_connected_count();
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -744,13 +733,13 @@ static void netif_status_change(netif_fe_interface_status_changed_t *status)
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a network devices.
|
||||
*
|
||||
/** Create a network device.
|
||||
* @param handle device handle
|
||||
* @param val return parameter for created device
|
||||
* @return 0 on success, error code otherwise
|
||||
*/
|
||||
static int create_netdev(int handle, struct net_device **val){
|
||||
static int create_netdev(int handle, struct net_device **val)
|
||||
{
|
||||
int err = 0;
|
||||
struct net_device *dev = NULL;
|
||||
struct net_private *np = NULL;
|
||||
@@ -847,11 +836,7 @@ static int __init init_module(void)
|
||||
{
|
||||
ctrl_msg_t cmsg;
|
||||
netif_fe_driver_status_changed_t st;
|
||||
int err = 0;
|
||||
#ifdef MULTIVIF
|
||||
int wait_n = 20;
|
||||
int wait_i;
|
||||
#endif
|
||||
int err = 0, wait_i, wait_n = 20;
|
||||
|
||||
if ( (start_info.flags & SIF_INITDOMAIN) ||
|
||||
(start_info.flags & SIF_NET_BE_DOMAIN) )
|
||||
@@ -860,9 +845,8 @@ static int __init init_module(void)
|
||||
printk("Initialising Xen virtual ethernet frontend driver");
|
||||
|
||||
INIT_LIST_HEAD(&dev_list);
|
||||
#ifdef MULTIVIF
|
||||
|
||||
netctrl_init();
|
||||
#endif
|
||||
|
||||
(void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
|
||||
CALLBACK_IN_BLOCKING_CONTEXT);
|
||||
@@ -876,7 +860,6 @@ static int __init init_module(void)
|
||||
memcpy(cmsg.msg, &st, sizeof(st));
|
||||
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
|
||||
|
||||
#ifdef MULTIVIF
|
||||
/* Wait for all interfaces to be connected. */
|
||||
for ( wait_i = 0; ; wait_i++)
|
||||
{
|
||||
@@ -888,7 +871,6 @@ static int __init init_module(void)
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( err )
|
||||
ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
|
||||
|
||||
@@ -101,7 +101,7 @@ continue_boot_cpu:
|
||||
mov 0x4(%eax),%eax /* %eax = mod[mod_count-1]->end */
|
||||
mov %eax,%ecx
|
||||
sub %ebx,%ecx /* %ecx = byte len of all mods */
|
||||
mov $(MAX_DIRECTMAP_ADDRESS), %edi
|
||||
mov $(DIRECTMAP_PHYS_END), %edi
|
||||
add %ecx, %edi /* %edi = src + length */
|
||||
shr $2,%ecx /* %ecx = length/4 */
|
||||
1: sub $4,%eax /* %eax = src, %edi = dst */
|
||||
@@ -117,7 +117,7 @@ skip_dom0_copy:
|
||||
1: mov %eax,__PAGE_OFFSET>>20(%edi) /* high mapping */
|
||||
stosl /* low mapping */
|
||||
add $(1<<L2_PAGETABLE_SHIFT),%eax
|
||||
cmp $MAX_DIRECTMAP_ADDRESS+0x1e3,%eax
|
||||
cmp $DIRECTMAP_PHYS_END+0x1e3,%eax
|
||||
jne 1b
|
||||
|
||||
call start_paging
|
||||
|
||||
+1
-1
@@ -347,7 +347,7 @@ void *memguard_init(void *heap_start)
|
||||
PAGE_MASK);
|
||||
|
||||
/* Memory guarding is incompatible with super pages. */
|
||||
for ( i = 0; i < (MAX_XENHEAP_ADDRESS >> L2_PAGETABLE_SHIFT); i++ )
|
||||
for ( i = 0; i < (xenheap_phys_end >> L2_PAGETABLE_SHIFT); i++ )
|
||||
{
|
||||
l1 = (l1_pgentry_t *)heap_start;
|
||||
heap_start = (void *)((unsigned long)heap_start + PAGE_SIZE);
|
||||
|
||||
+61
-28
@@ -27,6 +27,8 @@
|
||||
#include <asm/domain_page.h>
|
||||
#include <hypervisor-ifs/dom0_ops.h>
|
||||
|
||||
unsigned long xenheap_phys_end;
|
||||
|
||||
kmem_cache_t *domain_struct_cachep;
|
||||
|
||||
struct e820entry {
|
||||
@@ -69,6 +71,11 @@ char opt_physdev_dom0_hide[200] = "";
|
||||
/* level- or edge-triggered. */
|
||||
/* Example: 'leveltrigger=4,5,6,20 edgetrigger=21'. */
|
||||
char opt_leveltrigger[30] = "", opt_edgetrigger[30] = "";
|
||||
/*
|
||||
* opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
|
||||
* pfn_info table and allocation bitmap.
|
||||
*/
|
||||
unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
|
||||
|
||||
static struct {
|
||||
unsigned char *name;
|
||||
@@ -91,6 +98,7 @@ static struct {
|
||||
{ "physdev_dom0_hide", OPT_STR, &opt_physdev_dom0_hide },
|
||||
{ "leveltrigger", OPT_STR, &opt_leveltrigger },
|
||||
{ "edgetrigger", OPT_STR, &opt_edgetrigger },
|
||||
{ "xenheap_megabytes", OPT_UINT, &opt_xenheap_megabytes },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
@@ -180,52 +188,78 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
|
||||
for ( ; ; ) ;
|
||||
}
|
||||
|
||||
max_mem = max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
|
||||
|
||||
/* The array of pfn_info structures must fit into the reserved area. */
|
||||
if ( (sizeof(struct pfn_info) * max_page) >
|
||||
(FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) )
|
||||
if ( opt_xenheap_megabytes < 4 )
|
||||
{
|
||||
unsigned long new_max =
|
||||
(FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) /
|
||||
sizeof(struct pfn_info);
|
||||
printk("Truncating available memory to %lu/%luMB\n",
|
||||
new_max >> (20 - PAGE_SHIFT), max_page >> (20 - PAGE_SHIFT));
|
||||
max_page = new_max;
|
||||
printk("Xen heap size is too small to safely continue!\n");
|
||||
for ( ; ; ) ;
|
||||
}
|
||||
|
||||
set_current(&idle0_task);
|
||||
|
||||
init_frametable(max_page);
|
||||
printk("Initialised %luMB memory (%lu pages) on a %luMB machine\n",
|
||||
max_page >> (20-PAGE_SHIFT), max_page,
|
||||
max_mem >> (20-PAGE_SHIFT));
|
||||
xenheap_phys_end = opt_xenheap_megabytes << 20;
|
||||
|
||||
initial_images_start = MAX_DIRECTMAP_ADDRESS;
|
||||
max_mem = max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
if ( opt_xenheap_megabytes > XENHEAP_DEFAULT_MB )
|
||||
{
|
||||
printk("Xen heap size is limited to %dMB - you specified %dMB.\n",
|
||||
XENHEAP_DEFAULT_MB, opt_xenheap_megabytes);
|
||||
for ( ; ; ) ;
|
||||
}
|
||||
|
||||
ASSERT((sizeof(struct pfn_info) << 20) >
|
||||
(FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START));
|
||||
|
||||
init_frametable((void *)FRAMETABLE_VIRT_START, max_page);
|
||||
|
||||
/* Initial images stashed away above DIRECTMAP area in boot.S. */
|
||||
initial_images_start = DIRECTMAP_PHYS_END;
|
||||
initial_images_end = initial_images_start +
|
||||
(mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
init_frametable(__va(xenheap_phys_end), max_page);
|
||||
|
||||
initial_images_start = __pa(frame_table) + frame_table_size;
|
||||
initial_images_end = initial_images_start +
|
||||
(mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
|
||||
if ( initial_images_end > (max_page << PAGE_SHIFT) )
|
||||
{
|
||||
printk("Not enough memory to stash the DOM0 kernel image.\n");
|
||||
for ( ; ; ) ;
|
||||
}
|
||||
memmove(__va(initial_images_start),
|
||||
__va(mod[0].mod_start),
|
||||
mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
|
||||
|
||||
#endif
|
||||
|
||||
dom0_memory_start = (initial_images_end + ((4<<20)-1)) & ~((4<<20)-1);
|
||||
dom0_memory_end = dom0_memory_start + (opt_dom0_mem << 10);
|
||||
dom0_memory_end = (dom0_memory_end + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
/* Cheesy sanity check: enough memory for DOM0 allocation + some slack? */
|
||||
if ( (dom0_memory_end + (8<<20)) > (max_page<<PAGE_SHIFT) )
|
||||
panic("Not enough memory to craete initial domain!\n");
|
||||
if ( (dom0_memory_end + (8<<20)) > (max_page << PAGE_SHIFT) )
|
||||
{
|
||||
printk("Not enough memory for DOM0 memory reservation.\n");
|
||||
for ( ; ; ) ;
|
||||
}
|
||||
|
||||
printk("Initialised %luMB memory (%lu pages) on a %luMB machine\n",
|
||||
max_page >> (20-PAGE_SHIFT), max_page,
|
||||
max_mem >> (20-PAGE_SHIFT));
|
||||
|
||||
add_to_domain_alloc_list(dom0_memory_end, max_page << PAGE_SHIFT);
|
||||
|
||||
heap_start = memguard_init(&_end);
|
||||
|
||||
printk("Xen heap size is %luKB\n",
|
||||
(MAX_XENHEAP_ADDRESS-__pa(heap_start))/1024 );
|
||||
(xenheap_phys_end-__pa(heap_start))/1024 );
|
||||
|
||||
if ( ((MAX_XENHEAP_ADDRESS-__pa(heap_start))/1024) <= 4096 )
|
||||
{
|
||||
printk("Xen heap size is too small to safely continue!\n");
|
||||
for ( ; ; ) ;
|
||||
}
|
||||
|
||||
init_page_allocator(__pa(heap_start), MAX_XENHEAP_ADDRESS);
|
||||
init_page_allocator(__pa(heap_start), xenheap_phys_end);
|
||||
|
||||
/* Initialise the slab allocator. */
|
||||
kmem_cache_init();
|
||||
@@ -253,8 +287,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
|
||||
|
||||
/*
|
||||
* We're going to setup domain0 using the module(s) that we stashed safely
|
||||
* above our MAX_DIRECTMAP_ADDRESS in boot/boot.S. The second module, if
|
||||
* present, is an initrd ramdisk.
|
||||
* above our heap. The second module, if present, is an initrd ramdisk.
|
||||
*/
|
||||
if ( construct_dom0(new_dom, dom0_memory_start, dom0_memory_end,
|
||||
(char *)initial_images_start,
|
||||
|
||||
+12
-9
@@ -144,7 +144,7 @@ static struct {
|
||||
#define GPS (percpu_info[smp_processor_id()].gps ? : current)
|
||||
|
||||
|
||||
void __init init_frametable(unsigned long nr_pages)
|
||||
void __init init_frametable(void *frametable_vstart, unsigned long nr_pages)
|
||||
{
|
||||
unsigned long mfn;
|
||||
|
||||
@@ -153,22 +153,23 @@ void __init init_frametable(unsigned long nr_pages)
|
||||
max_page = nr_pages;
|
||||
frame_table_size = nr_pages * sizeof(struct pfn_info);
|
||||
frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
frame_table = (struct pfn_info *)FRAMETABLE_VIRT_START;
|
||||
frame_table = frametable_vstart;
|
||||
|
||||
if ( (__pa(frame_table) + frame_table_size) > (max_page << PAGE_SHIFT) )
|
||||
panic("Not enough memory for frame table - reduce Xen heap size?\n");
|
||||
|
||||
memset(frame_table, 0, frame_table_size);
|
||||
|
||||
spin_lock_init(&free_list_lock);
|
||||
INIT_LIST_HEAD(&free_list);
|
||||
free_pfns = 0;
|
||||
|
||||
/* initialise to a magic of 0x55555555 so easier to spot bugs later */
|
||||
memset( machine_to_phys_mapping, 0x55, 4*1024*1024 );
|
||||
|
||||
/* The array is sized for a 4GB machine regardless of actuall mem size.
|
||||
This costs 4MB -- may want to fix some day */
|
||||
/* Initialise to a magic of 0x55555555 so easier to spot bugs later. */
|
||||
memset(machine_to_phys_mapping, 0x55, 4<<20);
|
||||
|
||||
/* Pin the ownership of the MP table so that DOM0 can map it later. */
|
||||
for ( mfn = virt_to_phys(&machine_to_phys_mapping[0])>>PAGE_SHIFT;
|
||||
mfn < virt_to_phys(&machine_to_phys_mapping[1024*1024])>>PAGE_SHIFT;
|
||||
for ( mfn = virt_to_phys(&machine_to_phys_mapping[0<<20])>>PAGE_SHIFT;
|
||||
mfn < virt_to_phys(&machine_to_phys_mapping[1<<20])>>PAGE_SHIFT;
|
||||
mfn++ )
|
||||
{
|
||||
frame_table[mfn].count_and_flags = 1 | PGC_allocated;
|
||||
@@ -471,6 +472,7 @@ static int alloc_l2_table(struct pfn_info *page)
|
||||
if ( unlikely(!get_page_from_l2e(pl2e[i], page_nr)) )
|
||||
goto fail;
|
||||
|
||||
#if defined(__i386__)
|
||||
/* Now we add our private high mappings. */
|
||||
memcpy(&pl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
|
||||
&idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
|
||||
@@ -480,6 +482,7 @@ static int alloc_l2_table(struct pfn_info *page)
|
||||
pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
|
||||
mk_l2_pgentry(__pa(page->u.domain->mm.perdomain_pt) |
|
||||
__PAGE_HYPERVISOR);
|
||||
#endif
|
||||
|
||||
unmap_domain_mem(pl2e);
|
||||
return 1;
|
||||
|
||||
+5
-1
@@ -151,7 +151,9 @@ static inline int shadow_page_op( struct mm_struct *m, unsigned int op,
|
||||
PGT_l2_page_table )
|
||||
{
|
||||
unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT );
|
||||
memset( spl1e, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE * sizeof(*spl1e) );
|
||||
#ifdef __i386__
|
||||
memset(spl1e, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE * sizeof(*spl1e));
|
||||
#endif
|
||||
unmap_domain_mem( spl1e );
|
||||
}
|
||||
}
|
||||
@@ -574,6 +576,7 @@ unsigned long shadow_l2_table(
|
||||
// we need to do this before the linear map is set up
|
||||
spl2e = (l2_pgentry_t *) map_domain_mem(spfn << PAGE_SHIFT);
|
||||
|
||||
#ifdef __i386__
|
||||
// get hypervisor and 2x linear PT mapings installed
|
||||
memcpy(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
|
||||
&idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
|
||||
@@ -585,6 +588,7 @@ unsigned long shadow_l2_table(
|
||||
spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
|
||||
mk_l2_pgentry(__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) |
|
||||
__PAGE_HYPERVISOR);
|
||||
#endif
|
||||
|
||||
// can't use the linear map as we may not be in the right PT
|
||||
gpl2e = (l2_pgentry_t *) map_domain_mem(gpfn << PAGE_SHIFT);
|
||||
|
||||
@@ -93,6 +93,8 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
#define XENHEAP_DEFAULT_MB (16)
|
||||
|
||||
#define PML4_ENTRY_BITS 39
|
||||
#define PML4_ENTRY_BYTES (1UL<<PML4_ENTRY_BITS)
|
||||
|
||||
@@ -158,9 +160,8 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
/* The following are machine addresses. */
|
||||
#define MAX_XENHEAP_ADDRESS (12*1024*1024)
|
||||
#define MAX_DIRECTMAP_ADDRESS (40*1024*1024)
|
||||
#define XENHEAP_DEFAULT_MB (12)
|
||||
#define DIRECTMAP_PHYS_END (40*1024*1024)
|
||||
|
||||
/* Hypervisor owns top 64MB of virtual address space. */
|
||||
#define HYPERVISOR_VIRT_START (0xFC000000UL)
|
||||
@@ -173,9 +174,9 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
|
||||
#define RO_MPT_VIRT_END (RO_MPT_VIRT_START + (4*1024*1024))
|
||||
/* The virtual addresses for the 40MB direct-map region. */
|
||||
#define DIRECTMAP_VIRT_START (RO_MPT_VIRT_END)
|
||||
#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS)
|
||||
#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + DIRECTMAP_PHYS_END)
|
||||
#define XENHEAP_VIRT_START (DIRECTMAP_VIRT_START)
|
||||
#define XENHEAP_VIRT_END (XENHEAP_VIRT_START + MAX_XENHEAP_ADDRESS)
|
||||
#define XENHEAP_VIRT_END (XENHEAP_VIRT_START + (XENHEAP_DEFAULT_MB<<20))
|
||||
#define RDWR_MPT_VIRT_START (XENHEAP_VIRT_END)
|
||||
#define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (4*1024*1024))
|
||||
#define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END)
|
||||
@@ -207,6 +208,10 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
|
||||
|
||||
#endif /* __i386__ */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern unsigned long xenheap_phys_end; /* user-configurable */
|
||||
#endif
|
||||
|
||||
#define GDT_VIRT_START (PERDOMAIN_VIRT_START)
|
||||
#define GDT_VIRT_END (GDT_VIRT_START + (64*1024))
|
||||
#define LDT_VIRT_START (GDT_VIRT_END)
|
||||
|
||||
@@ -95,12 +95,12 @@ typedef struct { unsigned long pt_lo; } pagetable_t;
|
||||
extern l2_pgentry_t idle_pg_table[ENTRIES_PER_L2_PAGETABLE];
|
||||
extern void paging_init(void);
|
||||
|
||||
#define __flush_tlb() \
|
||||
do { \
|
||||
__asm__ __volatile__ ( \
|
||||
"movl %%cr3, %%eax; movl %%eax, %%cr3" \
|
||||
: : : "memory", "eax" ); \
|
||||
tlb_clocktick(); \
|
||||
#define __flush_tlb() \
|
||||
do { \
|
||||
__asm__ __volatile__ ( \
|
||||
"mov %%cr3, %%"__OP"ax; mov %%"__OP"ax, %%cr3" \
|
||||
: : : "memory", __OP"ax" ); \
|
||||
tlb_clocktick(); \
|
||||
} while ( 0 )
|
||||
|
||||
/* Flush global pages as well. */
|
||||
@@ -108,14 +108,14 @@ extern void paging_init(void);
|
||||
#define __pge_off() \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
"movl %0, %%cr4; # turn off PGE " \
|
||||
"mov %0, %%cr4; # turn off PGE " \
|
||||
:: "r" (mmu_cr4_features & ~X86_CR4_PGE)); \
|
||||
} while (0)
|
||||
|
||||
#define __pge_on() \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
"movl %0, %%cr4; # turn off PGE " \
|
||||
"mov %0, %%cr4; # turn off PGE " \
|
||||
:: "r" (mmu_cr4_features)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -1,485 +1,5 @@
|
||||
#ifndef _I386_STRING_H_
|
||||
#define _I386_STRING_H_
|
||||
|
||||
#include <xen/config.h>
|
||||
|
||||
/*
|
||||
* This string-include defines all string functions as inline
|
||||
* functions. Use gcc. It also assumes ds=es=data space, this should be
|
||||
* normal. Most of the string-functions are rather heavily hand-optimized,
|
||||
* see especially strtok,strstr,str[c]spn. They should work, but are not
|
||||
* very easy to understand. Everything is done entirely within the register
|
||||
* set, making the functions fast and clean. String instructions have been
|
||||
* used through-out, making for "slightly" unclear code :-)
|
||||
*
|
||||
* NO Copyright (C) 1991, 1992 Linus Torvalds,
|
||||
* consider these trivial functions to be PD.
|
||||
*/
|
||||
|
||||
|
||||
#define __HAVE_ARCH_STRCPY
|
||||
static inline char * strcpy(char * dest,const char *src)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"1:\tlodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
|
||||
:"0" (src),"1" (dest) : "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRNCPY
|
||||
static inline char * strncpy(char * dest,const char *src,size_t count)
|
||||
{
|
||||
int d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"1:\tdecl %2\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n\t"
|
||||
"rep\n\t"
|
||||
"stosb\n"
|
||||
"2:"
|
||||
: "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
|
||||
:"0" (src),"1" (dest),"2" (count) : "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRCAT
|
||||
static inline char * strcat(char * dest,const char * src)
|
||||
{
|
||||
int d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"decl %1\n"
|
||||
"1:\tlodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
|
||||
: "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRNCAT
|
||||
static inline char * strncat(char * dest,const char * src,size_t count)
|
||||
{
|
||||
int d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"decl %1\n\t"
|
||||
"movl %8,%3\n"
|
||||
"1:\tdecl %3\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n"
|
||||
"2:\txorl %2,%2\n\t"
|
||||
"stosb"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
|
||||
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
|
||||
: "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRCMP
|
||||
static inline int strcmp(const char * cs,const char * ct)
|
||||
{
|
||||
int d0, d1;
|
||||
register int __res;
|
||||
__asm__ __volatile__(
|
||||
"1:\tlodsb\n\t"
|
||||
"scasb\n\t"
|
||||
"jne 2f\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n\t"
|
||||
"xorl %%eax,%%eax\n\t"
|
||||
"jmp 3f\n"
|
||||
"2:\tsbbl %%eax,%%eax\n\t"
|
||||
"orb $1,%%al\n"
|
||||
"3:"
|
||||
:"=a" (__res), "=&S" (d0), "=&D" (d1)
|
||||
:"1" (cs),"2" (ct));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRNCMP
|
||||
static inline int strncmp(const char * cs,const char * ct,size_t count)
|
||||
{
|
||||
register int __res;
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"1:\tdecl %3\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"scasb\n\t"
|
||||
"jne 3f\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n"
|
||||
"2:\txorl %%eax,%%eax\n\t"
|
||||
"jmp 4f\n"
|
||||
"3:\tsbbl %%eax,%%eax\n\t"
|
||||
"orb $1,%%al\n"
|
||||
"4:"
|
||||
:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
|
||||
:"1" (cs),"2" (ct),"3" (count));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRCHR
|
||||
static inline char * strchr(const char * s, int c)
|
||||
{
|
||||
int d0;
|
||||
register char * __res;
|
||||
__asm__ __volatile__(
|
||||
"movb %%al,%%ah\n"
|
||||
"1:\tlodsb\n\t"
|
||||
"cmpb %%ah,%%al\n\t"
|
||||
"je 2f\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n\t"
|
||||
"movl $1,%1\n"
|
||||
"2:\tmovl %1,%0\n\t"
|
||||
"decl %0"
|
||||
:"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRRCHR
|
||||
static inline char * strrchr(const char * s, int c)
|
||||
{
|
||||
int d0, d1;
|
||||
register char * __res;
|
||||
__asm__ __volatile__(
|
||||
"movb %%al,%%ah\n"
|
||||
"1:\tlodsb\n\t"
|
||||
"cmpb %%ah,%%al\n\t"
|
||||
"jne 2f\n\t"
|
||||
"leal -1(%%esi),%0\n"
|
||||
"2:\ttestb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
:"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRLEN
|
||||
static inline size_t strlen(const char * s)
|
||||
{
|
||||
int d0;
|
||||
register int __res;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"notl %0\n\t"
|
||||
"decl %0"
|
||||
:"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
|
||||
return __res;
|
||||
}
|
||||
|
||||
static inline void * __memcpy(void * to, const void * from, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"rep ; movsl\n\t"
|
||||
"testb $2,%b4\n\t"
|
||||
"je 1f\n\t"
|
||||
"movsw\n"
|
||||
"1:\ttestb $1,%b4\n\t"
|
||||
"je 2f\n\t"
|
||||
"movsb\n"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
|
||||
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
|
||||
: "memory");
|
||||
return (to);
|
||||
}
|
||||
|
||||
/*
|
||||
* This looks horribly ugly, but the compiler can optimize it totally,
|
||||
* as the count is constant.
|
||||
*/
|
||||
static inline void * __constant_memcpy(void * to, const void * from, size_t n)
|
||||
{
|
||||
switch (n) {
|
||||
case 0:
|
||||
return to;
|
||||
case 1:
|
||||
*(unsigned char *)to = *(const unsigned char *)from;
|
||||
return to;
|
||||
case 2:
|
||||
*(unsigned short *)to = *(const unsigned short *)from;
|
||||
return to;
|
||||
case 3:
|
||||
*(unsigned short *)to = *(const unsigned short *)from;
|
||||
*(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
|
||||
return to;
|
||||
case 4:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
return to;
|
||||
case 6: /* for Ethernet addresses */
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(2+(unsigned short *)to) = *(2+(const unsigned short *)from);
|
||||
return to;
|
||||
case 8:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
return to;
|
||||
case 12:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
*(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
|
||||
return to;
|
||||
case 16:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
*(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
|
||||
*(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
|
||||
return to;
|
||||
case 20:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
*(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
|
||||
*(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
|
||||
*(4+(unsigned long *)to) = *(4+(const unsigned long *)from);
|
||||
return to;
|
||||
}
|
||||
#define COMMON(x) \
|
||||
__asm__ __volatile__( \
|
||||
"rep ; movsl" \
|
||||
x \
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2) \
|
||||
: "0" (n/4),"1" ((long) to),"2" ((long) from) \
|
||||
: "memory");
|
||||
{
|
||||
int d0, d1, d2;
|
||||
switch (n % 4) {
|
||||
case 0: COMMON(""); return to;
|
||||
case 1: COMMON("\n\tmovsb"); return to;
|
||||
case 2: COMMON("\n\tmovsw"); return to;
|
||||
default: COMMON("\n\tmovsw\n\tmovsb"); return to;
|
||||
}
|
||||
}
|
||||
|
||||
#undef COMMON
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
|
||||
#define memcpy(t, f, n) \
|
||||
(__builtin_constant_p(n) ? \
|
||||
__constant_memcpy((t),(f),(n)) : \
|
||||
__memcpy((t),(f),(n)))
|
||||
|
||||
|
||||
/*
|
||||
* struct_cpy(x,y), copy structure *x into (matching structure) *y.
|
||||
*
|
||||
* We get link-time errors if the structure sizes do not match.
|
||||
* There is no runtime overhead, it's all optimized away at
|
||||
* compile time.
|
||||
*/
|
||||
//extern void __struct_cpy_bug (void);
|
||||
|
||||
/*
|
||||
#define struct_cpy(x,y) \
|
||||
({ \
|
||||
if (sizeof(*(x)) != sizeof(*(y))) \
|
||||
__struct_cpy_bug; \
|
||||
memcpy(x, y, sizeof(*(x))); \
|
||||
})
|
||||
*/
|
||||
|
||||
#define __HAVE_ARCH_MEMMOVE
|
||||
static inline void * memmove(void * dest,const void * src, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
if (dest<src)
|
||||
__asm__ __volatile__(
|
||||
"rep\n\t"
|
||||
"movsb"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
:"0" (n),"1" (src),"2" (dest)
|
||||
: "memory");
|
||||
else
|
||||
__asm__ __volatile__(
|
||||
"std\n\t"
|
||||
"rep\n\t"
|
||||
"movsb\n\t"
|
||||
"cld"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
:"0" (n),
|
||||
"1" (n-1+(const char *)src),
|
||||
"2" (n-1+(char *)dest)
|
||||
:"memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_MEMCMP
|
||||
#define memcmp __builtin_memcmp
|
||||
|
||||
#define __HAVE_ARCH_MEMCHR
|
||||
static inline void * memchr(const void * cs,int c,size_t count)
|
||||
{
|
||||
int d0;
|
||||
register void * __res;
|
||||
if (!count)
|
||||
return NULL;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"je 1f\n\t"
|
||||
"movl $1,%0\n"
|
||||
"1:\tdecl %0"
|
||||
:"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
|
||||
return __res;
|
||||
}
|
||||
|
||||
static inline void * __memset_generic(void * s, char c,size_t count)
|
||||
{
|
||||
int d0, d1;
|
||||
__asm__ __volatile__(
|
||||
"rep\n\t"
|
||||
"stosb"
|
||||
: "=&c" (d0), "=&D" (d1)
|
||||
:"a" (c),"1" (s),"0" (count)
|
||||
:"memory");
|
||||
return s;
|
||||
}
|
||||
|
||||
/* we might want to write optimized versions of these later */
|
||||
#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
|
||||
|
||||
/*
|
||||
* memset(x,0,y) is a reasonably common thing to do, so we want to fill
|
||||
* things 32 bits at a time even when we don't know the size of the
|
||||
* area at compile-time..
|
||||
*/
|
||||
static inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
|
||||
{
|
||||
int d0, d1;
|
||||
__asm__ __volatile__(
|
||||
"rep ; stosl\n\t"
|
||||
"testb $2,%b3\n\t"
|
||||
"je 1f\n\t"
|
||||
"stosw\n"
|
||||
"1:\ttestb $1,%b3\n\t"
|
||||
"je 2f\n\t"
|
||||
"stosb\n"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1)
|
||||
:"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
|
||||
:"memory");
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Added by Gertjan van Wingerde to make minix and sysv module work */
|
||||
#define __HAVE_ARCH_STRNLEN
|
||||
static inline size_t strnlen(const char * s, size_t count)
|
||||
{
|
||||
int d0;
|
||||
register int __res;
|
||||
__asm__ __volatile__(
|
||||
"movl %2,%0\n\t"
|
||||
"jmp 2f\n"
|
||||
"1:\tcmpb $0,(%0)\n\t"
|
||||
"je 3f\n\t"
|
||||
"incl %0\n"
|
||||
"2:\tdecl %1\n\t"
|
||||
"cmpl $-1,%1\n\t"
|
||||
"jne 1b\n"
|
||||
"3:\tsubl %2,%0"
|
||||
:"=a" (__res), "=&d" (d0)
|
||||
:"c" (s),"1" (count));
|
||||
return __res;
|
||||
}
|
||||
/* end of additional stuff */
|
||||
|
||||
//#define __HAVE_ARCH_STRSTR
|
||||
|
||||
//extern char *strstr(const char *cs, const char *ct);
|
||||
|
||||
/*
|
||||
* This looks horribly ugly, but the compiler can optimize it totally,
|
||||
* as we by now know that both pattern and count is constant..
|
||||
*/
|
||||
static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
|
||||
{
|
||||
switch (count) {
|
||||
case 0:
|
||||
return s;
|
||||
case 1:
|
||||
*(unsigned char *)s = pattern;
|
||||
return s;
|
||||
case 2:
|
||||
*(unsigned short *)s = pattern;
|
||||
return s;
|
||||
case 3:
|
||||
*(unsigned short *)s = pattern;
|
||||
*(2+(unsigned char *)s) = pattern;
|
||||
return s;
|
||||
case 4:
|
||||
*(unsigned long *)s = pattern;
|
||||
return s;
|
||||
}
|
||||
#define COMMON(x) \
|
||||
__asm__ __volatile__( \
|
||||
"rep ; stosl" \
|
||||
x \
|
||||
: "=&c" (d0), "=&D" (d1) \
|
||||
: "a" (pattern),"0" (count/4),"1" ((long) s) \
|
||||
: "memory")
|
||||
{
|
||||
int d0, d1;
|
||||
switch (count % 4) {
|
||||
case 0: COMMON(""); return s;
|
||||
case 1: COMMON("\n\tstosb"); return s;
|
||||
case 2: COMMON("\n\tstosw"); return s;
|
||||
default: COMMON("\n\tstosw\n\tstosb"); return s;
|
||||
}
|
||||
}
|
||||
|
||||
#undef COMMON
|
||||
}
|
||||
|
||||
#define __constant_c_x_memset(s, c, count) \
|
||||
(__builtin_constant_p(count) ? \
|
||||
__constant_c_and_count_memset((s),(c),(count)) : \
|
||||
__constant_c_memset((s),(c),(count)))
|
||||
|
||||
#define __memset(s, c, count) \
|
||||
(__builtin_constant_p(count) ? \
|
||||
__constant_count_memset((s),(c),(count)) : \
|
||||
__memset_generic((s),(c),(count)))
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
#define memset(s, c, count) \
|
||||
(__builtin_constant_p(c) ? \
|
||||
__constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \
|
||||
__memset((s),(c),(count)))
|
||||
|
||||
/*
|
||||
* find the first occurrence of byte 'c', or 1 past the area if none
|
||||
*/
|
||||
#define __HAVE_ARCH_MEMSCAN
|
||||
static inline void * memscan(void * addr, int c, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
return addr;
|
||||
__asm__("repnz; scasb\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"dec %%edi\n"
|
||||
"1:"
|
||||
: "=D" (addr), "=c" (size)
|
||||
: "0" (addr), "1" (size), "a" (c));
|
||||
return addr;
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include <asm/x86_64/string.h>
|
||||
#else
|
||||
#include <asm/x86_32/string.h>
|
||||
#endif
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
typedef unsigned short umode_t;
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
/*
|
||||
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
|
||||
@@ -44,10 +43,12 @@ typedef unsigned int u32;
|
||||
typedef signed long long s64;
|
||||
typedef unsigned long long u64;
|
||||
#define BITS_PER_LONG 32
|
||||
typedef unsigned int size_t;
|
||||
#elif defined(__x86_64__)
|
||||
typedef signed long s64;
|
||||
typedef unsigned long u64;
|
||||
#define BITS_PER_LONG 64
|
||||
typedef unsigned long size_t;
|
||||
#endif
|
||||
|
||||
/* DMA addresses come in generic and 64-bit flavours. */
|
||||
|
||||
@@ -0,0 +1,485 @@
|
||||
#ifndef _I386_STRING_H_
|
||||
#define _I386_STRING_H_
|
||||
|
||||
#include <xen/config.h>
|
||||
|
||||
/*
|
||||
* This string-include defines all string functions as inline
|
||||
* functions. Use gcc. It also assumes ds=es=data space, this should be
|
||||
* normal. Most of the string-functions are rather heavily hand-optimized,
|
||||
* see especially strtok,strstr,str[c]spn. They should work, but are not
|
||||
* very easy to understand. Everything is done entirely within the register
|
||||
* set, making the functions fast and clean. String instructions have been
|
||||
* used through-out, making for "slightly" unclear code :-)
|
||||
*
|
||||
* NO Copyright (C) 1991, 1992 Linus Torvalds,
|
||||
* consider these trivial functions to be PD.
|
||||
*/
|
||||
|
||||
|
||||
#define __HAVE_ARCH_STRCPY
|
||||
static inline char * strcpy(char * dest,const char *src)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"1:\tlodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
|
||||
:"0" (src),"1" (dest) : "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRNCPY
|
||||
static inline char * strncpy(char * dest,const char *src,size_t count)
|
||||
{
|
||||
int d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"1:\tdecl %2\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n\t"
|
||||
"rep\n\t"
|
||||
"stosb\n"
|
||||
"2:"
|
||||
: "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
|
||||
:"0" (src),"1" (dest),"2" (count) : "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRCAT
|
||||
static inline char * strcat(char * dest,const char * src)
|
||||
{
|
||||
int d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"decl %1\n"
|
||||
"1:\tlodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
|
||||
: "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRNCAT
|
||||
static inline char * strncat(char * dest,const char * src,size_t count)
|
||||
{
|
||||
int d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"decl %1\n\t"
|
||||
"movl %8,%3\n"
|
||||
"1:\tdecl %3\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n"
|
||||
"2:\txorl %2,%2\n\t"
|
||||
"stosb"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
|
||||
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
|
||||
: "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRCMP
|
||||
static inline int strcmp(const char * cs,const char * ct)
|
||||
{
|
||||
int d0, d1;
|
||||
register int __res;
|
||||
__asm__ __volatile__(
|
||||
"1:\tlodsb\n\t"
|
||||
"scasb\n\t"
|
||||
"jne 2f\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n\t"
|
||||
"xorl %%eax,%%eax\n\t"
|
||||
"jmp 3f\n"
|
||||
"2:\tsbbl %%eax,%%eax\n\t"
|
||||
"orb $1,%%al\n"
|
||||
"3:"
|
||||
:"=a" (__res), "=&S" (d0), "=&D" (d1)
|
||||
:"1" (cs),"2" (ct));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRNCMP
|
||||
static inline int strncmp(const char * cs,const char * ct,size_t count)
|
||||
{
|
||||
register int __res;
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"1:\tdecl %3\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"scasb\n\t"
|
||||
"jne 3f\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n"
|
||||
"2:\txorl %%eax,%%eax\n\t"
|
||||
"jmp 4f\n"
|
||||
"3:\tsbbl %%eax,%%eax\n\t"
|
||||
"orb $1,%%al\n"
|
||||
"4:"
|
||||
:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
|
||||
:"1" (cs),"2" (ct),"3" (count));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRCHR
|
||||
static inline char * strchr(const char * s, int c)
|
||||
{
|
||||
int d0;
|
||||
register char * __res;
|
||||
__asm__ __volatile__(
|
||||
"movb %%al,%%ah\n"
|
||||
"1:\tlodsb\n\t"
|
||||
"cmpb %%ah,%%al\n\t"
|
||||
"je 2f\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n\t"
|
||||
"movl $1,%1\n"
|
||||
"2:\tmovl %1,%0\n\t"
|
||||
"decl %0"
|
||||
:"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRRCHR
|
||||
static inline char * strrchr(const char * s, int c)
|
||||
{
|
||||
int d0, d1;
|
||||
register char * __res;
|
||||
__asm__ __volatile__(
|
||||
"movb %%al,%%ah\n"
|
||||
"1:\tlodsb\n\t"
|
||||
"cmpb %%ah,%%al\n\t"
|
||||
"jne 2f\n\t"
|
||||
"leal -1(%%esi),%0\n"
|
||||
"2:\ttestb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
:"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRLEN
|
||||
static inline size_t strlen(const char * s)
|
||||
{
|
||||
int d0;
|
||||
register int __res;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"notl %0\n\t"
|
||||
"decl %0"
|
||||
:"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
|
||||
return __res;
|
||||
}
|
||||
|
||||
static inline void * __memcpy(void * to, const void * from, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"rep ; movsl\n\t"
|
||||
"testb $2,%b4\n\t"
|
||||
"je 1f\n\t"
|
||||
"movsw\n"
|
||||
"1:\ttestb $1,%b4\n\t"
|
||||
"je 2f\n\t"
|
||||
"movsb\n"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
|
||||
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
|
||||
: "memory");
|
||||
return (to);
|
||||
}
|
||||
|
||||
/*
|
||||
* This looks horribly ugly, but the compiler can optimize it totally,
|
||||
* as the count is constant.
|
||||
*/
|
||||
static inline void * __constant_memcpy(void * to, const void * from, size_t n)
|
||||
{
|
||||
switch (n) {
|
||||
case 0:
|
||||
return to;
|
||||
case 1:
|
||||
*(unsigned char *)to = *(const unsigned char *)from;
|
||||
return to;
|
||||
case 2:
|
||||
*(unsigned short *)to = *(const unsigned short *)from;
|
||||
return to;
|
||||
case 3:
|
||||
*(unsigned short *)to = *(const unsigned short *)from;
|
||||
*(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
|
||||
return to;
|
||||
case 4:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
return to;
|
||||
case 6: /* for Ethernet addresses */
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(2+(unsigned short *)to) = *(2+(const unsigned short *)from);
|
||||
return to;
|
||||
case 8:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
return to;
|
||||
case 12:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
*(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
|
||||
return to;
|
||||
case 16:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
*(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
|
||||
*(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
|
||||
return to;
|
||||
case 20:
|
||||
*(unsigned long *)to = *(const unsigned long *)from;
|
||||
*(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
|
||||
*(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
|
||||
*(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
|
||||
*(4+(unsigned long *)to) = *(4+(const unsigned long *)from);
|
||||
return to;
|
||||
}
|
||||
#define COMMON(x) \
|
||||
__asm__ __volatile__( \
|
||||
"rep ; movsl" \
|
||||
x \
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2) \
|
||||
: "0" (n/4),"1" ((long) to),"2" ((long) from) \
|
||||
: "memory");
|
||||
{
|
||||
int d0, d1, d2;
|
||||
switch (n % 4) {
|
||||
case 0: COMMON(""); return to;
|
||||
case 1: COMMON("\n\tmovsb"); return to;
|
||||
case 2: COMMON("\n\tmovsw"); return to;
|
||||
default: COMMON("\n\tmovsw\n\tmovsb"); return to;
|
||||
}
|
||||
}
|
||||
|
||||
#undef COMMON
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
|
||||
#define memcpy(t, f, n) \
|
||||
(__builtin_constant_p(n) ? \
|
||||
__constant_memcpy((t),(f),(n)) : \
|
||||
__memcpy((t),(f),(n)))
|
||||
|
||||
|
||||
/*
|
||||
* struct_cpy(x,y), copy structure *x into (matching structure) *y.
|
||||
*
|
||||
* We get link-time errors if the structure sizes do not match.
|
||||
* There is no runtime overhead, it's all optimized away at
|
||||
* compile time.
|
||||
*/
|
||||
//extern void __struct_cpy_bug (void);
|
||||
|
||||
/*
|
||||
#define struct_cpy(x,y) \
|
||||
({ \
|
||||
if (sizeof(*(x)) != sizeof(*(y))) \
|
||||
__struct_cpy_bug; \
|
||||
memcpy(x, y, sizeof(*(x))); \
|
||||
})
|
||||
*/
|
||||
|
||||
#define __HAVE_ARCH_MEMMOVE
|
||||
static inline void * memmove(void * dest,const void * src, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
if (dest<src)
|
||||
__asm__ __volatile__(
|
||||
"rep\n\t"
|
||||
"movsb"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
:"0" (n),"1" (src),"2" (dest)
|
||||
: "memory");
|
||||
else
|
||||
__asm__ __volatile__(
|
||||
"std\n\t"
|
||||
"rep\n\t"
|
||||
"movsb\n\t"
|
||||
"cld"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
:"0" (n),
|
||||
"1" (n-1+(const char *)src),
|
||||
"2" (n-1+(char *)dest)
|
||||
:"memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_MEMCMP
|
||||
#define memcmp __builtin_memcmp
|
||||
|
||||
#define __HAVE_ARCH_MEMCHR
|
||||
static inline void * memchr(const void * cs,int c,size_t count)
|
||||
{
|
||||
int d0;
|
||||
register void * __res;
|
||||
if (!count)
|
||||
return NULL;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"je 1f\n\t"
|
||||
"movl $1,%0\n"
|
||||
"1:\tdecl %0"
|
||||
:"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
|
||||
return __res;
|
||||
}
|
||||
|
||||
static inline void * __memset_generic(void * s, char c,size_t count)
|
||||
{
|
||||
int d0, d1;
|
||||
__asm__ __volatile__(
|
||||
"rep\n\t"
|
||||
"stosb"
|
||||
: "=&c" (d0), "=&D" (d1)
|
||||
:"a" (c),"1" (s),"0" (count)
|
||||
:"memory");
|
||||
return s;
|
||||
}
|
||||
|
||||
/* we might want to write optimized versions of these later */
|
||||
#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
|
||||
|
||||
/*
|
||||
* memset(x,0,y) is a reasonably common thing to do, so we want to fill
|
||||
* things 32 bits at a time even when we don't know the size of the
|
||||
* area at compile-time..
|
||||
*/
|
||||
static inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
|
||||
{
|
||||
int d0, d1;
|
||||
__asm__ __volatile__(
|
||||
"rep ; stosl\n\t"
|
||||
"testb $2,%b3\n\t"
|
||||
"je 1f\n\t"
|
||||
"stosw\n"
|
||||
"1:\ttestb $1,%b3\n\t"
|
||||
"je 2f\n\t"
|
||||
"stosb\n"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1)
|
||||
:"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
|
||||
:"memory");
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Added by Gertjan van Wingerde to make minix and sysv module work */
|
||||
#define __HAVE_ARCH_STRNLEN
|
||||
static inline size_t strnlen(const char * s, size_t count)
|
||||
{
|
||||
int d0;
|
||||
register int __res;
|
||||
__asm__ __volatile__(
|
||||
"movl %2,%0\n\t"
|
||||
"jmp 2f\n"
|
||||
"1:\tcmpb $0,(%0)\n\t"
|
||||
"je 3f\n\t"
|
||||
"incl %0\n"
|
||||
"2:\tdecl %1\n\t"
|
||||
"cmpl $-1,%1\n\t"
|
||||
"jne 1b\n"
|
||||
"3:\tsubl %2,%0"
|
||||
:"=a" (__res), "=&d" (d0)
|
||||
:"c" (s),"1" (count));
|
||||
return __res;
|
||||
}
|
||||
/* end of additional stuff */
|
||||
|
||||
//#define __HAVE_ARCH_STRSTR
|
||||
|
||||
//extern char *strstr(const char *cs, const char *ct);
|
||||
|
||||
/*
|
||||
* This looks horribly ugly, but the compiler can optimize it totally,
|
||||
* as we by now know that both pattern and count is constant..
|
||||
*/
|
||||
static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
|
||||
{
|
||||
switch (count) {
|
||||
case 0:
|
||||
return s;
|
||||
case 1:
|
||||
*(unsigned char *)s = pattern;
|
||||
return s;
|
||||
case 2:
|
||||
*(unsigned short *)s = pattern;
|
||||
return s;
|
||||
case 3:
|
||||
*(unsigned short *)s = pattern;
|
||||
*(2+(unsigned char *)s) = pattern;
|
||||
return s;
|
||||
case 4:
|
||||
*(unsigned long *)s = pattern;
|
||||
return s;
|
||||
}
|
||||
#define COMMON(x) \
|
||||
__asm__ __volatile__( \
|
||||
"rep ; stosl" \
|
||||
x \
|
||||
: "=&c" (d0), "=&D" (d1) \
|
||||
: "a" (pattern),"0" (count/4),"1" ((long) s) \
|
||||
: "memory")
|
||||
{
|
||||
int d0, d1;
|
||||
switch (count % 4) {
|
||||
case 0: COMMON(""); return s;
|
||||
case 1: COMMON("\n\tstosb"); return s;
|
||||
case 2: COMMON("\n\tstosw"); return s;
|
||||
default: COMMON("\n\tstosw\n\tstosb"); return s;
|
||||
}
|
||||
}
|
||||
|
||||
#undef COMMON
|
||||
}
|
||||
|
||||
#define __constant_c_x_memset(s, c, count) \
|
||||
(__builtin_constant_p(count) ? \
|
||||
__constant_c_and_count_memset((s),(c),(count)) : \
|
||||
__constant_c_memset((s),(c),(count)))
|
||||
|
||||
#define __memset(s, c, count) \
|
||||
(__builtin_constant_p(count) ? \
|
||||
__constant_count_memset((s),(c),(count)) : \
|
||||
__memset_generic((s),(c),(count)))
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
#define memset(s, c, count) \
|
||||
(__builtin_constant_p(c) ? \
|
||||
__constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \
|
||||
__memset((s),(c),(count)))
|
||||
|
||||
/*
|
||||
* find the first occurrence of byte 'c', or 1 past the area if none
|
||||
*/
|
||||
#define __HAVE_ARCH_MEMSCAN
|
||||
static inline void * memscan(void * addr, int c, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
return addr;
|
||||
__asm__("repnz; scasb\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"dec %%edi\n"
|
||||
"1:"
|
||||
: "=D" (addr), "=c" (size)
|
||||
: "0" (addr), "1" (size), "a" (c));
|
||||
return addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef _X86_64_STRING_H_
|
||||
#define _X86_64_STRING_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define struct_cpy(x,y) (*(x)=*(y))
|
||||
|
||||
/* Written 2002 by Andi Kleen */
|
||||
|
||||
/* Only used for special circumstances. Stolen from i386/string.h */
|
||||
static inline void * __inline_memcpy(void * to, const void * from, size_t n)
|
||||
{
|
||||
unsigned long d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"rep ; movsl\n\t"
|
||||
"testb $2,%b4\n\t"
|
||||
"je 1f\n\t"
|
||||
"movsw\n"
|
||||
"1:\ttestb $1,%b4\n\t"
|
||||
"je 2f\n\t"
|
||||
"movsb\n"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
|
||||
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
|
||||
: "memory");
|
||||
return (to);
|
||||
}
|
||||
|
||||
/* Even with __builtin_ the compiler may decide to use the out of line
|
||||
function. */
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY 1
|
||||
extern void *__memcpy(void *to, const void *from, size_t len);
|
||||
#define memcpy(dst,src,len) \
|
||||
({ size_t __len = (len); \
|
||||
void *__ret; \
|
||||
if (__builtin_constant_p(len) && __len >= 64) \
|
||||
__ret = __memcpy((dst),(src),__len); \
|
||||
else \
|
||||
__ret = __builtin_memcpy((dst),(src),__len); \
|
||||
__ret; })
|
||||
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
#define memset __builtin_memset
|
||||
|
||||
#define __HAVE_ARCH_MEMMOVE
|
||||
void * memmove(void * dest,const void *src,size_t count);
|
||||
|
||||
/* Use C out of line version for memcmp */
|
||||
#define memcmp __builtin_memcmp
|
||||
int memcmp(const void * cs,const void * ct,size_t count);
|
||||
|
||||
/* out of line string functions use always C versions */
|
||||
#define strlen __builtin_strlen
|
||||
size_t strlen(const char * s);
|
||||
|
||||
#define strcpy __builtin_strcpy
|
||||
char * strcpy(char * dest,const char *src);
|
||||
|
||||
#define strcat __builtin_strcat
|
||||
char * strcat(char * dest, const char * src);
|
||||
|
||||
#define strcmp __builtin_strcmp
|
||||
int strcmp(const char * cs,const char * ct);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
@@ -86,7 +86,7 @@ struct pfn_info
|
||||
#define PageSetSlab(page) ((void)0)
|
||||
#define PageClearSlab(page) ((void)0)
|
||||
|
||||
#define IS_XEN_HEAP_FRAME(_pfn) (page_to_phys(_pfn) < MAX_XENHEAP_ADDRESS)
|
||||
#define IS_XEN_HEAP_FRAME(_pfn) (page_to_phys(_pfn) < xenheap_phys_end)
|
||||
|
||||
#define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) \
|
||||
do { \
|
||||
@@ -104,7 +104,7 @@ extern struct list_head free_list;
|
||||
extern spinlock_t free_list_lock;
|
||||
extern unsigned int free_pfns;
|
||||
extern unsigned long max_page;
|
||||
void init_frametable(unsigned long nr_pages);
|
||||
void init_frametable(void *frametable_vstart, unsigned long nr_pages);
|
||||
void add_to_domain_alloc_list(unsigned long ps, unsigned long pe);
|
||||
|
||||
struct pfn_info *alloc_domain_page(struct domain *p);
|
||||
|
||||