diff --git a/gdb/NEWS b/gdb/NEWS
index 0dcfcc98af..a0f78e4c35 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -39,6 +39,14 @@
      variables that are to be set or unset from GDB.  These variables
      will affect the environment to be passed to the inferior.
 
+  ** On Unix systems, GDBserver is now able to enter a directory
+     before starting an inferior.
+
+     This is done by using the "cd" command in GDB, which instructs it
+     to tell GDBserver about this directory change the next time an
+     inferior is run.  If you want to make GDBserver enter the
+     directory your GDB is currently in, you can do a "cd ." in GDB.
+
 * New remote packets
 
 QEnvironmentHexEncoded
@@ -56,6 +64,9 @@ QEnvironmentReset
 QStartupWithShell
   Indicates whether the inferior must be started with a shell or not.
 
+QSetWorkingDir
+  Tell GDBserver to enter another directory before starting the inferior.
+
 * The "maintenance print c-tdesc" command now takes an optional
   argument which is the file name of XML target description.
 
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 515a8c0f4e..65c23a936b 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -34,4 +34,8 @@ extern char *get_exec_file (int err);
    been set, then return NULL.  */
 extern const char *get_inferior_cwd ();
 
+/* Set the inferior current working directory.  This directory will be
+   entered by the debugger before executing the inferior.  */
+extern void set_inferior_cwd (const char *cwd);
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c513a49c26..fc20a74bce 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
 @item The @emph{working directory.}
 You can set your program's working directory with the command
 @code{set cwd}.  If you do not set any working directory with this
-command, your program will inherit @value{GDBN}'s working directory.
-@xref{Working Directory, ,Your Program's Working Directory}.
+command, your program will inherit @value{GDBN}'s working directory if
+native debugging, or @code{gdbserver}'s working directory if remote
+debugging.  @xref{Working Directory, ,Your Program's Working
+Directory}.
 
 @item The @emph{standard input and output.}
 Your program normally uses the same device for standard input and
@@ -2429,7 +2431,9 @@ Each time you start your program with @code{run}, the inferior will be
 initialized with the current working directory specified by the
 @code{set cwd} command.  If no directory has been specified by this
 command, then the inferior will inherit @value{GDBN}'s current working
-directory as its working directory.
+directory as its working directory if native debugging, or it will
+inherit @code{gdbserver}'s current working directory if remote
+debugging.
 
 You can also change @value{GDBN}'s current working directory by using
 the @code{cd} command.
@@ -2444,7 +2448,8 @@ Specify Files}.
 @item set cwd @r{[}@var{directory}@r{]}
 Set the inferior's working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.  This has no effect on
-@value{GDBN}'s working directory.
+@value{GDBN}'s working directory.  This setting works for both native
+and remote debugging.
 
 @kindex show cwd
 @cindex show inferior's working directory
@@ -20982,6 +20987,10 @@ are:
 @tab @code{QEnvironmentReset}
 @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
 
+@item @code{set-working-dir}
+@tab @code{QSetWorkingDir}
+@tab @code{cd}
+
 @item @code{conditional-breakpoints-packet}
 @tab @code{Z0 and Z1}
 @tab @code{Support for target-side breakpoint condition evaluation}
@@ -36770,6 +36779,30 @@ Reply:
 @table @samp
 @item OK
 The request succeeded.
+
+@item QSetWorkingDir:@var{hex-value}
+@anchor{QSetWorkingDir packet}
+@cindex set working directory, remote request
+@cindex @samp{QSetWorkingDir} packet
+On UNIX-like targets, it is possible to set the current working
+directory that @command{gdbserver} will enter before starting the
+inferior.  This packet is used to inform @command{gdbserver} of a
+directory into which it should enter during the startup process.
+
+The packet is composed by @var{hex-value}, an hex encoded
+representation of the directory to be entered by @command{gdbserver}.
+
+This packet is only transmitted when the user issues a @code{cd}
+command in @value{GDBN} (@pxref{Working Directory, ,Your Program's
+Working Directory}).
+
+This packet is only available in extended mode (@pxref{extended
+mode}).
+
+Reply:
+@table @samp
+@item OK
+The request succeeded.
 @end table
 
 This packet is not probed by default; the remote stub must request it,
@@ -36800,6 +36833,9 @@ Reply:
 @table @samp
 @item OK
 The request succeeded.
+
+@item E @var{nn}
+An error occurred.  The error number @var{nn} is given as hex digits.
 @end table
 
 This packet is not probed by default; the remote stub must request it,
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index e78ad4faf1..326d01f4d9 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -456,3 +456,12 @@ get_inferior_cwd ()
 {
   return current_inferior_cwd;
 }
