All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/6] libxl: SECURITY: always honour request for vnc password
From: Ian Jackson @ 2011-02-01 18:24 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Ian Jackson
In-Reply-To: <1296584702-20138-2-git-send-email-ian.jackson@eu.citrix.com>

qemu only sets a password on its vnc display if the value for the -vnc
option has the ",password" modifier.  The code for constructing
qemu-dm options was broken and only added this modifier for one of the
cases.

Unfortunately there does not appear to be any code for passing the vnc
password to upstream qemu (ie, in the case where
libxl_build_device_model_args_new is called).  To avoid accidentally
running the domain without a password, check for this situation and
fail an assertion.  This will have to be revisited after 4.1.

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 tools/libxl/libxl_dm.c |   25 ++++++++++++++++---------
 1 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 3bef49a..7518118 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -23,6 +23,7 @@
 #include <signal.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <assert.h>
 #include "libxl_utils.h"
 #include "libxl_internal.h"
 #include "libxl.h"
@@ -55,26 +56,29 @@ static char ** libxl_build_device_model_args_old(libxl__gc *gc,
         flexarray_vappend(dm_args, "-domain-name", info->dom_name, NULL);
 
     if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
-        flexarray_append(dm_args, "-vnc");
+        char *vncarg;
         if (info->vncdisplay) {
             if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
-                flexarray_append(dm_args, 
-                    libxl__sprintf(gc, "%s:%d%s",
+                vncarg = libxl__sprintf(gc, "%s:%d",
                                   info->vnclisten,
-                                  info->vncdisplay,
-                                  info->vncpasswd ? ",password" : ""));
+                                  info->vncdisplay);
             } else {
-                flexarray_append(dm_args, libxl__sprintf(gc, "127.0.0.1:%d", info->vncdisplay));
+                vncarg = libxl__sprintf(gc, "127.0.0.1:%d", info->vncdisplay);
             }
         } else if (info->vnclisten) {
             if (strchr(info->vnclisten, ':') != NULL) {
-                flexarray_append(dm_args, info->vnclisten);
+                vncarg = info->vnclisten;
             } else {
-                flexarray_append(dm_args, libxl__sprintf(gc, "%s:0", info->vnclisten));
+                vncarg = libxl__sprintf(gc, "%s:0", info->vnclisten);
             }
         } else {
-            flexarray_append(dm_args, "127.0.0.1:0");
+            vncarg = "127.0.0.1:0";
         }
+        if (info->vncpasswd)
+            vncarg = libxl__sprintf(gc, "%s,password", vncarg);
+        flexarray_append(dm_args, "-vnc");
+        flexarray_append(dm_args, vncarg);
+        
         if (info->vncunused) {
             flexarray_append(dm_args, "-vncunused");
         }
@@ -190,6 +194,9 @@ static char ** libxl_build_device_model_args_new(libxl__gc *gc,
         int display = 0;
         const char *listen = "127.0.0.1";
 
+        if (info->vncpasswd && info->vncpasswd[0]) {
+            assert(!"missing code for supplying vnc password to qemu");
+        }
         flexarray_append(dm_args, "-vnc");
 
         if (info->vncdisplay) {
-- 
1.5.6.5

^ permalink raw reply related

* [PATCH 1/1] vnc, xen: write vnc address and password to xenstore
From: Ian Jackson @ 2011-02-01 18:24 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Ian Jackson
In-Reply-To: <1296584702-20138-1-git-send-email-ian.jackson@eu.citrix.com>

The xend protocol as actually implemented is:
  * xend writes:
     /vm/UUID/vncpasswd = "PASS"   (n0,rDOMID)
     /local/domain/0/backend/vfb/DOMID/0/vncunused = "0"   (n0,rDOMID)
     /local/domain/0/backend/vfb/DOMID/0/vnc = "1"   (n0,rDOMID)
     /local/domain/0/backend/vfb/DOMID/0/vnclisten = "ADDR"   (n0,rDOMID)
     /local/domain/0/backend/vfb/DOMID/0/vncdisplay = "PORT"   (n0,rDOMID)
     /local/domain/0/backend/vfb/DOMID/0/vncpasswd = "PASS"   (n0,rDOMID)
  * qemu reads /vm/UUID/vncpasswd and overwrites it with "\0"
  * qemu writes
     /local/domain/DOMID/console/vnc-port = "PORT"   (n0,rDOMID)
  * xm vncviewer reads entries from backend/vfb,
    as well as console/vnc-port.
Much of this is insane.

xl quite properly does not create anything in backend/vfb for an HVM
domain with no vfb.  But xl vncviewer needs to know the port number
and the address and the password.

So, for now, have qemu write these nodes too:
     /local/domain/DOMID/console/vnc-listen = "ADDR"   (n0,rDOMID)
     /local/domain/DOMID/console/vnc-pass = "PASS"   (n0,rDOMID)
This corresponds to the protocol actually currently implemented in
libxl.

We will revisit this after the 4.1 release and invent a non-insane
protocol.

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 qemu-common.h |    6 ++++++
 qemu-xen.h    |    1 -
 vl.c          |    1 -
 vnc.c         |    3 +++
 xenstore.c    |   57 ++++++++++++++++++++++++++++++++++++++++-----------------
 5 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/qemu-common.h b/qemu-common.h
index 50dfb6b..02d4cc4 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -209,4 +209,10 @@ void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
 
 #endif /* dyngen-exec.h hack */
 
+#include "qemu_socket.h"
+
+void xenstore_write_vncinfo(int port,
+                            const struct sockaddr *addr,
+                            socklen_t addrlen,
+                            const char *password);
 #endif
diff --git a/qemu-xen.h b/qemu-xen.h
index 0e70dbe..d50c89f 100644
--- a/qemu-xen.h
+++ b/qemu-xen.h
@@ -71,7 +71,6 @@ void xenstore_process_event(void *opaque);
 void xenstore_record_dm(const char *subpath, const char *state);
 void xenstore_record_dm_state(const char *state);
 void xenstore_check_new_media_present(int timeout);
-void xenstore_write_vncport(int vnc_display);
 void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen);
 void xenstore_write_vslots(char *vslots);
 
diff --git a/vl.c b/vl.c
index 5f48e1f..f07a659 100644
--- a/vl.c
+++ b/vl.c
@@ -6003,7 +6003,6 @@ int main(int argc, char **argv, char **envp)
                     vnc_display_port = vnc_display_open(ds, vnc_display, vncunused);
 		    if (vnc_display_port < 0)
                         exit(1);
-		    xenstore_write_vncport(vnc_display_port);
                 }
 #if defined(CONFIG_SDL)
                 if (sdl || !vnc_display)
diff --git a/vnc.c b/vnc.c
index ba26f9e..7629dfa 100644
--- a/vnc.c
+++ b/vnc.c
@@ -2768,6 +2768,9 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
 	return -1;
     }
 
+    xenstore_write_vncinfo(ntohs(iaddr.sin_port), addr, addrlen,
+                           vs->password);
+
     if (qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs) < 0)
 	return -1;
 
diff --git a/xenstore.c b/xenstore.c
index d364a5e..173a7c0 100644
--- a/xenstore.c
+++ b/xenstore.c
@@ -1149,32 +1149,55 @@ void xenstore_process_event(void *opaque)
     free(vec);
 }
 
-void xenstore_write_vncport(int display)
+static void xenstore_write_domain_console_item
+    (const char *item, const char *val)
 {
-    char *buf = NULL, *path;
-    char *portstr = NULL;
+    char *dompath;
+    char *path = NULL;
 
     if (xsh == NULL)
         return;
 
-    path = xs_get_domain_path(xsh, domid);
-    if (path == NULL) {
-        fprintf(logfile, "xs_get_domain_path() error\n");
-        goto out;
-    }
+    dompath = xs_get_domain_path(xsh, domid);
+    if (dompath == NULL) goto out_err;
 
-    if (pasprintf(&buf, "%s/console/vnc-port", path) == -1)
-        goto out;
-
-    if (pasprintf(&portstr, "%d", display) == -1)
-        goto out;
+    if (pasprintf(&path, "%s/console/%s", dompath, item) == -1) goto out_err;
 
-    if (xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)) == 0)
-        fprintf(logfile, "xs_write() vncport failed\n");
+    if (xs_write(xsh, XBT_NULL, path, val, strlen(val)) == 0)
+        goto out_err;
 
  out:
-    free(portstr);
-    free(buf);
+    free(path);
+    return;
+
+ out_err:
+    fprintf(logfile, "write console item %s (%s) failed\n", item, path);
+    goto out;
+}
+
+void xenstore_write_vncinfo(int port,
+                            const struct sockaddr *addr,
+                            socklen_t addrlen,
+                            const char *password)
+{
+    char *portstr = NULL;
+    const char *addrstr;
+
+    if (pasprintf(&portstr, "%d", port) != -1) {
+        xenstore_write_domain_console_item("vnc-port", portstr);
+        free(portstr);
+    }
+
+    assert(addr->sa_family == AF_INET); 
+    addrstr = inet_ntoa(((const struct sockaddr_in*)addr)->sin_addr);
+    if (!addrstr) {
+        fprintf(logfile, "inet_ntop on vnc-addr failed\n");
+    } else {
+        xenstore_write_domain_console_item("vnc-listen", addrstr);
+    }
+
+    if (password)
+        xenstore_write_domain_console_item("vnc-pass", password);
 }
 
 void xenstore_write_vslots(char *vslots)
-- 
1.5.6.5

^ permalink raw reply related

* [PATCH 0/6] Fix xl vncviewer
From: Ian Jackson @ 2011-02-01 18:24 UTC (permalink / raw)
  To: xen-devel

xl vncviewer does not work at all.  In this series I fix it.

Sadly the protocol spoken by xend and qemu is very bad.  xl makes some
assumptions about the protocol spoken by qemu which are not currently
true.  In patch 1 I make some interim changes to qemu have it do what
xl already expects, including storing the password in xenstore.  (This
is no worse than xend, which stores the password in two places
already, one of which is overwritten by qemu at startup...)

Patches 2-6 are fairly straightforward bugfixes to xl.

^ permalink raw reply

* Re: [PATCH 1/2] perf tools: Remove verbose build messages for the python binding
From: Arnaldo Carvalho de Melo @ 2011-02-01 18:24 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, linux-kernel, Frederic Weisbecker, Mike Galbraith,
	Paul Mackerras, Stephane Eranian, Tom Zanussi
In-Reply-To: <1296581819.26581.247.camel@laptop>

Em Tue, Feb 01, 2011 at 06:36:59PM +0100, Peter Zijlstra escreveu:
> This won't fix this, right?
> 
> running build_ext
> error: invalid Python installation: unable to open /usr/lib64/python2.6/config/Makefile (No such file or directory)
> make: *** [pyrf] Error 1

Right, I'll leverage the python script test for python-dev being present
in the system.

- Arnaldo

^ permalink raw reply

* Re: [Qemu-devel] [PATCH 0/4] new Blackfin QEMU port
From: Mike Frysinger @ 2011-02-01 18:16 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Edgar E. Iglesias, toolchain-devel, Alexander Graf, qemu-devel
In-Reply-To: <AANLkTi=EH5zCd_znOVZFcEmLvOF=vOK2vR5v9YDhtcvb@mail.gmail.com>

On Tue, Feb 1, 2011 at 12:30, Peter Maydell wrote:
> On 1 February 2011 17:20, Mike Frysinger wrote:
>> On Tue, Feb 1, 2011 at 05:31, Peter Maydell wrote:
>>> I suspect that this check of pc against the lbreg[]
>>> values should be being done in the generated code,
>>> not at translate time.
>>
>> the way i'm doing it atm i believe is safe.  if a lbreg changes, then
>> i invalidate any TBs associated with the old value and any TBs
>> associated with the new value.  thus i force the code to be
>> retranslated, and i can assume the lbreg values are constant when
>> doing so.
>
> That's OK too, that would fall into my category (3).

