WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] add framework for debugging processes

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] add framework for debugging processes
From: BitKeeper Bot <riel@xxxxxxxxxxx>
Date: Mon, 27 Jun 2005 21:30:47 +0000
Cc: james@xxxxxxxxxxxxx
Delivery-date: Tue, 28 Jun 2005 18:00:22 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: Xen Development List <xen-devel@xxxxxxxxxxxxxxxxxxx>
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
ChangeSet 1.1726.3.1, 2005/06/27 22:30:47+01:00, ach61@xxxxxxxxxxxxxxxxxxxxxx

        add framework for debugging processes



 tools/debugger/pdb/Domain.ml                     |   29 -
 tools/debugger/pdb/Intel.ml                      |   75 +-
 tools/debugger/pdb/Makefile                      |   24 
 tools/debugger/pdb/PDB.ml                        |  264 ++++++---
 tools/debugger/pdb/Process.ml                    |   41 +
 tools/debugger/pdb/Process.mli                   |   19 
 tools/debugger/pdb/Util.ml                       |    5 
 tools/debugger/pdb/Xen_domain.ml                 |   35 +
 tools/debugger/pdb/Xen_domain.mli                |   17 
 tools/debugger/pdb/debugger.ml                   |   57 +-
 tools/debugger/pdb/evtchn.ml                     |   12 
 tools/debugger/pdb/evtchn.mli                    |    5 
 tools/debugger/pdb/linux-2.6-module/Makefile     |   18 
 tools/debugger/pdb/linux-2.6-module/debug.c      |  169 ++++++
 tools/debugger/pdb/linux-2.6-module/module.c     |  226 ++++++++
 tools/debugger/pdb/linux-2.6-module/pdb_module.h |   65 ++
 tools/debugger/pdb/pdb_caml_domain.c             |  485 ++++++++++++++++++
 tools/debugger/pdb/pdb_caml_evtchn.c             |  178 ++++++
 tools/debugger/pdb/pdb_caml_process.c            |  543 ++++++++++++++++++++
 tools/debugger/pdb/pdb_caml_xc.c                 |  612 -----------------------
 tools/debugger/pdb/pdb_caml_xcs.c                |  305 +++++++++++
 tools/debugger/pdb/pdb_caml_xen.h                |   18 
 tools/debugger/pdb/pdb_xen.c                     |   14 
 tools/debugger/pdb/server.ml                     |   56 +-
 tools/debugger/pdb/xcs.ml                        |   85 +++
 tools/debugger/pdb/xcs.mli                       |    5 
 xen/include/public/io/domain_controller.h        |   14 
 27 files changed, 2576 insertions(+), 800 deletions(-)


diff -Nru a/tools/debugger/pdb/Domain.ml b/tools/debugger/pdb/Domain.ml
--- a/tools/debugger/pdb/Domain.ml      2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/Domain.ml      2005-06-28 14:01:24 -04:00
@@ -21,13 +21,10 @@
 let new_context dom exec_dom = {domain = dom; execution_domain = exec_dom}
 
 let set_domain ctx value =
-  ctx.domain <- value;
-  print_endline (Printf.sprintf "ctx.domain <- %d" ctx.domain)
+  ctx.domain <- value
 
 let set_execution_domain ctx value =
-  ctx.execution_domain <- value;
-  print_endline (Printf.sprintf "ctx.execution_domain <- %d"
-                ctx.execution_domain)
+  ctx.execution_domain <- value
 
 let get_domain ctx =
   ctx.domain
@@ -39,25 +36,25 @@
       Printf.sprintf "{domain} domain: %d, execution_domain: %d"
                       ctx.domain  ctx.execution_domain
 
-external read_registers : context_t -> registers = "read_registers"
+external read_registers : context_t -> registers = "dom_read_registers"
 external write_register : context_t -> register -> int32 -> unit =
-  "write_register"
+  "dom_write_register"
 external read_memory : context_t -> int32 -> int -> int list = 
-  "read_memory"
+  "dom_read_memory"
 external write_memory : context_t -> int32 -> int list -> unit = 
-  "write_memory"
+  "dom_write_memory"
        
-external continue : context_t -> unit = "continue_target"
-external step : context_t -> unit = "step_target"
+external continue : context_t -> unit = "dom_continue_target"
+external step : context_t -> unit = "dom_step_target"
 
 external insert_memory_breakpoint : context_t -> int32 -> int -> unit = 
-  "insert_memory_breakpoint"
+  "dom_insert_memory_breakpoint"
 external remove_memory_breakpoint : context_t -> int32 -> int -> unit = 
-  "remove_memory_breakpoint"
+  "dom_remove_memory_breakpoint"
 
-external attach_debugger : int -> int -> unit = "attach_debugger"
-external detach_debugger : int -> int -> unit = "detach_debugger"
-external pause_target : int -> unit = "pause_target"
+external attach_debugger : int -> int -> unit = "dom_attach_debugger"
+external detach_debugger : int -> int -> unit = "dom_detach_debugger"
+external pause_target : int -> unit = "dom_pause_target"
 
 let pause ctx =
   pause_target ctx.domain
diff -Nru a/tools/debugger/pdb/Intel.ml b/tools/debugger/pdb/Intel.ml
--- a/tools/debugger/pdb/Intel.ml       2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/Intel.ml       2005-06-28 14:01:24 -04:00
@@ -9,63 +9,58 @@
 
 
 type register =
-  | EBX
+  | EAX
   | ECX
   | EDX
+  | EBX
+  | ESP
+  | EBP
   | ESI
   | EDI
-  | EBP
-  | EAX
-  | Error_code
-  | Entry_vector
   | EIP
+  | EFL
   | CS
-  | EFLAGS
-  | ESP
   | SS
-  | ES
   | DS
+  | ES
   | FS
   | GS
 
 type registers =
