|
完全照搬原文,原文地址:http://fire-flying.diandian.com/。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
原文的代码可能比较旧,在我的机器上已经不能运行,下面是经我修改过的,先看domU端的代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
#include
unsigned long page;
struct as_request {
unsigned int id;
unsigned int status;
unsigned int operation;
};
struct as_response {
unsigned int id;
unsigned int status;
unsigned int operation;
};
DEFINE_RING_TYPES(as, struct as_request, struct as_response);
struct info_t {
struct as_front_ring ring;
grant_ref_t gref;
int irq;
int port;
}info;
#define DOM0_ID 0
static struct proc_dir_entry *proc_dir = NULL;
static struct proc_dir_entry *proc_file = NULL;
char proc_data[20];
int send_request_to_dom0(void)
{
struct as_request *ring_req;
int notify;
static int reqid = 9;
ring_req = RING_GET_REQUEST(&(info.ring), info.ring.req_prod_pvt);
ring_req->id = reqid;
ring_req->operation = reqid;
ring_req->status = reqid;
printk(KERN_DEBUG "\nxen:DomU: Fill in IDX-%d, with id=%d, op=%d, st=%d",
info.ring.req_prod_pvt, ring_req->id, ring_req->operation, ring_req->status);
reqid++;
info.ring.req_prod_pvt += 1;
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&(info.ring), notify);
if (notify) {
printk(KERN_DEBUG "\nxen: DomU: sent a req to Dom0");
notify_remote_via_irq(info.irq);
} else {
printk(KERN_DEBUG "\nxen:DomU: No notify req to Dom0");
notify_remote_via_irq(info.irq);
}
printk("...\n");
return 0;
}
int file_write (struct file *filp, const char __user *buff, unsigned long len, void *data)
{
int value;
printk(KERN_DEBUG "\nxen:domU: file_write %lu bytes", len);
if (copy_from_user(&proc_data[0], buff, len))
return -EFAULT;
proc_data[len] = '\x0';
value = simple_strtol(proc_data, 0, 10);
switch(value) {
case 1:
send_request_to_dom0();
printk(KERN_DEBUG " ,value = %d", value);
break;
default:
printk(KERN_DEBUG " ,value not recongnized!");
}
return len;
}
int file_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
sprintf(page, "%s", proc_data);
return strlen(page);
}
int create_procfs_entry(void)
{
int ret = 0;
proc_dir = proc_mkdir("demo", NULL);
if (!proc_dir) {
printk(KERN_DEBUG "\nxen:domU could not create demo entry in procfs");
ret = - EAGAIN;
return ret;
}
proc_file = create_proc_entry("file", 0600, proc_dir);
if (proc_file) {
proc_file->read_proc = file_read;
proc_file->write_proc = file_write;
//proc_file->owner = THIS_MODULE;
} else {
printk(KERN_DEBUG "\nxen:domU Could not create /proc/demo/file");
ret = -EAGAIN;
return ret;
}
return ret;
}
static irqreturn_t as_int (int irq, void *dev_id)
{
struct as_response *ring_resp;
RING_IDX i, rp;
printk("\nxen:DomU: as_int called");
again:
rp = info.ring.sring->rsp_prod;
printk(KERN_DEBUG "\nxen:DomU:ring pointers %d to %d", info.ring.rsp_cons, rp);
for (i = info.ring.rsp_cons; i != rp; i++) {
unsigned long id;
ring_resp = RING_GET_RESPONSE(&(info.ring), i);
printk(KERN_DEBUG "\nxen:domU: Recvd in IDX-%d, with id=%d, op=%d, st=%d", i, ring_resp->id, ring_resp->operation, ring_resp->status);
id = ring_resp->id;
switch(ring_resp->operation) {
case 0:
printk(KERN_DEBUG "\nxen:DomU: operation: 0");
break;
default:
break;
}
}
info.ring.rsp_cons = i;
if (i != info.ring.req_prod_pvt) {
int more_to_do;
RING_FINAL_CHECK_FOR_RESPONSES(&info.ring, more_to_do);
if (more_to_do)
goto again;
} else
info.ring.sring->rsp_event = i + 1;
return IRQ_HANDLED;
}
int gnt_init(void)
{
int mfn;
int err;
//int i;
struct as_sring *sring;
//char *p;
////////////
struct evtchn_alloc_unbound alloc_unbound;
printk(KERN_INFO "gnt_init\n");
page = __get_free_pages(GFP_KERNEL, 0);
if (page == 0) {
printk(KERN_DEBUG "\nxen:DomU:could not get free page");
return 0;
}
sring = (struct as_sring *)page;
SHARED_RING_INIT(sring);
FRONT_RING_INIT(&(info.ring), sring, PAGE_SIZE);
mfn = virt_to_mfn(page);
/*
p = (char *)page + PAGE_SIZE - 1;
for (i = 0; i addr, GNTMAP_host_map, info.gref, info.remoteDomain);//为下面的hypercall的参数做准备
if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &ops, 1)) {//页面映射
printk(KERN_DEBUG "\nxen:dom0: HYPERVISOR map grant ref failed");
return -EFAULT;
}
if (ops.status) {
printk(KERN_DEBUG "\nxen: dom0: HYPERVISOR map grant ref failed status = %d", ops.status);
return -EFAULT;
}
printk(KERN_DEBUG "\nxen:dom0:shared_page=%x, handle = %x, status = %x", (unsigned int)v_start->addr, ops.handle, ops.status);
unmap_ops.host_addr = (unsigned long)(v_start->addr);
unmap_ops.handle = ops.handle;
//////////////
/*
p = (char *)(v_start->addr) + PAGE_SIZE - 1;
printk(KERN_DEBUG "\nbytes in page");
for (i = 0;i addr;
BACK_RING_INIT(&info.ring, sring, PAGE_SIZE);
err = bind_interdomain_evtchn_to_irqhandler(info.remoteDomain, info.evtchn, as_int, 0, "dom0-backend", &info);
if (err < 0) {
printk(KERN_DEBUG "\nxen:dom0: gnt_init failed binding to evtchn");
err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmap_ops, 1);
return -EFAULT;
}
info.irq = err;
printk(KERN_DEBUG "\nxen:dom0:end gnt_int: int = %d", info.irq);
return 0;
}
static void gnt_exit(void)
{
int ret;
printk(KERN_DEBUG "\nxen:dom0:gnt_exit");
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmap_ops, 1);
if (ret == 0) {
printk(KERN_DEBUG "gnt_exit: unmapped shared frame");
} else {
printk(KERN_DEBUG "gnt_exit: unmapped shared frame failed");
}
printk("...\n");
}
module_init(gnt_init);
module_exit(gnt_exit);
MODULE_LICENSE("GPL");
Domain0
dom0所做的工作:
1. 因为我们需要将domU的一部分内存映射到dom0内,因此调用alloc_vm_area预留一段内核空间和页表,但是实际并没有映射;
2. 调用gnttab_set_map_op为超级调用的参数做准备,然后调用HYPERVISOR_grant_table_op(GTNTABOP_map_grant_ref, ...)进行页面映射;
3. 调用BACK_RING_INIT初始化共享环后端;
4. 调用bind_interdomain_evtchn_to_irqhandler将端口与中断处理程序绑定,这样会得到中断号,注意端口号是模块函数的参数。 |
|