diff options
author | Michael Meissner <gnu@the-meissners.org> | 1996-01-08 18:01:17 +0000 |
---|---|---|
committer | Michael Meissner <gnu@the-meissners.org> | 1996-01-08 18:01:17 +0000 |
commit | 979c3c25fd3f51d8effb28593edf222841053de9 (patch) | |
tree | e422fd8f377d34239db1bf2b92b752b1617f9df7 /sim/ppc/emul_chirp.c | |
parent | 436d4143274d6bb3c32632f7ae1bd82cda5128b5 (diff) | |
download | gdb-979c3c25fd3f51d8effb28593edf222841053de9.zip gdb-979c3c25fd3f51d8effb28593edf222841053de9.tar.gz gdb-979c3c25fd3f51d8effb28593edf222841053de9.tar.bz2 |
Latest cagney update
Diffstat (limited to 'sim/ppc/emul_chirp.c')
-rw-r--r-- | sim/ppc/emul_chirp.c | 489 |
1 files changed, 450 insertions, 39 deletions
diff --git a/sim/ppc/emul_chirp.c b/sim/ppc/emul_chirp.c index dc1d8e6..9c20262 100644 --- a/sim/ppc/emul_chirp.c +++ b/sim/ppc/emul_chirp.c @@ -47,7 +47,7 @@ /* Descriptor of the open boot services being emulated */ -typedef unsigned_word (chirp_handler) +typedef int (chirp_handler) (os_emul_data *data, cpu *processor, unsigned_word cia); @@ -61,6 +61,7 @@ typedef struct _chirp_services { request or waiting on a client callback */ typedef enum { serving, + faulting, catching, } chirp_emul_state; @@ -78,7 +79,64 @@ struct _os_emul_data { /* OpenBoot emulation functions */ -static unsigned_word +static int +chirp_emul_child(os_emul_data *data, + cpu *processor, + unsigned_word cia) +{ + struct child_args { + unsigned32 service; + unsigned32 n_args; + unsigned32 n_returns; + /*in*/ + unsigned32 phandle; + /*out*/ + unsigned32 child_phandle; + } args; + device *dev; + device *child_dev; + emul_read_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("child - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); + return -1; + } + /* read in the arguments */ + dev = cap_internal(data->phandles, args.phandle); + TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)T2H_4(args.phandle), + (unsigned long)dev, + (dev == NULL ? "" : device_name(dev)))); + if (dev == (device*)0) + return -1; + child_dev = device_child(dev); + if (child_dev == NULL) + args.child_phandle = 0; + else + args.child_phandle = cap_external(data->phandles, child_dev); + TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)T2H_4(args.child_phandle), + (unsigned long)child_dev, + (child_dev == NULL ? "" : device_name(child_dev)))); + emul_write_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + return 0; +} + +static int +chirp_emul_exit(os_emul_data *data, + cpu *processor, + unsigned_word cia) +{ + cpu_halt(processor, cia, was_exited, 0); /* always succeeds */ + return 0; +} + +static int chirp_emul_finddevice(os_emul_data *data, cpu *processor, unsigned_word cia) @@ -97,25 +155,35 @@ chirp_emul_finddevice(os_emul_data *data, emul_read_buffer(&args, data->arguments, sizeof(args), processor, cia); - if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) + if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("finddevice - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); return -1; + } emul_read_string(device_specifier, T2H_4(args.device_specifier), sizeof(device_specifier), processor, cia); + TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n", + device_specifier)); dev = device_tree_find_device(data->root, device_specifier); if (dev == (device*)0) args.phandle = -1; else args.phandle = cap_external(data->phandles, dev); + TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)T2H_4(args.phandle), + (unsigned long)dev, + (dev == NULL ? "" : device_name(dev)))); emul_write_buffer(&args, data->arguments, sizeof(args), processor, cia); return 0; } -static unsigned_word +static int chirp_emul_getprop(os_emul_data *data, cpu *processor, unsigned_word cia) @@ -138,16 +206,27 @@ chirp_emul_getprop(os_emul_data *data, emul_read_buffer(&args, data->arguments, sizeof(args), processor, cia); - if (T2H_4(args.n_args) != 4 || T2H_4(args.n_returns) != 1) + if (T2H_4(args.n_args) != 4 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("getprop - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); return -1; + } /* read in the arguments */ dev = cap_internal(data->phandles, args.phandle); - if (dev == (device*)0) - return -1; emul_read_string(name, T2H_4(args.name), sizeof(name), processor, cia); + TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n", + (unsigned long)T2H_4(args.phandle), + (unsigned long)dev, + (dev == NULL ? "" : device_name(dev)), + name, + (unsigned long)T2H_4(args.buf), + (unsigned long)T2H_4(args.buflen))); + if (dev == (device*)0) + return -1; prop = device_find_property(dev, name); if (prop == (device_property*)0) { args.size = -1; @@ -161,18 +240,223 @@ chirp_emul_getprop(os_emul_data *data, processor, cia); args.size = H2T_4(size); } + switch (prop->type) { + case string_property: + TRACE(trace_os_emul, ("getprop - value=`%s' (string)\n", + (char*)prop->array)); + break; + default: + break; + } + TRACE(trace_os_emul, ("getprop - out - size=%ld\n", + (unsigned long)T2H_4(args.size))); emul_write_buffer(&args, data->arguments, sizeof(args), processor, cia); return 0; } -static unsigned_word -chirp_emul_write(os_emul_data *data, +static int +chirp_emul_getproplen(os_emul_data *data, + cpu *processor, + unsigned_word cia) +{ + struct getproplen_args { + unsigned32 service; + unsigned32 n_args; + unsigned32 n_returns; + /*in*/ + unsigned32 phandle; + unsigned32 name; + /*out*/ + unsigned32 proplen; + } args; + char name[32]; + device *dev; + const device_property *prop; + emul_read_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + if (T2H_4(args.n_args) != 2 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("getproplen - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); + return -1; + } + /* read in the arguments */ + dev = cap_internal(data->phandles, args.phandle); + if (dev == (device*)0) + return -1; + emul_read_string(name, + T2H_4(args.name), + sizeof(name), + processor, cia); + TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n", + (unsigned long)T2H_4(args.phandle), + (unsigned long)dev, + (dev == NULL ? "" : device_name(dev)), + name)); + prop = device_find_property(dev, name); + if (prop == (device_property*)0) { + args.proplen = -1; + } + else { + args.proplen = H2T_4(prop->sizeof_array); + } + TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n", + (unsigned long)T2H_4(args.proplen))); + emul_write_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + return 0; +} + +static int +chirp_emul_open(os_emul_data *data, cpu *processor, unsigned_word cia) { - struct write_args { + struct open_args { + unsigned32 service; + unsigned32 n_args; + unsigned32 n_returns; + /*in*/ + unsigned32 device_specifier; + /*out*/ + unsigned32 ihandle; + } args; + char name[1024]; + emul_read_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("open - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); + return -1; + } + /* read in the arguments */ + emul_read_string(name, + T2H_4(args.device_specifier), + sizeof(name), + processor, cia); + TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n", + name)); + printf_filtered("OpenBoot - open unimplemented for %s\n", name); + args.ihandle = -1; + TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n", + (unsigned long)T2H_4(args.ihandle))); + emul_write_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + return 0; +} + +static int +chirp_emul_parent(os_emul_data *data, + cpu *processor, + unsigned_word cia) +{ + struct parent_args { + unsigned32 service; + unsigned32 n_args; + unsigned32 n_returns; + /*in*/ + unsigned32 phandle; + /*out*/ + unsigned32 parent_phandle; + } args; + device *dev; + device *parent_dev; + emul_read_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("parent - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); + return -1; + } + /* read in the arguments */ + dev = cap_internal(data->phandles, args.phandle); + TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)T2H_4(args.phandle), + (unsigned long)dev, + (dev == NULL ? "" : device_name(dev)))); + if (dev == (device*)0) + return -1; + parent_dev = device_parent(dev); + if (parent_dev == NULL) + args.parent_phandle = 0; + else + args.parent_phandle = cap_external(data->phandles, parent_dev); + TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)T2H_4(args.parent_phandle), + (unsigned long)parent_dev, + (parent_dev == NULL ? "" : device_name(parent_dev)))); + emul_write_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + return 0; +} + +static int +chirp_emul_peer(os_emul_data *data, + cpu *processor, + unsigned_word cia) +{ + struct peer_args { + unsigned32 service; + unsigned32 n_args; + unsigned32 n_returns; + /*in*/ + unsigned32 phandle; + /*out*/ + unsigned32 sibling_phandle; + } args; + device *dev; + device *sibling_dev = NULL; + emul_read_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("peer - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); + return -1; + } + /* read in the arguments */ + dev = cap_internal(data->phandles, args.phandle); + TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)T2H_4(args.phandle), + (unsigned long)dev, + (dev == NULL ? "" : device_name(dev)))); + if (dev == NULL && args.phandle != 0) + return -1; + if (args.phandle == 0) + sibling_dev = data->root; + else + sibling_dev = device_sibling(dev); + if (sibling_dev == NULL) + args.sibling_phandle = 0; + else + args.sibling_phandle = cap_external(data->phandles, sibling_dev); + TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)T2H_4(args.sibling_phandle), + (unsigned long)sibling_dev, + (sibling_dev == NULL ? "" : device_name(sibling_dev)))); + emul_write_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + return 0; +} + +static int +chirp_emul_read(os_emul_data *data, + cpu *processor, + unsigned_word cia) +{ + struct read_args { unsigned32 service; unsigned32 n_args; unsigned32 n_returns; @@ -188,40 +472,95 @@ chirp_emul_write(os_emul_data *data, emul_read_buffer(&args, data->arguments, sizeof(args), processor, cia); - if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) + if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("read - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); return -1; + } /* read in the arguments */ actual = T2H_4(args.len); - if (actual > sizeof(buf)) - actual = sizeof(buf); + if (actual >= sizeof(buf)) + actual = sizeof(buf) - 1; emul_read_buffer(buf, T2H_4(args.addr), actual, processor, cia); - /* write it out */ - write(BE2H_4(args.ihandle), buf, actual); + buf[actual] = '\0'; + /* read it in */ + TRACE(trace_os_emul, ("read - in - ihandle=0x%lx `%s' (%ld)\n", + (unsigned long)args.ihandle, buf, (long)actual)); + read(BE2H_4(args.ihandle), buf, actual); args.actual = H2T_4(actual); + TRACE(trace_os_emul, ("read - out - actual=%ld\n", + (long)T2H_4(args.actual))); emul_write_buffer(&args, data->arguments, sizeof(args), processor, cia); return 0; } -static unsigned_word -chirp_emul_exit(os_emul_data *data, - cpu *processor, - unsigned_word cia) +static int +chirp_emul_write(os_emul_data *data, + cpu *processor, + unsigned_word cia) { - error("chirp_emul_exit not implemnented\n"); + struct write_args { + unsigned32 service; + unsigned32 n_args; + unsigned32 n_returns; + /*in*/ + unsigned32 ihandle; + unsigned32 addr; + unsigned32 len; + /*out*/ + unsigned32 actual; + } args; + char buf[1024]; + int actual; + emul_read_buffer(&args, data->arguments, + sizeof(args), + processor, cia); + if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) { + TRACE(trace_os_emul, ("write - invalid nr - n_args=%ld, n_returns=%ld\n", + (long)T2H_4(args.n_args), + (long)T2H_4(args.n_returns))); + return -1; + } + /* read in the arguments */ + actual = T2H_4(args.len); + if (actual >= sizeof(buf)) + actual = sizeof(buf) - 1; + emul_read_buffer(buf, + T2H_4(args.addr), + actual, + processor, cia); + buf[actual] = '\0'; + /* write it out */ + TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n", + (unsigned long)args.ihandle, buf, (long)actual)); + write(BE2H_4(args.ihandle), buf, actual); + args.actual = H2T_4(actual); + TRACE(trace_os_emul, ("write - out - actual=%ld\n", + (long)T2H_4(args.actual))); + emul_write_buffer(&args, data->arguments, + sizeof(args), + processor, cia); return 0; } chirp_services services[] = { + { "child", chirp_emul_child }, + { "exit", chirp_emul_exit }, { "finddevice", chirp_emul_finddevice }, { "getprop", chirp_emul_getprop }, + { "getproplen", chirp_emul_getproplen }, + { "open", chirp_emul_open }, + { "parent", chirp_emul_parent }, + { "peer", chirp_emul_peer }, + { "read", chirp_emul_read }, { "write", chirp_emul_write }, - { "exit", chirp_emul_exit }, { 0, /* sentinal */ }, }; @@ -303,6 +642,7 @@ emul_chirp_create(device *root, { os_emul_data *data; chirp_note note; + int big_endian; /* Sanity check that this really is the chosen emulation */ if (name == NULL && image == NULL) @@ -322,6 +662,11 @@ emul_chirp_create(device *root, if (name == NULL && image != NULL && !note.found) return NULL; + /* the root node */ + device_add_string_property(root, + "name", + "gpl,clayton"); + { const unsigned_word memory_size = 0x200000; @@ -335,7 +680,7 @@ emul_chirp_create(device *root, /* a page for firmware calls */ const unsigned_word sizeof_code = 4096; const unsigned_word code_ra = htab_ra - sizeof_code; - + /* the stack */ const unsigned sizeof_stack = 32 * 1024; const unsigned_word stack_ra = code_ra - sizeof_stack; @@ -350,8 +695,17 @@ emul_chirp_create(device *root, /* the virtual addresses */ const unsigned_word stack_va = virt_base; const unsigned_word code_va = stack_va + sizeof_stack; + const unsigned_word code_client_va = code_va; + const unsigned_word code_callback_va = code_client_va + 16; + const unsigned_word code_loop_va = code_callback_va + 16; const unsigned_word htab_va = code_va + sizeof_code; - + +#ifdef bfd_big_endian /* new bfd */ + big_endian = bfd_big_endian(image); +#else + big_endian = image->xvec->byteorder_big_p; +#endif + /* options */ { device *options = device_tree_add_found(root, "/", "options"); @@ -360,14 +714,14 @@ emul_chirp_create(device *root, MAX_NR_PROCESSORS); device_add_boolean_property(options, "little-endian?", - !image->xvec->byteorder_big_p); + !big_endian); device_add_string_property(options, "env", "operating"); device_add_boolean_property(options, "strict-alignment?", (WITH_ALIGNMENT == STRICT_ALIGNMENT - || !image->xvec->byteorder_big_p)); + || !big_endian)); device_add_boolean_property(options, "floating-point?", WITH_FLOATING_POINT); @@ -387,17 +741,30 @@ emul_chirp_create(device *root, device *init_register = device_tree_add_found(init, "", "register"); device_add_integer_property(init_register, "pc", + code_loop_va); + device_add_integer_property(init_register, + "0.pc", bfd_get_start_address(image)); device_add_integer_property(init_register, "sp", stack_va + sizeof_stack - 16); - /* init the code callback */ + /* init the code callback along with a loop for the unused cpu's */ device_add_integer_property(init_register, "r5", - code_va); - device_tree_add_found_uw_u_u(init, "", "data", code_ra, 4, 0x1); - device_tree_add_found_uw_u_u(init, "", "data", code_ra+16, 4, 0x1); + code_client_va); + device_tree_add_found_uw_u_u(init, "", + "data", + code_ra + (code_client_va - code_va), + 4, 0x1); /*emul-call*/ + device_tree_add_found_uw_u_u(init, "", + "data", + code_ra + (code_callback_va - code_va), + 4, 0x1); /*emul-call*/ + device_tree_add_found_uw_u_u(init, "", + "data", + code_ra + (code_loop_va - code_va), + 4, 0x48000000); /*b .*/ device_add_integer_property(init_register, "msr", (msr_machine_check_enable @@ -405,7 +772,7 @@ emul_chirp_create(device *root, ? 0 : (msr_instruction_relocate | msr_data_relocate)) - | (image->xvec->byteorder_big_p + | (big_endian ? 0 : (msr_little_endian_mode | msr_interrupt_little_endian_mode @@ -445,15 +812,35 @@ emul_chirp_create(device *root, { /* chosen options */ device *chosen = device_tree_add_found(root, "/", "chosen"); + device_add_string_property(chosen, + "name", + "chosen"); + device_add_integer_property(chosen, + "stdin", + 0); /* FIXME: ihandle of stdin */ device_add_integer_property(chosen, "stdout", - 1); + 1); /* FIXME: ihandle of stdout */ + device_add_string_property(chosen, + "bootpath", + "/disk@0:\\boot"); + device_add_string_property(chosen, + "bootargs", + ""); +#if 0 + device_add_integer_property(chosen, + "memory", + 0); /* FIXME: ihandle of memory */ + device_add_integer_property(chosen, + "mmu", + 0); +#endif } /* FIXME - should come from the device tree */ data = ZALLOC(os_emul_data); - data->serving_instruction_ea = CHIRP_START_ADDRESS + sizeof_stack;; - data->catching_instruction_ea = CHIRP_START_ADDRESS + sizeof_stack + 16; + data->serving_instruction_ea = code_client_va; + data->catching_instruction_ea = code_callback_va; data->phandles = cap_create("chirp"); data->root = root; return data; @@ -470,9 +857,9 @@ emul_chirp_init(os_emul_data *emul_data, static int emul_chirp_instruction_call(cpu *processor, - unsigned_word cia, - unsigned_word ra, - os_emul_data *emul_data) + unsigned_word cia, + unsigned_word ra, + os_emul_data *emul_data) { unsigned_word service_name_addr; unsigned_word result; @@ -481,8 +868,10 @@ emul_chirp_instruction_call(cpu *processor, chirp_services *service; switch (emul_data->state) { + case serving: - /* verify then capture the current request */ + /* we are waiting on an OpenBoot request from the client program + via the client interface */ if (cia != emul_data->serving_instruction_ea) return 0; emul_data->return_address = LR; @@ -492,24 +881,46 @@ emul_chirp_instruction_call(cpu *processor, processor, cia); service_name = emul_read_string(service_buf, service_name_addr, sizeof(service_buf), processor, cia); + TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n", + service_name, + (unsigned long)emul_data->return_address, + (unsigned long)emul_data->arguments)); /* look it up */ service = services; while (service->name != NULL && strcmp(service->name, service_name) != 0) service++; if (service->name == NULL) { + error("OpenBoot service `%s' not found\n", service_name); + TRACE(trace_os_emul, ("%s not found\n", service_name)); cpu_registers(processor)->gpr[3] = 0; cpu_restart(processor, emul_data->return_address); } emul_data->service = service; - TRACE(trace_os_emul, ("%s called from 0x%lx\n", - service->name, emul_data->return_address)); /* call upon it */ result = service->handler(emul_data, processor, cia); break; + + case faulting: + /* We were handling a client request but encountered a page fault + (or other exception). The fault needs to be passed back to the + client using the the client suplied call back interface */ + error("emul_chirp_instruction_call() faulting unimplemented\n"); + result = -1; + break; + + case catching: + /* Have called the client (via the callback interface) because + some fault (hash table miss) occured. The client has finished + handling this and is now returning */ + error("emul_chirp_instruction_call() catching unimplemented\n"); + result = -1; + break; + default: error("emul_chirp_instruction_call() unknown internal state\n"); result = -1; break; + } /* return to caller */ |