[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] add framework for debugging processes



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.