+
+/* See common/common-inferior.h.  */
+
+void
+set_inferior_cwd (const char *cwd)
+{
+  xfree ((void *) current_inferior_cwd);
+  current_inferior_cwd = xstrdup (cwd);
+}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index f4faff9d77..a159708632 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -869,6 +869,21 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QSetWorkingDir:"))
+    {
+      const char *p = own_buf + strlen ("QSetWorkingDir:");
+      std::string path = hex2str (p);
+
+      set_inferior_cwd (path.c_str ());
+
+      if (remote_debug)
+	debug_printf (_("[Changed current directory to %s]\n"),
+		      path.c_str ());
+      write_ok (own_buf);
+
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -2345,7 +2360,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       sprintf (own_buf,
 	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
 	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
-	       "QEnvironmentReset+;QEnvironmentUnset+",
+	       "QEnvironmentReset+;QEnvironmentUnset+;"
+	       "QSetWorkingDir+",
 	       PBUFSIZ - 1);
 
       if (target_supports_catch_syscall ())
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index cc84d15c2f..b9fff29d74 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -562,6 +562,7 @@ static BOOL
 create_process (const char *program, char *args,
 		DWORD flags, PROCESS_INFORMATION *pi)
 {
+  const char *inferior_cwd = get_inferior_cwd ();
   BOOL ret;
 
 #ifdef _WIN32_WCE
@@ -586,7 +587,7 @@ create_process (const char *program, char *args,
 			FALSE,    /* inherit handles, not supported */
 			flags,    /* start flags */
 			NULL,     /* environment, not supported */
-			NULL,     /* current directory, not supported */
+			inferior_cwd,     /* current directory */
 			NULL,     /* start info, not supported */
 			pi);      /* proc info */
 #else
@@ -599,7 +600,7 @@ create_process (const char *program, char *args,
 			TRUE,     /* inherit handles */
 			flags,    /* start flags */
 			NULL,     /* environment */
-			NULL,     /* current directory */
+			inferior_cwd,     /* current directory */
 			&si,      /* start info */
 			pi);      /* proc info */
 #endif
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 178a3ca15f..a51a3d4e40 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -252,10 +252,9 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
-/* Set the inferior current working directory.  This directory will be
-   entered by GDB before executing the inferior.  */
+/* See common/common-inferior.h.  */
 
-static void
+void
 set_inferior_cwd (const char *cwd)
 {
   struct inferior *inf = current_inferior ();
diff --git a/gdb/remote.c b/gdb/remote.c
index 0963693a22..d900157ca9 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1428,6 +1428,7 @@ enum {
   PACKET_QPassSignals,
   PACKET_QCatchSyscalls,
   PACKET_QProgramSignals,
+  PACKET_QSetWorkingDir,
   PACKET_QStartupWithShell,
   PACKET_QEnvironmentHexEncoded,
   PACKET_QEnvironmentReset,
@@ -4637,6 +4638,8 @@ static const struct protocol_feature remote_protocol_features[] = {
     PACKET_QCatchSyscalls },
   { "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
     PACKET_QProgramSignals },
+  { "QSetWorkingDir", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QSetWorkingDir },
   { "QStartupWithShell", PACKET_DISABLE, remote_supported_packet,
     PACKET_QStartupWithShell },
   { "QEnvironmentHexEncoded", PACKET_DISABLE, remote_supported_packet,
@@ -9616,6 +9619,33 @@ extended_remote_environment_support (struct remote_state *rs)
       send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
 }
 
+/* Helper function to handle the change of the current working
+   directory in the remote.  */
+
+static void
+extended_remote_handle_inferior_cwd (struct remote_state *rs)
+{
+  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
+    {
+      const char *inferior_cwd = get_inferior_cwd ();
+
+      if (inferior_cwd != NULL)
+	{
+	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
+					 strlen (inferior_cwd));
+
+	  xsnprintf (rs->buf, get_remote_packet_size (),
+		     "QSetWorkingDir:%s", hexpath.c_str ());
+	  putpkt (rs->buf);
+	  getpkt (&rs->buf, &rs->buf_size, 0);
+	  if (strcmp (rs->buf, "OK") != 0)
+	    error (_("\
+Remote replied unexpectedly while changing working directory: %s"),
+		   rs->buf);
+	}
+    }
+}
+
 /* In the extended protocol we want to be able to do things like
    "run" and have them basically work as expected.  So we need
    a special create_inferior function.  We support changing the
@@ -9658,6 +9688,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
 
   extended_remote_environment_support (rs);
 
+  extended_remote_handle_inferior_cwd (rs);
+
   /* Now restart the remote server.  */
   run_worked = extended_remote_run (args) != -1;
   if (!run_worked)
@@ -14126,6 +14158,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
 			 "QProgramSignals", "program-signals", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
+			 "QSetWorkingDir", "set-working-dir", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
 			 "QStartupWithShell", "startup-with-shell", 0);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
index 3a6ffd3862..d3104287a0 100644
--- a/gdb/testsuite/gdb.base/set-cwd.exp
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -15,10 +15,16 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if { ![isnative] || [is_remote target] || [is_remote host]
-     || [target_info gdb_protocol] == "extended-remote" } then {
-    untested "not implemented on gdbserver"
-    return
+if { [target_info exists gdb_protocol] } {
+    if { [target_info gdb_protocol] == "remote" } {
+	untested "not implemented on native-gdbserver"
+	return
+    }
+
+    load_lib gdbserver-support.exp
+    if { [skip_gdbserver_tests] } {
+	return
+    }
 }
 
 standard_testfile