-    { ebx : int32;
+    { eax : int32;
       ecx : int32;
       edx : int32;
+      ebx : int32;
+      esp : int32;
+      ebp : int32;
       esi : int32;
       edi : int32;
-      ebp : int32;
-      eax : int32;
-      error_code : int32;
-      entry_vector : int32;
       eip : int32;
-      cs : int32;
-      eflags : int32;
-      esp : int32;
-      ss : int32;
-      es : int32;
-      ds : int32;
-      fs : int32;
-      gs : int32
+      efl : int32;
+      cs  : int32;
+      ss  : int32;
+      ds  : int32;
+      es  : int32;
+      fs  : int32;
+      gs  : int32
     }
 
 let null_registers =
-  { ebx = 0l;
-    ecx = 0l;
-    edx = 0l;
-    esi = 0l;
-    edi = 0l;
-    ebp = 0l;
-    eax = 0l;
-    error_code = 0l;
-    entry_vector = 0l;
-    eip = 0l;
-    cs = 0l;
-    eflags = 0l;
-    esp = 0l;
-    ss = 0l;
-    es = 0l;
-    ds = 0l;
-    fs = 0l;
-    gs = 0l
-  }
+    { eax = 0l;
+      ecx = 0l;
+      edx = 0l;
+      ebx = 0l;
+      esp = 0l;
+      ebp = 0l;
+      esi = 0l;
+      edi = 0l;
+      eip = 0l;
+      efl = 0l;
+      cs  = 0l;
+      ss  = 0l;
+      ds  = 0l;
+      es  = 0l;
+      fs  = 0l;
+      gs  = 0l
+    }
+
diff -Nru a/tools/debugger/pdb/Makefile b/tools/debugger/pdb/Makefile
--- a/tools/debugger/pdb/Makefile       2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/Makefile       2005-06-28 14:01:24 -04:00
@@ -7,10 +7,8 @@
 # otherwise, ocamlmktop gets confused.
 LDFLAGS     =
 
-OCAML_ROOT=/usr/local
 # force ocaml 3.08
-# OCAML_ROOT  = /anfs/nos1/ach61/ocaml
-
+OCAML_ROOT  = /usr/local
 OCAMLC      = $(OCAML_ROOT)/bin/ocamlc
 OCAMLMKTOP  = $(OCAML_ROOT)/bin/ocamlmktop
 OCAMLLIBPATH= $(OCAML_ROOT)/lib/ocaml
@@ -18,6 +16,7 @@
 INCLUDES   += -I $(XEN_XC)
 INCLUDES   += -I $(XEN_LIBXC)
 INCLUDES   += -I ../libxendebug
+INCLUDES   += -I ./linux-2.6-module
 INCLUDES   += -I $(OCAML_ROOT)/lib/ocaml
 
 CFLAGS     += $(INCLUDES)
@@ -27,29 +26,26 @@
 
 CLIBS      += xc
 CLIBS      += xendebug
-CLIBS      += pdb
 
 LIBDIRS    += $(XEN_LIBXC)
-LIBDIRS    += $(XEN_LIBXUTIL)
 LIBDIRS    += ../libxendebug
-LIBDIRS    += .
 
 LIBS       += unix str
 
-PRE_TARGETS = libpdb.a
-
-all : bc
+# bc = byte-code, dc = debug byte-code
+all : dc
 
-libpdb.a : pdb_xen.o
-       ar rc $@ $^
-       ranlib $@
-
-SOURCES    += pdb_caml_xc.c pdb_xen.c
+SOURCES    += pdb_caml_xc.c 
+SOURCES    += pdb_caml_domain.c pdb_caml_process.c
+SOURCES    += pdb_caml_evtchn.c pdb_caml_xcs.c pdb_xen.c
 SOURCES    += Util.ml Intel.ml 
 SOURCES    += evtchn.ml evtchn.mli
+SOURCES    += xcs.ml xcs.mli
+SOURCES    += Xen_domain.ml Xen_domain.mli
 SOURCES    += Domain.ml  Process.ml
 SOURCES    += Domain.mli Process.mli
 SOURCES    += PDB.ml debugger.ml server.ml
+
 RESULT      = pdb
 
 include $(OCAMLMAKEFILE)
diff -Nru a/tools/debugger/pdb/PDB.ml b/tools/debugger/pdb/PDB.ml
--- a/tools/debugger/pdb/PDB.ml 2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/PDB.ml 2005-06-28 14:01:24 -04:00
@@ -13,92 +13,105 @@
 
 type context_t =
   | Void
-  | Event_channel
+  | Xen_virq
+  | Xen_xcs
+  | Xen_domain of Xen_domain.context_t
   | Domain of Domain.context_t
   | Process of Process.context_t
 
 let string_of_context ctx =
   match ctx with
   | Void -> "{void}"
-  | Event_channel -> "{event channel}"
+  | Xen_virq  -> "{Xen virq evtchn}"
+  | Xen_xcs   -> "{Xen xcs socket}"
+  | Xen_domain d -> Xen_domain.string_of_context d
   | Domain d  -> Domain.string_of_context d
   | Process p -> Process.string_of_context p
 
 
+let hash = Hashtbl.create 10
 
-let read_registers ctx =
-  match ctx with
-  | Domain d  -> Domain.read_registers d 
-  | _ -> Intel.null_registers
-
-let write_register ctx register value =
-  match ctx with
-  | Domain d  -> Domain.write_register d register value
-  | _ -> raise (Unimplemented "write register")
-
-
-let read_memory ctx addr len =
-  match ctx with
-  | Domain d  -> Domain.read_memory d addr len
-  | _ -> raise (Unimplemented "read memory")
-
-let write_memory ctx addr values =
-  match ctx with
-  | Domain d  -> Domain.write_memory d addr values
-  | _ -> raise (Unimplemented "write memory")
 
+(***************************************************************************)
 
-let continue ctx =
-  match ctx with
-  | Domain d  -> Domain.continue d
-  | _ -> raise (Unimplemented "continue")
-
-let step ctx =
-  match ctx with
-  | Domain d  -> Domain.step d
-  | _ -> raise (Unimplemented "step")
-
+let find_context key =
+  try
+    Hashtbl.find hash key
+  with
+    Not_found ->
+      print_endline "error: (find_context) PDB context not found";
+      raise Not_found
 
-let insert_memory_breakpoint ctx addr len =
-  match ctx with
-  | Domain d  -> Domain.insert_memory_breakpoint d addr len
-  | _ -> raise (Unimplemented "insert memory breakpoint")
+let delete_context key =
+  Hashtbl.remove hash key
 
-let remove_memory_breakpoint ctx addr len =
-  match ctx with
-  | Domain d  -> Domain.remove_memory_breakpoint d addr len
-  | _ -> raise (Unimplemented "remove memory breakpoint")
+(**
+   find_domain : Locate the socket associated with the context(s)
+   matching a particular (domain, vcpu) pair.  if there are multiple
+   contexts (there shouldn't be), then return the first one.
+ *)
 
+let find_domain dom vcpu =
+    let find key ctx list =
+      match ctx with
+      |        Domain d ->
+         if (((Domain.get_domain d) = dom) &&
+             ((Domain.get_execution_domain d) = vcpu))
+         then
+           key :: list
+         else
+           list
+      | _ -> list
+    in
+    let sock_list = Hashtbl.fold find hash [] in
+    match sock_list with
+    | hd::tl -> hd
+    | [] -> raise Unknown_domain
 
-let pause ctx =
-  match ctx with
-  | Domain d  -> Domain.pause d
-  | _ -> raise (Unimplemented "pause target")
+(**
+   find_xen_domain_context : fetch the socket associated with the
+   xen_domain context for a domain.  if there are multiple contexts
+   (there shouldn't be), then return the first one.
+ *)
 
+let find_xen_domain_context domain =
+  let find key ctx list =
+    match ctx with
+      | Xen_domain d ->
+         if ((Xen_domain.get_domain d) = domain)
+         then
+           key :: list
+         else
+           list
+      | _ -> list
+  in
+  let sock_list = Hashtbl.fold find hash [] in
+  match sock_list with
+    | hd::tl -> hd
+    | [] -> raise Unknown_domain
 
 let attach_debugger ctx =
   match ctx with
   | Domain d  -> Domain.attach_debugger (Domain.get_domain d) 
                                        (Domain.get_execution_domain d)
+  | Process p ->
+      begin
+       let xdom_sock = find_xen_domain_context (Process.get_domain p) in
+       let xdom_ctx = find_context xdom_sock in
+       match xdom_ctx with
+         | Xen_domain d ->
+             Process.attach_debugger p d
+         | _ -> failwith ("context has wrong xen domain type")
+      end
   | _ -> raise (Unimplemented "attach debugger")
 
 let detach_debugger ctx =
   match ctx with
   | Domain d  -> Domain.detach_debugger (Domain.get_domain d) 
                                        (Domain.get_execution_domain d)
+  | Process p  -> Process.detach_debugger p
   | _ -> raise (Unimplemented "detach debugger")
 
-external open_debugger : unit -> unit = "open_context"
-external close_debugger : unit -> unit = "close_context"
-
-(* this is just the domains right now... expand to other contexts later *)
-external debugger_status : unit -> unit = "debugger_status"
-
-
-(***********************************************************)
-
-
-let hash = Hashtbl.create 10
 
 let debug_contexts () =
   print_endline "context list:";
@@ -106,14 +119,19 @@
     match ctx with
     | Void -> print_endline (Printf.sprintf "  [%s] {void}" 
                               (Util.get_connection_info key))
-    | Event_channel -> print_endline (Printf.sprintf "  [%s] {event_channel}" 
-                              (Util.get_connection_info key))
+    | Xen_virq  -> print_endline (Printf.sprintf "  [%s] {xen virq evtchn}" 
+                                 (Util.get_connection_info key))
+    | Xen_xcs   -> print_endline (Printf.sprintf "  [%s] {xen xcs socket}" 
+                                 (Util.get_connection_info key))
+    | Xen_domain d -> print_endline (Printf.sprintf "  [%s] %s" 
+                                 (Util.get_connection_info key) 
+                                  (Xen_domain.string_of_context d))
+    | Domain d  -> print_endline (Printf.sprintf "  [%s] %s" 
+                                 (Util.get_connection_info key)
+                                 (Domain.string_of_context d))
     | Process p -> print_endline (Printf.sprintf "  [%s] %s" 
-                                   (Util.get_connection_info key)
-                                   (Process.string_of_context p))
-    | Domain d -> print_endline (Printf.sprintf "  [%s] %s" 
-                                  (Util.get_connection_info key)
-                                  (Domain.string_of_context d))
+                                 (Util.get_connection_info key)
+                                 (Process.string_of_context p))
   in
   Hashtbl.iter print_context hash
 
@@ -123,13 +141,14 @@
  *)
 let add_context (key:Unix.file_descr) context params =
   match context with
-  | "void" -> Hashtbl.replace hash key Void
-  | "event channel" -> Hashtbl.replace hash key Event_channel
+  | "void"     -> Hashtbl.replace hash key Void
+  | "xen virq" -> Hashtbl.replace hash key Xen_virq
+  | "xen xcs"  -> Hashtbl.replace hash key Xen_xcs
   | "domain" -> 
       begin
        match params with
-       | dom::exec_dom::_ ->
-            let d = Domain(Domain.new_context dom exec_dom) in
+       | dom::vcpu::_ ->
+            let d = Domain(Domain.new_context dom vcpu) in
            attach_debugger d;
             Hashtbl.replace hash key d
        | _ -> failwith "bogus parameters to domain context"
@@ -138,43 +157,96 @@
       begin
        match params with
        | dom::pid::_ ->
-           let p = Process.new_context dom pid in
-           Hashtbl.replace hash key (Process(p))
+           let p = Process(Process.new_context dom pid) in
+           attach_debugger p;
+           Hashtbl.replace hash key p
        | _ -> failwith "bogus parameters to process context"
       end
+  | "xen domain"
   | _ -> raise (Unknown_context context)
 
+(* 
+ * this is really bogus.  add_xen_domain_context should really
+ * be a case within add_context.  however, we need to pass in
+ * a pointer that can only be represented as an int32.
+ * this would require a different type for params... :(
+ * 31 bit integers suck.
+ *)
+let add_xen_domain_context (key:Unix.file_descr) dom evtchn sring =
+  let d = Xen_domain.new_context dom evtchn sring in
+  Hashtbl.replace hash key (Xen_domain(d))
+
+
 let add_default_context sock =
   add_context sock "void" []
 
-let find_context key =
-  try
-    Hashtbl.find hash key
-  with
-    Not_found ->
-      print_endline "error: (find_context) PDB context not found";
-      raise Not_found
+(***************************************************************************)
 
-let delete_context key =
-  Hashtbl.remove hash key
+(***************************************************************************)
 
-(** find_domain : Locate the context(s) matching a particular domain 
- *  and execution_domain pair.
- *)
+let read_registers ctx =
+  match ctx with
+  | Void -> Intel.null_registers                    (* default for startup *)
+  | Domain d  -> Domain.read_registers d 
+  | Process p -> Process.read_registers p
+  | _ -> raise (Unimplemented "read registers")
+
+let write_register ctx register value =
+  match ctx with
+  | Domain d  -> Domain.write_register d register value
+  | Process p -> Process.write_register p register value
+  | _ -> raise (Unimplemented "write register")
+
+
+let read_memory ctx addr len =
+  match ctx with
+  | Domain d  -> Domain.read_memory d addr len
+  | Process p -> Process.read_memory p addr len
+  | _ -> raise (Unimplemented "read memory")
+
+let write_memory ctx addr values =
+  match ctx with
+  | Domain d  -> Domain.write_memory d addr values
+  | Process p -> Process.write_memory p addr values
+  | _ -> raise (Unimplemented "write memory")
+
+
+let continue ctx =
+  match ctx with
+  | Domain d  -> Domain.continue d
+  | Process p  -> Process.continue p
+  | _ -> raise (Unimplemented "continue")
+
+let step ctx =
+  match ctx with
+  | Domain d  -> Domain.step d
+  | Process p  -> Process.step p
+  | _ -> raise (Unimplemented "step")
+
+
+let insert_memory_breakpoint ctx addr len =
+  match ctx with
+  | Domain d  -> Domain.insert_memory_breakpoint d addr len
+  | Process p  -> Process.insert_memory_breakpoint p addr len
+  | _ -> raise (Unimplemented "insert memory breakpoint")
+
+let remove_memory_breakpoint ctx addr len =
+  match ctx with
+  | Domain d  -> Domain.remove_memory_breakpoint d addr len
+  | Process p  -> Process.remove_memory_breakpoint p addr len
+  | _ -> raise (Unimplemented "remove memory breakpoint")
+
+
+let pause ctx =
+  match ctx with
+  | Domain d  -> Domain.pause d
+  | Process p  -> Process.pause p
+  | _ -> raise (Unimplemented "pause target")
+
+
+external open_debugger : unit -> unit = "open_context"
+external close_debugger : unit -> unit = "close_context"
+
+(* this is just the domains right now... expand to other contexts later *)
+external debugger_status : unit -> unit = "debugger_status"
 
-let find_domain dom exec_dom =
-    let find key ctx list =
-      match ctx with
-      |        Domain d ->
-         if (((Domain.get_domain d) = dom) &&
-             ((Domain.get_execution_domain d) = exec_dom))
-         then
-           key :: list
-         else
-           list
-      | _ -> list
-    in
-    let sock_list = Hashtbl.fold find hash [] in
-    match sock_list with
-    | hd::tl -> hd
-    | [] -> raise Unknown_domain
diff -Nru a/tools/debugger/pdb/Process.ml b/tools/debugger/pdb/Process.ml
--- a/tools/debugger/pdb/Process.ml     2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/Process.ml     2005-06-28 14:01:24 -04:00
@@ -12,13 +12,16 @@
 
 type context_t =
 {
-  mutable domain : int;
+  mutable domain  : int;
   mutable process : int;
+  mutable evtchn  : int;
+  mutable ring    : int32;
 }
 
-let default_context = { domain = 0; process = 0 }
+let default_context = { domain = 0; process = 0; evtchn = 0; ring = 0l }
 
-let new_context dom proc = { domain = dom; process = proc }
+let new_context dom proc = { domain = dom; process = proc; 
+                             evtchn = 0; ring = 0l }
 
 let string_of_context ctx =
   Printf.sprintf "{process} domain: %d, process: %d"
@@ -37,3 +40,35 @@
 
 let get_process ctx =
   ctx.process
+
+external _attach_debugger : context_t -> unit = "proc_attach_debugger"
+external detach_debugger : context_t -> unit = "proc_detach_debugger"
+external pause_target : context_t -> unit = "proc_pause_target"
+
+(* save the event channel and ring for the domain for future use *)
+let attach_debugger proc_ctx dom_ctx =
+  print_endline (Printf.sprintf "%d %lx"
+    (Xen_domain.get_evtchn dom_ctx)
+    (Xen_domain.get_ring dom_ctx));
+  proc_ctx.evtchn <- Xen_domain.get_evtchn dom_ctx;
+  proc_ctx.ring   <- Xen_domain.get_ring   dom_ctx;
+  _attach_debugger proc_ctx
+
+external read_registers : context_t -> registers = "proc_read_registers"
+external write_register : context_t -> register -> int32 -> unit =
+  "proc_write_register"
+external read_memory : context_t -> int32 -> int -> int list = 
+  "proc_read_memory"
+external write_memory : context_t -> int32 -> int list -> unit = 
+  "proc_write_memory"
+
+external continue : context_t -> unit = "proc_continue_target"
+external step : context_t -> unit = "proc_step_target"
+
+external insert_memory_breakpoint : context_t -> int32 -> int -> unit = 
+  "proc_insert_memory_breakpoint"
+external remove_memory_breakpoint : context_t -> int32 -> int -> unit = 
+  "proc_remove_memory_breakpoint"
+
+let pause ctx =
+  pause_target ctx
diff -Nru a/tools/debugger/pdb/Process.mli b/tools/debugger/pdb/Process.mli
--- a/tools/debugger/pdb/Process.mli    2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/Process.mli    2005-06-28 14:01:24 -04:00
@@ -7,6 +7,9 @@
  *  @version 1
  *)
 
+open Int32
+open Intel
+
 type context_t
 
 val default_context : context_t
@@ -18,3 +21,19 @@
 val get_process : context_t -> int
 
 val string_of_context : context_t -> string
+
+val attach_debugger : context_t -> Xen_domain.context_t -> unit
+val detach_debugger : context_t -> unit
+val pause : context_t -> unit
+
+
+val read_registers : context_t -> registers
+val write_register : context_t -> register -> int32 -> unit
+val read_memory : context_t -> int32 -> int -> int list
+val write_memory : context_t -> int32 -> int list -> unit
+       
+val continue : context_t -> unit
+val step : context_t -> unit
+
+val insert_memory_breakpoint : context_t -> int32 -> int -> unit
+val remove_memory_breakpoint : context_t -> int32 -> int -> unit
diff -Nru a/tools/debugger/pdb/Util.ml b/tools/debugger/pdb/Util.ml
--- a/tools/debugger/pdb/Util.ml        2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/Util.ml        2005-06-28 14:01:24 -04:00
@@ -103,7 +103,7 @@
   let get_local_info fd =
     let sockname = Unix.getsockname fd in
     match sockname with
-    | Unix.ADDR_UNIX(s) -> s
+    | Unix.ADDR_UNIX(s) -> "unix"
     | Unix.ADDR_INET(a,p) -> ((Unix.string_of_inet_addr a) ^ ":" ^
                              (string_of_int p))
   and get_remote_info fd =
@@ -117,6 +117,9 @@
     get_remote_info fd
   with
   | Unix.Unix_error (Unix.ENOTSOCK, s1, s2) -> 
+      let s = Unix.fstat fd in
+      Printf.sprintf "dev: %d, inode: %d" s.Unix.st_dev s.Unix.st_ino
+  | Unix.Unix_error (Unix.EBADF, s1, s2) -> 
       let s = Unix.fstat fd in
       Printf.sprintf "dev: %d, inode: %d" s.Unix.st_dev s.Unix.st_ino
   | _ -> get_local_info fd
diff -Nru a/tools/debugger/pdb/Xen_domain.ml b/tools/debugger/pdb/Xen_domain.ml
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/Xen_domain.ml  2005-06-28 14:01:24 -04:00
@@ -0,0 +1,35 @@
+
+type context_t =
+{
+  mutable domain : int;
+  mutable evtchn : int;
+  mutable pdb_front_ring : int32
+}
+
+let default_context = { domain = 0; evtchn = 0; pdb_front_ring = 0l }
+
+let new_context dom evtchn ring = 
+  {domain = dom; evtchn = evtchn; pdb_front_ring = ring}
+
+let set_domain ctx value =
+  ctx.domain <- value
+
+let set_evtchn ctx value =
+  ctx.evtchn <- value
+
+let set_ring ctx value =
+  ctx.pdb_front_ring <- value
+
+let get_domain ctx =
+  ctx.domain
+
+let get_evtchn ctx =
+  ctx.evtchn
+
+let get_ring ctx =
+  ctx.pdb_front_ring
+
+let string_of_context ctx =
+      Printf.sprintf "{xen domain assist} domain: %d" ctx.domain 
+
+external process_response : int32 -> unit = "process_handle_response"
diff -Nru a/tools/debugger/pdb/Xen_domain.mli 
b/tools/debugger/pdb/Xen_domain.mli
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/Xen_domain.mli 2005-06-28 14:01:24 -04:00
@@ -0,0 +1,17 @@
+
+type context_t
+
+val default_context : context_t
+val new_context : int -> int -> int32 -> context_t 
+
+val set_domain : context_t -> int -> unit
+val get_domain : context_t -> int
+val set_evtchn : context_t -> int -> unit
+val get_evtchn : context_t -> int
+val set_ring   : context_t -> int32 -> unit
+val get_ring   : context_t -> int32
+
+val string_of_context : context_t -> string
+
+val process_response : int32 -> unit
+
diff -Nru a/tools/debugger/pdb/debugger.ml b/tools/debugger/pdb/debugger.ml
--- a/tools/debugger/pdb/debugger.ml    2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/debugger.ml    2005-06-28 14:01:24 -04:00
@@ -77,7 +77,7 @@
     (Printf.sprintf "%08lx" (Util.flip_int32 regs.esi)) ^
     (Printf.sprintf "%08lx" (Util.flip_int32 regs.edi)) ^
     (Printf.sprintf "%08lx" (Util.flip_int32 regs.eip)) ^
-    (Printf.sprintf "%08lx" (Util.flip_int32 regs.eflags)) ^
+    (Printf.sprintf "%08lx" (Util.flip_int32 regs.efl)) ^
     (Printf.sprintf "%08lx" (Util.flip_int32 regs.cs)) ^
     (Printf.sprintf "%08lx" (Util.flip_int32 regs.ss)) ^
     (Printf.sprintf "%08lx" (Util.flip_int32 regs.ds)) ^
@@ -140,7 +140,7 @@
     |  6 -> PDB.write_register ctx ESI new_val
     |  7 -> PDB.write_register ctx EDI new_val
     |  8 -> PDB.write_register ctx EIP new_val
-    |  9 -> PDB.write_register ctx EFLAGS new_val
+    |  9 -> PDB.write_register ctx EFL new_val
     | 10 -> PDB.write_register ctx CS new_val
     | 11 -> PDB.write_register ctx SS new_val
     | 12 -> PDB.write_register ctx DS new_val
@@ -195,13 +195,15 @@
  *)
 let pdb_extensions command sock =
   let process_extension key value =
-    (* since this command can change the context, we need to grab it each time 
*)
+    (* since this command can change the context, 
+       we need to grab it again each time *)
     let ctx = PDB.find_context sock in
     match key with
     | "status" ->
-       print_endline (string_of_context ctx);
        PDB.debug_contexts ();
-       debugger_status ()
+       (* print_endline ("debugger status");
+          debugger_status () 
+       *)
     | "context" ->
         PDB.add_context sock (List.hd value) 
                              (int_list_of_string_list (List.tl value))
@@ -216,6 +218,7 @@
   | Unknown_context s -> 
       print_endline (Printf.sprintf "unknown context [%s]" s);
       "E01"
+  | Unknown_domain -> "E01"
   | Failure s -> "E01"
 
 
@@ -274,27 +277,47 @@
     | 'Z' -> gdb_insert_bwcpoint ctx command
     | _ -> 
        print_endline (Printf.sprintf "unknown gdb command [%s]" command);
