A selection of s390x patches:

- cleanups, fixes and improvements
 - program check loop detection (useful with the corresponding kernel
   patch)
 - wire up virtio-crypto for ccw
 - and finally support many virtqueues for virtio-ccw
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJYr/qXAAoJEN7Pa5PG8C+vzSYP+wR/mA4wmXh0Jj8zzxeJaeQa
 UNNwR7Ege4KjdL0DKXw/Uy2S/H2qGZvD4cb3JLIwp15BSilmcxRGS+v18ooBuRtx
 X8+W2peH/Ldk4SAGbfXyRR4EXom4ZmmHtgdoWYPUhgq2BimH1vBcY06uHOkJ4zTP
 vBfpmvKL53SjjHF6b9NmlprSDrn8cbQgqqxTWc0YL0aEcFTcxpBfr98dCfrNfk8b
 k6f324hY+3YC7rdvLAsBx3tNjDmEoEh4aidGyECKOWiy2Bt2hQ/ZhxVUk7cFV30M
 F0mttRJSxuBY9xYfmuxTKkm2ttIH0BiOhFmE5+YEj7ot+iqBslyYHR2prkZC66v+
 wQ9Ynx8ys0ec/IkHx2uIt8iOdAiq/K5gJkyjEw6ekg70OOGrTtyv5y6G9FOc4B4W
 ms7eUnhIgr5rEv/oQgCSgCUlAUm6MWW/BtffqmKZ7M2/7l8Y3T1U4f9383sKZtIT
 7xr/AtV30yH695r+bllEljIjgMU5EWUDpA2kBCC6tzJQ0KYSoICSGloxKNEK3Z6X
 EsYby7YjLArTlvsLJ4y2k/BPzcM4IYJX9NDjCmMRpR2I46Nb35uwR73EZx6JS6fw
 dKmdx0qSZbaMbmwIJZzVz4kzG9z6gePkCvaEmPa99ZgnaZ0igm4y5W6Q8fLEn1Jz
 zy277Wciim5mnZWuJAbl
 =uM3N
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20170224' into staging

A selection of s390x patches:
- cleanups, fixes and improvements
- program check loop detection (useful with the corresponding kernel
  patch)
- wire up virtio-crypto for ccw
- and finally support many virtqueues for virtio-ccw

# gpg: Signature made Fri 24 Feb 2017 09:19:19 GMT
# gpg:                using RSA key 0xDECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20170224:
  s390x/css: handle format-0 TIC CCW correctly
  s390x/arch_dump: pass cpuid into notes sections
  s390x/arch_dump: use proper note name and note size
  virtio-ccw: support VIRTIO_QUEUE_MAX virtqueues
  s390x: bump ADAPTER_ROUTES_MAX_GSI
  virtio-ccw: check flic->adapter_routes_max_batch
  s390x: add property adapter_routes_max_batch
  virtio-ccw: Check the number of vqs in CCW_CMD_SET_IND
  virtio-ccw: add virtio-crypto-ccw device
  virtio-ccw: handle virtio 1 only devices
  s390x/flic: fail migration on source already
  s390x/kvm: detect some program check loops
  s390x/s390-virtio: get rid of DPRINTF

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-02-25 17:48:49 +00:00
commit 2421f381dc
10 changed files with 250 additions and 60 deletions

View file

