Add dom0 operation support for Xen3. Probably buggy, but it's enouth to have
xend and xenstored starting; xm info and xm list works.
This commit is contained in:
parent
96d1fdec03
commit
c8a960c560
89
sys/arch/xen/include/xenio3.h
Normal file
89
sys/arch/xen/include/xenio3.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* $NetBSD: xenio3.h,v 1.1 2006/05/07 10:18:28 bouyer Exp $ */
|
||||
/******************************************************************************
|
||||
* evtchn.h
|
||||
*
|
||||
* Interface to /dev/xen/evtchn.
|
||||
*
|
||||
* Copyright (c) 2003-2005, K A Fraser
|
||||
*
|
||||
* This file may be distributed separately from the Linux kernel, or
|
||||
* incorporated into other software packages, subject to the following license:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this source file (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_PUBLIC_EVTCHN_H__
|
||||
#define __LINUX_PUBLIC_EVTCHN_H__
|
||||
|
||||
/*
|
||||
* Bind a fresh port to VIRQ @virq.
|
||||
* Return allocated port.
|
||||
*/
|
||||
#define IOCTL_EVTCHN_BIND_VIRQ \
|
||||
_IOWR('E', 4, struct ioctl_evtchn_bind_virq)
|
||||
struct ioctl_evtchn_bind_virq {
|
||||
unsigned int virq;
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
/*
|
||||
* Bind a fresh port to remote <@remote_domain, @remote_port>.
|
||||
* Return allocated port.
|
||||
*/
|
||||
#define IOCTL_EVTCHN_BIND_INTERDOMAIN \
|
||||
_IOWR('E', 5, struct ioctl_evtchn_bind_interdomain)
|
||||
struct ioctl_evtchn_bind_interdomain {
|
||||
unsigned int remote_domain, remote_port;
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
/*
|
||||
* Allocate a fresh port for binding to @remote_domain.
|
||||
* Return allocated port.
|
||||
*/
|
||||
#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \
|
||||
_IOWR('E', 6, struct ioctl_evtchn_bind_unbound_port)
|
||||
struct ioctl_evtchn_bind_unbound_port {
|
||||
unsigned int remote_domain;
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
/*
|
||||
* Unbind previously allocated @port.
|
||||
*/
|
||||
#define IOCTL_EVTCHN_UNBIND \
|
||||
_IOW('E', 7, struct ioctl_evtchn_unbind)
|
||||
struct ioctl_evtchn_unbind {
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
/*
|
||||
* Send event to previously allocated @port.
|
||||
*/
|
||||
#define IOCTL_EVTCHN_NOTIFY \
|
||||
_IOW('E', 8, struct ioctl_evtchn_notify)
|
||||
struct ioctl_evtchn_notify {
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
/* Clear and reinitialise the event buffer. Clear error condition. */
|
||||
#define IOCTL_EVTCHN_RESET \
|
||||
_IO('E', 9)
|
||||
|
||||
#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: xenevt.c,v 1.7 2005/12/12 22:56:50 jld Exp $ */
|
||||
/* $NetBSD: xenevt.c,v 1.8 2006/05/07 10:18:28 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Manuel Bouyer.
|
||||
@ -30,6 +30,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opt_xen.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -42,8 +43,14 @@
|
||||
#include <sys/proc.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/xenpmap.h>
|
||||
#include <machine/xenio.h>
|
||||
#ifdef XEN3
|
||||
#include <machine/xenio3.h>
|
||||
#endif
|
||||
#include <machine/xen.h>
|
||||
|
||||
extern struct evcnt softxenevt_evtcnt;
|
||||
@ -59,40 +66,53 @@ extern struct evcnt softxenevt_evtcnt;
|
||||
*/
|
||||
|
||||
void xenevtattach(int);
|
||||
static int xenevt_read(struct file *, off_t *, struct uio *,
|
||||
static int xenevt_fread(struct file *, off_t *, struct uio *,
|
||||
struct ucred *, int);
|
||||
static int xenevt_write(struct file *, off_t *, struct uio *,
|
||||
static int xenevt_fwrite(struct file *, off_t *, struct uio *,
|
||||
struct ucred *, int);
|
||||
static int xenevt_ioctl(struct file *, u_long, void *, struct lwp *);
|
||||
static int xenevt_poll(struct file *, int, struct lwp *);
|
||||
static int xenevt_close(struct file *, struct lwp *);
|
||||
/* static int xenevt_kqfilter(struct file *, struct knote *); */
|
||||
static int xenevt_fioctl(struct file *, u_long, void *, struct lwp *);
|
||||
static int xenevt_fpoll(struct file *, int, struct lwp *);
|
||||
static int xenevt_fclose(struct file *, struct lwp *);
|
||||
/* static int xenevt_fkqfilter(struct file *, struct knote *); */
|
||||
|
||||
static const struct fileops xenevt_fileops = {
|
||||
xenevt_read,
|
||||
xenevt_write,
|
||||
xenevt_ioctl,
|
||||
xenevt_fread,
|
||||
xenevt_fwrite,
|
||||
xenevt_fioctl,
|
||||
fnullop_fcntl,
|
||||
xenevt_poll,
|
||||
xenevt_fpoll,
|
||||
fbadop_stat,
|
||||
xenevt_close,
|
||||
/* xenevt_kqfilter */ fnullop_kqfilter
|
||||
xenevt_fclose,
|
||||
/* xenevt_fkqfilter */ fnullop_kqfilter
|
||||
};
|
||||
|
||||
dev_type_open(xenevtopen);
|
||||
dev_type_read(xenevtread);
|
||||
dev_type_mmap(xenevtmmap);
|
||||
const struct cdevsw xenevt_cdevsw = {
|
||||
xenevtopen, noclose, noread, nowrite, noioctl,
|
||||
nostop, notty, nopoll, nommap, nokqfilter,
|
||||
xenevtopen, nullclose, xenevtread, nowrite, noioctl,
|
||||
nostop, notty, nopoll, xenevtmmap, nokqfilter,
|
||||
};
|
||||
|
||||
/* minor numbers */
|
||||
#define DEV_EVT 0
|
||||
#define DEV_XSD 1
|
||||
|
||||
/* per-instance datas */
|
||||
#define XENEVT_RING_SIZE 2048
|
||||
#define XENEVT_RING_MASK 2047
|
||||
|
||||
#ifndef XEN3
|
||||
typedef uint16_t evtchn_port_t;
|
||||
#endif
|
||||
|
||||
#define BYTES_PER_PORT (sizeof(evtchn_port_t) / sizeof(uint8_t))
|
||||
|
||||
struct xenevt_d {
|
||||
struct simplelock lock;
|
||||
STAILQ_ENTRY(xenevt_d) pendingq;
|
||||
boolean_t pending;
|
||||
u_int16_t ring[2048];
|
||||
evtchn_port_t ring[2048];
|
||||
u_int ring_read; /* pointer of the reader */
|
||||
u_int ring_write; /* pointer of the writer */
|
||||
u_int flags;
|
||||
@ -109,7 +129,7 @@ STAILQ_HEAD(, xenevt_d) devevent_pending =
|
||||
STAILQ_HEAD_INITIALIZER(devevent_pending);
|
||||
|
||||
static void xenevt_donotify(struct xenevt_d *);
|
||||
static void xenevt_record(struct xenevt_d *, int);
|
||||
static void xenevt_record(struct xenevt_d *, evtchn_port_t);
|
||||
|
||||
/* called at boot time */
|
||||
void
|
||||
@ -192,7 +212,7 @@ xenevt_donotify(struct xenevt_d *d)
|
||||
}
|
||||
|
||||
static void
|
||||
xenevt_record(struct xenevt_d *d, int port)
|
||||
xenevt_record(struct xenevt_d *d, evtchn_port_t port)
|
||||
{
|
||||
|
||||
/*
|
||||
@ -219,26 +239,94 @@ xenevtopen(dev_t dev, int flags, int mode, struct lwp *l)
|
||||
struct file *fp;
|
||||
int fd, error;
|
||||
|
||||
/* falloc() will use the descriptor for us. */
|
||||
if ((error = falloc(l->l_proc, &fp, &fd)) != 0)
|
||||
switch(minor(dev)) {
|
||||
case DEV_EVT:
|
||||
/* falloc() will use the descriptor for us. */
|
||||
if ((error = falloc(l->l_proc, &fp, &fd)) != 0)
|
||||
return error;
|
||||
|
||||
d = malloc(sizeof(*d), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
simple_lock_init(&d->lock);
|
||||
return fdclone(l, fp, fd, flags, &xenevt_fileops, d);
|
||||
#ifdef XEN3
|
||||
case DEV_XSD:
|
||||
/* no clone for /dev/xsd_kva */
|
||||
return (0);
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
/* read from device: only for /dev/xsd_kva, xenevt is done though fread */
|
||||
int
|
||||
xenevtread(dev_t dev, struct uio *uio, int flags)
|
||||
{
|
||||
#ifdef XEN3
|
||||
#define LD_STRLEN 21 /* a 64bit integer needs 20 digits in base10 */
|
||||
if (minor(dev) == DEV_XSD) {
|
||||
char strbuf[LD_STRLEN], *bf;
|
||||
int off, error;
|
||||
size_t len;
|
||||
|
||||
off = (int)uio->uio_offset;
|
||||
if (off < 0)
|
||||
return EINVAL;
|
||||
len = snprintf(strbuf, sizeof(strbuf), "%ld\n",
|
||||
xen_start_info.store_mfn);
|
||||
if (off >= len) {
|
||||
bf = strbuf;
|
||||
len = 0;
|
||||
} else {
|
||||
bf = &strbuf[off];
|
||||
len -= off;
|
||||
}
|
||||
error = uiomove(bf, len, uio);
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
d = malloc(sizeof(*d), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
simple_lock_init(&d->lock);
|
||||
|
||||
return fdclone(l, fp, fd, flags, &xenevt_fileops, d);
|
||||
/* mmap: only for xsd_kva */
|
||||
paddr_t
|
||||
xenevtmmap(dev_t dev, off_t off, int prot)
|
||||
{
|
||||
#ifdef XEN3
|
||||
if (minor(dev) == DEV_XSD) {
|
||||
/* only one page, so off is always 0 */
|
||||
if (off != 0)
|
||||
return -1;
|
||||
return x86_btop(
|
||||
xpmap_mtop(xen_start_info.store_mfn << PAGE_SHIFT));
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
xenevt_close(struct file *fp, struct lwp *l)
|
||||
xenevt_fclose(struct file *fp, struct lwp *l)
|
||||
{
|
||||
struct xenevt_d *d = fp->f_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NR_EVENT_CHANNELS; i++ ) {
|
||||
if (devevent[i] == d) {
|
||||
#ifdef XEN3
|
||||
evtchn_op_t op = { 0 };
|
||||
int error;
|
||||
#endif
|
||||
hypervisor_mask_event(i);
|
||||
devevent[i] = NULL;
|
||||
#ifdef XEN3
|
||||
op.cmd = EVTCHNOP_close;
|
||||
op.u.close.port = i;
|
||||
if ((error = HYPERVISOR_event_channel_op(&op))) {
|
||||
printf("xenevt_fclose: error %d from "
|
||||
"hypervisor\n", -error);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
free(d, M_DEVBUF);
|
||||
@ -248,7 +336,7 @@ xenevt_close(struct file *fp, struct lwp *l)
|
||||
}
|
||||
|
||||
static int
|
||||
xenevt_read(struct file *fp, off_t *offp, struct uio *uio,
|
||||
xenevt_fread(struct file *fp, off_t *offp, struct uio *uio,
|
||||
struct ucred *cred, int flags)
|
||||
{
|
||||
struct xenevt_d *d = fp->f_data;
|
||||
@ -289,25 +377,25 @@ xenevt_read(struct file *fp, off_t *offp, struct uio *uio,
|
||||
return error;
|
||||
}
|
||||
|
||||
uio_len = uio->uio_resid >> 1;
|
||||
uio_len = uio->uio_resid / BYTES_PER_PORT;
|
||||
if (ring_read <= ring_write)
|
||||
len = ring_write - ring_read;
|
||||
else
|
||||
len = XENEVT_RING_SIZE - ring_read;
|
||||
if (len > uio_len)
|
||||
len = uio_len;
|
||||
error = uiomove(&d->ring[ring_read], len << 1, uio);
|
||||
error = uiomove(&d->ring[ring_read], len * BYTES_PER_PORT, uio);
|
||||
if (error)
|
||||
return error;
|
||||
ring_read = (ring_read + len) & XENEVT_RING_MASK;
|
||||
uio_len = uio->uio_resid >> 1;
|
||||
uio_len = uio->uio_resid / BYTES_PER_PORT;
|
||||
if (uio_len == 0)
|
||||
goto done;
|
||||
/* ring wrapped, read the second part */
|
||||
len = ring_write - ring_read;
|
||||
if (len > uio_len)
|
||||
len = uio_len;
|
||||
error = uiomove(&d->ring[ring_read], len << 1, uio);
|
||||
error = uiomove(&d->ring[ring_read], len * BYTES_PER_PORT, uio);
|
||||
if (error)
|
||||
return error;
|
||||
ring_read = (ring_read + len) & XENEVT_RING_MASK;
|
||||
@ -323,7 +411,7 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
xenevt_write(struct file *fp, off_t *offp, struct uio *uio,
|
||||
xenevt_fwrite(struct file *fp, off_t *offp, struct uio *uio,
|
||||
struct ucred *cred, int flags)
|
||||
{
|
||||
struct xenevt_d *d = fp->f_data;
|
||||
@ -348,16 +436,94 @@ xenevt_write(struct file *fp, off_t *offp, struct uio *uio,
|
||||
}
|
||||
|
||||
static int
|
||||
xenevt_ioctl(struct file *fp, u_long cmd, void *addr, struct lwp *l)
|
||||
xenevt_fioctl(struct file *fp, u_long cmd, void *addr, struct lwp *l)
|
||||
{
|
||||
struct xenevt_d *d = fp->f_data;
|
||||
#ifdef XEN3
|
||||
evtchn_op_t op = { 0 };
|
||||
int error;
|
||||
#else
|
||||
u_int *arg = addr;
|
||||
#endif
|
||||
|
||||
switch(cmd) {
|
||||
case EVTCHN_RESET:
|
||||
#ifdef XEN3
|
||||
case IOCTL_EVTCHN_RESET:
|
||||
#endif
|
||||
d->ring_read = d->ring_write = 0;
|
||||
d->flags = 0;
|
||||
break;
|
||||
#ifdef XEN3
|
||||
case IOCTL_EVTCHN_BIND_VIRQ:
|
||||
{
|
||||
struct ioctl_evtchn_bind_virq *bind_virq = addr;
|
||||
op.cmd = EVTCHNOP_bind_virq;
|
||||
op.u.bind_virq.virq = bind_virq->virq;
|
||||
op.u.bind_virq.vcpu = 0;
|
||||
if ((error = HYPERVISOR_event_channel_op(&op))) {
|
||||
printf("IOCTL_EVTCHN_BIND_VIRQ failed: virq %d error %d\n", bind_virq->virq, error);
|
||||
return -error;
|
||||
}
|
||||
bind_virq->port = op.u.bind_virq.port;
|
||||
devevent[bind_virq->port] = d;
|
||||
hypervisor_unmask_event(bind_virq->port);
|
||||
break;
|
||||
}
|
||||
case IOCTL_EVTCHN_BIND_INTERDOMAIN:
|
||||
{
|
||||
struct ioctl_evtchn_bind_interdomain *bind_intd = addr;
|
||||
op.cmd = EVTCHNOP_bind_interdomain;
|
||||
op.u.bind_interdomain.remote_dom = bind_intd->remote_domain;
|
||||
op.u.bind_interdomain.remote_port = bind_intd->remote_port;
|
||||
if ((error = HYPERVISOR_event_channel_op(&op)))
|
||||
return error;
|
||||
bind_intd->port = op.u.bind_interdomain.local_port;
|
||||
devevent[bind_intd->port] = d;
|
||||
hypervisor_unmask_event(bind_intd->port);
|
||||
break;
|
||||
}
|
||||
case IOCTL_EVTCHN_BIND_UNBOUND_PORT:
|
||||
{
|
||||
struct ioctl_evtchn_bind_unbound_port *bind_unbound = addr;
|
||||
op.cmd = EVTCHNOP_alloc_unbound;
|
||||
op.u.alloc_unbound.dom = DOMID_SELF;
|
||||
op.u.alloc_unbound.remote_dom = bind_unbound->remote_domain;
|
||||
if ((error = HYPERVISOR_event_channel_op(&op)))
|
||||
return error;
|
||||
bind_unbound->port = op.u.alloc_unbound.port;
|
||||
devevent[bind_unbound->port] = d;
|
||||
hypervisor_unmask_event(bind_unbound->port);
|
||||
break;
|
||||
}
|
||||
case IOCTL_EVTCHN_UNBIND:
|
||||
{
|
||||
struct ioctl_evtchn_unbind *unbind = addr;
|
||||
|
||||
if (unbind->port > NR_EVENT_CHANNELS)
|
||||
return EINVAL;
|
||||
if (devevent[unbind->port] != d)
|
||||
return ENOTCONN;
|
||||
devevent[unbind->port] = NULL;
|
||||
hypervisor_mask_event(unbind->port);
|
||||
op.cmd = EVTCHNOP_close;
|
||||
op.u.close.port = unbind->port;
|
||||
if ((error = HYPERVISOR_event_channel_op(&op)))
|
||||
return error;
|
||||
break;
|
||||
}
|
||||
case IOCTL_EVTCHN_NOTIFY:
|
||||
{
|
||||
struct ioctl_evtchn_notify *notify = addr;
|
||||
|
||||
if (notify->port > NR_EVENT_CHANNELS)
|
||||
return EINVAL;
|
||||
if (devevent[notify->port] != d)
|
||||
return ENOTCONN;
|
||||
hypervisor_notify_via_evtchn(notify->port);
|
||||
break;
|
||||
}
|
||||
#else /* !XEN3 */
|
||||
case EVTCHN_BIND:
|
||||
if (*arg > NR_EVENT_CHANNELS)
|
||||
return EINVAL;
|
||||
@ -374,6 +540,7 @@ xenevt_ioctl(struct file *fp, u_long cmd, void *addr, struct lwp *l)
|
||||
devevent[*arg] = NULL;
|
||||
hypervisor_mask_event(*arg);
|
||||
break;
|
||||
#endif /* !XEN3 */
|
||||
case FIONBIO:
|
||||
break;
|
||||
default:
|
||||
@ -389,7 +556,7 @@ xenevt_ioctl(struct file *fp, u_long cmd, void *addr, struct lwp *l)
|
||||
*/
|
||||
|
||||
static int
|
||||
xenevt_poll(struct file *fp, int events, struct lwp *l)
|
||||
xenevt_fpoll(struct file *fp, int events, struct lwp *l)
|
||||
{
|
||||
struct xenevt_d *d = fp->f_data;
|
||||
int revents = events & (POLLOUT | POLLWRNORM); /* we can always write */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: xenbus_dev.c,v 1.3 2006/04/11 22:09:09 bouyer Exp $ */
|
||||
/* $NetBSD: xenbus_dev.c,v 1.4 2006/05/07 10:18:28 bouyer Exp $ */
|
||||
/*
|
||||
* xenbus_dev.c
|
||||
*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: xenbus_dev.c,v 1.3 2006/04/11 22:09:09 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: xenbus_dev.c,v 1.4 2006/05/07 10:18:28 bouyer Exp $");
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
@ -58,7 +58,6 @@ static int xenbus_dev_read(void *);
|
||||
static int xenbus_dev_write(void *);
|
||||
static int xenbus_dev_open(void *);
|
||||
static int xenbus_dev_close(void *);
|
||||
static int xsd_mfn_read(void *);
|
||||
static int xsd_port_read(void *);
|
||||
|
||||
struct xenbus_dev_transaction {
|
||||
@ -76,9 +75,6 @@ static const struct kernfs_fileop xenbus_fileops[] = {
|
||||
};
|
||||
|
||||
#define XSD_MODE (S_IRUSR)
|
||||
static const struct kernfs_fileop xsd_mfn_fileops[] = {
|
||||
{ .kf_fileop = KERNFS_FILEOP_READ, .kf_vop = xsd_mfn_read },
|
||||
};
|
||||
static const struct kernfs_fileop xsd_port_fileops[] = {
|
||||
{ .kf_fileop = KERNFS_FILEOP_READ, .kf_vop = xsd_port_read },
|
||||
};
|
||||
@ -95,11 +91,6 @@ xenbus_kernfs_init()
|
||||
PRIVCMD_MODE);
|
||||
kernfs_addentry(kernxen_pkt, dkt);
|
||||
|
||||
kfst = KERNFS_ALLOCTYPE(xsd_mfn_fileops);
|
||||
KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
|
||||
KERNFS_INITENTRY(dkt, DT_REG, "xsd_mfn", NULL, kfst, VREG, XSD_MODE);
|
||||
kernfs_addentry(kernxen_pkt, dkt);
|
||||
|
||||
kfst = KERNFS_ALLOCTYPE(xsd_port_fileops);
|
||||
KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
|
||||
KERNFS_INITENTRY(dkt, DT_REG, "xsd_port", NULL, kfst, VREG, XSD_MODE);
|
||||
@ -323,36 +314,6 @@ xenbus_dev_close(void *v)
|
||||
}
|
||||
|
||||
#define LD_STRLEN 21 /* a 64bit integer needs 20 digits in base10 */
|
||||
static int
|
||||
xsd_mfn_read(void *v)
|
||||
{
|
||||
struct vop_read_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct uio *a_uio;
|
||||
int a_ioflag;
|
||||
struct ucred *a_cred;
|
||||
} */ *ap = v;
|
||||
struct uio *uio = ap->a_uio;
|
||||
int off, error;
|
||||
size_t len;
|
||||
char strbuf[LD_STRLEN], *bf;
|
||||
|
||||
off = (int)uio->uio_offset;
|
||||
if (off < 0)
|
||||
return EINVAL;
|
||||
|
||||
len = snprintf(strbuf, sizeof(strbuf), "%ld\n",
|
||||
xen_start_info.store_mfn);
|
||||
if (off >= len) {
|
||||
bf = strbuf;
|
||||
len = 0;
|
||||
} else {
|
||||
bf = &strbuf[off];
|
||||
len -= off;
|
||||
}
|
||||
error = uiomove(bf, len, uio);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
xsd_port_read(void *v)
|
||||
|
Loading…
Reference in New Issue
Block a user