target/xtensa fixes:
- fix read/write simcall mapping flags and return value; - use -serial option to direct console output of sim machine to QEMU chardev; - fix handling of unknown registers in the gdbstub. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZNoftAAoJEFH5zJH4P6BE/D8P+gLL750NJPt5jDtyPFD0++Wl ELORyi0TjqarRTdhwf27Mrmq2IX/hUYPzwoHcGCLD9IWSwcjQKNAC2cUFyhx+kSs wawFUe8/AVRQHQN1PjL8MIGojro8jwrifYaHpodQcrQv4kq2hVdpjmq2+5ze4lff KZVpK4u9sVUDyilB8rGJzPLpV9W/b8lO8v908nreIUQivffmSWbfKAc2x0SzDzaJ br4F53RGW2Mgx1ZvHKCc+FNig8JoolMtRaPJGqYYkRZt6zO6i/hzFqUIICzKNxLb 4b97rsbA76nhMzWnIBzZo8FNym2QpNfT8d/ESmqA5zNcYy2MP78rSN7miPVqCNSg 0RRj3QRIwOliKVbMTTsGnqAoDGOLIrxIro0YjjG2lvERU4VAC4Evon2If5Hl7EVa l7JcKagV8xd9EO3AA8vvhQGh4nSU6mJUIsWhL3pxYETTov9xg9hSR1h4AyE/bk9m 9naCriwKVNmvnjhD7Y0zTnkuZ1XnjxOnD+MNlylZGYlY3b7G/AWAlw53zYgd6jZs tP+aEaa+xN/5i7Hlfk2oGkTn2NMCUvk8gZidBJKsO/TqNbHcyCwN7ISVdpWO5aIr h/Hfe/wYfa7djGBiHFgbNWlpnTXq18L3rQ6qAjKXE3OuXGjYcqk3KV9SiaWmGVyE Au9GCZsgkWbpHa/dBgkG =E8c8 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/xtensa/tags/20170606-xtensa' into staging target/xtensa fixes: - fix read/write simcall mapping flags and return value; - use -serial option to direct console output of sim machine to QEMU chardev; - fix handling of unknown registers in the gdbstub. # gpg: Signature made Tue 06 Jun 2017 11:46:05 BST # gpg: using RSA key 0x51F9CC91F83FA044 # gpg: Good signature from "Max Filippov <filippov@cadence.com>" # gpg: aka "Max Filippov <max.filippov@cogentembedded.com>" # gpg: aka "Max Filippov <jcmvbkbc@gmail.com>" # Primary key fingerprint: 2B67 854B 98E5 327D CDEB 17D8 51F9 CC91 F83F A044 * remotes/xtensa/tags/20170606-xtensa: target/xtensa: handle unknown registers in gdbstub target/xtensa: support output to chardev console target/xtensa: fix return value of read/write simcalls target/xtensa: fix mapping direction in read/write simcalls Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
65dfad62a1
@ -114,6 +114,9 @@ static void xtensa_sim_init(MachineState *machine)
|
|||||||
xtensa_create_memory_regions(&sysram, "xtensa.sysram");
|
xtensa_create_memory_regions(&sysram, "xtensa.sysram");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (serial_hds[0]) {
|
||||||
|
xtensa_sim_open_console(serial_hds[0]);
|
||||||
|
}
|
||||||
if (kernel_filename) {
|
if (kernel_filename) {
|
||||||
uint64_t elf_entry;
|
uint64_t elf_entry;
|
||||||
uint64_t elf_lowaddr;
|
uint64_t elf_lowaddr;
|
||||||
@ -136,6 +139,7 @@ static void xtensa_sim_machine_init(MachineClass *mc)
|
|||||||
mc->is_default = true;
|
mc->is_default = true;
|
||||||
mc->init = xtensa_sim_init;
|
mc->init = xtensa_sim_init;
|
||||||
mc->max_cpus = 4;
|
mc->max_cpus = 4;
|
||||||
|
mc->no_serial = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MACHINE("sim", xtensa_sim_machine_init)
|
DEFINE_MACHINE("sim", xtensa_sim_machine_init)
|
||||||
|
@ -483,6 +483,7 @@ void xtensa_translate_init(void);
|
|||||||
void xtensa_breakpoint_handler(CPUState *cs);
|
void xtensa_breakpoint_handler(CPUState *cs);
|
||||||
void xtensa_finalize_config(XtensaConfig *config);
|
void xtensa_finalize_config(XtensaConfig *config);
|
||||||
void xtensa_register_core(XtensaConfigList *node);
|
void xtensa_register_core(XtensaConfigList *node);
|
||||||
|
void xtensa_sim_open_console(Chardev *chr);
|
||||||
void check_interrupts(CPUXtensaState *s);
|
void check_interrupts(CPUXtensaState *s);
|
||||||
void xtensa_irq_init(CPUXtensaState *env);
|
void xtensa_irq_init(CPUXtensaState *env);
|
||||||
void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
|
void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
|
||||||
|
@ -58,7 +58,10 @@ int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||||||
case 8:
|
case 8:
|
||||||
return gdb_get_reg64(mem_buf, float64_val(env->fregs[i].f64));
|
return gdb_get_reg64(mem_buf, float64_val(env->fregs[i].f64));
|
||||||
default:
|
default:
|
||||||
return 0;
|
qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported size %d\n",
|
||||||
|
__func__, n, reg->size);
|
||||||
|
memset(mem_buf, 0, reg->size);
|
||||||
|
return reg->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 8: /*a*/
|
case 8: /*a*/
|
||||||
@ -67,6 +70,8 @@ int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||||||
default:
|
default:
|
||||||
qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported type %d\n",
|
qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported type %d\n",
|
||||||
__func__, n, reg->type);
|
__func__, n, reg->type);
|
||||||
|
memset(mem_buf, 0, reg->size);
|
||||||
|
return reg->size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,7 +116,9 @@ int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||||||
env->fregs[reg->targno & 0x0f].f64 = make_float64(tmp);
|
env->fregs[reg->targno & 0x0f].f64 = make_float64(tmp);
|
||||||
return 8;
|
return 8;
|
||||||
default:
|
default:
|
||||||
return 0;
|
qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported size %d\n",
|
||||||
|
__func__, n, reg->size);
|
||||||
|
return reg->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 8: /*a*/
|
case 8: /*a*/
|
||||||
@ -121,7 +128,7 @@ int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||||||
default:
|
default:
|
||||||
qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported type %d\n",
|
qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported type %d\n",
|
||||||
__func__, n, reg->type);
|
__func__, n, reg->type);
|
||||||
return 0;
|
return reg->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -27,9 +27,14 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "chardev/char-fe.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/semihost.h"
|
#include "exec/semihost.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
|
static CharBackend *xtensa_sim_console;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TARGET_SYS_exit = 1,
|
TARGET_SYS_exit = 1,
|
||||||
@ -148,6 +153,15 @@ static uint32_t errno_h2g(int host_errno)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xtensa_sim_open_console(Chardev *chr)
|
||||||
|
{
|
||||||
|
static CharBackend console;
|
||||||
|
|
||||||
|
qemu_chr_fe_init(&console, chr, &error_abort);
|
||||||
|
qemu_chr_fe_set_handlers(&console, NULL, NULL, NULL, NULL, NULL, true);
|
||||||
|
xtensa_sim_console = &console;
|
||||||
|
}
|
||||||
|
|
||||||
void HELPER(simcall)(CPUXtensaState *env)
|
void HELPER(simcall)(CPUXtensaState *env)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(xtensa_env_get_cpu(env));
|
CPUState *cs = CPU(xtensa_env_get_cpu(env));
|
||||||
@ -166,6 +180,7 @@ void HELPER(simcall)(CPUXtensaState *env)
|
|||||||
uint32_t fd = regs[3];
|
uint32_t fd = regs[3];
|
||||||
uint32_t vaddr = regs[4];
|
uint32_t vaddr = regs[4];
|
||||||
uint32_t len = regs[5];
|
uint32_t len = regs[5];
|
||||||
|
uint32_t len_done = 0;
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
hwaddr paddr = cpu_get_phys_page_debug(cs, vaddr);
|
hwaddr paddr = cpu_get_phys_page_debug(cs, vaddr);
|
||||||
@ -173,25 +188,54 @@ void HELPER(simcall)(CPUXtensaState *env)
|
|||||||
TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
|
TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
|
||||||
uint32_t io_sz = page_left < len ? page_left : len;
|
uint32_t io_sz = page_left < len ? page_left : len;
|
||||||
hwaddr sz = io_sz;
|
hwaddr sz = io_sz;
|
||||||
void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
|
void *buf = cpu_physical_memory_map(paddr, &sz, !is_write);
|
||||||
|
uint32_t io_done;
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
vaddr += io_sz;
|
vaddr += io_sz;
|
||||||
len -= io_sz;
|
len -= io_sz;
|
||||||
regs[2] = is_write ?
|
if (fd < 3 && xtensa_sim_console) {
|
||||||
write(fd, buf, io_sz) :
|
if (is_write && (fd == 1 || fd == 2)) {
|
||||||
read(fd, buf, io_sz);
|
io_done = qemu_chr_fe_write_all(xtensa_sim_console,
|
||||||
regs[3] = errno_h2g(errno);
|
buf, io_sz);
|
||||||
cpu_physical_memory_unmap(buf, sz, is_write, sz);
|
regs[3] = errno_h2g(errno);
|
||||||
if (regs[2] == -1) {
|
} else {
|
||||||
break;
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s fd %d is not supported with chardev console\n",
|
||||||
|
is_write ?
|
||||||
|
"writing to" : "reading from", fd);
|
||||||
|
io_done = -1;
|
||||||
|
regs[3] = TARGET_EBADF;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
io_done = is_write ?
|
||||||
|
write(fd, buf, io_sz) :
|
||||||
|
read(fd, buf, io_sz);
|
||||||
|
regs[3] = errno_h2g(errno);
|
||||||
}
|
}
|
||||||
|
if (io_done == -1) {
|
||||||
|
error = true;
|
||||||
|
io_done = 0;
|
||||||
|
}
|
||||||
|
cpu_physical_memory_unmap(buf, sz, !is_write, io_done);
|
||||||
} else {
|
} else {
|
||||||
regs[2] = -1;
|
error = true;
|
||||||
regs[3] = TARGET_EINVAL;
|
regs[3] = TARGET_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (error) {
|
||||||
|
if (!len_done) {
|
||||||
|
len_done = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len_done += io_done;
|
||||||
|
if (io_done < io_sz) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
regs[2] = len_done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -241,10 +285,6 @@ void HELPER(simcall)(CPUXtensaState *env)
|
|||||||
uint32_t target_tvv[2];
|
uint32_t target_tvv[2];
|
||||||
|
|
||||||
struct timeval tv = {0};
|
struct timeval tv = {0};
|
||||||
fd_set fdset;
|
|
||||||
|
|
||||||
FD_ZERO(&fdset);
|
|
||||||
FD_SET(fd, &fdset);
|
|
||||||
|
|
||||||
if (target_tv) {
|
if (target_tv) {
|
||||||
cpu_memory_rw_debug(cs, target_tv,
|
cpu_memory_rw_debug(cs, target_tv,
|
||||||
@ -252,12 +292,25 @@ void HELPER(simcall)(CPUXtensaState *env)
|
|||||||
tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
|
tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
|
||||||
tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
|
tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
|
||||||
}
|
}
|
||||||
regs[2] = select(fd + 1,
|
if (fd < 3 && xtensa_sim_console) {
|
||||||
rq == SELECT_ONE_READ ? &fdset : NULL,
|
if ((fd == 1 || fd == 2) && rq == SELECT_ONE_WRITE) {
|
||||||
rq == SELECT_ONE_WRITE ? &fdset : NULL,
|
regs[2] = 1;
|
||||||
rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
|
} else {
|
||||||
target_tv ? &tv : NULL);
|
regs[2] = 0;
|
||||||
regs[3] = errno_h2g(errno);
|
}
|
||||||
|
regs[3] = 0;
|
||||||
|
} else {
|
||||||
|
fd_set fdset;
|
||||||
|
|
||||||
|
FD_ZERO(&fdset);
|
||||||
|
FD_SET(fd, &fdset);
|
||||||
|
regs[2] = select(fd + 1,
|
||||||
|
rq == SELECT_ONE_READ ? &fdset : NULL,
|
||||||
|
rq == SELECT_ONE_WRITE ? &fdset : NULL,
|
||||||
|
rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
|
||||||
|
target_tv ? &tv : NULL);
|
||||||
|
regs[3] = errno_h2g(errno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user