@ -59,8 +59,7 @@ typedef struct S390xElfVregsHiStruct S390xElfVregsHi;
typedef struct noteStruct {
Elf64_Nhdr hdr;
char name[5];
char pad3[3];
char name[8];
union {
S390xElfPrstatus prstatus;
S390xElfFpregset fpregset;
@ -74,7 +73,7 @@ typedef struct noteStruct {
} contents;
} QEMU_PACKED Note;
static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu)
static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu, int id)
{
int i;
S390xUserRegs *regs;
@ -88,9 +87,10 @@ static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu)
regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]);
regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]);
}
note->contents.prstatus.pid = id;
}
static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu)
static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu, int id)
{
int i;
CPUS390XState *cs = &cpu->env;
@ -102,7 +102,7 @@ static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu)
}
}
static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu)
static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu, int id)
{
int i;
@ -112,7 +112,7 @@ static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu)
}
}
static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu)
static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu, int id)
{
int i;
S390xElfVregsHi *temp_vregshi;
@ -126,25 +126,25 @@ static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu)
}
}
static void s390x_write_elf64_timer(Note *note, S390CPU *cpu)
static void s390x_write_elf64_timer(Note *note, S390CPU *cpu, int id)
{
note->hdr.n_type = cpu_to_be32(NT_S390_TIMER);
note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm));
}
static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu)
static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu, int id)
{
note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP);
note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc));
}
static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu)
static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu, int id)
{
note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG);
note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr));
}
static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu)
static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu, int id)
{
int i;
@ -155,20 +155,26 @@ static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu)
}
}
static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu)
static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu, int id)
{
note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX);
note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa));
}
static const struct NoteFuncDescStruct {
typedef struct NoteFuncDescStruct {
int contents_size;
void (*note_contents_func)(Note *note, S390CPU *cpu);
} note_func[] = {
void (*note_contents_func)(Note *note, S390CPU *cpu, int id);
} NoteFuncDesc;
static const NoteFuncDesc note_core[] = {
{sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus},
{sizeof(((Note *)0)->contents.prefix), s390x_write_elf64_prefix},
{sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset},
{ 0, NULL}
};
static const NoteFuncDesc note_linux[] = {
{sizeof(((Note *)0)->contents.prefix), s390x_write_elf64_prefix},
{sizeof(((Note *)0)->contents.ctrs), s390x_write_elf64_ctrs},
{sizeof(((Note *)0)->contents.timer), s390x_write_elf64_timer},
{sizeof(((Note *)0)->contents.todcmp), s390x_write_elf64_todcmp},
@ -178,25 +184,23 @@ static const struct NoteFuncDescStruct {
{ 0, NULL}
};
typedef struct NoteFuncDescStruct NoteFuncDesc;
static int s390x_write_all_elf64_notes(const char *note_name,
static int s390x_write_elf64_notes(const char *note_name,
WriteCoreDumpFunction f,
S390CPU *cpu, int id,
void *opaque)
void *opaque,
const NoteFuncDesc *funcs)
{
Note note;
const NoteFuncDesc *nf;
int note_size;
int ret = -1;
for (nf = note_func; nf->note_contents_func; nf++) {
for (nf = funcs; nf->note_contents_func; nf++) {
memset(&note, 0, sizeof(note));
note.hdr.n_namesz = cpu_to_be32(sizeof(note.name));
note.hdr.n_namesz = cpu_to_be32(strlen(note_name) + 1);
note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
strncpy(note.name, note_name, sizeof(note.name));
(*nf->note_contents_func)(&note, cpu);
(*nf->note_contents_func)(&note, cpu, id);
note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
ret = f(&note, note_size, opaque);
@ -215,7 +219,13 @@ int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque)
{
S390CPU *cpu = S390_CPU(cs);
return s390x_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque);
int r;
r = s390x_write_elf64_notes("CORE", f, cpu, cpuid, opaque, note_core);
if (r) {
return r;
}
return s390x_write_elf64_notes("LINUX", f, cpu, cpuid, opaque, note_linux);
}
int cpu_get_dump_info(ArchDumpInfo *info,
@ -230,7 +240,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
{
int name_size = 8; /* "CORE" or "QEMU" rounded */
int name_size = 8; /* "LINUX" or "CORE" + pad */
size_t elf_note_size = 0;
int note_head_size;
const NoteFuncDesc *nf;
@ -240,7 +250,11 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
note_head_size = sizeof(Elf64_Nhdr);
for (nf = note_func; nf->note_contents_func; nf++) {
for (nf = note_core; nf->note_contents_func; nf++) {
elf_note_size = elf_note_size + note_head_size + name_size +
nf->contents_size;
}
for (nf = note_linux; nf->note_contents_func; nf++) {
elf_note_size = elf_note_size + note_head_size + name_size +
nf->contents_size;
}

View file

@ -1867,6 +1867,40 @@ static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset)
qemu_system_guest_panicked(NULL);
}
/* try to detect pgm check loops */
static int handle_oper_loop(S390CPU *cpu, struct kvm_run *run)
{
CPUState *cs = CPU(cpu);
PSW oldpsw, newpsw;
cpu_synchronize_state(cs);
newpsw.mask = ldq_phys(cs->as, cpu->env.psa +
offsetof(LowCore, program_new_psw));
newpsw.addr = ldq_phys(cs->as, cpu->env.psa +
offsetof(LowCore, program_new_psw) + 8);
oldpsw.mask = run->psw_mask;
oldpsw.addr = run->psw_addr;
/*
* Avoid endless loops of operation exceptions, if the pgm new
* PSW will cause a new operation exception.
* The heuristic checks if the pgm new psw is within 6 bytes before
* the faulting psw address (with same DAT, AS settings) and the
* new psw is not a wait psw and the fault was not triggered by
* problem state. In that case go into crashed state.
*/
if (oldpsw.addr - newpsw.addr <= 6 &&
!(newpsw.mask & PSW_MASK_WAIT) &&
!(oldpsw.mask & PSW_MASK_PSTATE) &&
(newpsw.mask & PSW_MASK_ASC) == (oldpsw.mask & PSW_MASK_ASC) &&
(newpsw.mask & PSW_MASK_DAT) == (oldpsw.mask & PSW_MASK_DAT)) {
unmanageable_intercept(cpu, "operation exception loop",
offsetof(LowCore, program_new_psw));
return EXCP_HALTED;
}
return 0;
}
static int handle_intercept(S390CPU *cpu)
{
CPUState *cs = CPU(cpu);
@ -1914,11 +1948,14 @@ static int handle_intercept(S390CPU *cpu)
r = EXCP_HALTED;
break;
case ICPT_OPEREXC:
/* currently only instr 0x0000 after enabled via capability */
/* check for break points */
r = handle_sw_breakpoint(cpu, run);
if (r == -ENOENT) {
enter_pgmcheck(cpu, PGM_OPERATION);
r = 0;
/* Then check for potential pgm check loops */
r = handle_oper_loop(cpu, run);
if (r == 0) {
enter_pgmcheck(cpu, PGM_OPERATION);
}
}
break;
case ICPT_SOFT_INTERCEPT: