mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.536 (3f9fd20aglcfc5h0kB1oldciJuy2dQ)
Many files: Modified blkdev and network interfaces to allow expedited flushing of pending request buffers.
This commit is contained in:
1 parent
042e1237bd
commit
35c6e9fc2e
19 files changed
+545
-484
No files matched your search
@@ -103,12 +103,13 @@ static inline int HYPERVISOR_set_callbacks(
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_net_update(void)
|
||||
static inline int HYPERVISOR_net_io_op(unsigned int op, unsigned int idx)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_net_update) );
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_net_io_op),
|
||||
"b" (op), "c" (idx) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -165,12 +166,13 @@ static inline int HYPERVISOR_network_op(void *network_op)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_block_io_op(void)
|
||||
static inline int HYPERVISOR_block_io_op(unsigned int op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_block_io_op) );
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_block_io_op),
|
||||
"b" (op) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#include <os.h>
|
||||
|
||||
/* Offsets in start_info structure */
|
||||
#define SHARED_INFO 4
|
||||
#define MOD_START 12
|
||||
#define MOD_LEN 16
|
||||
#define MOD_START 4
|
||||
#define MOD_LEN 8
|
||||
|
||||
#define ENTRY(X) .globl X ; X :
|
||||
|
||||
@@ -31,10 +30,10 @@ _start:
|
||||
|
||||
/* Clear BSS first so that there are no surprises... */
|
||||
2: xorl %eax,%eax
|
||||
movl $__bss_start,%edi
|
||||
movl $_end,%ecx
|
||||
subl %edi,%ecx
|
||||
rep stosb
|
||||
movl $__bss_start,%edi
|
||||
movl $_end,%ecx
|
||||
subl %edi,%ecx
|
||||
rep stosb
|
||||
|
||||
push %esi
|
||||
call start_kernel
|
||||
|
||||
@@ -230,12 +230,8 @@ static int setup_guestos(
|
||||
|
||||
alloc_index = tot_pages - 1;
|
||||
|
||||
/*
|
||||
* Count bottom-level PTs, rounding up. Include one PTE for shared info. We
|
||||
* therefore add 1024 because 1 is for shared_info, 1023 is to round up.
|
||||
*/
|
||||
num_pt_pages =
|
||||
(l1_table_offset(virt_load_addr) + tot_pages + 1024) / 1024;
|
||||
/* Count bottom-level PTs, rounding up. */
|
||||
num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
|
||||
|
||||
/* We must also count the page directory. */
|
||||
num_pt_pages++;
|
||||
@@ -250,7 +246,6 @@ static int setup_guestos(
|
||||
l2tab = page_array[alloc_index] << PAGE_SHIFT;
|
||||
alloc_index--;
|
||||
meminfo->l2_pgt_addr = l2tab;
|
||||
meminfo->virt_shinfo_addr = virt_load_addr + (tot_pages << PAGE_SHIFT);
|
||||
|
||||
/*
|
||||
* Pin down l2tab addr as page dir page - causes hypervisor to provide
|
||||
@@ -261,16 +256,12 @@ static int setup_guestos(
|
||||
pgt_updates++;
|
||||
num_pgt_updates++;
|
||||
|
||||
/*
|
||||
* Initialise the page tables. The final iteration is for the shared_info
|
||||
* PTE -- we break out before filling in the entry, as that is done by
|
||||
* Xen during final setup.
|
||||
*/
|
||||
/* Initialise the page tables. */
|
||||
if ( (vl2tab = map_pfn(l2tab >> PAGE_SHIFT)) == NULL )
|
||||
goto error_out;
|
||||
memset(vl2tab, 0, PAGE_SIZE);
|
||||
vl2e = vl2tab + l2_table_offset(virt_load_addr);
|
||||
for ( count = 0; count < (tot_pages + 1); count++ )
|
||||
for ( count = 0; count < tot_pages; count++ )
|
||||
{
|
||||
if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
|
||||
{
|
||||
@@ -291,9 +282,6 @@ static int setup_guestos(
|
||||
vl2e++;
|
||||
}
|
||||
|
||||
/* The last PTE we consider is filled in later by Xen. */
|
||||
if ( count == tot_pages ) break;
|
||||
|
||||
if ( count < pt_start )
|
||||
{
|
||||
pgt_updates->ptr = (unsigned long)vl1e;
|
||||
|
||||
@@ -710,7 +710,7 @@ ENTRY(hypervisor_call_table)
|
||||
.long SYMBOL_NAME(do_set_gdt)
|
||||
.long SYMBOL_NAME(do_stack_switch)
|
||||
.long SYMBOL_NAME(do_set_callbacks)
|
||||
.long SYMBOL_NAME(do_net_update)
|
||||
.long SYMBOL_NAME(do_net_io_op)
|
||||
.long SYMBOL_NAME(do_fpu_taskswitch)
|
||||
.long SYMBOL_NAME(do_yield)
|
||||
.long SYMBOL_NAME(kill_domain)
|
||||
|
||||
+11
-39
@@ -347,7 +347,6 @@ void release_task(struct task_struct *p)
|
||||
int final_setup_guestos(struct task_struct * p, dom_meminfo_t * meminfo)
|
||||
{
|
||||
l2_pgentry_t * l2tab;
|
||||
l1_pgentry_t * l1tab;
|
||||
start_info_t * virt_startinfo_addr;
|
||||
unsigned long virt_stack_addr;
|
||||
unsigned long phys_l2tab;
|
||||
@@ -374,19 +373,9 @@ int final_setup_guestos(struct task_struct * p, dom_meminfo_t * meminfo)
|
||||
p->mm.pagetable = mk_pagetable(phys_l2tab);
|
||||
unmap_domain_mem(l2tab);
|
||||
|
||||
/* map in the shared info structure */
|
||||
phys_l2tab = pagetable_val(p->mm.pagetable);
|
||||
l2tab = map_domain_mem(phys_l2tab);
|
||||
l2tab += l2_table_offset(meminfo->virt_shinfo_addr);
|
||||
l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
|
||||
l1tab += l1_table_offset(meminfo->virt_shinfo_addr);
|
||||
*l1tab = mk_l1_pgentry(__pa(p->shared_info) | L1_PROT);
|
||||
unmap_domain_mem((void *)((unsigned long)l2tab & PAGE_MASK));
|
||||
unmap_domain_mem((void *)((unsigned long)l1tab & PAGE_MASK));
|
||||
|
||||
/* set up the shared info structure */
|
||||
update_dom_time(p->shared_info);
|
||||
p->shared_info->domain_time = 0;
|
||||
p->shared_info->domain_time = 0;
|
||||
|
||||
/* we pass start info struct to guest os as function parameter on stack */
|
||||
virt_startinfo_addr = (start_info_t *)meminfo->virt_startinfo_addr;
|
||||
@@ -401,7 +390,7 @@ int final_setup_guestos(struct task_struct * p, dom_meminfo_t * meminfo)
|
||||
|
||||
memset(virt_startinfo_addr, 0, sizeof(*virt_startinfo_addr));
|
||||
virt_startinfo_addr->nr_pages = p->tot_pages;
|
||||
virt_startinfo_addr->shared_info = (shared_info_t *)meminfo->virt_shinfo_addr;
|
||||
virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info);
|
||||
virt_startinfo_addr->pt_base = meminfo->virt_load_addr +
|
||||
((p->tot_pages - 1) << PAGE_SHIFT);
|
||||
|
||||
@@ -474,7 +463,7 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
|
||||
int i, dom = p->domain;
|
||||
unsigned long phys_l1tab, phys_l2tab;
|
||||
unsigned long cur_address, alloc_address;
|
||||
unsigned long virt_load_address, virt_stack_address, virt_shinfo_address;
|
||||
unsigned long virt_load_address, virt_stack_address;
|
||||
start_info_t *virt_startinfo_address;
|
||||
unsigned long count;
|
||||
unsigned long alloc_index;
|
||||
@@ -551,16 +540,11 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
|
||||
memset(l2tab, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE*sizeof(l2_pgentry_t));
|
||||
p->mm.pagetable = mk_pagetable(phys_l2tab);
|
||||
|
||||
/*
|
||||
* NB. The upper limit on this loop does one extra page. This is to make
|
||||
* sure a pte exists when we want to map the shared_info struct.
|
||||
*/
|
||||
|
||||
l2tab += l2_table_offset(virt_load_address);
|
||||
cur_address = list_entry(p->pg_head.next, struct pfn_info, list) -
|
||||
frame_table;
|
||||
cur_address <<= PAGE_SHIFT;
|
||||
for ( count = 0; count < p->tot_pages + 1; count++ )
|
||||
for ( count = 0; count < p->tot_pages; count++ )
|
||||
{
|
||||
if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) )
|
||||
{
|
||||
@@ -574,14 +558,11 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
|
||||
}
|
||||
*l1tab++ = mk_l1_pgentry(cur_address|L1_PROT);
|
||||
|
||||
if ( count < p->tot_pages )
|
||||
{
|
||||
page = frame_table + (cur_address >> PAGE_SHIFT);
|
||||
page->flags = dom | PGT_writeable_page | PG_need_flush;
|
||||
page->type_count = page->tot_count = 1;
|
||||
/* Set up the MPT entry. */
|
||||
machine_to_phys_mapping[cur_address >> PAGE_SHIFT] = count;
|
||||
}
|
||||
page = frame_table + (cur_address >> PAGE_SHIFT);
|
||||
page->flags = dom | PGT_writeable_page | PG_need_flush;
|
||||
page->type_count = page->tot_count = 1;
|
||||
/* Set up the MPT entry. */
|
||||
machine_to_phys_mapping[cur_address >> PAGE_SHIFT] = count;
|
||||
|
||||
list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
|
||||
cur_address = list_entry(list_ent, struct pfn_info, list) -
|
||||
@@ -630,17 +611,9 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
|
||||
page->flags = dom | PGT_l2_page_table;
|
||||
unmap_domain_mem(l1start);
|
||||
|
||||
/* Map in the the shared info structure. */
|
||||
virt_shinfo_address = virt_load_address + (p->tot_pages << PAGE_SHIFT);
|
||||
l2tab = l2start + l2_table_offset(virt_shinfo_address);
|
||||
l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
|
||||
l1tab += l1_table_offset(virt_shinfo_address);
|
||||
*l1tab = mk_l1_pgentry(__pa(p->shared_info)|L1_PROT);
|
||||
unmap_domain_mem(l1start);
|
||||
|
||||
/* Set up shared info area. */
|
||||
update_dom_time(p->shared_info);
|
||||
p->shared_info->domain_time = 0;
|
||||
p->shared_info->domain_time = 0;
|
||||
|
||||
virt_startinfo_address = (start_info_t *)
|
||||
(virt_load_address + ((alloc_index - 1) << PAGE_SHIFT));
|
||||
@@ -671,8 +644,7 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
|
||||
/* Set up start info area. */
|
||||
memset(virt_startinfo_address, 0, sizeof(*virt_startinfo_address));
|
||||
virt_startinfo_address->nr_pages = p->tot_pages;
|
||||
virt_startinfo_address->shared_info =
|
||||
(shared_info_t *)virt_shinfo_address;
|
||||
virt_startinfo_address->shared_info = virt_to_phys(p->shared_info);
|
||||
virt_startinfo_address->pt_base = virt_load_address +
|
||||
((p->tot_pages - 1) << PAGE_SHIFT);
|
||||
|
||||
|
||||
+3
-33
@@ -159,40 +159,10 @@ net_vif_t *create_net_vif(int domain)
|
||||
|
||||
void destroy_net_vif(net_vif_t *vif)
|
||||
{
|
||||
int i;
|
||||
unsigned long *pte, flags;
|
||||
struct pfn_info *page;
|
||||
extern long flush_bufs_for_vif(net_vif_t *vif);
|
||||
struct task_struct *p = vif->domain;
|
||||
|
||||
/* Return any outstanding receive buffers to the guest OS. */
|
||||
spin_lock_irqsave(&p->page_lock, flags);
|
||||
for ( i = vif->rx_cons; i != vif->rx_prod; i = ((i+1) & (RX_RING_SIZE-1)) )
|
||||
{
|
||||
rx_shadow_entry_t *rx = vif->rx_shadow_ring + i;
|
||||
|
||||
/* Release the page-table page. */
|
||||
page = frame_table + (rx->pte_ptr >> PAGE_SHIFT);
|
||||
put_page_type(page);
|
||||
put_page_tot(page);
|
||||
|
||||
/* Give the buffer page back to the domain. */
|
||||
page = frame_table + rx->buf_pfn;
|
||||
list_add(&page->list, &p->pg_head);
|
||||
page->flags = vif->domain->domain;
|
||||
|
||||
/* Patch up the PTE if it hasn't changed under our feet. */
|
||||
pte = map_domain_mem(rx->pte_ptr);
|
||||
if ( !(*pte & _PAGE_PRESENT) )
|
||||
{
|
||||
*pte = (rx->buf_pfn<<PAGE_SHIFT) | (*pte & ~PAGE_MASK) |
|
||||
_PAGE_RW | _PAGE_PRESENT;
|
||||
page->flags |= PGT_writeable_page | PG_need_flush;
|
||||
page->type_count = page->tot_count = 1;
|
||||
}
|
||||
unmap_domain_mem(pte);
|
||||
}
|
||||
spin_unlock_irqrestore(&p->page_lock, flags);
|
||||
|
||||
(void)flush_bufs_for_vif(vif);
|
||||
UNSHARE_PFN(virt_to_page(vif->shared_rings));
|
||||
kmem_cache_free(net_vif_cache, vif);
|
||||
put_task_struct(p);
|
||||
}
|
||||
|
||||
@@ -241,11 +241,26 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate)
|
||||
* GUEST-OS SYSCALL -- Indicates there are requests outstanding.
|
||||
*/
|
||||
|
||||
long do_block_io_op(void)
|
||||
long do_block_io_op(unsigned int op)
|
||||
{
|
||||
add_to_blkdev_list_tail(current);
|
||||
maybe_trigger_io_schedule();
|
||||
return 0L;
|
||||
long ret = 0;
|
||||
|
||||
switch ( op )
|
||||
{
|
||||
case BLKOP_PUSH_BUFFERS:
|
||||
add_to_blkdev_list_tail(current);
|
||||
maybe_trigger_io_schedule();
|
||||
break;
|
||||
|
||||
case BLKOP_FLUSH_BUFFERS:
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
#ifndef __BLOCK_H__
|
||||
#define __BLOCK_H__
|
||||
|
||||
/*
|
||||
* Command values for block_io_op()
|
||||
*/
|
||||
|
||||
#define BLKOP_PUSH_BUFFERS 0 /* Notify Xen of new requests on the ring. */
|
||||
#define BLKOP_FLUSH_BUFFERS 1 /* Flush all pending request buffers. */
|
||||
|
||||
|
||||
/*
|
||||
* Device numbers
|
||||
*/
|
||||
|
||||
@@ -57,7 +57,6 @@ typedef struct domain_launch
|
||||
unsigned int domain;
|
||||
unsigned long l2_pgt_addr;
|
||||
unsigned long virt_load_addr;
|
||||
unsigned long virt_shinfo_addr;
|
||||
unsigned long virt_startinfo_addr;
|
||||
unsigned int num_vifs;
|
||||
char cmd_line[MAX_CMD_LEN];
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
* NB. The reserved range is inclusive (that is, both FIRST_RESERVED_GDT_ENTRY
|
||||
* and LAST_RESERVED_GDT_ENTRY are reserved).
|
||||
*/
|
||||
#define NR_RESERVED_GDT_ENTRIES 40
|
||||
#define FIRST_RESERVED_GDT_ENTRY 256
|
||||
#define LAST_RESERVED_GDT_ENTRY \
|
||||
#define NR_RESERVED_GDT_ENTRIES 40
|
||||
#define FIRST_RESERVED_GDT_ENTRY 256
|
||||
#define LAST_RESERVED_GDT_ENTRY \
|
||||
(FIRST_RESERVED_GDT_ENTRY + NR_RESERVED_GDT_ENTRIES - 1)
|
||||
|
||||
/*
|
||||
@@ -29,10 +29,10 @@
|
||||
* are also present in the initial GDT, many OSes will be able to avoid
|
||||
* installing their own GDT.
|
||||
*/
|
||||
#define FLAT_RING1_CS 0x0819
|
||||
#define FLAT_RING1_DS 0x0821
|
||||
#define FLAT_RING3_CS 0x082b
|
||||
#define FLAT_RING3_DS 0x0833
|
||||
#define FLAT_RING1_CS 0x0819
|
||||
#define FLAT_RING1_DS 0x0821
|
||||
#define FLAT_RING3_CS 0x082b
|
||||
#define FLAT_RING3_DS 0x0833
|
||||
|
||||
|
||||
/*
|
||||
@@ -40,25 +40,25 @@
|
||||
*/
|
||||
|
||||
/* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */
|
||||
#define __HYPERVISOR_set_trap_table 0
|
||||
#define __HYPERVISOR_mmu_update 1
|
||||
#define __HYPERVISOR_console_write 2
|
||||
#define __HYPERVISOR_set_gdt 3
|
||||
#define __HYPERVISOR_set_trap_table 0
|
||||
#define __HYPERVISOR_mmu_update 1
|
||||
#define __HYPERVISOR_console_write 2
|
||||
#define __HYPERVISOR_set_gdt 3
|
||||
#define __HYPERVISOR_stack_switch 4
|
||||
#define __HYPERVISOR_set_callbacks 5
|
||||
#define __HYPERVISOR_net_update 6
|
||||
#define __HYPERVISOR_fpu_taskswitch 7
|
||||
#define __HYPERVISOR_yield 8
|
||||
#define __HYPERVISOR_exit 9
|
||||
#define __HYPERVISOR_dom0_op 10
|
||||
#define __HYPERVISOR_network_op 11
|
||||
#define __HYPERVISOR_block_io_op 12
|
||||
#define __HYPERVISOR_set_debugreg 13
|
||||
#define __HYPERVISOR_get_debugreg 14
|
||||
#define __HYPERVISOR_update_descriptor 15
|
||||
#define __HYPERVISOR_set_fast_trap 16
|
||||
#define __HYPERVISOR_dom_mem_op 17
|
||||
#define __HYPERVISOR_multicall 18
|
||||
#define __HYPERVISOR_net_io_op 6
|
||||
#define __HYPERVISOR_fpu_taskswitch 7
|
||||
#define __HYPERVISOR_yield 8
|
||||
#define __HYPERVISOR_exit 9
|
||||
#define __HYPERVISOR_dom0_op 10
|
||||
#define __HYPERVISOR_network_op 11
|
||||
#define __HYPERVISOR_block_io_op 12
|
||||
#define __HYPERVISOR_set_debugreg 13
|
||||
#define __HYPERVISOR_get_debugreg 14
|
||||
#define __HYPERVISOR_update_descriptor 15
|
||||
#define __HYPERVISOR_set_fast_trap 16
|
||||
#define __HYPERVISOR_dom_mem_op 17
|
||||
#define __HYPERVISOR_multicall 18
|
||||
#define __HYPERVISOR_kbd_op 19
|
||||
#define __HYPERVISOR_update_va_mapping 20
|
||||
|
||||
@@ -276,19 +276,19 @@ typedef struct shared_info_st {
|
||||
* NB. We expect that this struct is smaller than a page.
|
||||
*/
|
||||
typedef struct start_info_st {
|
||||
unsigned long nr_pages; /* total pages allocated to this domain */
|
||||
shared_info_t *shared_info; /* VIRTUAL address of shared info struct */
|
||||
unsigned long pt_base; /* VIRTUAL address of page directory */
|
||||
unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
|
||||
unsigned long mod_len; /* size (bytes) of pre-loaded module */
|
||||
/* Machine address of net rings for each VIF. Will be page aligned. */
|
||||
unsigned long net_rings[MAX_DOMAIN_VIFS];
|
||||
unsigned char net_vmac[MAX_DOMAIN_VIFS][6];
|
||||
/* Machine address of block-device ring. Will be page aligned. */
|
||||
unsigned long blk_ring;
|
||||
unsigned int dom_id;
|
||||
unsigned long flags;
|
||||
unsigned char cmd_line[1]; /* variable-length */
|
||||
/* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
|
||||
unsigned long pt_base; /* VIRTUAL address of page directory. */
|
||||
unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */
|
||||
unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
|
||||
/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
|
||||
unsigned long nr_pages; /* total pages allocated to this domain. */
|
||||
unsigned long shared_info; /* MACHINE address of shared info struct.*/
|
||||
unsigned int dom_id; /* Domain identifier. */
|
||||
unsigned long flags; /* SIF_xxx flags. */
|
||||
unsigned long net_rings[MAX_DOMAIN_VIFS]; /* MACHINE address of ring.*/
|
||||
unsigned char net_vmac[MAX_DOMAIN_VIFS][6]; /* MAC address of VIF. */
|
||||
unsigned long blk_ring; /* MACHINE address of blkdev ring. */
|
||||
unsigned char cmd_line[1]; /* Variable-length options. */
|
||||
} start_info_t;
|
||||
|
||||
/* These flags are passed in the 'flags' field of start_info_t. */
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
#ifndef __RING_H__
|
||||
#define __RING_H__
|
||||
|
||||
/*
|
||||
* Command values for block_io_op()
|
||||
*/
|
||||
|
||||
#define NETOP_PUSH_BUFFERS 0 /* Notify Xen of new buffers on the rings. */
|
||||
#define NETOP_FLUSH_BUFFERS 1 /* Flush all pending request buffers. */
|
||||
|
||||
|
||||
typedef struct tx_req_entry_st
|
||||
{
|
||||
unsigned short id;
|
||||
|
||||
+202
-110
@@ -1877,7 +1877,7 @@ static int get_tx_bufs(net_vif_t *vif)
|
||||
tx = shared_rings->tx_ring[i].req;
|
||||
target = VIF_DROP;
|
||||
|
||||
if ( (tx.size < PKT_PROT_LEN) || (tx.size > ETH_FRAME_LEN) )
|
||||
if ( (tx.size <= PKT_PROT_LEN) || (tx.size > ETH_FRAME_LEN) )
|
||||
{
|
||||
DPRINTK("Bad packet size: %d\n", tx.size);
|
||||
__make_tx_response(vif, tx.id, RING_STATUS_BAD_PAGE);
|
||||
@@ -2019,130 +2019,222 @@ static int get_tx_bufs(net_vif_t *vif)
|
||||
}
|
||||
|
||||
|
||||
static long get_bufs_from_vif(net_vif_t *vif)
|
||||
{
|
||||
net_ring_t *shared_rings;
|
||||
net_idx_t *shared_idxs;
|
||||
unsigned int i, j;
|
||||
rx_req_entry_t rx;
|
||||
unsigned long pte_pfn, buf_pfn;
|
||||
struct pfn_info *pte_page, *buf_page;
|
||||
struct task_struct *p = vif->domain;
|
||||
unsigned long *ptep;
|
||||
|
||||
shared_idxs = vif->shared_idxs;
|
||||
shared_rings = vif->shared_rings;
|
||||
|
||||
/*
|
||||
* PHASE 1 -- TRANSMIT RING
|
||||
*/
|
||||
|
||||
if ( get_tx_bufs(vif) )
|
||||
{
|
||||
add_to_net_schedule_list_tail(vif);
|
||||
maybe_schedule_tx_action();
|
||||
}
|
||||
|
||||
/*
|
||||
* PHASE 2 -- RECEIVE RING
|
||||
*/
|
||||
|
||||
/*
|
||||
* Collect up new receive buffers. We collect up to the guest OS's new
|
||||
* producer index, but take care not to catch up with our own consumer
|
||||
* index.
|
||||
*/
|
||||
j = vif->rx_prod;
|
||||
for ( i = vif->rx_req_cons;
|
||||
(i != shared_idxs->rx_req_prod) &&
|
||||
(((vif->rx_resp_prod-i) & (RX_RING_SIZE-1)) != 1);
|
||||
i = RX_RING_INC(i) )
|
||||
{
|
||||
rx = shared_rings->rx_ring[i].req;
|
||||
|
||||
pte_pfn = rx.addr >> PAGE_SHIFT;
|
||||
pte_page = frame_table + pte_pfn;
|
||||
|
||||
spin_lock_irq(&p->page_lock);
|
||||
if ( (pte_pfn >= max_page) ||
|
||||
((pte_page->flags & (PG_type_mask | PG_domain_mask)) !=
|
||||
(PGT_l1_page_table | p->domain)) )
|
||||
{
|
||||
DPRINTK("Bad page frame for ppte %d,%08lx,%08lx,%08lx\n",
|
||||
p->domain, pte_pfn, max_page, pte_page->flags);
|
||||
spin_unlock_irq(&p->page_lock);
|
||||
make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
ptep = map_domain_mem(rx.addr);
|
||||
|
||||
if ( !(*ptep & _PAGE_PRESENT) )
|
||||
{
|
||||
DPRINTK("Invalid PTE passed down (not present)\n");
|
||||
make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
|
||||
goto rx_unmap_and_continue;
|
||||
}
|
||||
|
||||
buf_pfn = *ptep >> PAGE_SHIFT;
|
||||
buf_page = frame_table + buf_pfn;
|
||||
|
||||
if ( ((buf_page->flags & (PG_type_mask | PG_domain_mask)) !=
|
||||
(PGT_writeable_page | p->domain)) ||
|
||||
(buf_page->tot_count != 1) )
|
||||
{
|
||||
DPRINTK("Need a mapped-once writeable page (%ld/%ld/%08lx)\n",
|
||||
buf_page->type_count, buf_page->tot_count,
|
||||
buf_page->flags);
|
||||
make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
|
||||
goto rx_unmap_and_continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* The pte they passed was good, so take it away from them. We also
|
||||
* lock down the page-table page, so it doesn't go away.
|
||||
*/
|
||||
get_page_type(pte_page);
|
||||
get_page_tot(pte_page);
|
||||
*ptep &= ~_PAGE_PRESENT;
|
||||
buf_page->flags = buf_page->type_count = buf_page->tot_count = 0;
|
||||
list_del(&buf_page->list);
|
||||
|
||||
vif->rx_shadow_ring[j].id = rx.id;
|
||||
vif->rx_shadow_ring[j].pte_ptr = rx.addr;
|
||||
vif->rx_shadow_ring[j].buf_pfn = buf_pfn;
|
||||
vif->rx_shadow_ring[j].flush_count = (unsigned short)
|
||||
atomic_read(&tlb_flush_count[smp_processor_id()]);
|
||||
j = RX_RING_INC(j);
|
||||
|
||||
rx_unmap_and_continue:
|
||||
unmap_domain_mem(ptep);
|
||||
spin_unlock_irq(&p->page_lock);
|
||||
}
|
||||
|
||||
vif->rx_req_cons = i;
|
||||
|
||||
if ( vif->rx_prod != j )
|
||||
{
|
||||
smp_mb(); /* Let other CPUs see new descriptors first. */
|
||||
vif->rx_prod = j;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long flush_bufs_for_vif(net_vif_t *vif)
|
||||
{
|
||||
int i;
|
||||
unsigned long *pte, flags;
|
||||
struct pfn_info *page;
|
||||
struct task_struct *p = vif->domain;
|
||||
rx_shadow_entry_t *rx;
|
||||
net_ring_t *shared_rings = vif->shared_rings;
|
||||
net_idx_t *shared_idxs = vif->shared_idxs;
|
||||
|
||||
/* Return any outstanding receive buffers to the guest OS. */
|
||||
spin_lock_irqsave(&p->page_lock, flags);
|
||||
for ( i = vif->rx_req_cons;
|
||||
(i != shared_idxs->rx_req_prod) &&
|
||||
(((vif->rx_resp_prod-i) & (RX_RING_SIZE-1)) != 1);
|
||||
i = RX_RING_INC(i) )
|
||||
{
|
||||
make_rx_response(vif, shared_rings->rx_ring[i].req.id, 0,
|
||||
RING_STATUS_DROPPED, 0);
|
||||
}
|
||||
vif->rx_req_cons = i;
|
||||
for ( i = vif->rx_cons; i != vif->rx_prod; i = RX_RING_INC(i) )
|
||||
{
|
||||
rx = &vif->rx_shadow_ring[i];
|
||||
|
||||
/* Release the page-table page. */
|
||||
page = frame_table + (rx->pte_ptr >> PAGE_SHIFT);
|
||||
put_page_type(page);
|
||||
put_page_tot(page);
|
||||
|
||||
/* Give the buffer page back to the domain. */
|
||||
page = frame_table + rx->buf_pfn;
|
||||
list_add(&page->list, &p->pg_head);
|
||||
page->flags = vif->domain->domain;
|
||||
|
||||
/* Patch up the PTE if it hasn't changed under our feet. */
|
||||
pte = map_domain_mem(rx->pte_ptr);
|
||||
if ( !(*pte & _PAGE_PRESENT) )
|
||||
{
|
||||
*pte = (rx->buf_pfn<<PAGE_SHIFT) | (*pte & ~PAGE_MASK) |
|
||||
_PAGE_RW | _PAGE_PRESENT;
|
||||
page->flags |= PGT_writeable_page | PG_need_flush;
|
||||
page->type_count = page->tot_count = 1;
|
||||
}
|
||||
unmap_domain_mem(pte);
|
||||
|
||||
make_rx_response(vif, rx->id, 0, RING_STATUS_DROPPED, 0);
|
||||
}
|
||||
vif->rx_cons = i;
|
||||
spin_unlock_irqrestore(&p->page_lock, flags);
|
||||
|
||||
/*
|
||||
* Flush pending transmit buffers. The guest may still have to wait for
|
||||
* buffers that are queued at a physical NIC.
|
||||
*/
|
||||
spin_lock_irqsave(&vif->tx_lock, flags);
|
||||
for ( i = vif->tx_req_cons;
|
||||
(i != shared_idxs->tx_req_prod) &&
|
||||
(((vif->tx_resp_prod-i) & (TX_RING_SIZE-1)) != 1);
|
||||
i = TX_RING_INC(i) )
|
||||
{
|
||||
__make_tx_response(vif, shared_rings->tx_ring[i].req.id,
|
||||
RING_STATUS_DROPPED);
|
||||
}
|
||||
vif->tx_req_cons = i;
|
||||
spin_unlock_irqrestore(&vif->tx_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do_net_update:
|
||||
* do_net_io_op:
|
||||
*
|
||||
* Called from guest OS to notify updates to its transmit and/or receive
|
||||
* descriptor rings.
|
||||
*/
|
||||
|
||||
long do_net_update(void)
|
||||
long do_net_io_op(unsigned int op, unsigned int idx)
|
||||
{
|
||||
net_ring_t *shared_rings;
|
||||
net_vif_t *vif;
|
||||
net_idx_t *shared_idxs;
|
||||
unsigned int i, j, idx;
|
||||
rx_req_entry_t rx;
|
||||
unsigned long pte_pfn, buf_pfn;
|
||||
struct pfn_info *pte_page, *buf_page;
|
||||
unsigned long *ptep;
|
||||
long ret;
|
||||
|
||||
perfc_incr(net_hypercalls);
|
||||
|
||||
for ( idx = 0; idx < MAX_DOMAIN_VIFS; idx++ )
|
||||
if ( (vif = current->net_vif_list[idx]) == NULL )
|
||||
return -EINVAL;
|
||||
|
||||
switch ( op )
|
||||
{
|
||||
if ( (vif = current->net_vif_list[idx]) == NULL )
|
||||
break;
|
||||
case NETOP_PUSH_BUFFERS:
|
||||
ret = get_bufs_from_vif(vif);
|
||||
break;
|
||||
|
||||
shared_idxs = vif->shared_idxs;
|
||||
shared_rings = vif->shared_rings;
|
||||
|
||||
/*
|
||||
* PHASE 1 -- TRANSMIT RING
|
||||
*/
|
||||
case NETOP_FLUSH_BUFFERS:
|
||||
ret = flush_bufs_for_vif(vif);
|
||||
break;
|
||||
|
||||
if ( get_tx_bufs(vif) )
|
||||
{
|
||||
add_to_net_schedule_list_tail(vif);
|
||||
maybe_schedule_tx_action();
|
||||
}
|
||||
|
||||
/*
|
||||
* PHASE 2 -- RECEIVE RING
|
||||
*/
|
||||
|
||||
/*
|
||||
* Collect up new receive buffers. We collect up to the guest OS's
|
||||
* new producer index, but take care not to catch up with our own
|
||||
* consumer index.
|
||||
*/
|
||||
j = vif->rx_prod;
|
||||
for ( i = vif->rx_req_cons;
|
||||
(i != shared_idxs->rx_req_prod) &&
|
||||
(((vif->rx_resp_prod-i) & (RX_RING_SIZE-1)) != 1);
|
||||
i = RX_RING_INC(i) )
|
||||
{
|
||||
rx = shared_rings->rx_ring[i].req;
|
||||
|
||||
pte_pfn = rx.addr >> PAGE_SHIFT;
|
||||
pte_page = frame_table + pte_pfn;
|
||||
|
||||
spin_lock_irq(¤t->page_lock);
|
||||
if ( (pte_pfn >= max_page) ||
|
||||
((pte_page->flags & (PG_type_mask | PG_domain_mask)) !=
|
||||
(PGT_l1_page_table | current->domain)) )
|
||||
{
|
||||
DPRINTK("Bad page frame for ppte %d,%08lx,%08lx,%08lx\n",
|
||||
current->domain, pte_pfn, max_page, pte_page->flags);
|
||||
spin_unlock_irq(¤t->page_lock);
|
||||
make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
ptep = map_domain_mem(rx.addr);
|
||||
|
||||
if ( !(*ptep & _PAGE_PRESENT) )
|
||||
{
|
||||
DPRINTK("Invalid PTE passed down (not present)\n");
|
||||
make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
|
||||
goto rx_unmap_and_continue;
|
||||
}
|
||||
|
||||
buf_pfn = *ptep >> PAGE_SHIFT;
|
||||
buf_page = frame_table + buf_pfn;
|
||||
|
||||
if ( ((buf_page->flags & (PG_type_mask | PG_domain_mask)) !=
|
||||
(PGT_writeable_page | current->domain)) ||
|
||||
(buf_page->tot_count != 1) )
|
||||
{
|
||||
DPRINTK("Need a mapped-once writeable page (%ld/%ld/%08lx)\n",
|
||||
buf_page->type_count, buf_page->tot_count, buf_page->flags);
|
||||
make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
|
||||
goto rx_unmap_and_continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* The pte they passed was good, so take it away from them. We
|
||||
* also lock down the page-table page, so it doesn't go away.
|
||||
*/
|
||||
get_page_type(pte_page);
|
||||
get_page_tot(pte_page);
|
||||
*ptep &= ~_PAGE_PRESENT;
|
||||
buf_page->flags = buf_page->type_count = buf_page->tot_count = 0;
|
||||
list_del(&buf_page->list);
|
||||
|
||||
vif->rx_shadow_ring[j].id = rx.id;
|
||||
vif->rx_shadow_ring[j].pte_ptr = rx.addr;
|
||||
vif->rx_shadow_ring[j].buf_pfn = buf_pfn;
|
||||
vif->rx_shadow_ring[j].flush_count = (unsigned short)
|
||||
atomic_read(&tlb_flush_count[smp_processor_id()]);
|
||||
j = RX_RING_INC(j);
|
||||
|
||||
rx_unmap_and_continue:
|
||||
unmap_domain_mem(ptep);
|
||||
spin_unlock_irq(¤t->page_lock);
|
||||
}
|
||||
|
||||
vif->rx_req_cons = i;
|
||||
|
||||
if ( vif->rx_prod != j )
|
||||
{
|
||||
smp_mb(); /* Let other CPUs see new descriptors first. */
|
||||
vif->rx_prod = j;
|
||||
}
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ static inline void signal_requests_to_xen(void)
|
||||
{
|
||||
DISABLE_SCATTERGATHER();
|
||||
blk_ring->req_prod = req_prod;
|
||||
HYPERVISOR_block_io_op();
|
||||
HYPERVISOR_block_io_op(BLKOP_PUSH_BUFFERS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
/* Batch Xen notifications. */
|
||||
if ( np->rx_bufs_to_notify > (RX_MAX_ENTRIES/4) )
|
||||
{
|
||||
HYPERVISOR_net_update();
|
||||
HYPERVISOR_net_io_op(NETOP_PUSH_BUFFERS, np->idx);
|
||||
np->rx_bufs_to_notify = 0;
|
||||
}
|
||||
}
|
||||
@@ -322,7 +322,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Only notify Xen if there are no outstanding responses. */
|
||||
mb();
|
||||
if ( np->net_idx->tx_resp_prod == i )
|
||||
HYPERVISOR_net_update();
|
||||
HYPERVISOR_net_io_op(NETOP_PUSH_BUFFERS, np->idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#include <asm/desc.h>
|
||||
|
||||
/* Offsets in start_info structure */
|
||||
#define SHARED_INFO 4
|
||||
#define MOD_START 12
|
||||
#define MOD_LEN 16
|
||||
#define MOD_START 4
|
||||
#define MOD_LEN 8
|
||||
|
||||
startup_32:
|
||||
cld
|
||||
@@ -35,19 +34,16 @@ startup_32:
|
||||
|
||||
/* Clear BSS first so that there are no surprises... */
|
||||
2: xorl %eax,%eax
|
||||
movl $SYMBOL_NAME(__bss_start),%edi
|
||||
movl $SYMBOL_NAME(_end),%ecx
|
||||
subl %edi,%ecx
|
||||
rep stosb
|
||||
movl $SYMBOL_NAME(__bss_start),%edi
|
||||
movl $SYMBOL_NAME(_end),%ecx
|
||||
subl %edi,%ecx
|
||||
rep stosb
|
||||
|
||||
/* Copy the necessary stuff from start_info structure. */
|
||||
/* We need to copy shared_info early, so that sti/cli work */
|
||||
mov SHARED_INFO(%esi),%eax
|
||||
mov %eax,SYMBOL_NAME(HYPERVISOR_shared_info)
|
||||
mov $SYMBOL_NAME(start_info_union),%edi
|
||||
mov $128,%ecx
|
||||
rep movsl
|
||||
|
||||
|
||||
jmp SYMBOL_NAME(start_kernel)
|
||||
|
||||
ENTRY(stack_start)
|
||||
|
||||
@@ -46,7 +46,11 @@
|
||||
#include <asm/hypervisor.h>
|
||||
#include <asm/hypervisor-ifs/dom0_ops.h>
|
||||
|
||||
shared_info_t *HYPERVISOR_shared_info;
|
||||
/*
|
||||
* Point at the empty zero page to start with. We map the real shared_info
|
||||
* page as soon as fixmap is up and running.
|
||||
*/
|
||||
shared_info_t *HYPERVISOR_shared_info = empty_zero_page;
|
||||
|
||||
unsigned long *phys_to_machine_mapping;
|
||||
|
||||
|
||||
@@ -43,50 +43,50 @@ static unsigned long totalhigh_pages;
|
||||
|
||||
int do_check_pgt_cache(int low, int high)
|
||||
{
|
||||
int freed = 0;
|
||||
if(pgtable_cache_size > high) {
|
||||
do {
|
||||
int freed = 0;
|
||||
if(pgtable_cache_size > high) {
|
||||
do {
|
||||
if (!QUICKLIST_EMPTY(pgd_quicklist)) {
|
||||
free_pgd_slow(get_pgd_fast());
|
||||
freed++;
|
||||
}
|
||||
free_pgd_slow(get_pgd_fast());
|
||||
freed++;
|
||||
}
|
||||
if (!QUICKLIST_EMPTY(pte_quicklist)) {
|
||||
pte_free_slow(pte_alloc_one_fast(NULL, 0));
|
||||
freed++;
|
||||
}
|
||||
} while(pgtable_cache_size > low);
|
||||
}
|
||||
return freed;
|
||||
pte_free_slow(pte_alloc_one_fast(NULL, 0));
|
||||
freed++;
|
||||
}
|
||||
} while(pgtable_cache_size > low);
|
||||
}
|
||||
return freed;
|
||||
}
|
||||
|
||||
void show_mem(void)
|
||||
{
|
||||
int i, total = 0, reserved = 0;
|
||||
int shared = 0, cached = 0;
|
||||
int highmem = 0;
|
||||
int i, total = 0, reserved = 0;
|
||||
int shared = 0, cached = 0;
|
||||
int highmem = 0;
|
||||
|
||||
printk("Mem-info:\n");
|
||||
show_free_areas();
|
||||
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
|
||||
i = max_mapnr;
|
||||
while (i-- > 0) {
|
||||
total++;
|
||||
if (PageHighMem(mem_map+i))
|
||||
highmem++;
|
||||
if (PageReserved(mem_map+i))
|
||||
reserved++;
|
||||
else if (PageSwapCache(mem_map+i))
|
||||
cached++;
|
||||
else if (page_count(mem_map+i))
|
||||
shared += page_count(mem_map+i) - 1;
|
||||
}
|
||||
printk("%d pages of RAM\n", total);
|
||||
printk("%d pages of HIGHMEM\n",highmem);
|
||||
printk("%d reserved pages\n",reserved);
|
||||
printk("%d pages shared\n",shared);
|
||||
printk("%d pages swap cached\n",cached);
|
||||
printk("%ld pages in page table cache\n",pgtable_cache_size);
|
||||
show_buffers();
|
||||
printk("Mem-info:\n");
|
||||
show_free_areas();
|
||||
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
|
||||
i = max_mapnr;
|
||||
while (i-- > 0) {
|
||||
total++;
|
||||
if (PageHighMem(mem_map+i))
|
||||
highmem++;
|
||||
if (PageReserved(mem_map+i))
|
||||
reserved++;
|
||||
else if (PageSwapCache(mem_map+i))
|
||||
cached++;
|
||||
else if (page_count(mem_map+i))
|
||||
shared += page_count(mem_map+i) - 1;
|
||||
}
|
||||
printk("%d pages of RAM\n", total);
|
||||
printk("%d pages of HIGHMEM\n",highmem);
|
||||
printk("%d reserved pages\n",reserved);
|
||||
printk("%d pages shared\n",shared);
|
||||
printk("%d pages swap cached\n",cached);
|
||||
printk("%ld pages in page table cache\n",pgtable_cache_size);
|
||||
show_buffers();
|
||||
}
|
||||
|
||||
/* References to section boundaries */
|
||||
@@ -95,118 +95,118 @@ extern char _text, _etext, _edata, __bss_start, _end;
|
||||
extern char __init_begin, __init_end;
|
||||
|
||||
static inline void set_pte_phys (unsigned long vaddr,
|
||||
unsigned long phys, pgprot_t flags)
|
||||
unsigned long phys, pgprot_t flags)
|
||||
{
|
||||
pgprot_t prot;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
pgprot_t prot;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
pgd = init_mm.pgd + __pgd_offset(vaddr);
|
||||
if (pgd_none(*pgd)) {
|
||||
printk("PAE BUG #00!\n");
|
||||
return;
|
||||
}
|
||||
pmd = pmd_offset(pgd, vaddr);
|
||||
if (pmd_none(*pmd)) {
|
||||
printk("PAE BUG #01!\n");
|
||||
return;
|
||||
}
|
||||
pte = pte_offset(pmd, vaddr);
|
||||
pgd = init_mm.pgd + __pgd_offset(vaddr);
|
||||
if (pgd_none(*pgd)) {
|
||||
printk("PAE BUG #00!\n");
|
||||
return;
|
||||
}
|
||||
pmd = pmd_offset(pgd, vaddr);
|
||||
if (pmd_none(*pmd)) {
|
||||
printk("PAE BUG #01!\n");
|
||||
return;
|
||||
}
|
||||
pte = pte_offset(pmd, vaddr);
|
||||
|
||||
if (pte_val(*pte))
|
||||
pte_ERROR(*pte);
|
||||
if (pte_val(*pte))
|
||||
pte_ERROR(*pte);
|
||||
|
||||
pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags);
|
||||
pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags);
|
||||
|
||||
/* We queue directly, avoiding hidden phys->machine translation. */
|
||||
queue_l1_entry_update(pte, phys | pgprot_val(prot));
|
||||
/* We queue directly, avoiding hidden phys->machine translation. */
|
||||
queue_l1_entry_update(pte, phys | pgprot_val(prot));
|
||||
|
||||
/*
|
||||
* It's enough to flush this one mapping.
|
||||
* (PGE mappings get flushed as well)
|
||||
*/
|
||||
__flush_tlb_one(vaddr);
|
||||
/*
|
||||
* It's enough to flush this one mapping.
|
||||
* (PGE mappings get flushed as well)
|
||||
*/
|
||||
__flush_tlb_one(vaddr);
|
||||
}
|
||||
|
||||
void __set_fixmap (enum fixed_addresses idx, unsigned long phys,
|
||||
pgprot_t flags)
|
||||
{
|
||||
unsigned long address = __fix_to_virt(idx);
|
||||
unsigned long address = __fix_to_virt(idx);
|
||||
|
||||
if (idx >= __end_of_fixed_addresses) {
|
||||
printk("Invalid __set_fixmap\n");
|
||||
return;
|
||||
}
|
||||
set_pte_phys(address, phys, flags);
|
||||
if (idx >= __end_of_fixed_addresses) {
|
||||
printk("Invalid __set_fixmap\n");
|
||||
return;
|
||||
}
|
||||
set_pte_phys(address, phys, flags);
|
||||
}
|
||||
|
||||
static void __init fixrange_init (unsigned long start,
|
||||
unsigned long end, pgd_t *pgd_base)
|
||||
{
|
||||
pgd_t *pgd, *kpgd;
|
||||
pmd_t *pmd, *kpmd;
|
||||
pte_t *pte, *kpte;
|
||||
int i, j;
|
||||
unsigned long vaddr;
|
||||
pgd_t *pgd, *kpgd;
|
||||
pmd_t *pmd, *kpmd;
|
||||
pte_t *pte, *kpte;
|
||||
int i, j;
|
||||
unsigned long vaddr;
|
||||
|
||||
vaddr = start;
|
||||
i = __pgd_offset(vaddr);
|
||||
j = __pmd_offset(vaddr);
|
||||
pgd = pgd_base + i;
|
||||
vaddr = start;
|
||||
i = __pgd_offset(vaddr);
|
||||
j = __pmd_offset(vaddr);
|
||||
pgd = pgd_base + i;
|
||||
|
||||
for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
|
||||
for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
|
||||
#if CONFIG_X86_PAE
|
||||
if (pgd_none(*pgd)) {
|
||||
pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
set_pgd(pgd, __pgd(__pa(pmd) + 0x1));
|
||||
if (pmd != pmd_offset(pgd, 0))
|
||||
printk("PAE BUG #02!\n");
|
||||
}
|
||||
pmd = pmd_offset(pgd, vaddr);
|
||||
if (pgd_none(*pgd)) {
|
||||
pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
set_pgd(pgd, __pgd(__pa(pmd) + 0x1));
|
||||
if (pmd != pmd_offset(pgd, 0))
|
||||
printk("PAE BUG #02!\n");
|
||||
}
|
||||
pmd = pmd_offset(pgd, vaddr);
|
||||
#else
|
||||
pmd = (pmd_t *)pgd;
|
||||
pmd = (pmd_t *)pgd;
|
||||
#endif
|
||||
for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
|
||||
if (pmd_none(*pmd)) {
|
||||
pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
clear_page(pte);
|
||||
kpgd = pgd_offset_k((unsigned long)pte);
|
||||
kpmd = pmd_offset(kpgd, (unsigned long)pte);
|
||||
kpte = pte_offset(kpmd, (unsigned long)pte);
|
||||
queue_l1_entry_update(kpte,
|
||||
for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
|
||||
if (pmd_none(*pmd)) {
|
||||
pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
clear_page(pte);
|
||||
kpgd = pgd_offset_k((unsigned long)pte);
|
||||
kpmd = pmd_offset(kpgd, (unsigned long)pte);
|
||||
kpte = pte_offset(kpmd, (unsigned long)pte);
|
||||
queue_l1_entry_update(kpte,
|
||||
(*(unsigned long *)kpte)&~_PAGE_RW);
|
||||
|
||||
set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
|
||||
}
|
||||
vaddr += PMD_SIZE;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
|
||||
}
|
||||
vaddr += PMD_SIZE;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
|
||||
XENO_flush_page_update_queue();
|
||||
XENO_flush_page_update_queue();
|
||||
}
|
||||
|
||||
|
||||
static void __init zone_sizes_init(void)
|
||||
{
|
||||
unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
|
||||
unsigned int max_dma, high, low;
|
||||
unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
|
||||
unsigned int max_dma, high, low;
|
||||
|
||||
max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||
low = max_low_pfn;
|
||||
high = highend_pfn;
|
||||
max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||
low = max_low_pfn;
|
||||
high = highend_pfn;
|
||||
|
||||
if (low < max_dma)
|
||||
zones_size[ZONE_DMA] = low;
|
||||
else {
|
||||
zones_size[ZONE_DMA] = max_dma;
|
||||
zones_size[ZONE_NORMAL] = low - max_dma;
|
||||
if (low < max_dma)
|
||||
zones_size[ZONE_DMA] = low;
|
||||
else {
|
||||
zones_size[ZONE_DMA] = max_dma;
|
||||
zones_size[ZONE_NORMAL] = low - max_dma;
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
zones_size[ZONE_HIGHMEM] = high - low;
|
||||
zones_size[ZONE_HIGHMEM] = high - low;
|
||||
#endif
|
||||
}
|
||||
free_area_init(zones_size);
|
||||
}
|
||||
free_area_init(zones_size);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -218,60 +218,65 @@ static void __init zone_sizes_init(void)
|
||||
*/
|
||||
void __init paging_init(void)
|
||||
{
|
||||
unsigned long vaddr;
|
||||
unsigned long vaddr;
|
||||
|
||||
zone_sizes_init();
|
||||
zone_sizes_init();
|
||||
|
||||
/*
|
||||
* Fixed mappings, only the page table structure has to be created -
|
||||
* mappings will be set by set_fixmap():
|
||||
*/
|
||||
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
|
||||
fixrange_init(vaddr, HYPERVISOR_VIRT_START, init_mm.pgd);
|
||||
/*
|
||||
* Fixed mappings, only the page table structure has to be created -
|
||||
* mappings will be set by set_fixmap():
|
||||
*/
|
||||
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
|
||||
fixrange_init(vaddr, HYPERVISOR_VIRT_START, init_mm.pgd);
|
||||
|
||||
/* Cheesy: this can probably be moved to the blkdev driver. */
|
||||
set_fixmap(FIX_BLKRING_BASE, start_info.blk_ring);
|
||||
/* Cheesy: this can probably be moved to the blkdev driver. */
|
||||
set_fixmap(FIX_BLKRING_BASE, start_info.blk_ring);
|
||||
|
||||
/* Switch to the real shared_info page, and clear the dummy page. */
|
||||
set_fixmap(FIX_SHARED_INFO, start_info.shared_info);
|
||||
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
|
||||
memset(empty_zero_page, 0, sizeof(empty_zero_page));
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
#error
|
||||
kmap_init();
|
||||
kmap_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int page_is_ram (unsigned long pagenr)
|
||||
{
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
|
||||
{
|
||||
if (!page_is_ram(pfn)) {
|
||||
SetPageReserved(page);
|
||||
return;
|
||||
}
|
||||
if (!page_is_ram(pfn)) {
|
||||
SetPageReserved(page);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bad_ppro && page_kills_ppro(pfn)) {
|
||||
SetPageReserved(page);
|
||||
return;
|
||||
}
|
||||
if (bad_ppro && page_kills_ppro(pfn)) {
|
||||
SetPageReserved(page);
|
||||
return;
|
||||
}
|
||||
|
||||
ClearPageReserved(page);
|
||||
set_bit(PG_highmem, &page->flags);
|
||||
atomic_set(&page->count, 1);
|
||||
__free_page(page);
|
||||
totalhigh_pages++;
|
||||
ClearPageReserved(page);
|
||||
set_bit(PG_highmem, &page->flags);
|
||||
atomic_set(&page->count, 1);
|
||||
__free_page(page);
|
||||
totalhigh_pages++;
|
||||
}
|
||||
#endif /* CONFIG_HIGHMEM */
|
||||
|
||||
static void __init set_max_mapnr_init(void)
|
||||
{
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
highmem_start_page = mem_map + highstart_pfn;
|
||||
max_mapnr = num_physpages = highend_pfn;
|
||||
num_mappedpages = max_low_pfn;
|
||||
highmem_start_page = mem_map + highstart_pfn;
|
||||
max_mapnr = num_physpages = highend_pfn;
|
||||
num_mappedpages = max_low_pfn;
|
||||
#else
|
||||
max_mapnr = num_mappedpages = num_physpages = max_low_pfn;
|
||||
max_mapnr = num_mappedpages = num_physpages = max_low_pfn;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -279,112 +284,112 @@ static int __init free_pages_init(void)
|
||||
{
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
#error Where is this supposed to be initialised?
|
||||
int bad_ppro;
|
||||
int bad_ppro;
|
||||
#endif
|
||||
int reservedpages, pfn;
|
||||
int reservedpages, pfn;
|
||||
|
||||
/* this will put all low memory onto the freelists */
|
||||
totalram_pages += free_all_bootmem();
|
||||
/* this will put all low memory onto the freelists */
|
||||
totalram_pages += free_all_bootmem();
|
||||
|
||||
reservedpages = 0;
|
||||
for (pfn = 0; pfn < max_low_pfn; pfn++) {
|
||||
/*
|
||||
* Only count reserved RAM pages
|
||||
*/
|
||||
if (page_is_ram(pfn) && PageReserved(mem_map+pfn))
|
||||
reservedpages++;
|
||||
}
|
||||
reservedpages = 0;
|
||||
for (pfn = 0; pfn < max_low_pfn; pfn++) {
|
||||
/*
|
||||
* Only count reserved RAM pages
|
||||
*/
|
||||
if (page_is_ram(pfn) && PageReserved(mem_map+pfn))
|
||||
reservedpages++;
|
||||
}
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
for (pfn = highend_pfn-1; pfn >= highstart_pfn; pfn--)
|
||||
one_highpage_init((struct page *) (mem_map + pfn), pfn, bad_ppro);
|
||||
totalram_pages += totalhigh_pages;
|
||||
for (pfn = highend_pfn-1; pfn >= highstart_pfn; pfn--)
|
||||
one_highpage_init((struct page *) (mem_map + pfn), pfn, bad_ppro);
|
||||
totalram_pages += totalhigh_pages;
|
||||
#endif
|
||||
return reservedpages;
|
||||
return reservedpages;
|
||||
}
|
||||
|
||||
void __init mem_init(void)
|
||||
{
|
||||
int codesize, reservedpages, datasize, initsize;
|
||||
int codesize, reservedpages, datasize, initsize;
|
||||
|
||||
if (!mem_map)
|
||||
BUG();
|
||||
if (!mem_map)
|
||||
BUG();
|
||||
|
||||
set_max_mapnr_init();
|
||||
set_max_mapnr_init();
|
||||
|
||||
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
|
||||
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
|
||||
|
||||
/* clear the zero-page */
|
||||
memset(empty_zero_page, 0, PAGE_SIZE);
|
||||
/* clear the zero-page */
|
||||
memset(empty_zero_page, 0, PAGE_SIZE);
|
||||
|
||||
reservedpages = free_pages_init();
|
||||
reservedpages = free_pages_init();
|
||||
|
||||
codesize = (unsigned long) &_etext - (unsigned long) &_text;
|
||||
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
|
||||
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
|
||||
codesize = (unsigned long) &_etext - (unsigned long) &_text;
|
||||
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
|
||||
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
|
||||
|
||||
printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
|
||||
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
|
||||
max_mapnr << (PAGE_SHIFT-10),
|
||||
codesize >> 10,
|
||||
reservedpages << (PAGE_SHIFT-10),
|
||||
datasize >> 10,
|
||||
initsize >> 10,
|
||||
(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
|
||||
);
|
||||
printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
|
||||
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
|
||||
max_mapnr << (PAGE_SHIFT-10),
|
||||
codesize >> 10,
|
||||
reservedpages << (PAGE_SHIFT-10),
|
||||
datasize >> 10,
|
||||
initsize >> 10,
|
||||
(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
|
||||
);
|
||||
|
||||
boot_cpu_data.wp_works_ok = 1;
|
||||
}
|
||||
|
||||
void free_initmem(void)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned long addr;
|
||||
|
||||
addr = (unsigned long)(&__init_begin);
|
||||
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(addr));
|
||||
set_page_count(virt_to_page(addr), 1);
|
||||
free_page(addr);
|
||||
totalram_pages++;
|
||||
}
|
||||
printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
|
||||
addr = (unsigned long)(&__init_begin);
|
||||
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(addr));
|
||||
set_page_count(virt_to_page(addr), 1);
|
||||
free_page(addr);
|
||||
totalram_pages++;
|
||||
}
|
||||
printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (start < end)
|
||||
printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
|
||||
for (; start < end; start += PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(start));
|
||||
set_page_count(virt_to_page(start), 1);
|
||||
free_page(start);
|
||||
totalram_pages++;
|
||||
}
|
||||
if (start < end)
|
||||
printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
|
||||
for (; start < end; start += PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(start));
|
||||
set_page_count(virt_to_page(start), 1);
|
||||
free_page(start);
|
||||
totalram_pages++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void si_meminfo(struct sysinfo *val)
|
||||
{
|
||||
val->totalram = totalram_pages;
|
||||
val->sharedram = 0;
|
||||
val->freeram = nr_free_pages();
|
||||
val->bufferram = atomic_read(&buffermem_pages);
|
||||
val->totalhigh = totalhigh_pages;
|
||||
val->freehigh = nr_free_highpages();
|
||||
val->mem_unit = PAGE_SIZE;
|
||||
return;
|
||||
val->totalram = totalram_pages;
|
||||
val->sharedram = 0;
|
||||
val->freeram = nr_free_pages();
|
||||
val->bufferram = atomic_read(&buffermem_pages);
|
||||
val->totalhigh = totalhigh_pages;
|
||||
val->freehigh = nr_free_highpages();
|
||||
val->mem_unit = PAGE_SIZE;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_X86_PAE)
|
||||
struct kmem_cache_s *pae_pgd_cachep;
|
||||
void __init pgtable_cache_init(void)
|
||||
{
|
||||
/*
|
||||
* PAE pgds must be 16-byte aligned:
|
||||
/*
|
||||
* PAE pgds must be 16-byte aligned:
|
||||
*/
|
||||
pae_pgd_cachep = kmem_cache_create("pae_pgd", 32, 0,
|
||||
SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
|
||||
if (!pae_pgd_cachep)
|
||||
panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
|
||||
pae_pgd_cachep = kmem_cache_create("pae_pgd", 32, 0,
|
||||
SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
|
||||
if (!pae_pgd_cachep)
|
||||
panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
|
||||
}
|
||||
#endif /* CONFIG_X86_PAE */
|
||||
@@ -47,15 +47,16 @@ enum fixed_addresses {
|
||||
FIX_NETRING1_BASE,
|
||||
FIX_NETRING2_BASE,
|
||||
FIX_NETRING3_BASE,
|
||||
FIX_SHARED_INFO,
|
||||
|
||||
#ifdef CONFIG_VGA_CONSOLE
|
||||
#define NR_FIX_BTMAPS 32 /* 128KB For the Dom0 VGA Console A0000-C0000 */
|
||||
#else
|
||||
#define NR_FIX_BTMAPS 1 /* have on page incase anyone wants it in future */
|
||||
#define NR_FIX_BTMAPS 1 /* in case anyone wants it in future... */
|
||||
#endif
|
||||
FIX_BTMAP_END,
|
||||
FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
|
||||
/* our bt_ioremap is permenant unlike other architectures */
|
||||
/* our bt_ioremap is permanent, unlike other architectures */
|
||||
|
||||
__end_of_permanent_fixed_addresses,
|
||||
__end_of_fixed_addresses = __end_of_permanent_fixed_addresses
|
||||
|
||||
@@ -219,12 +219,13 @@ static inline int HYPERVISOR_set_callbacks(
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_net_update(void)
|
||||
static inline int HYPERVISOR_net_io_op(unsigned int op, unsigned int idx)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_net_update) );
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_net_io_op),
|
||||
"b" (op), "c" (idx) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -281,12 +282,13 @@ static inline int HYPERVISOR_network_op(void *network_op)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_block_io_op(void)
|
||||
static inline int HYPERVISOR_block_io_op(unsigned int op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_block_io_op) );
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_block_io_op),
|
||||
"b" (op) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||