Exemple #1
0
INLINE_EMUL_GENERIC void
emul_add_tree_options(device *tree,
		      bfd *image,
		      const char *emul,
		      const char *env,
		      int oea_interrupt_prefix)
{
  int little_endian = 0;

  /* sort out little endian */
  if (tree_find_property(tree, "/options/little-endian?"))
    little_endian = tree_find_boolean_property(tree, "/options/little-endian?");
  else {
#ifdef bfd_little_endian	/* new bfd */
    little_endian = (image != NULL && bfd_little_endian(image));
#else
    little_endian = (image != NULL &&
		     !image->xvec->byteorder_big_p);
#endif
    tree_parse(tree, "/options/little-endian? %s",
	       little_endian ? "true" : "false");
  }

  /* misc other stuff */
  tree_parse(tree, "/openprom/options/oea-memory-size 0x%x",
	     OEA_MEMORY_SIZE);
  tree_parse(tree, "/openprom/options/oea-interrupt-prefix %d",
	     oea_interrupt_prefix);
  tree_parse(tree, "/openprom/options/smp 1");
  tree_parse(tree, "/openprom/options/env %s", env);
  tree_parse(tree, "/openprom/options/os-emul %s", emul);
  tree_parse(tree, "/openprom/options/strict-alignment? %s",
	     (WITH_ALIGNMENT == STRICT_ALIGNMENT)
	     ? "true" : "false");
  tree_parse(tree, "/openprom/options/floating-point? %s",
	     WITH_FLOATING_POINT ? "true" : "false");
  tree_parse(tree, "/openprom/options/use-stdio? %s",
	     ((WITH_STDIO == DO_USE_STDIO
	       || WITH_STDIO == 0)
	      ? "true" : "false"));
  tree_parse(tree, "/openprom/options/model \"%s",
	     model_name[WITH_DEFAULT_MODEL]);
  tree_parse(tree, "/openprom/options/model-issue %d",
	     MODEL_ISSUE_IGNORE);

  /* useful options */
}
Exemple #2
0
static os_emul_data *
emul_netbsd_create(device *root,
		   bfd *image,
		   const char *name)
{
  unsigned_word top_of_stack;
  unsigned stack_size;
  int elf_binary;
  os_emul_data *bsd_data;
  device *vm;
  char *filename;

  /* check that this emulation is really for us */
  if (name != NULL && strcmp(name, "netbsd") != 0)
    return NULL;
  if (image == NULL)
    return NULL;


  /* merge any emulation specific entries into the device tree */

  /* establish a few defaults */
  if (image->xvec->flavour == bfd_target_elf_flavour) {
    elf_binary = 1;
    top_of_stack = 0xe0000000;
    stack_size =   0x00100000;
  }
  else {
    elf_binary = 0;
    top_of_stack = 0x20000000;
    stack_size =   0x00100000;
  }

  /* options */
  emul_add_tree_options(root, image, "netbsd",
			(WITH_ENVIRONMENT == USER_ENVIRONMENT
			 ? "user" : "virtual"),
			0 /*oea-interrupt-prefix*/);

  /* virtual memory - handles growth of stack/heap */
  vm = tree_parse(root, "/openprom/vm");
  tree_parse(vm, "./stack-base 0x%lx",
	     (unsigned long)(top_of_stack - stack_size));
  tree_parse(vm, "./nr-bytes 0x%x", stack_size);

  filename = tree_quote_property (bfd_get_filename(image));
  tree_parse(root, "/openprom/vm/map-binary/file-name %s",
	     filename);
  free (filename);

  /* finish the init */
  tree_parse(root, "/openprom/init/register/pc 0x%lx",
	     (unsigned long)bfd_get_start_address(image));
  tree_parse(root, "/openprom/init/register/sp 0x%lx",
	     (unsigned long)top_of_stack);
  tree_parse(root, "/openprom/init/register/msr 0x%x",
	     ((tree_find_boolean_property(root, "/options/little-endian?")
	       ? msr_little_endian_mode
	       : 0)
	      | (tree_find_boolean_property(root, "/openprom/options/floating-point?")
		 ? (msr_floating_point_available
		    | msr_floating_point_exception_mode_0
		    | msr_floating_point_exception_mode_1)
		 : 0)));
  tree_parse(root, "/openprom/init/stack/stack-type %s",
	     (elf_binary ? "ppc-elf" : "ppc-xcoff"));

  /* finally our emulation data */
  bsd_data = ZALLOC(os_emul_data);
  bsd_data->vm = vm;
  bsd_data->syscalls = &emul_netbsd_syscalls;
  return bsd_data;
}
Exemple #3
0
SIM_RC
sim_config (SIM_DESC sd)
{
  enum bfd_endian prefered_target_byte_order;
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);

  /* extract all relevant information */
  if (STATE_PROG_BFD (sd) == NULL
      /* If we have a binary input file (presumably with specified
	 "--architecture"), it'll have no endianness.  */
      || (!bfd_little_endian (STATE_PROG_BFD (sd))
	  && !bfd_big_endian (STATE_PROG_BFD (sd))))
    prefered_target_byte_order = BFD_ENDIAN_UNKNOWN;
  else
    prefered_target_byte_order = (bfd_little_endian (STATE_PROG_BFD (sd))
				  ? BFD_ENDIAN_LITTLE
				  : BFD_ENDIAN_BIG);

  /* set the target byte order */
