diff options
Diffstat (limited to 'sim')
-rw-r--r-- | sim/ChangeLog | 17 | ||||
-rw-r--r-- | sim/cris/traps.c | 75 |
2 files changed, 68 insertions, 24 deletions
diff --git a/sim/ChangeLog b/sim/ChangeLog index d502ab6..87cbc8c 100644 --- a/sim/ChangeLog +++ b/sim/ChangeLog @@ -1,3 +1,20 @@ +2009-01-06 Hans-Peter Nilsson <hp@axis.com> + + * cris/traps.c (abort): Define to call sim_io_error. + (create_map): Make -1 imply a non-fixed address, not 0. All + callers changed. Only prefer the next higher unmapped address if + the last mapped address is no less than 0x40000000. Check that + the address to be mapped is not already mapped. Update head + comment. + (unmap_pages): Don't call abort when recursive call fails, just + note and return an error if a page in the range couldn't be unmapped. + (cris_bmod_handler, h_supr_set_handler, h_supr_get_handler) + (schedule, make_first_thread, cris_pipe_empty): New local variable sd. + (cris_break_13_handler) <case TARGET_SYS_mmap2>: Handle + non-MAP_FIXED argument overlapping existing map. For MAP_FIXED, + don't abort on page not being mapped. Handle non-anon filemap + with length padded to pagesize. + 2009-01-03 Hans-Peter Nilsson <hp@axis.com> * cris/sim-if.c (TARGET_AT_NULL, TARGET_AT_PHDR, TARGET_AT_PHENT) diff --git a/sim/cris/traps.c b/sim/cris/traps.c index aa3b90a..5bd98bf 100644 --- a/sim/cris/traps.c +++ b/sim/cris/traps.c @@ -755,6 +755,11 @@ static const CB_TARGET_DEFS_MAP open_map[] = { { -1, -1 } }; +/* Let's be less drastic and more traceable. FIXME: mark as noreturn. */ +#define abort() \ + sim_io_error (sd, "simulator unhandled condition at %s:%d", \ + __FUNCTION__, __LINE__) + /* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls. */ static SIM_CPU *current_cpu_for_cb_callback; @@ -975,7 +980,8 @@ cris_dump_map (SIM_CPU *current_cpu) sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end); } -/* Create mmapped memory. */ +/* Create mmapped memory. ADDR is -1 if any address will do. Caller + must make sure that the address isn't already mapped. */ static USI create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, @@ -985,9 +991,9 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, struct cris_sim_mmapped_page **higher_prevp = rootp; USI new_addr = 0x40000000; - if (addr != 0) + if (addr != (USI) -1) new_addr = addr; - else if (*rootp) + else if (*rootp && rootp[0]->addr >= new_addr) new_addr = rootp[0]->addr + 8192; if (len != 8192) @@ -1011,6 +1017,10 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, mapp = mapp->prev) higher_prevp = &mapp->prev; + /* Assert for consistency that we don't create duplicate maps. */ + if (is_mapped (sd, rootp, new_addr, len)) + abort (); + /* Allocate the new page, on the next higher page from the last one allocated, and link in the new descriptor before previous ones. */ mapp = malloc (sizeof (*mapp)); @@ -1041,6 +1051,7 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, if (len != 8192) { USI page_addr; + int ret = 0; if (len & 8191) /* Which is better: return an error for this, or just round it up? */ @@ -1049,12 +1060,15 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, /* Loop backwards to make each call is O(1) over the number of pages allocated, if we're unmapping from the high end of the pages. */ for (page_addr = addr + len - 8192; - page_addr >= addr; + page_addr > addr; page_addr -= 8192) - if (unmap_pages (sd, rootp, page_addr, 8192) != 0) - abort (); + if (unmap_pages (sd, rootp, page_addr, 8192)) + ret = EINVAL; - return 0; + if (unmap_pages (sd, rootp, addr, 8192)) + ret = EINVAL; + + return ret; } for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev) @@ -1087,6 +1101,7 @@ cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, UINT srcreg ATTRIBUTE_UNUSED, USI dstreg ATTRIBUTE_UNUSED) { + SIM_DESC sd = CPU_STATE (current_cpu); abort (); } @@ -1096,6 +1111,7 @@ h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, USI page ATTRIBUTE_UNUSED, USI newval ATTRIBUTE_UNUSED) { + SIM_DESC sd = CPU_STATE (current_cpu); abort (); } @@ -1104,6 +1120,7 @@ h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, UINT index ATTRIBUTE_UNUSED, USI page ATTRIBUTE_UNUSED) { + SIM_DESC sd = CPU_STATE (current_cpu); abort (); } @@ -1260,6 +1277,7 @@ schedule (SIM_CPU *current_cpu, int next) static void reschedule (SIM_CPU *current_cpu) { + SIM_DESC sd = CPU_STATE (current_cpu); int i; /* Iterate over all thread slots, because after a few thread creations @@ -1397,6 +1415,7 @@ deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid) static void make_first_thread (SIM_CPU *current_cpu) { + SIM_DESC sd = CPU_STATE (current_cpu); current_cpu->thread_data = xcalloc (1, SIM_TARGET_MAX_THREADS @@ -1706,10 +1725,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC) && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE)) || (fd == (USI) -1 && pgoff != 0) - || (fd != (USI) -1 && (flags & TARGET_MAP_ANONYMOUS)) - || ((flags & TARGET_MAP_FIXED) == 0 - && is_mapped (sd, ¤t_cpu->highest_mmapped_page, - addr, (len + 8191) & ~8191))) + || (fd != (USI) -1 && (flags & TARGET_MAP_ANONYMOUS))) { retval = cris_unknown_syscall (current_cpu, pc, @@ -1742,13 +1758,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE)) abort (); - if ((flags & TARGET_MAP_FIXED) - && unmap_pages (sd, ¤t_cpu->highest_mmapped_page, - addr, newlen) != 0) - abort (); + if (flags & TARGET_MAP_FIXED) + unmap_pages (sd, ¤t_cpu->highest_mmapped_page, + addr, newlen); + else if (is_mapped (sd, ¤t_cpu->highest_mmapped_page, + addr, newlen)) + addr = 0; newaddr - = create_map (sd, ¤t_cpu->highest_mmapped_page, addr, + = create_map (sd, ¤t_cpu->highest_mmapped_page, + addr != 0 || (flags & TARGET_MAP_FIXED) + ? addr : -1, newlen); if (newaddr >= (USI) -8191) @@ -1800,7 +1820,9 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, if (cb_syscall (cb, &s) != CB_RC_OK) abort (); - if ((USI) s.result != len) + /* If the result is a page or more lesser than what + was requested, something went wrong. */ + if (len >= 8192 && (USI) s.result <= len - 8192) abort (); /* After reading, we need to go back to the previous @@ -1821,13 +1843,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, USI newlen = (len + 8191) & ~8191; USI newaddr; - if ((flags & TARGET_MAP_FIXED) - && unmap_pages (sd, ¤t_cpu->highest_mmapped_page, - addr, newlen) != 0) - abort (); + if (flags & TARGET_MAP_FIXED) + unmap_pages (sd, ¤t_cpu->highest_mmapped_page, + addr, newlen); + else if (is_mapped (sd, ¤t_cpu->highest_mmapped_page, + addr, newlen)) + addr = 0; - newaddr = create_map (sd, ¤t_cpu->highest_mmapped_page, addr, - newlen); + newaddr = create_map (sd, ¤t_cpu->highest_mmapped_page, + addr != 0 || (flags & TARGET_MAP_FIXED) + ? addr : -1, + newlen); if (newaddr >= (USI) -8191) retval = -cb_host_to_target_errno (cb, -(SI) newaddr); @@ -2114,7 +2140,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, mapped_addr = create_map (sd, ¤t_cpu->highest_mmapped_page, - 0, new_len); + -1, new_len); if (mapped_addr > (USI) -8192) { @@ -3263,6 +3289,7 @@ cris_pipe_empty (host_callback *cb, { int i; SIM_CPU *cpu = current_cpu_for_cb_callback; + SIM_DESC sd = CPU_STATE (current_cpu_for_cb_callback); bfd_byte r10_buf[4]; int remaining = cb->pipe_buffer[writer].size - cb->pipe_buffer[reader].size; |