diff --git a/gdb/NEWS b/gdb/NEWS
index fcf454833f..d68b3464e7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -26,6 +26,14 @@
 
 * New features in the GDB remote stub, GDBserver
 
+  ** GDBserver is now able to set the inferior's current working
+     directory.
+
+     The user can set the desired working directory to be used by the
+     remote inferior on GDB, using the new "set cwd" command, which
+     will instruct GDB to tell GDBserver about this directory change
+     the next time an inferior is run.
+
   ** New "--selftest" command line option runs some GDBserver self
      tests.  These self tests are disabled in releases.
 
@@ -59,6 +67,10 @@ QEnvironmentReset
 QStartupWithShell
   Indicates whether the inferior must be started with a shell or not.
 
+QSetWorkingDir
+  Tell GDBserver that the inferior to be started should use a specific
+  working directory.
+
 * 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..3dcfda3e7b 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.  If CWD is NULL, unset
+   the directory.  */
+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 0d059603cf..2d041f9819 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
 @kbd{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 the remote server'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
@@ -2439,7 +2441,9 @@ Each time you start your program with @code{run}, the inferior will be
 initialized with the current working directory specified by the
 @kbd{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 the remote server's current working directory if remote
+debugging.
 
 You can also change @value{GDBN}'s current working directory by using
 the @code{cd} command.
@@ -20999,6 +21003,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{set cwd}
+
 @item @code{conditional-breakpoints-packet}
 @tab @code{Z0 and Z1}
 @tab @code{Support for target-side breakpoint condition evaluation}
@@ -36856,6 +36864,35 @@ by supplying an appropriate @samp{qSupported} response
 actually support passing environment variables to the starting
 inferior.
 
+@item QSetWorkingDir:@r{[}@var{directory}@r{]}
+@anchor{QSetWorkingDir packet}
+@cindex set working directory, remote request
+@cindex @samp{QSetWorkingDir} packet
+This packet is used to inform the remote server of the intended
+current working directory for programs that are going to be executed.
+
+The packet is composed by @var{directory}, an hex encoded
+representation of the directory that the remote inferior will use as
+its current working directory.  If @var{directory} is an empty string,
+the remote server should reset the inferior's current working
+directory to its original, empty value.
+
+This packet is always transmitted when the inferior is run.  If the
+user has not explcitly specified a directory with the @kbd{set cwd}
+command, then an empty packet will be sent to the remote server, which
+will have no effect.  Otherwise, the specified inferior's working
+directory will be transmitted (@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
+
 @item qfThreadInfo
 @itemx qsThreadInfo
 @cindex list active threads, remote request
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 57d9956ebb..154c167f4c 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -456,3 +456,15 @@ get_inferior_cwd ()
 {
   return current_inferior_cwd;
 }
+
+/* See common/common-inferior.h.  */
+
+void
+set_inferior_cwd (const char *cwd)
+{
+  xfree ((void *) current_inferior_cwd);
+  if (cwd != NULL)
+    current_inferior_cwd = xstrdup (cwd);
+  else
+    current_inferior_cwd = NULL;
+}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index f3eee31052..8e3d30fb53 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -869,6 +869,33 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QSetWorkingDir:"))
+    {
+      const char *p = own_buf + strlen ("QSetWorkingDir:");
+
+      if (*p != '\0')
+	{
+	  std::string path = hex2str (p);
+
+	  set_inferior_cwd (path.c_str ());
+
+	  if (remote_debug)
+	    debug_printf (_("[Set the inferior's current directory to %s]\n"),
+			  path.c_str ());
+	}
+      else
+	{
+	  set_inferior_cwd (NULL);
+
+	  if (remote_debug)
+	    debug_printf (_("\
+[Unset the inferior's current directory; will use gdbserver's cwd]\n"));
+	}
+      write_ok (own_buf);
+
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -2355,7 +2382,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..c11926f7c6 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -32,6 +32,7 @@
 #include <tlhelp32.h>
 #include <psapi.h>
 #include <process.h>
+#include "gdb_tilde_expand.h"
 
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>
@@ -562,10 +563,12 @@ static BOOL
 create_process (const char *program, char *args,
 		DWORD flags, PROCESS_INFORMATION *pi)
 {
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd = gdb_tilde_expand (inferior_cwd);
   BOOL ret;
 
 #ifdef _WIN32_WCE
-  wchar_t *p, *wprogram, *wargs;
+  wchar_t *p, *wprogram, *wargs, *wcwd = NULL;
   size_t argslen;
 
   wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
@@ -579,6 +582,19 @@ create_process (const char *program, char *args,
   wargs = alloca ((argslen + 1) * sizeof (wchar_t));
   mbstowcs (wargs, args, argslen + 1);
 
+  if (inferior_cwd != NULL)
+    {
+      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+		    '/', '\\');
+      wcwd = alloca ((expanded_infcwd.size () + 1) * sizeof (wchar_t));
+      if (mbstowcs (wcwd, expanded_infcwd.c_str (),
+		    expanded_infcwd.size () + 1) == NULL)
+	{
+	  error (_("\
+Could not convert the expanded inferior cwd to wide-char."));
+	}
+    }
+
   ret = CreateProcessW (wprogram, /* image name */
 			wargs,    /* command line */
 			NULL,     /* security, not supported */
@@ -586,7 +602,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 */
+			wcwd,     /* current directory */
 			NULL,     /* start info, not supported */
 			pi);      /* proc info */
 #else
@@ -599,7 +615,7 @@ create_process (const char *program, char *args,
 			TRUE,     /* inherit handles */
 			flags,    /* start flags */
 			NULL,     /* environment */
-			NULL,     /* current directory */
+			expanded_infcwd.c_str (), /* current directory */
 			&si,      /* start info */
 			pi);      /* proc info */
 #endif
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index dbdf273ca5..187c71f344 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -242,10 +242,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.  If CWD is NULL, unset
-   the directory.  */
+/* See common/common-inferior.h.  */
 
-static void
+void
 set_inferior_cwd (const char *cwd)
 {
   struct inferior *inf = current_inferior ();
@@ -289,7 +288,8 @@ show_cwd_command (struct ui_file *file, int from_tty,
     fprintf_filtered (gdb_stdout,
 		      _("\
 You have not set the inferior's current working directory.\n\
-The inferior will inherit GDB's cwd.\n"));
+The inferior will inherit GDB's cwd if native debugging, or the remote\n\
+server's cwd if remote debugging.\n"));
   else
     fprintf_filtered (gdb_stdout,
 		      _("Current working directory that will be used "
diff --git a/gdb/remote.c b/gdb/remote.c
index d4f06a84da..267646f2ef 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1430,6 +1430,7 @@ enum {
   PACKET_QPassSignals,
   PACKET_QCatchSyscalls,
   PACKET_QProgramSignals,
+  PACKET_QSetWorkingDir,
   PACKET_QStartupWithShell,
   PACKET_QEnvironmentHexEncoded,
   PACKET_QEnvironmentReset,
@@ -4661,6 +4662,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,
@@ -9640,6 +9643,41 @@ extended_remote_environment_support (struct remote_state *rs)
       send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
 }
 
+/* Helper function to set the current working directory for the
+   inferior in the remote.  */
+
+static void
+extended_remote_set_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 ());
+	}
+      else
+	xsnprintf (rs->buf, get_remote_packet_size (),
+		   "QSetWorkingDir:");
+
+      putpkt (rs->buf);
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      if (packet_ok (rs->buf,
+		     &remote_protocol_packets[PACKET_QSetWorkingDir])
+	  != PACKET_OK)
+	error (_("\
+Remote replied unexpectedly while setting the inferior's working\n\
+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
@@ -9682,6 +9720,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
 
   extended_remote_environment_support (rs);
 
+  extended_remote_set_inferior_cwd (rs);
+
   /* Now restart the remote server.  */
   run_worked = extended_remote_run (args) != -1;
   if (!run_worked)
@@ -14181,6 +14221,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 3d666ba18d..60eb404c06 100644
--- a/gdb/testsuite/gdb.base/set-cwd.exp
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -15,8 +15,8 @@
 # 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 { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
-    untested "not implemented on gdbserver"
+if { [use_gdb_stub] } {
+    untested "skipping tests due to use_gdb_stub"
     return
 }
 
