diff mbox

[v2,1/8] kvm tools: Add optional parameter used in ioport callbacks

Message ID 1306392135-16993-1-git-send-email-levinsasha928@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sasha Levin May 26, 2011, 6:42 a.m. UTC
Allow specifying an optional parameter when registering an
ioport range. The callback functions provided by the registering
module will be called with the same parameter.

This may be used to keep context during callbacks on IO operations.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/include/kvm/ioport.h |    3 ++
 tools/kvm/ioport.c             |   54 +++++++++++++++++++++++++++++----------
 2 files changed, 43 insertions(+), 14 deletions(-)

Comments

Pekka Enberg May 26, 2011, 8:53 a.m. UTC | #1
On Thu, 2011-05-26 at 09:42 +0300, Sasha Levin wrote:
> Allow specifying an optional parameter when registering an
> ioport range. The callback functions provided by the registering
> module will be called with the same parameter.
> 
> This may be used to keep context during callbacks on IO operations.
> 
> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> ---
>  tools/kvm/include/kvm/ioport.h |    3 ++
>  tools/kvm/ioport.c             |   54 +++++++++++++++++++++++++++++----------
>  2 files changed, 43 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
> index 8253938..2a8d74d 100644
> --- a/tools/kvm/include/kvm/ioport.h
> +++ b/tools/kvm/include/kvm/ioport.h
> @@ -25,11 +25,14 @@ struct kvm;
>  struct ioport_operations {
>  	bool (*io_in)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
>  	bool (*io_out)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
> +	bool (*io_in_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
> +	bool (*io_out_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);

So why not make that 'param' unconditional for io_in and io_out and just
pass NULL if it's not needed?

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sasha Levin May 26, 2011, 9:02 a.m. UTC | #2
On Thu, 2011-05-26 at 11:53 +0300, Pekka Enberg wrote:
> On Thu, 2011-05-26 at 09:42 +0300, Sasha Levin wrote:
> > Allow specifying an optional parameter when registering an
> > ioport range. The callback functions provided by the registering
> > module will be called with the same parameter.
> > 
> > This may be used to keep context during callbacks on IO operations.
> > 
> > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> > ---
> >  tools/kvm/include/kvm/ioport.h |    3 ++
> >  tools/kvm/ioport.c             |   54 +++++++++++++++++++++++++++++----------
> >  2 files changed, 43 insertions(+), 14 deletions(-)
> > 
> > diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
> > index 8253938..2a8d74d 100644
> > --- a/tools/kvm/include/kvm/ioport.h
> > +++ b/tools/kvm/include/kvm/ioport.h
> > @@ -25,11 +25,14 @@ struct kvm;
> >  struct ioport_operations {
> >  	bool (*io_in)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
> >  	bool (*io_out)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
> > +	bool (*io_in_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
> > +	bool (*io_out_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
> 
> So why not make that 'param' unconditional for io_in and io_out and just
> pass NULL if it's not needed?
> 

I've wanted to keep the original interface clean, Most of the IO port
users don't (and probably won't) require a parameter.
Pekka Enberg May 26, 2011, 9:04 a.m. UTC | #3
On Thu, May 26, 2011 at 12:02 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
> On Thu, 2011-05-26 at 11:53 +0300, Pekka Enberg wrote:
>> On Thu, 2011-05-26 at 09:42 +0300, Sasha Levin wrote:
>> > Allow specifying an optional parameter when registering an
>> > ioport range. The callback functions provided by the registering
>> > module will be called with the same parameter.
>> >
>> > This may be used to keep context during callbacks on IO operations.
>> >
>> > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
>> > ---
>> >  tools/kvm/include/kvm/ioport.h |    3 ++
>> >  tools/kvm/ioport.c             |   54 +++++++++++++++++++++++++++++----------
>> >  2 files changed, 43 insertions(+), 14 deletions(-)
>> >
>> > diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
>> > index 8253938..2a8d74d 100644
>> > --- a/tools/kvm/include/kvm/ioport.h
>> > +++ b/tools/kvm/include/kvm/ioport.h
>> > @@ -25,11 +25,14 @@ struct kvm;
>> >  struct ioport_operations {
>> >     bool (*io_in)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
>> >     bool (*io_out)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
>> > +   bool (*io_in_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
>> > +   bool (*io_out_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
>>
>> So why not make that 'param' unconditional for io_in and io_out and just
>> pass NULL if it's not needed?
>>
>
> I've wanted to keep the original interface clean, Most of the IO port
> users don't (and probably won't) require a parameter.

Well now struct ioport_operations isn't very clean is it - or the code
that needs to determine which function pointer to call?-)
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sasha Levin May 26, 2011, 9:14 a.m. UTC | #4
On Thu, 2011-05-26 at 12:04 +0300, Pekka Enberg wrote:
> On Thu, May 26, 2011 at 12:02 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
> > On Thu, 2011-05-26 at 11:53 +0300, Pekka Enberg wrote:
> >> On Thu, 2011-05-26 at 09:42 +0300, Sasha Levin wrote:
> >> > Allow specifying an optional parameter when registering an
> >> > ioport range. The callback functions provided by the registering
> >> > module will be called with the same parameter.
> >> >
> >> > This may be used to keep context during callbacks on IO operations.
> >> >
> >> > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> >> > ---
> >> >  tools/kvm/include/kvm/ioport.h |    3 ++
> >> >  tools/kvm/ioport.c             |   54 +++++++++++++++++++++++++++++----------
> >> >  2 files changed, 43 insertions(+), 14 deletions(-)
> >> >
> >> > diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
> >> > index 8253938..2a8d74d 100644
> >> > --- a/tools/kvm/include/kvm/ioport.h
> >> > +++ b/tools/kvm/include/kvm/ioport.h
> >> > @@ -25,11 +25,14 @@ struct kvm;
> >> >  struct ioport_operations {
> >> >     bool (*io_in)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
> >> >     bool (*io_out)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
> >> > +   bool (*io_in_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
> >> > +   bool (*io_out_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
> >>
> >> So why not make that 'param' unconditional for io_in and io_out and just
> >> pass NULL if it's not needed?
> >>
> >
> > I've wanted to keep the original interface clean, Most of the IO port
> > users don't (and probably won't) require a parameter.
> 
> Well now struct ioport_operations isn't very clean is it - or the code
> that needs to determine which function pointer to call?-)

struct ioport_operations is a bit more messy, but it's one spot instead
of adding a 'parameter' to each module that doesn't really need it.

My assumption is that most ioport users now and in the future won't need
it, it just solves several special cases more easily (multiple devices
which share same handling functions).
Pekka Enberg May 26, 2011, 9:20 a.m. UTC | #5
On Thu, May 26, 2011 at 12:14 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
>> > I've wanted to keep the original interface clean, Most of the IO port
>> > users don't (and probably won't) require a parameter.
>>
>> Well now struct ioport_operations isn't very clean is it - or the code
>> that needs to determine which function pointer to call?-)
>
> struct ioport_operations is a bit more messy, but it's one spot instead
> of adding a 'parameter' to each module that doesn't really need it.
>
> My assumption is that most ioport users now and in the future won't need
> it, it just solves several special cases more easily (multiple devices
> which share same handling functions).

Hey, that's not an excuse to make struct ioport_operations 'bit
messy'! Look at any kernel code that uses ops like we do here and you
will see we don't do APIs like this.

One option here is to rename 'struct ioport_entry' to 'struct ioport'
and pass a pointer to that as the first argument to all of the ops.
That's what most APIs in the kernel do anyway.

                        Pekka
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sasha Levin May 26, 2011, 9:38 a.m. UTC | #6
On Thu, 2011-05-26 at 12:20 +0300, Pekka Enberg wrote:
> On Thu, May 26, 2011 at 12:14 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
> >> > I've wanted to keep the original interface clean, Most of the IO port
> >> > users don't (and probably won't) require a parameter.
> >>
> >> Well now struct ioport_operations isn't very clean is it - or the code
> >> that needs to determine which function pointer to call?-)
> >
> > struct ioport_operations is a bit more messy, but it's one spot instead
> > of adding a 'parameter' to each module that doesn't really need it.
> >
> > My assumption is that most ioport users now and in the future won't need
> > it, it just solves several special cases more easily (multiple devices
> > which share same handling functions).
> 
> Hey, that's not an excuse to make struct ioport_operations 'bit
> messy'! Look at any kernel code that uses ops like we do here and you
> will see we don't do APIs like this.
> 
> One option here is to rename 'struct ioport_entry' to 'struct ioport'
> and pass a pointer to that as the first argument to all of the ops.
> That's what most APIs in the kernel do anyway.

Why do it like that? this way users of the callback functions will need
to know the internal structure of struct ioport_entry.
Pekka Enberg May 26, 2011, 9:43 a.m. UTC | #7
On Thu, May 26, 2011 at 12:38 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
>> One option here is to rename 'struct ioport_entry' to 'struct ioport'
>> and pass a pointer to that as the first argument to all of the ops.
>> That's what most APIs in the kernel do anyway.
>
> Why do it like that? this way users of the callback functions will need
> to know the internal structure of struct ioport_entry.

Look at 'struct inode' or similar data structure in the kernel. That's
how we do it. You can then also do s/params/priv/.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pekka Enberg May 26, 2011, 9:49 a.m. UTC | #8
Hi Sasha,

On Thu, May 26, 2011 at 12:38 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
>>> One option here is to rename 'struct ioport_entry' to 'struct ioport'
>>> and pass a pointer to that as the first argument to all of the ops.
>>> That's what most APIs in the kernel do anyway.
>>
>> Why do it like that? this way users of the callback functions will need
>> to know the internal structure of struct ioport_entry.

On Thu, May 26, 2011 at 12:43 PM, Pekka Enberg <penberg@kernel.org> wrote:
> Look at 'struct inode' or similar data structure in the kernel. That's
> how we do it. You can then also do s/params/priv/.

Btw, the whole notion of 'internal structure' for structs in C code is
a pretty broken concept. In most cases, you just end up passing
untyped fragments of the data to callers which makes following the
data flow in code difficult. Passing 'struct ioport' down to the code
makes the code more obvious and readable.

Encapsulation is important but emulating that with hiding structs in
.c files isn't helpful at all. Face it, there's no proper support for
that in C so you just need to rely on conventions to do it.

                      Pekka
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
index 8253938..2a8d74d 100644
--- a/tools/kvm/include/kvm/ioport.h
+++ b/tools/kvm/include/kvm/ioport.h
@@ -25,11 +25,14 @@  struct kvm;
 struct ioport_operations {
 	bool (*io_in)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
 	bool (*io_out)(struct kvm *kvm, u16 port, void *data, int size, u32 count);
+	bool (*io_in_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
+	bool (*io_out_param)(struct kvm *kvm, u16 port, void *data, int size, u32 count, void *param);
 };
 
 void ioport__setup_legacy(void);
 
 void ioport__register(u16 port, struct ioport_operations *ops, int count);
+void ioport__register_param(u16 port, struct ioport_operations *ops, int count, void *param);
 
 static inline u8 ioport__read8(u8 *data)
 {
diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
index 1f13960..159d089 100644
--- a/tools/kvm/ioport.c
+++ b/tools/kvm/ioport.c
@@ -18,6 +18,7 @@ 
 struct ioport_entry {
 	struct rb_int_node		node;
 	struct ioport_operations	*ops;
+	void				*param;
 };
 
 static struct rb_root ioport_tree = RB_ROOT;
@@ -89,6 +90,29 @@  void ioport__register(u16 port, struct ioport_operations *ops, int count)
 	ioport_insert(&ioport_tree, entry);
 }
 
+void ioport__register_param(u16 port, struct ioport_operations *ops, int count, void *param)
+{
+	struct ioport_entry *entry;
+
+	entry = ioport_search(&ioport_tree, port);
+	if (entry) {
+		pr_warning("ioport re-registered: %x", port);
+		rb_int_erase(&ioport_tree, &entry->node);
+	}
+
+	entry = malloc(sizeof(*entry));
+	if (entry == NULL)
+		die("Failed allocating new ioport entry");
+
+	*entry = (struct ioport_entry) {
+		.node	= RB_INT_INIT(port, port + count),
+		.ops	= ops,
+		.param	= param,
+	};
+
+	ioport_insert(&ioport_tree, entry);
+}
+
 static const char *to_direction(int direction)
 {
 	if (direction == KVM_EXIT_IO_IN)
@@ -105,30 +129,32 @@  static void ioport_error(u16 port, void *data, int direction, int size, u32 coun
 bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
 {
 	struct ioport_operations *ops;
-	bool ret;
+	bool ret = false;
 	struct ioport_entry *entry;
+	void *param;
 
 	entry = ioport_search(&ioport_tree, port);
 	if (!entry)
 		goto error;
 
-	ops = entry->ops;
+	ops	= entry->ops;
+	param	= entry->param;
 
 	if (direction == KVM_EXIT_IO_IN) {
-		if (!ops->io_in)
-			goto error;
-
-		ret = ops->io_in(kvm, port, data, size, count);
-		if (!ret)
-			goto error;
+		if (!param && ops->io_in)
+			ret = ops->io_in(kvm, port, data, size, count);
+		if (param && ops->io_in_param)
+			ret = ops->io_in_param(kvm, port, data, size, count, param);
 	} else {
-		if (!ops->io_out)
-			goto error;
-
-		ret = ops->io_out(kvm, port, data, size, count);
-		if (!ret)
-			goto error;
+		if (!param && ops->io_out)
+			ret = ops->io_out(kvm, port, data, size, count);
+		if (param && ops->io_out_param)
+			ret = ops->io_out_param(kvm, port, data, size, count, param);
 	}
+
+	if (!ret)
+		goto error;
+
 	return true;
 error:
 	if (ioport_debug)