so the TB invalidation checking can be taken care of implicitly if i
handled things in cpu_get_tb_cpu_state() ?  that would be nice.

but i guess i'm not seeing how i would handle this scenario ... i want
to attach to each TB the state of the two 32bit lbregs when that TB
was created.  then in this state func, make sure the current lbregs
have the same values.  but if i need to encode this information into
"flags", i dont think i have enough space.
-mike

^ permalink raw reply

* [Qemu-devel] Re: [PATCH 15/19] savevm: introduce qemu_savevm_trans_{begin, commit}.
From: Yoshiaki Tamura @ 2011-02-01 18:21 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, kvm
In-Reply-To: <AANLkTinaSgv-g+w8frLmBR_A0r+T76w7rB4QUJPqR774@mail.gmail.com>

Paolo,

I refactored the savevm functions.  Could you give me your
comments?

Thanks,

Yoshi

diff --git a/savevm.c b/savevm.c
index 5418280..90aae55 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1602,29 +1602,68 @@ bool qemu_savevm_state_blocked(Monitor *mon)
     return false;
 }

-int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
-                            int shared)
+/*
+ * section: header to write
+ * inc: if true, forces to pass SECTION_PART instead of SECTION_START
+ * pause: if true, breaks the loop when live handler returned 0
+ */
+static int qemu_savevm_state_live(Monitor *mon, QEMUFile *f, int section,
+                                  bool inc, bool pause)
 {
     SaveStateEntry *se;
+    int skip = 0, ret;

     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if(se->set_params == NULL) {
+        int len, stage;
+
+        if (se->save_live_state == NULL) {
             continue;
-	}
-	se->set_params(blk_enable, shared, se->opaque);
+        }
+
+        /* Section type */
+        qemu_put_byte(f, section);
+        qemu_put_be32(f, se->section_id);
+
+        if (section == QEMU_VM_SECTION_START) {
+            /* ID string */
+            len = strlen(se->idstr);
+            qemu_put_byte(f, len);
+            qemu_put_buffer(f, (uint8_t *)se->idstr, len);
+
+            qemu_put_be32(f, se->instance_id);
+            qemu_put_be32(f, se->version_id);
+
+            stage = inc ? QEMU_VM_SECTION_PART : QEMU_VM_SECTION_START;
+        } else {
+            assert(inc);
+            stage = section;
+        }
+
+        ret = se->save_live_state(mon, f, stage, se->opaque);
+        if (!ret) {
+            skip++;
+            if (pause) {
+                break;
+            }
+        }
     }
-
-    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
-    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+    return skip;
+}
+
+static void qemu_savevm_state_full(QEMUFile *f)
+{
+    SaveStateEntry *se;

     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         int len;

-        if (se->save_live_state == NULL)
+        if (se->save_state == NULL && se->vmsd == NULL) {
             continue;
+        }

         /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_START);
+        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
         qemu_put_be32(f, se->section_id);

         /* ID string */
@@ -1635,8 +1674,28 @@ int qemu_savevm_state_begin(Monitor *mon,
QEMUFile *f, int blk_enable,
         qemu_put_be32(f, se->instance_id);
         qemu_put_be32(f, se->version_id);

-        se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
+        vmstate_save(f, se);
+    }
+
+    qemu_put_byte(f, QEMU_VM_EOF);
+}
+
+int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
+                            int shared)
+{
+    SaveStateEntry *se;
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if(se->set_params == NULL) {
+            continue;
+        }
+        se->set_params(blk_enable, shared, se->opaque);
     }
+
+    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
+    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+    qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_START, 0, 0);

     if (qemu_file_has_error(f)) {
         qemu_savevm_state_cancel(mon, f);
@@ -1648,29 +1707,16 @@ int qemu_savevm_state_begin(Monitor *mon,
QEMUFile *f, int blk_enable,

 int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
 {
-    SaveStateEntry *se;
     int ret = 1;

-    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if (se->save_live_state == NULL)
-            continue;
-
-        /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_PART);
-        qemu_put_be32(f, se->section_id);
-
-        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
-        if (!ret) {
-            /* Do not proceed to the next vmstate before this one reported
-               completion of the current stage. This serializes the migration
-               and reduces the probability that a faster changing state is
-               synchronized over and over again. */
-            break;
-        }
-    }
-
-    if (ret)
+    /* Do not proceed to the next vmstate before this one reported
+       completion of the current stage. This serializes the migration
+       and reduces the probability that a faster changing state is
+       synchronized over and over again. */
+    ret = qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_PART, 1, 1);
+    if (!ret) {
         return 1;
+    }

     if (qemu_file_has_error(f)) {
         qemu_savevm_state_cancel(mon, f);
@@ -1682,46 +1728,40 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)

 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
 {
-    SaveStateEntry *se;
-
     cpu_synchronize_all_states();

-    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if (se->save_live_state == NULL)
-            continue;
-
-        /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_END);
-        qemu_put_be32(f, se->section_id);
+    qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_END, 1, 0);
+    qemu_savevm_state_full(f);

-        se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
-    }
+    if (qemu_file_has_error(f))
+        return -EIO;

-    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        int len;
+    return 0;
+}

-	if (se->save_state == NULL && se->vmsd == NULL)
-	    continue;
+int qemu_savevm_trans_begin(Monitor *mon, QEMUFile *f, int init)
+{
+    int ret;

-        /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
-        qemu_put_be32(f, se->section_id);
+    ret = qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_START, !init, 0);

-        /* ID string */
-        len = strlen(se->idstr);
-        qemu_put_byte(f, len);
-        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
+    if (qemu_file_has_error(f)) {
+        return -EIO;
+    }

-        qemu_put_be32(f, se->instance_id);
-        qemu_put_be32(f, se->version_id);
+    return ret;
+}

-        vmstate_save(f, se);
-    }
+int qemu_savevm_trans_complete(Monitor *mon, QEMUFile *f)
+{
+    cpu_synchronize_all_states();

-    qemu_put_byte(f, QEMU_VM_EOF);
+    qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_PART, 1, 0);
+    qemu_savevm_state_full(f);

-    if (qemu_file_has_error(f))
+    if (qemu_file_has_error(f)) {
         return -EIO;
+    }

     return 0;
 }
diff --git a/sysemu.h b/sysemu.h
index 329415f..ee2c382 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -81,6 +81,8 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile
*f, int blk_enable,
 int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
 void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
+int qemu_savevm_trans_begin(Monitor *mon, QEMUFile *f, int init);
+int qemu_savevm_trans_complete(Monitor *mon, QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f, int skip_header);

 /* SLIRP */

^ permalink raw reply related

* Re: [PATCH 15/19] savevm: introduce qemu_savevm_trans_{begin,commit}.
From: Yoshiaki Tamura @ 2011-02-01 18:21 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: kvm, qemu-devel
In-Reply-To: <AANLkTinaSgv-g+w8frLmBR_A0r+T76w7rB4QUJPqR774@mail.gmail.com>

Paolo,

I refactored the savevm functions.  Could you give me your
comments?

Thanks,

Yoshi

diff --git a/savevm.c b/savevm.c
index 5418280..90aae55 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1602,29 +1602,68 @@ bool qemu_savevm_state_blocked(Monitor *mon)
     return false;
 }

-int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
-                            int shared)
+/*
+ * section: header to write
+ * inc: if true, forces to pass SECTION_PART instead of SECTION_START
+ * pause: if true, breaks the loop when live handler returned 0
+ */
+static int qemu_savevm_state_live(Monitor *mon, QEMUFile *f, int section,
+                                  bool inc, bool pause)
 {
     SaveStateEntry *se;
+    int skip = 0, ret;

     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if(se->set_params == NULL) {
+        int len, stage;
+
+        if (se->save_live_state == NULL) {
             continue;
-	}
-	se->set_params(blk_enable, shared, se->opaque);
+        }
+
+        /* Section type */
+        qemu_put_byte(f, section);
+        qemu_put_be32(f, se->section_id);
+
+        if (section == QEMU_VM_SECTION_START) {
+            /* ID string */
+            len = strlen(se->idstr);
+            qemu_put_byte(f, len);
+            qemu_put_buffer(f, (uint8_t *)se->idstr, len);
+
+            qemu_put_be32(f, se->instance_id);
+            qemu_put_be32(f, se->version_id);
+
+            stage = inc ? QEMU_VM_SECTION_PART : QEMU_VM_SECTION_START;
+        } else {
+            assert(inc);
+            stage = section;
+        }
+
+        ret = se->save_live_state(mon, f, stage, se->opaque);
+        if (!ret) {
+            skip++;
+            if (pause) {
+                break;
+            }
+        }
     }
-
-    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
-    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+    return skip;
+}
+
+static void qemu_savevm_state_full(QEMUFile *f)
+{
+    SaveStateEntry *se;

     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         int len;

-        if (se->save_live_state == NULL)
+        if (se->save_state == NULL && se->vmsd == NULL) {
             continue;
+        }

         /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_START);
+        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
         qemu_put_be32(f, se->section_id);

         /* ID string */
@@ -1635,8 +1674,28 @@ int qemu_savevm_state_begin(Monitor *mon,
QEMUFile *f, int blk_enable,
         qemu_put_be32(f, se->instance_id);
         qemu_put_be32(f, se->version_id);

-        se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
+        vmstate_save(f, se);
+    }
+
+    qemu_put_byte(f, QEMU_VM_EOF);
+}
+
+int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
+                            int shared)
+{
+    SaveStateEntry *se;
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if(se->set_params == NULL) {
+            continue;
+        }
+        se->set_params(blk_enable, shared, se->opaque);
     }
+
+    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
+    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+    qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_START, 0, 0);

     if (qemu_file_has_error(f)) {
         qemu_savevm_state_cancel(mon, f);
@@ -1648,29 +1707,16 @@ int qemu_savevm_state_begin(Monitor *mon,
QEMUFile *f, int blk_enable,

 int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
 {
-    SaveStateEntry *se;
     int ret = 1;

-    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if (se->save_live_state == NULL)
-            continue;
-
-        /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_PART);
-        qemu_put_be32(f, se->section_id);
-
-        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
-        if (!ret) {
-            /* Do not proceed to the next vmstate before this one reported
-               completion of the current stage. This serializes the migration
-               and reduces the probability that a faster changing state is
-               synchronized over and over again. */
-            break;
-        }
-    }
-
-    if (ret)
+    /* Do not proceed to the next vmstate before this one reported
+       completion of the current stage. This serializes the migration
+       and reduces the probability that a faster changing state is
+       synchronized over and over again. */
+    ret = qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_PART, 1, 1);
+    if (!ret) {
         return 1;
+    }

     if (qemu_file_has_error(f)) {
         qemu_savevm_state_cancel(mon, f);
@@ -1682,46 +1728,40 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)

 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
 {
-    SaveStateEntry *se;
-
     cpu_synchronize_all_states();

-    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if (se->save_live_state == NULL)
-            continue;
-
-        /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_END);
-        qemu_put_be32(f, se->section_id);
+    qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_END, 1, 0);
+    qemu_savevm_state_full(f);

-        se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
-    }
+    if (qemu_file_has_error(f))
+        return -EIO;

-    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        int len;
+    return 0;
+}

-	if (se->save_state == NULL && se->vmsd == NULL)
-	    continue;
+int qemu_savevm_trans_begin(Monitor *mon, QEMUFile *f, int init)
+{
+    int ret;

-        /* Section type */
-        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
-        qemu_put_be32(f, se->section_id);
+    ret = qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_START, !init, 0);