#if (WITH_TREE_PROPERTIES)
  if (current_target_byte_order == BFD_ENDIAN_UNKNOWN)
    current_target_byte_order
      = (tree_find_boolean_property (root, "/options/little-endian?")
	 ? BFD_ENDIAN_LITTLE
	 : BFD_ENDIAN_BIG);
#endif
  if (current_target_byte_order == BFD_ENDIAN_UNKNOWN
      && prefered_target_byte_order != BFD_ENDIAN_UNKNOWN)
    current_target_byte_order = prefered_target_byte_order;
  if (current_target_byte_order == BFD_ENDIAN_UNKNOWN)
    current_target_byte_order = WITH_TARGET_BYTE_ORDER;
  if (current_target_byte_order == BFD_ENDIAN_UNKNOWN)
    current_target_byte_order = WITH_DEFAULT_TARGET_BYTE_ORDER;

  /* verify the target byte order */
  if (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_UNKNOWN)
    {
      sim_io_eprintf (sd, "Target byte order unspecified\n");
      return SIM_RC_FAIL;
    }
  if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
    sim_io_eprintf (sd, "Target (%s) and configured (%s) byte order in conflict\n",
		  config_byte_order_to_a (current_target_byte_order),
		  config_byte_order_to_a (CURRENT_TARGET_BYTE_ORDER));
  if (prefered_target_byte_order != BFD_ENDIAN_UNKNOWN
      && CURRENT_TARGET_BYTE_ORDER != prefered_target_byte_order)
    sim_io_eprintf (sd, "Target (%s) and specified (%s) byte order in conflict\n",
		  config_byte_order_to_a (CURRENT_TARGET_BYTE_ORDER),
		  config_byte_order_to_a (prefered_target_byte_order));


  /* set the stdio */
  if (current_stdio == 0)
    current_stdio = WITH_STDIO;
  if (current_stdio == 0)
    current_stdio = DO_USE_STDIO;

  /* verify the stdio */
  if (CURRENT_STDIO == 0)
    {
      sim_io_eprintf (sd, "Target standard IO unspecified\n");
      return SIM_RC_FAIL;
    }
  if (CURRENT_STDIO != current_stdio)
    {
      sim_io_eprintf (sd, "Target (%s) and configured (%s) standard IO in conflict\n",
		      config_stdio_to_a (CURRENT_STDIO),
		      config_stdio_to_a (current_stdio));
      return SIM_RC_FAIL;
    }


  /* check the value of MSB */
  if (WITH_TARGET_WORD_MSB != 0
      && WITH_TARGET_WORD_MSB != (WITH_TARGET_WORD_BITSIZE - 1))
    {
      sim_io_eprintf (sd, "Target bitsize (%d) contradicts target most significant bit (%d)\n",
		      WITH_TARGET_WORD_BITSIZE, WITH_TARGET_WORD_MSB);
      return SIM_RC_FAIL;
    }


  /* set the environment */