-       ""
+       "E02"
   with
     Unimplemented s ->
       print_endline (Printf.sprintf "loser. unimplemented command [%s][%s]" 
                                    command s);
-      ""
+      "E03"
 
+(**
+   process_xen_domain
+
+   This is called whenever a domain debug assist responds to a
+   pdb packet.
+*)
+
+let process_xen_domain fd =
+  let channel = Evtchn.read fd in
+  let ctx = find_context fd in
+  
+  begin
+    match ctx with
+      | Xen_domain d -> Xen_domain.process_response (Xen_domain.get_ring d)
+      | _ -> failwith ("process_xen_domain called without Xen_domain context")
+  end;
+    
+  Evtchn.unmask fd channel                                (* allow next virq *)
+  
 
 (**
-   process_evtchn  
+   process_xen_virq
 
    This is called each time a virq_pdb is sent from xen to dom 0.
    It is sent by Xen when a domain hits a breakpoint. 
 
-   Think of this as the continuation function for a "c" or "s" command.
+   Think of this as the continuation function for a "c" or "s" command
+   issued to a domain.
 *)
 
 external query_domain_stop : unit -> (int * int) list = "query_domain_stop"
 (* returns a list of paused domains : () -> (domain, vcpu) list *)
 
-let process_evtchn fd =
+let process_xen_virq fd =
   let channel = Evtchn.read fd in
   let find_pair (dom, vcpu) =
     print_endline (Printf.sprintf "checking %d.%d" dom vcpu);
@@ -313,3 +336,17 @@
   Util.send_reply sock "S05";
   Evtchn.unmask fd channel                                (* allow next virq *)
   
+
+(**
+   process_xen_xcs
+
+   This is called each time the software assist residing in a backend 
+   domain starts up.  The control message includes the address of a 
+   shared ring page and our end of an event channel (which indicates
+   when data is available on the ring).
+*)
+
+let process_xen_xcs xcs_fd =
+  let (local_evtchn_fd, evtchn, dom, ring) = Xcs.read xcs_fd in
+  add_xen_domain_context local_evtchn_fd dom evtchn ring;
+  local_evtchn_fd
diff -Nru a/tools/debugger/pdb/evtchn.ml b/tools/debugger/pdb/evtchn.ml
--- a/tools/debugger/pdb/evtchn.ml      2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/evtchn.ml      2005-06-28 14:01:24 -04:00
@@ -14,6 +14,7 @@
 let virq_pdb = 6                                      (* as defined VIRQ_PDB *)
 
 external bind_virq : int -> int = "evtchn_bind_virq"
+external bind_interdomain : int -> int * int = "evtchn_bind_interdomain"
 external bind : Unix.file_descr -> int -> unit = "evtchn_bind"
 external unbind : Unix.file_descr -> int -> unit = "evtchn_unbind"
 external ec_open : string -> int -> int -> Unix.file_descr = "evtchn_open"
@@ -21,10 +22,17 @@
 external ec_close : Unix.file_descr -> unit = "evtchn_close"
 external unmask : Unix.file_descr -> int -> unit = "evtchn_unmask"
 
+let _setup () =
+  let fd = ec_open dev_name dev_major dev_minor in
+  fd
+
+let _bind fd port =
+  bind fd port
+
 let setup () =
   let port = bind_virq virq_pdb in
-  let fd = ec_open dev_name dev_major dev_minor in
-  bind fd port;
+  let fd = _setup() in
+  _bind fd port;
   fd
 
 let teardown fd =
diff -Nru a/tools/debugger/pdb/evtchn.mli b/tools/debugger/pdb/evtchn.mli
--- a/tools/debugger/pdb/evtchn.mli     2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/evtchn.mli     2005-06-28 14:01:24 -04:00
@@ -7,6 +7,11 @@
  *  @version 1
  *)
 
+val _setup : unit -> Unix.file_descr
+val _bind : Unix.file_descr -> int -> unit
+
+val bind_interdomain : int -> int * int
+
 
 val setup : unit -> Unix.file_descr
 val read : Unix.file_descr -> int