-        /* ID string */
-        len = strlen(se->idstr);
-        qemu_put_byte(f, len);
-        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
+    if (qemu_file_has_error(f)) {
+        return -EIO;
+    }

-        qemu_put_be32(f, se->instance_id);
-        qemu_put_be32(f, se->version_id);
+    return ret;
+}

-        vmstate_save(f, se);
-    }
+int qemu_savevm_trans_complete(Monitor *mon, QEMUFile *f)
+{
+    cpu_synchronize_all_states();

-    qemu_put_byte(f, QEMU_VM_EOF);
+    qemu_savevm_state_live(mon, f, QEMU_VM_SECTION_PART, 1, 0);
+    qemu_savevm_state_full(f);

-    if (qemu_file_has_error(f))
+    if (qemu_file_has_error(f)) {
         return -EIO;
+    }

     return 0;
 }
diff --git a/sysemu.h b/sysemu.h
index 329415f..ee2c382 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -81,6 +81,8 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile
*f, int blk_enable,
 int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
 void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
+int qemu_savevm_trans_begin(Monitor *mon, QEMUFile *f, int init);
+int qemu_savevm_trans_complete(Monitor *mon, QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f, int skip_header);

 /* SLIRP */

^ permalink raw reply related

* need help with bouncing emails ...
From: Kamble, Nitin A @ 2011-02-01 18:21 UTC (permalink / raw)
  To: poky@yoctoproject.org

[-- Attachment #1: Type: text/plain, Size: 1893 bytes --]



_____________________________________________
From: Mail Delivery System [mailto:MAILER-DAEMON@mga09.intel.com]
Sent: Tuesday, February 01, 2011 10:19 AM
To: Kamble, Nitin A
Subject: Undeliverable: [PATCH 1/4] distro_tracking: update latest upstream versions


Delivery has failed to these recipients or distribution lists:

poky@yoctolinux.org<mailto:poky@yoctolinux.org>
An error occurred while trying to deliver this message to the recipient's e-mail address. Microsoft Exchange will not try to redeliver this message for you. Please try resending this message, or provide the following diagnostic text to your system administrator.

The following organization rejected your message: [216.69.186.201].







Diagnostic information for administrators:

Generating server: mga09.intel.com

poky@yoctolinux.org
[216.69.186.201] #<[216.69.186.201] #5.0.0 smtp; 5.1.0 - Unknown address error 550-'#5.1.0 Address rejected poky@yoctolinux.org' (delivery attempts: 0)> #SMTP#

Original message headers:

Received: from orsmga002.jf.intel.com ([10.7.209.21])  by
 orsmga102.jf.intel.com with ESMTP; 01 Feb 2011 10:19:11 -0800
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="4.60,411,1291622400";
   d="scan'208";a="598515791"
Received: from nbuild1.sc.intel.com (HELO localhost) ([172.25.110.36])
  by orsmga002.jf.intel.com with ESMTP; 01 Feb 2011 10:19:11 -0800
Message-ID: <f260ac9776a6e9a62c3b8c88e0e2b7ce6c1c2a87.1296560850.git.nitin.a.kamble@intel.com>
In-Reply-To: <cover.1296560850.git.nitin.a.kamble@intel.com>
References: <cover.1296560850.git.nitin.a.kamble@intel.com>
Old-Date: Tue, 25 Jan 2011 15:58:54 -0800
Subject: [PATCH 1/4] distro_tracking: update latest upstream versions
Date: Tue, 1 Feb 2011 03:49:18 -0800
To: <poky@yoctolinux.org>
CC:
From: Nitin A Kamble <nitin.a.kamble@intel.com>
MIME-Version: 1.0
Content-Type: text/plain



[-- Attachment #2: Type: text/html, Size: 4400 bytes --]

^ permalink raw reply

* [PATCH] ARM: pxa: Properly configure PWM period for palm27x
From: Marek Vasut @ 2011-02-01 18:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296511613-24406-1-git-send-email-marek.vasut@gmail.com>

On Monday 31 January 2011 23:06:53 Marek Vasut wrote:
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> ---
>  arch/arm/mach-pxa/palm27x.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
> index 7d1434a..4c9a938 100644
> --- a/arch/arm/mach-pxa/palm27x.c
> +++ b/arch/arm/mach-pxa/palm27x.c
> @@ -322,7 +322,7 @@ static struct platform_pwm_backlight_data
> palm27x_backlight_data = { .pwm_id		= 0,
>  	.max_brightness	= 0xfe,
>  	.dft_brightness	= 0x7e,
> -	.pwm_period_ns	= 3500,
> +	.pwm_period_ns	= 3500 * 1024,
>  	.init		= palm27x_backlight_init,
>  	.notify		= palm27x_backlight_notify,
>  	.exit		= palm27x_backlight_exit,

CC linux-arm-kernel, I mistyped, sorry

^ permalink raw reply

* [PATCH 9/9] drm/i915/context: Insert MI_SET_CONTEXT in ringbuffer context switch
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

Added ringbuffer code to initiate context switch. The context switch can
fail since intel_ring_begin() can fail, and I am not sure how to handle
that yet. In most cases a context switch failure is pretty much fatal.

Modified the locking on deinit, which had a race (though results were
not fatal, just slower).

Fixed execbuffer to pass default_context when there is no context
specified by userspace.
---
 drivers/gpu/drm/i915/i915_context.c        |   28 ++++++++++++-----
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   13 +++++--
 drivers/gpu/drm/i915/intel_ringbuffer.c    |   46 ++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_ringbuffer.h    |    2 +-
 4 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index 4f255fb..6674a9d 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -81,7 +81,7 @@ i915_context_validate(struct drm_device *dev, struct drm_file *file,
 	struct drm_gem_object *obj;
 	struct drm_i915_gem_object *obj_priv;
 	struct drm_i915_gem_context *ctx;
-	int i, ret = 0;
+	int i;
 
 	ctx = i915_context_lookup_id(dev, ctx_id);
 	if (ctx == NULL) {
@@ -261,21 +261,32 @@ static void i915_context_hw_init(struct drm_device *dev,
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static void i915_context_hw_deinit(struct drm_device *dev,
+static int i915_context_hw_deinit(struct drm_device *dev,
 				   struct drm_i915_gem_context *ctx,
 				   struct intel_ring_buffer *ring)
 {
+	int ret;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
 	/* XXX We can prevent restoring contexts, but not saving them
 	 * so if we're going to take away our backing context object
 	 * of the last context, we have to switch now.
 	 */
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	mutex_lock(&dev->struct_mutex);
 	if (ring->last_context == ctx && ctx != dev_priv->default_context) {
-		mutex_lock(&dev->struct_mutex);
-		ring->context_switch(ring, dev_priv->default_context,
-				     I915_CONTEXT_NORMAL_SWITCH);
-		mutex_unlock(&dev->struct_mutex);
+		DRM_DEBUG_DRIVER("Switching to default context\n");
+		ret = ring->context_switch(ring, dev_priv->default_context,
+					   I915_CONTEXT_NORMAL_SWITCH);
+		if (ret) {
+			DRM_ERROR("Couldn't switch back to default context\n");
+			goto out;
+		}
+		ring->last_context = dev_priv->default_context;
 	}
+
+out:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
 }
 
 static int
@@ -428,7 +439,8 @@ void i915_context_init(struct drm_device *dev)
 		dev_priv->ctx_disable = 1;
 		idr_destroy(&dev_priv->i915_ctx_idr);
 	} else {
-		DRM_DEBUG_DRIVER("Context support enabled\n", ret);
+		DRM_DEBUG_DRIVER("Default context = %p\n",
+		 to_intel_bo(dev_priv->default_context->ctx_obj)->gtt_offset);
 	}
 }
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 9d022fb..c1d9a0a 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -990,7 +990,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	struct drm_i915_gem_object *batch_obj;
 	struct drm_clip_rect *cliprects = NULL;
 	struct intel_ring_buffer *ring;
-	struct drm_i915_gem_context *ctx;
+	struct drm_i915_gem_context *ctx = NULL;
 	u32 exec_start, exec_len;
 	u32 seqno;
 	u32 ctx_id;
@@ -1013,7 +1013,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			DRM_DEBUG_DRIVER("Context resubmission required\n");
 			return -EIO;
 		}
-	}
+	} else
+		ctx = dev_priv->default_context;
+
 #if WATCH_EXEC
 	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
 		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
@@ -1203,8 +1205,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		}
 	}
 
-	if (!dev_priv->ctx_disable)
-		ring->context_switch(ring, ctx, I915_CONTEXT_NORMAL_SWITCH);
+	if (!dev_priv->ctx_disable) {
+		ret = ring->context_switch(ring, ctx, I915_CONTEXT_NORMAL_SWITCH);
+		if (ret)
+			goto err;
+	}
 
 	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
 	exec_len = args->batch_len;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 89adb9d..4381730 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -750,15 +750,55 @@ render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 	return 0;
 }
 
-static void
+static int
 render_ring_ctx_switch(struct intel_ring_buffer *ring,
 		       struct drm_i915_gem_context *ctx,
-		       uint32_t flags)
+		       u32 flags)
 {
+	struct drm_device *dev = ring->dev;
+	struct drm_gem_object *obj;
+	uint32_t ctx_switch_flags;
+	int ret = 0;
+
 	if (ring->last_context == ctx)
-		return;
+		return 0;
+
+	DRM_DEBUG_DRIVER("Context switch to %d\n",
+			 ctx->ctx_id);
 
 	ring->last_context = ctx;
+	obj = ctx->ctx_obj;
+
+	if (flags == I915_CONTEXT_SAVE_ONLY)
+		ctx_switch_flags = MI_RESTORE_INHIBIT;
+	else
+		ctx_switch_flags = 0;
+
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
+
+	if (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev))
+		intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
+	else
+		intel_ring_emit(ring, MI_NOOP);
+
+	intel_ring_emit(ring, MI_SET_CONTEXT);
+	intel_ring_emit(ring, to_intel_bo(obj)->gtt_offset |
+			MI_MM_SPACE_GTT |
+			MI_SAVE_EXT_STATE_EN |
+			MI_RESTORE_EXT_STATE_EN |
+			ctx_switch_flags);
+
+	if (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev))
+		intel_ring_emit(ring, MI_SUSPEND_FLUSH);
+		/* TODO: we may need a NOOP here */
+	else
+		intel_ring_emit(ring, MI_NOOP);
+
+	intel_ring_advance(ring);
+
+	return 0;
 }
 
 static void cleanup_status_page(struct intel_ring_buffer *ring)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 61525ba..e8f8b6a 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -80,7 +80,7 @@ struct  intel_ring_buffer {
 					       u32 offset, u32 length);
 	void		(*cleanup)(struct intel_ring_buffer *ring);
 	struct		drm_i915_gem_context *last_context;
-	void		(*context_switch)(struct intel_ring_buffer *ring,
+	int		(*context_switch)(struct intel_ring_buffer *ring,
 					  struct drm_i915_gem_context *ctx,
 					  u32 flags);
 
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 8/9] drm/i915/context: enable calling context_switch
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

Changed context_validation code to return a pointer to the context which
was validated. This saved us a context id lookup later when we want to
actually context switch. The downside is we can't differentiate a
lost context (buffer moved) from a never-existed context. This seems
okay to me for now.

Added a call from do_execbuffer to actually context_switch for the
ringbuffer. Although context_switch is not yet implemented, this can
hopefully prove we don't break the existing code.
---
 drivers/gpu/drm/i915/i915_context.c        |   14 ++++++++------
 drivers/gpu/drm/i915/i915_drv.h            |    9 +++++----
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   13 ++++++++-----
 drivers/gpu/drm/i915/intel_ringbuffer.h    |    2 +-
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index cba0452..4f255fb 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -73,7 +73,8 @@ static void i915_context_del_id(struct drm_device *dev,
 	idr_remove(&dev_priv->i915_ctx_idr, ctx->ctx_id);
 }
 
