Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
bc01b761
Commit
bc01b761
authored
Jun 21, 2021
by
Alex Williamson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'hch-mdev-direct-v4' into v5.14/vfio/next
parents
3b62a624
681c1615
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
441 additions
and
409 deletions
+441
-409
Documentation/driver-api/vfio-mediated-device.rst
Documentation/driver-api/vfio-mediated-device.rst
+12
-23
Documentation/s390/vfio-ap.rst
Documentation/s390/vfio-ap.rst
+0
-1
arch/s390/Kconfig
arch/s390/Kconfig
+1
-1
drivers/base/base.h
drivers/base/base.h
+0
-1
drivers/base/bus.c
drivers/base/bus.c
+2
-6
drivers/base/dd.c
drivers/base/dd.c
+106
-86
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/Kconfig
+1
-1
drivers/vfio/mdev/Kconfig
drivers/vfio/mdev/Kconfig
+0
-7
drivers/vfio/mdev/Makefile
drivers/vfio/mdev/Makefile
+1
-2
drivers/vfio/mdev/mdev_core.c
drivers/vfio/mdev/mdev_core.c
+36
-10
drivers/vfio/mdev/mdev_driver.c
drivers/vfio/mdev/mdev_driver.c
+10
-0
drivers/vfio/mdev/mdev_private.h
drivers/vfio/mdev/mdev_private.h
+2
-0
drivers/vfio/mdev/vfio_mdev.c
drivers/vfio/mdev/vfio_mdev.c
+1
-23
include/linux/device.h
include/linux/device.h
+2
-0
include/linux/mdev.h
include/linux/mdev.h
+2
-0
samples/Kconfig
samples/Kconfig
+3
-3
samples/vfio-mdev/mbochs.c
samples/vfio-mdev/mbochs.c
+91
-72
samples/vfio-mdev/mdpy.c
samples/vfio-mdev/mdpy.c
+88
-71
samples/vfio-mdev/mtty.c
samples/vfio-mdev/mtty.c
+83
-102
No files found.
Documentation/driver-api/vfio-mediated-device.rst
View file @
bc01b761
...
...
@@ -93,7 +93,7 @@ interfaces:
Registration Interface for a Mediated Bus Driver
------------------------------------------------
The registration interface for a mediated
bus
driver provides the following
The registration interface for a mediated
device
driver provides the following
structure to represent a mediated device's driver::
/*
...
...
@@ -136,37 +136,26 @@ The structures in the mdev_parent_ops structure are as follows:
* dev_attr_groups: attributes of the parent device
* mdev_attr_groups: attributes of the mediated device
* supported_config: attributes to define supported configurations
* device_driver: device driver to bind for mediated device instances
The functions in the mdev_parent_ops structure are as follows:
The mdev_parent_ops also still has various functions pointers. Theses exist
for historical reasons only and shall not be used for new drivers.
* create: allocate basic resources in a driver for a mediated device
* remove: free resources in a driver when a mediated device is destroyed
(Note that mdev-core provides no implicit serialization of create/remove
callbacks per mdev parent device, per mdev type, or any other categorization.
Vendor drivers are expected to be fully asynchronous in this respect or
provide their own internal resource protection.)
The callbacks in the mdev_parent_ops structure are as follows:
* open: open callback of mediated device
* close: close callback of mediated device
* ioctl: ioctl callback of mediated device
* read : read emulation callback
* write: write emulation callback
* mmap: mmap emulation callback
A driver should use the mdev_parent_ops structure in the function call to
register itself with the mdev core driver::
When a driver wants to add the GUID creation sysfs to an existing device it has
probe'd to then it should call::
extern int mdev_register_device(struct device *dev,
const struct mdev_parent_ops *ops);
However, the mdev_parent_ops structure is not required in the function call
that a driver should use to unregister itself with the mdev core driver::
This will provide the 'mdev_supported_types/XX/create' files which can then be
used to trigger the creation of a mdev_device. The created mdev_device will be
attached to the specified driver.
When the driver needs to remove itself it calls::
extern void mdev_unregister_device(struct device *dev);
Which will unbind and destroy all the created mdevs and remove the sysfs files.
Mediated Device Management Interface Through sysfs
==================================================
...
...
Documentation/s390/vfio-ap.rst
View file @
bc01b761
...
...
@@ -514,7 +514,6 @@ These are the steps:
* S390_AP_IOMMU
* VFIO
* VFIO_MDEV
* VFIO_MDEV_DEVICE
* KVM
If using make menuconfig select the following to build the vfio_ap module::
...
...
arch/s390/Kconfig
View file @
bc01b761
...
...
@@ -768,7 +768,7 @@ config VFIO_CCW
config VFIO_AP
def_tristate n
prompt "VFIO support for AP devices"
depends on S390_AP_IOMMU && VFIO_MDEV
_DEVICE
&& KVM
depends on S390_AP_IOMMU && VFIO_MDEV && KVM
depends on ZCRYPT
help
This driver grants access to Adjunct Processor (AP) devices
...
...
drivers/base/base.h
View file @
bc01b761
...
...
@@ -152,7 +152,6 @@ extern int driver_add_groups(struct device_driver *drv,
const
struct
attribute_group
**
groups
);
extern
void
driver_remove_groups
(
struct
device_driver
*
drv
,
const
struct
attribute_group
**
groups
);
int
device_driver_attach
(
struct
device_driver
*
drv
,
struct
device
*
dev
);
void
device_driver_detach
(
struct
device
*
dev
);
extern
char
*
make_class_name
(
const
char
*
name
,
struct
kobject
*
kobj
);
...
...
drivers/base/bus.c
View file @
bc01b761
...
...
@@ -210,15 +210,11 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
int
err
=
-
ENODEV
;
dev
=
bus_find_device_by_name
(
bus
,
NULL
,
buf
);
if
(
dev
&&
d
ev
->
driver
==
NULL
&&
d
river_match_device
(
drv
,
dev
))
{
if
(
dev
&&
driver_match_device
(
drv
,
dev
))
{
err
=
device_driver_attach
(
drv
,
dev
);
if
(
err
>
0
)
{
if
(
!
err
)
{
/* success */
err
=
count
;
}
else
if
(
err
==
0
)
{
/* driver didn't accept device */
err
=
-
ENODEV
;
}
}
put_device
(
dev
);
...
...
drivers/base/dd.c
View file @
bc01b761
...
...
@@ -471,6 +471,8 @@ static void driver_sysfs_remove(struct device *dev)
* (It is ok to call with no other effort from a driver's probe() method.)
*
* This function must be called with the device lock held.
*
* Callers should prefer to use device_driver_attach() instead.
*/
int
device_bind_driver
(
struct
device
*
dev
)
{
...
...
@@ -491,15 +493,6 @@ EXPORT_SYMBOL_GPL(device_bind_driver);
static
atomic_t
probe_count
=
ATOMIC_INIT
(
0
);
static
DECLARE_WAIT_QUEUE_HEAD
(
probe_waitqueue
);
static
void
driver_deferred_probe_add_trigger
(
struct
device
*
dev
,
int
local_trigger_count
)
{
driver_deferred_probe_add
(
dev
);
/* Did a trigger occur while probing? Need to re-trigger if yes */
if
(
local_trigger_count
!=
atomic_read
(
&
deferred_trigger_count
))
driver_deferred_probe_trigger
();
}
static
ssize_t
state_synced_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
...
...
@@ -513,12 +506,43 @@ static ssize_t state_synced_show(struct device *dev,
}
static
DEVICE_ATTR_RO
(
state_synced
);
static
int
call_driver_probe
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
int
ret
=
0
;
if
(
dev
->
bus
->
probe
)
ret
=
dev
->
bus
->
probe
(
dev
);
else
if
(
drv
->
probe
)
ret
=
drv
->
probe
(
dev
);
switch
(
ret
)
{
case
0
:
break
;
case
-
EPROBE_DEFER
:
/* Driver requested deferred probing */
dev_dbg
(
dev
,
"Driver %s requests probe deferral
\n
"
,
drv
->
name
);
break
;
case
-
ENODEV
:
case
-
ENXIO
:
pr_debug
(
"%s: probe of %s rejects match %d
\n
"
,
drv
->
name
,
dev_name
(
dev
),
ret
);
break
;
default:
/* driver matched but the probe failed */
pr_warn
(
"%s: probe of %s failed with error %d
\n
"
,
drv
->
name
,
dev_name
(
dev
),
ret
);
break
;
}
return
ret
;
}
static
int
really_probe
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
int
ret
=
-
EPROBE_DEFER
;
int
local_trigger_count
=
atomic_read
(
&
deferred_trigger_count
);
bool
test_remove
=
IS_ENABLED
(
CONFIG_DEBUG_TEST_DRIVER_REMOVE
)
&&
!
drv
->
suppress_bind_attrs
;
int
ret
;
if
(
defer_all_probes
)
{
/*
...
...
@@ -527,17 +551,13 @@ static int really_probe(struct device *dev, struct device_driver *drv)
* wait_for_device_probe() right after that to avoid any races.
*/
dev_dbg
(
dev
,
"Driver %s force probe deferral
\n
"
,
drv
->
name
);
driver_deferred_probe_add
(
dev
);
return
ret
;
return
-
EPROBE_DEFER
;
}
ret
=
device_links_check_suppliers
(
dev
);
if
(
ret
==
-
EPROBE_DEFER
)
driver_deferred_probe_add_trigger
(
dev
,
local_trigger_count
);
if
(
ret
)
return
ret
;
atomic_inc
(
&
probe_count
);
pr_debug
(
"bus: '%s': %s: probing driver %s with device %s
\n
"
,
drv
->
bus
->
name
,
__func__
,
drv
->
name
,
dev_name
(
dev
));
if
(
!
list_empty
(
&
dev
->
devres_head
))
{
...
...
@@ -572,14 +592,14 @@ static int really_probe(struct device *dev, struct device_driver *drv)
goto
probe_failed
;
}
if
(
dev
->
bus
->
probe
)
{
ret
=
dev
->
bus
->
probe
(
dev
);
if
(
ret
)
goto
probe_failed
;
}
else
if
(
drv
->
probe
)
{
ret
=
drv
->
probe
(
dev
);
if
(
ret
)
goto
probe_failed
;
ret
=
call_driver_probe
(
dev
,
drv
);
if
(
ret
)
{
/*
* Return probe errors as positive values so that the callers
* can distinguish them from other errors.
*/
ret
=
-
ret
;
goto
probe_failed
;
}
if
(
device_add_groups
(
dev
,
drv
->
dev_groups
))
{
...
...
@@ -621,7 +641,6 @@ static int really_probe(struct device *dev, struct device_driver *drv)
dev
->
pm_domain
->
sync
(
dev
);
driver_bound
(
dev
);
ret
=
1
;
pr_debug
(
"bus: '%s': %s: bound device %s to driver %s
\n
"
,
drv
->
bus
->
name
,
__func__
,
dev_name
(
dev
),
drv
->
name
);
goto
done
;
...
...
@@ -650,31 +669,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
dev
->
pm_domain
->
dismiss
(
dev
);
pm_runtime_reinit
(
dev
);
dev_pm_set_driver_flags
(
dev
,
0
);
switch
(
ret
)
{
case
-
EPROBE_DEFER
:
/* Driver requested deferred probing */
dev_dbg
(
dev
,
"Driver %s requests probe deferral
\n
"
,
drv
->
name
);
driver_deferred_probe_add_trigger
(
dev
,
local_trigger_count
);
break
;
case
-
ENODEV
:
case
-
ENXIO
:
pr_debug
(
"%s: probe of %s rejects match %d
\n
"
,
drv
->
name
,
dev_name
(
dev
),
ret
);
break
;
default:
/* driver matched but the probe failed */
pr_warn
(
"%s: probe of %s failed with error %d
\n
"
,
drv
->
name
,
dev_name
(
dev
),
ret
);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret
=
0
;
done:
atomic_dec
(
&
probe_count
);
wake_up_all
(
&
probe_waitqueue
);
return
ret
;
}
...
...
@@ -728,25 +723,14 @@ void wait_for_device_probe(void)
}
EXPORT_SYMBOL_GPL
(
wait_for_device_probe
);
/**
* driver_probe_device - attempt to bind device & driver together
* @drv: driver to bind a device to
* @dev: device to try to bind to the driver
*
* This function returns -ENODEV if the device is not registered,
* 1 if the device is bound successfully and 0 otherwise.
*
* This function must be called with @dev lock held. When called for a
* USB interface, @dev->parent lock must be held as well.
*
* If the device has a parent, runtime-resume the parent before driver probing.
*/
static
int
driver_probe_device
(
struct
device_driver
*
drv
,
struct
device
*
dev
)
static
int
__driver_probe_device
(
struct
device_driver
*
drv
,
struct
device
*
dev
)
{
int
ret
=
0
;
if
(
!
device_is_registered
(
dev
))
if
(
dev
->
p
->
dead
||
!
device_is_registered
(
dev
))
return
-
ENODEV
;
if
(
dev
->
driver
)
return
-
EBUSY
;
dev
->
can_match
=
true
;
pr_debug
(
"bus: '%s': %s: matched device %s with driver %s
\n
"
,
...
...
@@ -770,6 +754,42 @@ static int driver_probe_device(struct device_driver *drv, struct device *dev)
return
ret
;
}
/**
* driver_probe_device - attempt to bind device & driver together
* @drv: driver to bind a device to
* @dev: device to try to bind to the driver
*
* This function returns -ENODEV if the device is not registered, -EBUSY if it
* already has a driver, 0 if the device is bound successfully and a positive
* (inverted) error code for failures from the ->probe method.
*
* This function must be called with @dev lock held. When called for a
* USB interface, @dev->parent lock must be held as well.
*
* If the device has a parent, runtime-resume the parent before driver probing.
*/
static
int
driver_probe_device
(
struct
device_driver
*
drv
,
struct
device
*
dev
)
{
int
trigger_count
=
atomic_read
(
&
deferred_trigger_count
);
int
ret
;
atomic_inc
(
&
probe_count
);
ret
=
__driver_probe_device
(
drv
,
dev
);
if
(
ret
==
-
EPROBE_DEFER
||
ret
==
EPROBE_DEFER
)
{
driver_deferred_probe_add
(
dev
);
/*
* Did a trigger occur while probing? Need to re-trigger if yes
*/
if
(
trigger_count
!=
atomic_read
(
&
deferred_trigger_count
)
&&
!
defer_all_probes
)
driver_deferred_probe_trigger
();
}
atomic_dec
(
&
probe_count
);
wake_up_all
(
&
probe_waitqueue
);
return
ret
;
}
static
inline
bool
cmdline_requested_async_probing
(
const
char
*
drv_name
)
{
return
parse_option_str
(
async_probe_drv_names
,
drv_name
);
...
...
@@ -867,7 +887,14 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
if
(
data
->
check_async
&&
async_allowed
!=
data
->
want_async
)
return
0
;
return
driver_probe_device
(
drv
,
dev
);
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret
=
driver_probe_device
(
drv
,
dev
);
if
(
ret
<
0
)
return
ret
;
return
ret
==
0
;
}
static
void
__device_attach_async_helper
(
void
*
_dev
,
async_cookie_t
cookie
)
...
...
@@ -1023,43 +1050,34 @@ static void __device_driver_unlock(struct device *dev, struct device *parent)
* @dev: Device to attach it to
*
* Manually attach driver to a device. Will acquire both @dev lock and
* @dev->parent lock if needed.
* @dev->parent lock if needed.
Returns 0 on success, -ERR on failure.
*/
int
device_driver_attach
(
struct
device_driver
*
drv
,
struct
device
*
dev
)
{
int
ret
=
0
;
int
ret
;
__device_driver_lock
(
dev
,
dev
->
parent
);
/*
* If device has been removed or someone has already successfully
* bound a driver before us just skip the driver probe call.
*/
if
(
!
dev
->
p
->
dead
&&
!
dev
->
driver
)
ret
=
driver_probe_device
(
drv
,
dev
);
ret
=
__driver_probe_device
(
drv
,
dev
);
__device_driver_unlock
(
dev
,
dev
->
parent
);
/* also return probe errors as normal negative errnos */
if
(
ret
>
0
)
ret
=
-
ret
;
if
(
ret
==
-
EPROBE_DEFER
)
return
-
EAGAIN
;
return
ret
;
}
EXPORT_SYMBOL_GPL
(
device_driver_attach
);
static
void
__driver_attach_async_helper
(
void
*
_dev
,
async_cookie_t
cookie
)
{
struct
device
*
dev
=
_dev
;
struct
device_driver
*
drv
;
int
ret
=
0
;
int
ret
;
__device_driver_lock
(
dev
,
dev
->
parent
);
drv
=
dev
->
p
->
async_driver
;
/*
* If device has been removed or someone has already successfully
* bound a driver before us just skip the driver probe call.
*/
if
(
!
dev
->
p
->
dead
&&
!
dev
->
driver
)
ret
=
driver_probe_device
(
drv
,
dev
);
ret
=
driver_probe_device
(
drv
,
dev
);
__device_driver_unlock
(
dev
,
dev
->
parent
);
dev_dbg
(
dev
,
"driver %s async attach completed: %d
\n
"
,
drv
->
name
,
ret
);
...
...
@@ -1114,7 +1132,9 @@ static int __driver_attach(struct device *dev, void *data)
return
0
;
}
device_driver_attach
(
drv
,
dev
);
__device_driver_lock
(
dev
,
dev
->
parent
);
driver_probe_device
(
drv
,
dev
);
__device_driver_unlock
(
dev
,
dev
->
parent
);
return
0
;
}
...
...
drivers/gpu/drm/i915/Kconfig
View file @
bc01b761
...
...
@@ -124,7 +124,7 @@ config DRM_I915_GVT_KVMGT
tristate "Enable KVM/VFIO support for Intel GVT-g"
depends on DRM_I915_GVT
depends on KVM
depends on VFIO_MDEV
&& VFIO_MDEV_DEVICE
depends on VFIO_MDEV
default n
help
Choose this option if you want to enable KVMGT support for
...
...
drivers/vfio/mdev/Kconfig
View file @
bc01b761
...
...
@@ -9,10 +9,3 @@ config VFIO_MDEV
See Documentation/driver-api/vfio-mediated-device.rst for more details.
If you don't know what do here, say N.
config VFIO_MDEV_DEVICE
tristate "VFIO driver for Mediated devices"
depends on VFIO && VFIO_MDEV
default n
help
VFIO based driver for Mediated devices.
drivers/vfio/mdev/Makefile
View file @
bc01b761
# SPDX-License-Identifier: GPL-2.0-only
mdev-y
:=
mdev_core.o mdev_sysfs.o mdev_driver.o
mdev-y
:=
mdev_core.o mdev_sysfs.o mdev_driver.o
vfio_mdev.o
obj-$(CONFIG_VFIO_MDEV)
+=
mdev.o
obj-$(CONFIG_VFIO_MDEV_DEVICE)
+=
vfio_mdev.o
drivers/vfio/mdev/mdev_core.c
View file @
bc01b761
...
...
@@ -94,9 +94,11 @@ static void mdev_device_remove_common(struct mdev_device *mdev)
mdev_remove_sysfs_files
(
mdev
);
device_del
(
&
mdev
->
dev
);
lockdep_assert_held
(
&
parent
->
unreg_sem
);
ret
=
parent
->
ops
->
remove
(
mdev
);
if
(
ret
)
dev_err
(
&
mdev
->
dev
,
"Remove failed: err=%d
\n
"
,
ret
);
if
(
parent
->
ops
->
remove
)
{
ret
=
parent
->
ops
->
remove
(
mdev
);
if
(
ret
)
dev_err
(
&
mdev
->
dev
,
"Remove failed: err=%d
\n
"
,
ret
);
}
/* Balances with device_initialize() */
put_device
(
&
mdev
->
dev
);
...
...
@@ -127,7 +129,9 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
char
*
envp
[]
=
{
env_string
,
NULL
};
/* check for mandatory ops */
if
(
!
ops
||
!
ops
->
create
||
!
ops
->
remove
||
!
ops
->
supported_type_groups
)
if
(
!
ops
||
!
ops
->
supported_type_groups
)
return
-
EINVAL
;
if
(
!
ops
->
device_driver
&&
(
!
ops
->
create
||
!
ops
->
remove
))
return
-
EINVAL
;
dev
=
get_device
(
dev
);
...
...
@@ -256,6 +260,7 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid)
int
ret
;
struct
mdev_device
*
mdev
,
*
tmp
;
struct
mdev_parent
*
parent
=
type
->
parent
;
struct
mdev_driver
*
drv
=
parent
->
ops
->
device_driver
;
mutex_lock
(
&
mdev_list_lock
);
...
...
@@ -296,14 +301,22 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid)
goto
out_put_device
;
}
ret
=
parent
->
ops
->
create
(
mdev
);
if
(
ret
)
goto
out_unlock
;
if
(
parent
->
ops
->
create
)
{
ret
=
parent
->
ops
->
create
(
mdev
);
if
(
ret
)
goto
out_unlock
;
}
ret
=
device_add
(
&
mdev
->
dev
);
if
(
ret
)
goto
out_remove
;
if
(
!
drv
)
drv
=
&
vfio_mdev_driver
;
ret
=
device_driver_attach
(
&
drv
->
driver
,
&
mdev
->
dev
);
if
(
ret
)
goto
out_del
;
ret
=
mdev_create_sysfs_files
(
mdev
);
if
(
ret
)
goto
out_del
;
...
...
@@ -317,7 +330,8 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid)
out_del:
device_del
(
&
mdev
->
dev
);
out_remove:
parent
->
ops
->
remove
(
mdev
);
if
(
parent
->
ops
->
remove
)
parent
->
ops
->
remove
(
mdev
);
out_unlock:
up_read
(
&
parent
->
unreg_sem
);
out_put_device:
...
...
@@ -360,11 +374,24 @@ int mdev_device_remove(struct mdev_device *mdev)
static
int
__init
mdev_init
(
void
)
{
return
mdev_bus_register
();
int
rc
;
rc
=
mdev_bus_register
();
if
(
rc
)
return
rc
;
rc
=
mdev_register_driver
(
&
vfio_mdev_driver
);
if
(
rc
)
goto
err_bus
;
return
0
;
err_bus:
mdev_bus_unregister
();
return
rc
;
}
static
void
__exit
mdev_exit
(
void
)
{
mdev_unregister_driver
(
&
vfio_mdev_driver
);
if
(
mdev_bus_compat_class
)
class_compat_unregister
(
mdev_bus_compat_class
);
...
...
@@ -378,4 +405,3 @@ MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_SOFTDEP
(
"post: vfio_mdev"
);
drivers/vfio/mdev/mdev_driver.c
View file @
bc01b761
...
...
@@ -71,10 +71,20 @@ static int mdev_remove(struct device *dev)
return
0
;
}
static
int
mdev_match
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
/*
* No drivers automatically match. Drivers are only bound by explicit
* device_driver_attach()
*/
return
0
;
}
struct
bus_type
mdev_bus_type
=
{
.
name
=
"mdev"
,
.
probe
=
mdev_probe
,
.
remove
=
mdev_remove
,
.
match
=
mdev_match
,
};
EXPORT_SYMBOL_GPL
(
mdev_bus_type
);
...
...
drivers/vfio/mdev/mdev_private.h
View file @
bc01b761
...
...
@@ -37,6 +37,8 @@ struct mdev_type {
#define to_mdev_type(_kobj) \
container_of(_kobj, struct mdev_type, kobj)
extern
struct
mdev_driver
vfio_mdev_driver
;
int
parent_create_sysfs_files
(
struct
mdev_parent
*
parent
);
void
parent_remove_sysfs_files
(
struct
mdev_parent
*
parent
);
...
...
drivers/vfio/mdev/vfio_mdev.c
View file @
bc01b761
...
...
@@ -17,10 +17,6 @@
#include "mdev_private.h"
#define DRIVER_VERSION "0.1"
#define DRIVER_AUTHOR "NVIDIA Corporation"
#define DRIVER_DESC "VFIO based driver for Mediated device"
static
int
vfio_mdev_open
(
struct
vfio_device
*
core_vdev
)
{
struct
mdev_device
*
mdev
=
to_mdev_device
(
core_vdev
->
dev
);
...
...
@@ -140,7 +136,7 @@ static void vfio_mdev_remove(struct mdev_device *mdev)
kfree
(
vdev
);
}
st
atic
st
ruct
mdev_driver
vfio_mdev_driver
=
{
struct
mdev_driver
vfio_mdev_driver
=
{
.
driver
=
{
.
name
=
"vfio_mdev"
,
.
owner
=
THIS_MODULE
,
...
...
@@ -149,21 +145,3 @@ static struct mdev_driver vfio_mdev_driver = {
.
probe
=
vfio_mdev_probe
,
.
remove
=
vfio_mdev_remove
,
};
static
int
__init
vfio_mdev_init
(
void
)
{
return
mdev_register_driver
(
&
vfio_mdev_driver
);
}
static
void
__exit
vfio_mdev_exit
(
void
)
{
mdev_unregister_driver
(
&
vfio_mdev_driver
);
}
module_init
(
vfio_mdev_init
)
module_exit
(
vfio_mdev_exit
)
MODULE_VERSION
(
DRIVER_VERSION
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
include/linux/device.h
View file @
bc01b761
...
...
@@ -845,6 +845,8 @@ static inline void *dev_get_platdata(const struct device *dev)
* Manual binding of a device to driver. See drivers/base/bus.c
* for information on use.
*/
int
__must_check
device_driver_attach
(
struct
device_driver
*
drv
,
struct
device
*
dev
);
int
__must_check
device_bind_driver
(
struct
device
*
dev
);
void
device_release_driver
(
struct
device
*
dev
);
int
__must_check
device_attach
(
struct
device
*
dev
);
...
...
include/linux/mdev.h
View file @
bc01b761
...
...
@@ -55,6 +55,7 @@ struct device *mtype_get_parent_dev(struct mdev_type *mtype);
* register the device to mdev module.
*
* @owner: The module owner.
* @device_driver: Which device driver to probe() on newly created devices
* @dev_attr_groups: Attributes of the parent device.
* @mdev_attr_groups: Attributes of the mediated device.
* @supported_type_groups: Attributes to define supported types. It is mandatory
...
...
@@ -103,6 +104,7 @@ struct device *mtype_get_parent_dev(struct mdev_type *mtype);
**/
struct
mdev_parent_ops
{
struct
module
*
owner
;
struct
mdev_driver
*
device_driver
;
const
struct
attribute_group
**
dev_attr_groups
;
const
struct
attribute_group
**
mdev_attr_groups
;
struct
attribute_group
**
supported_type_groups
;
...
...
samples/Kconfig
View file @
bc01b761
...
...
@@ -154,14 +154,14 @@ config SAMPLE_UHID
config SAMPLE_VFIO_MDEV_MTTY
tristate "Build VFIO mtty example mediated device sample code -- loadable modules only"
depends on VFIO_MDEV
_DEVICE
&& m
depends on VFIO_MDEV && m
help
Build a virtual tty sample driver for use as a VFIO
mediated device
config SAMPLE_VFIO_MDEV_MDPY
tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
depends on VFIO_MDEV
_DEVICE
&& m
depends on VFIO_MDEV && m
help
Build a virtual display sample driver for use as a VFIO
mediated device. It is a simple framebuffer and supports
...
...
@@ -178,7 +178,7 @@ config SAMPLE_VFIO_MDEV_MDPY_FB
config SAMPLE_VFIO_MDEV_MBOCHS
tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
depends on VFIO_MDEV
_DEVICE
&& m
depends on VFIO_MDEV && m
select DMA_SHARED_BUFFER
help
Build a virtual display sample driver for use as a VFIO
...
...
samples/vfio-mdev/mbochs.c
View file @
bc01b761
...
...
@@ -130,6 +130,7 @@ static struct class *mbochs_class;
static
struct
cdev
mbochs_cdev
;
static
struct
device
mbochs_dev
;
static
int
mbochs_used_mbytes
;
static
const
struct
vfio_device_ops
mbochs_dev_ops
;
struct
vfio_region_info_ext
{
struct
vfio_region_info
base
;
...
...
@@ -160,6 +161,7 @@ struct mbochs_dmabuf {
/* State of each mdev device */
struct
mdev_state
{
struct
vfio_device
vdev
;
u8
*
vconfig
;
u64
bar_mask
[
3
];
u32
memory_bar_mask
;
...
...
@@ -425,11 +427,9 @@ static void handle_edid_blob(struct mdev_state *mdev_state, u16 offset,
memcpy
(
buf
,
mdev_state
->
edid_blob
+
offset
,
count
);
}
static
ssize_t
mdev_access
(
struct
mdev_
device
*
mdev
,
char
*
buf
,
size_t
count
,
loff_t
pos
,
bool
is_write
)
static
ssize_t
mdev_access
(
struct
mdev_
state
*
mdev_state
,
char
*
buf
,
size_t
count
,
loff_t
pos
,
bool
is_write
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
device
*
dev
=
mdev_dev
(
mdev
);
struct
page
*
pg
;
loff_t
poff
;
char
*
map
;
...
...
@@ -478,7 +478,7 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
put_page
(
pg
);
}
else
{
dev_dbg
(
dev
,
"%s: %s @0x%llx (unhandled)
\n
"
,
dev_dbg
(
mdev_state
->
vdev
.
dev
,
"%s: %s @0x%llx (unhandled)
\n
"
,
__func__
,
is_write
?
"WR"
:
"RD"
,
pos
);
ret
=
-
1
;
goto
accessfailed
;
...
...
@@ -493,9 +493,8 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
return
ret
;
}
static
int
mbochs_reset
(
struct
mdev_
device
*
mdev
)
static
int
mbochs_reset
(
struct
mdev_
state
*
mdev_state
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
u32
size64k
=
mdev_state
->
memsize
/
(
64
*
1024
);
int
i
;
...
...
@@ -506,12 +505,13 @@ static int mbochs_reset(struct mdev_device *mdev)
return
0
;
}
static
int
mbochs_
creat
e
(
struct
mdev_device
*
mdev
)
static
int
mbochs_
prob
e
(
struct
mdev_device
*
mdev
)
{
const
struct
mbochs_type
*
type
=
&
mbochs_types
[
mdev_get_type_group_id
(
mdev
)];
struct
device
*
dev
=
mdev_dev
(
mdev
);
struct
mdev_state
*
mdev_state
;
int
ret
=
-
ENOMEM
;
if
(
type
->
mbytes
+
mbochs_used_mbytes
>
max_mbytes
)
return
-
ENOMEM
;
...
...
@@ -519,6 +519,7 @@ static int mbochs_create(struct mdev_device *mdev)
mdev_state
=
kzalloc
(
sizeof
(
struct
mdev_state
),
GFP_KERNEL
);
if
(
mdev_state
==
NULL
)
return
-
ENOMEM
;
vfio_init_group_dev
(
&
mdev_state
->
vdev
,
&
mdev
->
dev
,
&
mbochs_dev_ops
);
mdev_state
->
vconfig
=
kzalloc
(
MBOCHS_CONFIG_SPACE_SIZE
,
GFP_KERNEL
);
if
(
mdev_state
->
vconfig
==
NULL
)
...
...
@@ -537,7 +538,6 @@ static int mbochs_create(struct mdev_device *mdev)
mutex_init
(
&
mdev_state
->
ops_lock
);
mdev_state
->
mdev
=
mdev
;
mdev_set_drvdata
(
mdev
,
mdev_state
);
INIT_LIST_HEAD
(
&
mdev_state
->
dmabufs
);
mdev_state
->
next_id
=
1
;
...
...
@@ -547,32 +547,38 @@ static int mbochs_create(struct mdev_device *mdev)
mdev_state
->
edid_regs
.
edid_offset
=
MBOCHS_EDID_BLOB_OFFSET
;
mdev_state
->
edid_regs
.
edid_max_size
=
sizeof
(
mdev_state
->
edid_blob
);
mbochs_create_config_space
(
mdev_state
);
mbochs_reset
(
mdev
);
mbochs_reset
(
mdev
_state
);
mbochs_used_mbytes
+=
type
->
mbytes
;
ret
=
vfio_register_group_dev
(
&
mdev_state
->
vdev
);
if
(
ret
)
goto
err_mem
;
dev_set_drvdata
(
&
mdev
->
dev
,
mdev_state
);
return
0
;
err_mem:
kfree
(
mdev_state
->
vconfig
);
kfree
(
mdev_state
);
return
-
ENOMEM
;
return
ret
;
}
static
int
mbochs_remove
(
struct
mdev_device
*
mdev
)
static
void
mbochs_remove
(
struct
mdev_device
*
mdev
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
m
dev
);
struct
mdev_state
*
mdev_state
=
dev_get_drvdata
(
&
mdev
->
dev
);
mbochs_used_mbytes
-=
mdev_state
->
type
->
mbytes
;
mdev_set_drvdata
(
mdev
,
NULL
);
vfio_unregister_group_dev
(
&
mdev_state
->
vdev
);
kfree
(
mdev_state
->
pages
);
kfree
(
mdev_state
->
vconfig
);
kfree
(
mdev_state
);
return
0
;
}
static
ssize_t
mbochs_read
(
struct
mdev_device
*
m
dev
,
char
__user
*
buf
,
static
ssize_t
mbochs_read
(
struct
vfio_device
*
v
dev
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
unsigned
int
done
=
0
;
int
ret
;
...
...
@@ -582,7 +588,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
if
(
count
>=
4
&&
!
(
*
ppos
%
4
))
{
u32
val
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -594,7 +600,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
}
else
if
(
count
>=
2
&&
!
(
*
ppos
%
2
))
{
u16
val
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -606,7 +612,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
}
else
{
u8
val
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -629,9 +635,11 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
return
-
EFAULT
;
}
static
ssize_t
mbochs_write
(
struct
mdev_device
*
m
dev
,
const
char
__user
*
buf
,
static
ssize_t
mbochs_write
(
struct
vfio_device
*
v
dev
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
unsigned
int
done
=
0
;
int
ret
;
...
...
@@ -644,7 +652,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -656,7 +664,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -668,7 +676,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -754,9 +762,10 @@ static const struct vm_operations_struct mbochs_region_vm_ops = {
.
fault
=
mbochs_region_vm_fault
,
};
static
int
mbochs_mmap
(
struct
mdev_device
*
m
dev
,
struct
vm_area_struct
*
vma
)
static
int
mbochs_mmap
(
struct
vfio_device
*
v
dev
,
struct
vm_area_struct
*
vma
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
if
(
vma
->
vm_pgoff
!=
MBOCHS_MEMORY_BAR_OFFSET
>>
PAGE_SHIFT
)
return
-
EINVAL
;
...
...
@@ -963,7 +972,7 @@ mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
static
int
mbochs_dmabuf_export
(
struct
mbochs_dmabuf
*
dmabuf
)
{
struct
mdev_state
*
mdev_state
=
dmabuf
->
mdev_state
;
struct
device
*
dev
=
mdev_
dev
(
mdev_state
->
mdev
)
;
struct
device
*
dev
=
mdev_
state
->
vdev
.
dev
;
DEFINE_DMA_BUF_EXPORT_INFO
(
exp_info
);
struct
dma_buf
*
buf
;
...
...
@@ -991,15 +1000,10 @@ static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
return
0
;
}
static
int
mbochs_get_region_info
(
struct
mdev_
device
*
mdev
,
static
int
mbochs_get_region_info
(
struct
mdev_
state
*
mdev_state
,
struct
vfio_region_info_ext
*
ext
)
{
struct
vfio_region_info
*
region_info
=
&
ext
->
base
;
struct
mdev_state
*
mdev_state
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
!
mdev_state
)
return
-
EINVAL
;
if
(
region_info
->
index
>=
MBOCHS_NUM_REGIONS
)
return
-
EINVAL
;
...
...
@@ -1047,15 +1051,13 @@ static int mbochs_get_region_info(struct mdev_device *mdev,
return
0
;
}
static
int
mbochs_get_irq_info
(
struct
mdev_device
*
mdev
,
struct
vfio_irq_info
*
irq_info
)
static
int
mbochs_get_irq_info
(
struct
vfio_irq_info
*
irq_info
)
{
irq_info
->
count
=
0
;
return
0
;
}
static
int
mbochs_get_device_info
(
struct
mdev_device
*
mdev
,
struct
vfio_device_info
*
dev_info
)
static
int
mbochs_get_device_info
(
struct
vfio_device_info
*
dev_info
)
{
dev_info
->
flags
=
VFIO_DEVICE_FLAGS_PCI
;
dev_info
->
num_regions
=
MBOCHS_NUM_REGIONS
;
...
...
@@ -1063,11 +1065,9 @@ static int mbochs_get_device_info(struct mdev_device *mdev,
return
0
;
}
static
int
mbochs_query_gfx_plane
(
struct
mdev_
device
*
mdev
,
static
int
mbochs_query_gfx_plane
(
struct
mdev_
state
*
mdev_state
,
struct
vfio_device_gfx_plane_info
*
plane
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
device
*
dev
=
mdev_dev
(
mdev
);
struct
mbochs_dmabuf
*
dmabuf
;
struct
mbochs_mode
mode
;
int
ret
;
...
...
@@ -1121,18 +1121,16 @@ static int mbochs_query_gfx_plane(struct mdev_device *mdev,
done:
if
(
plane
->
drm_plane_type
==
DRM_PLANE_TYPE_PRIMARY
&&
mdev_state
->
active_id
!=
plane
->
dmabuf_id
)
{
dev_dbg
(
dev
,
"%s: primary: %d => %d
\n
"
,
__func__
,
mdev_state
->
active_id
,
plane
->
dmabuf_id
);
dev_dbg
(
mdev_state
->
vdev
.
dev
,
"%s: primary: %d => %d
\n
"
,
__func__
,
mdev_state
->
active_id
,
plane
->
dmabuf_id
);
mdev_state
->
active_id
=
plane
->
dmabuf_id
;
}
mutex_unlock
(
&
mdev_state
->
ops_lock
);
return
0
;
}
static
int
mbochs_get_gfx_dmabuf
(
struct
mdev_device
*
mdev
,
u32
id
)
static
int
mbochs_get_gfx_dmabuf
(
struct
mdev_state
*
mdev_state
,
u32
id
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
mbochs_dmabuf
*
dmabuf
;
mutex_lock
(
&
mdev_state
->
ops_lock
);
...
...
@@ -1154,9 +1152,11 @@ static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
return
dma_buf_fd
(
dmabuf
->
buf
,
0
);
}
static
long
mbochs_ioctl
(
struct
mdev_device
*
m
dev
,
unsigned
int
cmd
,
unsigned
long
arg
)
static
long
mbochs_ioctl
(
struct
vfio_device
*
v
dev
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
int
ret
=
0
;
unsigned
long
minsz
,
outsz
;
...
...
@@ -1173,7 +1173,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
info
.
argsz
<
minsz
)
return
-
EINVAL
;
ret
=
mbochs_get_device_info
(
mdev
,
&
info
);
ret
=
mbochs_get_device_info
(
&
info
);
if
(
ret
)
return
ret
;
...
...
@@ -1197,7 +1197,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
outsz
>
sizeof
(
info
))
return
-
EINVAL
;
ret
=
mbochs_get_region_info
(
mdev
,
&
info
);
ret
=
mbochs_get_region_info
(
mdev
_state
,
&
info
);
if
(
ret
)
return
ret
;
...
...
@@ -1220,7 +1220,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
(
info
.
index
>=
VFIO_PCI_NUM_IRQS
))
return
-
EINVAL
;
ret
=
mbochs_get_irq_info
(
mdev
,
&
info
);
ret
=
mbochs_get_irq_info
(
&
info
);
if
(
ret
)
return
ret
;
...
...
@@ -1243,7 +1243,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
plane
.
argsz
<
minsz
)
return
-
EINVAL
;
ret
=
mbochs_query_gfx_plane
(
mdev
,
&
plane
);
ret
=
mbochs_query_gfx_plane
(
mdev
_state
,
&
plane
);
if
(
ret
)
return
ret
;
...
...
@@ -1260,19 +1260,19 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
get_user
(
dmabuf_id
,
(
__u32
__user
*
)
arg
))
return
-
EFAULT
;
return
mbochs_get_gfx_dmabuf
(
mdev
,
dmabuf_id
);
return
mbochs_get_gfx_dmabuf
(
mdev
_state
,
dmabuf_id
);
}
case
VFIO_DEVICE_SET_IRQS
:
return
-
EINVAL
;
case
VFIO_DEVICE_RESET
:
return
mbochs_reset
(
mdev
);
return
mbochs_reset
(
mdev
_state
);
}
return
-
ENOTTY
;
}
static
int
mbochs_open
(
struct
mdev_device
*
m
dev
)
static
int
mbochs_open
(
struct
vfio_device
*
v
dev
)
{
if
(
!
try_module_get
(
THIS_MODULE
))
return
-
ENODEV
;
...
...
@@ -1280,9 +1280,10 @@ static int mbochs_open(struct mdev_device *mdev)
return
0
;
}
static
void
mbochs_close
(
struct
mdev_device
*
m
dev
)
static
void
mbochs_close
(
struct
vfio_device
*
v
dev
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
struct
mbochs_dmabuf
*
dmabuf
,
*
tmp
;
mutex_lock
(
&
mdev_state
->
ops_lock
);
...
...
@@ -1306,8 +1307,7 @@ static ssize_t
memory_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
mdev_device
*
mdev
=
mdev_from_dev
(
dev
);
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
mdev_state
*
mdev_state
=
dev_get_drvdata
(
dev
);
return
sprintf
(
buf
,
"%d MB
\n
"
,
mdev_state
->
type
->
mbytes
);
}
...
...
@@ -1398,18 +1398,30 @@ static struct attribute_group *mdev_type_groups[] = {
NULL
,
};
static
const
struct
vfio_device_ops
mbochs_dev_ops
=
{
.
open
=
mbochs_open
,
.
release
=
mbochs_close
,
.
read
=
mbochs_read
,
.
write
=
mbochs_write
,
.
ioctl
=
mbochs_ioctl
,
.
mmap
=
mbochs_mmap
,
};
static
struct
mdev_driver
mbochs_driver
=
{
.
driver
=
{
.
name
=
"mbochs"
,
.
owner
=
THIS_MODULE
,
.
mod_name
=
KBUILD_MODNAME
,
.
dev_groups
=
mdev_dev_groups
,
},
.
probe
=
mbochs_probe
,
.
remove
=
mbochs_remove
,
};
static
const
struct
mdev_parent_ops
mdev_fops
=
{
.
owner
=
THIS_MODULE
,
.
mdev_attr_groups
=
mdev_dev_groups
,
.
device_driver
=
&
mbochs_driver
,
.
supported_type_groups
=
mdev_type_groups
,
.
create
=
mbochs_create
,
.
remove
=
mbochs_remove
,
.
open
=
mbochs_open
,
.
release
=
mbochs_close
,
.
read
=
mbochs_read
,
.
write
=
mbochs_write
,
.
ioctl
=
mbochs_ioctl
,
.
mmap
=
mbochs_mmap
,
};
static
const
struct
file_operations
vd_fops
=
{
...
...
@@ -1434,11 +1446,15 @@ static int __init mbochs_dev_init(void)
cdev_add
(
&
mbochs_cdev
,
mbochs_devt
,
MINORMASK
+
1
);
pr_info
(
"%s: major %d
\n
"
,
__func__
,
MAJOR
(
mbochs_devt
));
ret
=
mdev_register_driver
(
&
mbochs_driver
);
if
(
ret
)
goto
err_cdev
;
mbochs_class
=
class_create
(
THIS_MODULE
,
MBOCHS_CLASS_NAME
);
if
(
IS_ERR
(
mbochs_class
))
{
pr_err
(
"Error: failed to register mbochs_dev class
\n
"
);
ret
=
PTR_ERR
(
mbochs_class
);
goto
failed1
;
goto
err_driver
;
}
mbochs_dev
.
class
=
mbochs_class
;
mbochs_dev
.
release
=
mbochs_device_release
;
...
...
@@ -1446,19 +1462,21 @@ static int __init mbochs_dev_init(void)
ret
=
device_register
(
&
mbochs_dev
);
if
(
ret
)
goto
failed2
;
goto
err_class
;
ret
=
mdev_register_device
(
&
mbochs_dev
,
&
mdev_fops
);
if
(
ret
)
goto
failed3
;
goto
err_device
;
return
0
;
failed3
:
err_device
:
device_unregister
(
&
mbochs_dev
);
failed2
:
err_class
:
class_destroy
(
mbochs_class
);
failed1:
err_driver:
mdev_unregister_driver
(
&
mbochs_driver
);
err_cdev:
cdev_del
(
&
mbochs_cdev
);
unregister_chrdev_region
(
mbochs_devt
,
MINORMASK
+
1
);
return
ret
;
...
...
@@ -1470,6 +1488,7 @@ static void __exit mbochs_dev_exit(void)
mdev_unregister_device
(
&
mbochs_dev
);
device_unregister
(
&
mbochs_dev
);
mdev_unregister_driver
(
&
mbochs_driver
);
cdev_del
(
&
mbochs_cdev
);
unregister_chrdev_region
(
mbochs_devt
,
MINORMASK
+
1
);
class_destroy
(
mbochs_class
);
...
...
samples/vfio-mdev/mdpy.c
View file @
bc01b761
...
...
@@ -85,9 +85,11 @@ static struct class *mdpy_class;
static
struct
cdev
mdpy_cdev
;
static
struct
device
mdpy_dev
;
static
u32
mdpy_count
;
static
const
struct
vfio_device_ops
mdpy_dev_ops
;
/* State of each mdev device */
struct
mdev_state
{
struct
vfio_device
vdev
;
u8
*
vconfig
;
u32
bar_mask
;
struct
mutex
ops_lock
;
...
...
@@ -162,11 +164,9 @@ static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
}
}
static
ssize_t
mdev_access
(
struct
mdev_
device
*
mdev
,
char
*
buf
,
size_t
count
,
loff_t
pos
,
bool
is_write
)
static
ssize_t
mdev_access
(
struct
mdev_
state
*
mdev_state
,
char
*
buf
,
size_t
count
,
loff_t
pos
,
bool
is_write
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
device
*
dev
=
mdev_dev
(
mdev
);
int
ret
=
0
;
mutex_lock
(
&
mdev_state
->
ops_lock
);
...
...
@@ -187,8 +187,9 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
memcpy
(
buf
,
mdev_state
->
memblk
,
count
);
}
else
{
dev_info
(
dev
,
"%s: %s @0x%llx (unhandled)
\n
"
,
__func__
,
is_write
?
"WR"
:
"RD"
,
pos
);
dev_info
(
mdev_state
->
vdev
.
dev
,
"%s: %s @0x%llx (unhandled)
\n
"
,
__func__
,
is_write
?
"WR"
:
"RD"
,
pos
);
ret
=
-
1
;
goto
accessfailed
;
}
...
...
@@ -202,9 +203,8 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
return
ret
;
}
static
int
mdpy_reset
(
struct
mdev_
device
*
mdev
)
static
int
mdpy_reset
(
struct
mdev_
state
*
mdev_state
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
u32
stride
,
i
;
/* initialize with gray gradient */
...
...
@@ -216,13 +216,14 @@ static int mdpy_reset(struct mdev_device *mdev)
return
0
;
}
static
int
mdpy_
creat
e
(
struct
mdev_device
*
mdev
)
static
int
mdpy_
prob
e
(
struct
mdev_device
*
mdev
)
{
const
struct
mdpy_type
*
type
=
&
mdpy_types
[
mdev_get_type_group_id
(
mdev
)];
struct
device
*
dev
=
mdev_dev
(
mdev
);
struct
mdev_state
*
mdev_state
;
u32
fbsize
;
int
ret
;
if
(
mdpy_count
>=
max_devices
)
return
-
ENOMEM
;
...
...
@@ -230,6 +231,7 @@ static int mdpy_create(struct mdev_device *mdev)
mdev_state
=
kzalloc
(
sizeof
(
struct
mdev_state
),
GFP_KERNEL
);
if
(
mdev_state
==
NULL
)
return
-
ENOMEM
;
vfio_init_group_dev
(
&
mdev_state
->
vdev
,
&
mdev
->
dev
,
&
mdpy_dev_ops
);
mdev_state
->
vconfig
=
kzalloc
(
MDPY_CONFIG_SPACE_SIZE
,
GFP_KERNEL
);
if
(
mdev_state
->
vconfig
==
NULL
)
{
...
...
@@ -250,36 +252,41 @@ static int mdpy_create(struct mdev_device *mdev)
mutex_init
(
&
mdev_state
->
ops_lock
);
mdev_state
->
mdev
=
mdev
;
mdev_set_drvdata
(
mdev
,
mdev_state
);
mdev_state
->
type
=
type
;
mdev_state
->
memsize
=
fbsize
;
mdpy_create_config_space
(
mdev_state
);
mdpy_reset
(
mdev
);
mdpy_reset
(
mdev
_state
);
mdpy_count
++
;
ret
=
vfio_register_group_dev
(
&
mdev_state
->
vdev
);
if
(
ret
)
{
kfree
(
mdev_state
);
return
ret
;
}
dev_set_drvdata
(
&
mdev
->
dev
,
mdev_state
);
return
0
;
}
static
int
mdpy_remove
(
struct
mdev_device
*
mdev
)
static
void
mdpy_remove
(
struct
mdev_device
*
mdev
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
device
*
dev
=
mdev_dev
(
mdev
);
struct
mdev_state
*
mdev_state
=
dev_get_drvdata
(
&
mdev
->
dev
);
dev_info
(
dev
,
"%s
\n
"
,
__func__
);
dev_info
(
&
mdev
->
dev
,
"%s
\n
"
,
__func__
);
mdev_set_drvdata
(
mdev
,
NULL
);
vfio_unregister_group_dev
(
&
mdev_state
->
vdev
);
vfree
(
mdev_state
->
memblk
);
kfree
(
mdev_state
->
vconfig
);
kfree
(
mdev_state
);
mdpy_count
--
;
return
0
;
}
static
ssize_t
mdpy_read
(
struct
mdev_device
*
m
dev
,
char
__user
*
buf
,
static
ssize_t
mdpy_read
(
struct
vfio_device
*
v
dev
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
unsigned
int
done
=
0
;
int
ret
;
...
...
@@ -289,8 +296,8 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
if
(
count
>=
4
&&
!
(
*
ppos
%
4
))
{
u32
val
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
ret
=
mdev_access
(
mdev_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -301,7 +308,7 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
}
else
if
(
count
>=
2
&&
!
(
*
ppos
%
2
))
{
u16
val
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -313,7 +320,7 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
}
else
{
u8
val
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -336,9 +343,11 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
return
-
EFAULT
;
}
static
ssize_t
mdpy_write
(
struct
mdev_device
*
m
dev
,
const
char
__user
*
buf
,
static
ssize_t
mdpy_write
(
struct
vfio_device
*
v
dev
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
unsigned
int
done
=
0
;
int
ret
;
...
...
@@ -351,7 +360,7 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -363,7 +372,7 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -375,7 +384,7 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
char
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
char
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -393,9 +402,10 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
return
-
EFAULT
;
}
static
int
mdpy_mmap
(
struct
mdev_device
*
m
dev
,
struct
vm_area_struct
*
vma
)
static
int
mdpy_mmap
(
struct
vfio_device
*
v
dev
,
struct
vm_area_struct
*
vma
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
if
(
vma
->
vm_pgoff
!=
MDPY_MEMORY_BAR_OFFSET
>>
PAGE_SHIFT
)
return
-
EINVAL
;
...
...
@@ -409,16 +419,10 @@ static int mdpy_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
return
remap_vmalloc_range
(
vma
,
mdev_state
->
memblk
,
0
);
}
static
int
mdpy_get_region_info
(
struct
mdev_
device
*
mdev
,
static
int
mdpy_get_region_info
(
struct
mdev_
state
*
mdev_state
,
struct
vfio_region_info
*
region_info
,
u16
*
cap_type_id
,
void
**
cap_type
)
{
struct
mdev_state
*
mdev_state
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
!
mdev_state
)
return
-
EINVAL
;
if
(
region_info
->
index
>=
VFIO_PCI_NUM_REGIONS
&&
region_info
->
index
!=
MDPY_DISPLAY_REGION
)
return
-
EINVAL
;
...
...
@@ -447,15 +451,13 @@ static int mdpy_get_region_info(struct mdev_device *mdev,
return
0
;
}
static
int
mdpy_get_irq_info
(
struct
mdev_device
*
mdev
,
struct
vfio_irq_info
*
irq_info
)
static
int
mdpy_get_irq_info
(
struct
vfio_irq_info
*
irq_info
)
{
irq_info
->
count
=
0
;
return
0
;
}
static
int
mdpy_get_device_info
(
struct
mdev_device
*
mdev
,
struct
vfio_device_info
*
dev_info
)
static
int
mdpy_get_device_info
(
struct
vfio_device_info
*
dev_info
)
{
dev_info
->
flags
=
VFIO_DEVICE_FLAGS_PCI
;
dev_info
->
num_regions
=
VFIO_PCI_NUM_REGIONS
;
...
...
@@ -463,11 +465,9 @@ static int mdpy_get_device_info(struct mdev_device *mdev,
return
0
;
}
static
int
mdpy_query_gfx_plane
(
struct
mdev_
device
*
mdev
,
static
int
mdpy_query_gfx_plane
(
struct
mdev_
state
*
mdev_state
,
struct
vfio_device_gfx_plane_info
*
plane
)
{
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
plane
->
flags
&
VFIO_GFX_PLANE_TYPE_PROBE
)
{
if
(
plane
->
flags
==
(
VFIO_GFX_PLANE_TYPE_PROBE
|
VFIO_GFX_PLANE_TYPE_REGION
))
...
...
@@ -496,14 +496,13 @@ static int mdpy_query_gfx_plane(struct mdev_device *mdev,
return
0
;
}
static
long
mdpy_ioctl
(
struct
mdev_device
*
m
dev
,
unsigned
int
cmd
,
static
long
mdpy_ioctl
(
struct
vfio_device
*
v
dev
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
ret
=
0
;
unsigned
long
minsz
;
struct
mdev_state
*
mdev_state
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
switch
(
cmd
)
{
case
VFIO_DEVICE_GET_INFO
:
...
...
@@ -518,7 +517,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
info
.
argsz
<
minsz
)
return
-
EINVAL
;
ret
=
mdpy_get_device_info
(
mdev
,
&
info
);
ret
=
mdpy_get_device_info
(
&
info
);
if
(
ret
)
return
ret
;
...
...
@@ -543,7 +542,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
info
.
argsz
<
minsz
)
return
-
EINVAL
;
ret
=
mdpy_get_region_info
(
mdev
,
&
info
,
&
cap_type_id
,
ret
=
mdpy_get_region_info
(
mdev
_state
,
&
info
,
&
cap_type_id
,
&
cap_type
);
if
(
ret
)
return
ret
;
...
...
@@ -567,7 +566,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
(
info
.
index
>=
mdev_state
->
dev_info
.
num_irqs
))
return
-
EINVAL
;
ret
=
mdpy_get_irq_info
(
mdev
,
&
info
);
ret
=
mdpy_get_irq_info
(
&
info
);
if
(
ret
)
return
ret
;
...
...
@@ -590,7 +589,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
plane
.
argsz
<
minsz
)
return
-
EINVAL
;
ret
=
mdpy_query_gfx_plane
(
mdev
,
&
plane
);
ret
=
mdpy_query_gfx_plane
(
mdev
_state
,
&
plane
);
if
(
ret
)
return
ret
;
...
...
@@ -604,12 +603,12 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
return
-
EINVAL
;
case
VFIO_DEVICE_RESET
:
return
mdpy_reset
(
mdev
);
return
mdpy_reset
(
mdev
_state
);
}
return
-
ENOTTY
;
}
static
int
mdpy_open
(
struct
mdev_device
*
m
dev
)
static
int
mdpy_open
(
struct
vfio_device
*
v
dev
)
{
if
(
!
try_module_get
(
THIS_MODULE
))
return
-
ENODEV
;
...
...
@@ -617,7 +616,7 @@ static int mdpy_open(struct mdev_device *mdev)
return
0
;
}
static
void
mdpy_close
(
struct
mdev_device
*
m
dev
)
static
void
mdpy_close
(
struct
vfio_device
*
v
dev
)
{
module_put
(
THIS_MODULE
);
}
...
...
@@ -626,8 +625,7 @@ static ssize_t
resolution_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
mdev_device
*
mdev
=
mdev_from_dev
(
dev
);
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
struct
mdev_state
*
mdev_state
=
dev_get_drvdata
(
dev
);
return
sprintf
(
buf
,
"%dx%d
\n
"
,
mdev_state
->
type
->
width
,
...
...
@@ -716,18 +714,30 @@ static struct attribute_group *mdev_type_groups[] = {
NULL
,
};
static
const
struct
vfio_device_ops
mdpy_dev_ops
=
{
.
open
=
mdpy_open
,
.
release
=
mdpy_close
,
.
read
=
mdpy_read
,
.
write
=
mdpy_write
,
.
ioctl
=
mdpy_ioctl
,
.
mmap
=
mdpy_mmap
,
};
static
struct
mdev_driver
mdpy_driver
=
{
.
driver
=
{
.
name
=
"mdpy"
,
.
owner
=
THIS_MODULE
,
.
mod_name
=
KBUILD_MODNAME
,
.
dev_groups
=
mdev_dev_groups
,
},
.
probe
=
mdpy_probe
,
.
remove
=
mdpy_remove
,
};
static
const
struct
mdev_parent_ops
mdev_fops
=
{
.
owner
=
THIS_MODULE
,
.
mdev_attr_groups
=
mdev_dev_groups
,
.
device_driver
=
&
mdpy_driver
,
.
supported_type_groups
=
mdev_type_groups
,
.
create
=
mdpy_create
,
.
remove
=
mdpy_remove
,
.
open
=
mdpy_open
,
.
release
=
mdpy_close
,
.
read
=
mdpy_read
,
.
write
=
mdpy_write
,
.
ioctl
=
mdpy_ioctl
,
.
mmap
=
mdpy_mmap
,
};
static
const
struct
file_operations
vd_fops
=
{
...
...
@@ -752,11 +762,15 @@ static int __init mdpy_dev_init(void)
cdev_add
(
&
mdpy_cdev
,
mdpy_devt
,
MINORMASK
+
1
);
pr_info
(
"%s: major %d
\n
"
,
__func__
,
MAJOR
(
mdpy_devt
));
ret
=
mdev_register_driver
(
&
mdpy_driver
);
if
(
ret
)
goto
err_cdev
;
mdpy_class
=
class_create
(
THIS_MODULE
,
MDPY_CLASS_NAME
);
if
(
IS_ERR
(
mdpy_class
))
{
pr_err
(
"Error: failed to register mdpy_dev class
\n
"
);
ret
=
PTR_ERR
(
mdpy_class
);
goto
failed1
;
goto
err_driver
;
}
mdpy_dev
.
class
=
mdpy_class
;
mdpy_dev
.
release
=
mdpy_device_release
;
...
...
@@ -764,19 +778,21 @@ static int __init mdpy_dev_init(void)
ret
=
device_register
(
&
mdpy_dev
);
if
(
ret
)
goto
failed2
;
goto
err_class
;
ret
=
mdev_register_device
(
&
mdpy_dev
,
&
mdev_fops
);
if
(
ret
)
goto
failed3
;
goto
err_device
;
return
0
;
failed3
:
err_device
:
device_unregister
(
&
mdpy_dev
);
failed2
:
err_class
:
class_destroy
(
mdpy_class
);
failed1:
err_driver:
mdev_unregister_driver
(
&
mdpy_driver
);
err_cdev:
cdev_del
(
&
mdpy_cdev
);
unregister_chrdev_region
(
mdpy_devt
,
MINORMASK
+
1
);
return
ret
;
...
...
@@ -788,6 +804,7 @@ static void __exit mdpy_dev_exit(void)
mdev_unregister_device
(
&
mdpy_dev
);
device_unregister
(
&
mdpy_dev
);
mdev_unregister_driver
(
&
mdpy_driver
);
cdev_del
(
&
mdpy_cdev
);
unregister_chrdev_region
(
mdpy_devt
,
MINORMASK
+
1
);
class_destroy
(
mdpy_class
);
...
...
samples/vfio-mdev/mtty.c
View file @
bc01b761
...
...
@@ -127,6 +127,7 @@ struct serial_port {
/* State of each mdev device */
struct
mdev_state
{
struct
vfio_device
vdev
;
int
irq_fd
;
struct
eventfd_ctx
*
intx_evtfd
;
struct
eventfd_ctx
*
msi_evtfd
;
...
...
@@ -150,6 +151,8 @@ static const struct file_operations vd_fops = {
.
owner
=
THIS_MODULE
,
};
static
const
struct
vfio_device_ops
mtty_dev_ops
;
/* function prototypes */
static
int
mtty_trigger_interrupt
(
struct
mdev_state
*
mdev_state
);
...
...
@@ -631,22 +634,15 @@ static void mdev_read_base(struct mdev_state *mdev_state)
}
}
static
ssize_t
mdev_access
(
struct
mdev_
device
*
mdev
,
u8
*
buf
,
size_t
count
,
static
ssize_t
mdev_access
(
struct
mdev_
state
*
mdev_state
,
u8
*
buf
,
size_t
count
,
loff_t
pos
,
bool
is_write
)
{
struct
mdev_state
*
mdev_state
;
unsigned
int
index
;
loff_t
offset
;
int
ret
=
0
;
if
(
!
mdev
||
!
buf
)
return
-
EINVAL
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
!
mdev_state
)
{
pr_err
(
"%s mdev_state not found
\n
"
,
__func__
);
if
(
!
buf
)
return
-
EINVAL
;
}
mutex_lock
(
&
mdev_state
->
ops_lock
);
...
...
@@ -708,15 +704,18 @@ static ssize_t mdev_access(struct mdev_device *mdev, u8 *buf, size_t count,
return
ret
;
}
static
int
mtty_
creat
e
(
struct
mdev_device
*
mdev
)
static
int
mtty_
prob
e
(
struct
mdev_device
*
mdev
)
{
struct
mdev_state
*
mdev_state
;
int
nr_ports
=
mdev_get_type_group_id
(
mdev
)
+
1
;
int
ret
;
mdev_state
=
kzalloc
(
sizeof
(
struct
mdev_state
),
GFP_KERNEL
);
if
(
mdev_state
==
NULL
)
return
-
ENOMEM
;
vfio_init_group_dev
(
&
mdev_state
->
vdev
,
&
mdev
->
dev
,
&
mtty_dev_ops
);
mdev_state
->
nr_ports
=
nr_ports
;
mdev_state
->
irq_index
=
-
1
;
mdev_state
->
s
[
0
].
max_fifo_size
=
MAX_FIFO_SIZE
;
...
...
@@ -731,7 +730,6 @@ static int mtty_create(struct mdev_device *mdev)
mutex_init
(
&
mdev_state
->
ops_lock
);
mdev_state
->
mdev
=
mdev
;
mdev_set_drvdata
(
mdev
,
mdev_state
);
mtty_create_config_space
(
mdev_state
);
...
...
@@ -739,50 +737,40 @@ static int mtty_create(struct mdev_device *mdev)
list_add
(
&
mdev_state
->
next
,
&
mdev_devices_list
);
mutex_unlock
(
&
mdev_list_lock
);
ret
=
vfio_register_group_dev
(
&
mdev_state
->
vdev
);
if
(
ret
)
{
kfree
(
mdev_state
);
return
ret
;
}
dev_set_drvdata
(
&
mdev
->
dev
,
mdev_state
);
return
0
;
}
static
int
mtty_remove
(
struct
mdev_device
*
mdev
)
static
void
mtty_remove
(
struct
mdev_device
*
mdev
)
{
struct
mdev_state
*
mds
,
*
tmp_mds
;
struct
mdev_state
*
mdev_state
=
mdev_get_drvdata
(
mdev
);
int
ret
=
-
EINVAL
;
struct
mdev_state
*
mdev_state
=
dev_get_drvdata
(
&
mdev
->
dev
);
vfio_unregister_group_dev
(
&
mdev_state
->
vdev
);
mutex_lock
(
&
mdev_list_lock
);
list_for_each_entry_safe
(
mds
,
tmp_mds
,
&
mdev_devices_list
,
next
)
{
if
(
mdev_state
==
mds
)
{
list_del
(
&
mdev_state
->
next
);
mdev_set_drvdata
(
mdev
,
NULL
);
kfree
(
mdev_state
->
vconfig
);
kfree
(
mdev_state
);
ret
=
0
;
break
;
}
}
list_del
(
&
mdev_state
->
next
);
mutex_unlock
(
&
mdev_list_lock
);
return
ret
;
kfree
(
mdev_state
->
vconfig
);
kfree
(
mdev_state
);
}
static
int
mtty_reset
(
struct
mdev_
device
*
mdev
)
static
int
mtty_reset
(
struct
mdev_
state
*
mdev_state
)
{
struct
mdev_state
*
mdev_state
;
if
(
!
mdev
)
return
-
EINVAL
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
!
mdev_state
)
return
-
EINVAL
;
pr_info
(
"%s: called
\n
"
,
__func__
);
return
0
;
}
static
ssize_t
mtty_read
(
struct
mdev_device
*
m
dev
,
char
__user
*
buf
,
static
ssize_t
mtty_read
(
struct
vfio_device
*
v
dev
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
unsigned
int
done
=
0
;
int
ret
;
...
...
@@ -792,7 +780,7 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
if
(
count
>=
4
&&
!
(
*
ppos
%
4
))
{
u32
val
;
ret
=
mdev_access
(
mdev
,
(
u8
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
u8
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -804,7 +792,7 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
}
else
if
(
count
>=
2
&&
!
(
*
ppos
%
2
))
{
u16
val
;
ret
=
mdev_access
(
mdev
,
(
u8
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
u8
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -816,7 +804,7 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
}
else
{
u8
val
;
ret
=
mdev_access
(
mdev
,
(
u8
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
u8
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
false
);
if
(
ret
<=
0
)
goto
read_err
;
...
...
@@ -839,9 +827,11 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
return
-
EFAULT
;
}
static
ssize_t
mtty_write
(
struct
mdev_device
*
m
dev
,
const
char
__user
*
buf
,
static
ssize_t
mtty_write
(
struct
vfio_device
*
v
dev
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
unsigned
int
done
=
0
;
int
ret
;
...
...
@@ -854,7 +844,7 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
u8
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
u8
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -866,7 +856,7 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
u8
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
u8
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -878,7 +868,7 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
if
(
copy_from_user
(
&
val
,
buf
,
sizeof
(
val
)))
goto
write_err
;
ret
=
mdev_access
(
mdev
,
(
u8
*
)
&
val
,
sizeof
(
val
),
ret
=
mdev_access
(
mdev
_state
,
(
u8
*
)
&
val
,
sizeof
(
val
),
*
ppos
,
true
);
if
(
ret
<=
0
)
goto
write_err
;
...
...
@@ -896,19 +886,11 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
return
-
EFAULT
;
}
static
int
mtty_set_irqs
(
struct
mdev_
device
*
mdev
,
uint32_t
flags
,
static
int
mtty_set_irqs
(
struct
mdev_
state
*
mdev_state
,
uint32_t
flags
,
unsigned
int
index
,
unsigned
int
start
,
unsigned
int
count
,
void
*
data
)
{
int
ret
=
0
;
struct
mdev_state
*
mdev_state
;
if
(
!
mdev
)
return
-
EINVAL
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
!
mdev_state
)
return
-
EINVAL
;
mutex_lock
(
&
mdev_state
->
ops_lock
);
switch
(
index
)
{
...
...
@@ -1024,21 +1006,13 @@ static int mtty_trigger_interrupt(struct mdev_state *mdev_state)
return
ret
;
}
static
int
mtty_get_region_info
(
struct
mdev_
device
*
mdev
,
static
int
mtty_get_region_info
(
struct
mdev_
state
*
mdev_state
,
struct
vfio_region_info
*
region_info
,
u16
*
cap_type_id
,
void
**
cap_type
)
{
unsigned
int
size
=
0
;
struct
mdev_state
*
mdev_state
;
u32
bar_index
;
if
(
!
mdev
)
return
-
EINVAL
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
!
mdev_state
)
return
-
EINVAL
;
bar_index
=
region_info
->
index
;
if
(
bar_index
>=
VFIO_PCI_NUM_REGIONS
)
return
-
EINVAL
;
...
...
@@ -1073,8 +1047,7 @@ static int mtty_get_region_info(struct mdev_device *mdev,
return
0
;
}
static
int
mtty_get_irq_info
(
struct
mdev_device
*
mdev
,
struct
vfio_irq_info
*
irq_info
)
static
int
mtty_get_irq_info
(
struct
vfio_irq_info
*
irq_info
)
{
switch
(
irq_info
->
index
)
{
case
VFIO_PCI_INTX_IRQ_INDEX
:
...
...
@@ -1098,8 +1071,7 @@ static int mtty_get_irq_info(struct mdev_device *mdev,
return
0
;
}
static
int
mtty_get_device_info
(
struct
mdev_device
*
mdev
,
struct
vfio_device_info
*
dev_info
)
static
int
mtty_get_device_info
(
struct
vfio_device_info
*
dev_info
)
{
dev_info
->
flags
=
VFIO_DEVICE_FLAGS_PCI
;
dev_info
->
num_regions
=
VFIO_PCI_NUM_REGIONS
;
...
...
@@ -1108,19 +1080,13 @@ static int mtty_get_device_info(struct mdev_device *mdev,
return
0
;
}
static
long
mtty_ioctl
(
struct
mdev_device
*
m
dev
,
unsigned
int
cmd
,
static
long
mtty_ioctl
(
struct
vfio_device
*
v
dev
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
mdev_state
*
mdev_state
=
container_of
(
vdev
,
struct
mdev_state
,
vdev
);
int
ret
=
0
;
unsigned
long
minsz
;
struct
mdev_state
*
mdev_state
;
if
(
!
mdev
)
return
-
EINVAL
;
mdev_state
=
mdev_get_drvdata
(
mdev
);
if
(
!
mdev_state
)
return
-
ENODEV
;
switch
(
cmd
)
{
case
VFIO_DEVICE_GET_INFO
:
...
...
@@ -1135,7 +1101,7 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
info
.
argsz
<
minsz
)
return
-
EINVAL
;
ret
=
mtty_get_device_info
(
mdev
,
&
info
);
ret
=
mtty_get_device_info
(
&
info
);
if
(
ret
)
return
ret
;
...
...
@@ -1160,7 +1126,7 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
if
(
info
.
argsz
<
minsz
)
return
-
EINVAL
;
ret
=
mtty_get_region_info
(
mdev
,
&
info
,
&
cap_type_id
,
ret
=
mtty_get_region_info
(
mdev
_state
,
&
info
,
&
cap_type_id
,
&
cap_type
);
if
(
ret
)
return
ret
;
...
...
@@ -1184,7 +1150,7 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
(
info
.
index
>=
mdev_state
->
dev_info
.
num_irqs
))
return
-
EINVAL
;
ret
=
mtty_get_irq_info
(
mdev
,
&
info
);
ret
=
mtty_get_irq_info
(
&
info
);
if
(
ret
)
return
ret
;
...
...
@@ -1218,25 +1184,25 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
return
PTR_ERR
(
data
);
}
ret
=
mtty_set_irqs
(
mdev
,
hdr
.
flags
,
hdr
.
index
,
hdr
.
start
,
ret
=
mtty_set_irqs
(
mdev
_state
,
hdr
.
flags
,
hdr
.
index
,
hdr
.
start
,
hdr
.
count
,
data
);
kfree
(
ptr
);
return
ret
;
}
case
VFIO_DEVICE_RESET
:
return
mtty_reset
(
mdev
);
return
mtty_reset
(
mdev
_state
);
}
return
-
ENOTTY
;
}
static
int
mtty_open
(
struct
mdev_device
*
m
dev
)
static
int
mtty_open
(
struct
vfio_device
*
v
dev
)
{
pr_info
(
"%s
\n
"
,
__func__
);
return
0
;
}
static
void
mtty_close
(
struct
mdev
_device
*
mdev
)
static
void
mtty_close
(
struct
vfio
_device
*
mdev
)
{
pr_info
(
"%s
\n
"
,
__func__
);
}
...
...
@@ -1351,18 +1317,31 @@ static struct attribute_group *mdev_type_groups[] = {
NULL
,
};
static
const
struct
vfio_device_ops
mtty_dev_ops
=
{
.
name
=
"vfio-mtty"
,
.
open
=
mtty_open
,
.
release
=
mtty_close
,
.
read
=
mtty_read
,
.
write
=
mtty_write
,
.
ioctl
=
mtty_ioctl
,
};
static
struct
mdev_driver
mtty_driver
=
{
.
driver
=
{
.
name
=
"mtty"
,
.
owner
=
THIS_MODULE
,
.
mod_name
=
KBUILD_MODNAME
,
.
dev_groups
=
mdev_dev_groups
,
},
.
probe
=
mtty_probe
,
.
remove
=
mtty_remove
,
};
static
const
struct
mdev_parent_ops
mdev_fops
=
{
.
owner
=
THIS_MODULE
,
.
device_driver
=
&
mtty_driver
,
.
dev_attr_groups
=
mtty_dev_groups
,
.
mdev_attr_groups
=
mdev_dev_groups
,
.
supported_type_groups
=
mdev_type_groups
,
.
create
=
mtty_create
,
.
remove
=
mtty_remove
,
.
open
=
mtty_open
,
.
release
=
mtty_close
,
.
read
=
mtty_read
,
.
write
=
mtty_write
,
.
ioctl
=
mtty_ioctl
,
};
static
void
mtty_device_release
(
struct
device
*
dev
)
...
...
@@ -1393,12 +1372,16 @@ static int __init mtty_dev_init(void)
pr_info
(
"major_number:%d
\n
"
,
MAJOR
(
mtty_dev
.
vd_devt
));
ret
=
mdev_register_driver
(
&
mtty_driver
);
if
(
ret
)
goto
err_cdev
;
mtty_dev
.
vd_class
=
class_create
(
THIS_MODULE
,
MTTY_CLASS_NAME
);
if
(
IS_ERR
(
mtty_dev
.
vd_class
))
{
pr_err
(
"Error: failed to register mtty_dev class
\n
"
);
ret
=
PTR_ERR
(
mtty_dev
.
vd_class
);
goto
failed1
;
goto
err_driver
;
}
mtty_dev
.
dev
.
class
=
mtty_dev
.
vd_class
;
...
...
@@ -1407,28 +1390,25 @@ static int __init mtty_dev_init(void)
ret
=
device_register
(
&
mtty_dev
.
dev
);
if
(
ret
)
goto
failed2
;
goto
err_class
;
ret
=
mdev_register_device
(
&
mtty_dev
.
dev
,
&
mdev_fops
);
if
(
ret
)
goto
failed3
;
goto
err_device
;
mutex_init
(
&
mdev_list_lock
);
INIT_LIST_HEAD
(
&
mdev_devices_list
);
return
0
;
goto
all_done
;
failed3:
err_device:
device_unregister
(
&
mtty_dev
.
dev
);
failed2
:
err_class
:
class_destroy
(
mtty_dev
.
vd_class
);
failed1:
err_driver:
mdev_unregister_driver
(
&
mtty_driver
);
err_cdev:
cdev_del
(
&
mtty_dev
.
vd_cdev
);
unregister_chrdev_region
(
mtty_dev
.
vd_devt
,
MINORMASK
+
1
);
all_done:
return
ret
;
}
...
...
@@ -1439,6 +1419,7 @@ static void __exit mtty_dev_exit(void)
device_unregister
(
&
mtty_dev
.
dev
);
idr_destroy
(
&
mtty_dev
.
vd_idr
);
mdev_unregister_driver
(
&
mtty_driver
);
cdev_del
(
&
mtty_dev
.
vd_cdev
);
unregister_chrdev_region
(
mtty_dev
.
vd_devt
,
MINORMASK
+
1
);
class_destroy
(
mtty_dev
.
vd_class
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment