bitkeeper revision 1.1159.1.545 (4208ec60-ql2CB2KKyZRC_8udlW9kA)

Merge tempest.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xeno.bk
into tempest.cl.cam.ac.uk:/local/scratch/smh22/xen-unstable.bk
This commit is contained in:
smh22@tempest.cl.cam.ac.uk committed 2005-02-08 16:44:16 +00:00
commit f50b658923
74 files changed
+1350 -1288

No files matched your search

+3 -1
View File
@@ -867,8 +867,8 @@
3ddb79bcBit4xJXbwtX0kb1hh2uO1Q xen/arch/x86/idle0_task.c
3ddb79bcKIkRR0kqWaJhe5VUDkMdxg xen/arch/x86/io_apic.c
3ddb79bdqfIcjkz_h9Hvtp8Tk_19Zw xen/arch/x86/irq.c
40ec29ffuOa1ZvmJHzFKyZn4k_RcXg xen/arch/x86/memory.c
41d54a76qfpO0VnbL2tYs0Jgt3W3XA xen/arch/x86/microcode.c
40ec29ffuOa1ZvmJHzFKyZn4k_RcXg xen/arch/x86/mm.c
3ddb79bdS4UeWWXDH-FaBKqcpMFcnw xen/arch/x86/mpparse.c
41aaf566Z4sTDgJ77eEg0TzzQ1ka6Q xen/arch/x86/mtrr/amd.c
41aaf566TOpOBXT00wwQGUh20f1rlA xen/arch/x86/mtrr/centaur.c
@@ -1038,6 +1038,7 @@
418fbcfe_WliJPToeVM-9VStvym-hw xen/include/asm-x86/x86_32/asm_defns.h
3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/include/asm-x86/x86_32/current.h
3e20b82fl1jmQiKdLy7fxMcutfpjWA xen/include/asm-x86/x86_32/domain_page.h
4208e2a3ZNFroNXbX9OYaOB-xtUyDQ xen/include/asm-x86/x86_32/page.h
3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/regs.h
3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h
3ddb79c3M2n1ROZH6xk3HbyN4CPDqg xen/include/asm-x86/x86_32/uaccess.h
@@ -1045,6 +1046,7 @@
404f1b9ceJeGVaPNIENm2FkK0AgEOQ xen/include/asm-x86/x86_64/current.h
41febc4b1aCGLsm0Y0b_82h7lFtrEA xen/include/asm-x86/x86_64/domain_page.h
404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86/x86_64/ldt.h
4208e2a3Fktw4ZttKdDxbhvTQ6brfQ xen/include/asm-x86/x86_64/page.h
404f1bb86rAXB3aLS1vYdcqpJiEcyg xen/include/asm-x86/x86_64/regs.h
40e1966azOJZfNI6Ilthe6Q-T3Hewg xen/include/asm-x86/x86_64/string.h
404f1bc4tWkB9Qr8RkKtZGW5eMQzhw xen/include/asm-x86/x86_64/uaccess.h
+4 -4
View File
@@ -915,7 +915,7 @@ static inline void establish_pte(struct vm_area_struct * vma, unsigned long addr
#ifdef CONFIG_XEN
if ( likely(vma->vm_mm == current->mm) ) {
XEN_flush_page_update_queue();
HYPERVISOR_update_va_mapping(address>>PAGE_SHIFT, entry, UVMF_INVLPG);
HYPERVISOR_update_va_mapping(address, entry, UVMF_INVLPG);
} else {
set_pte(page_table, entry);
flush_tlb_page(vma, address);
@@ -1191,7 +1191,7 @@ static int do_swap_page(struct mm_struct * mm,
#ifdef CONFIG_XEN
if ( likely(vma->vm_mm == current->mm) ) {
XEN_flush_page_update_queue();
HYPERVISOR_update_va_mapping(address>>PAGE_SHIFT, pte, 0);
HYPERVISOR_update_va_mapping(address, pte, 0);
} else {
set_pte(page_table, pte);
XEN_flush_page_update_queue();
@@ -1247,7 +1247,7 @@ static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma,
#ifdef CONFIG_XEN
if ( likely(vma->vm_mm == current->mm) ) {
XEN_flush_page_update_queue();
HYPERVISOR_update_va_mapping(addr>>PAGE_SHIFT, entry, 0);
HYPERVISOR_update_va_mapping(addr, entry, 0);
} else {
set_pte(page_table, entry);
XEN_flush_page_update_queue();
@@ -1333,7 +1333,7 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
#ifdef CONFIG_XEN
if ( likely(vma->vm_mm == current->mm) ) {
XEN_flush_page_update_queue();
HYPERVISOR_update_va_mapping(address>>PAGE_SHIFT, entry, 0);
HYPERVISOR_update_va_mapping(address, entry, 0);
} else {
set_pte(page_table, entry);
XEN_flush_page_update_queue();
@@ -229,7 +229,9 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code,
/* Set the "privileged fault" bit to something sane. */
error_code &= 3;
error_code |= (regs->xcs & 2) << 1;
if (regs->eflags & X86_EFLAGS_VM)
error_code |= 4;
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
SIGSEGV) == NOTIFY_STOP)
return;
@@ -95,7 +95,7 @@ static void fast_flush_area(int idx, int nr_pages)
for ( i = 0; i < nr_pages; i++ )
{
mcl[i].op = __HYPERVISOR_update_va_mapping;
mcl[i].args[0] = MMAP_VADDR(idx, i) >> PAGE_SHIFT;
mcl[i].args[0] = MMAP_VADDR(idx, i);
mcl[i].args[1] = 0;
mcl[i].args[2] = 0;
}
@@ -343,14 +343,14 @@ static void dispatch_probe(blkif_t *blkif, blkif_request_t *req)
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
if ( HYPERVISOR_update_va_mapping_otherdomain(
MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
MMAP_VADDR(pending_idx, 0),
(pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
0, (blkif->is_blktap ? ID_TO_DOM(req->id) : blkif->domid) ) )
goto out;
#else
if ( HYPERVISOR_update_va_mapping_otherdomain(
MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
MMAP_VADDR(pending_idx, 0),
(pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
0, blkif->domid) )
@@ -436,7 +436,7 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
for ( i = 0; i < nr_psegs; i++ )
{
mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
mcl[i].args[0] = MMAP_VADDR(pending_idx, i);
mcl[i].args[1] = (phys_seg[i].buffer & PAGE_MASK) | remap_prot;
mcl[i].args[2] = 0;
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
@@ -16,7 +16,7 @@
#include "blktap.h"
int __init xlblk_init(void)
int __init xlblktap_init(void)
{
ctrl_msg_t cmsg;
blkif_fe_driver_status_t fe_st;
@@ -64,6 +64,7 @@ int __init xlblk_init(void)
return 0;
}
#if 0 /* tap doesn't handle suspend/resume */
void blkdev_suspend(void)
{
}
@@ -81,6 +82,6 @@ void blkdev_resume(void)
memcpy(cmsg.msg, &st, sizeof(st));
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
}
#endif
__initcall(xlblk_init);
__initcall(xlblktap_init);
@@ -48,6 +48,12 @@
#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
/* -------[ state descriptors ]--------------------------------------- */
#define BLKIF_STATE_CLOSED 0
#define BLKIF_STATE_DISCONNECTED 1
#define BLKIF_STATE_CONNECTED 2
/* -------[ connection tracking ]------------------------------------- */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
@@ -99,7 +105,6 @@ typedef struct {
unsigned long mach_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
unsigned long virt_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
int next_free;
int inuse; /* debugging */
} active_req_t;
typedef unsigned int ACTIVE_RING_IDX;
@@ -181,7 +186,7 @@ extern unsigned long mmap_vstart;
* for shared memory rings.
*/
#define RING_PAGES 128
#define RING_PAGES 3 /* Ctrl, Front, and Back */
extern unsigned long rings_vstart;
@@ -190,11 +195,10 @@ extern unsigned long blktap_mode;
/* Connection to a single backend domain. */
extern blkif_front_ring_t blktap_be_ring;
extern unsigned int blktap_be_evtchn;
extern unsigned int blktap_be_state;
/* Event channel to backend domain. */
extern unsigned int blkif_ptbe_evtchn;
/* User ring status... this will soon vanish into a ring struct. */
/* User ring status. */
extern unsigned long blktap_ring_ok;
/* -------[ ...and function prototypes. ]----------------------------- */
@@ -213,8 +217,7 @@ void blktap_kick_user(void);
/* user ring access functions: */
int blktap_write_fe_ring(blkif_request_t *req);
int blktap_write_be_ring(blkif_response_t *rsp);
int blktap_read_fe_ring(void);
int blktap_read_be_ring(void);
int blktap_write_ctrl_ring(ctrl_msg_t *msg);
/* fe/be ring access functions: */
int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp);
@@ -10,10 +10,6 @@
#include "blktap.h"
#define BLKIF_STATE_CLOSED 0
#define BLKIF_STATE_DISCONNECTED 1
#define BLKIF_STATE_CONNECTED 2
static char *blkif_state_name[] = {
[BLKIF_STATE_CLOSED] = "closed",
[BLKIF_STATE_DISCONNECTED] = "disconnected",
@@ -26,9 +22,10 @@ static char * blkif_status_name[] = {
[BLKIF_INTERFACE_STATUS_CONNECTED] = "connected",
[BLKIF_INTERFACE_STATUS_CHANGED] = "changed",
};
static unsigned int blkif_pt_state = BLKIF_STATE_CLOSED;
static unsigned blkif_ptbe_irq;
unsigned int blkif_ptbe_evtchn;
static unsigned blktap_be_irq;
unsigned int blktap_be_state = BLKIF_STATE_CLOSED;
unsigned int blktap_be_evtchn;
/*-----[ Control Messages to/from Frontend VMs ]--------------------------*/
@@ -306,7 +303,7 @@ static void blkif_ptbe_disconnect(void)
sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL);
SHARED_RING_INIT(BLKIF_RING, sring);
FRONT_RING_INIT(BLKIF_RING, &blktap_be_ring, sring);
blkif_pt_state = BLKIF_STATE_DISCONNECTED;
blktap_be_state = BLKIF_STATE_DISCONNECTED;
DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n");
blkif_ptbe_send_interface_connect();
}
@@ -315,10 +312,10 @@ static void blkif_ptbe_connect(blkif_fe_interface_status_t *status)
{
int err = 0;
blkif_ptbe_evtchn = status->evtchn;
blkif_ptbe_irq = bind_evtchn_to_irq(blkif_ptbe_evtchn);
blktap_be_evtchn = status->evtchn;
blktap_be_irq = bind_evtchn_to_irq(blktap_be_evtchn);
err = request_irq(blkif_ptbe_irq, blkif_ptbe_int,
err = request_irq(blktap_be_irq, blkif_ptbe_int,
SA_SAMPLE_RANDOM, "blkif", NULL);
if ( err ) {
WPRINTK("blkfront request_irq failed (%d)\n", err);
@@ -326,7 +323,7 @@ static void blkif_ptbe_connect(blkif_fe_interface_status_t *status)
} else {
/* transtion to connected in case we need to do a
a partion probe on a whole disk */
blkif_pt_state = BLKIF_STATE_CONNECTED;
blktap_be_state = BLKIF_STATE_CONNECTED;
}
}
@@ -334,7 +331,7 @@ static void unexpected(blkif_fe_interface_status_t *status)
{
WPRINTK(" TAP: Unexpected blkif status %s in state %s\n",
blkif_status_name[status->status],
blkif_state_name[blkif_pt_state]);
blkif_state_name[blktap_be_state]);
}
static void blkif_ptbe_status(
@@ -352,7 +349,7 @@ static void blkif_ptbe_status(
switch ( status->status )
{
case BLKIF_INTERFACE_STATUS_CLOSED:
switch ( blkif_pt_state )
switch ( blktap_be_state )
{
case BLKIF_STATE_CLOSED:
unexpected(status);
@@ -366,7 +363,7 @@ static void blkif_ptbe_status(
break;
case BLKIF_INTERFACE_STATUS_DISCONNECTED:
switch ( blkif_pt_state )
switch ( blktap_be_state )
{
case BLKIF_STATE_CLOSED:
blkif_ptbe_disconnect();
@@ -380,7 +377,7 @@ static void blkif_ptbe_status(
break;
case BLKIF_INTERFACE_STATUS_CONNECTED:
switch ( blkif_pt_state )
switch ( blktap_be_state )
{
case BLKIF_STATE_CLOSED:
unexpected(status);
@@ -398,7 +395,7 @@ static void blkif_ptbe_status(
break;
case BLKIF_INTERFACE_STATUS_CHANGED:
switch ( blkif_pt_state )
switch ( blktap_be_state )
{
case BLKIF_STATE_CLOSED:
case BLKIF_STATE_DISCONNECTED:
@@ -440,6 +437,14 @@ void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
case CMSG_BLKIF_BE:
/* send a copy of the message to user if wanted */
if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
(blktap_mode & BLKTAP_MODE_COPY_FE) ) {
blktap_write_ctrl_ring(msg);
}
switch ( msg->subtype )
{
case CMSG_BLKIF_BE_CREATE:
@@ -500,11 +505,13 @@ void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
ctrl_if_send_response(msg);
}
/*-----[ All control messages enter here: ]-------------------------------*/
/*-----[ Initialization ]-------------------------------------------------*/
void __init blkif_interface_init(void)
{
blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
0, 0, NULL, NULL);
memset(blkif_hash, 0, sizeof(blkif_hash));
blktap_be_ring.sring = NULL;
}
@@ -40,8 +40,6 @@ inline active_req_t *get_active_req(void)
spin_lock_irqsave(&active_req_lock, flags);
idx = active_req_ring[MASK_ACTIVE_IDX(active_cons++)];
ar = &active_reqs[idx];
if (ar->inuse) WPRINTK("AR INUSE! (%lu)\n", ar->id);
ar->inuse = 1;
spin_unlock_irqrestore(&active_req_lock, flags);
return ar;
@@ -52,7 +50,6 @@ inline void free_active_req(active_req_t *ar)
unsigned long flags;
spin_lock_irqsave(&active_req_lock, flags);
ar->inuse = 0;
active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar);
spin_unlock_irqrestore(&active_req_lock, flags);
}
@@ -97,11 +94,8 @@ inline int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp)
blkif_response_t *resp_d;
active_req_t *ar;
/* remap id, and free the active req. blkif lookup goes here too.*/
ar = &active_reqs[ID_TO_IDX(rsp->id)];
/* WPRINTK("%3u > %3lu\n", ID_TO_IDX(rsp->id), ar->id); */
rsp->id = ar->id;
free_active_req(ar);
resp_d = RING_GET_RESPONSE(BLKIF_RING, &blkif->blk_ring,
blkif->blk_ring.rsp_prod_pvt);
@@ -109,6 +103,9 @@ inline int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp)
wmb();
blkif->blk_ring.rsp_prod_pvt++;
blkif_put(ar->blkif);
free_active_req(ar);
return 0;
}
@@ -116,6 +113,11 @@ inline int write_req_to_be_ring(blkif_request_t *req)
{
blkif_request_t *req_d;
if ( blktap_be_state != BLKIF_STATE_CONNECTED ) {
WPRINTK("Tap trying to access an unconnected backend!\n");
return 0;
}
req_d = RING_GET_REQUEST(BLKIF_RING, &blktap_be_ring,
blktap_be_ring.req_prod_pvt);
memcpy(req_d, req, sizeof(blkif_request_t));
@@ -135,9 +137,12 @@ inline void kick_fe_domain(blkif_t *blkif)
inline void kick_be_domain(void)
{
if ( blktap_be_state != BLKIF_STATE_CONNECTED )
return;
wmb(); /* Ensure that the frontend can see the requests. */
RING_PUSH_REQUESTS(BLKIF_RING, &blktap_be_ring);
notify_via_evtchn(blkif_ptbe_evtchn);
notify_via_evtchn(blktap_be_evtchn);
DPRINTK("notified BE\n");
}
@@ -310,6 +315,7 @@ static int do_block_io_op(blkif_t *blkif, int max_to_do)
*/
ar = get_active_req();
ar->id = req_s->id;
blkif_get(blkif);
ar->blkif = blkif;
req_s->id = MAKE_ID(blkif->domid, ACTIVE_IDX(ar));
/* WPRINTK("%3u < %3lu\n", ID_TO_IDX(req_s->id), ar->id); */
@@ -458,11 +464,13 @@ void print_vm_ring_idxs(void)
blkif->blk_ring.sring->req_prod,
blkif->blk_ring.sring->rsp_prod);
}
WPRINTK("BE Ring: \n--------\n");
WPRINTK("BE: rsp_cons: %2d, req_prod_prv: %2d "
"| req_prod: %2d, rsp_prod: %2d\n",
blktap_be_ring.rsp_cons,
blktap_be_ring.req_prod_pvt,
blktap_be_ring.sring->req_prod,
blktap_be_ring.sring->rsp_prod);
if (blktap_be_ring.sring != NULL) {
WPRINTK("BE Ring: \n--------\n");
WPRINTK("BE: rsp_cons: %2d, req_prod_prv: %2d "
"| req_prod: %2d, rsp_prod: %2d\n",
blktap_be_ring.rsp_cons,
blktap_be_ring.req_prod_pvt,
blktap_be_ring.sring->req_prod,
blktap_be_ring.sring->rsp_prod);
}
}
@@ -19,6 +19,7 @@
#include <linux/gfp.h>
#include <linux/poll.h>
#include <asm/pgalloc.h>
#include <asm-xen/xen-public/io/blkif.h> /* for control ring. */
#include "blktap.h"
@@ -40,6 +41,11 @@ unsigned long rings_vstart;
/* Rings up to user space. */
static blkif_front_ring_t blktap_ufe_ring;
static blkif_back_ring_t blktap_ube_ring;
static ctrl_front_ring_t blktap_uctrl_ring;
/* local prototypes */
static int blktap_read_fe_ring(void);
static int blktap_read_be_ring(void);
/* -------[ blktap vm ops ]------------------------------------------- */
@@ -66,16 +72,28 @@ struct vm_operations_struct blktap_vm_ops = {
static int blktap_open(struct inode *inode, struct file *filp)
{
blkif_sring_t *sring;
ctrl_sring_t *csring;
if ( test_and_set_bit(0, &blktap_dev_inuse) )
return -EBUSY;
printk(KERN_ALERT "blktap open.\n");
/* Allocate the ctrl ring. */
csring = (ctrl_sring_t *)get_zeroed_page(GFP_KERNEL);
if (csring == NULL)
goto fail_nomem;
SetPageReserved(virt_to_page(csring));
SHARED_RING_INIT(CTRL_RING, csring);
FRONT_RING_INIT(CTRL_RING, &blktap_uctrl_ring, csring);
/* Allocate the fe ring. */
sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
if (sring == NULL)
goto fail_nomem;
goto fail_free_ctrl;
SetPageReserved(virt_to_page(sring));
@@ -95,6 +113,9 @@ static int blktap_open(struct inode *inode, struct file *filp)
DPRINTK(KERN_ALERT "blktap open.\n");
return 0;
fail_free_ctrl:
free_page( (unsigned long) blktap_uctrl_ring.sring);
fail_free_fe:
free_page( (unsigned long) blktap_ufe_ring.sring);
@@ -111,6 +132,9 @@ static int blktap_release(struct inode *inode, struct file *filp)
printk(KERN_ALERT "blktap closed.\n");
/* Free the ring page. */
ClearPageReserved(virt_to_page(blktap_uctrl_ring.sring));
free_page((unsigned long) blktap_uctrl_ring.sring);
ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
free_page((unsigned long) blktap_ufe_ring.sring);
@@ -120,6 +144,15 @@ static int blktap_release(struct inode *inode, struct file *filp)
return 0;
}
/* Note on mmap:
* remap_pfn_range sets VM_IO on vma->vm_flags. In trying to make libaio
* work to do direct page access from userspace, this ended up being a
* problem. The bigger issue seems to be that there is no way to map
* a foreign page in to user space and have the virtual address of that
* page map sanely down to a mfn.
* Removing the VM_IO flag results in a loop in get_user_pages, as
* pfn_valid() always fails on a foreign page.
*/
static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
{
int size;
@@ -148,20 +181,28 @@ static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
/* not sure if I really need to do this... */
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
DPRINTK("Mapping be_ring page %lx.\n", __pa(blktap_ube_ring.sring));
if (remap_page_range(vma, vma->vm_start,
__pa(blktap_ube_ring.sring),
DPRINTK("Mapping ctrl_ring page %lx.\n", __pa(blktap_uctrl_ring.sring));
if (remap_pfn_range(vma, vma->vm_start,
__pa(blktap_uctrl_ring.sring) >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
WPRINTK("be_ring: remap_page_range failure!\n");
WPRINTK("ctrl_ring: remap_pfn_range failure!\n");
}
DPRINTK("Mapping be_ring page %lx.\n", __pa(blktap_ube_ring.sring));
if (remap_pfn_range(vma, vma->vm_start + PAGE_SIZE,
__pa(blktap_ube_ring.sring) >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
WPRINTK("be_ring: remap_pfn_range failure!\n");
}
DPRINTK("Mapping fe_ring page %lx.\n", __pa(blktap_ufe_ring.sring));
if (remap_page_range(vma, vma->vm_start + PAGE_SIZE,
__pa(blktap_ufe_ring.sring),
if (remap_pfn_range(vma, vma->vm_start + ( 2 * PAGE_SIZE ),
__pa(blktap_ufe_ring.sring) >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
WPRINTK("fe_ring: remap_page_range failure!\n");
WPRINTK("fe_ring: remap_pfn_range failure!\n");
}
blktap_vma = vma;
blktap_ring_ok = 1;
@@ -211,9 +252,11 @@ static unsigned int blktap_poll(struct file *file, poll_table *wait)
{
poll_wait(file, &blktap_wait, wait);
if ( RING_HAS_UNPUSHED_REQUESTS(BLKIF_RING, &blktap_ufe_ring) ||
if ( RING_HAS_UNPUSHED_REQUESTS(BLKIF_RING, &blktap_uctrl_ring) ||
RING_HAS_UNPUSHED_REQUESTS(BLKIF_RING, &blktap_ufe_ring) ||
RING_HAS_UNPUSHED_RESPONSES(BLKIF_RING, &blktap_ube_ring) ) {
RING_PUSH_REQUESTS(BLKIF_RING, &blktap_uctrl_ring);
RING_PUSH_REQUESTS(BLKIF_RING, &blktap_ufe_ring);
RING_PUSH_RESPONSES(BLKIF_RING, &blktap_ube_ring);
return POLLIN | POLLRDNORM;
@@ -260,7 +303,6 @@ int blktap_write_fe_ring(blkif_request_t *req)
return 0;
}
//target = RING_NEXT_EMPTY_REQUEST(BLKIF_RING, &blktap_ufe_ring);
target = RING_GET_REQUEST(BLKIF_RING, &blktap_ufe_ring,
blktap_ufe_ring.req_prod_pvt);
memcpy(target, req, sizeof(*req));
@@ -270,7 +312,7 @@ int blktap_write_fe_ring(blkif_request_t *req)
error = direct_remap_area_pages(blktap_vma->vm_mm,
MMAP_VADDR(ID_TO_IDX(req->id), i),
target->frame_and_sects[0] & PAGE_MASK,
target->frame_and_sects[i] & PAGE_MASK,
PAGE_SIZE,
blktap_vma->vm_page_prot,
ID_TO_DOM(req->id));
@@ -302,7 +344,6 @@ int blktap_write_be_ring(blkif_response_t *rsp)
/* No test for fullness in the response direction. */
//target = RING_NEXT_EMPTY_RESPONSE(BLKIF_RING, &blktap_ube_ring);
target = RING_GET_RESPONSE(BLKIF_RING, &blktap_ube_ring,
blktap_ube_ring.rsp_prod_pvt);
memcpy(target, rsp, sizeof(*rsp));
@@ -314,7 +355,7 @@ int blktap_write_be_ring(blkif_response_t *rsp)
return 0;
}
int blktap_read_fe_ring(void)
static int blktap_read_fe_ring(void)
{
/* This is called to read responses from the UFE ring. */
@@ -329,7 +370,6 @@ int blktap_read_fe_ring(void)
if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
/* for each outstanding message on the UFEring */
//RING_FOREACH_RESPONSE(BLKIF_RING, &blktap_ufe_ring, prod, resp_s) {
rp = blktap_ufe_ring.sring->rsp_prod;
rmb();
@@ -349,7 +389,7 @@ int blktap_read_fe_ring(void)
return 0;
}
int blktap_read_be_ring(void)
static int blktap_read_be_ring(void)
{
/* This is called to read requests from the UBE ring. */
@@ -362,7 +402,6 @@ int blktap_read_be_ring(void)
if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
/* for each outstanding message on the UFEring */
//RING_FOREACH_REQUEST(BLKIF_RING, &blktap_ube_ring, prod, req_s) {
rp = blktap_ube_ring.sring->req_prod;
rmb();
for ( i = blktap_ube_ring.req_cons; i != rp; i++ )
@@ -379,6 +418,31 @@ int blktap_read_be_ring(void)
return 0;
}
int blktap_write_ctrl_ring(ctrl_msg_t *msg)
{
ctrl_msg_t *target;
if ( ! blktap_ring_ok ) {
DPRINTK("blktap: be_ring not ready for a request!\n");
return 0;
}
/* No test for fullness in the response direction. */
target = RING_GET_REQUEST(CTRL_RING, &blktap_uctrl_ring,
blktap_uctrl_ring.req_prod_pvt);
memcpy(target, msg, sizeof(*msg));
blktap_uctrl_ring.req_prod_pvt++;
/* currently treat the ring as unidirectional. */
blktap_uctrl_ring.rsp_cons = blktap_uctrl_ring.sring->rsp_prod;
return 0;
}
/* -------[ blktap module setup ]------------------------------------- */
static struct miscdevice blktap_miscdev = {
@@ -234,7 +234,7 @@ static void net_rx_action(unsigned long unused)
mmu[2].val = MMUEXT_REASSIGN_PAGE;
mcl[0].op = __HYPERVISOR_update_va_mapping;
mcl[0].args[0] = vdata >> PAGE_SHIFT;
mcl[0].args[0] = vdata;
mcl[0].args[1] = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL;
mcl[0].args[2] = 0;
mcl[1].op = __HYPERVISOR_mmu_update;
@@ -409,7 +409,7 @@ static void net_tx_action(unsigned long unused)
{
pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
mcl[0].op = __HYPERVISOR_update_va_mapping;
mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
mcl[0].args[0] = MMAP_VADDR(pending_idx);
mcl[0].args[1] = 0;
mcl[0].args[2] = 0;
mcl++;
@@ -546,7 +546,7 @@ static void net_tx_action(unsigned long unused)
skb_reserve(skb, 16);
mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain;
mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
mcl[0].args[0] = MMAP_VADDR(pending_idx);
mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL;
mcl[0].args[2] = 0;
mcl[0].args[3] = netif->domid;
@@ -392,7 +392,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
= INVALID_P2M_ENTRY;
rx_mcl[i].op = __HYPERVISOR_update_va_mapping;
rx_mcl[i].args[0] = (unsigned long)skb->head >> PAGE_SHIFT;
rx_mcl[i].args[0] = (unsigned long)skb->head;
rx_mcl[i].args[1] = 0;
rx_mcl[i].args[2] = 0;
}
@@ -593,7 +593,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
mmu->val = __pa(skb->head) >> PAGE_SHIFT;
mmu++;
mcl->op = __HYPERVISOR_update_va_mapping;
mcl->args[0] = (unsigned long)skb->head >> PAGE_SHIFT;
mcl->args[0] = (unsigned long)skb->head;
mcl->args[1] = (rx->addr & PAGE_MASK) | __PAGE_KERNEL;
mcl->args[2] = 0;
mcl++;
@@ -191,7 +191,7 @@ static void fast_flush_area(int idx, int nr_pages)
for ( i = 0; i < nr_pages; i++ )
{
mcl[i].op = __HYPERVISOR_update_va_mapping;
mcl[i].args[0] = MMAP_VADDR(idx, i) >> PAGE_SHIFT;
mcl[i].args[0] = MMAP_VADDR(idx, i);
mcl[i].args[1] = 0;
mcl[i].args[2] = 0;
}
@@ -630,7 +630,7 @@ static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req)
i++, offset += PAGE_SIZE )
{
mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
mcl[i].args[0] = MMAP_VADDR(pending_idx, i);
mcl[i].args[1] = ((buffer_mach & PAGE_MASK) + offset) | remap_prot;
mcl[i].args[2] = 0;
mcl[i].args[3] = up->domid;
@@ -646,7 +646,7 @@ static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req)
{
/* Map in ISO schedule, if necessary. */
mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
mcl[i].args[0] = MMAP_VADDR(pending_idx, i);
mcl[i].args[1] = (req->iso_schedule & PAGE_MASK) | remap_prot;
mcl[i].args[2] = 0;
mcl[i].args[3] = up->domid;
@@ -426,7 +426,7 @@ extern pte_t *lookup_address(unsigned long address);
if (__dirty) { \
if ( likely((__vma)->vm_mm == current->mm) ) { \
xen_flush_page_update_queue(); \
HYPERVISOR_update_va_mapping((__address)>>PAGE_SHIFT, (__entry), UVMF_INVLPG); \
HYPERVISOR_update_va_mapping((__address), (__entry), UVMF_INVLPG); \
} else { \
xen_l1_entry_update((__ptep), (__entry).pte_low); \
flush_tlb_page((__vma), (__address)); \
@@ -445,7 +445,7 @@ do { \
do { \
if (likely((__vma)->vm_mm == current->mm)) { \
xen_flush_page_update_queue(); \
HYPERVISOR_update_va_mapping((__address)>>PAGE_SHIFT, \
HYPERVISOR_update_va_mapping((__address), \
__entry, 0); \
} else { \
xen_l1_entry_update((__ptep), (__entry).pte_low); \
@@ -438,7 +438,7 @@ HYPERVISOR_multicall(
static inline int
HYPERVISOR_update_va_mapping(
unsigned long page_nr, pte_t new_val, unsigned long flags)
unsigned long nr, pte_t new_val, unsigned long flags)
{
int ret;
unsigned long ign1, ign2, ign3;
@@ -447,13 +447,13 @@ HYPERVISOR_update_va_mapping(
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
: "0" (__HYPERVISOR_update_va_mapping),
"1" (page_nr), "2" ((new_val).pte_low), "3" (flags)
"1" (va), "2" ((new_val).pte_low), "3" (flags)
: "memory" );
if ( unlikely(ret < 0) )
{
printk(KERN_ALERT "Failed update VA mapping: %08lx, %08lx, %08lx\n",
page_nr, (new_val).pte_low, flags);
va, (new_val).pte_low, flags);
BUG();
}
@@ -540,7 +540,7 @@ HYPERVISOR_grant_table_op(
static inline int
HYPERVISOR_update_va_mapping_otherdomain(
unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid)
unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
@@ -549,7 +549,7 @@ HYPERVISOR_update_va_mapping_otherdomain(
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
: "0" (__HYPERVISOR_update_va_mapping_otherdomain),
"1" (page_nr), "2" ((new_val).pte_low), "3" (flags), "4" (domid) :
"1" (va), "2" ((new_val).pte_low), "3" (flags), "4" (domid) :
"memory" );
return ret;
@@ -398,7 +398,7 @@ HYPERVISOR_multicall(void *call_list, int nr_calls)
}
static inline int
HYPERVISOR_update_va_mapping(unsigned long page_nr, unsigned long new_val,
HYPERVISOR_update_va_mapping(unsigned long va, unsigned long new_val,
unsigned long flags)
{
int ret;
@@ -408,12 +408,12 @@ HYPERVISOR_update_va_mapping(unsigned long page_nr, unsigned long new_val,
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
: "0" (__HYPERVISOR_update_va_mapping),
"1" (page_nr), "2" (new_val), "3" (flags)
"1" (va), "2" (new_val), "3" (flags)
: "memory" );
if (__predict_false(ret < 0))
panic("Failed update VA mapping: %08lx, %08lx, %08lx",
page_nr, new_val, flags);
va, new_val, flags);
return ret;
}
@@ -494,7 +494,7 @@ HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
}
static inline int
HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
HYPERVISOR_update_va_mapping_otherdomain(unsigned long va,
unsigned long new_val, unsigned long flags, domid_t domid)
{
int ret;
@@ -504,7 +504,7 @@ HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
: "0" (__HYPERVISOR_update_va_mapping_otherdomain),
"1" (page_nr), "2" (new_val), "3" (flags), "4" (domid) :
"1" (va), "2" (new_val), "3" (flags), "4" (domid) :
"memory" );
return ret;
@@ -580,7 +580,7 @@ xennet_rx_push_buffer(struct xennet_softc *sc, int id)
INVALID_P2M_ENTRY;
rx_mcl[nr_pfns].op = __HYPERVISOR_update_va_mapping;
rx_mcl[nr_pfns].args[0] = sc->sc_rx_bufa[id].xb_rx.xbrx_va >> PAGE_SHIFT;
rx_mcl[nr_pfns].args[0] = sc->sc_rx_bufa[id].xb_rx.xbrx_va;
rx_mcl[nr_pfns].args[1] = 0;
rx_mcl[nr_pfns].args[2] = 0;
@@ -679,7 +679,7 @@ xen_network_handler(void *arg)
mmu->val = (pa - XPMAP_OFFSET) >> PAGE_SHIFT;
mmu++;
mcl->op = __HYPERVISOR_update_va_mapping;
mcl->args[0] = sc->sc_rx_bufa[rx->id].xb_rx.xbrx_va >> PAGE_SHIFT;
mcl->args[0] = sc->sc_rx_bufa[rx->id].xb_rx.xbrx_va;
mcl->args[1] = (rx->addr & PG_FRAME) | PG_V|PG_KW;
mcl->args[2] = UVMF_FLUSH_TLB; // 0;
mcl++;
@@ -872,7 +872,7 @@ network_alloc_rx_buffers(struct xennet_softc *sc)
INVALID_P2M_ENTRY;
rx_mcl[nr_pfns].op = __HYPERVISOR_update_va_mapping;
rx_mcl[nr_pfns].args[0] = va >> PAGE_SHIFT;
rx_mcl[nr_pfns].args[0] = va;
rx_mcl[nr_pfns].args[1] = 0;
rx_mcl[nr_pfns].args[2] = 0;
+4 -3
View File
@@ -3,10 +3,12 @@
#vgaromimage: $BXSHARE/VGABIOS-lgpl-latest
floppya: 1_44=a.img, status=inserted
floppyb: 1_44=b.img, status=inserted
#ata0-master: type=disk, path=minibootable.img, cylinders=900, heads=15, spt=17
# if you don't use absolute paths below, bochs looks under the cwd of xend,
# which is usually "/"
ata0-master: type=disk, path=/tmp/min-fc2-i386.img, cylinders=800, heads=4, spt=32
#ata0-master: type=disk, path=/var/images/min-el3-i386.img, cylinders=800, heads=4, spt=32
i440fxsupport: enabled=1
ne2k: ioaddr=0x300, irq=9, mac=b0:c4:22:01:00:00, ethmod=linux, ethdev=eth0
ata0-master: type=disk, path=/var/images/1g-el3-i386.img, mode=flat, cylinders=2048, heads=16, spt=63
boot: c
log: /tmp/bochsout.txt
@@ -16,4 +18,3 @@ error: action=report
panic: action=ask
mouse: enabled=0
ips: 1500000
+2 -2
View File
@@ -37,8 +37,8 @@ domain=${domain:?}
vif=${vif:?}
ip=${ip:?}
# better way to strip /netmask from the ip?
vif_ip=`echo ${ip} | awk -F. '{print $1"."$2"."$3"."$4}'`
# strip /netmask
vif_ip=`echo ${ip} | awk -F/ '{print $1}'`
main_ip=`ifconfig eth0 | grep "inet addr:" | sed -e 's/.*inet addr:\(\w\w*\.\w\w*\.\w\w*\.\w\w*\).*/\1/'`
+2 -2
View File
@@ -687,13 +687,13 @@ typedef
#define BX_NUM_SIMULATORS 1
// limited i440FX PCI support
#define BX_PCI_SUPPORT 0
#define BX_PCI_SUPPORT 1
// Experimental VGA on PCI
#define BX_PCI_VGA_SUPPORT 1
// limited USB on PCI
#define BX_PCI_USB_SUPPORT 0
#define BX_PCI_USB_SUPPORT 1
#if (BX_PCI_USB_SUPPORT && !BX_PCI_SUPPORT)
#error To enable USB, you must also enable PCI
+27
View File
@@ -45,6 +45,13 @@ BOCHSAPI extern class bx_pc_system_c bx_pc_system;
extern double m_ips;
#endif
#ifdef BX_USE_VMX
extern unsigned int tsc_per_bx_tick;
#define rdtscll(val) \
__asm__ __volatile__("rdtsc" : "=A" (val))
#endif
class BOCHSAPI bx_pc_system_c : private logfunctions {
private:
@@ -87,6 +94,26 @@ private:
double m_ips; // Millions of Instructions Per Second
#endif
#ifdef BX_USE_VMX
static Bit64s get_clock(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000LL + tv.tv_usec;
}
static Bit64u cpu_calibrate_ticks(void) {
Bit64s usec, t1, t2;
usec = get_clock();
rdtscll(t1);
usleep(50 * 1000);
usec = get_clock() - usec;
rdtscll(t2);
return (((t2 - t1) * 1000000LL + (usec >> 1)) / usec);
}
#endif
// This handler is called when the function which decrements the clock
// ticks finds that an event has occurred.
void countdownEvent(void);
+21 -8
View File
@@ -180,7 +180,8 @@ bx_cpu_c::cpu_loop(int max_instr_count)
FD_ZERO(&rfds);
while (1) {
unsigned long t1, t2;
static unsigned long long t1 = 0;
unsigned long long t2;
/* Wait up to one seconds. */
tv.tv_sec = 0;
@@ -188,18 +189,30 @@ bx_cpu_c::cpu_loop(int max_instr_count)
FD_SET(evtchn_fd, &rfds);
send_event = 0;
rdtscl(t1);
if (t1 == 0) // the first time
rdtscll(t1);
retval = select(evtchn_fd+1, &rfds, NULL, NULL, &tv);
rdtscl(t2);
if (retval == -1) {
perror("select");
return;
}
//stime_usec = 1000000 * (1 - tv.tv_sec) - tv.tv_usec;
if (t2 > t1)
BX_TICKN((t2 - t1) / 2000); // should match ips in bochsrc
rdtscll(t2);
#if __WORDSIZE == 32
#define ULONGLONG_MAX 0xffffffffffffffffULL
#else
#define ULONGLONG_MAX ULONG_MAX
#endif
if (t2 <= t1)
BX_TICKN((t2 + ULONGLONG_MAX - t1) / tsc_per_bx_tick);
else
BX_TICKN((MAXINT - t1 + t2) / 2000); // should match ips in bochsrc
BX_TICKN((t2 - t1) / tsc_per_bx_tick);
t1 = t2;
timer_handler();
if (BX_CPU_INTR) {
#if BX_SUPPORT_APIC
@@ -248,7 +261,7 @@ bx_cpu_c::interrupt(Bit8u vector)
// page.
rdtscl(tscl);
BX_INFO(("%lx: injecting vector: %x\n", tscl, vector));
BX_DEBUG(("%lx: injecting vector: %x\n", tscl, vector));
intr = &(((vcpu_iodata_t *) shared_page)->vp_intr[0]);
set_bit(vector, intr);
+14
View File
@@ -44,6 +44,10 @@ unsigned long ips_count=0;
double m_ips; // Millions of Instructions Per Second
#endif
#ifdef BX_USE_VMX
unsigned int tsc_per_bx_tick;
#endif
// Option for turning off BX_TIMER_DEBUG?
// Check out m_ips and ips
@@ -98,6 +102,16 @@ bx_pc_system_c::init_ips(Bit32u ips)
a20_mask = 0xffffffff;
#endif
#ifdef BX_USE_VMX
Bit64u phy_cpu_freq = cpu_calibrate_ticks();
if (ips == 500000) { //default ips: we use fixed scaling factor to calulate ips
tsc_per_bx_tick = 2000;
ips = phy_cpu_freq / tsc_per_bx_tick;
} else //use uesr defined ips to calulate factor
tsc_per_bx_tick = ((phy_cpu_freq + (ips>>1)) / ips);
#endif
// parameter 'ips' is the processor speed in Instructions-Per-Second
m_ips = double(ips) / 1000000.0L;
+6 -6
View File
@@ -558,10 +558,10 @@ static int parseelfimage(char *elfbase,
phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
if ( !is_loadable_phdr(phdr) )
continue;
if ( phdr->p_vaddr < kernstart )
kernstart = phdr->p_vaddr;
if ( (phdr->p_vaddr + phdr->p_memsz) > kernend )
kernend = phdr->p_vaddr + phdr->p_memsz;
if ( phdr->p_paddr < kernstart )
kernstart = phdr->p_paddr;
if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
kernend = phdr->p_paddr + phdr->p_memsz;
}
if ( (kernstart > kernend) ||
@@ -611,7 +611,7 @@ loadelfimage(
for ( done = 0; done < phdr->p_filesz; done += chunksz )
{
pa = (phdr->p_vaddr + done) - vstart;
pa = (phdr->p_paddr + done) - vstart;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_filesz - done;
@@ -624,7 +624,7 @@ loadelfimage(
for ( ; done < phdr->p_memsz; done += chunksz )
{
pa = (phdr->p_vaddr + done) - vstart;
pa = (phdr->p_paddr + done) - vstart;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_memsz - done;
+6 -6
View File
@@ -629,10 +629,10 @@ static int parseelfimage(char *elfbase,
phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
if ( !is_loadable_phdr(phdr) )
continue;
if ( phdr->p_vaddr < kernstart )
kernstart = phdr->p_vaddr;
if ( (phdr->p_vaddr + phdr->p_memsz) > kernend )
kernend = phdr->p_vaddr + phdr->p_memsz;
if ( phdr->p_paddr < kernstart )
kernstart = phdr->p_paddr;
if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
kernend = phdr->p_paddr + phdr->p_memsz;
}
if ( (kernstart > kernend) ||
@@ -676,7 +676,7 @@ loadelfimage(
for ( done = 0; done < phdr->p_filesz; done += chunksz )
{
pa = (phdr->p_vaddr + done) - vstart - LINUX_PAGE_OFFSET;
pa = (phdr->p_paddr + done) - vstart - LINUX_PAGE_OFFSET;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_filesz - done;
@@ -689,7 +689,7 @@ loadelfimage(
for ( ; done < phdr->p_memsz; done += chunksz )
{
pa = (phdr->p_vaddr + done) - vstart - LINUX_PAGE_OFFSET;
pa = (phdr->p_paddr + done) - vstart - LINUX_PAGE_OFFSET;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_memsz - done;
+1
View File
@@ -1337,6 +1337,7 @@ add_config_handler('memory', vm_field_ignore)
add_config_handler('cpu', vm_field_ignore)
add_config_handler('cpu_weight', vm_field_ignore)
add_config_handler('console', vm_field_ignore)
add_config_handler('restart', vm_field_ignore)
add_config_handler('image', vm_field_ignore)
add_config_handler('device', vm_field_ignore)
add_config_handler('backend', vm_field_ignore)
+3 -1
View File
@@ -486,10 +486,12 @@ class Daemon:
# XXX KAF: Why doesn't this capture output from C extensions that
# fprintf(stdout) or fprintf(stderr) ??
os.open('/var/log/xend-debug.log', os.O_WRONLY|os.O_CREAT)
os.dup(1)
else:
os.open('/dev/null', os.O_RDWR)
os.dup(0)
os.dup(1)
os.open('/var/log/xend-debug.log', os.O_WRONLY|os.O_CREAT)
def start(self, trace=0):
"""Attempts to start the daemons.
+6
View File
@@ -245,6 +245,12 @@ int main(int argc, char **argv)
return 1;
}
/*
* End the image on a page boundary. This gets round alignment bugs
* in the boot- or chain-loader (e.g., kexec on the XenoBoot CD).
*/
mem_siz += -(loadbase + mem_siz) & 0xfff;
out_ehdr.e_entry = loadbase;
out_ehdr.e_shoff = RAW_OFFSET + dat_siz;
+2 -2
View File
@@ -214,7 +214,7 @@ ENTRY(gdt_table)
.org 0x1000
ENTRY(idle_pg_table) # Initial page directory is 4kB
.org 0x2000
ENTRY(cpu0_stack) # Initial stack is 8kB
.org 0x4000
ENTRY(cpu0_stack)
.org 0x2000 + STACK_SIZE
ENTRY(stext)
ENTRY(_stext)
+4 -4
View File
@@ -193,8 +193,8 @@ ENTRY(gdt_table)
.quad 0x00af9a000000ffff /* 0x0810 ring 0 code, 64-bit mode */
.quad 0x00cf92000000ffff /* 0x0818 ring 0 data */
.quad 0x00cffa000000ffff /* 0x0823 ring 3 code, compatibility */
.quad 0x00affa000000ffff /* 0x082b ring 3 code, 64-bit mode */
.quad 0x00cff2000000ffff /* 0x0833 ring 3 data */
.quad 0x00cff2000000ffff /* 0x082b ring 3 data */
.quad 0x00affa000000ffff /* 0x0833 ring 3 code, 64-bit mode */
.quad 0x0000000000000000 /* unused */
.fill 4*NR_CPUS,8,0 /* space for TSS and LDT per CPU */
@@ -243,8 +243,8 @@ ENTRY(idle_pg_table_l2)
identmap /* Too orangey for crows :-) */
.org 0x4000
ENTRY(cpu0_stack) # Initial stack is 8kB
ENTRY(cpu0_stack)
.org 0x6000
.org 0x4000 + STACK_SIZE
ENTRY(stext)
ENTRY(_stext)
+1 -1
View File
@@ -376,7 +376,7 @@ void arch_getdomaininfo_ctxt(
{
for ( i = 0; i < 16; i++ )
c->gdt_frames[i] =
l1_pgentry_to_pagenr(ed->arch.perdomain_ptes[i]);
l1_pgentry_to_pfn(ed->arch.perdomain_ptes[i]);
c->gdt_ents = GET_GDT_ENTRIES(ed);
}
c->guestos_ss = ed->arch.guestos_ss;
+39 -27
View File
@@ -304,7 +304,7 @@ void arch_vmx_do_launch(struct exec_domain *ed)
static void monitor_mk_pagetable(struct exec_domain *ed)
{
unsigned long mpfn;
l2_pgentry_t *mpl2e;
l2_pgentry_t *mpl2e, *phys_table;
struct pfn_info *mpfn_info;
struct domain *d = ed->domain;
@@ -312,20 +312,26 @@ static void monitor_mk_pagetable(struct exec_domain *ed)
ASSERT( mpfn_info );
mpfn = (unsigned long) (mpfn_info - frame_table);
mpl2e = (l2_pgentry_t *) map_domain_mem(mpfn << L1_PAGETABLE_SHIFT);
mpl2e = (l2_pgentry_t *) map_domain_mem(mpfn << PAGE_SHIFT);
memset(mpl2e, 0, PAGE_SIZE);
memcpy(&mpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
&idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
ed->arch.monitor_table = mk_pagetable(mpfn << L1_PAGETABLE_SHIFT);
ed->arch.monitor_table = mk_pagetable(mpfn << PAGE_SHIFT);
d->arch.shadow_mode = SHM_full_32;
mpl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
mk_l2_pgentry((__pa(d->arch.mm_perdomain_pt) & PAGE_MASK)
| __PAGE_HYPERVISOR);
phys_table = (l2_pgentry_t *) map_domain_mem(pagetable_val(
ed->arch.phys_table));
memcpy(d->arch.mm_perdomain_pt, phys_table,
ENTRIES_PER_L1_PAGETABLE * sizeof(l1_pgentry_t));
unmap_domain_mem(phys_table);
unmap_domain_mem(mpl2e);
}
@@ -466,6 +472,7 @@ int arch_final_setup_guestos(
phys_basetab = c->pt_base;
d->arch.pagetable = mk_pagetable(phys_basetab);
d->arch.phys_table = d->arch.pagetable;
if ( !get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], d->domain,
PGT_base_page_table) )
return -EINVAL;
@@ -628,12 +635,11 @@ long do_iopl(domid_t domain, unsigned int new_io_pl)
return 0;
}
unsigned long hypercall_create_continuation(
unsigned long __hypercall_create_continuation(
unsigned int op, unsigned int nr_args, ...)
{
struct mc_state *mcs = &mc_state[smp_processor_id()];
execution_context_t *ec;
unsigned long *preg;
unsigned int i;
va_list args;
@@ -653,10 +659,34 @@ unsigned long hypercall_create_continuation(
ec->eax = op;
ec->eip -= 2; /* re-execute 'int 0x82' */
for ( i = 0, preg = &ec->ebx; i < nr_args; i++, preg++ )
*preg = va_arg(args, unsigned long);
#else
preg = NULL; /* XXX x86/64 */
for ( i = 0; i < nr_args; i++ )
{
switch ( i )
{
case 0: ec->ebx = va_arg(args, unsigned long); break;
case 1: ec->ecx = va_arg(args, unsigned long); break;
case 2: ec->edx = va_arg(args, unsigned long); break;
case 3: ec->esi = va_arg(args, unsigned long); break;
case 4: ec->edi = va_arg(args, unsigned long); break;
case 5: ec->ebp = va_arg(args, unsigned long); break;
}
}
#elif defined(__x86_64__)
ec->rax = op;
ec->rip -= 2; /* re-execute 'syscall' */
for ( i = 0; i < nr_args; i++ )
{
switch ( i )
{
case 0: ec->rdi = va_arg(args, unsigned long); break;
case 1: ec->rsi = va_arg(args, unsigned long); break;
case 2: ec->rdx = va_arg(args, unsigned long); break;
case 3: ec->r10 = va_arg(args, unsigned long); break;
case 4: ec->r8 = va_arg(args, unsigned long); break;
case 5: ec->r9 = va_arg(args, unsigned long); break;
}
}
#endif
}
@@ -726,8 +756,6 @@ static void relinquish_list(struct domain *d, struct list_head *list)
#ifdef CONFIG_VMX
static void vmx_domain_relinquish_memory(struct exec_domain *ed)
{
struct domain *d = ed->domain;
/*
* Free VMCS
*/
@@ -736,22 +764,6 @@ static void vmx_domain_relinquish_memory(struct exec_domain *ed)
ed->arch.arch_vmx.vmcs = 0;
monitor_rm_pagetable(ed);
if (ed == d->exec_domain[0]) {
int i;
unsigned long pfn;
for (i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++) {
unsigned long l1e;
l1e = l1_pgentry_val(d->arch.mm_perdomain_pt[i]);
if (l1e & _PAGE_PRESENT) {
pfn = l1e >> PAGE_SHIFT;
free_domheap_page(&frame_table[pfn]);
}
}
}
}
#endif
+240 -43
View File
@@ -1,8 +1,8 @@
/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
/******************************************************************************
* arch/x86/memory.c
* arch/x86/mm.c
*
* Copyright (c) 2002-2004 K A Fraser
* Copyright (c) 2002-2005 K A Fraser
* Copyright (c) 2004 Christian Limpach
*
* This program is free software; you can redistribute it and/or modify
@@ -200,14 +200,14 @@ void write_ptbase(struct exec_domain *ed)
unsigned long pa;
#ifdef CONFIG_VMX
if ( unlikely(d->arch.shadow_mode) )
pa = ((d->arch.shadow_mode == SHM_full_32) ?
if ( unlikely(shadow_mode(d)) )
pa = ((shadow_mode(d) == SHM_full_32) ?
pagetable_val(ed->arch.monitor_table) :
pagetable_val(ed->arch.shadow_table));
else
pa = pagetable_val(ed->arch.pagetable);
#else
if ( unlikely(d->arch.shadow_mode) )
if ( unlikely(shadow_mode(d)) )
pa = pagetable_val(ed->arch.shadow_table);
else
pa = pagetable_val(ed->arch.pagetable);
@@ -226,7 +226,7 @@ static void __invalidate_shadow_ldt(struct exec_domain *d)
for ( i = 16; i < 32; i++ )
{
pfn = l1_pgentry_to_pagenr(d->arch.perdomain_ptes[i]);
pfn = l1_pgentry_to_pfn(d->arch.perdomain_ptes[i]);
if ( pfn == 0 ) continue;
d->arch.perdomain_ptes[i] = mk_l1_pgentry(0);
page = &frame_table[pfn];
@@ -249,11 +249,13 @@ static inline void invalidate_shadow_ldt(struct exec_domain *d)
static int alloc_segdesc_page(struct pfn_info *page)
{
unsigned long *descs = map_domain_mem((page-frame_table) << PAGE_SHIFT);
struct desc_struct *descs;
int i;
descs = map_domain_mem((page-frame_table) << PAGE_SHIFT);
for ( i = 0; i < 512; i++ )
if ( unlikely(!check_descriptor(&descs[i*2])) )
if ( unlikely(!check_descriptor(&descs[i])) )
goto fail;
unmap_domain_mem(descs);
@@ -275,8 +277,8 @@ int map_ldt_shadow_page(unsigned int off)
if ( unlikely(in_irq()) )
BUG();
__get_user(l1e, (unsigned long *)&linear_pg_table[(ed->arch.ldt_base >>
PAGE_SHIFT) + off]);
__get_user(l1e, (unsigned long *)
&linear_pg_table[l1_linear_offset(ed->arch.ldt_base) + off]);
if ( unlikely(!(l1e & _PAGE_PRESENT)) ||
unlikely(!get_page_and_type(&frame_table[l1e >> PAGE_SHIFT],
@@ -362,14 +364,14 @@ get_linear_pagetable(
if ( (l2_pgentry_val(l2e) >> PAGE_SHIFT) != pfn )
{
/* Make sure the mapped frame belongs to the correct domain. */
if ( unlikely(!get_page_from_pagenr(l2_pgentry_to_pagenr(l2e), d)) )
if ( unlikely(!get_page_from_pagenr(l2_pgentry_to_pfn(l2e), d)) )
return 0;
/*
* Make sure that the mapped frame is an already-validated L2 table.
* If so, atomically increment the count (checking for overflow).
*/
page = &frame_table[l2_pgentry_to_pagenr(l2e)];
page = &frame_table[l2_pgentry_to_pfn(l2e)];
y = page->u.inuse.type_info;
do {
x = y;
@@ -393,7 +395,7 @@ get_page_from_l1e(
l1_pgentry_t l1e, struct domain *d)
{
unsigned long l1v = l1_pgentry_val(l1e);
unsigned long pfn = l1_pgentry_to_pagenr(l1e);
unsigned long pfn = l1_pgentry_to_pfn(l1e);
struct pfn_info *page = &frame_table[pfn];
extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
@@ -447,7 +449,7 @@ get_page_from_l2e(
}
rc = get_page_and_type_from_pagenr(
l2_pgentry_to_pagenr(l2e),
l2_pgentry_to_pfn(l2e),
PGT_l1_page_table | (va_idx<<PGT_va_shift), d);
if ( unlikely(!rc) )
@@ -460,7 +462,7 @@ get_page_from_l2e(
static void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
{
unsigned long l1v = l1_pgentry_val(l1e);
unsigned long pfn = l1_pgentry_to_pagenr(l1e);
unsigned long pfn = l1_pgentry_to_pfn(l1e);
struct pfn_info *page = &frame_table[pfn];
struct domain *e;
@@ -510,7 +512,7 @@ static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
{
if ( (l2_pgentry_val(l2e) & _PAGE_PRESENT) &&
((l2_pgentry_val(l2e) >> PAGE_SHIFT) != pfn) )
put_page_and_type(&frame_table[l2_pgentry_to_pagenr(l2e)]);
put_page_and_type(&frame_table[l2_pgentry_to_pfn(l2e)]);
}
@@ -705,7 +707,7 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e)
if ( l1_pgentry_val(nl1e) & _PAGE_PRESENT )
{
/* Differ in mapping (bits 12-31), r/w (bit 1), or presence (bit 0)? */
/* Same mapping (bits 12-31), r/w (bit 1), and presence (bit 0)? */
if ( ((l1_pgentry_val(ol1e) ^ l1_pgentry_val(nl1e)) & ~0xffc) == 0 )
return update_l1e(pl1e, ol1e, nl1e);
@@ -770,7 +772,7 @@ void free_page_type(struct pfn_info *page, unsigned int type)
BUG();
}
if ( unlikely(d->arch.shadow_mode) &&
if ( unlikely(shadow_mode(d)) &&
(get_shadow_status(d, page_to_pfn(page)) & PSH_shadowed) )
{
unshadow_table(page_to_pfn(page), type);
@@ -1327,7 +1329,7 @@ int do_mmu_update(
struct pfn_info *page;
int rc = 0, okay = 1, i = 0, cpu = smp_processor_id();
unsigned int cmd, done = 0;
unsigned long prev_spfn = 0;
unsigned long prev_smfn = 0;
l1_pgentry_t *prev_spl1e = 0;
struct exec_domain *ed = current;
struct domain *d = ed->domain;
@@ -1338,6 +1340,9 @@ int do_mmu_update(
cleanup_writable_pagetable(d);
if ( unlikely(shadow_mode(d)) )
check_pagetable(d, ed->arch.pagetable, "pre-mmu"); /* debug */
/*
* If we are resuming after preemption, read how much work we have already
* done. This allows us to set the @done output parameter correctly.
@@ -1378,8 +1383,8 @@ int do_mmu_update(
{
if ( hypercall_preempt_check() )
{
rc = hypercall_create_continuation(
__HYPERVISOR_mmu_update, 3, ureqs,
rc = hypercall3_create_continuation(
__HYPERVISOR_mmu_update, ureqs,
(count - i) |
(FOREIGNDOM->id << MMU_UPDATE_PREEMPT_FDOM_SHIFT) |
MMU_UPDATE_PREEMPTED, pdone);
@@ -1432,12 +1437,12 @@ int do_mmu_update(
okay = mod_l1_entry((l1_pgentry_t *)va,
mk_l1_pgentry(req.val));
if ( unlikely(d->arch.shadow_mode) && okay &&
if ( unlikely(shadow_mode(d)) && okay &&
(get_shadow_status(d, page-frame_table) &
PSH_shadowed) )
{
shadow_l1_normal_pt_update(
req.ptr, req.val, &prev_spfn, &prev_spl1e);
req.ptr, req.val, &prev_smfn, &prev_spl1e);
put_shadow_status(d);
}
@@ -1451,7 +1456,7 @@ int do_mmu_update(
mk_l2_pgentry(req.val),
pfn);
if ( unlikely(d->arch.shadow_mode) && okay &&
if ( unlikely(shadow_mode(d)) && okay &&
(get_shadow_status(d, page-frame_table) &
PSH_shadowed) )
{
@@ -1489,7 +1494,7 @@ int do_mmu_update(
* If in log-dirty mode, mark the corresponding pseudo-physical
* page as dirty.
*/
if ( unlikely(d->arch.shadow_mode == SHM_logdirty) &&
if ( unlikely(shadow_mode(d) == SHM_logdirty) &&
mark_dirty(d, pfn) )
d->arch.shadow_dirty_block_count++;
@@ -1545,12 +1550,15 @@ int do_mmu_update(
if ( unlikely(pdone != NULL) )
__put_user(done + i, pdone);
if ( unlikely(shadow_mode(d)) )
check_pagetable(d, ed->arch.pagetable, "post-mmu"); /* debug */
UNLOCK_BIGLOCK(d);
return rc;
}
int do_update_va_mapping(unsigned long page_nr,
int do_update_va_mapping(unsigned long va,
unsigned long val,
unsigned long flags)
{
@@ -1562,7 +1570,7 @@ int do_update_va_mapping(unsigned long page_nr,
perfc_incrc(calls_to_update_va);
if ( unlikely(page_nr >= (HYPERVISOR_VIRT_START >> PAGE_SHIFT)) )
if ( unlikely(!__addr_ok(va)) )
return -EINVAL;
LOCK_BIGLOCK(d);
@@ -1574,18 +1582,18 @@ int do_update_va_mapping(unsigned long page_nr,
* the case of updating L2 entries.
*/
if ( unlikely(!mod_l1_entry(&linear_pg_table[page_nr],
if ( unlikely(!mod_l1_entry(&linear_pg_table[l1_linear_offset(va)],
mk_l1_pgentry(val))) )
err = -EINVAL;
if ( unlikely(d->arch.shadow_mode) )
if ( unlikely(shadow_mode(d)) )
{
unsigned long sval;
unsigned long sval = 0;
l1pte_propagate_from_guest(d, &val, &sval);
if ( unlikely(__put_user(sval, ((unsigned long *)(
&shadow_linear_pg_table[page_nr])))) )
&shadow_linear_pg_table[l1_linear_offset(va)])))) )
{
/*
* Since L2's are guranteed RW, failure indicates the page was not
@@ -1599,8 +1607,8 @@ int do_update_va_mapping(unsigned long page_nr,
* the PTE in the PT-holding page. We need the machine frame number
* for this.
*/
if ( d->arch.shadow_mode == SHM_logdirty )
mark_dirty(d, va_to_l1mfn(page_nr << PAGE_SHIFT));
if ( shadow_mode(d) == SHM_logdirty )
mark_dirty(d, va_to_l1mfn(va));
check_pagetable(d, ed->arch.pagetable, "va"); /* debug */
}
@@ -1612,7 +1620,7 @@ int do_update_va_mapping(unsigned long page_nr,
unlikely(flags & UVMF_FLUSH_TLB) )
local_flush_tlb();
else if ( unlikely(flags & UVMF_INVLPG) )
__flush_tlb_one(page_nr << PAGE_SHIFT);
__flush_tlb_one(va);
if ( unlikely(deferred_ops & DOP_RELOAD_LDT) )
(void)map_ldt_shadow_page(0);
@@ -1622,7 +1630,7 @@ int do_update_va_mapping(unsigned long page_nr,
return err;
}
int do_update_va_mapping_otherdomain(unsigned long page_nr,
int do_update_va_mapping_otherdomain(unsigned long va,
unsigned long val,
unsigned long flags,
domid_t domid)
@@ -1641,7 +1649,7 @@ int do_update_va_mapping_otherdomain(unsigned long page_nr,
return -ESRCH;
}
rc = do_update_va_mapping(page_nr, val, flags);
rc = do_update_va_mapping(va, val, flags);
put_domain(d);
percpu_info[cpu].foreign = NULL;
@@ -1651,6 +1659,182 @@ int do_update_va_mapping_otherdomain(unsigned long page_nr,
/*************************
* Descriptor Tables
*/
void destroy_gdt(struct exec_domain *ed)
{
int i;
unsigned long pfn;
for ( i = 0; i < 16; i++ )
{
if ( (pfn = l1_pgentry_to_pfn(ed->arch.perdomain_ptes[i])) != 0 )
put_page_and_type(&frame_table[pfn]);
ed->arch.perdomain_ptes[i] = mk_l1_pgentry(0);
}
}
long set_gdt(struct exec_domain *ed,
unsigned long *frames,
unsigned int entries)
{
struct domain *d = ed->domain;
/* NB. There are 512 8-byte entries per GDT page. */
int i = 0, nr_pages = (entries + 511) / 512;
struct desc_struct *vgdt;
unsigned long pfn;
/* Check the first page in the new GDT. */
if ( (pfn = frames[0]) >= max_page )
goto fail;
/* The first page is special because Xen owns a range of entries in it. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
{
/* GDT checks failed: try zapping the Xen reserved entries. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) )
goto fail;
vgdt = map_domain_mem(pfn << PAGE_SHIFT);
memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0,
NR_RESERVED_GDT_ENTRIES*8);
unmap_domain_mem(vgdt);
put_page_and_type(&frame_table[pfn]);
/* Okay, we zapped the entries. Now try the GDT checks again. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
goto fail;
}
/* Check the remaining pages in the new GDT. */
for ( i = 1; i < nr_pages; i++ )
if ( ((pfn = frames[i]) >= max_page) ||
!get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
goto fail;
/* Copy reserved GDT entries to the new GDT. */
vgdt = map_domain_mem(frames[0] << PAGE_SHIFT);
memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY,
gdt_table + FIRST_RESERVED_GDT_ENTRY,
NR_RESERVED_GDT_ENTRIES*8);
unmap_domain_mem(vgdt);
/* Tear down the old GDT. */
destroy_gdt(ed);
/* Install the new GDT. */
for ( i = 0; i < nr_pages; i++ )
ed->arch.perdomain_ptes[i] =
mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
SET_GDT_ADDRESS(ed, GDT_VIRT_START(ed));
SET_GDT_ENTRIES(ed, entries);
return 0;
fail:
while ( i-- > 0 )
put_page_and_type(&frame_table[frames[i]]);
return -EINVAL;
}
long do_set_gdt(unsigned long *frame_list, unsigned int entries)
{
int nr_pages = (entries + 511) / 512;
unsigned long frames[16];
long ret;
if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) )
return -EINVAL;
if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
return -EFAULT;
LOCK_BIGLOCK(current->domain);
if ( (ret = set_gdt(current, frames, entries)) == 0 )
{
local_flush_tlb();
__asm__ __volatile__ ("lgdt %0" : "=m" (*current->arch.gdt));
}
UNLOCK_BIGLOCK(current->domain);
return ret;
}
long do_update_descriptor(
unsigned long pa, unsigned long word1, unsigned long word2)
{
unsigned long pfn = pa >> PAGE_SHIFT;
struct desc_struct *gdt_pent, d;
struct pfn_info *page;
struct exec_domain *ed;
long ret = -EINVAL;
d.a = (u32)word1;
d.b = (u32)word2;
LOCK_BIGLOCK(current->domain);
if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(&d) ) {
UNLOCK_BIGLOCK(current->domain);
return -EINVAL;
}
page = &frame_table[pfn];
if ( unlikely(!get_page(page, current->domain)) ) {
UNLOCK_BIGLOCK(current->domain);
return -EINVAL;
}
/* Check if the given frame is in use in an unsafe context. */
switch ( page->u.inuse.type_info & PGT_type_mask )
{
case PGT_gdt_page:
/* Disallow updates of Xen-reserved descriptors in the current GDT. */
for_each_exec_domain(current->domain, ed) {
if ( (l1_pgentry_to_pfn(ed->arch.perdomain_ptes[0]) == pfn) &&
(((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
(((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
goto out;
}
if ( unlikely(!get_page_type(page, PGT_gdt_page)) )
goto out;
break;
case PGT_ldt_page:
if ( unlikely(!get_page_type(page, PGT_ldt_page)) )
goto out;
break;
default:
if ( unlikely(!get_page_type(page, PGT_writable_page)) )
goto out;
break;
}
/* All is good so make the update. */
gdt_pent = map_domain_mem(pa);
memcpy(gdt_pent, &d, 8);
unmap_domain_mem(gdt_pent);
put_page_type(page);
ret = 0; /* success */
out:
put_page(page);
UNLOCK_BIGLOCK(current->domain);
return ret;
}
/*************************
* Writable Pagetables
*/
@@ -1696,7 +1880,7 @@ void ptwr_flush(const int which)
PTWR_PRINT_WHICH, ptep, pte);
pte &= ~_PAGE_RW;
if ( unlikely(d->arch.shadow_mode) )
if ( unlikely(shadow_mode(d)) )
{
/* Write-protect the p.t. page in the shadow page table. */
l1pte_propagate_from_guest(d, &pte, &spte);
@@ -1755,7 +1939,7 @@ void ptwr_flush(const int which)
l1pte_propagate_from_guest(
d, &l1_pgentry_val(nl1e),
&l1_pgentry_val(sl1e[i]));
put_page_type(&frame_table[l1_pgentry_to_pagenr(nl1e)]);
put_page_type(&frame_table[l1_pgentry_to_pfn(nl1e)]);
}
continue;
}
@@ -1788,7 +1972,7 @@ void ptwr_flush(const int which)
* STEP 3. Reattach the L1 p.t. page into the current address space.
*/
if ( (which == PTWR_PT_ACTIVE) && likely(!d->arch.shadow_mode) )
if ( (which == PTWR_PT_ACTIVE) && likely(!shadow_mode(d)) )
{
pl2e = &linear_l2_table[ptwr_info[cpu].ptinfo[which].l2_idx];
*pl2e = mk_l2_pgentry(l2_pgentry_val(*pl2e) | _PAGE_PRESENT);
@@ -1816,6 +2000,10 @@ int ptwr_do_page_fault(unsigned long addr)
int which, cpu = smp_processor_id();
u32 l2_idx;
#ifdef __x86_64__
return 0; /* Writable pagetables need fixing for x86_64. */
#endif
/*
* Attempt to read the PTE that maps the VA being accessed. By checking for
* PDE validity in the L2 we avoid many expensive fixups in __get_user().
@@ -1892,7 +2080,7 @@ int ptwr_do_page_fault(unsigned long addr)
/* For safety, disconnect the L1 p.t. page from current space. */
if ( (which == PTWR_PT_ACTIVE) &&
likely(!current->domain->arch.shadow_mode) )
likely(!shadow_mode(current->domain)) )
{
*pl2e = mk_l2_pgentry(l2e & ~_PAGE_PRESENT);
#if 1
@@ -2313,7 +2501,6 @@ void audit_domain(struct domain *d)
}
/* PHASE 3 */
list_ent = d->page_list.next;
for ( i = 0; (list_ent != &d->page_list); i++ )
{
@@ -2334,7 +2521,12 @@ void audit_domain(struct domain *d)
if ( pt[i] & _PAGE_PRESENT )
{
unsigned long l1pfn = pt[i]>>PAGE_SHIFT;
struct pfn_info *l1page = &frame_table[l1pfn];
struct pfn_info *l1page;
if (l1pfn>max_page)
continue;
l1page = &frame_table[l1pfn];
if ( page_get_owner(l1page) == d )
adjust(l1page, 1, 1);
@@ -2355,7 +2547,12 @@ void audit_domain(struct domain *d)
if ( pt[i] & _PAGE_PRESENT )
{
unsigned long l1pfn = pt[i]>>PAGE_SHIFT;
struct pfn_info *l1page = &frame_table[l1pfn];
struct pfn_info *l1page;
if (l1pfn>max_page)
continue;
l1page = &frame_table[l1pfn];
if ( (page_get_owner(l1page) != d) ||
(l1pfn < 0x100) || (l1pfn > max_page) )
+5 -5
View File
@@ -298,19 +298,21 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
unsigned long cpu_initialized;
void __init cpu_init(void)
{
extern void percpu_traps_init(void);
int nr = smp_processor_id();
struct tss_struct *t = &init_tss[nr];
unsigned char idt_load[10];
if ( test_and_set_bit(nr, &cpu_initialized) )
panic("CPU#%d already initialized!!!\n", nr);
printk("Initializing CPU#%d\n", nr);
/* Set up GDT and IDT. */
SET_GDT_ENTRIES(current, DEFAULT_GDT_ENTRIES);
SET_GDT_ADDRESS(current, DEFAULT_GDT_ADDRESS);
__asm__ __volatile__ ( "lgdt %0" : "=m" (*current->arch.gdt) );
__asm__ __volatile__ ( "lidt %0" : "=m" (idt_descr) );
*(unsigned short *)(&idt_load[0]) = (IDT_ENTRIES*sizeof(idt_entry_t))-1;
*(unsigned long *)(&idt_load[2]) = (unsigned long)idt_tables[nr];
__asm__ __volatile__ ( "lidt %0" : "=m" (idt_load) );
/* No nested task. */
__asm__ __volatile__ ( "pushf ; andw $0xbfff,(%"__OP"sp) ; popf" );
@@ -336,8 +338,6 @@ void __init cpu_init(void)
CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
#undef CD
percpu_traps_init();
/* Install correct page table. */
write_ptbase(current);
+130 -107
View File
@@ -73,11 +73,11 @@ static void free_shadow_state(struct domain *d)
/* Free the head page. */
free_shadow_page(
d, &frame_table[x->spfn_and_flags & PSH_pfn_mask]);
d, &frame_table[x->smfn_and_flags & PSH_pfn_mask]);
/* Reinitialise the head node. */
x->pfn = 0;
x->spfn_and_flags = 0;
x->smfn_and_flags = 0;
n = x->next;
x->next = NULL;
@@ -88,11 +88,11 @@ static void free_shadow_state(struct domain *d)
{
/* Free the shadow page. */
free_shadow_page(
d, &frame_table[x->spfn_and_flags & PSH_pfn_mask]);
d, &frame_table[x->smfn_and_flags & PSH_pfn_mask]);
/* Re-initialise the chain node. */
x->pfn = 0;
x->spfn_and_flags = 0;
x->smfn_and_flags = 0;
/* Add to the free list. */
n = x->next;
@@ -113,14 +113,14 @@ static inline int clear_shadow_page(
{
unsigned long *p;
int restart = 0;
struct pfn_info *spage = &frame_table[x->spfn_and_flags & PSH_pfn_mask];
struct pfn_info *spage = &frame_table[x->smfn_and_flags & PSH_pfn_mask];
switch ( spage->u.inuse.type_info & PGT_type_mask )
{
/* We clear L2 pages by zeroing the guest entries. */
case PGT_l2_page_table:
p = map_domain_mem((spage - frame_table) << PAGE_SHIFT);
if (d->arch.shadow_mode == SHM_full_32)
if ( shadow_mode(d) == SHM_full_32 )
memset(p, 0, ENTRIES_PER_L2_PAGETABLE * sizeof(*p));
else
memset(p, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE * sizeof(*p));
@@ -419,7 +419,7 @@ static inline struct pfn_info *alloc_shadow_page(struct domain *d)
void unshadow_table(unsigned long gpfn, unsigned int type)
{
unsigned long spfn;
unsigned long smfn;
struct domain *d = page_get_owner(&frame_table[gpfn]);
SH_VLOG("unshadow_table type=%08x gpfn=%08lx", type, gpfn);
@@ -431,15 +431,15 @@ void unshadow_table(unsigned long gpfn, unsigned int type)
* guests there won't be a race here as this CPU was the one that
* cmpxchg'ed the page to invalid.
*/
spfn = __shadow_status(d, gpfn) & PSH_pfn_mask;
smfn = __shadow_status(d, gpfn) & PSH_pfn_mask;
delete_shadow_status(d, gpfn);
free_shadow_page(d, &frame_table[spfn]);
free_shadow_page(d, &frame_table[smfn]);
}
#ifdef CONFIG_VMX
void vmx_shadow_clear_state(struct domain *d)
{
SH_VVLOG("vmx_clear_shadow_state: \n");
SH_VVLOG("vmx_clear_shadow_state:");
clear_shadow_state(d);
}
#endif
@@ -453,7 +453,7 @@ unsigned long shadow_l2_table(
l2_pgentry_t *spl2e = 0;
unsigned long guest_gpfn;
__get_machine_to_phys(d, guest_gpfn, gpfn);
guest_gpfn = __mfn_to_gpfn(d, gpfn);
SH_VVLOG("shadow_l2_table( %08lx )", gpfn);
@@ -471,9 +471,13 @@ unsigned long shadow_l2_table(
#ifdef __i386__
/* Install hypervisor and 2x linear p.t. mapings. */
if ( d->arch.shadow_mode == SHM_full_32 )
if ( shadow_mode(d) == SHM_full_32 )
{
#ifdef CONFIG_VMX
vmx_update_shadow_state(d->exec_domain[0], gpfn, spfn);
#else
panic("Shadow Full 32 not yet implemented without VMX\n");
#endif
}
else
{
@@ -499,7 +503,7 @@ unsigned long shadow_l2_table(
}
#endif
if ( d->arch.shadow_mode != SHM_full_32 )
if ( shadow_mode(d) != SHM_full_32 )
unmap_domain_mem(spl2e);
SH_VLOG("shadow_l2_table( %08lx -> %08lx)", gpfn, spfn);
@@ -510,13 +514,13 @@ static void shadow_map_l1_into_current_l2(unsigned long va)
{
struct exec_domain *ed = current;
struct domain *d = ed->domain;
unsigned long *gpl1e, *spl1e, gpl2e, spl2e, gl1pfn, sl1pfn=0, sl1ss;
unsigned long *gpl1e, *spl1e, gl2e, sl2e, gl1pfn, sl1pfn=0, sl1ss;
struct pfn_info *sl1pfn_info;
int i;
__guest_get_pl2e(ed, va, &gpl2e);
__guest_get_l2e(ed, va, &gl2e);
gl1pfn = gpl2e >> PAGE_SHIFT;
gl1pfn = gl2e >> PAGE_SHIFT;
sl1ss = __shadow_status(d, gl1pfn);
if ( !(sl1ss & PSH_shadowed) )
@@ -534,10 +538,10 @@ static void shadow_map_l1_into_current_l2(unsigned long va)
set_shadow_status(d, gl1pfn, PSH_shadowed | sl1pfn);
l2pde_general(d, &gpl2e, &spl2e, sl1pfn);
l2pde_general(d, &gl2e, &sl2e, sl1pfn);
__guest_set_pl2e(ed, va, gpl2e);
__shadow_set_pl2e(ed, va, spl2e);
__guest_set_l2e(ed, va, gl2e);
__shadow_set_l2e(ed, va, sl2e);
gpl1e = (unsigned long *) &(linear_pg_table[
(va>>L1_PAGETABLE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1)]);
@@ -554,9 +558,9 @@ static void shadow_map_l1_into_current_l2(unsigned long va)
SH_VVLOG("4b: was shadowed, l2 missing ( %08lx )", sl1pfn);
sl1pfn = sl1ss & PSH_pfn_mask;
l2pde_general(d, &gpl2e, &spl2e, sl1pfn);
__guest_set_pl2e(ed, va, gpl2e);
__shadow_set_pl2e(ed, va, spl2e);
l2pde_general(d, &gl2e, &sl2e, sl1pfn);
__guest_set_l2e(ed, va, gl2e);
__shadow_set_l2e(ed, va, sl2e);
}
}
@@ -576,7 +580,7 @@ void vmx_shadow_invlpg(struct domain *d, unsigned long va)
return;
}
host_pfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT];
host_pfn = phys_to_machine_mapping(gpte >> PAGE_SHIFT);
spte = (host_pfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
if (__put_user(spte, (unsigned long *)
@@ -588,7 +592,7 @@ void vmx_shadow_invlpg(struct domain *d, unsigned long va)
int shadow_fault(unsigned long va, long error_code)
{
unsigned long gpte, spte;
unsigned long gpte, spte = 0;
struct exec_domain *ed = current;
struct domain *d = ed->domain;
@@ -628,14 +632,14 @@ int shadow_fault(unsigned long va, long error_code)
if ( unlikely(__get_user(gpte, (unsigned long *)
&linear_pg_table[va >> PAGE_SHIFT])) )
{
SH_VVLOG("shadow_fault - EXIT: read gpte faulted" );
SH_VVLOG("shadow_fault - EXIT: read gpte faulted2" );
shadow_unlock(d);
return 0;
}
if ( unlikely(!(gpte & _PAGE_PRESENT)) )
{
SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte );
SH_VVLOG("shadow_fault - EXIT: gpte not present2 (%lx)",gpte );
shadow_unlock(d);
return 0;
}
@@ -691,20 +695,20 @@ int shadow_fault(unsigned long va, long error_code)
void shadow_l1_normal_pt_update(
unsigned long pa, unsigned long gpte,
unsigned long *prev_spfn_ptr,
unsigned long *prev_smfn_ptr,
l1_pgentry_t **prev_spl1e_ptr)
{
unsigned long spfn, spte, prev_spfn = *prev_spfn_ptr;
unsigned long smfn, spte, prev_smfn = *prev_smfn_ptr;
l1_pgentry_t *spl1e, *prev_spl1e = *prev_spl1e_ptr;
/* N.B. To get here, we know the l1 page *must* be shadowed. */
SH_VVLOG("shadow_l1_normal_pt_update pa=%08lx, gpte=%08lx, "
"prev_spfn=%08lx, prev_spl1e=%p\n",
pa, gpte, prev_spfn, prev_spl1e);
"prev_smfn=%08lx, prev_spl1e=%p",
pa, gpte, prev_smfn, prev_spl1e);
spfn = __shadow_status(current->domain, pa >> PAGE_SHIFT) & PSH_pfn_mask;
smfn = __shadow_status(current->domain, pa >> PAGE_SHIFT) & PSH_pfn_mask;
if ( spfn == prev_spfn )
if ( smfn == prev_smfn )
{
spl1e = prev_spl1e;
}
@@ -712,8 +716,8 @@ void shadow_l1_normal_pt_update(
{
if ( prev_spl1e != NULL )
unmap_domain_mem( prev_spl1e );
spl1e = (l1_pgentry_t *)map_domain_mem(spfn << PAGE_SHIFT);
*prev_spfn_ptr = spfn;
spl1e = (l1_pgentry_t *)map_domain_mem(smfn << PAGE_SHIFT);
*prev_smfn_ptr = smfn;
*prev_spl1e_ptr = spl1e;
}
@@ -721,24 +725,24 @@ void shadow_l1_normal_pt_update(
spl1e[(pa & ~PAGE_MASK) / sizeof(l1_pgentry_t)] = mk_l1_pgentry(spte);
}
void shadow_l2_normal_pt_update(unsigned long pa, unsigned long gpte)
void shadow_l2_normal_pt_update(unsigned long pa, unsigned long gpde)
{
unsigned long spfn, spte;
unsigned long sl2mfn, spde;
l2_pgentry_t *spl2e;
unsigned long s_sh;
unsigned long sl1mfn;
/* N.B. To get here, we know the l2 page *must* be shadowed. */
SH_VVLOG("shadow_l2_normal_pt_update pa=%08lx, gpte=%08lx",pa,gpte);
SH_VVLOG("shadow_l2_normal_pt_update pa=%08lx, gpde=%08lx",pa,gpde);
spfn = __shadow_status(current->domain, pa >> PAGE_SHIFT) & PSH_pfn_mask;
sl2mfn = __shadow_status(current->domain, pa >> PAGE_SHIFT) & PSH_pfn_mask;
s_sh = (gpte & _PAGE_PRESENT) ?
__shadow_status(current->domain, gpte >> PAGE_SHIFT) : 0;
sl1mfn = (gpde & _PAGE_PRESENT) ?
__shadow_status(current->domain, gpde >> PAGE_SHIFT) : 0;
/* XXXX Should mark guest pte as DIRTY and ACCESSED too! */
l2pde_general(current->domain, &gpte, &spte, s_sh);
spl2e = (l2_pgentry_t *)map_domain_mem(spfn << PAGE_SHIFT);
spl2e[(pa & ~PAGE_MASK) / sizeof(l2_pgentry_t)] = mk_l2_pgentry(spte);
l2pde_general(current->domain, &gpde, &spde, sl1mfn);
spl2e = (l2_pgentry_t *)map_domain_mem(sl2mfn << PAGE_SHIFT);
spl2e[(pa & ~PAGE_MASK) / sizeof(l2_pgentry_t)] = mk_l2_pgentry(spde);
unmap_domain_mem(spl2e);
}
@@ -751,23 +755,36 @@ void shadow_l2_normal_pt_update(unsigned long pa, unsigned long gpte)
#if SHADOW_DEBUG
// BUG: these are not SMP safe...
static int sh_l2_present;
static int sh_l1_present;
static int errors;
char * sh_check_name;
#define FAIL(_f, _a...) \
do { \
printk("XXX %s-FAIL (%d,%d)" _f " g=%08lx s=%08lx\n", \
sh_check_name, level, i, ## _a , gpte, spte); \
BUG(); \
#define virt_to_phys2(adr) ({ \
unsigned long _a = (unsigned long)(adr); \
unsigned long _pte = l1_pgentry_val( \
shadow_linear_pg_table[_a >> PAGE_SHIFT]); \
unsigned long _pa = _pte & PAGE_MASK; \
_pa | (_a & ~PAGE_MASK); \
})
#define FAIL(_f, _a...) \
do { \
printk("XXX %s-FAIL (%d,%d)" _f " g=%08lx s=%08lx &g=%08lx &s=%08lx" \
" pa(&g)=%08lx pa(&s)=%08lx\n", \
sh_check_name, level, i, ## _a , gpte, spte, pgpte, pspte, \
virt_to_phys2(pgpte), virt_to_phys2(pspte)); \
errors++; \
} while ( 0 )
static int check_pte(
struct domain *d, unsigned long gpte, unsigned long spte,
struct domain *d, unsigned long *pgpte, unsigned long *pspte,
int level, int i)
{
unsigned long mask, gpfn, spfn;
unsigned long guest_gpfn;
unsigned gpte = *pgpte;
unsigned spte = *pspte;
unsigned long mask, gpfn, smfn;
if ( (spte == 0) || (spte == 0xdeadface) || (spte == 0x00000E00) )
return 1; /* always safe */
@@ -781,7 +798,7 @@ static int check_pte(
if ( !(gpte & _PAGE_PRESENT) )
FAIL("Guest not present yet shadow is");
mask = ~(_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW|0xFFFFF000);
mask = ~(_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW|PAGE_MASK);
if ( (spte & mask) != (gpte & mask) )
FAIL("Corrupt?");
@@ -798,10 +815,10 @@ static int check_pte(
if ( (spte & _PAGE_RW ) && !((gpte & _PAGE_RW) && (gpte & _PAGE_DIRTY)) )
FAIL("RW2 coherence");
spfn = spte >> PAGE_SHIFT;
smfn = spte >> PAGE_SHIFT;
gpfn = gpte >> PAGE_SHIFT;
if ( gpfn == spfn )
if ( gpfn == smfn )
{
if ( level > 1 )
FAIL("Linear map ???"); /* XXX this will fail on BSD */
@@ -811,20 +828,9 @@ static int check_pte(
if ( level < 2 )
FAIL("Shadow in L1 entry?");
if (d->arch.shadow_mode == SHM_full_32) {
guest_gpfn = phys_to_machine_mapping[gpfn];
if ( __shadow_status(d, guest_gpfn) != (PSH_shadowed | spfn) )
FAIL("spfn problem g.sf=%08lx",
__shadow_status(d, guest_gpfn) );
} else {
if ( __shadow_status(d, gpfn) != (PSH_shadowed | spfn) )
FAIL("spfn problem g.sf=%08lx",
__shadow_status(d, gpfn) );
}
if ( __shadow_status(d, gpfn) != (PSH_shadowed | smfn) )
FAIL("smfn problem g.sf=%08lx",
__shadow_status(d, gpfn) );
}
return 1;
@@ -832,17 +838,17 @@ static int check_pte(
static int check_l1_table(
struct domain *d, unsigned long va,
unsigned long g2, unsigned long s2)
struct domain *d,
unsigned long g2mfn, unsigned long s2mfn)
{
int i;
unsigned long *gpl1e, *spl1e;
gpl1e = map_domain_mem(g2 << PAGE_SHIFT);
spl1e = map_domain_mem(s2 << PAGE_SHIFT);
gpl1e = map_domain_mem(g2mfn << PAGE_SHIFT);
spl1e = map_domain_mem(s2mfn << PAGE_SHIFT);
for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ )
check_pte(d, gpl1e[i], spl1e[i], 1, i);
check_pte(d, &gpl1e[i], &spl1e[i], 1, i);
unmap_domain_mem(spl1e);
unmap_domain_mem(gpl1e);
@@ -853,49 +859,46 @@ static int check_l1_table(
#define FAILPT(_f, _a...) \
do { \
printk("XXX FAIL %s-PT" _f "\n", s, ## _a ); \
BUG(); \
errors++; \
} while ( 0 )
int check_pagetable(struct domain *d, pagetable_t pt, char *s)
void check_pagetable(struct domain *d, pagetable_t pt, char *s)
{
unsigned long gptbase = pagetable_val(pt);
unsigned long gpfn, spfn;
unsigned long ptbase_pfn, smfn, ss;
unsigned long i;
l2_pgentry_t *gpl2e, *spl2e;
unsigned long host_gpfn = 0;
unsigned long ptbase_mfn = 0;
int cpu = current->processor;
errors = 0;
sh_check_name = s;
SH_VVLOG("%s-PT Audit", s);
sh_l2_present = sh_l1_present = 0;
gpfn = gptbase >> PAGE_SHIFT;
ptbase_pfn = gptbase >> PAGE_SHIFT;
ptbase_mfn = __gpfn_to_mfn(d, ptbase_pfn);
__get_phys_to_machine(d, host_gpfn, gpfn);
ss = __shadow_status(d, ptbase_pfn);
if ( ! (__shadow_status(d, gpfn) & PSH_shadowed) )
if ( ! (ss & PSH_shadowed) )
{
printk("%s-PT %08lx not shadowed\n", s, gptbase);
if( __shadow_status(d, gpfn) != 0 ) BUG();
return 0;
if ( ss != 0 )
BUG();
return;
}
spfn = __shadow_status(d, gpfn) & PSH_pfn_mask;
smfn = ss & PSH_pfn_mask;
if ( ! __shadow_status(d, gpfn) == (PSH_shadowed | spfn) )
FAILPT("ptbase shadow inconsistent1");
if ( ss != (PSH_shadowed | smfn) )
FAILPT("ptbase shadow inconsistent1");
if (d->arch.shadow_mode == SHM_full_32)
{
host_gpfn = phys_to_machine_mapping[gpfn];
gpl2e = (l2_pgentry_t *) map_domain_mem( host_gpfn << PAGE_SHIFT );
} else
gpl2e = (l2_pgentry_t *) map_domain_mem( gpfn << PAGE_SHIFT );
spl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
gpl2e = (l2_pgentry_t *) map_domain_mem( ptbase_mfn << PAGE_SHIFT );
spl2e = (l2_pgentry_t *) map_domain_mem( smfn << PAGE_SHIFT );
if ( memcmp(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
&gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
@@ -916,40 +919,60 @@ int check_pagetable(struct domain *d, pagetable_t pt, char *s)
if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >>
L2_PAGETABLE_SHIFT]) !=
((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) )
((smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) )
FAILPT("hypervisor shadow linear map inconsistent %08lx %08lx",
l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >>
L2_PAGETABLE_SHIFT]),
(spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
(smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
if (d->arch.shadow_mode != SHM_full_32) {
if ( shadow_mode(d) != SHM_full_32 ) {
// BUG: this shouldn't be using exec_domain[0] here...
if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
((__pa(page_get_owner(&frame_table[gpfn])->arch.mm_perdomain_pt) |
((__pa(page_get_owner(&frame_table[ptbase_pfn])->arch.mm_perdomain_pt) |
__PAGE_HYPERVISOR))) )
FAILPT("hypervisor per-domain map inconsistent");
}
/* Check the whole L2. */
for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
check_pte(d, l2_pgentry_val(gpl2e[i]), l2_pgentry_val(spl2e[i]), 2, i);
check_pte(d, &l2_pgentry_val(gpl2e[i]), &l2_pgentry_val(spl2e[i]), 2, i);
/* Go back and recurse. */
for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
{
unsigned long gl1pfn = l2_pgentry_val(gpl2e[i]) >> PAGE_SHIFT;
unsigned long gl1mfn = __gpfn_to_mfn(d, gl1pfn);
unsigned long sl1mfn = l2_pgentry_val(spl2e[i]) >> PAGE_SHIFT;
if ( l2_pgentry_val(spl2e[i]) != 0 )
check_l1_table(
d, i << L2_PAGETABLE_SHIFT,
l2_pgentry_val(gpl2e[i]) >> PAGE_SHIFT,
l2_pgentry_val(spl2e[i]) >> PAGE_SHIFT);
{
// First check to see if this guest page is currently the active
// PTWR page. If so, then we compare the (old) cached copy of the
// guest page to the shadow, and not the currently writable (and
// thus potentially out-of-sync) guest page.
//
if ( ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va &&
(i == ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) &&
likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
{
gl1mfn = (__pa(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].page) >>
PAGE_SHIFT);
}
check_l1_table(d, gl1mfn, sl1mfn);
}
}
unmap_domain_mem(spl2e);
unmap_domain_mem(gpl2e);
SH_VVLOG("PT verified : l2_present = %d, l1_present = %d\n",
SH_VVLOG("PT verified : l2_present = %d, l1_present = %d",
sh_l2_present, sh_l1_present);
return 1;
if ( errors )
BUG();
return;
}
#endif
#endif // SHADOW_DEBUG
+10 -16
View File
@@ -388,33 +388,27 @@ static int cpucount;
void __init start_secondary(void)
{
unsigned int cpu = cpucount;
/* 6 bytes suitable for passing to LIDT instruction. */
unsigned char idt_load[6];
extern void percpu_traps_init(void);
extern void cpu_init(void);
set_current(idle_task[cpu]);
/*
* Dont put anything before smp_callin(), SMP
* booting is too fragile that we want to limit the
* things done here to the most necessary things.
*/
cpu_init();
smp_callin();
while (!atomic_read(&smp_commenced))
rep_nop();
/*
* At this point, boot CPU has fully initialised the IDT. It is
* now safe to make ourselves a private copy.
*/
idt_tables[cpu] = xmalloc_array(idt_entry_t, IDT_ENTRIES);
memcpy(idt_tables[cpu], idt_table, IDT_ENTRIES*sizeof(idt_entry_t));
*(unsigned short *)(&idt_load[0]) = (IDT_ENTRIES*sizeof(idt_entry_t))-1;
*(unsigned long *)(&idt_load[2]) = (unsigned long)idt_tables[cpu];
__asm__ __volatile__ ( "lidt %0" : "=m" (idt_load) );
percpu_traps_init();
cpu_init();
smp_callin();
while (!atomic_read(&smp_commenced))
rep_nop();
/*
* low-memory mappings have been cleared, flush them from the local TLBs
+89 -38
View File
@@ -149,6 +149,11 @@ static inline int do_trap(int trapnr, char *str,
if ( !GUEST_FAULT(regs) )
goto xen_fault;
#ifndef NDEBUG
if ( (ed->arch.traps[trapnr].address == 0) && (ed->domain->id == 0) )
goto xen_fault;
#endif
ti = current->arch.traps + trapnr;
tb->flags = TBF_EXCEPTION;
tb->cs = ti->cs;
@@ -267,6 +272,12 @@ asmlinkage int do_page_fault(struct xen_regs *regs)
perfc_incrc(page_faults);
#if 0
printk("do_page_fault(addr=0x%08lx, error_code=%d)\n",
addr, regs->error_code);
show_registers(regs);
#endif
if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
{
LOCK_BIGLOCK(d);
@@ -314,6 +325,11 @@ asmlinkage int do_page_fault(struct xen_regs *regs)
if ( !GUEST_FAULT(regs) )
goto xen_fault;
#ifndef NDEBUG
if ( (ed->arch.traps[TRAP_page_fault].address == 0) && (d->id == 0) )
goto xen_fault;
#endif
propagate_page_fault(addr, regs->error_code);
return 0;
@@ -512,7 +528,7 @@ asmlinkage int do_general_protection(struct xen_regs *regs)
/* Emulate some simple privileged instructions when exec'ed in ring 1. */
if ( (regs->error_code == 0) &&
RING_1(regs) &&
GUESTOS_FAULT(regs) &&
emulate_privileged_op(regs) )
return 0;
@@ -523,6 +539,12 @@ asmlinkage int do_general_protection(struct xen_regs *regs)
return 0;
#endif
#ifndef NDEBUG
if ( (ed->arch.traps[TRAP_gp_fault].address == 0) &&
(ed->domain->id == 0) )
goto gp_in_kernel;
#endif
/* Pass on GPF as is. */
ti = current->arch.traps + 13;
tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
@@ -553,19 +575,55 @@ asmlinkage int do_general_protection(struct xen_regs *regs)
return 0;
}
unsigned long nmi_softirq_reason;
static void nmi_softirq(void)
{
if ( dom0 == NULL )
return;
if ( test_and_clear_bit(0, &nmi_softirq_reason) )
send_guest_virq(dom0->exec_domain[0], VIRQ_PARITY_ERR);
if ( test_and_clear_bit(1, &nmi_softirq_reason) )
send_guest_virq(dom0->exec_domain[0], VIRQ_IO_ERR);
}
asmlinkage void mem_parity_error(struct xen_regs *regs)
{
console_force_unlock();
printk("\n\nNMI - MEMORY ERROR\n");
fatal_trap(TRAP_nmi, regs);
/* Clear and disable the parity-error line. */
outb((inb(0x61)&15)|4,0x61);
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
set_bit(0, &nmi_softirq_reason);
raise_softirq(NMI_SOFTIRQ);
case 'i': /* 'ignore' */
break;
default: /* 'fatal' */
console_force_unlock();
printk("\n\nNMI - MEMORY ERROR\n");
fatal_trap(TRAP_nmi, regs);
}
}
asmlinkage void io_check_error(struct xen_regs *regs)
{
console_force_unlock();
/* Clear and disable the I/O-error line. */
outb((inb(0x61)&15)|8,0x61);
printk("\n\nNMI - I/O ERROR\n");
fatal_trap(TRAP_nmi, regs);
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
set_bit(0, &nmi_softirq_reason);
raise_softirq(NMI_SOFTIRQ);
case 'i': /* 'ignore' */
break;
default: /* 'fatal' */
console_force_unlock();
printk("\n\nNMI - I/O ERROR\n");
fatal_trap(TRAP_nmi, regs);
}
}
static void unknown_nmi_error(unsigned char reason)
@@ -579,27 +637,17 @@ asmlinkage void do_nmi(struct xen_regs *regs, unsigned long reason)
{
++nmi_count(smp_processor_id());
#if CONFIG_X86_LOCAL_APIC
if ( nmi_watchdog )
nmi_watchdog_tick(regs);
else
#endif
if ( reason & 0x80 )
mem_parity_error(regs);
else if ( reason & 0x40 )
io_check_error(regs);
else if ( !nmi_watchdog )
unknown_nmi_error((unsigned char)(reason&0xff));
}
unsigned long nmi_softirq_reason;
static void nmi_softirq(void)
{
if ( dom0 == NULL )
return;
if ( test_and_clear_bit(0, &nmi_softirq_reason) )
send_guest_virq(dom0->exec_domain[0], VIRQ_PARITY_ERR);
if ( test_and_clear_bit(1, &nmi_softirq_reason) )
send_guest_virq(dom0->exec_domain[0], VIRQ_IO_ERR);
}
asmlinkage int math_state_restore(struct xen_regs *regs)
{
/* Prevent recursion. */
@@ -706,8 +754,8 @@ void set_tss_desc(unsigned int n, void *addr)
void __init trap_init(void)
{
extern void doublefault_init(void);
doublefault_init();
extern void percpu_traps_init(void);
extern void cpu_init(void);
/*
* Note that interrupt gates are always used, rather than trap gates. We
@@ -745,13 +793,9 @@ void __init trap_init(void)
/* CPU0 uses the master IDT. */
idt_tables[0] = idt_table;
/*
* Should be a barrier for any external CPU state.
*/
{
extern void cpu_init(void);
cpu_init();
}
percpu_traps_init();
cpu_init();
open_softirq(NMI_SOFTIRQ, nmi_softirq);
}
@@ -769,8 +813,8 @@ long do_set_trap_table(trap_info_t *traps)
if ( hypercall_preempt_check() )
{
UNLOCK_BIGLOCK(current->domain);
return hypercall_create_continuation(
__HYPERVISOR_set_trap_table, 1, traps);
return hypercall1_create_continuation(
__HYPERVISOR_set_trap_table, traps);
}
if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
@@ -816,6 +860,13 @@ long do_fpu_taskswitch(void)
}
#if defined(__i386__)
#define DB_VALID_ADDR(_a) \
((_a) <= (PAGE_OFFSET - 4))
#elif defined(__x86_64__)
#define DB_VALID_ADDR(_a) \
((_a) >= HYPERVISOR_VIRT_END) || ((_a) <= (HYPERVISOR_VIRT_START-8))
#endif
long set_debugreg(struct exec_domain *p, int reg, unsigned long value)
{
int i;
@@ -823,22 +874,22 @@ long set_debugreg(struct exec_domain *p, int reg, unsigned long value)
switch ( reg )
{
case 0:
if ( value > (PAGE_OFFSET-4) ) return -EPERM;
if ( !DB_VALID_ADDR(value) ) return -EPERM;
if ( p == current )
__asm__ ( "mov %0, %%db0" : : "r" (value) );
break;
case 1:
if ( value > (PAGE_OFFSET-4) ) return -EPERM;
if ( !DB_VALID_ADDR(value) ) return -EPERM;
if ( p == current )
__asm__ ( "mov %0, %%db1" : : "r" (value) );
break;
case 2:
if ( value > (PAGE_OFFSET-4) ) return -EPERM;
if ( !DB_VALID_ADDR(value) ) return -EPERM;
if ( p == current )
__asm__ ( "mov %0, %%db2" : : "r" (value) );
break;
case 3:
if ( value > (PAGE_OFFSET-4) ) return -EPERM;
if ( !DB_VALID_ADDR(value) ) return -EPERM;
if ( p == current )
__asm__ ( "mov %0, %%db3" : : "r" (value) );
break;
+14 -8
View File
@@ -36,6 +36,8 @@
#include <asm/vmx_vmcs.h>
#include <public/io/ioreq.h>
#ifdef CONFIG_VMX
int vmcs_size;
unsigned int opt_vmx_debug_level;
@@ -123,13 +125,13 @@ static int vmx_do_page_fault(unsigned long va, unsigned long error_code)
/*
* Set up guest page directory cache to make linear_pt_table[] work.
*/
__guest_get_pl2e(ed, va, &gpde);
__guest_get_l2e(ed, va, &gpde);
if (!(gpde & _PAGE_PRESENT))
return 0;
index = (va >> L2_PAGETABLE_SHIFT);
if (!l2_pgentry_val(ed->arch.guest_pl2e_cache[index])) {
pfn = phys_to_machine_mapping[gpde >> PAGE_SHIFT];
pfn = phys_to_machine_mapping(gpde >> PAGE_SHIFT);
VMX_DBG_LOG(DBG_LEVEL_VMMU, "vmx_do_page_fault: pagetable = %lx\n",
pagetable_val(ed->arch.pagetable));
@@ -301,10 +303,10 @@ inline unsigned long gva_to_gpa(unsigned long gva)
unsigned long gpde, gpte, pfn, index;
struct exec_domain *ed = current;
__guest_get_pl2e(ed, gva, &gpde);
__guest_get_l2e(ed, gva, &gpde);
index = (gva >> L2_PAGETABLE_SHIFT);
pfn = phys_to_machine_mapping[gpde >> PAGE_SHIFT];
pfn = phys_to_machine_mapping(gpde >> PAGE_SHIFT);
ed->arch.guest_pl2e_cache[index] =
mk_l2_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
@@ -451,8 +453,8 @@ static void mov_to_cr(int gp, int cr, struct xen_regs *regs)
/*
* The guest CR3 must be pointing to the guest physical.
*/
if (!(pfn = phys_to_machine_mapping[
d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT]))
if (!(pfn = phys_to_machine_mapping(
d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)))
{
VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value = %lx\n",
d->arch.arch_vmx.cpu_cr3);
@@ -504,7 +506,7 @@ static void mov_to_cr(int gp, int cr, struct xen_regs *regs)
* removed some translation or changed page attributes.
* We simply invalidate the shadow.
*/
pfn = phys_to_machine_mapping[value >> PAGE_SHIFT];
pfn = phys_to_machine_mapping(value >> PAGE_SHIFT);
if ((pfn << PAGE_SHIFT) != pagetable_val(d->arch.pagetable))
__vmx_bug(regs);
vmx_shadow_clear_state(d->domain);
@@ -521,7 +523,7 @@ static void mov_to_cr(int gp, int cr, struct xen_regs *regs)
"Invalid CR3 value=%lx\n", value);
domain_crash(); /* need to take a clean path */
}
pfn = phys_to_machine_mapping[value >> PAGE_SHIFT];
pfn = phys_to_machine_mapping(value >> PAGE_SHIFT);
vmx_shadow_clear_state(d->domain);
d->arch.pagetable = mk_pagetable(pfn << PAGE_SHIFT);
shadow_mk_pagetable(d);
@@ -927,6 +929,8 @@ asmlinkage void vmx_vmexit_handler(struct xen_regs regs)
default:
__vmx_bug(&regs); /* should not happen */
}
vmx_intr_assist(d);
return;
}
@@ -937,3 +941,5 @@ asmlinkage void load_cr2(void)
local_irq_disable();
asm volatile("movl %0,%%cr2": :"r" (d->arch.arch_vmx.cpu_cr2));
}
#endif /* CONFIG_VMX */
+4
View File
@@ -32,6 +32,8 @@
#include <public/io/ioreq.h>
#include <asm/vmx_platform.h>
#ifdef CONFIG_VMX
extern long do_block();
#if defined (__i386__)
@@ -386,3 +388,5 @@ void vmx_do_resume(struct exec_domain *d)
if (!test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags))
vmx_intr_assist(d);
}
#endif /* CONFIG_VMX */
+4 -1
View File
@@ -34,6 +34,8 @@
#include <xen/sched.h>
#include <asm/current.h>
#ifdef CONFIG_VMX
#define DECODE_success 1
#define DECODE_failure 0
@@ -369,7 +371,7 @@ static int inst_copy_from_guest(char *buf, unsigned long guest_eip, int inst_len
printk("inst_copy_from_guest- EXIT: read gpte faulted" );
return 0;
}
mfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT];
mfn = phys_to_machine_mapping(gpte >> PAGE_SHIFT);
ma = (mfn << PAGE_SHIFT) | (guest_eip & (PAGE_SIZE - 1));
inst_start = (unsigned char *)map_domain_mem(ma);
@@ -553,3 +555,4 @@ void handle_mmio(unsigned long va, unsigned long gpte, unsigned long gpa)
domain_crash();
}
#endif /* CONFIG_VMX */
+8 -38
View File
@@ -33,6 +33,8 @@
#include <public/io/ioreq.h>
#include <asm/domain_page.h>
#ifdef CONFIG_VMX
struct vmcs_struct *alloc_vmcs(void)
{
struct vmcs_struct *vmcs;
@@ -118,7 +120,7 @@ int vmx_setup_platform(struct exec_domain *d, execution_context_t *context)
addr = context->edi;
offset = (addr & ~PAGE_MASK);
addr = round_pgdown(addr);
mpfn = phys_to_machine_mapping[addr >> PAGE_SHIFT];
mpfn = phys_to_machine_mapping(addr >> PAGE_SHIFT);
p = map_domain_mem(mpfn << PAGE_SHIFT);
e820p = (struct e820entry *) ((unsigned long) p + offset);
@@ -131,52 +133,20 @@ int vmx_setup_platform(struct exec_domain *d, execution_context_t *context)
}
if (gpfn == 0) {
VMX_DBG_LOG(DBG_LEVEL_1, "No shared Page ?\n");
printk("No shared Page ?\n");
unmap_domain_mem(p);
return -1;
}
unmap_domain_mem(p);
mpfn = phys_to_machine_mapping[gpfn];
mpfn = phys_to_machine_mapping(gpfn);
p = map_domain_mem(mpfn << PAGE_SHIFT);
ASSERT(p != NULL);
d->arch.arch_vmx.vmx_platform.shared_page_va = (unsigned long) p;
return 0;
}
/*
* Add <guest pfn, machine pfn> mapping to per-domain mapping. Full
* virtualization does not need per-domain mapping.
*/
static int add_mapping_perdomain(struct exec_domain *d, unsigned long gpfn,
unsigned long mpfn)
{
struct pfn_info *page;
unsigned long pfn = 0;
/*
* We support up to 4GB memory for a guest at this point
*/
if (gpfn > ENTRIES_PER_L2_PAGETABLE * ENTRIES_PER_L1_PAGETABLE)
return -1;
if (!(l1_pgentry_val(d->domain->arch.mm_perdomain_pt[
gpfn >> (L2_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)]) & _PAGE_PRESENT))
{
page = (struct pfn_info *) alloc_domheap_page(NULL);
if (!page) {
return -1;
}
pfn = (unsigned long) (page - frame_table);
d->domain->arch.mm_perdomain_pt[gpfn >> (L2_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)] =
mk_l1_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
}
phys_to_machine_mapping[gpfn] = mpfn;
return 0;
}
void vmx_do_launch(struct exec_domain *ed)
{
/* Update CR3, GDT, LDT, TR */
@@ -204,7 +174,6 @@ void vmx_do_launch(struct exec_domain *ed)
d->arch.min_pfn = min(d->arch.min_pfn, pfn);
d->arch.max_pfn = max(d->arch.max_pfn, pfn);
list_ent = frame_table[pfn].list.next;
add_mapping_perdomain(ed, i, pfn);
}
spin_unlock(&d->page_alloc_lock);
@@ -502,3 +471,4 @@ void vm_resume_fail(unsigned long eflags)
BUG();
}
#endif /* CONFIG_VMX */
+9 -5
View File
@@ -20,6 +20,7 @@
#include <xen/event.h>
#include <xen/elf.h>
#include <xen/kernel.h>
#include <asm/shadow.h>
/* No ring-3 access in initial page tables. */
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
@@ -261,7 +262,7 @@ int construct_dom0(struct domain *d,
for ( count = 0; count < nr_pt_pages; count++ )
{
*l1tab = mk_l1_pgentry(l1_pgentry_val(*l1tab) & ~_PAGE_RW);
page = &frame_table[l1_pgentry_to_pagenr(*l1tab)];
page = &frame_table[l1_pgentry_to_pfn(*l1tab)];
if ( count == 0 )
{
page->u.inuse.type_info &= ~PGT_type_mask;
@@ -377,10 +378,13 @@ int construct_dom0(struct domain *d,
new_thread(ed, dsi.v_kernentry, vstack_end, vstartinfo_start);
#if 0 /* XXXXX DO NOT CHECK IN ENABLED !!! (but useful for testing so leave) */
shadow_lock(&d->mm);
shadow_mode_enable(d, SHM_test);
shadow_unlock(&d->mm);
#ifndef NDEBUG
if (0) /* XXXXX DO NOT CHECK IN ENABLED !!! (but useful for testing so leave) */
{
shadow_lock(d);
shadow_mode_enable(d, SHM_test);
shadow_unlock(d);
}
#endif
return 0;
+15 -7
View File
@@ -596,7 +596,7 @@ ENTRY(nmi)
# Okay, its almost a normal NMI tick. We can only process it if:
# A. We are the outermost Xen activation (in which case we have
# the selectors safely saved on our stack)
# B. DS-GS all contain sane Xen values.
# B. DS and ES contain sane Xen values.
# In all other cases we bail without touching DS-GS, as we have
# interrupted an enclosing Xen activation in tricky prologue or
# epilogue code.
@@ -644,11 +644,11 @@ nmi_parity_err:
orb $0x4,%al
outb %al,$0x61
cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
je restore_all_xen
je nmi_out
bts $0,%ss:SYMBOL_NAME(nmi_softirq_reason)
bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
je restore_all_xen
je nmi_out
movl $(__HYPERVISOR_DS),%edx # nmi=fatal
movl %edx,%ds
movl %edx,%es
@@ -656,7 +656,15 @@ nmi_parity_err:
push %edx
call SYMBOL_NAME(mem_parity_error)
addl $4,%esp
jmp ret_from_intr
nmi_out:movl %ss:XREGS_eflags(%esp),%eax
movb %ss:XREGS_cs(%esp),%al
testl $(3|X86_EFLAGS_VM),%eax
jz restore_all_xen
movl $(__HYPERVISOR_DS),%edx
movl %edx,%ds
movl %edx,%es
GET_CURRENT(%ebx)
jmp test_all_events
nmi_io_err:
# Clear and disable the I/O-error line
@@ -664,11 +672,11 @@ nmi_io_err:
orb $0x8,%al
outb %al,$0x61
cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
je restore_all_xen
je nmi_out
bts $1,%ss:SYMBOL_NAME(nmi_softirq_reason)
bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
je restore_all_xen
je nmi_out
movl $(__HYPERVISOR_DS),%edx # nmi=fatal
movl %edx,%ds
movl %edx,%es
@@ -676,7 +684,7 @@ nmi_io_err:
push %edx
call SYMBOL_NAME(io_check_error)
addl $4,%esp
jmp ret_from_intr
jmp nmi_out
ENTRY(setup_vm86_frame)
+6 -174
View File
@@ -164,7 +164,7 @@ void subarch_init_memory(struct domain *dom_xen)
}
/* M2P table is mappable read-only by privileged domains. */
m2p_start_mfn = l2_pgentry_to_pagenr(
m2p_start_mfn = l2_pgentry_to_pfn(
idle_pg_table[l2_table_offset(RDWR_MPT_VIRT_START)]);
for ( i = 0; i < 1024; i++ )
{
@@ -212,9 +212,10 @@ long do_stack_switch(unsigned long ss, unsigned long esp)
/* Returns TRUE if given descriptor is valid for GDT or LDT. */
int check_descriptor(unsigned long *d)
int check_descriptor(struct desc_struct *d)
{
unsigned long base, limit, a = d[0], b = d[1];
unsigned long base, limit;
u32 a = d->a, b = d->b;
/* A not-present descriptor will always fault, so is safe. */
if ( !(b & _SEGMENT_P) )
@@ -298,8 +299,8 @@ int check_descriptor(unsigned long *d)
if ( !(b & _SEGMENT_G) )
goto bad; /* too dangerous; too hard to work out... */
limit = (limit >> 12) - 1;
d[0] &= ~0x0ffff; d[0] |= limit & 0x0ffff;
d[1] &= ~0xf0000; d[1] |= limit & 0xf0000;
d->a &= ~0x0ffff; d->a |= limit & 0x0ffff;
d->b &= ~0xf0000; d->b |= limit & 0xf0000;
}
}
@@ -310,175 +311,6 @@ int check_descriptor(unsigned long *d)
}
void destroy_gdt(struct exec_domain *ed)
{
int i;
unsigned long pfn;
for ( i = 0; i < 16; i++ )
{
if ( (pfn = l1_pgentry_to_pagenr(ed->arch.perdomain_ptes[i])) != 0 )
put_page_and_type(&frame_table[pfn]);
ed->arch.perdomain_ptes[i] = mk_l1_pgentry(0);
}
}
long set_gdt(struct exec_domain *ed,
unsigned long *frames,
unsigned int entries)
{
struct domain *d = ed->domain;
/* NB. There are 512 8-byte entries per GDT page. */
int i = 0, nr_pages = (entries + 511) / 512;
struct desc_struct *vgdt;
unsigned long pfn;
/* Check the first page in the new GDT. */
if ( (pfn = frames[0]) >= max_page )
goto fail;
/* The first page is special because Xen owns a range of entries in it. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
{
/* GDT checks failed: try zapping the Xen reserved entries. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) )
goto fail;
vgdt = map_domain_mem(pfn << PAGE_SHIFT);
memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0,
NR_RESERVED_GDT_ENTRIES*8);
unmap_domain_mem(vgdt);
put_page_and_type(&frame_table[pfn]);
/* Okay, we zapped the entries. Now try the GDT checks again. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
goto fail;
}
/* Check the remaining pages in the new GDT. */
for ( i = 1; i < nr_pages; i++ )
if ( ((pfn = frames[i]) >= max_page) ||
!get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
goto fail;
/* Copy reserved GDT entries to the new GDT. */
vgdt = map_domain_mem(frames[0] << PAGE_SHIFT);
memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY,
gdt_table + FIRST_RESERVED_GDT_ENTRY,
NR_RESERVED_GDT_ENTRIES*8);
unmap_domain_mem(vgdt);
/* Tear down the old GDT. */
destroy_gdt(ed);
/* Install the new GDT. */
for ( i = 0; i < nr_pages; i++ )
ed->arch.perdomain_ptes[i] =
mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
SET_GDT_ADDRESS(ed, GDT_VIRT_START(ed));
SET_GDT_ENTRIES(ed, entries);
return 0;
fail:
while ( i-- > 0 )
put_page_and_type(&frame_table[frames[i]]);
return -EINVAL;
}
long do_set_gdt(unsigned long *frame_list, unsigned int entries)
{
int nr_pages = (entries + 511) / 512;
unsigned long frames[16];
long ret;
if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) )
return -EINVAL;
if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
return -EFAULT;
LOCK_BIGLOCK(current->domain);
if ( (ret = set_gdt(current, frames, entries)) == 0 )
{
local_flush_tlb();
__asm__ __volatile__ ("lgdt %0" : "=m" (*current->arch.gdt));
}
UNLOCK_BIGLOCK(current->domain);
return ret;
}
long do_update_descriptor(
unsigned long pa, unsigned long word1, unsigned long word2)
{
unsigned long *gdt_pent, pfn = pa >> PAGE_SHIFT, d[2];
struct pfn_info *page;
struct exec_domain *ed;
long ret = -EINVAL;
d[0] = word1;
d[1] = word2;
LOCK_BIGLOCK(current->domain);
if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) ) {
UNLOCK_BIGLOCK(current->domain);
return -EINVAL;
}
page = &frame_table[pfn];
if ( unlikely(!get_page(page, current->domain)) ) {
UNLOCK_BIGLOCK(current->domain);
return -EINVAL;
}
/* Check if the given frame is in use in an unsafe context. */
switch ( page->u.inuse.type_info & PGT_type_mask )
{
case PGT_gdt_page:
/* Disallow updates of Xen-reserved descriptors in the current GDT. */
for_each_exec_domain(current->domain, ed) {
if ( (l1_pgentry_to_pagenr(ed->arch.perdomain_ptes[0]) == pfn) &&
(((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
(((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
goto out;
}
if ( unlikely(!get_page_type(page, PGT_gdt_page)) )
goto out;
break;
case PGT_ldt_page:
if ( unlikely(!get_page_type(page, PGT_ldt_page)) )
goto out;
break;
default:
if ( unlikely(!get_page_type(page, PGT_writable_page)) )
goto out;
break;
}
/* All is good so make the update. */
gdt_pent = map_domain_mem(pa);
memcpy(gdt_pent, d, 8);
unmap_domain_mem(gdt_pent);
put_page_type(page);
ret = 0; /* success */
out:
put_page(page);
UNLOCK_BIGLOCK(current->domain);
return ret;
}
#ifdef MEMORY_GUARD
void *memguard_init(void *heap_start)
+25 -24
View File
@@ -7,6 +7,7 @@
#include <xen/console.h>
#include <xen/mm.h>
#include <xen/irq.h>
#include <asm/flushtlb.h>
static int kstack_depth_to_print = 8*20;
@@ -114,6 +115,7 @@ void show_registers(struct xen_regs *regs)
regs->esi, regs->edi, regs->ebp, esp);
printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
ds, es, fs, gs, ss);
printk("cr3: %08lx\n", read_cr3());
show_stack((unsigned long *)&regs->esp);
}
@@ -175,32 +177,31 @@ asmlinkage void do_double_fault(void)
__asm__ __volatile__ ( "hlt" );
}
void __init doublefault_init(void)
{
/*
* Make a separate task for double faults. This will get us debug output if
* we blow the kernel stack.
*/
struct tss_struct *tss = &doublefault_tss;
memset(tss, 0, sizeof(*tss));
tss->ds = __HYPERVISOR_DS;
tss->es = __HYPERVISOR_DS;
tss->ss = __HYPERVISOR_DS;
tss->esp = (unsigned long)
&doublefault_stack[DOUBLEFAULT_STACK_SIZE];
tss->__cr3 = __pa(idle_pg_table);
tss->cs = __HYPERVISOR_CS;
tss->eip = (unsigned long)do_double_fault;
tss->eflags = 2;
tss->bitmap = IOBMP_INVALID_OFFSET;
_set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY,
(unsigned long)tss, 235, 9);
set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3);
}
void __init percpu_traps_init(void)
{
if ( smp_processor_id() == 0 )
{
/*
* Make a separate task for double faults. This will get us debug
* output if we blow the kernel stack.
*/
struct tss_struct *tss = &doublefault_tss;
memset(tss, 0, sizeof(*tss));
tss->ds = __HYPERVISOR_DS;
tss->es = __HYPERVISOR_DS;
tss->ss = __HYPERVISOR_DS;
tss->esp = (unsigned long)
&doublefault_stack[DOUBLEFAULT_STACK_SIZE];
tss->__cr3 = __pa(idle_pg_table);
tss->cs = __HYPERVISOR_CS;
tss->eip = (unsigned long)do_double_fault;
tss->eflags = 2;
tss->bitmap = IOBMP_INVALID_OFFSET;
_set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY,
(unsigned long)tss, 235, 9);
}
set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3);
}
long set_fast_trap(struct exec_domain *p, int idx)
+1 -1
View File
@@ -294,7 +294,7 @@ int construct_dom0(struct domain *d,
for ( count = 0; count < nr_pt_pages; count++ )
{
*l1tab = mk_l1_pgentry(l1_pgentry_val(*l1tab) & ~_PAGE_RW);
page = &frame_table[l1_pgentry_to_pagenr(*l1tab)];
page = &frame_table[l1_pgentry_to_pfn(*l1tab)];
/* Read-only mapping + PGC_allocated + page-table page. */
page->count_info = PGC_allocated | 3;
+23 -7
View File
@@ -11,16 +11,25 @@
#include <asm/apicdef.h>
#include <public/xen.h>
/*
* %rax = hypercall vector
* %rdi, %rsi, %rdx, %r10, %r8, %9 = hypercall arguments
* %r11, %rcx = SYSCALL-saved %rflags and %rip
* NB. We must move %r10 to %rcx for C function-calling ABI.
*/
ENTRY(hypercall)
movl $0x0833,8(%rsp)
sti
movl $__GUEST_SS,8(%rsp)
pushq %r11
pushq $0x082b
pushq $__GUEST_CS
pushq %rcx
pushq $0
SAVE_ALL
andq $(NR_hypercalls-1),%rax
leaq SYMBOL_NAME(exception_table)(%rip),%rcx
callq *(%rcx,%rax,8)
movq %r10,%rcx
andq $(NR_hypercalls-1),%rax
leaq SYMBOL_NAME(hypercall_table)(%rip),%rbx
callq *(%rbx,%rax,8)
RESTORE_ALL
addq $8,%rsp
popq %rcx
@@ -38,11 +47,12 @@ restore_all_xen:
error_code:
SAVE_ALL
sti
movq %rsp,%rdi
movl XREGS_entry_vector(%rsp),%eax
leaq SYMBOL_NAME(exception_table)(%rip),%rdx
callq *(%rdx,%rax,8)
jmp restore_all_xen
jmp restore_all_xen
ENTRY(divide_error)
pushq $0
@@ -133,7 +143,13 @@ ENTRY(double_fault)
jmp error_code
ENTRY(nmi)
iretq
pushq $0
SAVE_ALL
inb $0x61,%al
movl %eax,%esi # reason
movq %rsp,%rdi # regs
call SYMBOL_NAME(do_nmi)
jmp restore_all_xen
.data
+21 -235
View File
@@ -199,7 +199,7 @@ void subarch_init_memory(struct domain *dom_xen)
l2e = l3_pgentry_to_l2(l3e)[l2_table_offset(v)];
if ( !(l2_pgentry_val(l2e) & _PAGE_PRESENT) )
continue;
m2p_start_mfn = l2_pgentry_to_pagenr(l2e);
m2p_start_mfn = l2_pgentry_to_pfn(l2e);
for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ )
{
@@ -240,99 +240,38 @@ long do_stack_switch(unsigned long ss, unsigned long esp)
/* Returns TRUE if given descriptor is valid for GDT or LDT. */
int check_descriptor(unsigned long *d)
int check_descriptor(struct desc_struct *d)
{
unsigned long base, limit, a = d[0], b = d[1];
u32 a = d->a, b = d->b;
/* A not-present descriptor will always fault, so is safe. */
if ( !(b & _SEGMENT_P) )
goto good;
/*
* We don't allow a DPL of zero. There is no legitimate reason for
* specifying DPL==0, and it gets rather dangerous if we also accept call
* gates (consider a call gate pointing at another guestos descriptor with
* DPL 0 -- this would get the OS ring-0 privileges).
*/
if ( (b & _SEGMENT_DPL) == 0 )
/* The guest can only safely be executed in ring 3. */
if ( (b & _SEGMENT_DPL) != 3 )
goto bad;
if ( !(b & _SEGMENT_S) )
{
/*
* System segment:
* 1. Don't allow interrupt or trap gates as they belong in the IDT.
* 2. Don't allow TSS descriptors or task gates as we don't
* virtualise x86 tasks.
* 3. Don't allow LDT descriptors because they're unnecessary and
* I'm uneasy about allowing an LDT page to contain LDT
* descriptors. In any case, Xen automatically creates the
* required descriptor when reloading the LDT register.
* 4. We allow call gates but they must not jump to a private segment.
*/
/* Disallow everything but call gates. */
if ( (b & _SEGMENT_TYPE) != 0xc00 )
goto bad;
#if 0
/* Can't allow far jump to a Xen-private segment. */
if ( !VALID_CODESEL(a>>16) )
goto bad;
#endif
/* Reserved bits must be zero. */
if ( (b & 0xe0) != 0 )
goto bad;
/* No base/limit check is needed for a call gate. */
/* Any code or data segment is okay. No base/limit checking. */
if ( (b & _SEGMENT_S) )
goto good;
}
/* Check that base is at least a page away from Xen-private area. */
base = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
if ( base >= (PAGE_OFFSET - PAGE_SIZE) )
/* Invalid type 0 is harmless. It is used for 2nd half of a call gate. */
if ( (b & _SEGMENT_TYPE) == 0x000 )
goto good;
/* Everything but a call gate is discarded here. */
if ( (b & _SEGMENT_TYPE) != 0xc00 )
goto bad;
/* Check and truncate the limit if necessary. */
limit = (b&0xf0000) | (a&0xffff);
limit++; /* We add one because limit is inclusive. */
if ( (b & _SEGMENT_G) )
limit <<= 12;
if ( (b & (_SEGMENT_CODE | _SEGMENT_EC)) == _SEGMENT_EC )
{
/*
* Grows-down limit check.
* NB. limit == 0xFFFFF provides no access (if G=1).
* limit == 0x00000 provides 4GB-4kB access (if G=1).
*/
if ( (base + limit) > base )
{
limit = -(base & PAGE_MASK);
goto truncate;
}
}
else
{
/*
* Grows-up limit check.
* NB. limit == 0xFFFFF provides 4GB access (if G=1).
* limit == 0x00000 provides 4kB access (if G=1).
*/
if ( ((base + limit) <= base) ||
((base + limit) > PAGE_OFFSET) )
{
limit = PAGE_OFFSET - base;
truncate:
if ( !(b & _SEGMENT_G) )
goto bad; /* too dangerous; too hard to work out... */
limit = (limit >> 12) - 1;
d[0] &= ~0x0ffff; d[0] |= limit & 0x0ffff;
d[1] &= ~0xf0000; d[1] |= limit & 0xf0000;
}
}
/* Can't allow far jump to a Xen-private segment. */
if ( !VALID_CODESEL(a>>16) )
goto bad;
/* Reserved bits must be zero. */
if ( (b & 0xe0) != 0 )
goto bad;
good:
return 1;
bad:
@@ -340,159 +279,6 @@ int check_descriptor(unsigned long *d)
}
void destroy_gdt(struct exec_domain *ed)
{
int i;
unsigned long pfn;
for ( i = 0; i < 16; i++ )
{
if ( (pfn = l1_pgentry_to_pagenr(ed->arch.perdomain_ptes[i])) != 0 )
put_page_and_type(&frame_table[pfn]);
ed->arch.perdomain_ptes[i] = mk_l1_pgentry(0);
}
}
long set_gdt(struct exec_domain *ed,
unsigned long *frames,
unsigned int entries)
{
struct domain *d = ed->domain;
/* NB. There are 512 8-byte entries per GDT page. */
int i = 0, nr_pages = (entries + 511) / 512;
struct desc_struct *vgdt;
unsigned long pfn;
/* Check the first page in the new GDT. */
if ( (pfn = frames[0]) >= max_page )
goto fail;
/* The first page is special because Xen owns a range of entries in it. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
{
/* GDT checks failed: try zapping the Xen reserved entries. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) )
goto fail;
vgdt = map_domain_mem(pfn << PAGE_SHIFT);
memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0,
NR_RESERVED_GDT_ENTRIES*8);
unmap_domain_mem(vgdt);
put_page_and_type(&frame_table[pfn]);
/* Okay, we zapped the entries. Now try the GDT checks again. */
if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
goto fail;
}
/* Check the remaining pages in the new GDT. */
for ( i = 1; i < nr_pages; i++ )
if ( ((pfn = frames[i]) >= max_page) ||
!get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
goto fail;
/* Copy reserved GDT entries to the new GDT. */
vgdt = map_domain_mem(frames[0] << PAGE_SHIFT);
memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY,
gdt_table + FIRST_RESERVED_GDT_ENTRY,
NR_RESERVED_GDT_ENTRIES*8);
unmap_domain_mem(vgdt);
/* Tear down the old GDT. */
destroy_gdt(ed);
/* Install the new GDT. */
for ( i = 0; i < nr_pages; i++ )
ed->arch.perdomain_ptes[i] =
mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
SET_GDT_ADDRESS(ed, GDT_VIRT_START(ed));
SET_GDT_ENTRIES(ed, entries);
return 0;
fail:
while ( i-- > 0 )
put_page_and_type(&frame_table[frames[i]]);
return -EINVAL;
}
long do_set_gdt(unsigned long *frame_list, unsigned int entries)
{
int nr_pages = (entries + 511) / 512;
unsigned long frames[16];
long ret;
if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) )
return -EINVAL;
if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
return -EFAULT;
if ( (ret = set_gdt(current, frames, entries)) == 0 )
{
local_flush_tlb();
__asm__ __volatile__ ("lgdt %0" : "=m" (*current->arch.gdt));
}
return ret;
}
long do_update_descriptor(
unsigned long pa, unsigned long word1, unsigned long word2)
{
unsigned long *gdt_pent, pfn = pa >> PAGE_SHIFT, d[2];
struct pfn_info *page;
long ret = -EINVAL;
d[0] = word1;
d[1] = word2;
if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) )
return -EINVAL;
page = &frame_table[pfn];
if ( unlikely(!get_page(page, current->domain)) )
return -EINVAL;
/* Check if the given frame is in use in an unsafe context. */
switch ( page->u.inuse.type_info & PGT_type_mask )
{
case PGT_gdt_page:
/* Disallow updates of Xen-reserved descriptors in the current GDT. */
if ( (l1_pgentry_to_pagenr(current->arch.perdomain_ptes[0]) == pfn) &&
(((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
(((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
goto out;
if ( unlikely(!get_page_type(page, PGT_gdt_page)) )
goto out;
break;
case PGT_ldt_page:
if ( unlikely(!get_page_type(page, PGT_ldt_page)) )
goto out;
break;
default:
if ( unlikely(!get_page_type(page, PGT_writable_page)) )
goto out;
break;
}
/* All is good so make the update. */
gdt_pent = map_domain_mem(pa);
memcpy(gdt_pent, d, 8);
unmap_domain_mem(gdt_pent);
put_page_type(page);
ret = 0; /* success */
out:
put_page(page);
return ret;
}
#ifdef MEMORY_GUARD
#define ALLOC_PT(_level) \
+50 -32
View File
@@ -129,10 +129,7 @@ void show_page_walk(unsigned long addr)
printk(" L1 = %p\n", page);
}
#define DOUBLEFAULT_STACK_SIZE 1024
static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
asmlinkage void double_fault(void);
asmlinkage void do_double_fault(struct xen_regs *regs)
{
/* Disable the NMI watchdog. It's useless now. */
@@ -142,19 +139,9 @@ asmlinkage void do_double_fault(struct xen_regs *regs)
/* Find information saved during fault and dump it to the console. */
printk("************************************\n");
printk("EIP: %04lx:[<%p>] \nEFLAGS: %p\n",
0xffff & regs->cs, regs->rip, regs->eflags);
printk("rax: %p rbx: %p rcx: %p rdx: %p\n",
regs->rax, regs->rbx, regs->rcx, regs->rdx);
printk("rsi: %p rdi: %p rbp: %p rsp: %p\n",
regs->rsi, regs->rdi, regs->rbp, regs->rsp);
printk("r8: %p r9: %p r10: %p r11: %p\n",
regs->r8, regs->r9, regs->r10, regs->r11);
printk("r12: %p r13: %p r14: %p r15: %p\n",
regs->r12, regs->r13, regs->r14, regs->r15);
show_registers(regs);
printk("************************************\n");
printk("CPU%d DOUBLE FAULT -- system shutdown\n",
logical_smp_processor_id());
printk("CPU%d DOUBLE FAULT -- system shutdown\n", smp_processor_id());
printk("System needs manual reset.\n");
printk("************************************\n");
@@ -166,25 +153,29 @@ asmlinkage void do_double_fault(struct xen_regs *regs)
__asm__ __volatile__ ( "hlt" );
}
void __init doublefault_init(void)
{
int i;
/* Initialise IST1 for each CPU. Note the handler is non-reentrant. */
for ( i = 0; i < NR_CPUS; i++ )
init_tss[i].ist[0] = (unsigned long)
&doublefault_stack[DOUBLEFAULT_STACK_SIZE];
/* Set interrupt gate for double faults, specifying IST1. */
set_intr_gate(TRAP_double_fault, &double_fault);
idt_table[TRAP_double_fault].a |= 1UL << 32; /* IST1 */
}
asmlinkage void hypercall(void);
void __init percpu_traps_init(void)
{
char *stack_top = (char *)get_stack_top();
char *stack = (char *)((unsigned long)stack_top & ~(STACK_SIZE - 1));
int cpu = smp_processor_id();
/* Double-fault handler has its own per-CPU 1kB stack. */
init_tss[cpu].ist[0] = (unsigned long)&stack[1024];
set_intr_gate(TRAP_double_fault, &double_fault);
idt_tables[cpu][TRAP_double_fault].a |= 1UL << 32; /* IST1 */
/* NMI handler has its own per-CPU 1kB stack. */
init_tss[cpu].ist[1] = (unsigned long)&stack[2048];
idt_tables[cpu][TRAP_nmi].a |= 2UL << 32; /* IST2 */
/*
* Trampoline for SYSCALL entry from long mode.
*/
/* Skip the NMI and DF stacks. */
stack = &stack[2048];
wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
/* movq %rsp, saversp(%rip) */
stack[0] = 0x48;
@@ -202,9 +193,36 @@ void __init percpu_traps_init(void)
stack[14] = 0xe9;
*(u32 *)&stack[15] = (char *)hypercall - &stack[19];
wrmsr(MSR_STAR, 0, (FLAT_RING3_CS64<<16) | __HYPERVISOR_CS);
wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
wrmsr(MSR_SYSCALL_MASK, 0xFFFFFFFFU, 0U);
/*
* Trampoline for SYSCALL entry from compatibility mode.
*/
/* Skip the long-mode entry trampoline. */
stack = &stack[19];
wrmsr(MSR_CSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
/* movq %rsp, saversp(%rip) */
stack[0] = 0x48;
stack[1] = 0x89;
stack[2] = 0x25;
*(u32 *)&stack[3] = (stack_top - &stack[7]) - 16;
/* leaq saversp(%rip), %rsp */
stack[7] = 0x48;
stack[8] = 0x8d;
stack[9] = 0x25;
*(u32 *)&stack[10] = (stack_top - &stack[14]) - 16;
/* jmp hypercall */
stack[14] = 0xe9;
*(u32 *)&stack[15] = (char *)hypercall - &stack[19];
/*
* Common SYSCALL parameters.
*/
wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);
wrmsr(MSR_SYSCALL_MASK, ~EF_IE, 0U); /* disable interrupts */
}
void *decode_reg(struct xen_regs *regs, u8 b)
+6 -9
View File
@@ -25,8 +25,8 @@
#define PREEMPT_CHECK(_op) \
if ( hypercall_preempt_check() ) \
return hypercall_create_continuation( \
__HYPERVISOR_dom_mem_op, 5, \
return hypercall5_create_continuation( \
__HYPERVISOR_dom_mem_op, \
(_op) | (i << START_EXTENT_SHIFT), \
extent_list, nr_extents, extent_order, \
(d == current->domain) ? DOMID_SELF : d->id);
@@ -122,7 +122,7 @@ free_dom_mem(struct domain *d,
long
do_dom_mem_op(unsigned long op,
unsigned long *extent_list,
unsigned long nr_extents,
unsigned int nr_extents,
unsigned int extent_order,
domid_t domid)
{
@@ -133,8 +133,7 @@ do_dom_mem_op(unsigned long op,
start_extent = op >> START_EXTENT_SHIFT;
op &= (1 << START_EXTENT_SHIFT) - 1;
if ( unlikely(start_extent > nr_extents) ||
unlikely(nr_extents > ~0U) ) /* can pack into a uint? */
if ( unlikely(start_extent > nr_extents) )
return -EINVAL;
if ( likely(domid == DOMID_SELF) )
@@ -150,13 +149,11 @@ do_dom_mem_op(unsigned long op,
{
case MEMOP_increase_reservation:
rc = alloc_dom_mem(
d, extent_list, start_extent,
(unsigned int)nr_extents, extent_order);
d, extent_list, start_extent, nr_extents, extent_order);
break;
case MEMOP_decrease_reservation:
rc = free_dom_mem(
d, extent_list, start_extent,
(unsigned int)nr_extents, extent_order);
d, extent_list, start_extent, nr_extents, extent_order);
break;
default:
rc = -ENOSYS;
-2
View File
@@ -45,8 +45,6 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
ed->processor = cpu;
d->create_time = NOW();
memcpy(&ed->arch, &idle0_exec_domain.arch, sizeof(ed->arch));
spin_lock_init(&d->time_lock);
spin_lock_init(&d->big_lock);
+6 -8
View File
@@ -13,10 +13,8 @@
#ifdef CONFIG_X86
#define FORCE_XENELF_IMAGE 1
#define ELF_ADDR p_vaddr
#elif defined(__ia64__)
#define FORCE_XENELF_IMAGE 0
#define ELF_ADDR p_paddr
#endif
static inline int is_loadable_phdr(Elf_Phdr *phdr)
@@ -100,10 +98,10 @@ int parseelfimage(char *elfbase,
phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
if ( !is_loadable_phdr(phdr) )
continue;
if ( phdr->ELF_ADDR < kernstart )
kernstart = phdr->ELF_ADDR;
if ( (phdr->ELF_ADDR + phdr->p_memsz) > kernend )
kernend = phdr->ELF_ADDR + phdr->p_memsz;
if ( phdr->p_paddr < kernstart )
kernstart = phdr->p_paddr;
if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
kernend = phdr->p_paddr + phdr->p_memsz;
}
if ( (kernstart > kernend) ||
@@ -144,10 +142,10 @@ int loadelfimage(char *elfbase)
if ( !is_loadable_phdr(phdr) )
continue;
if ( phdr->p_filesz != 0 )
memcpy((char *)phdr->ELF_ADDR, elfbase + phdr->p_offset,
memcpy((char *)phdr->p_paddr, elfbase + phdr->p_offset,
phdr->p_filesz);
if ( phdr->p_memsz > phdr->p_filesz )
memset((char *)phdr->ELF_ADDR + phdr->p_filesz, 0,
memset((char *)phdr->p_paddr + phdr->p_filesz, 0,
phdr->p_memsz - phdr->p_filesz);
}
+2 -2
View File
@@ -27,7 +27,7 @@ static struct {
static unsigned char keypress_key;
void keypress_softirq(void)
static void keypress_softirq(void)
{
keyhandler_t *h;
unsigned char key = keypress_key;
@@ -94,7 +94,7 @@ static void halt_machine(unsigned char key, struct xen_regs *regs)
machine_restart(NULL);
}
void do_task_queues(unsigned char key)
static void do_task_queues(unsigned char key)
{
struct domain *d;
struct exec_domain *ed;
+2 -2
View File
@@ -67,8 +67,8 @@ long do_multicall(multicall_entry_t *call_list, unsigned int nr_calls)
if ( i < nr_calls )
{
mcs->flags = 0;
return hypercall_create_continuation(
__HYPERVISOR_multicall, 2, &call_list[i], nr_calls-i);
return hypercall2_create_continuation(
__HYPERVISOR_multicall, &call_list[i], nr_calls-i);
}
}
}
+1 -1
View File
@@ -720,7 +720,7 @@ string_param("physdev_dom0_hide", opt_physdev_dom0_hide);
/* Test if boot params specify this device should NOT be visible to DOM0
* (e.g. so that another domain can control it instead) */
int pcidev_dom0_hidden(struct pci_dev *dev)
static int pcidev_dom0_hidden(struct pci_dev *dev)
{
char cmp[10] = "(.......)";
-13
View File
@@ -254,19 +254,6 @@ struct resource * __request_region(struct resource *parent, unsigned long start,
return res;
}
int __check_region(struct resource *parent, unsigned long start, unsigned long n)
{
struct resource * res;
res = __request_region(parent, start, n, "check-region");
if (!res)
return -EBUSY;
release_resource(res);
xfree(res);
return 0;
}
void __release_region(struct resource *parent, unsigned long start, unsigned long n)
{
struct resource **p;
+8 -8
View File
@@ -167,7 +167,7 @@ static inline u32 calc_evt(struct exec_domain *d, u32 avt)
*
* Returns non-zero on failure.
*/
int bvt_alloc_task(struct exec_domain *ed)
static int bvt_alloc_task(struct exec_domain *ed)
{
struct domain *d = ed->domain;
if ( (d->sched_priv == NULL) ) {
@@ -184,7 +184,7 @@ int bvt_alloc_task(struct exec_domain *ed)
/*
* Add and remove a domain
*/
void bvt_add_task(struct exec_domain *d)
static void bvt_add_task(struct exec_domain *d)
{
struct bvt_dom_info *inf = BVT_INFO(d->domain);
struct bvt_edom_info *einf = EBVT_INFO(d);
@@ -225,7 +225,7 @@ void bvt_add_task(struct exec_domain *d)
}
}
int bvt_init_idle_task(struct exec_domain *p)
static int bvt_init_idle_task(struct exec_domain *p)
{
if ( bvt_alloc_task(p) < 0 )
return -1;
@@ -239,7 +239,7 @@ int bvt_init_idle_task(struct exec_domain *p)
return 0;
}
void bvt_wake(struct exec_domain *d)
static void bvt_wake(struct exec_domain *d)
{
struct bvt_edom_info *einf = EBVT_INFO(d);
struct exec_domain *curr;
@@ -290,14 +290,14 @@ static void bvt_sleep(struct exec_domain *d)
* bvt_free_task - free BVT private structures for a task
* @d: task
*/
void bvt_free_task(struct domain *d)
static void bvt_free_task(struct domain *d)
{
ASSERT(d->sched_priv != NULL);
xfree(d->sched_priv);
}
/* Control the scheduler. */
int bvt_ctl(struct sched_ctl_cmd *cmd)
static int bvt_ctl(struct sched_ctl_cmd *cmd)
{
struct bvt_ctl *params = &cmd->u.bvt;
@@ -310,7 +310,7 @@ int bvt_ctl(struct sched_ctl_cmd *cmd)
}
/* Adjust scheduling parameter for a given domain. */
int bvt_adjdom(
static int bvt_adjdom(
struct domain *d, struct sched_adjdom_cmd *cmd)
{
struct bvt_adjdom *params = &cmd->u.bvt;
@@ -549,7 +549,7 @@ static void bvt_dump_cpu_state(int i)
}
/* Initialise the data structures. */
int bvt_init_scheduler()
static int bvt_init_scheduler(void)
{
int i;
+1 -1
View File
@@ -4,7 +4,7 @@
include $(BASEDIR)/Rules.mk
OBJS := pci.o quirks.o compat.o names.o setup-res.o
OBJS := pci.o quirks.o names.o setup-res.o
#obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
#obj-$(CONFIG_PROC_FS) += proc.o
-65
View File
@@ -1,65 +0,0 @@
/*
* $Id: compat.c,v 1.1 1998/02/16 10:35:50 mj Exp $
*
* PCI Bus Services -- Function For Backward Compatibility
*
* Copyright 1998--2000 Martin Mares <mj@ucw.cz>
*/
#include <xen/types.h>
//#include <xen/kernel.h>
#include <xen/pci.h>
int
pcibios_present(void)
{
return !list_empty(&pci_devices);
}
int
pcibios_find_class(unsigned int class, unsigned short index, unsigned char *bus, unsigned char *devfn)
{
const struct pci_dev *dev = NULL;
int cnt = 0;
while ((dev = pci_find_class(class, dev)))
if (index == cnt++) {
*bus = dev->bus->number;
*devfn = dev->devfn;
return PCIBIOS_SUCCESSFUL;
}
return PCIBIOS_DEVICE_NOT_FOUND;
}
int
pcibios_find_device(unsigned short vendor, unsigned short device, unsigned short index,
unsigned char *bus, unsigned char *devfn)
{
const struct pci_dev *dev = NULL;
int cnt = 0;
while ((dev = pci_find_device(vendor, device, dev)))
if (index == cnt++) {
*bus = dev->bus->number;
*devfn = dev->devfn;
return PCIBIOS_SUCCESSFUL;
}
return PCIBIOS_DEVICE_NOT_FOUND;
}
#define PCI_OP(rw,size,type) \
int pcibios_##rw##_config_##size (unsigned char bus, unsigned char dev_fn, \
unsigned char where, unsigned type val) \
{ \
struct pci_dev *dev = pci_find_slot(bus, dev_fn); \
if (!dev) return PCIBIOS_DEVICE_NOT_FOUND; \
return pci_##rw##_config_##size(dev, where, val); \
}
PCI_OP(read, byte, char *)
PCI_OP(read, word, short *)
PCI_OP(read, dword, int *)
PCI_OP(write, byte, char)
PCI_OP(write, word, short)
PCI_OP(write, dword, int)
+4
View File
@@ -191,6 +191,10 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
#define __HYPERVISOR_DS32 0x0818
#define __HYPERVISOR_DS __HYPERVISOR_DS64
#define __GUEST_CS 0x0833
#define __GUEST_DS 0x0000
#define __GUEST_SS 0x082b
/* For generic assembly code: use macros to define operation/operand sizes. */
#define __OS "q" /* Operation Suffix */
#define __OP "r" /* Operand Prefix */
+1
View File
@@ -96,6 +96,7 @@ struct arch_exec_domain
pagetable_t pagetable;
pagetable_t monitor_table;
pagetable_t phys_table; /* 1:1 pagetable */
pagetable_t shadow_table;
l2_pgentry_t *vpagetable; /* virtual address of pagetable */
l2_pgentry_t *shadow_vtable; /* virtual address of shadow_table */
+15 -2
View File
@@ -13,6 +13,7 @@
#include <asm/desc.h>
#include <asm/flushtlb.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <public/xen.h>
@@ -218,7 +219,7 @@ static inline int get_page_and_type(struct pfn_info *page,
ASSERT(((_p)->count_info & PGC_count_mask) != 0); \
ASSERT(page_get_owner(_p) == (_d))
int check_descriptor(unsigned long *d);
int check_descriptor(struct desc_struct *d);
/*
* Use currently-executing domain's pagetables on the specified CPUs.
@@ -241,8 +242,20 @@ void synchronise_pagetables(unsigned long cpu_mask);
#undef phys_to_machine_mapping
#define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
#define phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START)
#define __phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START)
/* Returns the machine physical */
static inline unsigned long phys_to_machine_mapping(unsigned long pfn)
{
unsigned long mfn;
l1_pgentry_t pte;
if (__get_user(l1_pgentry_val(pte), (__phys_to_machine_mapping + pfn))) {
return 0;
}
mfn = l1_pgentry_to_phys(pte) >> PAGE_SHIFT;
return mfn;
}
#define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn)
#define DEFAULT_GDT_ENTRIES (LAST_RESERVED_GDT_ENTRY+1)
+17 -1
View File
@@ -9,7 +9,23 @@
#ifdef __x86_64__
#define do_multicall_call(_call) BUG()
#define do_multicall_call(_call) \
do { \
__asm__ __volatile__ ( \
"movq "STR(MULTICALL_op)"(%0),%%rax; " \
"andq $("STR(NR_hypercalls)"-1),%%rax; " \
"leaq "STR(hypercall_table)"(%%rip),%%rdi; "\
"leaq (%%rdi,%%rax,8),%%rax; " \
"movq "STR(MULTICALL_arg0)"(%0),%%rdi; " \
"movq "STR(MULTICALL_arg1)"(%0),%%rsi; " \
"movq "STR(MULTICALL_arg2)"(%0),%%rdx; " \
"movq "STR(MULTICALL_arg3)"(%0),%%rcx; " \
"movq "STR(MULTICALL_arg4)"(%0),%%r8; " \
"callq *(%%rax); " \
"movq %%rax,"STR(MULTICALL_result)"(%0); " \
: : "b" (_call) \
: "rax", "rdi", "rsi", "rdx", "rcx", "r8" ); \
} while ( 0 )
#else
+5 -98
View File
@@ -1,39 +1,14 @@
/******************************************************************************
* asm-x86/page.h
*
* Definitions relating to page tables.
*/
/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
#ifndef __X86_PAGE_H__
#define __X86_PAGE_H__
#if defined(__x86_64__)
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 21
#define L3_PAGETABLE_SHIFT 30
#define L4_PAGETABLE_SHIFT 39
#define ENTRIES_PER_L1_PAGETABLE 512
#define ENTRIES_PER_L2_PAGETABLE 512
#define ENTRIES_PER_L3_PAGETABLE 512
#define ENTRIES_PER_L4_PAGETABLE 512
#define __PAGE_OFFSET (0xFFFF830000000000)
#elif defined(__i386__)
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 22
#define ENTRIES_PER_L1_PAGETABLE 1024
#define ENTRIES_PER_L2_PAGETABLE 1024
#define __PAGE_OFFSET (0xFC400000)
#if defined(__i386__)
#include <asm/x86_32/page.h>
#elif defined(__x86_64__)
#include <asm/x86_64/page.h>
#endif
#define PAGE_SHIFT L1_PAGETABLE_SHIFT
#ifndef __ASSEMBLY__
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#else
@@ -44,77 +19,9 @@
#define clear_page(_p) memset((void *)(_p), 0, PAGE_SIZE)
#define copy_page(_t,_f) memcpy((void *)(_t), (void *)(_f), PAGE_SIZE)
#ifndef __ASSEMBLY__
#include <xen/config.h>
typedef struct { unsigned long l1_lo; } l1_pgentry_t;
typedef struct { unsigned long l2_lo; } l2_pgentry_t;
typedef struct { unsigned long l3_lo; } l3_pgentry_t;
typedef struct { unsigned long l4_lo; } l4_pgentry_t;
#endif /* !__ASSEMBLY__ */
/* Strip type from a table entry. */
#define l1_pgentry_val(_x) ((_x).l1_lo)
#define l2_pgentry_val(_x) ((_x).l2_lo)
#define l3_pgentry_val(_x) ((_x).l3_lo)
#define l4_pgentry_val(_x) ((_x).l4_lo)
/* Add type to a table entry. */
#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } )
#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } )
#define mk_l3_pgentry(_x) ( (l3_pgentry_t) { (_x) } )
#define mk_l4_pgentry(_x) ( (l4_pgentry_t) { (_x) } )
/* Turn a typed table entry into a page index. */
#define l1_pgentry_to_pagenr(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT)
#define l2_pgentry_to_pagenr(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT)
#define l3_pgentry_to_pagenr(_x) (l3_pgentry_val(_x) >> PAGE_SHIFT)
#define l4_pgentry_to_pagenr(_x) (l4_pgentry_val(_x) >> PAGE_SHIFT)
/* Turn a typed table entry into a physical address. */
#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & PAGE_MASK)
#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PAGE_MASK)
#define l3_pgentry_to_phys(_x) (l3_pgentry_val(_x) & PAGE_MASK)
#define l4_pgentry_to_phys(_x) (l4_pgentry_val(_x) & PAGE_MASK)
/* Pagetable walking. */
#define l2_pgentry_to_l1(_x) \
((l1_pgentry_t *)__va(l2_pgentry_val(_x) & PAGE_MASK))
#define l3_pgentry_to_l2(_x) \
((l2_pgentry_t *)__va(l3_pgentry_val(_x) & PAGE_MASK))
#define l4_pgentry_to_l3(_x) \
((l3_pgentry_t *)__va(l4_pgentry_val(_x) & PAGE_MASK))
/* Given a virtual address, get an entry offset into a page table. */
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
#if defined(__i386__)
#define l2_table_offset(_a) \
((_a) >> L2_PAGETABLE_SHIFT)
#elif defined(__x86_64__)
#define l2_table_offset(_a) \
(((_a) >> L2_PAGETABLE_SHIFT) & (ENTRIES_PER_L2_PAGETABLE - 1))
#define l3_table_offset(_a) \
(((_a) >> L3_PAGETABLE_SHIFT) & (ENTRIES_PER_L3_PAGETABLE - 1))
#define l4_table_offset(_a) \
(((_a) >> L4_PAGETABLE_SHIFT) & (ENTRIES_PER_L4_PAGETABLE - 1))
#endif
#if defined(__i386__)
#define pagetable_t l2_pgentry_t
#define pagetable_val(_x) ((_x).l2_lo)
#define mk_pagetable(_x) ( (l2_pgentry_t) { (_x) } )
#define ENTRIES_PER_PAGETABLE ENTRIES_PER_L2_PAGETABLE
#elif defined(__x86_64__)
#define pagetable_t l4_pgentry_t
#define pagetable_val(_x) ((_x).l4_lo)
#define mk_pagetable(_x) ( (l4_pgentry_t) { (_x) } )
#define ENTRIES_PER_PAGETABLE ENTRIES_PER_L4_PAGETABLE
#endif
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#define page_address(_p) (__va(((_p) - frame_table) << PAGE_SHIFT))
#define pfn_to_page(_pfn) (frame_table + (_pfn))
#define phys_to_page(kaddr) (frame_table + ((kaddr) >> PAGE_SHIFT))
#define virt_to_page(kaddr) (frame_table + (__pa(kaddr) >> PAGE_SHIFT))
+118 -142
View File
@@ -8,6 +8,10 @@
#include <xen/perfc.h>
#include <asm/processor.h>
#ifdef CONFIG_VMX
#include <asm/domain_page.h>
#endif
/* Shadow PT flag bits in pfn_info */
#define PSH_shadowed (1<<31) /* page has a shadow. PFN points to shadow */
#define PSH_pfn_mask ((1<<21)-1)
@@ -34,7 +38,7 @@ extern int shadow_fault(unsigned long va, long error_code);
extern void shadow_l1_normal_pt_update(
unsigned long pa, unsigned long gpte,
unsigned long *prev_spfn_ptr, l1_pgentry_t **prev_spl1e_ptr);
extern void shadow_l2_normal_pt_update(unsigned long pa, unsigned long gpte);
extern void shadow_l2_normal_pt_update(unsigned long pa, unsigned long gpde);
extern void unshadow_table(unsigned long gpfn, unsigned int type);
extern int shadow_mode_enable(struct domain *p, unsigned int mode);
@@ -43,17 +47,15 @@ extern void vmx_shadow_clear_state(struct domain *);
extern void vmx_shadow_invlpg(struct domain *, unsigned long);
#endif
#define __get_machine_to_phys(_d, guest_gpfn, gpfn) \
if ((_d)->arch.shadow_mode == SHM_full_32) \
(guest_gpfn) = machine_to_phys_mapping[(gpfn)]; \
else \
(guest_gpfn) = (gpfn);
#define __mfn_to_gpfn(_d, mfn) \
( (shadow_mode(_d) == SHM_full_32) \
? machine_to_phys_mapping[(mfn)] \
: (mfn) )
#define __get_phys_to_machine(_d, host_gpfn, gpfn) \
if ((_d)->arch.shadow_mode == SHM_full_32) \
(host_gpfn) = phys_to_machine_mapping[(gpfn)]; \
else \
(host_gpfn) = (gpfn);
#define __gpfn_to_mfn(_d, gpfn) \
( (shadow_mode(_d) == SHM_full_32) \
? phys_to_machine_mapping(gpfn) \
: (gpfn) )
extern void __shadow_mode_disable(struct domain *d);
static inline void shadow_mode_disable(struct domain *d)
@@ -66,17 +68,18 @@ extern unsigned long shadow_l2_table(
struct domain *d, unsigned long gpfn);
static inline void shadow_invalidate(struct exec_domain *ed) {
if ( ed->domain->arch.shadow_mode != SHM_full_32 )
if ( shadow_mode(ed->domain) != SHM_full_32 )
BUG();
memset(ed->arch.shadow_vtable, 0, PAGE_SIZE);
}
#define SHADOW_DEBUG 1
#define SHADOW_VERBOSE_DEBUG 0
#define SHADOW_HASH_DEBUG 1
struct shadow_status {
unsigned long pfn; /* Guest pfn. */
unsigned long spfn_and_flags; /* Shadow pfn plus flags. */
unsigned long smfn_and_flags; /* Shadow mfn plus flags. */
struct shadow_status *next; /* Pull-to-front list. */
};
@@ -84,62 +87,72 @@ struct shadow_status {
#define shadow_ht_buckets 256
#ifdef VERBOSE
#define SH_LOG(_f, _a...) \
printk("DOM%u: (file=shadow.c, line=%d) " _f "\n", \
current->domain->id , __LINE__ , ## _a )
#define SH_LOG(_f, _a...) \
printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n", \
current->domain->id , current->processor, __LINE__ , ## _a )
#else
#define SH_LOG(_f, _a...)
#endif
#if SHADOW_DEBUG
#define SH_VLOG(_f, _a...) \
printk("DOM%u: (file=shadow.c, line=%d) " _f "\n", \
current->domain->id , __LINE__ , ## _a )
#define SH_VLOG(_f, _a...) \
printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n", \
current->domain->id, current->processor, __LINE__ , ## _a )
#else
#define SH_VLOG(_f, _a...)
#endif
#if 0
#define SH_VVLOG(_f, _a...) \
printk("DOM%u: (file=shadow.c, line=%d) " _f "\n", \
current->domain->id , __LINE__ , ## _a )
#if SHADOW_VERBOSE_DEBUG
#define SH_VVLOG(_f, _a...) \
printk("DOM%uP%u: (file=shadow.c, line=%d) " _f "\n", \
current->domain->id, current->processor, __LINE__ , ## _a )
#else
#define SH_VVLOG(_f, _a...)
#endif
static inline void __shadow_get_pl2e(
// BUG: mafetter: this assumes ed == current, so why pass ed?
static inline void __shadow_get_l2e(
struct exec_domain *ed, unsigned long va, unsigned long *sl2e)
{
*sl2e = (ed->domain->arch.shadow_mode == SHM_full_32) ?
l2_pgentry_val(ed->arch.shadow_vtable[l2_table_offset(va)]) :
l2_pgentry_val(linear_l2_table[l2_table_offset(va)]);
if ( shadow_mode(ed->domain) == SHM_full_32 ) {
*sl2e = l2_pgentry_val(ed->arch.shadow_vtable[l2_table_offset(va)]);
}
else if ( shadow_mode(ed->domain) ) {
*sl2e = l2_pgentry_val(shadow_linear_l2_table[l2_table_offset(va)]);
}
else
*sl2e = l2_pgentry_val(linear_l2_table[l2_table_offset(va)]);
}
static inline void __shadow_set_pl2e(
static inline void __shadow_set_l2e(
struct exec_domain *ed, unsigned long va, unsigned long value)
{
if ( ed->domain->arch.shadow_mode == SHM_full_32 )
if ( shadow_mode(ed->domain) == SHM_full_32 ) {
ed->arch.shadow_vtable[l2_table_offset(va)] = mk_l2_pgentry(value);
}
else if ( shadow_mode(ed->domain) ) {
shadow_linear_l2_table[l2_table_offset(va)] = mk_l2_pgentry(value);
}
else
linear_l2_table[l2_table_offset(va)] = mk_l2_pgentry(value);
}
static inline void __guest_get_pl2e(
static inline void __guest_get_l2e(
struct exec_domain *ed, unsigned long va, unsigned long *l2e)
{
*l2e = (ed->domain->arch.shadow_mode == SHM_full_32) ?
*l2e = ( shadow_mode(ed->domain) == SHM_full_32) ?
l2_pgentry_val(ed->arch.vpagetable[l2_table_offset(va)]) :
l2_pgentry_val(linear_l2_table[l2_table_offset(va)]);
}
static inline void __guest_set_pl2e(
static inline void __guest_set_l2e(
struct exec_domain *ed, unsigned long va, unsigned long value)
{
if ( ed->domain->arch.shadow_mode == SHM_full_32 )
if ( shadow_mode(ed->domain) == SHM_full_32 )
{
unsigned long pfn;
pfn = phys_to_machine_mapping[value >> PAGE_SHIFT];
pfn = phys_to_machine_mapping(value >> PAGE_SHIFT);
ed->arch.guest_pl2e_cache[l2_table_offset(va)] =
mk_l2_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
@@ -213,32 +226,18 @@ static inline void l1pte_write_fault(
{
unsigned long gpte = *gpte_p;
unsigned long spte = *spte_p;
unsigned long pfn = gpte >> PAGE_SHIFT;
unsigned long mfn = __gpfn_to_mfn(d, pfn);
ASSERT(gpte & _PAGE_RW);
gpte |= _PAGE_DIRTY | _PAGE_ACCESSED;
switch ( d->arch.shadow_mode )
{
case SHM_test:
spte = gpte | _PAGE_RW;
break;
if ( shadow_mode(d) == SHM_logdirty )
__mark_dirty(d, pfn);
case SHM_logdirty:
spte = gpte | _PAGE_RW;
__mark_dirty(d, gpte >> PAGE_SHIFT);
spte = (mfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
case SHM_full_32:
{
unsigned long host_pfn, host_gpte;
host_pfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT];
host_gpte = (host_pfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
spte = host_gpte | _PAGE_RW;
}
break;
}
SH_VVLOG("updating spte=%lx gpte=%lx", spte, gpte);
SH_VVLOG("l1pte_write_fault: updating spte=0x%08lx gpte=0x%08lx", spte, gpte);
*gpte_p = gpte;
*spte_p = spte;
}
@@ -248,31 +247,16 @@ static inline void l1pte_read_fault(
{
unsigned long gpte = *gpte_p;
unsigned long spte = *spte_p;
unsigned long pfn = gpte >> PAGE_SHIFT;
unsigned long mfn = __gpfn_to_mfn(d, pfn);
gpte |= _PAGE_ACCESSED;
spte = (mfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
switch ( d->arch.shadow_mode )
{
case SHM_test:
spte = (gpte & _PAGE_DIRTY) ? gpte : (gpte & ~_PAGE_RW);
break;
case SHM_logdirty:
spte = gpte & ~_PAGE_RW;
break;
case SHM_full_32:
{
unsigned long host_pfn, host_gpte;
host_pfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT];
host_gpte = (host_pfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
spte = (host_gpte & _PAGE_DIRTY) ? host_gpte : (host_gpte & ~_PAGE_RW);
}
break;
}
if ( (shadow_mode(d) == SHM_logdirty) || ! (gpte & _PAGE_DIRTY) )
spte &= ~_PAGE_RW;
SH_VVLOG("l1pte_read_fault: updating spte=0x%08lx gpte=0x%08lx", spte, gpte);
*gpte_p = gpte;
*spte_p = spte;
}
@@ -283,8 +267,11 @@ static inline void l1pte_propagate_from_guest(
unsigned long gpte = *gpte_p;
unsigned long spte = *spte_p;
unsigned long host_pfn, host_gpte;
#if SHADOW_VERBOSE_DEBUG
unsigned long old_spte = spte;
#endif
switch ( d->arch.shadow_mode )
switch ( shadow_mode(d) )
{
case SHM_test:
spte = 0;
@@ -309,7 +296,7 @@ static inline void l1pte_propagate_from_guest(
return;
}
host_pfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT];
host_pfn = phys_to_machine_mapping(gpte >> PAGE_SHIFT);
host_gpte = (host_pfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK);
if ( (host_gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
@@ -320,6 +307,11 @@ static inline void l1pte_propagate_from_guest(
break;
}
#if SHADOW_VERBOSE_DEBUG
if ( old_spte || spte || gpte )
SH_VVLOG("l1pte_propagate_from_guest: gpte=0x%08lx, old spte=0x%08lx, new spte=0x%08lx ", gpte, old_spte, spte);
#endif
*gpte_p = gpte;
*spte_p = spte;
}
@@ -328,24 +320,24 @@ static inline void l2pde_general(
struct domain *d,
unsigned long *gpde_p,
unsigned long *spde_p,
unsigned long sl1pfn)
unsigned long sl1mfn)
{
unsigned long gpde = *gpde_p;
unsigned long spde = *spde_p;
spde = 0;
if ( sl1pfn != 0 )
if ( sl1mfn != 0 )
{
spde = (gpde & ~PAGE_MASK) | (sl1pfn << PAGE_SHIFT) |
spde = (gpde & ~PAGE_MASK) | (sl1mfn << PAGE_SHIFT) |
_PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY;
gpde |= _PAGE_ACCESSED | _PAGE_DIRTY;
/* Detect linear p.t. mappings and write-protect them. */
if ( (frame_table[sl1pfn].u.inuse.type_info & PGT_type_mask) ==
if ( (frame_table[sl1mfn].u.inuse.type_info & PGT_type_mask) ==
PGT_l2_page_table )
{
if ( d->arch.shadow_mode != SHM_full_32 )
if ( shadow_mode(d) != SHM_full_32 )
spde = gpde & ~_PAGE_RW;
}
@@ -366,20 +358,20 @@ static void shadow_audit(struct domain *d, int print)
for ( j = 0; j < shadow_ht_buckets; j++ )
{
a = &d->arch.shadow_ht[j];
if ( a->pfn ) { live++; ASSERT(a->spfn_and_flags & PSH_pfn_mask); }
if ( a->pfn ) { live++; ASSERT(a->smfn_and_flags & PSH_pfn_mask); }
ASSERT(a->pfn < 0x00100000UL);
a = a->next;
while ( a && (live < 9999) )
{
live++;
if ( (a->pfn == 0) || (a->spfn_and_flags == 0) )
if ( (a->pfn == 0) || (a->smfn_and_flags == 0) )
{
printk("XXX live=%d pfn=%08lx sp=%08lx next=%p\n",
live, a->pfn, a->spfn_and_flags, a->next);
live, a->pfn, a->smfn_and_flags, a->next);
BUG();
}
ASSERT(a->pfn < 0x00100000UL);
ASSERT(a->spfn_and_flags & PSH_pfn_mask);
ASSERT(a->smfn_and_flags & PSH_pfn_mask);
a = a->next;
}
ASSERT(live < 9999);
@@ -411,6 +403,12 @@ static inline struct shadow_status *hash_bucket(
}
/*
* N.B. This takes a guest pfn (i.e. a pfn in the guest's namespace,
* which, depending on full shadow mode, may or may not equal
* its mfn).
* The shadow status it returns is a mfn.
*/
static inline unsigned long __shadow_status(
struct domain *d, unsigned int gpfn)
{
@@ -419,7 +417,7 @@ static inline unsigned long __shadow_status(
x = head = hash_bucket(d, gpfn);
p = NULL;
SH_VVLOG("lookup gpfn=%08x bucket=%p", gpfn, x);
//SH_VVLOG("lookup gpfn=%08x bucket=%p", gpfn, x);
shadow_audit(d, 0);
do
@@ -438,10 +436,12 @@ static inline unsigned long __shadow_status(
/* Swap 'x' contents with head contents. */
SWAP(head->pfn, x->pfn);
SWAP(head->spfn_and_flags, x->spfn_and_flags);
SWAP(head->smfn_and_flags, x->smfn_and_flags);
}
return head->spfn_and_flags;
SH_VVLOG("lookup gpfn=%08lx => status=%08lx",
gpfn, head->smfn_and_flags);
return head->smfn_and_flags;
}
p = x;
@@ -449,6 +449,7 @@ static inline unsigned long __shadow_status(
}
while ( x != NULL );
SH_VVLOG("lookup gpfn=%08lx => status=0", gpfn);
return 0;
}
@@ -462,7 +463,7 @@ static inline unsigned long get_shadow_status(
{
unsigned long res;
ASSERT(d->arch.shadow_mode);
ASSERT(shadow_mode(d));
/*
* If we get here we know that some sort of update has happened to the
@@ -474,7 +475,7 @@ static inline unsigned long get_shadow_status(
shadow_lock(d);
if ( d->arch.shadow_mode == SHM_logdirty )
if ( shadow_mode(d) == SHM_logdirty )
__mark_dirty(d, gpfn);
if ( !(res = __shadow_status(d, gpfn)) )
@@ -511,14 +512,14 @@ static inline void delete_shadow_status(
{
/* Overwrite head with contents of following node. */
head->pfn = n->pfn;
head->spfn_and_flags = n->spfn_and_flags;
head->smfn_and_flags = n->smfn_and_flags;
/* Delete following node. */
head->next = n->next;
/* Add deleted node to the free list. */
n->pfn = 0;
n->spfn_and_flags = 0;
n->smfn_and_flags = 0;
n->next = d->arch.shadow_ht_free;
d->arch.shadow_ht_free = n;
}
@@ -526,7 +527,7 @@ static inline void delete_shadow_status(
{
/* This bucket is now empty. Initialise the head node. */
head->pfn = 0;
head->spfn_and_flags = 0;
head->smfn_and_flags = 0;
}
goto found;
@@ -544,7 +545,7 @@ static inline void delete_shadow_status(
/* Add deleted node to the free list. */
x->pfn = 0;
x->spfn_and_flags = 0;
x->smfn_and_flags = 0;
x->next = d->arch.shadow_ht_free;
d->arch.shadow_ht_free = x;
@@ -587,7 +588,7 @@ static inline void set_shadow_status(
{
if ( x->pfn == gpfn )
{
x->spfn_and_flags = s;
x->smfn_and_flags = s;
goto done;
}
@@ -603,7 +604,7 @@ static inline void set_shadow_status(
if ( head->pfn == 0 )
{
head->pfn = gpfn;
head->spfn_and_flags = s;
head->smfn_and_flags = s;
ASSERT(head->next == NULL);
goto done;
}
@@ -643,7 +644,7 @@ static inline void set_shadow_status(
/* Initialise the new node and insert directly after the head item. */
x->pfn = gpfn;
x->spfn_and_flags = s;
x->smfn_and_flags = s;
x->next = head->next;
head->next = x;
@@ -652,10 +653,9 @@ static inline void set_shadow_status(
}
#ifdef CONFIG_VMX
#include <asm/domain_page.h>
static inline void vmx_update_shadow_state(
struct exec_domain *ed, unsigned long gpfn, unsigned long spfn)
struct exec_domain *ed, unsigned long gpfn, unsigned long smfn)
{
l2_pgentry_t *mpl2e = 0;
@@ -672,70 +672,46 @@ static inline void vmx_update_shadow_state(
map_domain_mem(pagetable_val(ed->arch.monitor_table));
mpl2e[l2_table_offset(SH_LINEAR_PT_VIRT_START)] =
mk_l2_pgentry((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
mk_l2_pgentry((smfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
__flush_tlb_one(SH_LINEAR_PT_VIRT_START);
spl2e = (l2_pgentry_t *)map_domain_mem(spfn << PAGE_SHIFT);
spl2e = (l2_pgentry_t *)map_domain_mem(smfn << PAGE_SHIFT);
gpl2e = (l2_pgentry_t *)map_domain_mem(gpfn << PAGE_SHIFT);
memset(spl2e, 0, ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
ed->arch.shadow_table = mk_pagetable(spfn<<PAGE_SHIFT);
ed->arch.shadow_vtable = spl2e;
ed->arch.vpagetable = gpl2e; /* expect the guest did clean this up */
unmap_domain_mem(mpl2e);
}
#endif /* CONFIG_VMX */
static inline void __shadow_mk_pagetable(struct exec_domain *ed)
{
struct domain *d = ed->domain;
unsigned long gpfn = pagetable_val(ed->arch.pagetable) >> PAGE_SHIFT;
unsigned long spfn;
SH_VLOG("0: __shadow_mk_pagetable(gpfn=%08lx\n", gpfn);
unsigned long smfn = __shadow_status(d, gpfn) & PSH_pfn_mask;
if (d->arch.shadow_mode == SHM_full_32)
{
unsigned long guest_gpfn;
guest_gpfn = machine_to_phys_mapping[gpfn];
SH_VVLOG("0: __shadow_mk_pagetable(gpfn=%08lx, smfn=%08lx)", gpfn, smfn);
SH_VVLOG("__shadow_mk_pagetable(guest_gpfn=%08lx, gpfn=%08lx\n",
guest_gpfn, gpfn);
if ( unlikely(smfn == 0) )
smfn = shadow_l2_table(d, gpfn);
#ifdef CONFIG_VMX
else
if (d->arch.shadow_mode == SHM_full_32)
vmx_update_shadow_state(ed, gpfn, smfn);
#endif
spfn = __shadow_status(d, guest_gpfn) & PSH_pfn_mask;
if ( unlikely(spfn == 0) ) {
spfn = shadow_l2_table(d, gpfn);
ed->arch.shadow_table = mk_pagetable(spfn<<PAGE_SHIFT);
} else {
vmx_update_shadow_state(ed, gpfn, spfn);
}
} else {
spfn = __shadow_status(d, gpfn) & PSH_pfn_mask;
if ( unlikely(spfn == 0) ) {
spfn = shadow_l2_table(d, gpfn);
}
ed->arch.shadow_table = mk_pagetable(spfn<<PAGE_SHIFT);
}
ed->arch.shadow_table = mk_pagetable(smfn<<PAGE_SHIFT);
}
#else
static inline void __shadow_mk_pagetable(struct exec_domain *ed)
{
unsigned long gpfn = pagetable_val(ed->arch.pagetable) >> PAGE_SHIFT;
unsigned long spfn = __shadow_status(ed->domain, gpfn);
if ( unlikely(spfn == 0) )
spfn = shadow_l2_table(ed->domain, gpfn);
ed->arch.shadow_table = mk_pagetable(spfn << PAGE_SHIFT);
}
#endif /* CONFIG_VMX */
static inline void shadow_mk_pagetable(struct exec_domain *ed)
{
if ( unlikely(ed->domain->arch.shadow_mode) )
if ( unlikely(shadow_mode(ed->domain)) )
{
SH_VVLOG("shadow_mk_pagetable( gptbase=%08lx, mode=%d )",
pagetable_val(ed->arch.pagetable),
ed->domain->arch.shadow_mode);
shadow_mode(ed->domain));
shadow_lock(ed->domain);
__shadow_mk_pagetable(ed);
@@ -744,13 +720,13 @@ static inline void shadow_mk_pagetable(struct exec_domain *ed)
SH_VVLOG("leaving shadow_mk_pagetable:\n"
"( gptbase=%08lx, mode=%d ) sh=%08lx",
pagetable_val(ed->arch.pagetable),
ed->domain->arch.shadow_mode,
shadow_mode(ed->domain),
pagetable_val(ed->arch.shadow_table) );
}
}
#if SHADOW_DEBUG
extern int check_pagetable(struct domain *d, pagetable_t pt, char *s);
extern void check_pagetable(struct domain *d, pagetable_t pt, char *s);
#else
#define check_pagetable(d, pt, s) ((void)0)
#endif
+56
View File
@@ -0,0 +1,56 @@
/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
#ifndef __X86_32_PAGE_H__
#define __X86_32_PAGE_H__
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 22
#define PAGE_SHIFT L1_PAGETABLE_SHIFT
#define ENTRIES_PER_L1_PAGETABLE 1024
#define ENTRIES_PER_L2_PAGETABLE 1024
#define __PAGE_OFFSET (0xFC400000)
#ifndef __ASSEMBLY__
#include <xen/config.h>
typedef struct { unsigned long l1_lo; } l1_pgentry_t;
typedef struct { unsigned long l2_lo; } l2_pgentry_t;
#endif /* !__ASSEMBLY__ */
/* Strip type from a table entry. */
#define l1_pgentry_val(_x) ((_x).l1_lo)
#define l2_pgentry_val(_x) ((_x).l2_lo)
/* Add type to a table entry. */
#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } )
#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } )
/* Turn a typed table entry into a physical address. */
#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & PAGE_MASK)
#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PAGE_MASK)
/* Turn a typed table entry into a page index. */
#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT)
#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT)
/* Pagetable walking. */
#define l2_pgentry_to_l1(_x) \
((l1_pgentry_t *)__va(l2_pgentry_to_phys(_x)))
/* Given a virtual address, get an entry offset into a page table. */
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
#define l2_table_offset(_a) \
((_a) >> L2_PAGETABLE_SHIFT)
/* Given a virtual address, get an entry offset into a linear page table. */
#define l1_linear_offset(_a) ((_a) >> PAGE_SHIFT)
/* Root page-table definitions. */
#define pagetable_t l2_pgentry_t
#define pagetable_val(_x) ((_x).l2_lo)
#define mk_pagetable(_x) ( (l2_pgentry_t) { (_x) } )
#define ENTRIES_PER_PAGETABLE ENTRIES_PER_L2_PAGETABLE
#endif /* __X86_32_PAGE_H__ */
+2
View File
@@ -39,4 +39,6 @@ struct xen_regs
#define RING_2(_r) (((_r)->cs & 3) == 2)
#define RING_3(_r) (((_r)->cs & 3) == 3)
#define GUESTOS_FAULT(_r) (!VM86_MODE(_r) && RING_1(_r))
#endif
-1
View File
@@ -8,7 +8,6 @@
#include <xen/errno.h>
#include <xen/prefetch.h>
#include <xen/string.h>
#include <xen/sched.h>
#define __user
+84
View File
@@ -0,0 +1,84 @@
/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
#ifndef __X86_64_PAGE_H__
#define __X86_64_PAGE_H__
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 21
#define L3_PAGETABLE_SHIFT 30
#define L4_PAGETABLE_SHIFT 39
#define PAGE_SHIFT L1_PAGETABLE_SHIFT
#define ENTRIES_PER_L1_PAGETABLE 512
#define ENTRIES_PER_L2_PAGETABLE 512
#define ENTRIES_PER_L3_PAGETABLE 512
#define ENTRIES_PER_L4_PAGETABLE 512
#define __PAGE_OFFSET (0xFFFF830000000000)
/* These may increase in future (phys. bits in particular). */
#define PADDR_BITS 40
#define VADDR_BITS 48
#define PADDR_MASK ((1UL << PADDR_BITS)-1)
#define VADDR_MASK ((1UL << VADDR_BITS)-1)
#ifndef __ASSEMBLY__
#include <xen/config.h>
typedef struct { unsigned long l1_lo; } l1_pgentry_t;
typedef struct { unsigned long l2_lo; } l2_pgentry_t;
typedef struct { unsigned long l3_lo; } l3_pgentry_t;
typedef struct { unsigned long l4_lo; } l4_pgentry_t;
#endif /* !__ASSEMBLY__ */
/* Strip type from a table entry. */
#define l1_pgentry_val(_x) ((_x).l1_lo)
#define l2_pgentry_val(_x) ((_x).l2_lo)
#define l3_pgentry_val(_x) ((_x).l3_lo)
#define l4_pgentry_val(_x) ((_x).l4_lo)
/* Add type to a table entry. */
#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } )
#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } )
#define mk_l3_pgentry(_x) ( (l3_pgentry_t) { (_x) } )
#define mk_l4_pgentry(_x) ( (l4_pgentry_t) { (_x) } )
/* Turn a typed table entry into a physical address. */
#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
#define l3_pgentry_to_phys(_x) (l3_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
#define l4_pgentry_to_phys(_x) (l4_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
/* Turn a typed table entry into a page index. */
#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT)
#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT)
#define l3_pgentry_to_pfn(_x) (l3_pgentry_val(_x) >> PAGE_SHIFT)
#define l4_pgentry_to_pfn(_x) (l4_pgentry_val(_x) >> PAGE_SHIFT)
/* Pagetable walking. */
#define l2_pgentry_to_l1(_x) \
((l1_pgentry_t *)__va(l2_pgentry_to_phys(_x)))
#define l3_pgentry_to_l2(_x) \
((l2_pgentry_t *)__va(l3_pgentry_to_phys(_x)))
#define l4_pgentry_to_l3(_x) \
((l3_pgentry_t *)__va(l4_pgentry_to_phys(_x)))
/* Given a virtual address, get an entry offset into a page table. */
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
#define l2_table_offset(_a) \
(((_a) >> L2_PAGETABLE_SHIFT) & (ENTRIES_PER_L2_PAGETABLE - 1))
#define l3_table_offset(_a) \
(((_a) >> L3_PAGETABLE_SHIFT) & (ENTRIES_PER_L3_PAGETABLE - 1))
#define l4_table_offset(_a) \
(((_a) >> L4_PAGETABLE_SHIFT) & (ENTRIES_PER_L4_PAGETABLE - 1))
/* Given a virtual address, get an entry offset into a linear page table. */
#define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> PAGE_SHIFT)
/* Root page-table definitions. */
#define pagetable_t l4_pgentry_t
#define pagetable_val(_x) ((_x).l4_lo)
#define mk_pagetable(_x) ( (l4_pgentry_t) { (_x) } )
#define ENTRIES_PER_PAGETABLE ENTRIES_PER_L4_PAGETABLE
#endif /* __X86_64_PAGE_H__ */
+2
View File
@@ -36,4 +36,6 @@ struct xen_regs
#define RING_2(_r) (((_r)->cs & 3) == 2)
#define RING_3(_r) (((_r)->cs & 3) == 3)
#define GUESTOS_FAULT(_r) (!VM86_MODE(_r) && RING_3(_r))
#endif
+9 -25
View File
@@ -7,7 +7,6 @@
#include <xen/config.h>
#include <xen/compiler.h>
#include <xen/errno.h>
#include <xen/sched.h>
#include <xen/prefetch.h>
#include <asm/page.h>
@@ -16,34 +15,19 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
#define __addr_ok(addr) ((unsigned long)(addr) < HYPERVISOR_VIRT_START)
/*
* Test whether a block of memory is a valid user space address.
* Returns 0 if the range is valid, nonzero otherwise.
*
* This is equivalent to the following test:
* ((u65)addr >= (u65)HYPERVISOR_VIRT_END) ?
* (((u65)addr + (u65)size) >= ((u65)1 << 64)) :
* (((u65)addr + (u65)size) >= ((u65)HYPERVISOR_VIRT_START))
* Valid if in +ve half of 48-bit address space, or above Xen-reserved area.
* This is also valid for range checks (addr, addr+size). As long as the
* start address is outside the Xen-reserved area then we will access a
* non-canonical address (and thus fault) before ever reaching VIRT_START.
*/
#define __range_not_ok(addr,size) ({ \
unsigned long flag,sum; \
if ((unsigned long)addr >= HYPERVISOR_VIRT_END) \
asm("addq %3,%1 ; sbbq %0,%0" \
:"=&r" (flag), "=r" (sum) \
:"1" (addr),"g" ((long)(size))); \
else \
asm("addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0" \
:"=&r" (flag), "=r" (sum) \
:"1" (addr),"g" ((long)(size)),"r" (HYPERVISOR_VIRT_START)); \
flag; })
#define __addr_ok(addr) \
(((unsigned long)(addr) < (1UL<<48)) || \
((unsigned long)(addr) >= HYPERVISOR_VIRT_END))
#define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
#define access_ok(type, addr, size) (__addr_ok(addr))
#define array_access_ok(type,addr,count,size) \
(likely(sizeof(count) <= 4) /* disallow 64-bit counts */ && \
access_ok(type,addr,(unsigned long)count*(unsigned long)size))
#define array_access_ok(type,addr,count,size) (__addr_ok(addr))
extern long __get_user_bad(void);
extern void __put_user_bad(void);
+4 -4
View File
@@ -43,11 +43,11 @@
*/
#define FLAT_RING3_CS32 0x0823 /* GDT index 260 */
#define FLAT_RING3_CS64 0x082b /* GDT index 261 */
#define FLAT_RING3_DS32 0x0833 /* GDT index 262 */
#define FLAT_RING3_CS64 0x0833 /* GDT index 261 */
#define FLAT_RING3_DS32 0x082b /* GDT index 262 */
#define FLAT_RING3_DS64 0x0000 /* NULL selector */
#define FLAT_RING3_SS32 0x0833 /* GDT index 262 */
#define FLAT_RING3_SS64 0x0833 /* GDT index 262 */
#define FLAT_RING3_SS32 0x082b /* GDT index 262 */
#define FLAT_RING3_SS64 0x082b /* GDT index 262 */
#define FLAT_GUESTOS_DS64 FLAT_RING3_DS64
#define FLAT_GUESTOS_DS32 FLAT_RING3_DS32
+8 -1
View File
@@ -23,7 +23,14 @@
* XEN "SYSTEM CALLS" (a.k.a. HYPERCALLS).
*/
/* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */
/*
* x86_32: EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5.
* EAX = return value
* (argument registers may be clobbered on return)
* x86_64: RAX = vector; RDI, RSI, RDX, R10, R8, R9 = args 1, 2, 3, 4, 5, 6.
* RAX = return value
* (argument registers not clobbered on return; RCX, R11 are)
*/
#define __HYPERVISOR_set_trap_table 0
#define __HYPERVISOR_mmu_update 1
#define __HYPERVISOR_set_gdt 2
+2 -6
View File
@@ -100,17 +100,13 @@ extern int allocate_resource(struct resource *root, struct resource *new,
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))
extern struct resource * __request_region(struct resource *, unsigned long start, unsigned long n, const char *name);
/* Compatibility cruft */
#define check_region(start,n) __check_region(&ioport_resource, (start), (n))
#define release_region(start,n) __release_region(&ioport_resource, (start), (n))
#define check_mem_region(start,n) __check_region(&iomem_resource, (start), (n))
#define release_mem_region(start,n) __release_region(&iomem_resource, (start), (n))
extern int __check_region(struct resource *, unsigned long, unsigned long);
extern void __release_region(struct resource *, unsigned long, unsigned long);
extern struct resource * __request_region(struct resource *, unsigned long start, unsigned long n, const char *name);
#define get_ioport_list(buf) get_resource_list(&ioport_resource, buf, PAGE_SIZE)
#define get_mem_list(buf) get_resource_list(&iomem_resource, buf, PAGE_SIZE)
+25 -1
View File
@@ -262,8 +262,32 @@ int idle_cpu(int cpu); /* Is CPU 'cpu' idle right now? */
void startup_cpu_idle_loop(void);
unsigned long hypercall_create_continuation(
unsigned long __hypercall_create_continuation(
unsigned int op, unsigned int nr_args, ...);
#define hypercall0_create_continuation(_op) \
__hypercall_create_continuation((_op), 0)
#define hypercall1_create_continuation(_op, _a1) \
__hypercall_create_continuation((_op), 1, \
(unsigned long)(_a1))
#define hypercall2_create_continuation(_op, _a1, _a2) \
__hypercall_create_continuation((_op), 2, \
(unsigned long)(_a1), (unsigned long)(_a2))
#define hypercall3_create_continuation(_op, _a1, _a2, _a3) \
__hypercall_create_continuation((_op), 3, \
(unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3))
#define hypercall4_create_continuation(_op, _a1, _a2, _a3, _a4) \
__hypercall_create_continuation((_op), 4, \
(unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
(unsigned long)(_a4))
#define hypercall5_create_continuation(_op, _a1, _a2, _a3, _a4, _a5) \
__hypercall_create_continuation((_op), 5, \
(unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
(unsigned long)(_a4), (unsigned long)(_a5))
#define hypercall6_create_continuation(_op, _a1, _a2, _a3, _a4, _a5, _a6) \
__hypercall_create_continuation((_op), 6, \
(unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
(unsigned long)(_a4), (unsigned long)(_a5), (unsigned long)(_a6))
#define hypercall_preempt_check() \
(unlikely(softirq_pending(smp_processor_id())))
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.