-int i915_context_validate(struct drm_device *dev, struct drm_file *file,
+struct drm_i915_gem_context *
+i915_context_validate(struct drm_device *dev, struct drm_file *file,
 			  uint32_t ctx_id,
 			  struct drm_i915_context_flag *ctx_flag, int count)
 {
@@ -85,7 +86,7 @@ int i915_context_validate(struct drm_device *dev, struct drm_file *file,
 	ctx = i915_context_lookup_id(dev, ctx_id);
 	if (ctx == NULL) {
 		DRM_ERROR("Couldn't find context\n");
-		return -ENXIO;
+		return ctx;
 	}
 
 	if ((!count || !ctx_flag))
@@ -117,7 +118,7 @@ int i915_context_validate(struct drm_device *dev, struct drm_file *file,
 			}
 			obj_priv = to_intel_bo(obj);
 			if (flag->offset && HAS_PPGTT(dev)) {
-				/* 
+				/*
 				 * No need to check for overlaps because this is
 				 * in their local GTT so they can only screw up
 				 * themselves. But do check serious violations
@@ -163,13 +164,14 @@ out:
 			DRM_DEBUG_DRIVER("Context associated buffer has moved"
 					 " %p->%p\n",
 					 ppgtt_offset, obj_priv->gtt_offset);
-			ret = -EIO;
-			break;
+			mutex_unlock(&ctx->slot_mtx);
+			ctx = NULL;
+			return ctx;
 		}
 	}
 
 	mutex_unlock(&ctx->slot_mtx);
-	return ret;
+	return ctx;
 }
 
 void i915_context_handle_binding(struct drm_i915_gem_object *obj)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3105fd6..110e495 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1326,10 +1326,11 @@ extern void i915_context_init(struct drm_device *dev);
 extern void i915_context_deinit(struct drm_device *dev);
 extern void i915_context_close(struct drm_device *dev, struct drm_file *file);
 struct drm_i915_context_flag;
-extern int i915_context_validate(struct drm_device *dev,
-				 struct drm_file *file, uint32_t ctx_id,
-				 struct drm_i915_context_flag *ctx_flag,
-				 int count);
+extern struct drm_i915_gem_context *
+i915_context_validate(struct drm_device *dev,
+		      struct drm_file *file, uint32_t ctx_id,
+		      struct drm_i915_context_flag *ctx_flag,
+		      int count);
 extern void i915_context_handle_binding(struct drm_i915_gem_object *obj);
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 1051b1e..9d022fb 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -990,6 +990,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	struct drm_i915_gem_object *batch_obj;
 	struct drm_clip_rect *cliprects = NULL;
 	struct intel_ring_buffer *ring;
+	struct drm_i915_gem_context *ctx;
 	u32 exec_start, exec_len;
 	u32 seqno;
 	u32 ctx_id;
@@ -1006,12 +1007,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	ctx_id = EXECBUFFER2_CTX_ID(args);
 	if (ctx_id) {
-		ret = i915_context_validate(dev, file, ctx_id,
+		ctx = i915_context_validate(dev, file, ctx_id,
 					    ctx_flags, flag_count);
-		if (ret) {
-			if (ret == -EIO)
-				DRM_DEBUG_DRIVER("Context resubmission required\n");
-			return ret;
+		if (!ctx) {
+			DRM_DEBUG_DRIVER("Context resubmission required\n");
+			return -EIO;
 		}
 	}
 #if WATCH_EXEC
@@ -1203,6 +1203,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		}
 	}
 
+	if (!dev_priv->ctx_disable)
+		ring->context_switch(ring, ctx, I915_CONTEXT_NORMAL_SWITCH);
+
 	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
 	exec_len = args->batch_len;
 	if (cliprects) {
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 68ebecf..61525ba 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -82,7 +82,7 @@ struct  intel_ring_buffer {
 	struct		drm_i915_gem_context *last_context;
 	void		(*context_switch)(struct intel_ring_buffer *ring,
 					  struct drm_i915_gem_context *ctx,
-					  uint32_t flags);
+					  u32 flags);
 
 	/**
 	 * List of objects currently involved in rendering from the
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 7/9] drm/i915/context: context validation for execbuffer2
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

Adds the support for actually doing something with buffer validation for
the context when submitted via execbuffer2. When a set of context flags
are submitted in the execbuffer call, the code is able to handle the
commands. It will also go through the existing buffers associated with
the context and make sure they are still present. The big thing missing
is if the client wants to change the domains of buffers which have
already been associated. In this case, the client must disassociate and
then re-associate with the proper domains.

Fixed up some small issues which hooks the main gem code the context
code to do buffer association and validation.

As a result of this, the unit test posted on the mailing list should
behave as expected.
---
 drivers/gpu/drm/i915/i915_context.c        |  111 +++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_drv.h            |    3 +
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   12 ++-
 include/drm/i915_drm.h                     |    5 +-
 4 files changed, 124 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index a486a9c..cba0452 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -29,6 +29,13 @@
 #include "i915_drm.h"
 #include "intel_drv.h"
 
+#define PPGTT_NEEDS_RELOC	(1ULL << 63)
+#define PPGTT_USER_DEFINED	(1ULL << 62)
+#define PPGTT_RELOCATED		(1ULL << 61)
+#define PPGTT_ADDR(x)		(x & 0xFFFFFFFFFFULL)
+
+#define PPGTT_PINNED(x) ((uint64_t)x & (PPGTT_USER_DEFINED | PPGTT_RELOCATED))
+
 static int
 i915_context_gen_id(struct drm_i915_private *dev_priv,
 		    struct drm_i915_gem_context *ctx)
@@ -70,8 +77,110 @@ int i915_context_validate(struct drm_device *dev, struct drm_file *file,
 			  uint32_t ctx_id,
 			  struct drm_i915_context_flag *ctx_flag, int count)
 {
-	return 0;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_context *ctx;
+	int i, ret = 0;
+
+	ctx = i915_context_lookup_id(dev, ctx_id);
+	if (ctx == NULL) {
+		DRM_ERROR("Couldn't find context\n");
+		return -ENXIO;
+	}
+
+	if ((!count || !ctx_flag))
+		goto out;
+
+	for (i = 0; i < count; i++) {
+		struct drm_i915_context_flag *flag = &ctx_flag[i];
+		if (flag->slot >= ctx->slot_count) {
+			DRM_ERROR("Context command for invalid slot\n");
+			continue;
+		}
+		if (flag->command & (flag->command - 1)) {
+			DRM_ERROR("More than one command per context flag is not allowed\n");
+			continue;
+		}
+
+		switch (flag->command) {
+		case I915_CTX_ASSOC_BUF:
+			mutex_lock(&ctx->slot_mtx);
+			if (ctx->bufs[flag->slot] != NULL) {
+				DRM_DEBUG("Overwriting buffer slot without "
+					  "disassociating\n");
+			}
+			obj = drm_gem_object_lookup(dev, file, flag->handle);
+			if (obj == NULL) {
+				DRM_ERROR("Couldn't find object\n");
+				mutex_unlock(&ctx->slot_mtx);
+				continue;
+			}
+			obj_priv = to_intel_bo(obj);
+			if (flag->offset && HAS_PPGTT(dev)) {
+				/* 
+				 * No need to check for overlaps because this is
+				 * in their local GTT so they can only screw up
+				 * themselves. But do check serious violations
+				 */
+				if (flag->offset + obj->size >= 1ULL << 40) {
+					mutex_unlock(&ctx->slot_mtx);
+					continue;
+				}
+				obj_priv->ppgtt_offset = flag->offset | PPGTT_USER_DEFINED;
+			} else
+				obj_priv->ppgtt_offset = PPGTT_NEEDS_RELOC;
+
+			ctx->bufs[flag->slot] = obj;
+			mutex_unlock(&ctx->slot_mtx);
+			break;
+		case I915_CTX_DISASSOC_BUF:
+			mutex_lock(&ctx->slot_mtx);
+			ctx->bufs[flag->slot] = NULL;
+			mutex_unlock(&ctx->slot_mtx);
+			break;
+		case I915_CTX_DOMAIN_BUF:
+			DRM_ERROR("Changing domains is not yet supported\n");
+			break;
+		default:
+			DRM_ERROR("Unknown slot command\n");
+		}
+	}
+
+out:
+	mutex_lock(&ctx->slot_mtx);
+	/* Go through all slots to make sure everything is sane. */
+	for (i = 0; i < ctx->slot_count; i++) {
+		uint64_t ppgtt_offset;
+		if (ctx->bufs[i] == NULL)
+			continue;
+		obj_priv = to_intel_bo(ctx->bufs[i]);
+		if (obj_priv->ppgtt_offset == PPGTT_NEEDS_RELOC)
+			continue;
+
+		ppgtt_offset = PPGTT_ADDR(obj_priv->ppgtt_offset);
+		if (PPGTT_PINNED(obj_priv->ppgtt_offset) &&
+		    ppgtt_offset != obj_priv->gtt_offset) {
+			DRM_DEBUG_DRIVER("Context associated buffer has moved"
+					 " %p->%p\n",
+					 ppgtt_offset, obj_priv->gtt_offset);
+			ret = -EIO;
+			break;
+		}
+	}
+
+	mutex_unlock(&ctx->slot_mtx);
+	return ret;
 }
+
+void i915_context_handle_binding(struct drm_i915_gem_object *obj)
+{
+	if (obj->ppgtt_offset == PPGTT_NEEDS_RELOC) {
+		obj->ppgtt_offset = obj->gtt_offset;
+		obj->ppgtt_offset |= PPGTT_RELOCATED;
+	}
+}
+
+
 /**
  * i915_context_alloc_backing_obj - Allocate and pin space in the global GTT for
  * use by the HW to save, and restore context information.
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 48d4e6f..3105fd6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -851,6 +851,8 @@ struct drm_i915_gem_object {
 	 * reaches 0, dev_priv->pending_flip_queue will be woken up.
 	 */
 	atomic_t pending_flip;
+
+	uint64_t ppgtt_offset;
 };
 
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
@@ -1328,6 +1330,7 @@ extern int i915_context_validate(struct drm_device *dev,
 				 struct drm_file *file, uint32_t ctx_id,
 				 struct drm_i915_context_flag *ctx_flag,
 				 int count);
+extern void i915_context_handle_binding(struct drm_i915_gem_object *obj);
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a60996d..1051b1e 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -589,6 +589,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 			}
 
 			entry->offset = obj->gtt_offset;
+			i915_context_handle_binding(obj);
 		}
 
 		/* Decrement pin count for bound objects */
@@ -991,6 +992,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	struct intel_ring_buffer *ring;
 	u32 exec_start, exec_len;
 	u32 seqno;