#if (WITH_TREE_PROPERTIES)
  if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
    {
      const char *env =
	tree_find_string_property (root, "/openprom/options/env");
      STATE_ENVIRONMENT (sd) = ((strcmp (env, "user") == 0
				 || strcmp (env, "uea") == 0)
				? USER_ENVIRONMENT
				: (strcmp (env, "virtual") == 0
				   || strcmp (env, "vea") == 0)
				? VIRTUAL_ENVIRONMENT
				: (strcmp (env, "operating") == 0
				   || strcmp (env, "oea") == 0)
				? OPERATING_ENVIRONMENT
				: ALL_ENVIRONMENT);
    }
#endif
  if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
    STATE_ENVIRONMENT (sd) = (WITH_ENVIRONMENT != ALL_ENVIRONMENT ?
			      WITH_ENVIRONMENT : USER_ENVIRONMENT);


  /* set the alignment */
#if (WITH_TREE_PROPERTIES)
  if (current_alignment == 0)
    current_alignment =
      (tree_find_boolean_property (root, "/openprom/options/strict-alignment?")
       ? STRICT_ALIGNMENT
       : NONSTRICT_ALIGNMENT);
#endif
  if (current_alignment == 0)
    current_alignment = WITH_ALIGNMENT;
  if (current_alignment == 0)
    current_alignment = WITH_DEFAULT_ALIGNMENT;

  /* verify the alignment */
  if (CURRENT_ALIGNMENT == 0)
    {
      sim_io_eprintf (sd, "Target alignment unspecified\n");
      return SIM_RC_FAIL;
    }
  if (CURRENT_ALIGNMENT != current_alignment)
    {
      sim_io_eprintf (sd, "Target (%s) and configured (%s) alignment in conflict\n",
		      config_alignment_to_a (CURRENT_ALIGNMENT),
		      config_alignment_to_a (current_alignment));
      return SIM_RC_FAIL;
    }

#if defined (WITH_FLOATING_POINT)

  /* set the floating point */
  if (current_floating_point == 0)
    current_floating_point = WITH_FLOATING_POINT;

  /* verify the floating point */
  if (CURRENT_FLOATING_POINT == 0)
    {
      sim_io_eprintf (sd, "Target floating-point unspecified\n");
      return SIM_RC_FAIL;
    }
  if (CURRENT_FLOATING_POINT != current_floating_point)
    {
      sim_io_eprintf (sd, "Target (%s) and configured (%s) floating-point in conflict\n",
		      config_alignment_to_a (CURRENT_FLOATING_POINT),
		      config_alignment_to_a (current_floating_point));
      return SIM_RC_FAIL;
    }