diff -Nru a/tools/debugger/pdb/linux-2.6-module/Makefile 
b/tools/debugger/pdb/linux-2.6-module/Makefile
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/linux-2.6-module/Makefile      2005-06-28 14:01:24 
-04:00
@@ -0,0 +1,18 @@
+XEN_ROOT=/anfs/nos1/ach61/bk
+KDIR=$(XEN_ROOT)/linux-2.6.11-xenU
+
+obj-m    += pdb.o
+pdb-objs += module.o
+pdb-objs += debug.o
+
+CFLAGS += -g
+CFLAGS += -Wall
+CFLAGS += -Werror
+
+module : 
+#      make KBUILD_VERBOSE=1 ARCH=xen -C $(KDIR) M=$(PWD) modules
+       make                  ARCH=xen -C $(KDIR) M=$(PWD) modules
+
+clean :
+       make -C $(KDIR) M=$(PWD) clean
+
diff -Nru a/tools/debugger/pdb/linux-2.6-module/debug.c 
b/tools/debugger/pdb/linux-2.6-module/debug.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/linux-2.6-module/debug.c       2005-06-28 14:01:24 
-04:00
@@ -0,0 +1,169 @@
+/*
+ * debug.c
+ * pdb debug functionality for processes.
+ */
+
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm-xen/asm-i386/ptrace.h>
+#include <asm-xen/xen-public/xen.h>
+
+#include "pdb_module.h"
+
+EXPORT_SYMBOL(pdb_attach);
+EXPORT_SYMBOL(pdb_detach);
+
+int
+pdb_attach (int pid)
+{
+    struct task_struct *target;
+    u32 rc = 0;
+
+    printk ("pdb attach: 0x%x\n", pid);
+
+    read_lock(&tasklist_lock);
+    target = find_task_by_pid(pid);
+    if (target)
+        get_task_struct(target);
+    read_unlock(&tasklist_lock);
+
+    force_sig(SIGSTOP, target);                    /* force_sig_specific ??? */
+
+    return rc;
+}
+
+int
+pdb_detach (int pid)
+{
+    int rc = 0;
+    struct task_struct *target;
+
+    printk ("pdb detach: 0x%x\n", pid);
+
+    read_lock(&tasklist_lock);
+    target = find_task_by_pid(pid);
+    if (target)
+        get_task_struct(target);
+    read_unlock(&tasklist_lock);
+
+    wake_up_process(target);
+
+    return rc;
+}
+
+/*
+ * from linux-2.6.11/arch/i386/kernel/ptrace.c::getreg()
+ */
+int
+pdb_read_register (int pid, pdb_op_rd_reg_p op, unsigned long *dest)
+{
+    int rc = 0;
+    struct task_struct *target;
+    unsigned long offset;
+    unsigned char *stack = 0L;
+
+    *dest = ~0UL;
+
+    read_lock(&tasklist_lock);
+    target = find_task_by_pid(pid);
+    if (target)
+        get_task_struct(target);
+    read_unlock(&tasklist_lock);
+
+    switch (op->reg)
+    {
+    case FS:
+        *dest = target->thread.fs;
+        break;
+    case GS:
+        *dest = target->thread.gs;
+        break;
+    case DS:
+    case ES:
+    case SS:
+    case CS:
+        *dest = 0xffff;
+        /* fall through */
+    default:
+        if (op->reg > GS)
+            op->reg -= 2;
+
+        offset = op->reg * sizeof(long);
+        offset -= sizeof(struct pt_regs);
+        stack = (unsigned char *)target->thread.esp0;
+        stack += offset;
+        *dest &= *((int *)stack);
+    }
+
+    /*
+    printk ("pdb read register: 0x%x %2d 0x%p 0x%lx\n", 
+            pid, op->reg, stack, *dest);
+    */
+
+    return rc;
+}
+
+/*
+ * from linux-2.6.11/arch/i386/kernel/ptrace.c::putreg()
+ */
+int
+pdb_write_register (int pid, pdb_op_wr_reg_p op)
+{
+    int rc = 0;
+    struct task_struct *target;
+    unsigned long offset;
+    unsigned char *stack;
+    unsigned long value = op->value;
+
+    /*
+    printk ("pdb write register: 0x%x %2d 0x%lx\n", pid, op->reg, value);
+    */
+
+    read_lock(&tasklist_lock);
+    target = find_task_by_pid(pid);
+    if (target)
+        get_task_struct(target);
+    read_unlock(&tasklist_lock);
+
+    switch (op->reg)
+    {
+    case FS:
+        target->thread.fs = value;
+        return rc;
+    case GS:
+        target->thread.gs = value;
+        return rc;
+    case DS:
+    case ES:
+        value &= 0xffff;
+        break;
+    case SS:
+    case CS:
+        value &= 0xffff;
+        break;
+    case EFL:
+        break;
+    }
+
+    if (op->reg > GS)
+        op->reg -= 2;
+    offset = op->reg * sizeof(long);
+    offset -= sizeof(struct pt_regs);
+    stack = (unsigned char *)target->thread.esp0;
+    stack += offset;
+    *(unsigned long *) stack = op->value;
+
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -Nru a/tools/debugger/pdb/linux-2.6-module/module.c 
b/tools/debugger/pdb/linux-2.6-module/module.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/linux-2.6-module/module.c      2005-06-28 14:01:24 
-04:00
@@ -0,0 +1,226 @@
+
+/*
+ * module.c
+ *
+ * Handles initial registration with pdb when the pdb module starts up
+ * and cleanup when the module goes away (sortof :)
+ * Also receives each request from pdb in domain 0 and dispatches to the
+ * appropriate debugger function.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#include <asm-xen/evtchn.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+#include <asm-xen/xen-public/xen.h>
+
+#include <asm-xen/xen-public/io/ring.h>
+
+#include "pdb_module.h"
+
+#define PDB_RING_SIZE __RING_SIZE((pdb_sring_t *)0, PAGE_SIZE)
+
+static pdb_back_ring_t pdb_ring;
+static unsigned int    pdb_evtchn;
+static unsigned int    pdb_irq;
+
+/*
+ * send response to a pdb request
+ */
+static void
+pdb_send_response (pdb_response_t *response)
+{
+    pdb_response_t *resp;
+
+    resp = RING_GET_RESPONSE(&pdb_ring, pdb_ring.rsp_prod_pvt);
+
+    memcpy(resp, response, sizeof(pdb_response_t));
+    
+    wmb();                 /* Ensure other side can see the response fields. */
+    pdb_ring.rsp_prod_pvt++;
+    RING_PUSH_RESPONSES(&pdb_ring);
+    notify_via_evtchn(pdb_evtchn);
+    return;
+}
+
+/*
+ * handle a debug command from the front end
+ */
+static void
+pdb_process_request (pdb_request_t *request)
+{
+    pdb_response_t resp;
+
+    switch (request->operation)
+    {
+    case PDB_OPCODE_ATTACH :
+        pdb_attach(request->process);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    case PDB_OPCODE_DETACH :
+        pdb_detach(request->process);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    case PDB_OPCODE_RD_REG :
+        pdb_read_register(request->process, &request->u.rd_reg, 
+                          (unsigned long *)&resp.value);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    case PDB_OPCODE_WR_REG :
+        pdb_write_register(request->process, &request->u.wr_reg);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    default:
+        printk("(pdb) unknown request operation %d\n", request->operation);
+        resp.status = PDB_RESPONSE_ERROR;
+    }
+        
+    resp.operation = request->operation;
+            
+    pdb_send_response (&resp);
+    return;
+}
+
+/*
+ * receive a pdb request
+ */
+static irqreturn_t
+pdb_interrupt (int irq, void *dev_id, struct pt_regs *ptregs)
+{
+    pdb_request_t *req;
+    RING_IDX i, rp;
+
+    rp = pdb_ring.sring->req_prod;
+    rmb();
+
+    for ( i = pdb_ring.req_cons; 
+          (i != rp) && !RING_REQUEST_CONS_OVERFLOW(&pdb_ring, i);
+          i++ )
+    {
+        req = RING_GET_REQUEST(&pdb_ring, i);
+        pdb_process_request(req);
+
+    }
+    pdb_ring.req_cons = i;
+
+    return IRQ_HANDLED;
+}
+
+
+static void
+pdb_send_connection_status(int status, memory_t ring)
+{
+    ctrl_msg_t cmsg = 
+    {
+        .type = CMSG_DEBUG,
+        .subtype = CMSG_DEBUG_CONNECTION_STATUS,
+        .length  = sizeof(pdb_connection_t),
+    };
+    pdb_connection_t *conn = (pdb_connection_t *)cmsg.msg;
+
+    conn->status = status;
+    conn->ring = ring;
+    conn->evtchn = 0;
+
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+}
+
+
+/*
+ * this is called each time a message is received on the control channel
+ */
+static void
+pdb_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+{
+printk ("pdb ctrlif rx\n");
+
+    switch (msg->subtype)
+    {
+    case CMSG_DEBUG_CONNECTION_STATUS:
+        /* initialize event channel created by the pdb server */
+
+        pdb_evtchn = ((pdb_connection_p) msg->msg)->evtchn;
+        pdb_irq = bind_evtchn_to_irq(pdb_evtchn);
+
+        if ( request_irq(pdb_irq, pdb_interrupt, 
+                         SA_SAMPLE_RANDOM, "pdb", NULL) )
+        {
+            printk("(pdb) request irq failed: %d %d\n", pdb_evtchn, pdb_irq);
+        }
+        break;
+
+    default:
+        printk ("(pdb) unknown xcs control message: %d\n", msg->subtype);
+        break;
+    }
+
+    return;
+}
+
+static int __init 
+pdb_initialize(void)
+{
+    pdb_sring_t *sring;
+
+    printk("----\npdb initialize   %s %s\n", __DATE__, __TIME__);
+
+    /*
+    if ( xen_start_info.flags & SIF_INITDOMAIN )
+        return 1;
+    */
+
+    (void)ctrl_if_register_receiver(CMSG_DEBUG, pdb_ctrlif_rx,
+                                    CALLBACK_IN_BLOCKING_CONTEXT);
+
+    /* rings */
+    sring = (pdb_sring_t *)__get_free_page(GFP_KERNEL);
+    SHARED_RING_INIT(sring);
+    BACK_RING_INIT(&pdb_ring, sring, PAGE_SIZE);
+ 
+    /* notify pdb in dom 0 */
+    pdb_send_connection_status(PDB_CONNECTION_STATUS_UP, 
+                               virt_to_machine(pdb_ring.sring) >> PAGE_SHIFT);
+
+    return 0;
+}
+
+static void __exit
+pdb_terminate(void)
+{
+    printk("pdb cleanup\n");
+
+    (void)ctrl_if_unregister_receiver(CMSG_DEBUG, pdb_ctrlif_rx);
+
+    if (pdb_irq)
+    {
+        free_irq(pdb_irq, NULL);
+        pdb_irq = 0;
+    }
+
+    if (pdb_evtchn)
+    {
+        unbind_evtchn_from_irq(pdb_evtchn); 
+        pdb_evtchn = 0;
+    }
+
+    pdb_send_connection_status(PDB_CONNECTION_STATUS_DOWN, 0);
+}
+
+
+module_init(pdb_initialize);
+module_exit(pdb_terminate);
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -Nru a/tools/debugger/pdb/linux-2.6-module/pdb_module.h 
b/tools/debugger/pdb/linux-2.6-module/pdb_module.h
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/linux-2.6-module/pdb_module.h  2005-06-28 14:01:24 
-04:00
@@ -0,0 +1,65 @@
+
+#ifndef __XEN_PDB_H_
+#define __XEN_PDB_H_
+
+#define PDB_OPCODE_ATTACH 1
+#define PDB_OPCODE_DETACH 2
+
+#define PDB_OPCODE_RD_REG 3
+typedef struct pdb_op_rd_reg
+{
+    u32 reg;
+} pdb_op_rd_reg_t, *pdb_op_rd_reg_p;
+
+#define PDB_OPCODE_WR_REG 4
+typedef struct pdb_op_wr_reg
+{
+    u32 reg;
+    u32 value;
+} pdb_op_wr_reg_t, *pdb_op_wr_reg_p;
+
+typedef struct 
+{
+    u8   operation;       /* PDB_OPCODE_???      */
+    u32  domain;
+    u32  process;
+    union
+    {
+        pdb_op_rd_reg_t rd_reg;
+        pdb_op_wr_reg_t wr_reg;
+    } u;
+} PACKED pdb_request_t, *pdb_request_p;
+ 
+
+#define PDB_RESPONSE_OKAY   0
+#define PDB_RESPONSE_ERROR -1
+
+typedef struct {
+    u8   operation;       /* copied from request */
+    s16  status;          /* PDB_RESPONSE_???    */
+    u32  value;
+} PACKED pdb_response_t, *pdb_response_p;
+
+
+DEFINE_RING_TYPES(pdb, pdb_request_t, pdb_response_t);
+
+
+int pdb_attach (int pid);
+int pdb_detach (int pid);
+int pdb_read_register (int pid, pdb_op_rd_reg_p op, unsigned long *dest);
+int pdb_write_register (int pid, pdb_op_wr_reg_p op);
+
+
+#endif
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -Nru a/tools/debugger/pdb/pdb_caml_domain.c 
b/tools/debugger/pdb/pdb_caml_domain.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/pdb_caml_domain.c      2005-06-28 14:01:24 -04:00
@@ -0,0 +1,485 @@
+/*
+ * pdb_caml_xc.c
+ *
+ * http://www.cl.cam.ac.uk/netos/pdb
+ *
+ * PDB's OCaml interface library for debugging domains
+ */
+
+#include <xc.h>
+#include <xendebug.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#include "pdb_caml_xen.h"
+
+/* this order comes from xen/include/public/arch-x86_32.h */
+enum x86_registers { PDB_EBX, PDB_ECX, PDB_EDX, PDB_ESI, PDB_EDI,
+                     PDB_EBP, PDB_EAX, PDB_Error_code, PDB_Entry_vector, 
+                     PDB_EIP, PDB_CS, PDB_EFLAGS, PDB_ESP, PDB_SS,
+                     PDB_ES, PDB_DS, PDB_FS, PDB_GS };
+
+typedef struct
+{
+    int domain;
+    int vcpu;
+} context_t;
+
+#define decode_context(_ctx, _ocaml)   \
+{  \
+    (_ctx)->domain = Int_val(Field((_ocaml),0));  \
+    (_ctx)->vcpu = Int_val(Field((_ocaml),1));  \
+}
+
+#define encode_context(_ctx, _ocaml)  \
+{  \
+    (_ocaml) = caml_alloc_tuple(2);  \
+    Store_field((_ocaml), 0, Val_int((_ctx)->domain));  \
+    Store_field((_ocaml), 1, Val_int((_ctx)->vcpu));  \
+}
+
+
+/****************************************************************************/
+
+/*
+ * dom_read_registers : context_t -> int32
+ */
+value
+dom_read_registers (value context)
+{
+    CAMLparam1(context);
+    CAMLlocal1(result);
+
+    cpu_user_regs_t *regs;
+    context_t ctx;
+
+    decode_context(&ctx, context);
+
+    if ( xendebug_read_registers(xc_handle, ctx.domain, ctx.vcpu, &regs) )
+    {
+        printf("(pdb) read registers error!\n");  fflush(stdout);
+        failwith("read registers error");
+    }
+
+    dump_regs(regs);
+
+    result = caml_alloc_tuple(16);
+
+    Store_field(result,  0, caml_copy_int32(regs->eax));
+    Store_field(result,  1, caml_copy_int32(regs->ecx));
+    Store_field(result,  2, caml_copy_int32(regs->edx));
+    Store_field(result,  3, caml_copy_int32(regs->ebx));
+    Store_field(result,  4, caml_copy_int32(regs->esp));
+    Store_field(result,  5, caml_copy_int32(regs->ebp));
+    Store_field(result,  6, caml_copy_int32(regs->esi));
+    Store_field(result,  7, caml_copy_int32(regs->edi));
+    Store_field(result,  8, caml_copy_int32(regs->eip));
+    Store_field(result,  9, caml_copy_int32(regs->eflags));
+    Store_field(result, 10, caml_copy_int32(regs->cs));                /* 16 */
+    Store_field(result, 11, caml_copy_int32(regs->ss));                /* 16 */
+    Store_field(result, 12, caml_copy_int32(regs->ds));                /* 16 */
+    Store_field(result, 13, caml_copy_int32(regs->es));                /* 16 */
+    Store_field(result, 14, caml_copy_int32(regs->fs));                /* 16 */
+    Store_field(result, 15, caml_copy_int32(regs->gs));                /* 16 */
+
+    CAMLreturn(result);
+}
+
+
+/*
+ * dom_write_register : context_t -> register -> int32 -> unit
+ */
+value
+dom_write_register (value context, value reg, value newval)
+{
+    CAMLparam3(context, reg, newval);
+
+    int my_reg = Int_val(reg);
+    int val = Int32_val(newval);
+
+    context_t ctx;
+    cpu_user_regs_t *regs;
+
+    printf("(pdb) write register\n");
+
+    decode_context(&ctx, context);
+
+    if ( xendebug_read_registers(xc_handle, ctx.domain, ctx.vcpu, &regs) )
+    {
+        printf("(pdb) write register (get) error!\n");  fflush(stdout);
+        failwith("write register error");
+    }
+
+    switch (my_reg)
+    {
+    case PDB_EBX: regs->ebx = val; break;
+    case PDB_ECX: regs->ecx = val; break;
+    case PDB_EDX: regs->edx = val; break;
+    case PDB_ESI: regs->esi = val; break;
+    case PDB_EDI: regs->edi = val; break;
+
+    case PDB_EBP: regs->ebp = val; break;
+    case PDB_EAX: regs->eax = val; break;
+    case PDB_Error_code: regs->error_code = val; break;
+    case PDB_Entry_vector: regs->entry_vector = val; break;
+ 
+    case PDB_EIP: regs->eip = val; break;
+    case PDB_CS:  regs->cs  = val; break;
+    case PDB_EFLAGS: regs->eflags = val; break;
+    case PDB_ESP: regs->esp = val; break;
+    case PDB_SS:  regs->ss  = val; break;
+    case PDB_ES:  regs->es  = val; break;
+    case PDB_DS:  regs->ds  = val; break;
+    case PDB_FS:  regs->fs  = val; break;
+    case PDB_GS:  regs->gs  = val; break;
+    }
+
+    if ( xendebug_write_registers(xc_handle, ctx.domain, ctx.vcpu, regs) )
+    {
+        printf("(pdb) write register (set) error!\n");  fflush(stdout);
+        failwith("write register error");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * dom_read_memory : context_t -> int32 -> int -> int
+ */
+value
+dom_read_memory (value context, value address, value length)
+{
+    CAMLparam3(context, address, length);
+    CAMLlocal2(result, temp);
+
+    context_t ctx;
+    int loop;
+    char *buffer;
+    memory_t my_address = Int32_val(address);
+    u32 my_length = Int_val(length);
+
+    printf ("(pdb) read memory\n");
+
+    decode_context(&ctx, context);
+
+    buffer = malloc(my_length);
+    if ( buffer == NULL )
+    {
+        printf("(pdb) read memory: malloc failed.\n");  fflush(stdout);
+        failwith("read memory error");
+    }
+
+    if ( xendebug_read_memory(xc_handle, ctx.domain, ctx.vcpu, 
+                              my_address, my_length, buffer) )
+    {
+        printf("(pdb) read memory error!\n");  fflush(stdout);
+        failwith("read memory error");
+    }
+
+    result = caml_alloc(2,0);
+    if ( my_length > 0 )                                              /* car */
+    {
+        Store_field(result, 0, Val_int(buffer[my_length - 1] & 0xff));
+    }
+    else
+
+    {
+        Store_field(result, 0, Val_int(0));                    
+    }
+    Store_field(result, 1, Val_int(0));                               /* cdr */
+
+    for (loop = 1; loop < my_length; loop++)
+    {
+        temp = result;
+        result = caml_alloc(2,0);
+        Store_field(result, 0, Val_int(buffer[my_length - loop - 1] & 0xff));
+        Store_field(result, 1, temp);
+    }
+
+    CAMLreturn(result);
+}
+
+/*
+ * dom_write_memory : context_t -> int32 -> int list -> unit
+ */
+value
+dom_write_memory (value context, value address, value val_list)
+{
+    CAMLparam3(context, address, val_list);
+    CAMLlocal1(node);
+
+    context_t ctx;
+
+    char buffer[4096];  /* a big buffer */
+    memory_t  my_address;
+    u32 length = 0;
+
+    printf ("(pdb) write memory\n");
+
+    decode_context(&ctx, context);
+
+    node = val_list;
+    if ( Int_val(node) == 0 )       /* gdb functionalty test uses empty list */
+    {
+        CAMLreturn(Val_unit);
+    }
+
+    while ( Int_val(Field(node,1)) != 0 )
+    {
+        buffer[length++] = Int_val(Field(node, 0));
+        node = Field(node,1);
+    }
+    buffer[length++] = Int_val(Field(node, 0));
+
+    my_address = (memory_t) Int32_val(address);
+
+    if ( xendebug_write_memory(xc_handle, ctx.domain, ctx.vcpu,
+                               my_address, length, buffer) )
+    {
+        printf("(pdb) write memory error!\n");  fflush(stdout);
+        failwith("write memory error");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * dom_continue_target : context_t -> unit
+ */
+value
+dom_continue_target (value context)
+{
+    CAMLparam1(context);
+
+    context_t ctx;
+
+    decode_context(&ctx, context);
+
+    if ( xendebug_continue(xc_handle, ctx.domain, ctx.vcpu) )
+    {
+        printf("(pdb) continue\n");  fflush(stdout);
+        failwith("continue");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * dom_step_target : context_t -> unit
+ */
+value
+dom_step_target (value context)
+{
+    CAMLparam1(context);
+
+    context_t ctx;
+
+    decode_context(&ctx, context);
+
+    if ( xendebug_step(xc_handle, ctx.domain, ctx.vcpu) )
+    {
+        printf("(pdb) step\n");  fflush(stdout);
+        failwith("step");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+
+
+/*
+ * dom_insert_memory_breakpoint : context_t -> int32 -> int list -> unit
+ */
+value
+dom_insert_memory_breakpoint (value context, value address, value length)
+{
+    CAMLparam3(context, address, length);
+
+    context_t ctx;
+    memory_t my_address = (memory_t) Int32_val(address);
+    int my_length = Int_val(length);
+
+    decode_context(&ctx, context);
+
+    printf ("(pdb) insert memory breakpoint 0x%lx %d\n",
+            my_address, my_length);
+
+    if ( xendebug_insert_memory_breakpoint(xc_handle, ctx.domain, ctx.vcpu,
+                                           my_address, my_length) )
+    {
+        printf("(pdb) error: insert memory breakpoint\n");  fflush(stdout);
+        failwith("insert memory breakpoint");
+    }
+
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * dom_remove_memory_breakpoint : context_t -> int32 -> int list -> unit
+ */
+value
+dom_remove_memory_breakpoint (value context, value address, value length)
+{
+    CAMLparam3(context, address, length);
+
+    context_t ctx;
+
+    memory_t my_address = (memory_t) Int32_val(address);
+    int my_length = Int_val(length);
+
+    printf ("(pdb) remove memory breakpoint 0x%lx %d\n",
+            my_address, my_length);
+
+    decode_context(&ctx, context);
+
+    if ( xendebug_remove_memory_breakpoint(xc_handle, 
+                                           ctx.domain, ctx.vcpu,
+                                           my_address, my_length) )
+    {
+        printf("(pdb) error: remove memory breakpoint\n");  fflush(stdout);
+        failwith("remove memory breakpoint");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * dom_attach_debugger : int -> int -> unit
+ */
+value
+dom_attach_debugger (value domain, value vcpu)
+{
+    CAMLparam2(domain, vcpu);
+
+    int my_domain = Int_val(domain);
+    int my_vcpu = Int_val(vcpu);
+
+    printf ("(pdb) attach domain [%d.%d]\n", my_domain, my_vcpu);
+
+    if ( xendebug_attach(xc_handle, my_domain, my_vcpu) )
+    {
+        printf("(pdb) attach error!\n");  fflush(stdout);
+        failwith("attach error");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * dom_detach_debugger : int -> int -> unit
+ */
+value
+dom_detach_debugger (value domain, value vcpu)
+{
+    CAMLparam2(domain, vcpu);
+
+    int my_domain = Int_val(domain);
+    int my_vcpu = Int_val(vcpu);
+
+    printf ("(pdb) detach domain [%d.%d]\n", my_domain, my_vcpu);
+
+    if ( xendebug_detach(xc_handle, my_domain, my_vcpu) )
+    {
+        printf("(pdb) detach error!\n");  fflush(stdout);
+        failwith("detach error");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * dom_pause_target : int -> unit
+ */
+value
+dom_pause_target (value domid)
+{
+    CAMLparam1(domid);
+
+    int my_domid = Int_val(domid);
+
+    printf ("(pdb) pause target %d\n", my_domid);
+
+    xc_domain_pause(xc_handle, my_domid);
+
+    CAMLreturn(Val_unit);
+}
+
+/****************************************************************************/
+/****************************************************************************/
+
+/*
+ * query_domain_stop : unit -> (int * int) list
+ */
+value
+query_domain_stop (value unit)
+{
+    CAMLparam1(unit);
+    CAMLlocal3(result, temp, node);
+
+    int max_domains = 20;
+    int dom_list[max_domains];
+    int loop, count;
+
+    count = xendebug_query_domain_stop(xc_handle, dom_list, max_domains);
+    if ( count < 0 )
+    {
+        printf("(pdb) query domain stop!\n");  fflush(stdout);
+        failwith("query domain stop");
+    }
+
+    printf ("QDS: %d\n", count);
+    for (loop = 0; loop < count; loop ++)
+        printf ("  %d %d\n", loop, dom_list[loop]);
+
+    result = caml_alloc(2,0);
+    if ( count > 0 )                                                  /* car */
+    {
+        node = caml_alloc(2,0);
+        Store_field(node, 0, Val_int(dom_list[0]));             /* domain id */
+        Store_field(node, 1, Val_int(0));                            /* vcpu */
+        Store_field(result, 0, node);
+    }
+    else
+    {
+        Store_field(result, 0, Val_int(0));                    
+    }
+    Store_field(result, 1, Val_int(0));                               /* cdr */
+
+    for ( loop = 1; loop < count; loop++ )
+    {
+        temp = result;
+        result = caml_alloc(2,0);
+        node = caml_alloc(2,0);
+        Store_field(node, 0, Val_int(dom_list[loop]));          /* domain id */
+        Store_field(node, 1, Val_int(0));                            /* vcpu */
+        Store_field(result, 0, node);
+        Store_field(result, 1, temp);
+    }
+
+    CAMLreturn(result);
+}
+
+/****************************************************************************/
+
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -Nru a/tools/debugger/pdb/pdb_caml_evtchn.c 
b/tools/debugger/pdb/pdb_caml_evtchn.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/pdb_caml_evtchn.c      2005-06-28 14:01:24 -04:00
@@ -0,0 +1,178 @@
+#include <xc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int xen_evtchn_bind (int evtchn_fd, int idx);
+int xen_evtchn_unbind (int evtchn_fd, int idx);
+
+int
+__evtchn_open (char *filename, int major, int minor)
+{
+    int   evtchn_fd;
+    struct stat st;
+    
+    /* Make sure any existing device file links to correct device. */
+    if ( (lstat(filename, &st) != 0) ||
+         !S_ISCHR(st.st_mode) ||
+         (st.st_rdev != makedev(major, minor)) )
+    {
+        (void)unlink(filename);
+    }
+
+ reopen:
+    evtchn_fd = open(filename, O_RDWR); 
+    if ( evtchn_fd == -1 )
+    {
+        if ( (errno == ENOENT) &&
+             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+             (mknod(filename, S_IFCHR|0600, makedev(major,minor)) == 0) )
+        {
+            goto reopen;
+        }
+        return -errno;
+    }
+
+    return evtchn_fd;
+}
+
+/*
+ * evtchn_open : string -> int -> int -> Unix.file_descr
+ *
+ * OCaml's Unix library doesn't have mknod, so it makes more sense just write
+ * this in C.  This code is from Keir/Andy.
+ */
+value
+evtchn_open (value filename, value major, value minor)
+{
+    CAMLparam3(filename, major, minor);
+
+    char *myfilename = String_val(filename);
+    int   mymajor = Int_val(major);
+    int   myminor = Int_val(minor);
+    int   evtchn_fd;
+
+    evtchn_fd = __evtchn_open(myfilename, mymajor, myminor);
+
+    CAMLreturn(Val_int(evtchn_fd));
+}
+
+/*
+ * evtchn_bind : Unix.file_descr -> int -> unit
+ */
+value
+evtchn_bind (value fd, value idx)
+{
+    CAMLparam2(fd, idx);
+
+    int myfd = Int_val(fd);
+    int myidx = Int_val(idx);
+
+    if ( xen_evtchn_bind(myfd, myidx) < 0 )
+    {
+        printf("(pdb) evtchn_bind error!\n");  fflush(stdout);
+        failwith("evtchn_bind error");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * evtchn_unbind : Unix.file_descr -> int -> unit
+ */
+value
+evtchn_unbind (value fd, value idx)
+{
+    CAMLparam2(fd, idx);
+
+    int myfd = Int_val(fd);
+    int myidx = Int_val(idx);
+
+    if ( xen_evtchn_unbind(myfd, myidx) < 0 )
+    {
+        printf("(pdb) evtchn_unbind error!\n");  fflush(stdout);
+        failwith("evtchn_unbind error");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * evtchn_read : Unix.file_descr -> int
+ */
+value
+evtchn_read (value fd)
+{
+    CAMLparam1(fd);
+
+    u16 v;
+    int bytes;
+    int rc = -1;
+    int myfd = Int_val(fd);
+
+    while ( (bytes = read(myfd, &v, sizeof(v))) == -1 )
+    {
+        if ( errno == EINTR )  continue;
+        rc = -errno;
+        goto exit;
+    }
+    
+    if ( bytes == sizeof(v) )
+        rc = v;
+    
+ exit:
+    CAMLreturn(Val_int(rc));
+}
+
+
+/*
+ * evtchn_close : Unix.file_descr -> unit
+ */
+value
+evtchn_close (value fd)
+{
+    CAMLparam1(fd);
+    int myfd = Int_val(fd);
+
+    (void)close(myfd);
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * evtchn_unmask : Unix.file_descr -> int -> unit
+ */
+value
+evtchn_unmask (value fd, value idx)
+{
+    CAMLparam1(fd);
+
+    int myfd = Int_val(fd);
+    u16 myidx = Int_val(idx);
+
+    (void)write(myfd, &myidx, sizeof(myidx));
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nru a/tools/debugger/pdb/pdb_caml_process.c 
b/tools/debugger/pdb/pdb_caml_process.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/pdb_caml_process.c     2005-06-28 14:01:24 -04:00
@@ -0,0 +1,543 @@
+/*
+ * pdb_caml_process.c
+ *
+ * http://www.cl.cam.ac.uk/netos/pdb
+ *
+ * PDB's OCaml interface library for debugging processes
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#include <xc.h>
+#include <xen/xen.h>
+#include <xen/io/domain_controller.h>
+#include <xen/linux/privcmd.h>
+#include "pdb_module.h"
+#include "pdb_caml_xen.h"
+
+/* this order comes from linux-2.6.11/include/asm-i386/ptrace.h */
+enum x86_registers { LINUX_EBX, LINUX_ECX, LINUX_EDX, LINUX_ESI, LINUX_EDI,
+                     LINUX_EBP, LINUX_EAX, LINUX_DS,  LINUX_ES,  LINUX_FS,
+                     LINUX_GS,  LINUX_ORIG_EAX, LINUX_EIP, LINUX_CS, LINUX_EFL,
+                     LINUX_ESP, LINUX_SS };
+#define FRAME_SIZE 17
+
+typedef struct
+{
+    int domain;
+    int process;
+    int evtchn;
+    pdb_front_ring_t *ring;
+} context_t;
+
+#define decode_context(_ctx, _ocaml)   \
+{  \
+    (_ctx)->domain  = Int_val(Field((_ocaml),0));  \
+    (_ctx)->process = Int_val(Field((_ocaml),1));  \
+    (_ctx)->evtchn  = Int_val(Field((_ocaml),2));  \
+    (_ctx)->ring    =  (pdb_front_ring_t *)Int32_val(Field((_ocaml),3));  \
+}
+
+#define encode_context(_ctx, _ocaml)  \
+{  \
+    (_ocaml) = caml_alloc_tuple(2);  \
+    Store_field((_ocaml), 0, Val_int((_ctx)->domain));  \
+    Store_field((_ocaml), 1, Val_int((_ctx)->process));  \
+}
+
+/*
+ * send a request to a pdb domain backend.
+ *
+ * puts the request on a ring and kicks the backend using an event channel.
+ */
+static void
+send_request (pdb_front_ring_t *pdb_ring, int evtchn, pdb_request_t *request)
+{
+    pdb_request_t    *req;
+
+    req = RING_GET_REQUEST(pdb_ring, pdb_ring->req_prod_pvt);
+
+    memcpy(req, request, sizeof(pdb_request_t));
+
+    pdb_ring->req_prod_pvt++;
+
+    RING_PUSH_REQUESTS(pdb_ring);
+    xc_evtchn_send(xc_handle, evtchn);
+}
+
+/*
+ * read a response from a pdb domain backend.
+ *
+ * grabs the response off a ring.
+ */
+static void
+read_response (pdb_front_ring_t *pdb_ring, pdb_response_p response)
+{
+    RING_IDX loop, rp;
+
+    rp = pdb_ring->sring->rsp_prod;
+    rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+    for ( loop = pdb_ring->rsp_cons; loop != rp; loop++ )
+    {
+        pdb_response_p resp;
+
+        resp = RING_GET_RESPONSE(pdb_ring, loop);
+        memcpy(response, resp, sizeof(pdb_response_t));
+
+        /*        
+        printf ("got response %x %x %x\n", response->operation, 
+                response->status, response->value);
+        */
+    }
+    pdb_ring->rsp_cons = loop;
+}
+
+/*
+ * process_handle_response : int32 -> unit
+ */
+
+value
+process_handle_response (value ring)
+{
+    CAMLparam1(ring);
+
+    pdb_front_ring_t *my_ring = (pdb_front_ring_t *)Int32_val(ring);
+    pdb_response_t resp;
+
+    if ( my_ring )
+        read_response(my_ring, &resp);
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * proc_attach_debugger : context_t -> unit
+ */
+value
+proc_attach_debugger (value context)
+{
+    CAMLparam1(context);
+    context_t ctx;
+    pdb_request_t req;
+    pdb_response_t resp;
+
+    decode_context(&ctx, context);
+
+    printf("(pdb) attach process [%d.%d] %d %p\n", ctx.domain, ctx.process,
+           ctx.evtchn, ctx.ring);
+    fflush(stdout);
+
+    req.operation = PDB_OPCODE_ATTACH;
+    req.domain  = ctx.domain;
+    req.process = ctx.process;
+
+    send_request (ctx.ring, ctx.evtchn, &req);
+
+    printf("awaiting response\n");
+    fflush(stdout);
+
+    read_response (ctx.ring, &resp);
+
+    printf("response %d %d\n", resp.operation, resp.status);
+    fflush(stdout);
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * proc_detach_debugger : context_t -> unit
+ */
+value
+proc_detach_debugger (value context)
+{
+    CAMLparam1(context);
+    context_t ctx;
+    pdb_request_t req;
+
+    decode_context(&ctx, context);
+
+    printf("(pdb) detach process [%d.%d] %d %p\n", ctx.domain, ctx.process,
+           ctx.evtchn, ctx.ring);
+    fflush(stdout);
+
+    req.operation = PDB_OPCODE_DETACH;
+    req.domain  = ctx.domain;
+    req.process = ctx.process;
+
+    send_request (ctx.ring, ctx.evtchn, &req);
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * proc_pause_target : int -> unit
+ */
+value
+proc_pause_target (value context)
+{
+    CAMLparam1(context);
+    context_t ctx;
+
+    decode_context(&ctx, context);
+
+    printf("(pdb) pause target %d %d\n", ctx.domain, ctx.process);
+    fflush(stdout);
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * proc_read_registers : context_t -> int32
+ */
+value
+proc_read_registers (value context)
+{
+    CAMLparam1(context);
+    CAMLlocal1(result);
+
+    u32 regs[FRAME_SIZE];
+
+    pdb_request_t req;
+    context_t ctx;
+    int loop;
+
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_RD_REG;
+    req.domain  = ctx.domain;
+    req.process = ctx.process;
+
+    for (loop = 0; loop < FRAME_SIZE; loop++)
+    {
+        pdb_response_t resp;
+
+        req.u.rd_reg.reg = loop;
+        send_request(ctx.ring, ctx.evtchn, &req);
+        read_response(ctx.ring, &resp);
+        regs[loop] = resp.value;
+    }
+
+    result = caml_alloc_tuple(16);
+
+    Store_field(result,  0, caml_copy_int32(regs[LINUX_EAX]));
+    Store_field(result,  1, caml_copy_int32(regs[LINUX_ECX]));
+    Store_field(result,  2, caml_copy_int32(regs[LINUX_EDX]));
+    Store_field(result,  3, caml_copy_int32(regs[LINUX_EBX]));
+    Store_field(result,  4, caml_copy_int32(regs[LINUX_ESP]));
+    Store_field(result,  5, caml_copy_int32(regs[LINUX_EBP]));
+    Store_field(result,  6, caml_copy_int32(regs[LINUX_ESI]));
+    Store_field(result,  7, caml_copy_int32(regs[LINUX_EDI]));
+    Store_field(result,  8, caml_copy_int32(regs[LINUX_EIP]));
+    Store_field(result,  9, caml_copy_int32(regs[LINUX_EFL]));
+    Store_field(result, 10, caml_copy_int32(regs[LINUX_CS]));          /* 16 */
+    Store_field(result, 11, caml_copy_int32(regs[LINUX_SS]));          /* 16 */
+    Store_field(result, 12, caml_copy_int32(regs[LINUX_DS]));          /* 16 */
+    Store_field(result, 13, caml_copy_int32(regs[LINUX_ES]));          /* 16 */
+    Store_field(result, 14, caml_copy_int32(regs[LINUX_FS]));          /* 16 */
+    Store_field(result, 15, caml_copy_int32(regs[LINUX_GS]));          /* 16 */
+
+    CAMLreturn(result);
+}
+
+
+/*
+ * proc_write_register : context_t -> register -> int32 -> unit
+ */
+value
+proc_write_register (value context, value reg, value newval)
+{
+    CAMLparam3(context, reg, newval);
+
+    int my_reg = Int_val(reg);
+    unsigned long my_newval = Int32_val(newval);
+
+    context_t ctx;
+    pdb_request_t req;
+    pdb_response_t resp;
+
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_WR_REG;
+    req.domain = ctx.domain;
+    req.process = ctx.process;
+    req.u.wr_reg.value = my_newval;
+
+    switch (my_reg)
+    {
+    case GDB_EAX: req.u.wr_reg.reg = LINUX_EAX; break;
+    case GDB_ECX: req.u.wr_reg.reg = LINUX_ECX; break;
+    case GDB_EDX: req.u.wr_reg.reg = LINUX_EDX; break;
+    case GDB_EBX: req.u.wr_reg.reg = LINUX_EBX; break;
+
+    case GDB_ESP: req.u.wr_reg.reg = LINUX_ESP; break;
+    case GDB_EBP: req.u.wr_reg.reg = LINUX_EBP; break;
+    case GDB_ESI: req.u.wr_reg.reg = LINUX_ESI; break;
+    case GDB_EDI: req.u.wr_reg.reg = LINUX_EDI; break;
+
+    case GDB_EIP: req.u.wr_reg.reg = LINUX_EIP; break;
+    case GDB_EFL: req.u.wr_reg.reg = LINUX_EFL; break;
+ 
+    case GDB_CS:  req.u.wr_reg.reg = LINUX_CS; break;
+    case GDB_SS:  req.u.wr_reg.reg = LINUX_SS; break;
+    case GDB_DS:  req.u.wr_reg.reg = LINUX_DS; break;
+    case GDB_ES:  req.u.wr_reg.reg = LINUX_ES; break;
+    case GDB_FS:  req.u.wr_reg.reg = LINUX_FS; break;
+    case GDB_GS:  req.u.wr_reg.reg = LINUX_GS; break;
+    }
+
+    send_request(ctx.ring, ctx.evtchn, &req);
+    read_response(ctx.ring, &resp);
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * proc_read_memory : context_t -> int32 -> int -> int
+ */
+value
+proc_read_memory (value context, value address, value length)
+{
+    CAMLparam3(context, address, length);
+    CAMLlocal2(result, temp);
+
+    context_t ctx;
+    int loop;
+    char *buffer;
+    /*    memory_t my_address = Int32_val(address); */
+    u32 my_length = Int_val(length);
+
+    printf ("(pdb) read memory\n");
+
+    decode_context(&ctx, context);
+
+    buffer = malloc(my_length);
+    if ( buffer == NULL )
+    {
+        printf("(pdb) read memory: malloc failed.\n");  fflush(stdout);
+        failwith("read memory error");
+    }
+
+    /*
+    if ( xendebug_read_memory(xc_handle, ctx.domain, ctx.vcpu, 
+                              my_address, my_length, buffer) )
+    {
+        printf("(pdb) read memory error!\n");  fflush(stdout);
+        failwith("read memory error");
+    }
+    */
+
+    memset(buffer, 0xff, my_length);
+
+    result = caml_alloc(2,0);
+    if ( my_length > 0 )                                              /* car */
+    {
+        Store_field(result, 0, Val_int(buffer[my_length - 1] & 0xff));
+    }
+    else
+
+    {
+        Store_field(result, 0, Val_int(0));                    
+    }
+    Store_field(result, 1, Val_int(0));                               /* cdr */
+
+    for (loop = 1; loop < my_length; loop++)
+    {
+        temp = result;
+        result = caml_alloc(2,0);
+        Store_field(result, 0, Val_int(buffer[my_length - loop - 1] & 0xff));
+        Store_field(result, 1, temp);
+    }
+
+    CAMLreturn(result);
+}
+
+/*
+ * proc_write_memory : context_t -> int32 -> int list -> unit
+ */
+value
+proc_write_memory (value context, value address, value val_list)
+{
+    CAMLparam3(context, address, val_list);
+    CAMLlocal1(node);
+
+    context_t ctx;
+
+    char buffer[4096];  /* a big buffer */
+    memory_t  my_address;
+    u32 length = 0;
+
+    printf ("(pdb) write memory\n");
+
+    decode_context(&ctx, context);
+
+    node = val_list;
+    if ( Int_val(node) == 0 )       /* gdb functionalty test uses empty list */
+    {
+        CAMLreturn(Val_unit);
+    }
+
+    while ( Int_val(Field(node,1)) != 0 )
+    {
+        buffer[length++] = Int_val(Field(node, 0));
+        node = Field(node,1);
+    }
+    buffer[length++] = Int_val(Field(node, 0));
+
+    my_address = (memory_t) Int32_val(address);
+
+    /*
+    if ( xendebug_write_memory(xc_handle, ctx.domain, ctx.vcpu,
+                               my_address, length, buffer) )
+    {
+        printf("(pdb) write memory error!\n");  fflush(stdout);
+        failwith("write memory error");
+    }
+    */
+    {
+        int loop;
+        for (loop = 0; loop < length; loop++)
+        {
+            printf (" %02x", buffer[loop]);
+        }
+        printf ("\n");
+    }
+
+    CAMLreturn(Val_unit);
+}
+
+
+
+/*
+ * proc_continue_target : context_t -> unit
+ */
+value
+proc_continue_target (value context)
+{
+    CAMLparam1(context);
+
+    context_t ctx;
+
+    decode_context(&ctx, context);
+
+    /*
+    if ( xendebug_continue(xc_handle, ctx.domain, ctx.vcpu) )
+    {
+        printf("(pdb) continue\n");  fflush(stdout);
+        failwith("continue");
+    }
+    */
+    printf ("CONTINUE\n");
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * proc_step_target : context_t -> unit
+ */
+value
+proc_step_target (value context)
+{
+    CAMLparam1(context);
+
+    context_t ctx;
+
+    decode_context(&ctx, context);
+
+    /*
+    if ( xendebug_step(xc_handle, ctx.domain, ctx.vcpu) )
+    {
+        printf("(pdb) step\n");  fflush(stdout);
+        failwith("step");
+    }
+    */
+    printf ("STEP\n");
+
+    CAMLreturn(Val_unit);
+}
+
+
+
+/*
+ * proc_insert_memory_breakpoint : context_t -> int32 -> int list -> unit
+ */
+value
+proc_insert_memory_breakpoint (value context, value address, value length)
+{
+    CAMLparam3(context, address, length);
+
+    context_t ctx;
+    memory_t my_address = (memory_t) Int32_val(address);
+    int my_length = Int_val(length);
+
+    decode_context(&ctx, context);
+
+    printf ("(pdb) insert memory breakpoint 0x%lx %d\n",
+            my_address, my_length);
+
+    /*
+    if ( xendebug_insert_memory_breakpoint(xc_handle, ctx.domain, ctx.vcpu,
+                                           my_address, my_length) )
+    {
+        printf("(pdb) error: insert memory breakpoint\n");  fflush(stdout);
+        failwith("insert memory breakpoint");
+    }
+    */
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * proc_remove_memory_breakpoint : context_t -> int32 -> int list -> unit
+ */
+value
+proc_remove_memory_breakpoint (value context, value address, value length)
+{
+    CAMLparam3(context, address, length);
+
+    context_t ctx;
+
+    memory_t my_address = (memory_t) Int32_val(address);
+    int my_length = Int_val(length);
+
+    printf ("(pdb) remove memory breakpoint 0x%lx %d\n",
+            my_address, my_length);
+
+    decode_context(&ctx, context);
+
+    /*
+    if ( xendebug_remove_memory_breakpoint(xc_handle, 
+                                           ctx.domain, ctx.vcpu,
+                                           my_address, my_length) )
+    {
+        printf("(pdb) error: remove memory breakpoint\n");  fflush(stdout);
+        failwith("remove memory breakpoint");
+    }
+    */
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
+
diff -Nru a/tools/debugger/pdb/pdb_caml_xc.c b/tools/debugger/pdb/pdb_caml_xc.c
--- a/tools/debugger/pdb/pdb_caml_xc.c  2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/pdb_caml_xc.c  2005-06-28 14:01:24 -04:00
@@ -3,7 +3,7 @@
  *
  * http://www.cl.cam.ac.uk/netos/pdb
  *
- * OCaml to libxc interface library for PDB
+ * PDB's OCaml interface library for debugging domains
  */
 
 #include <xc.h>
@@ -18,38 +18,9 @@
 #include <caml/memory.h>
 #include <caml/mlvalues.h>
 
-int pdb_evtchn_bind_virq (int xc_handle, int virq, int *port);
-int xen_evtchn_bind (int evtchn_fd, int idx);
-int xen_evtchn_unbind (int evtchn_fd, int idx);
+#include "pdb_caml_xen.h"
 
-/* this order comes from xen/include/public/arch-x86_32.h */
-enum x86_registers { PDB_EBX, PDB_ECX, PDB_EDX, PDB_ESI, PDB_EDI,
-                     PDB_EBP, PDB_EAX, PDB_Error_code, PDB_Entry_vector, 
-                     PDB_EIP, PDB_CS, PDB_EFLAGS, PDB_ESP, PDB_SS,
-                     PDB_ES, PDB_DS, PDB_FS, PDB_GS };
-
-static void dump_regs (cpu_user_regs_t *ctx);
-
-static int xc_handle = -1;
-
-typedef struct
-{
-    int domain;
-    int vcpu;
-} context_t;
-
-#define decode_context(_ctx, _ocaml)   \
-{  \
-    (_ctx)->domain = Int_val(Field((_ocaml),0));  \
-    (_ctx)->vcpu = Int_val(Field((_ocaml),1));  \
-}
-
-#define encode_context(_ctx, _ocaml)  \
-{  \
-    (_ocaml) = caml_alloc_tuple(2);  \
-    Store_field((_ocaml), 0, Val_int((_ctx)->domain));  \
-    Store_field((_ocaml), 1, Val_int((_ctx)->vcpu));  \
-}
+int xc_handle = -1;
 
 
 /****************************************************************************/
@@ -91,210 +62,6 @@
     CAMLreturn(Val_unit);
 }
 
-/*
- * read_registers : context_t -> int32
- */
-value
-read_registers (value context)
-{
-    CAMLparam1(context);
-    CAMLlocal1(result);
-
-    cpu_user_regs_t *regs;
-    context_t ctx;
-
-    decode_context(&ctx, context);
-
-    if ( xendebug_read_registers(xc_handle, ctx.domain, ctx.vcpu, &regs) )
-    {
-        printf("(pdb) read registers error!\n");  fflush(stdout);
-        failwith("read registers error");
-    }
-
-    dump_regs(regs);
-
-    result = caml_alloc_tuple(18);                                  /* FIXME */
-
-    Store_field(result,  0, caml_copy_int32(regs->ebx));
-    Store_field(result,  1, caml_copy_int32(regs->ecx));
-    Store_field(result,  2, caml_copy_int32(regs->edx));
-    Store_field(result,  3, caml_copy_int32(regs->esi));
-    Store_field(result,  4, caml_copy_int32(regs->edi));
-    Store_field(result,  5, caml_copy_int32(regs->ebp));
-    Store_field(result,  6, caml_copy_int32(regs->eax));
-    Store_field(result,  7, caml_copy_int32(regs->error_code));        /* 16 */
-    Store_field(result,  8, caml_copy_int32(regs->entry_vector));      /* 16 */
-    Store_field(result,  9, caml_copy_int32(regs->eip));
-    Store_field(result, 10, caml_copy_int32(regs->cs));                /* 16 */
-    Store_field(result, 11, caml_copy_int32(regs->eflags));
-    Store_field(result, 12, caml_copy_int32(regs->esp));
-    Store_field(result, 13, caml_copy_int32(regs->ss));                /* 16 */
-    Store_field(result, 14, caml_copy_int32(regs->es));                /* 16 */
-    Store_field(result, 15, caml_copy_int32(regs->ds));                /* 16 */
-    Store_field(result, 16, caml_copy_int32(regs->fs));                /* 16 */
-    Store_field(result, 17, caml_copy_int32(regs->gs));                /* 16 */
-
-    CAMLreturn(result);
-}
-
-
-/*
- * write_register : context_t -> register -> int32 -> unit
- */
-value
-write_register (value context, value reg, value newval)
-{
-    CAMLparam3(context, reg, newval);
-
-    int my_reg = Int_val(reg);
-    int val = Int32_val(newval);
-
-    context_t ctx;
-    cpu_user_regs_t *regs;
-
-    printf("(pdb) write register\n");
-
-    decode_context(&ctx, context);
-
-    if ( xendebug_read_registers(xc_handle, ctx.domain, ctx.vcpu, &regs) )
-    {
-        printf("(pdb) write register (get) error!\n");  fflush(stdout);
-        failwith("write register error");
-    }
-
-    switch (my_reg)
-    {
-    case PDB_EBX: regs->ebx = val; break;
-    case PDB_ECX: regs->ecx = val; break;
-    case PDB_EDX: regs->edx = val; break;
-    case PDB_ESI: regs->esi = val; break;
-    case PDB_EDI: regs->edi = val; break;
-
-    case PDB_EBP: regs->ebp = val; break;
-    case PDB_EAX: regs->eax = val; break;
-    case PDB_Error_code: regs->error_code = val; break;
-    case PDB_Entry_vector: regs->entry_vector = val; break;
- 
-    case PDB_EIP: regs->eip = val; break;
-    case PDB_CS:  regs->cs  = val; break;
-    case PDB_EFLAGS: regs->eflags = val; break;
-    case PDB_ESP: regs->esp = val; break;
-    case PDB_SS:  regs->ss  = val; break;
-    case PDB_ES:  regs->es  = val; break;
-    case PDB_DS:  regs->ds  = val; break;
-    case PDB_FS:  regs->fs  = val; break;
-    case PDB_GS:  regs->gs  = val; break;
-    }
-
-    if ( xendebug_write_registers(xc_handle, ctx.domain, ctx.vcpu, regs) )
-    {
-        printf("(pdb) write register (set) error!\n");  fflush(stdout);
-        failwith("write register error");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
-/*
- * read_memory : context_t -> int32 -> int -> int
- */
-value
-read_memory (value context, value address, value length)
-{
-    CAMLparam3(context, address, length);
-    CAMLlocal2(result, temp);
-
-    context_t ctx;
-    int loop;
-    char *buffer;
-    memory_t my_address = Int32_val(address);
-    u32 my_length = Int_val(length);
-
-    printf ("(pdb) read memory\n");
-
-    decode_context(&ctx, context);
-
-    buffer = malloc(my_length);
-    if (buffer == NULL)
-    {
-        printf("(pdb) read memory: malloc failed.\n");  fflush(stdout);
-        failwith("read memory error");
-    }
-
-    if ( xendebug_read_memory(xc_handle, ctx.domain, ctx.vcpu, 
-                              my_address, my_length, buffer) )
-    {
-        printf("(pdb) read memory error!\n");  fflush(stdout);
-        failwith("read memory error");
-    }
-
-    result = caml_alloc(2,0);
-    if ( my_length > 0 )                                              /* car */
-    {
-        Store_field(result, 0, Val_int(buffer[my_length - 1] & 0xff));
-    }
-    else
-
-    {
-        Store_field(result, 0, Val_int(0));                    
-    }
-    Store_field(result, 1, Val_int(0));                               /* cdr */
-
-    for (loop = 1; loop < my_length; loop++)
-    {
-        temp = result;
-        result = caml_alloc(2,0);
-        Store_field(result, 0, Val_int(buffer[my_length - loop - 1] & 0xff));
-        Store_field(result, 1, temp);
-    }
-
-    CAMLreturn(result);
-}
-
-/*
- * write_memory : context_t -> int32 -> int list -> unit
- */
-value
-write_memory (value context, value address, value val_list)
-{
-    CAMLparam3(context, address, val_list);
-    CAMLlocal1(node);
-
-    context_t ctx;
-
-    char buffer[4096];  /* a big buffer */
-    memory_t  my_address;
-    u32 length = 0;
-
-    printf ("(pdb) write memory\n");
-
-    decode_context(&ctx, context);
-
-    node = val_list;
-    if ( Int_val(node) == 0 )       /* gdb functionalty test uses empty list */
-    {
-        CAMLreturn(Val_unit);
-    }
-
-    while ( Int_val(Field(node,1)) != 0 )
-    {
-        buffer[length++] = Int_val(Field(node, 0));
-        node = Field(node,1);
-    }
-    buffer[length++] = Int_val(Field(node, 0));
-
-    my_address = (memory_t) Int32_val(address);
-
-    if ( xendebug_write_memory(xc_handle, ctx.domain, ctx.vcpu,
-                               my_address, length, buffer) )
-    {
-        printf("(pdb) write memory error!\n");  fflush(stdout);
-        failwith("write memory error");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
 
 /*********************************************************************/
 
@@ -322,153 +89,6 @@
 }
 
 /*
- * continue_target : context_t -> unit
- */
-value
-continue_target (value context)
-{
-    CAMLparam1(context);
-
-    context_t ctx;
-
-    decode_context(&ctx, context);
-
-    if ( xendebug_continue(xc_handle, ctx.domain, ctx.vcpu) )
-    {
-        printf("(pdb) continue\n");  fflush(stdout);
-        failwith("continue");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
-/*
- * step_target : context_t -> unit
- */
-value
-step_target (value context)
-{
-    CAMLparam1(context);
-
-    context_t ctx;
-
-    decode_context(&ctx, context);
-
-    if ( xendebug_step(xc_handle, ctx.domain, ctx.vcpu) )
-    {
-        printf("(pdb) step\n");  fflush(stdout);
-        failwith("step");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
-
-
-/*
- * insert_memory_breakpoint : context_t -> int32 -> int list -> unit
- */
-value
-insert_memory_breakpoint (value context, value address, value length)
-{
-    CAMLparam3(context, address, length);
-
-    context_t ctx;
-    memory_t my_address = (memory_t) Int32_val(address);
-    int my_length = Int_val(length);
-
-    decode_context(&ctx, context);
-
-    printf ("(pdb) insert memory breakpoint 0x%lx %d\n",
-            my_address, my_length);
-
-    if ( xendebug_insert_memory_breakpoint(xc_handle, ctx.domain, ctx.vcpu,
-                                           my_address, my_length) )
-    {
-        printf("(pdb) error: insert memory breakpoint\n");  fflush(stdout);
-        failwith("insert memory breakpoint");
-    }
-
-
-    CAMLreturn(Val_unit);
-}
-
-/*
- * remove_memory_breakpoint : context_t -> int32 -> int list -> unit
- */
-value
-remove_memory_breakpoint (value context, value address, value length)
-{
-    CAMLparam3(context, address, length);
-
-    context_t ctx;
-
-    memory_t my_address = (memory_t) Int32_val(address);
-    int my_length = Int_val(length);
-
-    printf ("(pdb) remove memory breakpoint 0x%lx %d\n",
-            my_address, my_length);
-
-    decode_context(&ctx, context);
-
-    if ( xendebug_remove_memory_breakpoint(xc_handle, 
-                                           ctx.domain, ctx.vcpu,
-                                           my_address, my_length) )
-    {
-        printf("(pdb) error: remove memory breakpoint\n");  fflush(stdout);
-        failwith("remove memory breakpoint");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
-/*
- * attach_debugger : int -> int -> unit
- */
-value
-attach_debugger (value domain, value vcpu)
-{
-    CAMLparam2(domain, vcpu);
-
-    int my_domain = Int_val(domain);
-    int my_vcpu = Int_val(vcpu);
-
-    printf ("(pdb) attach domain [%d.%d]\n", my_domain, my_vcpu);
-
-    if ( xendebug_attach(xc_handle, my_domain, my_vcpu) )
-    {
-        printf("(pdb) attach error!\n");  fflush(stdout);
-        failwith("attach error");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
-
-/*
- * detach_debugger : int -> int -> unit
- */
-value
-detach_debugger (value domain, value vcpu)
-{
-    CAMLparam2(domain, vcpu);
-
-    int my_domain = Int_val(domain);
-    int my_vcpu = Int_val(vcpu);
-
-    printf ("(pdb) detach domain [%d.%d]\n", my_domain, my_vcpu);
-
-    if ( xendebug_detach(xc_handle, my_domain, my_vcpu) )
-    {
-        printf("(pdb) detach error!\n");  fflush(stdout);
-        failwith("detach error");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
-
-/*
  * debugger_status : unit -> unit
  */
 value
@@ -476,25 +96,6 @@
 {
     CAMLparam1(unit);
 
-    printf ("(pdb) debugger status\n");
-
-    CAMLreturn(Val_unit);
-}
-
-/*
- * pause_target : int -> unit
- */
-value
-pause_target (value domid)
-{
-    CAMLparam1(domid);
-
-    int my_domid = Int_val(domid);
-
-    printf ("(pdb) pause target %d\n", my_domid);
-
-    xc_domain_pause(xc_handle, my_domid);
-
     CAMLreturn(Val_unit);
 }
 
@@ -502,108 +103,6 @@
 /****************************************************************************/
 
 /*
- * query_domain_stop : unit -> (int * int) list
- */
-value
-query_domain_stop (value unit)
-{
-    CAMLparam1(unit);
-    CAMLlocal3(result, temp, node);
-
-    int max_domains = 20;
-    int dom_list[max_domains];
-    int loop, count;
-
-    count = xendebug_query_domain_stop(xc_handle, dom_list, max_domains);
-    if ( count < 0 )
-    {
-        printf("(pdb) query domain stop!\n");  fflush(stdout);
-        failwith("query domain stop");
-    }
-
-    printf ("QDS: %d\n", count);
-    for (loop = 0; loop < count; loop ++)
-        printf ("  %d %d\n", loop, dom_list[loop]);
-
-    result = caml_alloc(2,0);
-    if ( count > 0 )                                                  /* car */
-    {
-        node = caml_alloc(2,0);
-        Store_field(node, 0, Val_int(dom_list[0]));             /* domain id */
-        Store_field(node, 1, Val_int(0));                            /* vcpu */
-        Store_field(result, 0, node);
-    }
-    else
-    {
-        Store_field(result, 0, Val_int(0));                    
-    }
-    Store_field(result, 1, Val_int(0));                               /* cdr */
-
-    for ( loop = 1; loop < count; loop++ )
-    {
-        temp = result;
-        result = caml_alloc(2,0);
-        node = caml_alloc(2,0);
-        Store_field(node, 0, Val_int(dom_list[loop]));          /* domain id */
-        Store_field(node, 1, Val_int(0));                            /* vcpu */
-        Store_field(result, 0, node);
-        Store_field(result, 1, temp);
-    }
-
-    CAMLreturn(result);
-}
-
-/****************************************************************************/
-/****************************************************************************/
-
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-/*
- * evtchn_open : string -> int -> int -> Unix.file_descr
- *
- * OCaml's Unix library doesn't have mknod, so it makes more sense just write
- * this in C.  This code is from Keir/Andy.
- */
-value
-evtchn_open (value filename, value major, value minor)
-{
-    CAMLparam3(filename, major, minor);
-
-    char *myfilename = String_val(filename);
-    int   mymajor = Int_val(major);
-    int   myminor = Int_val(minor);
-    int   evtchn_fd;
-    struct stat st;
-    
-    /* Make sure any existing device file links to correct device. */
-    if ( (lstat(myfilename, &st) != 0) ||
-         !S_ISCHR(st.st_mode) ||
-         (st.st_rdev != makedev(mymajor, myminor)) )
-    {
-        (void)unlink(myfilename);
-    }
-
- reopen:
-    evtchn_fd = open(myfilename, O_RDWR); 
-    if ( evtchn_fd == -1 )
-    {
-        if ( (errno == ENOENT) &&
-             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
-             (mknod(myfilename, S_IFCHR|0600, makedev(mymajor,myminor)) == 0) )
-        {
-            goto reopen;
-        }
-        return -errno;
-    }
-
-    CAMLreturn(Val_int(evtchn_fd));
-}
-
-/*
  * evtchn_bind_virq : int -> int
  */
 value
@@ -612,8 +111,9 @@
     CAMLparam1(virq);
 
     int port;
+    int my_virq = Int_val(virq);
 
-    if ( pdb_evtchn_bind_virq(xc_handle, Int_val(virq), &port) < 0 )
+    if ( xc_evtchn_bind_virq(xc_handle, my_virq, &port) < 0 )
     {
         printf("(pdb) evtchn_bind_virq error!\n");  fflush(stdout);
         failwith("evtchn_bind_virq error");
@@ -623,102 +123,40 @@
 }
 
 /*
- * evtchn_bind : Unix.file_descr -> int -> unit
- */
-value
-evtchn_bind (value fd, value idx)
-{
-    CAMLparam2(fd, idx);
-
-    int myfd = Int_val(fd);
-    int myidx = Int_val(idx);
-
-    if ( xen_evtchn_bind(myfd, myidx) < 0 )
-    {
-        printf("(pdb) evtchn_bind error!\n");  fflush(stdout);
-        failwith("evtchn_bind error");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
-/*
- * evtchn_unbind : Unix.file_descr -> int -> unit
+ * evtchn_bind_interdomain : int -> int * int
  */
 value
-evtchn_unbind (value fd, value idx)
+evtchn_bind_interdomain (value remote_domain)
 {
-    CAMLparam2(fd, idx);
+    CAMLparam1(remote_domain);
+    CAMLlocal1(result);
 
-    int myfd = Int_val(fd);
-    int myidx = Int_val(idx);
+    int my_remote_domain = Int_val(remote_domain);
+    int local_domain = 0;
+    int local_port = 0;
+    int remote_port = 0;
 
-    if ( xen_evtchn_unbind(myfd, myidx) < 0 )
+    if ( xc_evtchn_bind_interdomain(xc_handle, local_domain, my_remote_domain,
+                                    &local_port, &remote_port) < 0 )
     {
-        printf("(pdb) evtchn_unbind error!\n");  fflush(stdout);
-        failwith("evtchn_unbind error");
+        printf("(pdb) evtchn_bind_interdomain error!\n");  fflush(stdout);
+        failwith("evtchn_bind_interdomain error");
     }
 
-    CAMLreturn(Val_unit);
-}
+    result = caml_alloc_tuple(2);                                   /* FIXME */
+    Store_field(result, 0, Val_int(local_port));
+    Store_field(result, 1, Val_int(remote_port));
 
-/*
- * evtchn_read : Unix.file_descr -> int
- */
-value
-evtchn_read (value fd)
-{
-    CAMLparam1(fd);
-
-    u16 v;
-    int bytes;
-    int rc = -1;
-    int myfd = Int_val(fd);
-
-    while ( (bytes = read(myfd, &v, sizeof(v))) == -1 )
-    {
-        if ( errno == EINTR )  continue;
-        rc = -errno;
-        goto exit;
-    }
-    
-    if ( bytes == sizeof(v) )
-        rc = v;
-    
- exit:
-    CAMLreturn(Val_int(rc));
+    CAMLreturn(result);
 }
 
-
-/*
- * evtchn_close : Unix.file_descr -> unit
- */
-value
-evtchn_close (value fd)
+void *
+map_ring(u32 dom, unsigned long mfn )
 {
-    CAMLparam1(fd);
-    int myfd = Int_val(fd);
-
-    (void)close(myfd);
-
-    CAMLreturn(Val_unit);
+    return xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
+                                PROT_READ | PROT_WRITE, mfn);
 }
 
-/*
- * evtchn_unmask : Unix.file_descr -> int -> unit
- */
-value
-evtchn_unmask (value fd, value idx)
-{
-    CAMLparam1(fd);
-
-    int myfd = Int_val(fd);
-    u16 myidx = Int_val(idx);
-
-    (void)write(myfd, &myidx, sizeof(myidx));
-
-    CAMLreturn(Val_unit);
-}
 
 /*
  * Local variables:
diff -Nru a/tools/debugger/pdb/pdb_caml_xcs.c 
b/tools/debugger/pdb/pdb_caml_xcs.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/pdb_caml_xcs.c 2005-06-28 14:01:24 -04:00
@@ -0,0 +1,305 @@
+/*
+ *  xcs stuff
+ *
+ *  this is responsible for establishing the initial connection
+ *  between a backend domain and the pdb server.
+ *
+ *  liberated from xu.c
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <xc.h>
+
+#include <xen/xen.h>
+#include <xen/io/domain_controller.h>
+#include <xen/linux/privcmd.h>
+
+#include <arpa/inet.h>
+#include <xcs_proto.h>
+
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+static int control_fd = -1;
+
+#include "pdb_module.h"
+#include "pdb_caml_xen.h"
+
+void *map_ring(u32 dom, unsigned long mfn );
+
+/*
+ * xcs_initialize_ring : int -> int32 -> int32
+ *
+ * initialize a communications ring
+ * (probably belongs in a different file :)
+ */
+
+value
+xcs_initialize_ring (value domain, value ring)
+{
+    CAMLparam2(domain, ring);
+    int my_domain = Int_val(domain);
+    memory_t my_ring = Int32_val(ring);
+
+    pdb_front_ring_t *front_ring;
+    pdb_sring_t *sring;
+
+    front_ring = (pdb_front_ring_t *)malloc(sizeof(pdb_front_ring_t));
+    if ( front_ring == NULL )
+    {
+        printf("(pdb) xcs initialize ring: malloc failed.\n");  fflush(stdout);
+        failwith("xcs initialize ring: malloc");
+    }
+
+    sring = map_ring(my_domain, my_ring);
+    if ( sring == NULL )
+    {
+        printf("(pdb) xcs initialize ring: map ring failed.\n");fflush(stdout);
+        failwith("xcs initialize ring: map ring");
+    }
+    FRONT_RING_INIT(front_ring, sring, PAGE_SIZE);
+
+    CAMLreturn(caml_copy_int32((unsigned long)front_ring));
+}
+
+
+/*
+ * xcs_write_message : Unix.file_descr -> xcs_message -> unit
+ *
+ * ack a packet
+ */
+value
+xcs_write_message (value data_fd, value msg)
+{
+    CAMLparam2(data_fd, msg);
+    int my_data_fd = Int_val(data_fd);
+    xcs_msg_t my_msg;
+    pdb_connection_p conn;
+
+    my_msg.type = XCS_REQUEST;
+    my_msg.u.control.remote_dom = Int_val(Field(msg,0));
+    my_msg.u.control.msg.type = CMSG_DEBUG;
+    my_msg.u.control.msg.subtype = CMSG_DEBUG_CONNECTION_STATUS;
+    my_msg.u.control.msg.id = 0;
+    my_msg.u.control.msg.length = sizeof(pdb_connection_t);
+
+    conn = (pdb_connection_p)my_msg.u.control.msg.msg;
+
+    conn->status = Int_val(Field(msg,1));
+    conn->ring = Int32_val(Field(msg,2));
+    conn->evtchn = Int_val(Field(msg,3));
+        
+    send(my_data_fd, &my_msg, sizeof(xcs_msg_t), 0);                  /* ack */
+
+    CAMLreturn(Val_unit);
+}
+
+/*
+ * xcs_read_message : Unix.file_descr -> xcs_message
+ *
+ * read pending data on xcs socket.
+ */
+
+value
+xcs_read_message (value data_fd)
+{
+    CAMLparam1(data_fd);
+    CAMLlocal1(result);
+    int my_data_fd = Int_val(data_fd);
+    xcs_msg_t msg;
+
+    if ( read(my_data_fd, &msg, sizeof(xcs_msg_t)) < 0 )
+    {
+        perror("read");
+        failwith("xcs message: read");
+    }
+
+    switch (msg.type)
+    {
+    case XCS_REQUEST :
+    {
+        pdb_connection_p conn;
+
+        if ( msg.u.control.msg.type != CMSG_DEBUG ||
+             msg.u.control.msg.subtype != CMSG_DEBUG_CONNECTION_STATUS )
+        {
+            printf("bogus message type: %d %d\n", 
+                   msg.u.control.msg.type, msg.u.control.msg.subtype);
+            failwith("xcs message: invalid message type");
+        }
+
+        conn = (pdb_connection_p) msg.u.control.msg.msg;
+        
+        result = caml_alloc_tuple(4);                               /* FIXME */
+        Store_field(result, 0, Val_int(msg.u.control.remote_dom)); /* domain */
+        Store_field(result, 1, Val_int(conn->status));             /* status */
+        Store_field(result, 2, caml_copy_int32(conn->ring));         /* ring */
+        Store_field(result, 3, Val_int(0));                   /* OUT: evtchn */
+
+        break;
+    }
+    case XCS_RESPONSE :
+    {
+        printf("[XCS RESPONSE]  type: %d, remote_dom: %d\n", 
+               msg.type, msg.u.control.remote_dom);
+        printf("strange.  we never initiate messages, so what is the ");
+        printf("domain responding to?\n");
+        failwith ("xcs message: resonse");
+        break;
+    }
+    default:
+    {
+        printf("[XCS IGNORE] type: %d\n", msg.type);
+        failwith ("xcs message: unknown");
+        break;
+    }
+    }
+
+    CAMLreturn(result);
+}
+
+/*
+ * xcs_connect : string -> int -> Unix.file_descr
+ */
+
+value
+xcs_connect (value path, value msg_type)
+{
+    CAMLparam2(path, msg_type);
+    char *my_path = String_val(path);
+    int my_msg_type = Int_val(msg_type);
+    struct sockaddr_un addr;
+    u32 session_id = 0;
+    int data_fd;
+    int ret, len;
+    xcs_msg_t msg;
+
+    /* setup control channel connection to xcs */
+
+    control_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if ( control_fd < 0 )
+    {
+        printf("error creating xcs socket!\n");
+        goto fail;
+    }
+
+    addr.sun_family = AF_UNIX;
+    strcpy(addr.sun_path, my_path);
+    len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
+
+    ret = connect(control_fd, (struct sockaddr *)&addr, len);
+    if (ret < 0) 
+    {
+        printf("error connecting to xcs(ctrl)! (%d)\n", errno);
+        goto ctrl_fd_fail;
+    }
+            
+    msg.type = XCS_CONNECT_CTRL;
+    msg.u.connect.session_id = session_id;
+    send(control_fd, &msg, sizeof(xcs_msg_t), 0);
+    /* bug: this should have a timeout & error! */
+    read(control_fd, &msg, sizeof(xcs_msg_t));
+    
+    if (msg.result != XCS_RSLT_OK)
+    {
+        printf("error connecting xcs control channel!\n");
+        goto ctrl_fd_fail;
+    }
+    session_id = msg.u.connect.session_id;
+
+
+    /* setup data channel connection to xcs */
+    
+    data_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if ( data_fd < 0 )
+    {
+        printf("error creating xcs data socket!\n");
+        goto ctrl_fd_fail;
+    }
+    
+    addr.sun_family = AF_UNIX;
+    strcpy(addr.sun_path, my_path);
+    len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
+    
+    ret = connect(data_fd, (struct sockaddr *)&addr, len);
+    if (ret < 0) 
+    {
+        printf("error connecting to xcs(data)! (%d)\n", errno);
+        goto data_fd_fail;
+    }
+
+    msg.type = XCS_CONNECT_DATA;
+    msg.u.connect.session_id = session_id;
+    send(data_fd, &msg, sizeof(xcs_msg_t), 0);
+    read(data_fd, &msg, sizeof(xcs_msg_t));                      /* same bug */
+    
+    if ( msg.result != XCS_RSLT_OK )
+    {
+        printf("error connecting xcs control channel!\n");
+        goto ctrl_fd_fail;
+    }
+
+
+
+    /* now request all messages of a particular type */
+
+    msg.type = XCS_MSG_BIND;
+    msg.u.bind.port = PORT_WILDCARD;
+    msg.u.bind.type = my_msg_type;
+    send(control_fd, &msg, sizeof(xcs_msg_t), 0);
+    read(control_fd, &msg, sizeof(xcs_msg_t));                /* still buggy */
+
+    if (msg.result != XCS_RSLT_OK) {
+        printf ("error: MSG BIND\n");
+       goto bind_fail;
+    }
+
+    CAMLreturn(Val_int(data_fd));
+
+bind_fail:
+data_fd_fail: 
+    close(data_fd);  
+    
+ctrl_fd_fail:
+    close(control_fd);
+     
+fail:
+    failwith("xcs connection error");             /* should be more explicit */
+}
+
+
+/* xcs_disconnect: Unix.file_descr -> unit */
+
+value
+xcs_disconnect (value data_fd)
+{
+    CAMLparam1(data_fd);
+
+    int my_data_fd = Int_val(data_fd);
+
+    close(my_data_fd);
+    close(control_fd);
+    control_fd = -1;
+
+    CAMLreturn(Val_unit);
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -Nru a/tools/debugger/pdb/pdb_caml_xen.h 
b/tools/debugger/pdb/pdb_caml_xen.h
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/pdb_caml_xen.h 2005-06-28 14:01:24 -04:00
@@ -0,0 +1,18 @@
+
+#ifndef _PDB_CAML_XEN_DEFINED_
+#define _PDB_CAML_XEN_DEFINED_
+
+enum gdb_registers { GDB_EAX, GDB_ECX, GDB_EDX, GDB_EBX,
+                     GDB_ESP, GDB_EBP, GDB_ESI, GDB_EDI,
+                     GDB_EIP, GDB_EFL, 
+                     GDB_CS,  GDB_SS,  GDB_DS,  GDB_ES,
+                     GDB_FS,  GDB_GS };
+
+#define PAGE_SIZE 4096
+
+extern int xc_handle;
+
+void dump_regs (cpu_user_regs_t *ctx);
+
+#endif
+
diff -Nru a/tools/debugger/pdb/pdb_xen.c b/tools/debugger/pdb/pdb_xen.c
--- a/tools/debugger/pdb/pdb_xen.c      2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/pdb_xen.c      2005-06-28 14:01:24 -04:00
@@ -42,20 +42,6 @@
 }
 
 
-int 
-pdb_evtchn_bind_virq (int xc_handle, int virq, int *port)
-{
-    int rc;
-    
-    if ( (rc = xc_evtchn_bind_virq(xc_handle, virq, port) < 0 ) )
-    {
-        fprintf(stderr, "(pdb) error binding virq to event channel: %d (%s)\n",
-                errno, strerror(errno));
-    }
-    return rc;
-}
-
-
 #include <sys/ioctl.h>
 
 /* /dev/xen/evtchn ioctls */
diff -Nru a/tools/debugger/pdb/server.ml b/tools/debugger/pdb/server.ml
--- a/tools/debugger/pdb/server.ml      2005-06-28 14:01:24 -04:00
+++ b/tools/debugger/pdb/server.ml      2005-06-28 14:01:24 -04:00
@@ -59,6 +59,7 @@
   conn.length <- conn.length + length;
   let re = Str.regexp "[^\\$]*\\$\\([^#]*\\)#\\(..\\)" in
 
+  (* interrupt the target if there was a ctrl-c *)
   begin
     try
       let break = String.index conn.buffer '\003' + 1 in
@@ -118,9 +119,13 @@
  *  connection_hash is a hash (duh!) with one connection_t for each
  *  open connection.
  * 
- *  in_list is a list of active sockets.  it also contains two 
- *  magic entries: server_sock for accepting new entries and 
- *  event_sock for Xen event channel asynchronous notifications.
+ *  in_list is a list of active sockets.  it also contains a number
+ *  of magic entries: 
+ *  - server_sock   for accepting new client connections (e.g. gdb)
+ *  - xen_virq_sock for Xen virq asynchronous notifications (via evtchn).
+ *                  This is used by context = domain
+ *  - xcs_sock      for xcs messages when a new backend domain registers
+ *                  This is used by context = process
  *)
 let main_server_loop sockaddr =
   let connection_hash = Hashtbl.create 10
@@ -143,10 +148,20 @@
       begin
        try
          match PDB.find_context sock with
-         | PDB.Event_channel ->
-             print_endline (Printf.sprintf "[%s] event channel"
+         | PDB.Xen_virq ->
+             print_endline (Printf.sprintf "[%s] Xen virq"
                                            (Util.get_connection_info sock));
-             Debugger.process_evtchn sock;
+             Debugger.process_xen_virq sock;
+             (new_list, closed_list)
+         | PDB.Xen_xcs ->
+             print_endline (Printf.sprintf "[%s] Xen xcs"
+                                           (Util.get_connection_info sock));
+             let new_xen_domain = Debugger.process_xen_xcs sock in
+             (new_xen_domain :: new_list, closed_list)
+         | PDB.Xen_domain d ->
+             print_endline (Printf.sprintf "[%s] Xen domain"
+                                           (Util.get_connection_info sock));
+             Debugger.process_xen_domain sock;
              (new_list, closed_list)
          | _ ->
              let conn = Hashtbl.find connection_hash sock in
@@ -167,18 +182,22 @@
            (new_list, sock :: closed_list)
       end
   in
+
   let rec helper in_list server_sock =
-  (*
-   * List.iter (fun x->Printf.printf "{%s} " 
-   *                                (Util.get_connection_info x)) in_list;   
-   * Printf.printf "\n";
-   *)
+
+    (*    
+     List.iter (fun x->Printf.printf " {%s}\n" 
+                                    (Util.get_connection_info x)) in_list;   
+     Printf.printf "\n";
+    *)
+
     let (rd_list, _, _) = select in_list [] [] (-1.0) in 
     let (new_list, closed_list) = List.fold_left (process_socket server_sock)
                                                 ([],[]) rd_list  in
     let merge_list = Util.list_remove (new_list @ in_list) closed_list  in
     helper merge_list server_sock
   in
+
   try
     let server_sock = socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in
     setsockopt server_sock SO_REUSEADDR true;
@@ -186,16 +205,19 @@
     listen server_sock 2;
 
     PDB.open_debugger ();
-    let event_sock = Evtchn.setup () in
-    PDB.add_context event_sock "event channel" [];
-    helper [server_sock; event_sock] server_sock
+    let xen_virq_sock = Evtchn.setup () in
+    PDB.add_context xen_virq_sock "xen virq" [];
+
+    let xcs_sock = Xcs.setup () in
+    PDB.add_context xcs_sock "xen xcs" [];
+    helper [server_sock; xen_virq_sock; xcs_sock] server_sock
   with
   | Sys.Break ->
       print_endline "break: cleaning up";
       PDB.close_debugger ();
       Hashtbl.iter (fun sock conn -> close sock) connection_hash
-  | Unix_error(e,err,param) -> 
-      Printf.printf "unix error: [%s][%s][%s]\n" (error_message e) err param
+(*  | Unix_error(e,err,param) -> 
+      Printf.printf "unix error: [%s][%s][%s]\n" (error_message e) err param*)
   | Sys_error s -> Printf.printf "sys error: [%s]\n" s
   | Failure s -> Printf.printf "failure: [%s]\n" s
   | End_of_file -> Printf.printf "end of file\n"
@@ -207,7 +229,7 @@
     int_of_string Sys.argv.(1)
   else
     begin
-      print_endline (Printf.sprintf "syntax error: %s <port>" Sys.argv.(0));
+      print_endline (Printf.sprintf "error: %s <port>" Sys.argv.(0));
       exit 1
     end
 
diff -Nru a/tools/debugger/pdb/xcs.ml b/tools/debugger/pdb/xcs.ml
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/xcs.ml 2005-06-28 14:01:24 -04:00
@@ -0,0 +1,85 @@
+(** xcs.ml
+ *
+ *  xen control switch interface
+ *
+ *  @author copyright (c) 2005 alex ho
+ *  @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger
+ *  @version 1
+ *)
+
+open Int32
+
+let xcs_path = "/var/lib/xen/xcs_socket"                    (* XCS_SUN_PATH *)
+let xcs_type = 11                                             (* CMSG_DEBUG *)
+
+
+type xcs_message =
+    {
+              domain  : int;
+              status  : int;
+              ring    : int32;
+      mutable evtchn  : int;
+    }
+
+external connect : string -> int -> Unix.file_descr = "xcs_connect"
+external disconnect : Unix.file_descr -> unit = "xcs_disconnect"
+external read_message : Unix.file_descr -> xcs_message = "xcs_read_message"
+external write_message : Unix.file_descr -> xcs_message -> unit = 
+                                                            "xcs_write_message"
+external initialize_ring : int -> int32 -> int32 = "xcs_initialize_ring"
+
+(*
+ * initialize xcs stuff
+ *)
+let setup () =
+  connect xcs_path xcs_type
+
+
+(*
+ * adios
+ *)
+let teardown fd =
+  disconnect fd
+
+
+(*
+ * message from a domain backend
+ *)
+let read socket =
+  let xcs = read_message socket in
+  begin
+    match xcs.status with
+      | 1 ->                                    (* PDB_CONNECTION_STATUS_UP *)
+         begin
+           print_endline (Printf.sprintf "  new backend domain available (%d)"
+                          xcs.domain);
+           let ring = initialize_ring xcs.domain xcs.ring in
+
+           let (local_evtchn, remote_evtchn) = 
+             Evtchn.bind_interdomain xcs.domain in
+
+           xcs.evtchn <- remote_evtchn;
+           write_message socket xcs;
+
+           let evtchn_fd = Evtchn._setup () in
+           Evtchn._bind evtchn_fd local_evtchn;
+
+           (evtchn_fd, local_evtchn, xcs.domain, ring)
+         end
+      | 2 ->                                  (* PDB_CONNECTION_STATUS_DOWN *)
+         begin
+           (* TODO:
+              unmap the ring
+              unbind event channel  xen_evtchn_unbind
+              find the evtchn_fd for this domain and close it
+              finally, need to failwith something
+           *)
+           print_endline (Printf.sprintf "  close connection from domain %d"
+                          xcs.domain);
+           (socket, 0, 0, 0l)
+         end
+      | _ ->
+         failwith "xcs read: unknown xcs status"
+  end
+    
+
diff -Nru a/tools/debugger/pdb/xcs.mli b/tools/debugger/pdb/xcs.mli
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/tools/debugger/pdb/xcs.mli        2005-06-28 14:01:24 -04:00
@@ -0,0 +1,5 @@
+
+
+val setup : unit -> Unix.file_descr
+val read : Unix.file_descr -> Unix.file_descr * int * int * int32
+val teardown : Unix.file_descr -> unit
diff -Nru a/xen/include/public/io/domain_controller.h 
b/xen/include/public/io/domain_controller.h
--- a/xen/include/public/io/domain_controller.h 2005-06-28 14:01:24 -04:00
+++ b/xen/include/public/io/domain_controller.h 2005-06-28 14:01:24 -04:00
@@ -62,6 +62,7 @@
 #define CMSG_USBIF_BE       8  /* USB controller backend  */
 #define CMSG_USBIF_FE       9  /* USB controller frontend */
 #define CMSG_VCPU_HOTPLUG  10  /* Hotplug VCPU messages   */
+#define CMSG_DEBUG         11  /* PDB backend             */
 
 /******************************************************************************
  * CONSOLE DEFINITIONS
@@ -794,5 +795,18 @@
     u32 status;       /* 4: Return code indicates success or failure. */
 } PACKED mem_request_t; /* 8 bytes */
 
+
+/******************************************************************************
+ * PDB INTERFACE DEFINITIONS
+ */
+
+#define CMSG_DEBUG_CONNECTION_STATUS 0
+typedef struct {
+#define PDB_CONNECTION_STATUS_UP   1
+#define PDB_CONNECTION_STATUS_DOWN 2
+    u32      status;
+    memory_t ring;       /* status: UP */
+    u32      evtchn;     /* status: UP */
+} PACKED pdb_connection_t, *pdb_connection_p;
 
 #endif /* __XEN_PUBLIC_IO_DOMAIN_CONTROLLER_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] add framework for debugging processes, BitKeeper Bot <=