+	u32 ctx_id;
 	int ret, mode, i;
 
 	if (!i915_gem_check_execbuffer(args)) {
@@ -1001,11 +1003,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	ret = validate_exec_list(exec, args->buffer_count);
 	if (ret)
 		return ret;
-	if (ctx_flags) {
-		ret = i915_context_validate(dev, file, EXECBUFFER2_CTX_ID(args),
+
+	ctx_id = EXECBUFFER2_CTX_ID(args);
+	if (ctx_id) {
+		ret = i915_context_validate(dev, file, ctx_id,
 					    ctx_flags, flag_count);
 		if (ret) {
-			if (ret == -EAGAIN)
+			if (ret == -EIO)
 				DRM_DEBUG_DRIVER("Context resubmission required\n");
 			return ret;
 		}
@@ -1370,7 +1374,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 		return -EFAULT;
 	}
 	if (EXECBUFFER2_FLAGS_PTR(args) && EXECBUFFER2_FLAGS_COUNT(argc)) {
-		flag_count = EXECBUFFER2_FLAGS_COUNT(argc);
+		flag_count = EXECBUFFER2_FLAGS_COUNT(args);
 		flags = drm_malloc_ab(sizeof(*flags), flag_count);
 		if (flags == NULL) {
 			DRM_ERROR("allocation of flags failed\n");
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 0ebce11..dbd0332 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -669,8 +669,9 @@ struct drm_i915_context_flag {
 	__u64 offset;
 	__u32 read_domain;
 	__u32 write_domain;
-#define I915_CTX_ASSOC_BUF (1 << 0)
-#define I915_CTX_DISASSOC_BUF (1 << 1)
+#define I915_CTX_ASSOC_BUF	(1 << 0)
+#define I915_CTX_DISASSOC_BUF	(1 << 1)
+#define I915_CTX_DOMAIN_BUF	(1 << 2)
 	__u32 command;
 };
 
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 6/9] drm/i915/context: minimal support for contexts in execbuffer2
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

This change doesn't do anything except take parameters from clients
for context flag information, and pass it to a stubbed function to
validate the context flag information.

Included here are the updates to the necessary functions and structures
needed to handle contexts when execbuffer is called. It seems we are
able to reuse the rsvd1 and rsvd2 fields and not need a new ioctl for
this.

Renamed ctx to context in many places to avoid confusion with drm
contexts which seem unrelated.
---
 drivers/gpu/drm/i915/i915_context.c        |   11 +++++--
 drivers/gpu/drm/i915/i915_drv.h            |    5 +++
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   45 +++++++++++++++++++++++++--
 include/drm/i915_drm.h                     |   15 +++++++++
 4 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index 90b7bf3..a486a9c 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -59,14 +59,19 @@ i915_context_lookup_id(struct drm_device *dev,
 	return idr_find(&dev_priv->i915_ctx_idr, id);
 }
 
-static void
-i915_context_del_id(struct drm_device *dev,
-		    struct drm_i915_gem_context *ctx)
+static void i915_context_del_id(struct drm_device *dev,
+				struct drm_i915_gem_context *ctx)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	idr_remove(&dev_priv->i915_ctx_idr, ctx->ctx_id);
 }
 
+int i915_context_validate(struct drm_device *dev, struct drm_file *file,
+			  uint32_t ctx_id,
+			  struct drm_i915_context_flag *ctx_flag, int count)
+{
+	return 0;
+}
 /**
  * i915_context_alloc_backing_obj - Allocate and pin space in the global GTT for
  * use by the HW to save, and restore context information.
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 695a0bf..48d4e6f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1323,6 +1323,11 @@ extern void intel_display_print_error_state(struct seq_file *m,
 extern void i915_context_init(struct drm_device *dev);
 extern void i915_context_deinit(struct drm_device *dev);
 extern void i915_context_close(struct drm_device *dev, struct drm_file *file);
+struct drm_i915_context_flag;
+extern int i915_context_validate(struct drm_device *dev,
+				 struct drm_file *file, uint32_t ctx_id,
+				 struct drm_i915_context_flag *ctx_flag,
+				 int count);
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d2f445e..a60996d 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -979,7 +979,9 @@ static int
 i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		       struct drm_file *file,
 		       struct drm_i915_gem_execbuffer2 *args,
-		       struct drm_i915_gem_exec_object2 *exec)
+		       struct drm_i915_gem_exec_object2 *exec,
+		       struct drm_i915_context_flag *ctx_flags,
+		       int flag_count)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head objects;
@@ -999,7 +1001,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	ret = validate_exec_list(exec, args->buffer_count);
 	if (ret)
 		return ret;
-
+	if (ctx_flags) {
+		ret = i915_context_validate(dev, file, EXECBUFFER2_CTX_ID(args),
+					    ctx_flags, flag_count);
+		if (ret) {
+			if (ret == -EAGAIN)
+				DRM_DEBUG_DRIVER("Context resubmission required\n");
+			return ret;
+		}
+	}
 #if WATCH_EXEC
 	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
 		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
@@ -1299,7 +1309,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 	exec2.cliprects_ptr = args->cliprects_ptr;
 	exec2.flags = I915_EXEC_RENDER;
 
-	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
+	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list,
+				     NULL, 0);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
 		for (i = 0; i < args->buffer_count; i++)
@@ -1328,6 +1339,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 {
 	struct drm_i915_gem_execbuffer2 *args = data;
 	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+	struct drm_i915_context_flag *flags = NULL;
+	uint32_t flag_count = 0;
 	int ret;
 
 #if WATCH_EXEC
@@ -1356,8 +1369,32 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 		drm_free_large(exec2_list);
 		return -EFAULT;
 	}
+	if (EXECBUFFER2_FLAGS_PTR(args) && EXECBUFFER2_FLAGS_COUNT(argc)) {
+		flag_count = EXECBUFFER2_FLAGS_COUNT(argc);
+		flags = drm_malloc_ab(sizeof(*flags), flag_count);
+		if (flags == NULL) {
+			DRM_ERROR("allocation of flags failed\n");
+			drm_free_large(exec2_list);
+			/*  return -EAGAIN; */
+			return -ENOMEM;
+		}
 
-	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
+		ret = copy_from_user(flags,
+				     (struct drm_context_flags __user *)
+				     (uintptr_t)EXECBUFFER2_FLAGS_PTR(args),
+				     sizeof(*flags) * flag_count);
+		if (ret != 0) {
+			DRM_ERROR("copy %d flags failed %d\n",
+				  flag_count, ret);
+			drm_free_large(flags);
+			drm_free_large(exec2_list);
+			return -EFAULT;
+		}
+		ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list,
+					     flags, flag_count);
+	} else
+		ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list,
+					     NULL, 0);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
 		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 58c4482..0ebce11 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -659,6 +659,21 @@ struct drm_i915_gem_execbuffer2 {
 	__u64 rsvd2;
 };
 
+#define EXECBUFFER2_FLAGS_PTR(exec2) (exec2->rsvd1)
+#define EXECBUFFER2_FLAGS_COUNT(exec2)  ((uint32_t)(args->rsvd2>>32))
+#define EXECBUFFER2_CTX_ID(exec2) ((uint32_t)args->rsvd2 )
+
+struct drm_i915_context_flag {
+	__u8 slot;
+	__u32 handle;
+	__u64 offset;
+	__u32 read_domain;
+	__u32 write_domain;
+#define I915_CTX_ASSOC_BUF (1 << 0)
+#define I915_CTX_DISASSOC_BUF (1 << 1)
+	__u32 command;
+};
+
 struct drm_i915_gem_pin {
 	/** Handle of the buffer to be pinned. */
 	__u32 handle;
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 5/9] drm/i915/context: switch context support query to variable
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

---
 drivers/gpu/drm/i915/i915_dma.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index b0acc0d..9d055ba 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -772,7 +772,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
 		value = INTEL_INFO(dev)->gen >= 4;
 		break;
 	case I915_PARAM_HAS_CONTEXTS:
-		value = HAS_HW_CONTEXTS(dev);
+		value = dev_priv->ctx_disable ? 0 : 1;
 		break;
 	case I915_PARAM_HAS_PPGTT:
 		value = HAS_PPGTT(dev);
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 4/9] drm/i915/context: whitespace cleanup, and warning cleanup
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

---
 drivers/gpu/drm/i915/i915_context.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index 4e19636..90b7bf3 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -115,6 +115,7 @@ err_unref:
 	mutex_unlock(&dev->struct_mutex);
 	return NULL;
 }
+
 /**
  * i915_context_hw_init - Create a valid context for the given object
  * on the specified ring. This may need to be hardware dependent in the future,
@@ -315,12 +316,14 @@ void i915_context_init(struct drm_device *dev)
 	}
 }
 
+static int warn_idr_cleanup = 0;
+
 static
 int i915_context_idr_cleanup(int id, void *p, void *data)
 {
 	struct drm_device *dev = (struct drm_device *)data;
 	struct drm_i915_gem_context *ctx = (struct drm_i915_gem_context *)p;
-	DRM_DEBUG_DRIVER("Destroying abandoned context %d\n", ctx->ctx_id);
+	WARN_ON_ONCE(warn_idr_cleanup);
 	do_context_destroy(dev, ctx);
 	return 0;
 }
@@ -333,8 +336,10 @@ void i915_context_deinit(struct drm_device *dev)
 
 	i915_destroy_hw_context(dev, dev_priv->default_context);
 	spin_lock(&dev_priv->i915_ctx_lock);
+	warn_idr_cleanup=1;
 	idr_for_each(&dev_priv->i915_ctx_idr, i915_context_idr_cleanup, dev);
 	idr_remove_all(&dev_priv->i915_ctx_idr);
 	idr_destroy(&dev_priv->i915_ctx_idr);
+	warn_idr_cleanup=0;
 	spin_unlock(&dev_priv->i915_ctx_lock);
 }
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 3/9] drm/i915/context: context initialization/destruction
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

This does most of the work needed to create, destroy, and cleanup-after
contexts, but does not have the actual code to the do the context
switching, or buffer association.  This includes context id/name
generation, context object allocation, calls hardware initialization
functions, ringbuffer API for context switch, as well as calls from
upper layers on init/deinit, and drm file close and open.
---
 drivers/gpu/drm/i915/i915_context.c     |  273 ++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_dma.c         |   10 +-
 drivers/gpu/drm/i915/i915_drv.h         |   11 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c |   14 ++-
 drivers/gpu/drm/i915/intel_ringbuffer.h |    7 +
 5 files changed, 286 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index 0d140b8..4e19636 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -29,8 +29,30 @@
 #include "i915_drm.h"
 #include "intel_drv.h"
 
+static int
+i915_context_gen_id(struct drm_i915_private *dev_priv,
+		    struct drm_i915_gem_context *ctx)
+{
+	int ret, id;
+again:
+	if (idr_pre_get(&dev_priv->i915_ctx_idr, GFP_KERNEL) == 0) {
+		return -ENOMEM;
+	}
+
+	spin_lock(&dev_priv->i915_ctx_lock);
+	/*  Don't start at 0 to make finding non-context users easier */
+	ret = idr_get_new_above(&dev_priv->i915_ctx_idr, ctx, 1, &id);
+	if (ret == -EAGAIN) {
+		spin_unlock(&dev_priv->i915_ctx_lock);
+		goto again;
+	}
+	spin_unlock(&dev_priv->i915_ctx_lock);
+
+	return id;
+}
+
 static struct drm_i915_gem_context *