#endif
  return SIM_RC_OK;
}
static os_emul_data *
emul_bugapi_create(device *root,
		   bfd *image,
		   const char *name)
{
  device *node;
  os_emul_data *bugapi;
  char *filename;

  /* check it really is for us */
  if (name != NULL
      && strcmp(name, "bugapi") != 0
      && strcmp(name, "bug") != 0)
    return NULL;
  if (image != NULL
      && name == NULL
      && bfd_get_start_address(image) >= BUGAPI_END_ADDRESS)
    return NULL;

  bugapi = ZALLOC(os_emul_data);

  /* options */
  emul_add_tree_options(root, image, "bug", "oea",
			1 /*oea-interrupt-prefix*/);

  /* add some real hardware, include eeprom memory for the eeprom trap
     addresses */
  emul_add_tree_hardware(root);
  node = tree_parse(root, "/openprom/memory@0xfff00000");
  tree_parse(node, "./psim,description \"eeprom trap addresses");
  tree_parse(node, "./reg 0xfff00000 0x3000");

  bugapi->root = root;

  bugapi->memory_size
    = tree_find_integer_property(root, "/openprom/options/oea-memory-size");
  bugapi->interrupt_prefix =
    tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
  bugapi->interrupt_vector_address = (bugapi->interrupt_prefix
				      ? MASK(0, 43)
				      : 0);
  bugapi->system_call_address = (bugapi->interrupt_vector_address + 0x00c00);
  bugapi->stall_cpu_loop_address = (bugapi->system_call_address + 0x000f0);
  bugapi->top_of_stack = bugapi->memory_size - 0x1000;
  bugapi->little_endian
    = tree_find_boolean_property(root, "/options/little-endian?");
  bugapi->floating_point_available
    = tree_find_boolean_property(root, "/openprom/options/floating-point?");
  bugapi->input = NULL;
  bugapi->output = NULL;

  /* initialization */
  if (image != NULL)
    tree_parse(root, "/openprom/init/register/0.pc 0x%lx",
	       (unsigned long)bfd_get_start_address(image));
  tree_parse(root, "/openprom/init/register/pc 0x%lx",
	     (unsigned long)bugapi->stall_cpu_loop_address);
  tree_parse(root, "/openprom/init/register/sp 0x%lx",
	     (unsigned long)(bugapi->top_of_stack - 16));
  tree_parse(root, "/openprom/init/register/msr 0x%x",
	     (msr_recoverable_interrupt
	      | (bugapi->little_endian
		 ? (msr_little_endian_mode
		    | msr_interrupt_little_endian_mode)
		 : 0)
	      | (bugapi->floating_point_available
		 ? msr_floating_point_available
		 : 0)
	      | (bugapi->interrupt_prefix
		 ? msr_interrupt_prefix
		 : 0)
	      ));

  /* patch the system call instruction to call this emulation and then
     do an rfi */
  node = tree_parse(root, "/openprom/init/data@0x%lx",
		    (unsigned long)bugapi->system_call_address);
  tree_parse(node, "./psim,description \"system-call trap instruction");
  tree_parse(node, "./real-address 0x%lx",
	     (unsigned long)bugapi->system_call_address);
  tree_parse(node, "./data 0x%x", emul_call_instruction);
  node = tree_parse(root, "/openprom/init/data@0x%lx",
		    (unsigned long)bugapi->system_call_address + 4);
  tree_parse(node, "./psim,description \"return from interrupt instruction");
  tree_parse(node, "./real-address 0x%lx",
	     (unsigned long)bugapi->system_call_address + 4);
  tree_parse(node, "./data 0x%x",
	     emul_rfi_instruction);

  /* patch the end of the system call instruction so that it contains
     a loop to self instruction and point all the cpu's at this */
  node = tree_parse(root, "/openprom/init/data@0x%lx",
		    (unsigned long)bugapi->stall_cpu_loop_address);
  tree_parse(node, "./psim,description \"cpu-loop instruction");
  tree_parse(node, "./real-address 0x%lx",
	     (unsigned long)bugapi->stall_cpu_loop_address);
  tree_parse(node, "./data 0x%lx",
	     (unsigned long)emul_loop_instruction);

  if (image != NULL)
    tree_parse(root, "/openprom/init/stack/stack-type %s",
	       (image->xvec->flavour == bfd_target_elf_flavour
		? "ppc-elf"
		: "ppc-xcoff"));

  if (image != NULL)
    {
      filename = tree_quote_property (bfd_get_filename(image));
      tree_parse(root, "/openprom/init/load-binary/file-name %s",
		 filename);
      free (filename);
    }

  return bugapi;
}
psim_create(const char *file_name,
            device *root)
{
    int cpu_nr;
    const char *env;
    psim *system;
    os_emul *os_emulation;
    int nr_cpus;

    /* given this partially populated device tree, os_emul_create() uses
       it and file_name to determine the selected emulation and hence
       further populate the tree with any other required nodes. */

    os_emulation = os_emul_create(file_name, root);
    if (os_emulation == NULL)
        error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);

    /* fill in the missing real number of CPU's */
    nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
    if (MAX_NR_PROCESSORS < nr_cpus)
        error("target and configured number of cpus conflict\n");

    /* fill in the missing TARGET BYTE ORDER information */
    current_target_byte_order
        = (tree_find_boolean_property(root, "/options/little-endian?")
           ? LITTLE_ENDIAN
           : BIG_ENDIAN);
    if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
        error("target and configured byte order conflict\n");

    /* fill in the missing HOST BYTE ORDER information */
    current_host_byte_order = (current_host_byte_order = 1,
                               (*(char*)(&current_host_byte_order)
                                ? LITTLE_ENDIAN
                                : BIG_ENDIAN));
    if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
        error("host and configured byte order conflict\n");

    /* fill in the missing OEA/VEA information */
    env = tree_find_string_property(root, "/openprom/options/env");
    current_environment = ((strcmp(env, "user") == 0
                            || strcmp(env, "uea") == 0)
                           ? USER_ENVIRONMENT
                           : (strcmp(env, "virtual") == 0
                              || strcmp(env, "vea") == 0)
                           ? VIRTUAL_ENVIRONMENT
                           : (strcmp(env, "operating") == 0
                              || strcmp(env, "oea") == 0)
                           ? OPERATING_ENVIRONMENT
                           : 0);
    if (current_environment == 0)
        error("unreconized /options env property\n");
    if (CURRENT_ENVIRONMENT != current_environment)
        error("target and configured environment conflict\n");

    /* fill in the missing ALLIGNMENT information */
    current_alignment
        = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
           ? STRICT_ALIGNMENT
           : NONSTRICT_ALIGNMENT);
    if (CURRENT_ALIGNMENT != current_alignment)
        error("target and configured alignment conflict\n");

    /* fill in the missing FLOATING POINT information */
    current_floating_point
        = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
           ? HARD_FLOATING_POINT
           : SOFT_FLOATING_POINT);
    if (CURRENT_FLOATING_POINT != current_floating_point)
        error("target and configured floating-point conflict\n");

    /* fill in the missing STDIO information */
    current_stdio
        = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
           ? DO_USE_STDIO
           : DONT_USE_STDIO);
    if (CURRENT_STDIO != current_stdio)
        error("target and configured stdio interface conflict\n");

    /* sort out the level of detail for issue modeling */
    current_model_issue
        = tree_find_integer_property(root, "/openprom/options/model-issue");
    if (CURRENT_MODEL_ISSUE != current_model_issue)
        error("target and configured model-issue conflict\n");

    /* sort out our model architecture - wrong.

       FIXME: this should be obtaining the required information from the
       device tree via the "/chosen" property "cpu" which is an instance
       (ihandle) for the only executing processor. By converting that
       ihandle into the corresponding cpu's phandle and then querying
       the "name" property, the cpu type can be determined. Ok? */

    model_set(tree_find_string_property(root, "/openprom/options/model"));

    /* create things */
    system = ZALLOC(psim);
    system->events = event_queue_create();
    system->memory = core_from_device(root);
    system->monitor = mon_create();
    system->nr_cpus = nr_cpus;
    system->os_emulation = os_emulation;
    system->devices = root;

    /* now all the processors attaching to each their per-cpu information */
    for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
        system->processors[cpu_nr] = cpu_create(system,
                                                system->memory,
                                                mon_cpu(system->monitor,
                                                        cpu_nr),
                                                system->os_emulation,
                                                cpu_nr);
    }

    /* dump out the contents of the device tree */
    if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
        tree_print(root);
    if (ppc_trace[trace_dump_device_tree])
        error("");

    return system;
}