Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
e4073623
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e4073623
编写于
4月 03, 2009
作者:
D
Daniel P. Berrange
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Support PCI passthrough for Xen
上级
11b0ed46
变更
14
显示空白变更内容
内联
并排
Showing
14 changed file
with
821 addition
and
68 deletion
+821
-68
ChangeLog
ChangeLog
+21
-1
src/pci.c
src/pci.c
+134
-64
src/xen_unified.c
src/xen_unified.c
+122
-3
src/xend_internal.c
src/xend_internal.c
+232
-0
src/xm_internal.c
src/xm_internal.c
+156
-0
tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr
tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr
+2
-0
tests/sexpr2xmldata/sexpr2xml-pci-devs.xml
tests/sexpr2xmldata/sexpr2xml-pci-devs.xml
+37
-0
tests/sexpr2xmltest.c
tests/sexpr2xmltest.c
+1
-0
tests/xmconfigdata/test-pci-devs.cfg
tests/xmconfigdata/test-pci-devs.cfg
+24
-0
tests/xmconfigdata/test-pci-devs.xml
tests/xmconfigdata/test-pci-devs.xml
+56
-0
tests/xmconfigtest.c
tests/xmconfigtest.c
+1
-0
tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr
tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr
+1
-0
tests/xml2sexprdata/xml2sexpr-pci-devs.xml
tests/xml2sexprdata/xml2sexpr-pci-devs.xml
+33
-0
tests/xml2sexprtest.c
tests/xml2sexprtest.c
+1
-0
未找到文件。
ChangeLog
浏览文件 @
e4073623
Thu Apr 3 11:55:00 BST 2009 Daniel P. Berrange <berrange@redhat.com>
Fri Apr 3 11:55:00 BST 2009 Daniel P. Berrange <berrange@redhat.com>
Support PCI passthrough in Xen driver
* src/pci.c: Refactor to support Xen's pci-back.ko too
* src/xen_unified.c: Implement node device reattach/detach
reset APIs
* src/xend_internal.c: Handle creation of VMs with PCI
devices
* src/xm_internal.c: serialization of PCI device config
* tests/sexpr2xmltest.c, tests/xmconfigtest.c,
tests/xml2sexprtest.c: Add tests for PCI devices
* tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr,
tests/sexpr2xmldata/sexpr2xml-pci-devs.xml,
tests/xmconfigdata/test-pci-devs.cfg,
tests/xmconfigdata/test-pci-devs.xml,
tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr,
tests/xml2sexprdata/xml2sexpr-pci-devs.xml: Add data
files for PCI testing
Fri Apr 3 11:55:00 BST 2009 Daniel P. Berrange <berrange@redhat.com>
Improve error reporting/ verification of security labels
(Dan Walsh)
...
...
src/pci.c
浏览文件 @
e4073623
...
...
@@ -614,31 +614,72 @@ pciResetDevice(virConnectPtr conn, pciDevice *dev)
return
ret
;
}
static
int
pciBindDeviceToStub
(
virConnectPtr
conn
,
pciDevice
*
dev
,
const
char
*
stub_module
)
static
void
pciDriverDir
(
char
*
buf
,
size_t
buflen
,
const
char
*
driver
)
{
char
stub_dir
[
PATH_MAX
]
;
char
path
[
PATH_MAX
];
snprintf
(
buf
,
buflen
,
PCI_SYSFS
"drivers/%s"
,
driver
)
;
}
snprintf
(
stub_dir
,
sizeof
(
stub_dir
),
PCI_SYSFS
"drivers/%s"
,
stub_module
);
static
void
pciDriverFile
(
char
*
buf
,
size_t
buflen
,
const
char
*
driver
,
const
char
*
file
)
{
snprintf
(
buf
,
buflen
,
PCI_SYSFS
"drivers/%s/%s"
,
driver
,
file
);
}
/* Try loading the stub module if it isn't already loaded;
* Do not return an error if the stub module is not available.
*/
if
(
!
virFileExists
(
stub_dir
))
{
const
char
*
const
modprobeargv
[]
=
{
MODPROBE
,
stub_module
,
NULL
};
static
void
pciDeviceFile
(
char
*
buf
,
size_t
buflen
,
const
char
*
device
,
const
char
*
file
)
{
snprintf
(
buf
,
buflen
,
PCI_SYSFS
"devices/%s/%s"
,
device
,
file
);
}
if
(
virRun
(
conn
,
modprobeargv
,
NULL
)
<
0
)
{
static
const
char
*
pciFindStubDriver
(
virConnectPtr
conn
)
{
char
drvpath
[
PATH_MAX
];
int
probed
=
0
;
recheck:
pciDriverDir
(
drvpath
,
sizeof
(
drvpath
),
"pci-stub"
);
if
(
virFileExists
(
drvpath
))
return
"pci-stub"
;
pciDriverDir
(
drvpath
,
sizeof
(
drvpath
),
"pciback"
);
if
(
virFileExists
(
drvpath
))
return
"pciback"
;
if
(
!
probed
)
{
const
char
*
const
stubprobe
[]
=
{
MODPROBE
,
"pci-stub"
,
NULL
};
const
char
*
const
backprobe
[]
=
{
MODPROBE
,
"pciback"
,
NULL
};
probed
=
1
;
/*
* Probing for pci-stub will succeed regardless of whether
* on native or Xen kernels.
* On Xen though, we want to prefer pciback, so probe
* for that first, because that will only work on Xen
*/
if
(
virRun
(
conn
,
backprobe
,
NULL
)
<
0
&&
virRun
(
conn
,
stubprobe
,
NULL
)
<
0
)
{
char
ebuf
[
1024
];
VIR_WARN
(
_
(
"
modprobe %s failed: %s"
),
stub_module
,
VIR_WARN
(
_
(
"
failed to load pci-stub or pciback drivers: %s"
)
,
virStrerror
(
errno
,
ebuf
,
sizeof
ebuf
));
return
0
;
}
goto
recheck
;
}
if
(
!
virFileExists
(
stub_dir
))
{
VIR_WARN
(
_
(
"%s module not available, cannot bind device %s to it"
),
stub_module
,
dev
->
name
);
}
else
{
return
NULL
;
}
static
int
pciBindDeviceToStub
(
virConnectPtr
conn
,
pciDevice
*
dev
,
const
char
*
driver
)
{
char
drvdir
[
PATH_MAX
];
char
path
[
PATH_MAX
];
/* Add the PCI device ID to the stub's dynamic ID table;
* this is needed to allow us to bind the device to the stub.
* Note: if the device is not currently bound to any driver,
...
...
@@ -647,38 +688,45 @@ pciBindDeviceToStub(virConnectPtr conn, pciDevice *dev, const char *stub_module)
* is triggered for such a device, it will also be immediately
* bound by the stub.
*/
snprintf
(
path
,
sizeof
(
path
),
"%s/new_id"
,
stub_dir
);
pciDriverFile
(
path
,
sizeof
(
path
),
driver
,
"new_id"
);
if
(
virFileWriteStr
(
path
,
dev
->
id
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to add PCI device ID '%s' to %s"
),
dev
->
id
,
stub_module
);
dev
->
id
,
driver
);
return
-
1
;
}
}
/* If the device is already bound to a driver, unbind it.
* Note, this will have rather unpleasant side effects if this
* PCI device happens to be IDE controller for the disk hosting
* your root filesystem.
*/
snprintf
(
path
,
sizeof
(
path
),
PCI_SYSFS
"devices/%s/driver/unbind"
,
dev
->
name
);
pciDeviceFile
(
path
,
sizeof
(
path
),
dev
->
name
,
"driver/unbind"
);
if
(
virFileExists
(
path
)
&&
virFileWriteStr
(
path
,
dev
->
name
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to unbind PCI device '%s'"
),
dev
->
name
);
return
-
1
;
}
if
(
virFileExists
(
stub_dir
))
{
/* If the device isn't already bound to pci-stub, try binding it now.
*/
snprintf
(
path
,
sizeof
(
path
),
PCI_SYSFS
"devices/%s/driver"
,
dev
->
name
);
if
(
!
virFileLinkPointsTo
(
path
,
stub_dir
))
{
snprintf
(
path
,
sizeof
(
path
),
"%s/bind"
,
stub_dir
);
pciDriverDir
(
drvdir
,
sizeof
(
drvdir
),
driver
);
pciDeviceFile
(
path
,
sizeof
(
path
),
dev
->
name
,
"driver"
);
if
(
!
virFileLinkPointsTo
(
path
,
drvdir
))
{
/* Xen's pciback.ko wants you to use new_slot first */
pciDriverFile
(
path
,
sizeof
(
path
),
driver
,
"new_slot"
);
if
(
virFileExists
(
path
)
&&
virFileWriteStr
(
path
,
dev
->
name
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to add slot for PCI device '%s' to %s"
),
dev
->
name
,
driver
);
return
-
1
;
}
pciDriverFile
(
path
,
sizeof
(
path
),
driver
,
"bind"
);
if
(
virFileWriteStr
(
path
,
dev
->
name
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to bind PCI device '%s' to %s"
),
dev
->
name
,
stub_module
);
dev
->
name
,
driver
);
return
-
1
;
}
}
...
...
@@ -686,14 +734,13 @@ pciBindDeviceToStub(virConnectPtr conn, pciDevice *dev, const char *stub_module)
/* If 'remove_id' exists, remove the device id from pci-stub's dynamic
* ID table so that 'drivers_probe' works below.
*/
snprintf
(
path
,
sizeof
(
path
),
"%s/remove_id"
,
stub_dir
);
pciDriverFile
(
path
,
sizeof
(
path
),
driver
,
"remove_id"
);
if
(
virFileExists
(
path
)
&&
virFileWriteStr
(
path
,
dev
->
id
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to remove PCI ID '%s' from %s"
),
dev
->
id
,
stub_module
);
dev
->
id
,
driver
);
return
-
1
;
}
}
return
0
;
}
...
...
@@ -701,37 +748,53 @@ pciBindDeviceToStub(virConnectPtr conn, pciDevice *dev, const char *stub_module)
int
pciDettachDevice
(
virConnectPtr
conn
,
pciDevice
*
dev
)
{
return
pciBindDeviceToStub
(
conn
,
dev
,
"pci-stub"
);
const
char
*
driver
=
pciFindStubDriver
(
conn
);
if
(
!
driver
)
{
pciReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"cannot find any PCI stub module"
));
return
-
1
;
}
return
pciBindDeviceToStub
(
conn
,
dev
,
driver
);
}
static
int
pciUnBindDeviceFromStub
(
virConnectPtr
conn
,
pciDevice
*
dev
,
const
char
*
stub_module
)
pciUnBindDeviceFromStub
(
virConnectPtr
conn
,
pciDevice
*
dev
,
const
char
*
driver
)
{
char
stub_
dir
[
PATH_MAX
];
char
drv
dir
[
PATH_MAX
];
char
path
[
PATH_MAX
];
snprintf
(
stub_dir
,
sizeof
(
stub_dir
),
PCI_SYSFS
"drivers/%s"
,
stub_module
);
/* If the device is bound to stub, unbind it.
*/
snprintf
(
path
,
sizeof
(
path
),
PCI_SYSFS
"devices/%s/driver"
,
dev
->
name
);
if
(
virFileExists
(
stub_dir
)
&&
virFileLinkPointsTo
(
path
,
stub_dir
))
{
snprintf
(
path
,
sizeof
(
path
),
"%s/unbind"
,
stub_dir
);
pciDriverDir
(
drvdir
,
sizeof
(
drvdir
),
driver
);
pciDeviceFile
(
path
,
sizeof
(
path
),
dev
->
name
,
"driver"
);
if
(
virFileExists
(
drvdir
)
&&
virFileLinkPointsTo
(
path
,
drvdir
))
{
pciDriverFile
(
path
,
sizeof
(
path
),
driver
,
"unbind"
);
if
(
virFileWriteStr
(
path
,
dev
->
name
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to bind PCI device '%s' to %s"
),
dev
->
name
,
stub_module
);
dev
->
name
,
driver
);
return
-
1
;
}
}
/* Xen's pciback.ko wants you to use remove_slot on the specific device */
pciDriverFile
(
path
,
sizeof
(
path
),
driver
,
"remove_slot"
);
if
(
virFileExists
(
path
)
&&
virFileWriteStr
(
path
,
dev
->
name
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to remove slot for PCI device '%s' to %s"
),
dev
->
name
,
driver
);
return
-
1
;
}
/* Trigger a re-probe of the device is not in the stub's dynamic
* ID table. If the stub is available, but 'remove_id' isn't
* available, then re-probing would just cause the device to be
* re-bound to the stub.
*/
snprintf
(
path
,
sizeof
(
path
),
"%s/remove_id"
,
stub_dir
);
if
(
!
virFileExists
(
stub_
dir
)
||
virFileExists
(
path
))
{
pciDriverFile
(
path
,
sizeof
(
path
),
driver
,
"remove_id"
);
if
(
!
virFileExists
(
drv
dir
)
||
virFileExists
(
path
))
{
if
(
virFileWriteStr
(
PCI_SYSFS
"drivers_probe"
,
dev
->
name
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to trigger a re-probe for PCI device '%s'"
),
...
...
@@ -746,7 +809,14 @@ pciUnBindDeviceFromStub(virConnectPtr conn, pciDevice *dev, const char *stub_mod
int
pciReAttachDevice
(
virConnectPtr
conn
,
pciDevice
*
dev
)
{
return
pciUnBindDeviceFromStub
(
conn
,
dev
,
"pci-stub"
);
const
char
*
driver
=
pciFindStubDriver
(
conn
);
if
(
!
driver
)
{
pciReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"cannot find any PCI stub module"
));
return
-
1
;
}
return
pciUnBindDeviceFromStub
(
conn
,
dev
,
driver
);
}
static
char
*
...
...
src/xen_unified.c
浏览文件 @
e4073623
...
...
@@ -43,6 +43,8 @@
#include "xml.h"
#include "util.h"
#include "memory.h"
#include "node_device_conf.h"
#include "pci.h"
#define VIR_FROM_THIS VIR_FROM_XEN
...
...
@@ -1420,6 +1422,123 @@ xenUnifiedDomainEventDeregister (virConnectPtr conn,
return
ret
;
}
static
int
xenUnifiedNodeDeviceGetPciInfo
(
virNodeDevicePtr
dev
,
unsigned
*
domain
,
unsigned
*
bus
,
unsigned
*
slot
,
unsigned
*
function
)
{
virNodeDeviceDefPtr
def
=
NULL
;
virNodeDevCapsDefPtr
cap
;
char
*
xml
=
NULL
;
int
ret
=
-
1
;
xml
=
virNodeDeviceGetXMLDesc
(
dev
,
0
);
if
(
!
xml
)
goto
out
;
def
=
virNodeDeviceDefParseString
(
dev
->
conn
,
xml
);
if
(
!
def
)
goto
out
;
cap
=
def
->
caps
;
while
(
cap
)
{
if
(
cap
->
type
==
VIR_NODE_DEV_CAP_PCI_DEV
)
{
*
domain
=
cap
->
data
.
pci_dev
.
domain
;
*
bus
=
cap
->
data
.
pci_dev
.
bus
;
*
slot
=
cap
->
data
.
pci_dev
.
slot
;
*
function
=
cap
->
data
.
pci_dev
.
function
;
break
;
}
cap
=
cap
->
next
;
}
if
(
!
cap
)
{
xenUnifiedError
(
dev
->
conn
,
VIR_ERR_INVALID_ARG
,
_
(
"device %s is not a PCI device"
),
dev
->
name
);
goto
out
;
}
ret
=
0
;
out:
virNodeDeviceDefFree
(
def
);
VIR_FREE
(
xml
);
return
ret
;
}
static
int
xenUnifiedNodeDeviceDettach
(
virNodeDevicePtr
dev
)
{
pciDevice
*
pci
;
unsigned
domain
,
bus
,
slot
,
function
;
int
ret
=
-
1
;
if
(
xenUnifiedNodeDeviceGetPciInfo
(
dev
,
&
domain
,
&
bus
,
&
slot
,
&
function
)
<
0
)
return
-
1
;
pci
=
pciGetDevice
(
dev
->
conn
,
domain
,
bus
,
slot
,
function
);
if
(
!
pci
)
return
-
1
;
if
(
pciDettachDevice
(
dev
->
conn
,
pci
)
<
0
)
goto
out
;
ret
=
0
;
out:
pciFreeDevice
(
dev
->
conn
,
pci
);
return
ret
;
}
static
int
xenUnifiedNodeDeviceReAttach
(
virNodeDevicePtr
dev
)
{
pciDevice
*
pci
;
unsigned
domain
,
bus
,
slot
,
function
;
int
ret
=
-
1
;
if
(
xenUnifiedNodeDeviceGetPciInfo
(
dev
,
&
domain
,
&
bus
,
&
slot
,
&
function
)
<
0
)
return
-
1
;
pci
=
pciGetDevice
(
dev
->
conn
,
domain
,
bus
,
slot
,
function
);
if
(
!
pci
)
return
-
1
;
if
(
pciReAttachDevice
(
dev
->
conn
,
pci
)
<
0
)
goto
out
;
ret
=
0
;
out:
pciFreeDevice
(
dev
->
conn
,
pci
);
return
ret
;
}
static
int
xenUnifiedNodeDeviceReset
(
virNodeDevicePtr
dev
)
{
pciDevice
*
pci
;
unsigned
domain
,
bus
,
slot
,
function
;
int
ret
=
-
1
;
if
(
xenUnifiedNodeDeviceGetPciInfo
(
dev
,
&
domain
,
&
bus
,
&
slot
,
&
function
)
<
0
)
return
-
1
;
pci
=
pciGetDevice
(
dev
->
conn
,
domain
,
bus
,
slot
,
function
);
if
(
!
pci
)
return
-
1
;
if
(
pciResetDevice
(
dev
->
conn
,
pci
)
<
0
)
goto
out
;
ret
=
0
;
out:
pciFreeDevice
(
dev
->
conn
,
pci
);
return
ret
;
}
/*----- Register with libvirt.c, and initialise Xen drivers. -----*/
/* The interface which we export upwards to libvirt.c. */
...
...
@@ -1486,9 +1605,9 @@ static virDriver xenUnifiedDriver = {
xenUnifiedDomainEventDeregister
,
/* domainEventDeregister */
NULL
,
/* domainMigratePrepare2 */
NULL
,
/* domainMigrateFinish2 */
NULL
,
/* nodeDeviceDettach */
NULL
,
/* nodeDeviceReAttach */
NULL
,
/* nodeDeviceReset */
xenUnifiedNodeDeviceDettach
,
/* nodeDeviceDettach */
xenUnifiedNodeDeviceReAttach
,
/* nodeDeviceReAttach */
xenUnifiedNodeDeviceReset
,
/* nodeDeviceReset */
};
/**
...
...
src/xend_internal.c
浏览文件 @
e4073623
...
...
@@ -92,6 +92,11 @@ xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
int
xendConfigVersion
,
int
isAttach
);
static
int
xenDaemonFormatSxprOnePCI
(
virConnectPtr
conn
,
virDomainHostdevDefPtr
def
,
virBufferPtr
buf
);
static
int
virDomainXMLDevID
(
virDomainPtr
domain
,
virDomainDeviceDefPtr
dev
,
char
*
class
,
...
...
@@ -2145,6 +2150,131 @@ error:
return
-
1
;
}
/**
* xenDaemonParseSxprPCI
* @conn: connection
* @root: root sexpr
*
* This parses out block devices from the domain sexpr
*
* Returns 0 if successful or -1 if failed.
*/
static
int
xenDaemonParseSxprPCI
(
virConnectPtr
conn
,
virDomainDefPtr
def
,
const
struct
sexpr
*
root
)
{
const
struct
sexpr
*
cur
,
*
tmp
=
NULL
,
*
node
;
virDomainHostdevDefPtr
dev
=
NULL
;
/*
* With the (domain ...) block we have the following odd setup
*
* (device
* (pci
* (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
* (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
* )
* )
*
* Normally there is one (device ...) block per device, but in
* wierd world of Xen PCI, once (device ...) covers multiple
* devices.
*/
for
(
cur
=
root
;
cur
->
kind
==
SEXPR_CONS
;
cur
=
cur
->
u
.
s
.
cdr
)
{
node
=
cur
->
u
.
s
.
car
;
if
((
tmp
=
sexpr_lookup
(
node
,
"device/pci"
))
!=
NULL
)
break
;
}
if
(
!
tmp
)
return
0
;
for
(
cur
=
tmp
;
cur
->
kind
==
SEXPR_CONS
;
cur
=
cur
->
u
.
s
.
cdr
)
{
const
char
*
domain
=
NULL
;
const
char
*
bus
=
NULL
;
const
char
*
slot
=
NULL
;
const
char
*
func
=
NULL
;
int
domainID
;
int
busID
;
int
slotID
;
int
funcID
;
node
=
cur
->
u
.
s
.
car
;
if
(
!
sexpr_lookup
(
node
,
"dev"
))
continue
;
if
(
!
(
domain
=
sexpr_node
(
node
,
"dev/domain"
)))
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"missing PCI domain"
));
goto
error
;
}
if
(
!
(
bus
=
sexpr_node
(
node
,
"dev/bus"
)))
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"missing PCI bus"
));
goto
error
;
}
if
(
!
(
slot
=
sexpr_node
(
node
,
"dev/slot"
)))
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"missing PCI slot"
));
goto
error
;
}
if
(
!
(
func
=
sexpr_node
(
node
,
"dev/func"
)))
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"missing PCI func"
));
goto
error
;
}
if
(
virStrToLong_i
(
domain
,
NULL
,
0
,
&
domainID
)
<
0
)
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot parse PCI domain '%s'"
),
domain
);
goto
error
;
}
if
(
virStrToLong_i
(
bus
,
NULL
,
0
,
&
busID
)
<
0
)
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot parse PCI bus '%s'"
),
bus
);
goto
error
;
}
if
(
virStrToLong_i
(
slot
,
NULL
,
0
,
&
slotID
)
<
0
)
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot parse PCI slot '%s'"
),
slot
);
goto
error
;
}
if
(
virStrToLong_i
(
func
,
NULL
,
0
,
&
funcID
)
<
0
)
{
virXendError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot parse PCI func '%s'"
),
func
);
goto
error
;
}
if
(
VIR_ALLOC
(
dev
)
<
0
)
goto
no_memory
;
dev
->
mode
=
VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
;
dev
->
managed
=
0
;
dev
->
source
.
subsys
.
type
=
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
;
dev
->
source
.
subsys
.
u
.
pci
.
domain
=
domainID
;
dev
->
source
.
subsys
.
u
.
pci
.
bus
=
busID
;
dev
->
source
.
subsys
.
u
.
pci
.
slot
=
slotID
;
dev
->
source
.
subsys
.
u
.
pci
.
function
=
funcID
;
if
(
VIR_REALLOC_N
(
def
->
hostdevs
,
def
->
nhostdevs
+
1
)
<
0
)
{
goto
no_memory
;
}
def
->
hostdevs
[
def
->
nhostdevs
++
]
=
dev
;
}
return
0
;
no_memory:
virReportOOMError
(
conn
);
error:
virDomainHostdevDefFree
(
dev
);
return
-
1
;
}
/**
* xenDaemonParseSxpr:
...
...
@@ -2315,6 +2445,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
if
(
xenDaemonParseSxprNets
(
conn
,
def
,
root
)
<
0
)
goto
error
;
if
(
xenDaemonParseSxprPCI
(
conn
,
def
,
root
)
<
0
)
goto
error
;
/* New style graphics device config */
if
(
xenDaemonParseSxprGraphicsNew
(
conn
,
def
,
root
)
<
0
)
goto
error
;
...
...
@@ -3956,6 +4089,20 @@ xenDaemonAttachDevice(virDomainPtr domain, const char *xml)
goto
cleanup
;
break
;
case
VIR_DOMAIN_DEVICE_HOSTDEV
:
if
(
dev
->
data
.
hostdev
->
mode
==
VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
&&
dev
->
data
.
hostdev
->
source
.
subsys
.
type
==
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
)
{
if
(
xenDaemonFormatSxprOnePCI
(
domain
->
conn
,
dev
->
data
.
hostdev
,
&
buf
)
<
0
)
goto
cleanup
;
}
else
{
virXendError
(
domain
->
conn
,
VIR_ERR_NO_SUPPORT
,
"%s"
,
_
(
"unsupported device type"
));
goto
cleanup
;
}
break
;
default:
virXendError
(
domain
->
conn
,
VIR_ERR_NO_SUPPORT
,
"%s"
,
_
(
"unsupported device type"
));
...
...
@@ -5266,6 +5413,85 @@ xenDaemonFormatSxprNet(virConnectPtr conn,
return
0
;
}
static
void
xenDaemonFormatSxprPCI
(
virDomainHostdevDefPtr
def
,
virBufferPtr
buf
)
{
virBufferVSprintf
(
buf
,
"(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))"
,
def
->
source
.
subsys
.
u
.
pci
.
domain
,
def
->
source
.
subsys
.
u
.
pci
.
bus
,
def
->
source
.
subsys
.
u
.
pci
.
slot
,
def
->
source
.
subsys
.
u
.
pci
.
function
);
}
static
int
xenDaemonFormatSxprOnePCI
(
virConnectPtr
conn
,
virDomainHostdevDefPtr
def
,
virBufferPtr
buf
)
{
if
(
def
->
managed
)
{
virXendError
(
conn
,
VIR_ERR_NO_SUPPORT
,
"%s"
,
_
(
"managed PCI devices not supported with XenD"
));
return
-
1
;
}
virBufferAddLit
(
buf
,
"(pci "
);
xenDaemonFormatSxprPCI
(
def
,
buf
);
virBufferAddLit
(
buf
,
")"
);
return
0
;
}
static
int
xenDaemonFormatSxprAllPCI
(
virConnectPtr
conn
,
virDomainDefPtr
def
,
virBufferPtr
buf
)
{
int
hasPCI
=
0
;
int
i
;
for
(
i
=
0
;
i
<
def
->
nhostdevs
;
i
++
)
if
(
def
->
hostdevs
[
i
]
->
mode
==
VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
&&
def
->
hostdevs
[
i
]
->
source
.
subsys
.
type
==
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
)
hasPCI
=
1
;
if
(
!
hasPCI
)
return
0
;
/*
* With the (domain ...) block we have the following odd setup
*
* (device
* (pci
* (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
* (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
* )
* )
*
* Normally there is one (device ...) block per device, but in
* wierd world of Xen PCI, once (device ...) covers multiple
* devices.
*/
virBufferAddLit
(
buf
,
"(device (pci "
);
for
(
i
=
0
;
i
<
def
->
nhostdevs
;
i
++
)
{
if
(
def
->
hostdevs
[
i
]
->
mode
==
VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
&&
def
->
hostdevs
[
i
]
->
source
.
subsys
.
type
==
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
)
{
if
(
def
->
hostdevs
[
i
]
->
managed
)
{
virXendError
(
conn
,
VIR_ERR_NO_SUPPORT
,
"%s"
,
_
(
"managed PCI devices not supported with XenD"
));
return
-
1
;
}
xenDaemonFormatSxprPCI
(
def
->
hostdevs
[
i
],
buf
);
}
}
virBufferAddLit
(
buf
,
"))"
);
return
0
;
}
int
xenDaemonFormatSxprSound
(
virConnectPtr
conn
,
virDomainDefPtr
def
,
...
...
@@ -5537,6 +5763,9 @@ xenDaemonFormatSxpr(virConnectPtr conn,
&
buf
,
hvm
,
xendConfigVersion
,
0
)
<
0
)
goto
error
;
if
(
xenDaemonFormatSxprAllPCI
(
conn
,
def
,
&
buf
)
<
0
)
goto
error
;
/* New style PV graphics config xen >= 3.0.4,
* or HVM graphics config xen >= 3.0.5 */
if
((
xendConfigVersion
>=
XEND_CONFIG_MIN_VERS_PVFB_NEWCONF
&&
!
hvm
)
||
...
...
@@ -5624,6 +5853,9 @@ virDomainXMLDevID(virDomainPtr domain,
strncpy
(
ref
,
xref
,
ref_len
);
free
(
xref
);
ref
[
ref_len
-
1
]
=
'\0'
;
}
else
if
(
dev
->
type
==
VIR_DOMAIN_DEVICE_HOSTDEV
&&
dev
->
data
.
hostdev
->
mode
==
VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
&&
dev
->
data
.
hostdev
->
source
.
subsys
.
type
==
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
)
{
}
else
{
virXendError
(
NULL
,
VIR_ERR_NO_SUPPORT
,
"%s"
,
_
(
"hotplug of device type not supported"
));
...
...
src/xm_internal.c
浏览文件 @
e4073623
...
...
@@ -672,6 +672,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
virDomainDiskDefPtr
disk
=
NULL
;
virDomainNetDefPtr
net
=
NULL
;
virDomainGraphicsDefPtr
graphics
=
NULL
;
virDomainHostdevDefPtr
hostdev
=
NULL
;
int
i
;
const
char
*
defaultArch
,
*
defaultMachine
;
...
...
@@ -1126,6 +1127,88 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
}
}
list
=
virConfGetValue
(
conf
,
"pci"
);
if
(
list
&&
list
->
type
==
VIR_CONF_LIST
)
{
list
=
list
->
list
;
while
(
list
)
{
char
domain
[
5
];
char
bus
[
3
];
char
slot
[
3
];
char
func
[
2
];
char
*
key
,
*
nextkey
;
int
domainID
;
int
busID
;
int
slotID
;
int
funcID
;
domain
[
0
]
=
bus
[
0
]
=
slot
[
0
]
=
func
[
0
]
=
'\0'
;
if
((
list
->
type
!=
VIR_CONF_STRING
)
||
(
list
->
str
==
NULL
))
goto
skippci
;
/* pci=['0000:00:1b.0','0000:00:13.0'] */
key
=
list
->
str
;
if
(
!
(
key
=
list
->
str
))
goto
skippci
;
if
(
!
(
nextkey
=
strchr
(
key
,
':'
)))
goto
skippci
;
if
((
nextkey
-
key
)
>
(
sizeof
(
domain
)
-
1
))
goto
skippci
;
strncpy
(
domain
,
key
,
sizeof
(
domain
));
domain
[
sizeof
(
domain
)
-
1
]
=
'\0'
;
key
=
nextkey
+
1
;
if
(
!
(
nextkey
=
strchr
(
key
,
':'
)))
goto
skippci
;
strncpy
(
bus
,
key
,
sizeof
(
bus
));
bus
[
sizeof
(
bus
)
-
1
]
=
'\0'
;
key
=
nextkey
+
1
;
if
(
!
(
nextkey
=
strchr
(
key
,
'.'
)))
goto
skippci
;
strncpy
(
slot
,
key
,
sizeof
(
slot
));
slot
[
sizeof
(
slot
)
-
1
]
=
'\0'
;
key
=
nextkey
+
1
;
if
(
strlen
(
key
)
!=
1
)
goto
skippci
;
strncpy
(
func
,
key
,
sizeof
(
func
));
func
[
sizeof
(
func
)
-
1
]
=
'\0'
;
if
(
virStrToLong_i
(
domain
,
NULL
,
16
,
&
domainID
)
<
0
)
goto
skippci
;
if
(
virStrToLong_i
(
bus
,
NULL
,
16
,
&
busID
)
<
0
)
goto
skippci
;
if
(
virStrToLong_i
(
slot
,
NULL
,
16
,
&
slotID
)
<
0
)
goto
skippci
;
if
(
virStrToLong_i
(
func
,
NULL
,
16
,
&
funcID
)
<
0
)
goto
skippci
;
if
(
VIR_ALLOC
(
hostdev
)
<
0
)
goto
cleanup
;
hostdev
->
managed
=
0
;
hostdev
->
source
.
subsys
.
type
=
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
;
hostdev
->
source
.
subsys
.
u
.
pci
.
domain
=
domainID
;
hostdev
->
source
.
subsys
.
u
.
pci
.
bus
=
busID
;
hostdev
->
source
.
subsys
.
u
.
pci
.
slot
=
slotID
;
hostdev
->
source
.
subsys
.
u
.
pci
.
function
=
funcID
;
if
(
VIR_REALLOC_N
(
def
->
hostdevs
,
def
->
nhostdevs
+
1
)
<
0
)
goto
no_memory
;
def
->
hostdevs
[
def
->
nhostdevs
++
]
=
hostdev
;
hostdev
=
NULL
;
skippci:
list
=
list
->
next
;
}
}
if
(
hvm
)
{
if
(
xenXMConfigGetString
(
conn
,
conf
,
"usbdevice"
,
&
str
,
NULL
)
<
0
)
goto
cleanup
;
...
...
@@ -1951,6 +2034,76 @@ cleanup:
static
int
xenXMDomainConfigFormatPCI
(
virConnectPtr
conn
,
virConfPtr
conf
,
virDomainDefPtr
def
)
{
virConfValuePtr
pciVal
=
NULL
;
int
hasPCI
=
0
;
int
i
;
for
(
i
=
0
;
i
<
def
->
nhostdevs
;
i
++
)
if
(
def
->
hostdevs
[
i
]
->
mode
==
VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
&&
def
->
hostdevs
[
i
]
->
source
.
subsys
.
type
==
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
)
hasPCI
=
1
;
if
(
!
hasPCI
)
return
0
;
if
(
VIR_ALLOC
(
pciVal
)
<
0
)
return
-
1
;
pciVal
->
type
=
VIR_CONF_LIST
;
pciVal
->
list
=
NULL
;
for
(
i
=
0
;
i
<
def
->
nhostdevs
;
i
++
)
{
if
(
def
->
hostdevs
[
i
]
->
mode
==
VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
&&
def
->
hostdevs
[
i
]
->
source
.
subsys
.
type
==
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
)
{
virConfValuePtr
val
,
tmp
;
char
*
buf
;
if
(
virAsprintf
(
&
buf
,
"%04x:%02x:%02x.%x"
,
def
->
hostdevs
[
i
]
->
source
.
subsys
.
u
.
pci
.
domain
,
def
->
hostdevs
[
i
]
->
source
.
subsys
.
u
.
pci
.
bus
,
def
->
hostdevs
[
i
]
->
source
.
subsys
.
u
.
pci
.
slot
,
def
->
hostdevs
[
i
]
->
source
.
subsys
.
u
.
pci
.
function
)
<
0
)
goto
error
;
if
(
VIR_ALLOC
(
val
)
<
0
)
{
VIR_FREE
(
buf
);
virReportOOMError
(
conn
);
goto
error
;
}
val
->
type
=
VIR_CONF_STRING
;
val
->
str
=
buf
;
tmp
=
pciVal
->
list
;
while
(
tmp
&&
tmp
->
next
)
tmp
=
tmp
->
next
;
if
(
tmp
)
tmp
->
next
=
val
;
else
pciVal
->
list
=
val
;
}
}
if
(
pciVal
->
list
!=
NULL
)
{
int
ret
=
virConfSetValue
(
conf
,
"pci"
,
pciVal
);
pciVal
=
NULL
;
if
(
ret
<
0
)
return
-
1
;
}
VIR_FREE
(
pciVal
);
return
0
;
error:
virConfFreeValue
(
pciVal
);
return
-
1
;
}
virConfPtr
xenXMDomainConfigFormat
(
virConnectPtr
conn
,
virDomainDefPtr
def
)
{
virConfPtr
conf
=
NULL
;
...
...
@@ -2272,6 +2425,9 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
}
VIR_FREE
(
netVal
);
if
(
xenXMDomainConfigFormatPCI
(
conn
,
conf
,
def
)
<
0
)
goto
cleanup
;
if
(
hvm
)
{
if
(
def
->
nparallels
)
{
virBuffer
buf
=
VIR_BUFFER_INITIALIZER
;
...
...
tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr
0 → 100644
浏览文件 @
e4073623
(domain (domid 6)(name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (pci (backend 0)(dev (domain 0x0001) (bus 0x0c) (slot 0x1b) (func 0x2))(dev (domain 0x0000) (bus 0x01) (slot 0x13) (func 0x0))))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestVG')(mode 'w'))))
tests/sexpr2xmldata/sexpr2xml-pci-devs.xml
0 → 100644
浏览文件 @
e4073623
<domain
type=
'xen'
id=
'6'
>
<name>
pvtest
</name>
<uuid>
596a5d21-71f4-8fb2-e068-e2386a5c413e
</uuid>
<memory>
430080
</memory>
<currentMemory>
430080
</currentMemory>
<vcpu>
2
</vcpu>
<os>
<type>
linux
</type>
<kernel>
/var/lib/xen/vmlinuz.2Dn2YT
</kernel>
<initrd>
/var/lib/xen/initrd.img.0u-Vhq
</initrd>
<cmdline>
method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os
</cmdline>
</os>
<clock
offset=
'utc'
/>
<on_poweroff>
destroy
</on_poweroff>
<on_reboot>
destroy
</on_reboot>
<on_crash>
destroy
</on_crash>
<devices>
<disk
type=
'block'
device=
'disk'
>
<driver
name=
'phy'
/>
<source
dev=
'/dev/MainVG/GuestVG'
/>
<target
dev=
'xvda'
bus=
'xen'
/>
</disk>
<console
type=
'pty'
>
<target
port=
'0'
/>
</console>
<hostdev
mode=
'subsystem'
type=
'pci'
managed=
'no'
>
<source>
<address
domain=
'0x0001'
bus=
'0x0c'
slot=
'0x1b'
function=
'0x2'
/>
</source>
</hostdev>
<hostdev
mode=
'subsystem'
type=
'pci'
managed=
'no'
>
<source>
<address
domain=
'0x0000'
bus=
'0x01'
slot=
'0x13'
function=
'0x0'
/>
</source>
</hostdev>
</devices>
</domain>
tests/sexpr2xmltest.c
浏览文件 @
e4073623
...
...
@@ -145,6 +145,7 @@ mymain(int argc, char **argv)
DO_TEST
(
"bridge-ipaddr"
,
"bridge-ipaddr"
,
3
);
DO_TEST
(
"no-source-cdrom"
,
"no-source-cdrom"
,
2
);
DO_TEST
(
"pv-localtime"
,
"pv-localtime"
,
2
);
DO_TEST
(
"pci-devs"
,
"pci-devs"
,
2
);
DO_TEST
(
"fv-utc"
,
"fv-utc"
,
1
);
DO_TEST
(
"fv-localtime"
,
"fv-localtime"
,
1
);
...
...
tests/xmconfigdata/test-pci-devs.cfg
0 → 100644
浏览文件 @
e4073623
name = "test"
uuid = "cc2315e7-d26a-307a-438c-6d188ec4c09c"
maxmem = 382
memory = 350
vcpus = 1
builder = "hvm"
kernel = "/usr/lib/xen/boot/hvmloader"
boot = "c"
pae = 1
acpi = 1
apic = 1
localtime = 0
on_poweroff = "destroy"
on_reboot = "destroy"
on_crash = "destroy"
device_model = "/usr/lib/xen/bin/qemu-dm"
sdl = 0
vnc = 1
vncunused = 1
disk = [ "phy:/dev/sda8,hda,w", ",hdc:cdrom,r" ]
vif = [ "mac=00:16:3e:0a:7b:39,bridge=xenbr0,type=ioemu" ]
pci = [ "0001:0c:1b.2", "0000:01:13.0" ]
parallel = "none"
serial = "pty"
tests/xmconfigdata/test-pci-devs.xml
0 → 100644
浏览文件 @
e4073623
<domain
type=
'xen'
>
<name>
test
</name>
<uuid>
cc2315e7-d26a-307a-438c-6d188ec4c09c
</uuid>
<memory>
391168
</memory>
<currentMemory>
358400
</currentMemory>
<vcpu>
1
</vcpu>
<os>
<type
arch=
'i686'
machine=
'xenfv'
>
hvm
</type>
<loader>
/usr/lib/xen/boot/hvmloader
</loader>
<boot
dev=
'hd'
/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock
offset=
'utc'
/>
<on_poweroff>
destroy
</on_poweroff>
<on_reboot>
destroy
</on_reboot>
<on_crash>
destroy
</on_crash>
<devices>
<emulator>
/usr/lib/xen/bin/qemu-dm
</emulator>
<disk
type=
'block'
device=
'disk'
>
<driver
name=
'phy'
/>
<source
dev=
'/dev/sda8'
/>
<target
dev=
'hda'
bus=
'ide'
/>
</disk>
<disk
type=
'block'
device=
'cdrom'
>
<driver
name=
'phy'
/>
<target
dev=
'hdc'
bus=
'ide'
/>
<readonly/>
</disk>
<interface
type=
'bridge'
>
<mac
address=
'00:16:3e:0a:7b:39'
/>
<source
bridge=
'xenbr0'
/>
</interface>
<serial
type=
'pty'
>
<target
port=
'0'
/>
</serial>
<console
type=
'pty'
>
<target
port=
'0'
/>
</console>
<input
type=
'mouse'
bus=
'ps2'
/>
<graphics
type=
'vnc'
port=
'-1'
autoport=
'yes'
/>
<hostdev
mode=
'subsystem'
type=
'pci'
managed=
'no'
>
<source>
<address
domain=
'0x0001'
bus=
'0x0c'
slot=
'0x1b'
function=
'0x2'
/>
</source>
</hostdev>
<hostdev
mode=
'subsystem'
type=
'pci'
managed=
'no'
>
<source>
<address
domain=
'0x0000'
bus=
'0x01'
slot=
'0x13'
function=
'0x0'
/>
</source>
</hostdev>
</devices>
</domain>
tests/xmconfigtest.c
浏览文件 @
e4073623
...
...
@@ -232,6 +232,7 @@ mymain(int argc, char **argv)
DO_TEST
(
"escape-paths"
,
2
);
DO_TEST
(
"no-source-cdrom"
,
2
);
DO_TEST
(
"pci-devs"
,
2
);
virCapabilitiesFree
(
caps
);
...
...
tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr
0 → 100644
浏览文件 @
e4073623
(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w')))(device (pci (dev (domain 0x0001)(bus 0x0c)(slot 0x1b)(func 0x2))(dev (domain 0x0000)(bus 0x01)(slot 0x13)(func 0x0)))))
\ No newline at end of file
tests/xml2sexprdata/xml2sexpr-pci-devs.xml
0 → 100644
浏览文件 @
e4073623
<domain
type=
'xen'
id=
'15'
>
<name>
pvtest
</name>
<uuid>
596a5d2171f48fb2e068e2386a5c413e
</uuid>
<os>
<type>
linux
</type>
<kernel>
/var/lib/xen/vmlinuz.2Dn2YT
</kernel>
<initrd>
/var/lib/xen/initrd.img.0u-Vhq
</initrd>
<cmdline>
method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os
</cmdline>
</os>
<memory>
430080
</memory>
<vcpu>
2
</vcpu>
<on_poweroff>
destroy
</on_poweroff>
<on_reboot>
destroy
</on_reboot>
<on_crash>
destroy
</on_crash>
<devices>
<disk
type=
'block'
device=
'disk'
>
<source
dev=
'/dev/MainVG/GuestLV'
/>
<target
dev=
'xvda'
/>
</disk>
<console
tty=
'/dev/pts/4'
/>
<hostdev
mode=
'subsystem'
type=
'pci'
managed=
'no'
>
<source>
<address
domain=
'0x0001'
bus=
'0x0c'
slot=
'0x1b'
function=
'0x2'
/>
</source>
</hostdev>
<hostdev
mode=
'subsystem'
type=
'pci'
managed=
'no'
>
<source>
<address
domain=
'0x0000'
bus=
'0x01'
slot=
'0x13'
function=
'0x0'
/>
</source>
</hostdev>
</devices>
</domain>
tests/xml2sexprtest.c
浏览文件 @
e4073623
...
...
@@ -130,6 +130,7 @@ mymain(int argc, char **argv)
DO_TEST
(
"bridge-ipaddr"
,
"bridge-ipaddr"
,
"pvtest"
,
2
);
DO_TEST
(
"no-source-cdrom"
,
"no-source-cdrom"
,
"test"
,
2
);
DO_TEST
(
"pv-localtime"
,
"pv-localtime"
,
"pvtest"
,
1
);
DO_TEST
(
"pci-devs"
,
"pci-devs"
,
"pvtest"
,
2
);
DO_TEST
(
"fv-utc"
,
"fv-utc"
,
"fvtest"
,
1
);
DO_TEST
(
"fv-localtime"
,
"fv-localtime"
,
"fvtest"
,
1
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录