-i915_gem_lookup_ctx_id(struct drm_device *dev,
+i915_context_lookup_id(struct drm_device *dev,
 		       uint32_t id)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -38,23 +60,169 @@ i915_gem_lookup_ctx_id(struct drm_device *dev,
 }
 
 static void
-i915_gem_del_ctx_id(struct drm_device *dev,
+i915_context_del_id(struct drm_device *dev,
 		    struct drm_i915_gem_context *ctx)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	idr_remove(&dev_priv->i915_ctx_idr, ctx->ctx_id);
 }
 
-int
-i915_gem_alloc_hw_context(struct drm_device *dev,
+/**
+ * i915_context_alloc_backing_obj - Allocate and pin space in the global GTT for
+ * use by the HW to save, and restore context information.
+ */
+static struct drm_gem_object *
+i915_context_alloc_backing_obj(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj;
+	int ret;
+	size_t size = dev_priv->ctx_size;
+	if (!size) {
+		/*  XXX size is HW specific, this needs to be fixed!! */
+		size = 4096;
+		dev_priv->ctx_size = size;
+	}
+
+	obj = i915_gem_alloc_object(dev, size);
+
+	if (!obj) {
+		DRM_DEBUG("Failed to allocate context\n");
+		return NULL;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+
+	ret = i915_gem_object_pin(obj, 0x1000, false);
+	if (ret) {
+		DRM_ERROR("Failed to pin context: %d\n", ret);
+		goto err_unref;
+	}
+
+	ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+	if (ret) {
+		DRM_ERROR("failed to set domain on context: %d\n", ret);
+		goto err_unpin;
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	return &obj->base;
+
+err_unpin:
+	i915_gem_object_unpin(obj);
+err_unref:
+	drm_gem_object_unreference(&obj->base);
+	mutex_unlock(&dev->struct_mutex);
+	return NULL;
+}
+/**
+ * i915_context_hw_init - Create a valid context for the given object
+ * on the specified ring. This may need to be hardware dependent in the future,
+ * but for now just creates a CCID for the context, saves state, and then
+ * restores that stte.
+ * @dev: drm
+ * @obj: object where the context will be stored.
+ * @ring: ring to submit commands to. Render ring only for now.
+ */
+static void i915_context_hw_init(struct drm_device *dev,
+				 struct drm_i915_gem_context *ctx,
+				 struct intel_ring_buffer *ring)
+{
+	if (ring->context_switch == NULL)
+		return;
+
+	mutex_lock(&dev->struct_mutex);
+	if (intel_ring_begin(ring, 2)) {
+		mutex_unlock(&dev->struct_mutex);
+		return;
+	}
+	intel_ring_emit(ring, MI_FLUSH);
+	intel_ring_emit(ring, MI_NOOP | (1 << 22) | ctx->ctx_id);
+	intel_ring_advance(ring);
+	ring->context_switch(ring, ctx, I915_CONTEXT_SAVE_ONLY);
+	ring->context_switch(ring, ctx, I915_CONTEXT_NORMAL_SWITCH);
+	mutex_unlock(&dev->struct_mutex);
+}
+
+static void i915_context_hw_deinit(struct drm_device *dev,
+				   struct drm_i915_gem_context *ctx,
+				   struct intel_ring_buffer *ring)
+{
+	/* XXX We can prevent restoring contexts, but not saving them
+	 * so if we're going to take away our backing context object
+	 * of the last context, we have to switch now.
+	 */
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (ring->last_context == ctx && ctx != dev_priv->default_context) {
+		mutex_lock(&dev->struct_mutex);
+		ring->context_switch(ring, dev_priv->default_context,
+				     I915_CONTEXT_NORMAL_SWITCH);
+		mutex_unlock(&dev->struct_mutex);
+	}
+}
+
+static int
+i915_alloc_hw_context(struct drm_device *dev,
 			  uint64_t aperture_size,
 			  struct drm_i915_gem_context **ctx_out)
 {
-	return -ENOMEM;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_context *ctx;
+	int ret = 0;
+
+	ctx = kzalloc(sizeof(struct drm_i915_gem_context), GFP_KERNEL);
+	if (ctx == NULL)
+		return -ENOMEM;
+
+	ctx->ctx_id = i915_context_gen_id(dev_priv, ctx);
+	if (ctx->ctx_id < 0) {
+		ret = ctx->ctx_id;
+		goto out;
+	}
+
+	ctx->ctx_obj = i915_context_alloc_backing_obj(dev);
+	if (ctx->ctx_obj == NULL) {
+		ret = -ENOMEM;
+		goto id_out;
+	}
+
+	if (!aperture_size)
+		aperture_size = 256 << 20;
+	ctx->aperture_size_mb = aperture_size >> 20;
+
+	i915_context_hw_init(dev, ctx, &dev_priv->ring[RCS]);
+
+	mutex_init(&ctx->slot_mtx);
+	INIT_LIST_HEAD(&ctx->context_list);
+	INIT_LIST_HEAD(&ctx->file_list);
+
+	*ctx_out = ctx;
+	return ret;
+
+id_out:
+	i915_context_del_id(dev, ctx);
+out:
+	kfree(ctx);
+	return ret;
+}
+
+/**
+ * Destroy everything associated with a context but does not free the context's
+ * memory.
+ */
+static int
+i915_destroy_hw_context(struct drm_device *dev,
+		        struct drm_i915_gem_context *ctx)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	i915_context_hw_deinit(dev, ctx, (&dev_priv->ring[RCS]));
+	i915_gem_free_object(ctx->ctx_obj);
+	i915_context_del_id(dev, ctx);
+	return 0;
 }
 
 int
-i915_gem_ctx_create_ioctl(struct drm_device *dev, void *data,
+i915_context_create_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *file)
 {
 	struct drm_i915_gem_ctx_create *args = data;
@@ -63,19 +231,22 @@ i915_gem_ctx_create_ioctl(struct drm_device *dev, void *data,
 	int slots = args->slot_count;
 	int i, ret = 0;
 
-	/* TODO: sanitize aperture_size*/
-	ret = i915_gem_alloc_hw_context(dev, args->aperture_size, &ctx);
+	if(args->aperture_size & (args->aperture_size - 1))
+		return -EINVAL;
+
+	ret = i915_alloc_hw_context(dev, args->aperture_size, &ctx);
 	if (ret) {
-		goto out;
+		DRM_DEBUG_DRIVER("Couldn't allocate a HW context\n");
+		return -ENOMEM;
 	}
 
 	ctx->bufs = drm_malloc_ab(slots + 1, sizeof(struct drm_gem_object*));
 	if (ctx->bufs == NULL) {
+		i915_destroy_hw_context(dev, ctx);
 		kfree(ctx);
-		drm_free_large(ctx->bufs);
-		ret = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
+
 	ctx->slot_count = slots;
 	for(i = 0; i < slots + 1; i++) {
 		ctx->bufs[i] = NULL;
@@ -84,30 +255,86 @@ i915_gem_ctx_create_ioctl(struct drm_device *dev, void *data,
 	list_add(&ctx->file_list, &file_priv->context.context_list);
 
 	args->ctx_id = ctx->ctx_id;
-out:
+
 	return ret;
 }
 
+static int
+do_context_destroy(struct drm_device *dev, struct drm_i915_gem_context *ctx)
+{
+	list_del(&ctx->file_list);
+	drm_free_large(ctx->bufs);
+	i915_destroy_hw_context(dev, ctx);
+	kfree(ctx);
+	return 0;
+}
+
 int
-i915_gem_ctx_destroy_ioctl(struct drm_device *dev, void *data,
+i915_context_destroy_ioctl(struct drm_device *dev, void *data,
 			   struct drm_file *file)
 {
 	struct drm_i915_gem_ctx_destroy *args = data;
-	struct drm_i915_gem_context *ctx, *ctx_temp;
-	struct list_head *pos, *n;
-	struct drm_i915_file_private *file_priv = file->driver_priv;
+	struct drm_i915_gem_context *ctx;
 
-	ctx = i915_gem_lookup_ctx_id(dev, args->ctx_id);
+	ctx = i915_context_lookup_id(dev, args->ctx_id);
 	if (ctx == NULL) {
 		return -EINVAL;
 	}
+	return do_context_destroy(dev, ctx);
+}
 
-	list_for_each_safe(pos, n, &file_priv->context.context_list) {
-		ctx_temp = list_entry(pos, struct drm_i915_gem_context, context_list);
+void i915_context_close(struct drm_device *dev, struct drm_file *file)
+{
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+	struct drm_i915_gem_context *ctx, *next;
+	list_for_each_entry_safe(ctx, next, &file_priv->context.context_list,
+		file_list) {
+		do_context_destroy(dev, ctx);
 	}
-	i915_gem_del_ctx_id(dev, ctx);
-	kfree(ctx);
+}
 
-	/* TODO: ring switch may be needed */
+void i915_context_init(struct drm_device *dev)
+{
+	int ret;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (!HAS_HW_CONTEXTS(dev)) {
+		DRM_DEBUG_DRIVER("Context support disabled, device does not support\n");
+		dev_priv->ctx_disable = 1;
+		return;
+	}
+
+	idr_init(&dev_priv->i915_ctx_idr);
+	spin_lock_init(&dev_priv->i915_ctx_lock);
+	ret = i915_alloc_hw_context(dev, 0, &dev_priv->default_context);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Context support disabled [%d]\n", ret);
+		dev_priv->ctx_disable = 1;
+		idr_destroy(&dev_priv->i915_ctx_idr);
+	} else {
+		DRM_DEBUG_DRIVER("Context support enabled\n", ret);
+	}
+}
+
+static
+int i915_context_idr_cleanup(int id, void *p, void *data)
+{
+	struct drm_device *dev = (struct drm_device *)data;
+	struct drm_i915_gem_context *ctx = (struct drm_i915_gem_context *)p;
+	DRM_DEBUG_DRIVER("Destroying abandoned context %d\n", ctx->ctx_id);
+	do_context_destroy(dev, ctx);
 	return 0;
 }
+
+void i915_context_deinit(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (dev_priv->ctx_disable)
+		return;
+
+	i915_destroy_hw_context(dev, dev_priv->default_context);
+	spin_lock(&dev_priv->i915_ctx_lock);
+	idr_for_each(&dev_priv->i915_ctx_idr, i915_context_idr_cleanup, dev);
+	idr_remove_all(&dev_priv->i915_ctx_idr);
+	idr_destroy(&dev_priv->i915_ctx_idr);
+	spin_unlock(&dev_priv->i915_ctx_lock);
+}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index f314b0f..b0acc0d 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -2041,6 +2041,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	ips_ping_for_i915_load();
 
+	i915_context_init(dev);
 	return 0;
 
 out_gem_unload:
@@ -2066,6 +2067,8 @@ int i915_driver_unload(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	i915_context_deinit(dev);
+
 	spin_lock(&mchdev_lock);
 	i915_mch_dev = NULL;
 	spin_unlock(&mchdev_lock);
@@ -2165,6 +2168,8 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
 
 	spin_lock_init(&file_priv->mm.lock);
 	INIT_LIST_HEAD(&file_priv->mm.request_list);
+	mutex_init(&file_priv->context.mtx);
+	INIT_LIST_HEAD(&file_priv->context.context_list);
 
 	return 0;
 }
@@ -2203,6 +2208,7 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	i915_gem_release(dev, file_priv);
+	i915_context_close(dev, file_priv);
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_mem_release(dev, file_priv, dev_priv->agp_heap);
 }
@@ -2255,8 +2261,8 @@ struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I915_GEM_CTX_CREATE, i915_gem_ctx_create_ioctl, DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I915_GEM_CTX_DESTROY, i915_gem_ctx_destroy_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GEM_CTX_CREATE, i915_context_create_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GEM_CTX_DESTROY, i915_context_destroy_ioctl, DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 60aec8f..695a0bf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -282,7 +282,7 @@ typedef struct drm_i915_private {
 
 	/** Device specific context info */
 	uint32_t ctx_size;
-	struct drm_i915_gem_context *default_ctx;
+	struct drm_i915_gem_context *default_context;
 	struct spinlock i915_ctx_lock;
 	struct idr i915_ctx_idr;
 	bool ctx_disable;
@@ -1123,9 +1123,9 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
-int i915_gem_ctx_create_ioctl(struct drm_device *dev, void *data,
+int i915_context_create_ioctl(struct drm_device *dev, void *data,
 			      struct drm_file *file);
-int i915_gem_ctx_destroy_ioctl(struct drm_device *dev, void *data,
+int i915_context_destroy_ioctl(struct drm_device *dev, void *data,
 			       struct drm_file *file);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_init_object(struct drm_gem_object *obj);
@@ -1319,6 +1319,11 @@ extern void intel_display_print_error_state(struct seq_file *m,
 					    struct intel_display_error_state *error);
 #endif
 
+/* context */
+extern void i915_context_init(struct drm_device *dev);
+extern void i915_context_deinit(struct drm_device *dev);
+extern void i915_context_close(struct drm_device *dev, struct drm_file *file);
+
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
 #define BEGIN_LP_RING(n) \
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6218fa9..89adb9d 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -750,6 +750,17 @@ render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 	return 0;
 }
 
+static void
+render_ring_ctx_switch(struct intel_ring_buffer *ring,
+		       struct drm_i915_gem_context *ctx,
+		       uint32_t flags)
+{
+	if (ring->last_context == ctx)
+		return;
+
+	ring->last_context = ctx;
+}
+
 static void cleanup_status_page(struct intel_ring_buffer *ring)
 {
 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
@@ -1015,7 +1026,8 @@ static const struct intel_ring_buffer render_ring = {
 	.irq_get		= render_ring_get_irq,
 	.irq_put		= render_ring_put_irq,
 	.dispatch_execbuffer	= render_ring_dispatch_execbuffer,
-       .cleanup			= render_ring_cleanup,
+	.cleanup		= render_ring_cleanup,
+	.context_switch		= render_ring_ctx_switch,
 };
 
 /* ring buffer for bit-stream decoder */
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 6d6fde8..68ebecf 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -35,6 +35,9 @@ struct  intel_hw_status_page {
 #define I915_READ_SYNC_0(ring) I915_RING_READ(RING_SYNC_0((ring)->mmio_base))
 #define I915_READ_SYNC_1(ring) I915_RING_READ(RING_SYNC_1((ring)->mmio_base))
 
+#define I915_CONTEXT_NORMAL_SWITCH	0
+#define I915_CONTEXT_SAVE_ONLY		1
+
 struct  intel_ring_buffer {
 	const char	*name;
 	enum intel_ring_id {
@@ -76,6 +79,10 @@ struct  intel_ring_buffer {
 	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,
 					       u32 offset, u32 length);
 	void		(*cleanup)(struct intel_ring_buffer *ring);
+	struct		drm_i915_gem_context *last_context;
+	void		(*context_switch)(struct intel_ring_buffer *ring,
+					  struct drm_i915_gem_context *ctx,
+					  uint32_t flags);
 
 	/**
 	 * List of objects currently involved in rendering from the
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 2/9] drm/i915/context: basic implementation context ioctls
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 9461 bytes --]

Added the minimal amount of code to enable the two ioctls used for
creating and destroying contexts. Also added neccessary information in
the structures to implement some basic operations the ioctls will have
to perform.

A small whitespace fixup in the Makefile also made it in here.
---
 drivers/gpu/drm/i915/Makefile       |    3 +-
 drivers/gpu/drm/i915/i915_context.c |  113 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_dma.c     |    2 +
 drivers/gpu/drm/i915/i915_drv.h     |   34 +++++++++++
 include/drm/i915_drm.h              |   15 +++++
 5 files changed, 166 insertions(+), 1 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/i915_context.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 0ae6a7c..244536a 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -5,13 +5,14 @@
 ccflags-y := -Iinclude/drm
 i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
 	  i915_debugfs.o \
-          i915_suspend.o \
+	  i915_suspend.o \
 	  i915_gem.o \
 	  i915_gem_debug.o \
 	  i915_gem_evict.o \
 	  i915_gem_execbuffer.o \
 	  i915_gem_gtt.o \
 	  i915_gem_tiling.o \
+	  i915_context.o \
 	  i915_trace_points.o \
 	  intel_display.o \
 	  intel_crt.o \
diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
new file mode 100644
index 0000000..0d140b8
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "intel_drv.h"
+
+static struct drm_i915_gem_context *
+i915_gem_lookup_ctx_id(struct drm_device *dev,
+		       uint32_t id)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	return idr_find(&dev_priv->i915_ctx_idr, id);
+}
+
+static void
+i915_gem_del_ctx_id(struct drm_device *dev,
+		    struct drm_i915_gem_context *ctx)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	idr_remove(&dev_priv->i915_ctx_idr, ctx->ctx_id);
+}
+
+int
+i915_gem_alloc_hw_context(struct drm_device *dev,
+			  uint64_t aperture_size,
+			  struct drm_i915_gem_context **ctx_out)
+{
+	return -ENOMEM;
+}
+
+int
+i915_gem_ctx_create_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file)
+{
+	struct drm_i915_gem_ctx_create *args = data;
+	struct drm_i915_gem_context *ctx = NULL;
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+	int slots = args->slot_count;
+	int i, ret = 0;
+
+	/* TODO: sanitize aperture_size*/
+	ret = i915_gem_alloc_hw_context(dev, args->aperture_size, &ctx);
+	if (ret) {
+		goto out;
+	}
+
+	ctx->bufs = drm_malloc_ab(slots + 1, sizeof(struct drm_gem_object*));
+	if (ctx->bufs == NULL) {
+		kfree(ctx);
+		drm_free_large(ctx->bufs);
+		ret = -ENOMEM;
+		goto out;
+	}
+	ctx->slot_count = slots;
+	for(i = 0; i < slots + 1; i++) {
+		ctx->bufs[i] = NULL;
+	}
+
+	list_add(&ctx->file_list, &file_priv->context.context_list);
+
+	args->ctx_id = ctx->ctx_id;
+out:
+	return ret;
+}
+
+int
+i915_gem_ctx_destroy_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file)
+{
+	struct drm_i915_gem_ctx_destroy *args = data;
+	struct drm_i915_gem_context *ctx, *ctx_temp;
+	struct list_head *pos, *n;
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+
+	ctx = i915_gem_lookup_ctx_id(dev, args->ctx_id);
+	if (ctx == NULL) {
+		return -EINVAL;
+	}
+
+	list_for_each_safe(pos, n, &file_priv->context.context_list) {
+		ctx_temp = list_entry(pos, struct drm_i915_gem_context, context_list);
+	}
+	i915_gem_del_ctx_id(dev, ctx);
+	kfree(ctx);
+
+	/* TODO: ring switch may be needed */
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index bbaf60c..f314b0f 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -2255,6 +2255,8 @@ struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GEM_CTX_CREATE, i915_gem_ctx_create_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GEM_CTX_DESTROY, i915_gem_ctx_destroy_ioctl, DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index caf0a28..60aec8f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -280,6 +280,13 @@ typedef struct drm_i915_private {
 	struct drm_i915_gem_object *pwrctx;
 	struct drm_i915_gem_object *renderctx;
 
+	/** Device specific context info */
+	uint32_t ctx_size;
+	struct drm_i915_gem_context *default_ctx;
+	struct spinlock i915_ctx_lock;
+	struct idr i915_ctx_idr;
+	bool ctx_disable;
+
 	struct resource mch_res;
 
 	unsigned int cpp;
@@ -848,6 +855,25 @@ struct drm_i915_gem_object {
 
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
 
+struct drm_i915_gem_context {
+	int ctx_id;
+	/** Pinned buffer for the HW context */
+	struct drm_gem_object *ctx_obj;
+	uint32_t aperture_size_mb;
+
+	/** TODO: rw lock? */
+	struct mutex slot_mtx;
+	struct drm_gem_object **bufs;
+	int slot_count;
+
+	/** This object's place on the per bo context list */
+	struct list_head context_list;
+
+	/** This object's place no the per file context list */
+	struct list_head file_list;
+};
+
+
 /**
  * Request queue structure.
  *
@@ -881,6 +907,10 @@ struct drm_i915_file_private {
 		struct spinlock lock;
 		struct list_head request_list;
 	} mm;
+	struct {
+		struct mutex mtx;
+		struct list_head context_list;
+	} context;
 };
 
 enum intel_chip_family {
@@ -1093,6 +1123,10 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+int i915_gem_ctx_create_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file);
+int i915_gem_ctx_destroy_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_init_object(struct drm_gem_object *obj);
 int __must_check i915_gem_flush_ring(struct drm_device *dev,
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 26759a8..58c4482 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_OVERLAY_PUT_IMAGE	0x27
 #define DRM_I915_OVERLAY_ATTRS	0x28
 #define DRM_I915_GEM_EXECBUFFER2	0x29
+#define DRM_I915_GEM_CTX_CREATE		0x2a
+#define DRM_I915_GEM_CTX_DESTROY	0x2b
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -239,6 +241,9 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_MADVISE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
 #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE	DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
 #define DRM_IOCTL_I915_OVERLAY_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
+#define DRM_IOCTL_I915_GEM_CTX_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CTX_CREATE, struct drm_i915_gem_ctx_create)
+#define DRM_IOCTL_I915_GEM_CTX_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CTX_DESTROY, struct drm_i915_gem_ctx_destroy)
+
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -845,4 +850,14 @@ struct drm_intel_overlay_attrs {
 	__u32 gamma5;
 };
 
+struct drm_i915_gem_ctx_create {
+	__s32 slot_count;
+	__u64 aperture_size;
+	__u32 ctx_id;
+};
+
+struct drm_i915_gem_ctx_destroy {
+	__u32 ctx_id;
+};
+
 #endif				/* _I915_DRM_H_ */
-- 
1.7.3.4


[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related

* [PATCH 1/9] drm/i915/context: context switch, and PPGTT params
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx
In-Reply-To: <1296584186-20446-1-git-send-email-bwidawsk@gmail.com>

Adding parameters for userspace to query what features the
driver/hardware supports. In the future context and ppgtt will always go
together, but for now we will use hardware contexts without ppgtt since
there are some issues with ppgtt on the current generation.
---
 drivers/gpu/drm/i915/i915_dma.c |    6 ++++++
 drivers/gpu/drm/i915/i915_drv.h |    3 +++
 include/drm/i915_drm.h          |    2 ++
 3 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 17bd766..bbaf60c 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -771,6 +771,12 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_EXEC_CONSTANTS:
 		value = INTEL_INFO(dev)->gen >= 4;
 		break;
+	case I915_PARAM_HAS_CONTEXTS:
+		value = HAS_HW_CONTEXTS(dev);
+		break;
+	case I915_PARAM_HAS_PPGTT:
+		value = HAS_PPGTT(dev);
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a0149c6..caf0a28 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -950,6 +950,9 @@ enum intel_chip_family {
 #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
 #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
 
+#define HAS_HW_CONTEXTS(dev)	(INTEL_INFO(dev)->gen >= 4)
+#define HAS_PPGTT(dev)		(INTEL_INFO(dev)->gen >= 7)
+
 #include "i915_trace.h"
 
 extern struct drm_ioctl_desc i915_ioctls[];
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 0039f1f..26759a8 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -290,6 +290,8 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_RELAXED_FENCING	 12
 #define I915_PARAM_HAS_COHERENT_RINGS	 13
 #define I915_PARAM_HAS_EXEC_CONSTANTS	 14
+#define I915_PARAM_HAS_CONTEXTS		 15
+#define I915_PARAM_HAS_PPGTT		 16
 
 typedef struct drm_i915_getparam {
 	int param;
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 0/9] drm/1915/context (i915HW Context support, early)
From: Ben Widawsky @ 2011-02-01 18:16 UTC (permalink / raw)
  To: intel-gfx


This patch adds the basic API for HW context manipulation. Right now
only a very basic unit test is passing. I was hoping to get some eyes on
this code while I look into porting some of mesa (and cleaning up my
libdrm patches).

I tried my best to split up the patches logically, but I'm afraid there
are still some fairly large ones.

Ben

^ permalink raw reply

* Re: [PATCH] System Wide Capability Bounding Set
From: Eric Paris @ 2011-02-01 18:17 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Steve Grubb, Andrew G. Morgan, Serge E. Hallyn, linux-kernel,
	linux-security-module
In-Reply-To: <20110128193809.GB8854@localhost>

What are we thinking?  Any suggestions how to do what we need other than

global bounding such that  pP' = gbset & (fI | pI)

Or an interface in which I can force things out of the bset and pI of
other tasks?  Possibly the interface could be specific to the "khelper"
thread?

-Eric


^ permalink raw reply

* Re: [PATCH] perf: Cure task_oncpu_function_call() races
From: Peter Zijlstra @ 2011-02-01 18:18 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Frederic Weisbecker, Ingo Molnar, Alan Stern,
	Arnaldo Carvalho de Melo, Paul Mackerras, Prasad, Roland McGrath,
	linux-kernel
In-Reply-To: <1296583698.26581.279.camel@laptop>

On Tue, 2011-02-01 at 19:08 +0100, Peter Zijlstra wrote:
> > > +static void perf_remove_from_context(struct perf_event *event)
> > >  {
> > > ...
> > >     raw_spin_lock_irq(&ctx->lock);
> > >     /*
> > > +    * If we failed to find a running task, but find it running now that
> > > +    * we've acquired the ctx->lock, retry.
> > >      */
> > > +   if (task_curr(task)) {
> > >             raw_spin_unlock_irq(&ctx->lock);
> > >             goto retry;
> > >     }
> > >
> > >     /*
> > > +    * Since the task isn't running, its safe to remove the event, us
> > > +    * holding the ctx->lock ensures the task won't get scheduled in.
> > >      */
> > > +   list_del_event(event, ctx);
> > 
> > this looks suspicious (the same for perf_install_in_context).
> > 
> > Unlike the IPI handler, this can see schedule-in-progress in any state.
> > In particular, we can see rq->curr == next (so that task_curr() == F),
> > but before "prev" has already called perf_event_task_sched_out().
> > 
> > So we have to check ctx->is_active, or schedule() should change rq->curr
> > after perf_event_task_sched_out().
> 
> I only considered current == next in that case, not current == prev, let
> me undo some of those sched.c bits and put a comment. 

On second thought, your proposed ->is_active check seems to result in
much nicer code in sched.c. Let me think through that.


^ permalink raw reply

* Re: Tracking empty directories
From: Ilari Liusvaara @ 2011-02-01 18:15 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: Jonathan Nieder, Jakub Narebski, Dmitry S. Kravtsov, git,
	Shawn Pearce
In-Reply-To: <AANLkTi=u6=mhOd9LFYRy48y41xRcXmYDtktOKoBjjMgO@mail.gmail.com>

On Wed, Feb 02, 2011 at 12:54:35AM +0700, Nguyen Thai Ngoc Duy wrote:
> On Wed, Feb 2, 2011 at 12:28 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:
> 
> Could it be done with an index extension? Interesting.
> 
> > Certainly one ought to register an extension name or bump the version
> > number to avoid confusing gits that don't know about the feature.
> 
> Index extension with lowercase name are "necessary for correct
> operation". Older git will abort on unknown required extensions. If
> you add to the main part of the index, better bump version number.

Worse problem than the index: Tree entries. Those are actually transferable
and IIRC older (current?) git versions don't handle empty subdirectories
(pointing entry of type directory to empty tree hash) all too well...

Worse yet, there isn't easy way to break the tree parser to avoid current
git versions from screwing things up (IIRC, when I tested, invalid octal
numbers finally broke it, invalid file types didn't do the trick)...

-Ilari

^ permalink raw reply

* Re: clients cannot reconnect to mounted nfs shares after server restart
From: J. Bruce Fields @ 2011-02-01 18:15 UTC (permalink / raw)
  To: camden lindsay; +Cc: linux-nfs
In-Reply-To: <AANLkTimA-sCz8LQLu1weh-qQOm30jHYyO3qtxmPDPX98@mail.gmail.com>

On Mon, Jan 31, 2011 at 07:24:30PM -0800, camden lindsay wrote:
> Having an issue i believe is an NFS bug, but would like someone to
> verify as well as... point me the correct direction to submit a bug as
> needed if it indeed is.
> Situation:
> NFS server running
> Client connected with mounted share
> NFS server is shut down -- (halt or /etc/init.d/nfs stop)
> NFS server is turned on (booted or /etc/init.d/nfs start)
> 
> Outcome:
> NFS client that was connected does not reconnect to that share automatically
> NFS client that was connected cannot reconnect via umount then mount again
> No other nfs client can connect to that share, before or after origial

How long have you waited?

> NFS clients attempts to connect/reconnect
> NFS clients CAN connect to a different share.
> Details/logs:
> Server shows that client is authenticating:
> Feb  1 03:01:47 BigBox mountd[6557]: authenticated mount request from
> 192.168.11.49:674 for /mnt/store/public (/mnt/store/public)
> Feb  1 03:01:48 BigBox mountd[6557]: authenticated mount request from
> 192.168.11.49:763 for /mnt/store/public (/mnt/store/public)
> Feb  1 03:01:50 BigBox mountd[6557]: authenticated mount request from
> 192.168.11.49:932 for /mnt/store/public (/mnt/store/public)
> Feb  1 03:01:54 BigBox mountd[6557]: authenticated mount request from
> 192.168.11.49:942 for /mnt/store/public (/mnt/store/public)

A network trace (tcpdump -s0 -wtmp.pcap, then reproduce the problem,
then ^C tcpdump, then send us tmp.pcap) might help.

> 
> Client shows retransmission:
> dylan@shobuntu:~$ sudo mount -v -t nfs bigbox:/mnt/store/public Public/
> mount.nfs: timeout set for Mon Jan 31 19:09:32 2011
> mount.nfs: text-based options: 'addr=192.168.11.10'
> mount.nfs: text-based options: 'addr=192.168.11.10'
> mount.nfs: text-based options: 'addr=192.168.11.10'
> mount.nfs: text-based options: 'addr=192.168.11.10'
> mount.nfs: text-based options: 'addr=192.168.11.10'
> 
> Server Version:
> net-fs/nfs-utils
>       Latest version available: 1.1.4-r1
>       Latest version installed: 1.1.4-r1
>       Size of files: 574 kB
>       Homepage:      http://linux-nfs.org/
>       Description:   NFS client and server daemons
>       License:       GPL-2
> (server is on Gentoo, client on Ubuntu)

Note most of the NFS code is actually in the kernel, so the kernel
version(s) involved would be useful too.

--b.

> Thanks!
> Camden
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [Qemu-devel] [PATCH 1/4] Add config-devices.h again
From: Stefan Weil @ 2011-02-01 18:14 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, Juan Quintela
In-Reply-To: <1296579203-21083-2-git-send-email-ehabkost@redhat.com>

Am 01.02.2011 17:53, schrieb Eduardo Habkost:
> This reverts part of commit a992fe3d0fc185112677286f7a02204d8245b61e.
>
> We do have code that needs #ifdefs depending on the list of enabled devices,
> but currently that code breaks when we try to disable a feature that is enabled
> by default.
>
> For example, if we try to disable CONFIG_VMWARE_VGA, we get the following:
>
>     LINK  x86_64-softmmu/qemu-system-x86_64
>    pc.o: In function `pc_vga_init':
>    /home/ehabkost/pessoal/proj/virt/qemu/qemu/hw/pc.c:991: undefined reference to `pci_vmsvga_init'
>    collect2: ld returned 1 exit status
>    make[1]: *** [qemu-system-x86_64] Error 1
>    rm config-devices.h-timestamp
>    make: *** [subdir-x86_64-softmmu] Error 2
>
> config-devices.h will allow us to add an #ifdef to fix the above error, and
> other similar cases.
>
> Signed-off-by: Eduardo Habkost<ehabkost@redhat.com>
> ---
>   Makefile        |    7 +++++--
>   Makefile.target |    2 +-
>   config.h        |   11 +++++++++++
>   3 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 4e120a2..22b53f6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1,6 +1,6 @@
>   # Makefile for QEMU.
>
> -GENERATED_HEADERS = config-host.h trace.h qemu-options.def
> +GENERATED_HEADERS = config-host.h trace.h qemu-options.def config-all-devices.h
>   ifeq ($(TRACE_BACKEND),dtrace)
>   GENERATED_HEADERS += trace-dtrace.h
>   endif
> @@ -77,6 +77,9 @@ config-host.h-timestamp: config-host.mak
>   qemu-options.def: $(SRC_PATH)/qemu-options.hx
>   	$(call quiet-command,sh $(SRC_PATH)/hxtool -h<  $<  >  $@,"  GEN   $@")
>
> +config-all-devices.h: config-all-devices.h-timestamp
> +config-all-devices.h-timestamp: config-all-devices.mak
> +
>   SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
>
>   subdir-%: $(GENERATED_HEADERS)
> @@ -190,7 +193,7 @@ clean:
>
>   distclean: clean
>   	rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi
> -	rm -f config-all-devices.mak
> +	rm -f config-all-devices.mak config-all-devices.h*
>   	rm -f roms/seabios/config.mak roms/vgabios/config.mak
>   	rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.dvi qemu-doc.fn qemu-doc.info qemu-doc.ky qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp qemu-doc.vr
>   	rm -f qemu-tech.info qemu-tech.aux qemu-tech.cp qemu-tech.dvi qemu-tech.fn qemu-tech.info qemu-tech.ky qemu-tech.log qemu-tech.pdf qemu-tech.pg qemu-tech.toc qemu-tech.tp qemu-tech.vr
> diff --git a/Makefile.target b/Makefile.target
> index 2800f47..03fc486 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -1,6 +1,6 @@
>   # -*- Mode: makefile -*-
>
> -GENERATED_HEADERS = config-target.h
> +GENERATED_HEADERS = config-target.h config-devices.h
>   CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
>
>   include ../config-host.mak
> diff --git a/config.h b/config.h
> index e20f786..07d79d4 100644
> --- a/config.h
> +++ b/config.h
> @@ -1,2 +1,13 @@
> +
>   #include "config-host.h"
>   #include "config-target.h"
> +
> +/* We want to include different config files for specific targets
> +   And for the common library.  They need a different name because
> +   we don't want to rely in paths */
>    

on paths?

> +
> +#if defined(NEED_CPU_H)
> +#include "config-devices.h"
> +#else
> +#include "config-all-devices.h"
> +#endif
>    

^ permalink raw reply

* Re: [1.8.0] Remote tag namespace
From: Jeff King @ 2011-02-01 18:14 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: Git Mailing List, Nicolas Pitre
In-Reply-To: <AANLkTi=yFwOAQMHhvLsB1_xmYOE9HHP2YB4H4TQzwwc8@mail.gmail.com>

On Tue, Feb 01, 2011 at 05:44:50PM +0700, Nguyen Thai Ngoc Duy wrote:

> OK I'm not familiar with tag code, but I can try.
> 
> Proposal:
> 
> Reserve refs/remote-tags namespace to store tags from remotes. Its
> structure is the same as in refs/remotes. When pulling tags, put them
> in refs/remote-tags/<remote> instead of refs/tags.
> Tag dereference code will be taught about refs/remote-tags with
> similar deref order as in remote branches.

There are similar questions around remote notes refs. Should there also
be a refs/remote-notes? And there was some discussion recently about
fetching remote replace refs.

Should we perhaps be massaging refs/remotes into a structure to handle
all of these things? Like:

  refs/remotes/origin/HEAD (-> refs/remotes/origin/heads/master)
  refs/remotes/origin/heads/master
  refs/remotes/origin/tags/v1.7.4
  refs/remotes/origin/notes/commit
  refs/remotes/origin/replace/f67e92af477a2255b64a1ece33d9d126e763fe9b

i.e., make refs/remotes/* an actual mirror of selected parts of the
remote's refs/ hierarchy. And then figure out sane rules for merging
those namespaces into the ref lookup procedure. For heads and tags,
probably some tweaking of the lookup rules in dwim_ref; for
replacements, probably you would want to manually say "I am interested
in this replace" and copy or symref-link it into your refs/ hierarchy.
And probably something similar with notes.

Obviously I haven't thought it all the way through, but it just seems a
shame not to deal with other similar issues when looking at tags.

-Peff

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.