* [Qemu-devel] [PATCH 01/12] S390: Make IPL reset address dynamic
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 02/12] S390: IPL: Support ELF firmware Alexander Graf
` (12 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
We can have different load addresses for different blobs we boot with.
Make the reset IP dynamic, so that we can handle things more flexibly.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/s390x/ipl.c | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 206d552..c43dfcd 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -48,8 +48,9 @@ typedef struct S390IPLClass {
typedef struct S390IPLState {
/*< private >*/
SysBusDevice parent_obj;
- /*< public >*/
+ uint64_t start_addr;
+ /*< public >*/
char *kernel;
char *initrd;
char *cmdline;
@@ -82,6 +83,7 @@ static int s390_ipl_init(SysBusDevice *dev)
bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START, 4096);
+ ipl->start_addr = ZIPL_IMAGE_START;
g_free(bios_filename);
if ((long)bios_size < 0) {
@@ -104,6 +106,13 @@ static int s390_ipl_init(SysBusDevice *dev)
}
/* we have to overwrite values in the kernel image, which are "rom" */
strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
+
+ /*
+ * we can not rely on the ELF entry point, since up to 3.2 this
+ * value was 0x800 (the SALIPL loader) and it wont work. For
+ * all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
+ */
+ ipl->start_addr = KERN_IMAGE_START;
}
if (ipl->initrd) {
ram_addr_t initrd_offset, initrd_size;
@@ -138,16 +147,7 @@ static void s390_ipl_reset(DeviceState *dev)
{
S390IPLState *ipl = S390_IPL(dev);
- if (ipl->kernel) {
- /*
- * we can not rely on the ELF entry point, since up to 3.2 this
- * value was 0x800 (the SALIPL loader) and it wont work. For
- * all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
- */
- return s390_ipl_cpu(KERN_IMAGE_START);
- } else {
- return s390_ipl_cpu(ZIPL_IMAGE_START);
- }
+ s390_ipl_cpu(ipl->start_addr);
}
static void s390_ipl_class_init(ObjectClass *klass, void *data)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 02/12] S390: IPL: Support ELF firmware
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 01/12] S390: Make IPL reset address dynamic Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 03/12] S390: IPL: Use different firmware for different machines Alexander Graf
` (11 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
Our firmware blob is always a raw file that we load at a fixed address today.
Support loading an ELF blob instead that we can map high up in memory.
This way we don't have to be so conscious about size constraints.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/s390x/ipl.c | 16 ++++++++++------
1 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index c43dfcd..d1f7acd 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -82,17 +82,21 @@ static int s390_ipl_init(SysBusDevice *dev)
}
bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
- bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START, 4096);
- ipl->start_addr = ZIPL_IMAGE_START;
+ bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
+ NULL, 1, ELF_MACHINE, 0);
+ if (bios_size == -1UL) {
+ bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
+ 4096);
+ ipl->start_addr = ZIPL_IMAGE_START;
+ if (bios_size > 4096) {
+ hw_error("stage1 bootloader is > 4k\n");
+ }
+ }
g_free(bios_filename);
if ((long)bios_size < 0) {
hw_error("could not load bootloader '%s'\n", bios_name);
}
-
- if (bios_size > 4096) {
- hw_error("stage1 bootloader is > 4k\n");
- }
return 0;
} else {
kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL, NULL,
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 03/12] S390: IPL: Use different firmware for different machines
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 01/12] S390: Make IPL reset address dynamic Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 02/12] S390: IPL: Support ELF firmware Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 04/12] S390: ccw firmware: Add start assembly Alexander Graf
` (10 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
We have a virtio-s390 and a virtio-ccw machine in QEMU. Both use vastly
different ways to do I/O. Having the same firmware blob for both doesn't
really make any sense.
Instead, let's parametrize the firmware file name, so that we can have
different blobs for different machines.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/s390x/ipl.c | 5 +++--
hw/s390x/s390-virtio-ccw.c | 2 +-
hw/s390x/s390-virtio.c | 7 +++++--
hw/s390x/s390-virtio.h | 3 ++-
4 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index d1f7acd..ace5ff5 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -23,7 +23,6 @@
#define INITRD_PARM_START 0x010408UL
#define INITRD_PARM_SIZE 0x010410UL
#define PARMFILE_START 0x001000UL
-#define ZIPL_FILENAME "s390-zipl.rom"
#define ZIPL_IMAGE_START 0x009000UL
#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
@@ -54,6 +53,7 @@ typedef struct S390IPLState {
char *kernel;
char *initrd;
char *cmdline;
+ char *firmware;
} S390IPLState;
@@ -78,7 +78,7 @@ static int s390_ipl_init(SysBusDevice *dev)
/* Load zipl bootloader */
if (bios_name == NULL) {
- bios_name = ZIPL_FILENAME;
+ bios_name = ipl->firmware;
}
bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -144,6 +144,7 @@ static Property s390_ipl_properties[] = {
DEFINE_PROP_STRING("kernel", S390IPLState, kernel),
DEFINE_PROP_STRING("initrd", S390IPLState, initrd),
DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
+ DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d436414..89670f2 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -80,7 +80,7 @@ static void ccw_init(QEMUMachineInitArgs *args)
css_bus = virtual_css_bus_init();
s390_sclp_init();
s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
- args->initrd_filename);
+ args->initrd_filename, "s390-zipl.rom");
/* register hypercalls */
virtio_ccw_register_hcalls();
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index e25c330..9a97a22 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -49,6 +49,7 @@
#endif
#define MAX_BLK_DEVS 10
+#define ZIPL_FILENAME "s390-zipl.rom"
static VirtIOS390Bus *s390_bus;
static S390CPU **ipi_states;
@@ -156,7 +157,8 @@ unsigned s390_del_running_cpu(S390CPU *cpu)
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
- const char *initrd_filename)
+ const char *initrd_filename,
+ const char *firmware)
{
DeviceState *dev;
@@ -168,6 +170,7 @@ void s390_init_ipl_dev(const char *kernel_filename,
qdev_prop_set_string(dev, "initrd", initrd_filename);
}
qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
+ qdev_prop_set_string(dev, "firmware", firmware);
qdev_init_nofail(dev);
}
@@ -243,7 +246,7 @@ static void s390_init(QEMUMachineInitArgs *args)
s390_bus = s390_virtio_bus_init(&my_ram_size);
s390_sclp_init();
s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
- args->initrd_filename);
+ args->initrd_filename, ZIPL_FILENAME);
/* register hypercalls */
s390_virtio_register_hcalls();
diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h
index a6c4c19..5c405e7 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -23,6 +23,7 @@ void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys);
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
- const char *initrd_filename);
+ const char *initrd_filename,
+ const char *firmware);
void s390_create_virtio_net(BusState *bus, const char *name);
#endif
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 04/12] S390: ccw firmware: Add start assembly
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (2 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 03/12] S390: IPL: Use different firmware for different machines Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program Alexander Graf
` (9 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
We want to write most of our code in C, so add a small assembly
stub that jumps straight into C code for us to continue booting.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
pc-bios/s390-ccw/start.S | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw/start.S
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
new file mode 100644
index 0000000..c2b9a19
--- /dev/null
+++ b/pc-bios/s390-ccw/start.S
@@ -0,0 +1,16 @@
+/*
+ * First stage boot loader for virtio devices. The compiled output goes
+ * into the pc-bios directory of qemu.
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+ .globl _start
+_start:
+
+larl %r15, stack + 0x8000 /* Set up stack */
+j main /* And call C */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (3 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 04/12] S390: ccw firmware: Add start assembly Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-23 8:43 ` Christian Borntraeger
2013-04-23 8:58 ` Cornelia Huck
2013-04-22 19:18 ` [Qemu-devel] [PATCH 06/12] S390: ccw firmware: Add sclp output Alexander Graf
` (8 subsequent siblings)
13 siblings, 2 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
This C file is the main driving piece of the s390 ccw firmware. It
provides a search for a workable block device, sets it as the default
to boot off of and boots from it.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
pc-bios/s390-ccw/main.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 56 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw/main.c
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
new file mode 100644
index 0000000..0913aac
--- /dev/null
+++ b/pc-bios/s390-ccw/main.c
@@ -0,0 +1,56 @@
+/*
+ * S390 virtio-ccw loading program
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+
+struct subchannel_id blk_schid;
+char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
+
+void virtio_panic(const char *string)
+{
+ sclp_print(string);
+ while (1) { }
+}
+
+static void virtio_setup(void)
+{
+ struct irb irb;
+ int i;
+ int r;
+ bool found = false;
+
+ blk_schid.one = 1;
+
+ for (i = 0; i < 0x10000; i++) {
+ blk_schid.sch_no = i;
+ r = tsch(blk_schid, &irb);
+ if (r != 3) {
+ if (virtio_is_blk(blk_schid)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ virtio_panic("No virtio-blk device found!\n");
+ }
+
+ virtio_setup_block(blk_schid);
+}
+
+int main(void)
+{
+ sclp_setup();
+ virtio_setup();
+ if (zipl_load() < 0)
+ sclp_print("Failed to load OS from hard disk\n");
+ while (1) { }
+}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program
2013-04-22 19:18 ` [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program Alexander Graf
@ 2013-04-23 8:43 ` Christian Borntraeger
2013-04-23 8:58 ` Cornelia Huck
1 sibling, 0 replies; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 8:43 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel, Dominik Dingel
On 22/04/13 21:18, Alexander Graf wrote:
> This C file is the main driving piece of the s390 ccw firmware. It
> provides a search for a workable block device, sets it as the default
> to boot off of and boots from it.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
> pc-bios/s390-ccw/main.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 56 insertions(+), 0 deletions(-)
> create mode 100644 pc-bios/s390-ccw/main.c
>
> diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
> new file mode 100644
> index 0000000..0913aac
> --- /dev/null
> +++ b/pc-bios/s390-ccw/main.c
> @@ -0,0 +1,56 @@
> +/*
> + * S390 virtio-ccw loading program
> + *
> + * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> + * your option) any later version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#include "s390-ccw.h"
> +
> +struct subchannel_id blk_schid;
> +char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
> +
> +void virtio_panic(const char *string)
> +{
> + sclp_print(string);
> + while (1) { }
> +}
> +
> +static void virtio_setup(void)
> +{
> + struct irb irb;
> + int i;
> + int r;
> + bool found = false;
> +
> + blk_schid.one = 1;
> +
> + for (i = 0; i < 0x10000; i++) {
> + blk_schid.sch_no = i;
> + r = tsch(blk_schid, &irb);
> + if (r != 3) {
> + if (virtio_is_blk(blk_schid)) {
> + found = true;
> + break;
> + }
> + }
> + }
> +
> + if (!found) {
> + virtio_panic("No virtio-blk device found!\n");
> + }
> +
> + virtio_setup_block(blk_schid);
> +}
> +
> +int main(void)
> +{
> + sclp_setup();
The sclp patch should probably be moved before this one...
> + virtio_setup();
> + if (zipl_load() < 0)
...as well as the bootmap loader
> + sclp_print("Failed to load OS from hard disk\n");
> + while (1) { }
This would waste host cpus spinning, no?
Please do a disabled wait. The easiest way might be a short assember routine:
.globl disabled_wait
disabled_wait:
larl %r1,disabled_wait_psw
lpswe 0(%r1)
.align 8
disabled_wait_psw:
.quad 0x0002000180000000,0x0000000000000000
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program
2013-04-22 19:18 ` [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program Alexander Graf
2013-04-23 8:43 ` Christian Borntraeger
@ 2013-04-23 8:58 ` Cornelia Huck
2013-04-23 11:35 ` Alexander Graf
1 sibling, 1 reply; 30+ messages in thread
From: Cornelia Huck @ 2013-04-23 8:58 UTC (permalink / raw)
To: Alexander Graf; +Cc: Christian Borntraeger, qemu-devel, Dominik Dingel
On Mon, 22 Apr 2013 21:18:11 +0200
Alexander Graf <agraf@suse.de> wrote:
> This C file is the main driving piece of the s390 ccw firmware. It
> provides a search for a workable block device, sets it as the default
> to boot off of and boots from it.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
> pc-bios/s390-ccw/main.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 56 insertions(+), 0 deletions(-)
> create mode 100644 pc-bios/s390-ccw/main.c
>
> diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
> new file mode 100644
> index 0000000..0913aac
> --- /dev/null
> +++ b/pc-bios/s390-ccw/main.c
> @@ -0,0 +1,56 @@
> +/*
> + * S390 virtio-ccw loading program
> + *
> + * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> + * your option) any later version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#include "s390-ccw.h"
> +
> +struct subchannel_id blk_schid;
> +char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
> +
> +void virtio_panic(const char *string)
> +{
> + sclp_print(string);
> + while (1) { }
> +}
> +
> +static void virtio_setup(void)
> +{
> + struct irb irb;
> + int i;
> + int r;
> + bool found = false;
> +
> + blk_schid.one = 1;
> +
> + for (i = 0; i < 0x10000; i++) {
> + blk_schid.sch_no = i;
> + r = tsch(blk_schid, &irb);
You want to do a stsch() loop here, not a tsch() loop :)
As a bonus, you can exit the loop on cc == 3.
r = stsch(blk_schid, &schib);
if (r == 3) {
break;
}
> + if (r != 3) {
if (schib.pmcw.dnv) {
> + if (virtio_is_blk(blk_schid)) {
> + found = true;
> + break;
> + }
> + }
> + }
> +
> + if (!found) {
> + virtio_panic("No virtio-blk device found!\n");
> + }
> +
> + virtio_setup_block(blk_schid);
The virtio_is_blk() and virtio_setup_block() functions should go into a
preceding patch, no?
> +}
> +
> +int main(void)
> +{
> + sclp_setup();
> + virtio_setup();
> + if (zipl_load() < 0)
> + sclp_print("Failed to load OS from hard disk\n");
> + while (1) { }
> +}
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program
2013-04-23 8:58 ` Cornelia Huck
@ 2013-04-23 11:35 ` Alexander Graf
2013-04-23 11:51 ` Cornelia Huck
0 siblings, 1 reply; 30+ messages in thread
From: Alexander Graf @ 2013-04-23 11:35 UTC (permalink / raw)
To: Cornelia Huck; +Cc: Christian Borntraeger, qemu-devel, Dominik Dingel
On 04/23/2013 10:58 AM, Cornelia Huck wrote:
> On Mon, 22 Apr 2013 21:18:11 +0200
> Alexander Graf<agraf@suse.de> wrote:
>
>> This C file is the main driving piece of the s390 ccw firmware. It
>> provides a search for a workable block device, sets it as the default
>> to boot off of and boots from it.
>>
>> Signed-off-by: Alexander Graf<agraf@suse.de>
>> ---
>> pc-bios/s390-ccw/main.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
>> 1 files changed, 56 insertions(+), 0 deletions(-)
>> create mode 100644 pc-bios/s390-ccw/main.c
>>
>> diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
>> new file mode 100644
>> index 0000000..0913aac
>> --- /dev/null
>> +++ b/pc-bios/s390-ccw/main.c
>> @@ -0,0 +1,56 @@
>> +/*
>> + * S390 virtio-ccw loading program
>> + *
>> + * Copyright (c) 2013 Alexander Graf<agraf@suse.de>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
>> + * your option) any later version. See the COPYING file in the top-level
>> + * directory.
>> + */
>> +
>> +#include "s390-ccw.h"
>> +
>> +struct subchannel_id blk_schid;
>> +char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
>> +
>> +void virtio_panic(const char *string)
>> +{
>> + sclp_print(string);
>> + while (1) { }
>> +}
>> +
>> +static void virtio_setup(void)
>> +{
>> + struct irb irb;
>> + int i;
>> + int r;
>> + bool found = false;
>> +
>> + blk_schid.one = 1;
>> +
>> + for (i = 0; i< 0x10000; i++) {
>> + blk_schid.sch_no = i;
>> + r = tsch(blk_schid,&irb);
> You want to do a stsch() loop here, not a tsch() loop :)
What does stsch buy us over tsch?
> As a bonus, you can exit the loop on cc == 3.
>
> r = stsch(blk_schid,&schib);
> if (r == 3) {
> break;
> }
>
>> + if (r != 3) {
> if (schib.pmcw.dnv) {
>
>> + if (virtio_is_blk(blk_schid)) {
>> + found = true;
>> + break;
>> + }
>> + }
>> + }
>> +
>> + if (!found) {
>> + virtio_panic("No virtio-blk device found!\n");
>> + }
>> +
>> + virtio_setup_block(blk_schid);
> The virtio_is_blk() and virtio_setup_block() functions should go into a
> preceding patch, no?
The code doesn't get compiled before the end of the series anyway, so
ordering might be slightly off :)
Alex
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program
2013-04-23 11:35 ` Alexander Graf
@ 2013-04-23 11:51 ` Cornelia Huck
0 siblings, 0 replies; 30+ messages in thread
From: Cornelia Huck @ 2013-04-23 11:51 UTC (permalink / raw)
To: Alexander Graf; +Cc: Christian Borntraeger, qemu-devel, Dominik Dingel
On Tue, 23 Apr 2013 13:35:47 +0200
Alexander Graf <agraf@suse.de> wrote:
> On 04/23/2013 10:58 AM, Cornelia Huck wrote:
> > On Mon, 22 Apr 2013 21:18:11 +0200
> > Alexander Graf<agraf@suse.de> wrote:
> >
> >> This C file is the main driving piece of the s390 ccw firmware. It
> >> provides a search for a workable block device, sets it as the default
> >> to boot off of and boots from it.
> >>
> >> Signed-off-by: Alexander Graf<agraf@suse.de>
> >> ---
> >> pc-bios/s390-ccw/main.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
> >> 1 files changed, 56 insertions(+), 0 deletions(-)
> >> create mode 100644 pc-bios/s390-ccw/main.c
> >>
> >> diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
> >> new file mode 100644
> >> index 0000000..0913aac
> >> --- /dev/null
> >> +++ b/pc-bios/s390-ccw/main.c
> >> @@ -0,0 +1,56 @@
> >> +/*
> >> + * S390 virtio-ccw loading program
> >> + *
> >> + * Copyright (c) 2013 Alexander Graf<agraf@suse.de>
> >> + *
> >> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> >> + * your option) any later version. See the COPYING file in the top-level
> >> + * directory.
> >> + */
> >> +
> >> +#include "s390-ccw.h"
> >> +
> >> +struct subchannel_id blk_schid;
> >> +char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
> >> +
> >> +void virtio_panic(const char *string)
> >> +{
> >> + sclp_print(string);
> >> + while (1) { }
> >> +}
> >> +
> >> +static void virtio_setup(void)
> >> +{
> >> + struct irb irb;
> >> + int i;
> >> + int r;
> >> + bool found = false;
> >> +
> >> + blk_schid.one = 1;
> >> +
> >> + for (i = 0; i< 0x10000; i++) {
> >> + blk_schid.sch_no = i;
> >> + r = tsch(blk_schid,&irb);
> > You want to do a stsch() loop here, not a tsch() loop :)
>
> What does stsch buy us over tsch?
A stsch() loop is the canonical way to find devices. tsch() is for
updating subchannel status.
And:
> > As a bonus, you can exit the loop on cc == 3.
:)
> >
> > r = stsch(blk_schid,&schib);
> > if (r == 3) {
> > break;
> > }
> >
> >> + if (r != 3) {
> > if (schib.pmcw.dnv) {
> >
> >> + if (virtio_is_blk(blk_schid)) {
> >> + found = true;
> >> + break;
> >> + }
> >> + }
> >> + }
> >> +
> >> + if (!found) {
> >> + virtio_panic("No virtio-blk device found!\n");
> >> + }
> >> +
> >> + virtio_setup_block(blk_schid);
> > The virtio_is_blk() and virtio_setup_block() functions should go into a
> > preceding patch, no?
>
> The code doesn't get compiled before the end of the series anyway, so
> ordering might be slightly off :)
>
>
> Alex
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 06/12] S390: ccw firmware: Add sclp output
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (4 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 05/12] S390: ccw firmware: Add main program Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 07/12] S390: ccw firmware: Add virtio device drivers Alexander Graf
` (7 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
In order to communicate with the user, we need an I/O mechanism that he
can read. Implement SCLP ASCII support, which happens to be the default
in the s390 ccw machine.
This file is missing read support for now. It can only print messages.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
pc-bios/s390-ccw/sclp-ascii.c | 81 +++++++++++++++++++++++++++++++
pc-bios/s390-ccw/sclp.h | 107 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 188 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw/sclp-ascii.c
create mode 100644 pc-bios/s390-ccw/sclp.h
diff --git a/pc-bios/s390-ccw/sclp-ascii.c b/pc-bios/s390-ccw/sclp-ascii.c
new file mode 100644
index 0000000..1c93937
--- /dev/null
+++ b/pc-bios/s390-ccw/sclp-ascii.c
@@ -0,0 +1,81 @@
+/*
+ * SCLP ASCII access driver
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+#include "sclp.h"
+
+static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
+
+/* Perform service call. Return 0 on success, non-zero otherwise. */
+static int sclp_service_call(unsigned int command, void *sccb)
+{
+ int cc;
+
+ asm volatile(
+ " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
+ " ipm %0\n"
+ " srl %0,28"
+ : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
+ : "cc", "memory");
+ if (cc == 3)
+ return -EIO;
+ if (cc == 2)
+ return -EBUSY;
+ return 0;
+}
+
+static void sclp_set_write_mask(void)
+{
+ WriteEventMask *sccb = (void*)_sccb;
+
+ sccb->h.length = sizeof(WriteEventMask);
+ sccb->mask_length = sizeof(unsigned int);
+ sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+ sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+ sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+ sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+
+ sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
+}
+
+void sclp_setup(void)
+{
+ sclp_set_write_mask();
+}
+
+static int _strlen(const char *str)
+{
+ int i;
+ for (i = 0; *str; i++)
+ str++;
+ return i;
+}
+
+static void _memcpy(char *dest, const char *src, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ dest[i] = src[i];
+}
+
+void sclp_print(const char *str)
+{
+ int len = _strlen(str);
+ WriteEventData *sccb = (void*)_sccb;
+
+ sccb->h.length = sizeof(WriteEventData) + len;
+ sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
+ sccb->ebh.length = sizeof(EventBufferHeader) + len;
+ sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
+ sccb->ebh.flags = 0;
+ _memcpy(sccb->data, str, len);
+
+ sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
+}
diff --git a/pc-bios/s390-ccw/sclp.h b/pc-bios/s390-ccw/sclp.h
new file mode 100644
index 0000000..3cbfb78
--- /dev/null
+++ b/pc-bios/s390-ccw/sclp.h
@@ -0,0 +1,107 @@
+/*
+ * SCLP ASCII access driver
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef SCLP_H
+#define SCLP_H
+
+/* SCLP command codes */
+#define SCLP_CMDW_READ_SCP_INFO 0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
+#define SCLP_CMD_READ_EVENT_DATA 0x00770005
+#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005
+#define SCLP_CMD_READ_EVENT_DATA 0x00770005
+#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005
+#define SCLP_CMD_WRITE_EVENT_MASK 0x00780005
+
+/* SCLP response codes */
+#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010
+#define SCLP_RC_NORMAL_COMPLETION 0x0020
+#define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0
+#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340
+#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300
+#define SCLP_RC_INVALID_FUNCTION 0x40f0
+#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0
+#define SCLP_RC_INVALID_SELECTION_MASK 0x70f0
+#define SCLP_RC_INCONSISTENT_LENGTHS 0x72f0
+#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR 0x73f0
+#define SCLP_RC_INVALID_MASK_LENGTH 0x74f0
+
+/* Service Call Control Block (SCCB) and its elements */
+
+#define SCCB_SIZE 4096
+
+#define SCLP_VARIABLE_LENGTH_RESPONSE 0x80
+#define SCLP_EVENT_BUFFER_ACCEPTED 0x80
+
+#define SCLP_FC_NORMAL_WRITE 0
+
+typedef struct SCCBHeader {
+ uint16_t length;
+ uint8_t function_code;
+ uint8_t control_mask[3];
+ uint16_t response_code;
+} __attribute__((packed)) SCCBHeader;
+
+#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
+
+typedef struct ReadInfo {
+ SCCBHeader h;
+ uint16_t rnmax;
+ uint8_t rnsize;
+} __attribute__((packed)) ReadInfo;
+
+typedef struct SCCB {
+ SCCBHeader h;
+ char data[SCCB_DATA_LEN];
+ } __attribute__((packed)) SCCB;
+
+/* SCLP event types */
+#define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a
+#define SCLP_EVENT_SIGNAL_QUIESCE 0x1d
+
+/* SCLP event masks */
+#define SCLP_EVENT_MASK_SIGNAL_QUIESCE 0x00000008
+#define SCLP_EVENT_MASK_MSG_ASCII 0x00000040
+
+#define SCLP_UNCONDITIONAL_READ 0x00
+#define SCLP_SELECTIVE_READ 0x01
+
+typedef struct WriteEventMask {
+ SCCBHeader h;
+ uint16_t _reserved;
+ uint16_t mask_length;
+ uint32_t cp_receive_mask;
+ uint32_t cp_send_mask;
+ uint32_t send_mask;
+ uint32_t receive_mask;
+} __attribute__((packed)) WriteEventMask;
+
+typedef struct EventBufferHeader {
+ uint16_t length;
+ uint8_t type;
+ uint8_t flags;
+ uint16_t _reserved;
+} __attribute__((packed)) EventBufferHeader;
+
+typedef struct WriteEventData {
+ SCCBHeader h;
+ EventBufferHeader ebh;
+ char data[0];
+} __attribute__((packed)) WriteEventData;
+
+typedef struct ReadEventData {
+ SCCBHeader h;
+ EventBufferHeader ebh;
+ uint32_t mask;
+} __attribute__((packed)) ReadEventData;
+
+#define __pa(x) (x)
+
+#endif /* SCLP_H */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 07/12] S390: ccw firmware: Add virtio device drivers
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (5 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 06/12] S390: ccw firmware: Add sclp output Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-23 11:24 ` Cornelia Huck
2013-04-22 19:18 ` [Qemu-devel] [PATCH 08/12] S390: ccw firmware: Add glue header Alexander Graf
` (6 subsequent siblings)
13 siblings, 1 reply; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
In order to boot, we need to be able to access a virtio-blk device through
the CCW bus. Implement support for this.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
pc-bios/s390-ccw/cio.h | 322 +++++++++++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/virtio.c | 274 ++++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/virtio.h | 158 ++++++++++++++++++++++
3 files changed, 754 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw/cio.h
create mode 100644 pc-bios/s390-ccw/virtio.c
create mode 100644 pc-bios/s390-ccw/virtio.h
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
new file mode 100644
index 0000000..cb5815a
--- /dev/null
+++ b/pc-bios/s390-ccw/cio.h
@@ -0,0 +1,322 @@
+/*
+ * Channel IO definitions
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * Inspired by various s390 headers in Linux 3.9.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef CIO_H
+#define CIO_H
+
+/*
+ * path management control word
+ */
+struct pmcw {
+ __u32 intparm; /* interruption parameter */
+ __u32 qf : 1; /* qdio facility */
+ __u32 w : 1;
+ __u32 isc : 3; /* interruption sublass */
+ __u32 res5 : 3; /* reserved zeros */
+ __u32 ena : 1; /* enabled */
+ __u32 lm : 2; /* limit mode */
+ __u32 mme : 2; /* measurement-mode enable */
+ __u32 mp : 1; /* multipath mode */
+ __u32 tf : 1; /* timing facility */
+ __u32 dnv : 1; /* device number valid */
+ __u32 dev : 16; /* device number */
+ __u8 lpm; /* logical path mask */
+ __u8 pnom; /* path not operational mask */
+ __u8 lpum; /* last path used mask */
+ __u8 pim; /* path installed mask */
+ __u16 mbi; /* measurement-block index */
+ __u8 pom; /* path operational mask */
+ __u8 pam; /* path available mask */
+ __u8 chpid[8]; /* CHPID 0-7 (if available) */
+ __u32 unused1 : 8; /* reserved zeros */
+ __u32 st : 3; /* subchannel type */
+ __u32 unused2 : 18; /* reserved zeros */
+ __u32 mbfc : 1; /* measurement block format control */
+ __u32 xmwme : 1; /* extended measurement word mode enable */
+ __u32 csense : 1; /* concurrent sense; can be enabled ...*/
+ /* ... per MSCH, however, if facility */
+ /* ... is not installed, this results */
+ /* ... in an operand exception. */
+} __attribute__ ((packed));
+
+/* Target SCHIB configuration. */
+struct schib_config {
+ __u64 mba;
+ __u32 intparm;
+ __u16 mbi;
+ __u32 isc:3;
+ __u32 ena:1;
+ __u32 mme:2;
+ __u32 mp:1;
+ __u32 csense:1;
+ __u32 mbfc:1;
+} __attribute__ ((packed));
+
+struct scsw {
+ __u16 flags;
+ __u16 ctrl;
+ __u32 cpa;
+ __u8 dstat;
+ __u8 cstat;
+ __u16 count;
+} __attribute__ ((packed));
+
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
+#define SCSW_FCTL_HALT_FUNC 0x2000
+#define SCSW_FCTL_START_FUNC 0x4000
+
+/*
+ * subchannel information block
+ */
+struct schib {
+ struct pmcw pmcw; /* path management control word */
+ struct scsw scsw; /* subchannel status word */
+ __u64 mba; /* measurement block address */
+ __u8 mda[4]; /* model dependent area */
+} __attribute__ ((packed,aligned(4)));
+
+struct subchannel_id {
+ __u32 cssid : 8;
+ __u32 : 4;
+ __u32 m : 1;
+ __u32 ssid : 2;
+ __u32 one : 1;
+ __u32 sch_no : 16;
+} __attribute__ ((packed, aligned(4)));
+
+/*
+ * TPI info structure
+ */
+struct tpi_info {
+ struct subchannel_id schid;
+ __u32 intparm; /* interruption parameter */
+ __u32 adapter_IO : 1;
+ __u32 reserved2 : 1;
+ __u32 isc : 3;
+ __u32 reserved3 : 12;
+ __u32 int_type : 3;
+ __u32 reserved4 : 12;
+} __attribute__ ((packed));
+
+/* channel command word (type 1) */
+struct ccw1 {
+ __u8 cmd_code;
+ __u8 flags;
+ __u16 count;
+ __u32 cda;
+} __attribute__ ((packed));
+
+#define CCW_FLAG_DC 0x80
+#define CCW_FLAG_CC 0x40
+#define CCW_FLAG_SLI 0x20
+#define CCW_FLAG_SKIP 0x10
+#define CCW_FLAG_PCI 0x08
+#define CCW_FLAG_IDA 0x04
+#define CCW_FLAG_SUSPEND 0x02
+
+#define CCW_CMD_NOOP 0x03
+#define CCW_CMD_BASIC_SENSE 0x04
+#define CCW_CMD_TIC 0x08
+#define CCW_CMD_SENSE_ID 0xe4
+
+#define CCW_CMD_SET_VQ 0x13
+#define CCW_CMD_VDEV_RESET 0x33
+#define CCW_CMD_READ_FEAT 0x12
+#define CCW_CMD_WRITE_FEAT 0x11
+#define CCW_CMD_READ_CONF 0x22
+#define CCW_CMD_WRITE_CONF 0x21
+#define CCW_CMD_WRITE_STATUS 0x31
+#define CCW_CMD_SET_IND 0x43
+#define CCW_CMD_SET_CONF_IND 0x53
+#define CCW_CMD_READ_VQ_CONF 0x32
+
+/*
+ * Command-mode operation request block
+ */
+struct cmd_orb {
+ __u32 intparm; /* interruption parameter */
+ __u32 key:4; /* flags, like key, suspend control, etc. */
+ __u32 spnd:1; /* suspend control */
+ __u32 res1:1; /* reserved */
+ __u32 mod:1; /* modification control */
+ __u32 sync:1; /* synchronize control */
+ __u32 fmt:1; /* format control */
+ __u32 pfch:1; /* prefetch control */
+ __u32 isic:1; /* initial-status-interruption control */
+ __u32 alcc:1; /* address-limit-checking control */
+ __u32 ssic:1; /* suppress-suspended-interr. control */
+ __u32 res2:1; /* reserved */
+ __u32 c64:1; /* IDAW/QDIO 64 bit control */
+ __u32 i2k:1; /* IDAW 2/4kB block size control */
+ __u32 lpm:8; /* logical path mask */
+ __u32 ils:1; /* incorrect length */
+ __u32 zero:6; /* reserved zeros */
+ __u32 orbx:1; /* ORB extension control */
+ __u32 cpa; /* channel program address */
+} __attribute__ ((packed, aligned(4)));
+
+struct ciw {
+ __u8 type;
+ __u8 command;
+ __u16 count;
+};
+
+/*
+ * sense-id response buffer layout
+ */
+struct senseid {
+ /* common part */
+ __u8 reserved; /* always 0x'FF' */
+ __u16 cu_type; /* control unit type */
+ __u8 cu_model; /* control unit model */
+ __u16 dev_type; /* device type */
+ __u8 dev_model; /* device model */
+ __u8 unused; /* padding byte */
+ /* extended part */
+ struct ciw ciw[62];
+} __attribute__ ((packed, aligned(4)));
+
+/* interruption response block */
+struct irb {
+ struct scsw scsw;
+ __u32 esw[5];
+ __u32 ecw[8];
+ __u32 emw[8];
+} __attribute__ ((packed, aligned(4)));
+
+/*
+ * Some S390 specific IO instructions as inline
+ */
+
+static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode = -EIO;
+
+ asm volatile(
+ " stsch 0(%3)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ : "+d" (ccode), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int msch(struct subchannel_id schid, struct schib *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode;
+
+ asm volatile(
+ " msch 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int msch_err(struct subchannel_id schid, struct schib *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode = -EIO;
+
+ asm volatile(
+ " msch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ : "+d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int tsch(struct subchannel_id schid, struct irb *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode;
+
+ asm volatile(
+ " tsch 0(%3)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
+{
+ register struct subchannel_id reg1 asm("1") = schid;
+ int ccode = -EIO;
+
+ asm volatile(
+ " ssch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ : "+d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc", "memory");
+ return ccode;
+}
+
+static inline int csch(struct subchannel_id schid)
+{
+ register struct subchannel_id reg1 asm("1") = schid;
+ int ccode;
+
+ asm volatile(
+ " csch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode)
+ : "d" (reg1)
+ : "cc");
+ return ccode;
+}
+
+static inline int tpi(struct tpi_info *addr)
+{
+ int ccode;
+
+ asm volatile(
+ " tpi 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode), "=m" (*addr)
+ : "a" (addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int chsc(void *chsc_area)
+{
+ typedef struct { char _[4096]; } addr_type;
+ int cc;
+
+ asm volatile(
+ " .insn rre,0xb25f0000,%2,0\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (cc), "=m" (*(addr_type *) chsc_area)
+ : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
+ : "cc");
+ return cc;
+}
+
+#endif /* CIO_H */
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
new file mode 100644
index 0000000..79e2941
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio.c
@@ -0,0 +1,274 @@
+/*
+ * Virtio driver bits
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+#include "virtio.h"
+
+struct vring block;
+
+static long kvm_hypercall(unsigned long nr, unsigned long param1,
+ unsigned long param2)
+{
+ register ulong r_nr asm("1") = nr;
+ register ulong r_param1 asm("2") = param1;
+ register ulong r_param2 asm("3") = param2;
+ register long retval asm("2");
+
+ asm volatile ("diag 2,4,0x500"
+ : "=d" (retval)
+ : "d" (r_nr), "0" (r_param1), "r"(r_param2)
+ : "memory", "cc");
+
+ return retval;
+}
+
+static void virtio_notify(struct subchannel_id schid)
+{
+ kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, *(u32*)&schid, 0);
+}
+
+/***********************************************
+ * Virtio functions *
+ ***********************************************/
+
+static void drain_irqs(struct subchannel_id schid)
+{
+ struct irb irb = {};
+ while (1) {
+ if (tsch(schid, &irb)) {
+ return;
+ }
+ }
+}
+
+static int run_ccw(struct subchannel_id schid, int cmd, void *ptr, int len)
+{
+ struct ccw1 ccw = {};
+ struct cmd_orb orb = {};
+ struct schib schib;
+ int r;
+
+ /* start command processing */
+ stsch_err(schid, &schib);
+ schib.scsw.ctrl = SCSW_FCTL_START_FUNC;
+ msch(schid, &schib);
+
+ /* start subchannel command */
+ orb.fmt = 1;
+ orb.cpa = (u32)(long)&ccw;
+ orb.lpm = 0x80;
+
+ ccw.cmd_code = cmd;
+ ccw.cda = (long)ptr;
+ ccw.count = len;
+
+ r = ssch(schid, &orb);
+ /*
+ * XXX Wait until device is done processing the CCW. For now we can
+ * assume that a simple tsch will have finished the CCW processing,
+ * but the architecture allows for asynchronous operation
+ */
+ drain_irqs(schid);
+ return r;
+}
+
+static void virtio_set_status(struct subchannel_id schid,
+ unsigned long dev_addr)
+{
+ unsigned char status = dev_addr;
+ run_ccw(schid, CCW_CMD_WRITE_STATUS, &status, sizeof(status));
+}
+
+static void virtio_reset(struct subchannel_id schid)
+{
+ run_ccw(schid, CCW_CMD_VDEV_RESET, NULL, 0);
+}
+
+static void vring_init(struct vring *vr, unsigned int num, void *p,
+ unsigned long align)
+{
+ debug_print_addr("init p", p);
+ vr->num = num;
+ vr->desc = p;
+ vr->avail = p + num*sizeof(struct vring_desc);
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
+ & ~(align - 1));
+
+ /* We're running with interrupts off anyways, so don't bother */
+ vr->used->flags = VRING_USED_F_NO_NOTIFY;
+
+ debug_print_addr("init vr", vr);
+}
+
+static void vring_notify(struct subchannel_id schid)
+{
+ virtio_notify(schid);
+}
+
+static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
+{
+ /* For follow-up chains we need to keep the first entry point */
+ if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
+ vr->avail->ring[vr->avail->idx % vr->num] = vr->next_idx;
+ }
+
+ vr->desc[vr->next_idx].addr = (ulong)p;
+ vr->desc[vr->next_idx].len = len;
+ vr->desc[vr->next_idx].flags = flags & ~VRING_HIDDEN_IS_CHAIN;
+ vr->desc[vr->next_idx].next = ++vr->next_idx;
+
+ /* Chains only have a single ID */
+ if (!(flags & VRING_DESC_F_NEXT)) {
+ vr->avail->idx++;
+ }
+
+ vr->used->idx = vr->next_idx;
+}
+
+static u64 get_clock(void)
+{
+ u64 r;
+
+ asm volatile("stck %0" : "=Q" (r) : : "cc");
+ return r;
+}
+
+static ulong get_second(void)
+{
+ return (get_clock() >> 12) / 1000000;
+}
+
+/*
+ * Wait for the host to reply.
+ *
+ * timeout is in seconds if > 0.
+ *
+ * Returns 0 on success, 1 on timeout.
+ */
+static int vring_wait_reply(struct vring *vr, int timeout)
+{
+ ulong target_second = get_second() + timeout;
+ struct subchannel_id schid = vr->schid;
+ int r = 0;
+
+ while (vr->used->idx == vr->next_idx) {
+ vring_notify(schid);
+ if (timeout && (get_second() >= target_second)) {
+ r = 1;
+ break;
+ }
+ yield();
+ }
+
+ vr->next_idx = 0;
+ vr->desc[0].len = 0;
+ vr->desc[0].flags = 0;
+
+ return r;
+}
+
+/***********************************************
+ * Virtio block *
+ ***********************************************/
+
+static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
+{
+ struct virtio_blk_outhdr out_hdr;
+ u8 status;
+
+ /* Tell the host we want to read */
+ out_hdr.type = VIRTIO_BLK_T_IN;
+ out_hdr.ioprio = 99;
+ out_hdr.sector = sector;
+
+ vring_send_buf(&block, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
+
+ /* This is where we want to receive data */
+ vring_send_buf(&block, load_addr, SECTOR_SIZE * sec_num,
+ VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
+ VRING_DESC_F_NEXT);
+
+ /* status field */
+ vring_send_buf(&block, &status, sizeof(u8), VRING_DESC_F_WRITE |
+ VRING_HIDDEN_IS_CHAIN);
+
+ /* Now we can tell the host to read */
+ vring_wait_reply(&block, 0);
+
+ drain_irqs(block.schid);
+
+ return status;
+}
+
+unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
+ ulong subchan_id, void *load_addr)
+{
+ u8 status;
+ int sec = rec_list1;
+ int sec_num = (((rec_list2 >> 32)+ 1) & 0xffff);
+ int sec_len = rec_list2 >> 48;
+ ulong addr = (ulong)load_addr;
+
+ if (sec_len != SECTOR_SIZE) {
+ return -1;
+ }
+
+ sclp_print(".");
+ status = virtio_read_many(sec, (void*)addr, sec_num);
+ if (status) {
+ virtio_panic("I/O Error");
+ }
+ addr += sec_num * SECTOR_SIZE;
+
+ return addr;
+}
+
+int virtio_read(ulong sector, void *load_addr)
+{
+ return virtio_read_many(sector, load_addr, 1);
+}
+
+void virtio_setup_block(struct subchannel_id schid)
+{
+ struct vq_info_block info;
+
+ virtio_reset(schid);
+
+ /* XXX need to fetch the 128 from host */
+ vring_init(&block, 128, (void*)(100 * 1024 * 1024),
+ KVM_S390_VIRTIO_RING_ALIGN);
+
+ info.queue = (100ULL * 1024ULL* 1024ULL);
+ info.align = KVM_S390_VIRTIO_RING_ALIGN;
+ info.index = 0;
+ info.num = 128;
+ block.schid = schid;
+
+ run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info));
+ virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
+}
+
+bool virtio_is_blk(struct subchannel_id schid)
+{
+ int r;
+ struct senseid senseid = {};
+
+ /* run sense id command */
+ r = run_ccw(schid, CCW_CMD_SENSE_ID, &senseid, sizeof(senseid));
+ if (r) {
+ return false;
+ }
+ if ((senseid.cu_type != 0x3832) || (senseid.cu_model != VIRTIO_ID_BLOCK)) {
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
new file mode 100644
index 0000000..a33199d
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio.h
@@ -0,0 +1,158 @@
+/*
+ * Virtio driver bits
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef VIRTIO_H
+#define VIRTIO_H
+
+#include "s390-ccw.h"
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER 2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK 4
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED 0x80
+
+enum virtio_dev_type {
+ VIRTIO_ID_NET = 1,
+ VIRTIO_ID_BLOCK = 2,
+ VIRTIO_ID_CONSOLE = 3,
+ VIRTIO_ID_BALLOON = 5,
+};
+
+struct virtio_dev_header {
+ enum virtio_dev_type type : 8;
+ u8 num_vq;
+ u8 feature_len;
+ u8 config_len;
+ u8 status;
+ u8 vqconfig[];
+} __attribute__((packed));
+
+struct virtio_vqconfig {
+ u64 token;
+ u64 address;
+ u16 num;
+ u8 pad[6];
+} __attribute__((packed));
+
+struct vq_info_block {
+ u64 queue;
+ u32 align;
+ u16 index;
+ u16 num;
+} __attribute__((packed));
+
+struct virtio_dev {
+ struct virtio_dev_header *header;
+ struct virtio_vqconfig *vqconfig;
+ char *host_features;
+ char *guest_features;
+ char *config;
+};
+
+#define KVM_S390_VIRTIO_RING_ALIGN 4096
+
+#define VRING_USED_F_NO_NOTIFY 1
+
+/* This marks a buffer as continuing via the next field. */
+#define VRING_DESC_F_NEXT 1
+/* This marks a buffer as write-only (otherwise read-only). */
+#define VRING_DESC_F_WRITE 2
+/* This means the buffer contains a list of buffer descriptors. */
+#define VRING_DESC_F_INDIRECT 4
+
+/* Internal flag to mark follow-up segments as such */
+#define VRING_HIDDEN_IS_CHAIN 256
+
+/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
+struct vring_desc {
+ /* Address (guest-physical). */
+ u64 addr;
+ /* Length. */
+ u32 len;
+ /* The flags as indicated above. */
+ u16 flags;
+ /* We chain unused descriptors via this, too */
+ u16 next;
+} __attribute__((packed));
+
+struct vring_avail {
+ u16 flags;
+ u16 idx;
+ u16 ring[];
+} __attribute__((packed));
+
+/* u32 is used here for ids for padding reasons. */
+struct vring_used_elem {
+ /* Index of start of used descriptor chain. */
+ u32 id;
+ /* Total length of the descriptor chain which was used (written to) */
+ u32 len;
+} __attribute__((packed));
+
+struct vring_used {
+ u16 flags;
+ u16 idx;
+ struct vring_used_elem ring[];
+} __attribute__((packed));
+
+struct vring {
+ unsigned int num;
+ int next_idx;
+ struct vring_desc *desc;
+ struct vring_avail *avail;
+ struct vring_used *used;
+ struct subchannel_id schid;
+};
+
+
+/***********************************************
+ * Virtio block *
+ ***********************************************/
+
+/*
+ * Command types
+ *
+ * Usage is a bit tricky as some bits are used as flags and some are not.
+ *
+ * Rules:
+ * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
+ * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own
+ * and may not be combined with any of the other flags.
+ */
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN 0
+#define VIRTIO_BLK_T_OUT 1
+
+/* This bit says it's a scsi command, not an actual read or write. */
+#define VIRTIO_BLK_T_SCSI_CMD 2
+
+/* Cache flush command */
+#define VIRTIO_BLK_T_FLUSH 4
+
+/* Barrier before this op. */
+#define VIRTIO_BLK_T_BARRIER 0x80000000
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr {
+ /* VIRTIO_BLK_T* */
+ u32 type;
+ /* io priority. */
+ u32 ioprio;
+ /* Sector (ie. 512 byte offset) */
+ u64 sector;
+};
+
+#endif /* VIRTIO_H */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] S390: ccw firmware: Add virtio device drivers
2013-04-22 19:18 ` [Qemu-devel] [PATCH 07/12] S390: ccw firmware: Add virtio device drivers Alexander Graf
@ 2013-04-23 11:24 ` Cornelia Huck
0 siblings, 0 replies; 30+ messages in thread
From: Cornelia Huck @ 2013-04-23 11:24 UTC (permalink / raw)
To: Alexander Graf; +Cc: Christian Borntraeger, qemu-devel, Dominik Dingel
On Mon, 22 Apr 2013 21:18:13 +0200
Alexander Graf <agraf@suse.de> wrote:
> In order to boot, we need to be able to access a virtio-blk device through
> the CCW bus. Implement support for this.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
> pc-bios/s390-ccw/cio.h | 322 +++++++++++++++++++++++++++++++++++++++++++++
> pc-bios/s390-ccw/virtio.c | 274 ++++++++++++++++++++++++++++++++++++++
> pc-bios/s390-ccw/virtio.h | 158 ++++++++++++++++++++++
> 3 files changed, 754 insertions(+), 0 deletions(-)
> create mode 100644 pc-bios/s390-ccw/cio.h
> create mode 100644 pc-bios/s390-ccw/virtio.c
> create mode 100644 pc-bios/s390-ccw/virtio.h
>
> diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
> new file mode 100644
> index 0000000..cb5815a
> --- /dev/null
> +++ b/pc-bios/s390-ccw/cio.h
> @@ -0,0 +1,322 @@
> +/*
> + * Channel IO definitions
> + *
> + * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
> + *
> + * Inspired by various s390 headers in Linux 3.9.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> + * your option) any later version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#ifndef CIO_H
> +#define CIO_H
> +
> +/*
> + * path management control word
> + */
> +struct pmcw {
> + __u32 intparm; /* interruption parameter */
> + __u32 qf : 1; /* qdio facility */
> + __u32 w : 1;
> + __u32 isc : 3; /* interruption sublass */
> + __u32 res5 : 3; /* reserved zeros */
> + __u32 ena : 1; /* enabled */
> + __u32 lm : 2; /* limit mode */
> + __u32 mme : 2; /* measurement-mode enable */
> + __u32 mp : 1; /* multipath mode */
> + __u32 tf : 1; /* timing facility */
> + __u32 dnv : 1; /* device number valid */
> + __u32 dev : 16; /* device number */
> + __u8 lpm; /* logical path mask */
> + __u8 pnom; /* path not operational mask */
> + __u8 lpum; /* last path used mask */
> + __u8 pim; /* path installed mask */
> + __u16 mbi; /* measurement-block index */
> + __u8 pom; /* path operational mask */
> + __u8 pam; /* path available mask */
> + __u8 chpid[8]; /* CHPID 0-7 (if available) */
> + __u32 unused1 : 8; /* reserved zeros */
> + __u32 st : 3; /* subchannel type */
> + __u32 unused2 : 18; /* reserved zeros */
> + __u32 mbfc : 1; /* measurement block format control */
> + __u32 xmwme : 1; /* extended measurement word mode enable */
> + __u32 csense : 1; /* concurrent sense; can be enabled ...*/
> + /* ... per MSCH, however, if facility */
> + /* ... is not installed, this results */
> + /* ... in an operand exception. */
> +} __attribute__ ((packed));
> +
> +/* Target SCHIB configuration. */
> +struct schib_config {
> + __u64 mba;
> + __u32 intparm;
> + __u16 mbi;
> + __u32 isc:3;
> + __u32 ena:1;
> + __u32 mme:2;
> + __u32 mp:1;
> + __u32 csense:1;
> + __u32 mbfc:1;
> +} __attribute__ ((packed));
I'd be surprised if you needed that structure.
> +
> +struct scsw {
> + __u16 flags;
> + __u16 ctrl;
> + __u32 cpa;
> + __u8 dstat;
> + __u8 cstat;
> + __u16 count;
> +} __attribute__ ((packed));
> +
> +#define SCSW_FCTL_CLEAR_FUNC 0x1000
> +#define SCSW_FCTL_HALT_FUNC 0x2000
> +#define SCSW_FCTL_START_FUNC 0x4000
> +
> +/*
> + * subchannel information block
> + */
> +struct schib {
> + struct pmcw pmcw; /* path management control word */
> + struct scsw scsw; /* subchannel status word */
> + __u64 mba; /* measurement block address */
> + __u8 mda[4]; /* model dependent area */
> +} __attribute__ ((packed,aligned(4)));
> +
> +struct subchannel_id {
> + __u32 cssid : 8;
> + __u32 : 4;
> + __u32 m : 1;
> + __u32 ssid : 2;
> + __u32 one : 1;
> + __u32 sch_no : 16;
> +} __attribute__ ((packed, aligned(4)));
> +
> +/*
> + * TPI info structure
> + */
> +struct tpi_info {
> + struct subchannel_id schid;
> + __u32 intparm; /* interruption parameter */
> + __u32 adapter_IO : 1;
> + __u32 reserved2 : 1;
> + __u32 isc : 3;
> + __u32 reserved3 : 12;
> + __u32 int_type : 3;
> + __u32 reserved4 : 12;
> +} __attribute__ ((packed));
> +
> +/* channel command word (type 1) */
> +struct ccw1 {
> + __u8 cmd_code;
> + __u8 flags;
> + __u16 count;
> + __u32 cda;
> +} __attribute__ ((packed));
> +
> +#define CCW_FLAG_DC 0x80
> +#define CCW_FLAG_CC 0x40
> +#define CCW_FLAG_SLI 0x20
> +#define CCW_FLAG_SKIP 0x10
> +#define CCW_FLAG_PCI 0x08
> +#define CCW_FLAG_IDA 0x04
> +#define CCW_FLAG_SUSPEND 0x02
> +
> +#define CCW_CMD_NOOP 0x03
> +#define CCW_CMD_BASIC_SENSE 0x04
> +#define CCW_CMD_TIC 0x08
> +#define CCW_CMD_SENSE_ID 0xe4
> +
> +#define CCW_CMD_SET_VQ 0x13
> +#define CCW_CMD_VDEV_RESET 0x33
> +#define CCW_CMD_READ_FEAT 0x12
> +#define CCW_CMD_WRITE_FEAT 0x11
> +#define CCW_CMD_READ_CONF 0x22
> +#define CCW_CMD_WRITE_CONF 0x21
> +#define CCW_CMD_WRITE_STATUS 0x31
> +#define CCW_CMD_SET_IND 0x43
> +#define CCW_CMD_SET_CONF_IND 0x53
> +#define CCW_CMD_READ_VQ_CONF 0x32
> +
> +/*
> + * Command-mode operation request block
> + */
> +struct cmd_orb {
> + __u32 intparm; /* interruption parameter */
> + __u32 key:4; /* flags, like key, suspend control, etc. */
> + __u32 spnd:1; /* suspend control */
> + __u32 res1:1; /* reserved */
> + __u32 mod:1; /* modification control */
> + __u32 sync:1; /* synchronize control */
> + __u32 fmt:1; /* format control */
> + __u32 pfch:1; /* prefetch control */
> + __u32 isic:1; /* initial-status-interruption control */
> + __u32 alcc:1; /* address-limit-checking control */
> + __u32 ssic:1; /* suppress-suspended-interr. control */
> + __u32 res2:1; /* reserved */
> + __u32 c64:1; /* IDAW/QDIO 64 bit control */
> + __u32 i2k:1; /* IDAW 2/4kB block size control */
> + __u32 lpm:8; /* logical path mask */
> + __u32 ils:1; /* incorrect length */
> + __u32 zero:6; /* reserved zeros */
> + __u32 orbx:1; /* ORB extension control */
> + __u32 cpa; /* channel program address */
> +} __attribute__ ((packed, aligned(4)));
Just make this orb. I doubt we want to emulate transport mode :)
> +
> +struct ciw {
> + __u8 type;
> + __u8 command;
> + __u16 count;
> +};
> +
> +/*
> + * sense-id response buffer layout
> + */
> +struct senseid {
> + /* common part */
> + __u8 reserved; /* always 0x'FF' */
> + __u16 cu_type; /* control unit type */
> + __u8 cu_model; /* control unit model */
> + __u16 dev_type; /* device type */
> + __u8 dev_model; /* device model */
> + __u8 unused; /* padding byte */
> + /* extended part */
> + struct ciw ciw[62];
> +} __attribute__ ((packed, aligned(4)));
> +
> +/* interruption response block */
> +struct irb {
> + struct scsw scsw;
> + __u32 esw[5];
> + __u32 ecw[8];
> + __u32 emw[8];
> +} __attribute__ ((packed, aligned(4)));
> +
> +/*
> + * Some S390 specific IO instructions as inline
> + */
> +
> +static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
> +{
> + register struct subchannel_id reg1 asm ("1") = schid;
> + int ccode = -EIO;
> +
> + asm volatile(
> + " stsch 0(%3)\n"
> + "0: ipm %0\n"
> + " srl %0,28\n"
> + "1:\n"
> + : "+d" (ccode), "=m" (*addr)
> + : "d" (reg1), "a" (addr)
> + : "cc");
> + return ccode;
> +}
> +
> +static inline int msch(struct subchannel_id schid, struct schib *addr)
> +{
> + register struct subchannel_id reg1 asm ("1") = schid;
> + int ccode;
> +
> + asm volatile(
> + " msch 0(%2)\n"
> + " ipm %0\n"
> + " srl %0,28"
> + : "=d" (ccode)
> + : "d" (reg1), "a" (addr), "m" (*addr)
> + : "cc");
> + return ccode;
> +}
> +
> +static inline int msch_err(struct subchannel_id schid, struct schib *addr)
> +{
> + register struct subchannel_id reg1 asm ("1") = schid;
> + int ccode = -EIO;
> +
> + asm volatile(
> + " msch 0(%2)\n"
> + "0: ipm %0\n"
> + " srl %0,28\n"
> + "1:\n"
> + : "+d" (ccode)
> + : "d" (reg1), "a" (addr), "m" (*addr)
> + : "cc");
> + return ccode;
> +}
> +
> +static inline int tsch(struct subchannel_id schid, struct irb *addr)
> +{
> + register struct subchannel_id reg1 asm ("1") = schid;
> + int ccode;
> +
> + asm volatile(
> + " tsch 0(%3)\n"
> + " ipm %0\n"
> + " srl %0,28"
> + : "=d" (ccode), "=m" (*addr)
> + : "d" (reg1), "a" (addr)
> + : "cc");
> + return ccode;
> +}
> +
> +static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
> +{
> + register struct subchannel_id reg1 asm("1") = schid;
> + int ccode = -EIO;
> +
> + asm volatile(
> + " ssch 0(%2)\n"
> + "0: ipm %0\n"
> + " srl %0,28\n"
> + "1:\n"
> + : "+d" (ccode)
> + : "d" (reg1), "a" (addr), "m" (*addr)
> + : "cc", "memory");
> + return ccode;
> +}
> +
> +static inline int csch(struct subchannel_id schid)
> +{
> + register struct subchannel_id reg1 asm("1") = schid;
> + int ccode;
> +
> + asm volatile(
> + " csch\n"
> + " ipm %0\n"
> + " srl %0,28"
> + : "=d" (ccode)
> + : "d" (reg1)
> + : "cc");
> + return ccode;
> +}
> +
> +static inline int tpi(struct tpi_info *addr)
> +{
> + int ccode;
> +
> + asm volatile(
> + " tpi 0(%2)\n"
> + " ipm %0\n"
> + " srl %0,28"
> + : "=d" (ccode), "=m" (*addr)
> + : "a" (addr)
> + : "cc");
> + return ccode;
> +}
> +
> +static inline int chsc(void *chsc_area)
You'll probably won't need chsc, unless you want to support ipling from
subchannel sets > 0.
> +{
> + typedef struct { char _[4096]; } addr_type;
> + int cc;
> +
> + asm volatile(
> + " .insn rre,0xb25f0000,%2,0\n"
> + " ipm %0\n"
> + " srl %0,28\n"
> + : "=d" (cc), "=m" (*(addr_type *) chsc_area)
> + : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
> + : "cc");
> + return cc;
> +}
> +
> +#endif /* CIO_H */
> diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
> new file mode 100644
> index 0000000..79e2941
> --- /dev/null
> +++ b/pc-bios/s390-ccw/virtio.c
> @@ -0,0 +1,274 @@
> +/*
> + * Virtio driver bits
> + *
> + * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> + * your option) any later version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#include "s390-ccw.h"
> +#include "virtio.h"
> +
> +struct vring block;
> +
> +static long kvm_hypercall(unsigned long nr, unsigned long param1,
> + unsigned long param2)
> +{
> + register ulong r_nr asm("1") = nr;
> + register ulong r_param1 asm("2") = param1;
> + register ulong r_param2 asm("3") = param2;
> + register long retval asm("2");
> +
> + asm volatile ("diag 2,4,0x500"
> + : "=d" (retval)
> + : "d" (r_nr), "0" (r_param1), "r"(r_param2)
> + : "memory", "cc");
> +
> + return retval;
> +}
> +
> +static void virtio_notify(struct subchannel_id schid)
> +{
> + kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, *(u32*)&schid, 0);
> +}
> +
> +/***********************************************
> + * Virtio functions *
> + ***********************************************/
> +
> +static void drain_irqs(struct subchannel_id schid)
> +{
> + struct irb irb = {};
> + while (1) {
> + if (tsch(schid, &irb)) {
> + return;
> + }
> + }
> +}
Please convert this to a tpi-loop with tsch on interrupt, and
actually return an error if the irb has an error condition (see the
guest virtio_ccw driver for an example).
> +
> +static int run_ccw(struct subchannel_id schid, int cmd, void *ptr, int len)
> +{
> + struct ccw1 ccw = {};
> + struct cmd_orb orb = {};
> + struct schib schib;
> + int r;
> +
> + /* start command processing */
> + stsch_err(schid, &schib);
> + schib.scsw.ctrl = SCSW_FCTL_START_FUNC;
Not needed.
> + msch(schid, &schib);
Hmm... where do you set pmcw.ena? If you can do I/O on disabled
subchannels, this is a bug in the virtual css :)
> +
> + /* start subchannel command */
> + orb.fmt = 1;
> + orb.cpa = (u32)(long)&ccw;
Is this guaranteed to always work?
> + orb.lpm = 0x80;
> +
> + ccw.cmd_code = cmd;
> + ccw.cda = (long)ptr;
> + ccw.count = len;
> +
> + r = ssch(schid, &orb);
> + /*
> + * XXX Wait until device is done processing the CCW. For now we can
> + * assume that a simple tsch will have finished the CCW processing,
> + * but the architecture allows for asynchronous operation
> + */
And that's why you should use a tpi-loop + tsch :)
> + drain_irqs(schid);
You don't need to collect status if ssch() returned an error, but you
should return errors indicated in the irb as well.
> + return r;
> +}
> +
> +static void virtio_set_status(struct subchannel_id schid,
> + unsigned long dev_addr)
> +{
> + unsigned char status = dev_addr;
> + run_ccw(schid, CCW_CMD_WRITE_STATUS, &status, sizeof(status));
It might be a good idea to do virtio_panic() on error (also some other
callers of run_ccw()).
> +}
> +
> +static void virtio_reset(struct subchannel_id schid)
> +{
> + run_ccw(schid, CCW_CMD_VDEV_RESET, NULL, 0);
> +}
> +
> +static void vring_init(struct vring *vr, unsigned int num, void *p,
> + unsigned long align)
> +{
> + debug_print_addr("init p", p);
> + vr->num = num;
> + vr->desc = p;
> + vr->avail = p + num*sizeof(struct vring_desc);
> + vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
> + & ~(align - 1));
> +
> + /* We're running with interrupts off anyways, so don't bother */
> + vr->used->flags = VRING_USED_F_NO_NOTIFY;
> +
> + debug_print_addr("init vr", vr);
> +}
> +
> +static void vring_notify(struct subchannel_id schid)
> +{
> + virtio_notify(schid);
> +}
> +
> +static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
> +{
> + /* For follow-up chains we need to keep the first entry point */
> + if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
> + vr->avail->ring[vr->avail->idx % vr->num] = vr->next_idx;
> + }
> +
> + vr->desc[vr->next_idx].addr = (ulong)p;
> + vr->desc[vr->next_idx].len = len;
> + vr->desc[vr->next_idx].flags = flags & ~VRING_HIDDEN_IS_CHAIN;
> + vr->desc[vr->next_idx].next = ++vr->next_idx;
> +
> + /* Chains only have a single ID */
> + if (!(flags & VRING_DESC_F_NEXT)) {
> + vr->avail->idx++;
> + }
> +
> + vr->used->idx = vr->next_idx;
> +}
> +
> +static u64 get_clock(void)
> +{
> + u64 r;
> +
> + asm volatile("stck %0" : "=Q" (r) : : "cc");
> + return r;
> +}
> +
> +static ulong get_second(void)
> +{
> + return (get_clock() >> 12) / 1000000;
> +}
> +
> +/*
> + * Wait for the host to reply.
> + *
> + * timeout is in seconds if > 0.
> + *
> + * Returns 0 on success, 1 on timeout.
> + */
> +static int vring_wait_reply(struct vring *vr, int timeout)
> +{
> + ulong target_second = get_second() + timeout;
> + struct subchannel_id schid = vr->schid;
> + int r = 0;
> +
> + while (vr->used->idx == vr->next_idx) {
> + vring_notify(schid);
> + if (timeout && (get_second() >= target_second)) {
> + r = 1;
> + break;
> + }
> + yield();
> + }
> +
> + vr->next_idx = 0;
> + vr->desc[0].len = 0;
> + vr->desc[0].flags = 0;
> +
> + return r;
> +}
> +
> +/***********************************************
> + * Virtio block *
> + ***********************************************/
> +
> +static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
> +{
> + struct virtio_blk_outhdr out_hdr;
> + u8 status;
> +
> + /* Tell the host we want to read */
> + out_hdr.type = VIRTIO_BLK_T_IN;
> + out_hdr.ioprio = 99;
> + out_hdr.sector = sector;
> +
> + vring_send_buf(&block, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
> +
> + /* This is where we want to receive data */
> + vring_send_buf(&block, load_addr, SECTOR_SIZE * sec_num,
> + VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
> + VRING_DESC_F_NEXT);
> +
> + /* status field */
> + vring_send_buf(&block, &status, sizeof(u8), VRING_DESC_F_WRITE |
> + VRING_HIDDEN_IS_CHAIN);
> +
> + /* Now we can tell the host to read */
> + vring_wait_reply(&block, 0);
> +
> + drain_irqs(block.schid);
Collect error from irb?
> +
> + return status;
> +}
> +
> +unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
> + ulong subchan_id, void *load_addr)
> +{
> + u8 status;
> + int sec = rec_list1;
> + int sec_num = (((rec_list2 >> 32)+ 1) & 0xffff);
> + int sec_len = rec_list2 >> 48;
> + ulong addr = (ulong)load_addr;
> +
> + if (sec_len != SECTOR_SIZE) {
> + return -1;
> + }
> +
> + sclp_print(".");
> + status = virtio_read_many(sec, (void*)addr, sec_num);
> + if (status) {
> + virtio_panic("I/O Error");
> + }
> + addr += sec_num * SECTOR_SIZE;
> +
> + return addr;
> +}
> +
> +int virtio_read(ulong sector, void *load_addr)
> +{
> + return virtio_read_many(sector, load_addr, 1);
> +}
> +
> +void virtio_setup_block(struct subchannel_id schid)
> +{
> + struct vq_info_block info;
> +
> + virtio_reset(schid);
> +
> + /* XXX need to fetch the 128 from host */
Please ;)
> + vring_init(&block, 128, (void*)(100 * 1024 * 1024),
> + KVM_S390_VIRTIO_RING_ALIGN);
> +
> + info.queue = (100ULL * 1024ULL* 1024ULL);
> + info.align = KVM_S390_VIRTIO_RING_ALIGN;
> + info.index = 0;
> + info.num = 128;
> + block.schid = schid;
> +
> + run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info));
No host->guest notifications, right? Otherwise you'd be dead without
indicators. (Mental note to self: make sure virtio-ccw handles this
fine.)
> + virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
> +}
> +
> +bool virtio_is_blk(struct subchannel_id schid)
> +{
> + int r;
> + struct senseid senseid = {};
> +
> + /* run sense id command */
> + r = run_ccw(schid, CCW_CMD_SENSE_ID, &senseid, sizeof(senseid));
> + if (r) {
> + return false;
> + }
> + if ((senseid.cu_type != 0x3832) || (senseid.cu_model != VIRTIO_ID_BLOCK)) {
> + return false;
> + }
> +
> + return true;
> +}
> +
> diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
> new file mode 100644
> index 0000000..a33199d
> --- /dev/null
> +++ b/pc-bios/s390-ccw/virtio.h
> @@ -0,0 +1,158 @@
> +/*
> + * Virtio driver bits
> + *
> + * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> + * your option) any later version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#ifndef VIRTIO_H
> +#define VIRTIO_H
> +
> +#include "s390-ccw.h"
> +
> +/* Status byte for guest to report progress, and synchronize features. */
> +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
> +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
> +/* We have found a driver for the device. */
> +#define VIRTIO_CONFIG_S_DRIVER 2
> +/* Driver has used its parts of the config, and is happy */
> +#define VIRTIO_CONFIG_S_DRIVER_OK 4
> +/* We've given up on this device. */
> +#define VIRTIO_CONFIG_S_FAILED 0x80
> +
> +enum virtio_dev_type {
> + VIRTIO_ID_NET = 1,
> + VIRTIO_ID_BLOCK = 2,
> + VIRTIO_ID_CONSOLE = 3,
> + VIRTIO_ID_BALLOON = 5,
> +};
> +
> +struct virtio_dev_header {
> + enum virtio_dev_type type : 8;
> + u8 num_vq;
> + u8 feature_len;
> + u8 config_len;
> + u8 status;
> + u8 vqconfig[];
> +} __attribute__((packed));
> +
> +struct virtio_vqconfig {
> + u64 token;
> + u64 address;
> + u16 num;
> + u8 pad[6];
> +} __attribute__((packed));
> +
> +struct vq_info_block {
> + u64 queue;
> + u32 align;
> + u16 index;
> + u16 num;
> +} __attribute__((packed));
> +
> +struct virtio_dev {
> + struct virtio_dev_header *header;
> + struct virtio_vqconfig *vqconfig;
> + char *host_features;
> + char *guest_features;
> + char *config;
> +};
> +
> +#define KVM_S390_VIRTIO_RING_ALIGN 4096
> +
> +#define VRING_USED_F_NO_NOTIFY 1
> +
> +/* This marks a buffer as continuing via the next field. */
> +#define VRING_DESC_F_NEXT 1
> +/* This marks a buffer as write-only (otherwise read-only). */
> +#define VRING_DESC_F_WRITE 2
> +/* This means the buffer contains a list of buffer descriptors. */
> +#define VRING_DESC_F_INDIRECT 4
> +
> +/* Internal flag to mark follow-up segments as such */
> +#define VRING_HIDDEN_IS_CHAIN 256
> +
> +/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
> +struct vring_desc {
> + /* Address (guest-physical). */
> + u64 addr;
> + /* Length. */
> + u32 len;
> + /* The flags as indicated above. */
> + u16 flags;
> + /* We chain unused descriptors via this, too */
> + u16 next;
> +} __attribute__((packed));
> +
> +struct vring_avail {
> + u16 flags;
> + u16 idx;
> + u16 ring[];
> +} __attribute__((packed));
> +
> +/* u32 is used here for ids for padding reasons. */
> +struct vring_used_elem {
> + /* Index of start of used descriptor chain. */
> + u32 id;
> + /* Total length of the descriptor chain which was used (written to) */
> + u32 len;
> +} __attribute__((packed));
> +
> +struct vring_used {
> + u16 flags;
> + u16 idx;
> + struct vring_used_elem ring[];
> +} __attribute__((packed));
> +
> +struct vring {
> + unsigned int num;
> + int next_idx;
> + struct vring_desc *desc;
> + struct vring_avail *avail;
> + struct vring_used *used;
> + struct subchannel_id schid;
> +};
> +
> +
> +/***********************************************
> + * Virtio block *
> + ***********************************************/
> +
> +/*
> + * Command types
> + *
> + * Usage is a bit tricky as some bits are used as flags and some are not.
> + *
> + * Rules:
> + * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
> + * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own
> + * and may not be combined with any of the other flags.
> + */
> +
> +/* These two define direction. */
> +#define VIRTIO_BLK_T_IN 0
> +#define VIRTIO_BLK_T_OUT 1
> +
> +/* This bit says it's a scsi command, not an actual read or write. */
> +#define VIRTIO_BLK_T_SCSI_CMD 2
> +
> +/* Cache flush command */
> +#define VIRTIO_BLK_T_FLUSH 4
> +
> +/* Barrier before this op. */
> +#define VIRTIO_BLK_T_BARRIER 0x80000000
> +
> +/* This is the first element of the read scatter-gather list. */
> +struct virtio_blk_outhdr {
> + /* VIRTIO_BLK_T* */
> + u32 type;
> + /* io priority. */
> + u32 ioprio;
> + /* Sector (ie. 512 byte offset) */
> + u64 sector;
> +};
> +
> +#endif /* VIRTIO_H */
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 08/12] S390: ccw firmware: Add glue header
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (6 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 07/12] S390: ccw firmware: Add virtio device drivers Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 09/12] S390: ccw firmware: Add bootmap interpreter Alexander Graf
` (5 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
Like all great programs, we have to call between different functions in
different object files. And all of them need a common ground of defines.
Provide a file that provides these defines.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
pc-bios/s390-ccw/s390-ccw.h | 131 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 131 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw/s390-ccw.h
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
new file mode 100644
index 0000000..a03dbaf
--- /dev/null
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -0,0 +1,131 @@
+/*
+ * S390 CCW boot loader
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef S390_CCW_H
+#define S390_CCW_H
+
+/* #define DEBUG */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+typedef unsigned long ulong;
+typedef long size_t;
+typedef int bool;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+typedef unsigned long long __u64;
+
+#define true 1
+#define false 0
+#define PAGE_SIZE 4096
+
+#ifndef EIO
+#define EIO 1
+#endif
+#ifndef EBUSY
+#define EBUSY 2
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include "cio.h"
+
+/* main.c */
+void virtio_panic(const char *string);
+
+/* sclp-ascii.c */
+void sclp_print(const char *string);
+void sclp_setup(void);
+
+/* virtio.c */
+unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
+ ulong subchan_id, void *load_addr);
+bool virtio_is_blk(struct subchannel_id schid);
+void virtio_setup_block(struct subchannel_id schid);
+int virtio_read(ulong sector, void *load_addr);
+
+/* bootmap.c */
+int zipl_load(void);
+
+static inline void *memset(void *s, int c, size_t n)
+{
+ int i;
+ unsigned char *p = s;
+
+ for (i = 0; i < n; i++) {
+ p[i] = c;
+ }
+
+ return s;
+}
+
+static inline void fill_hex(char *out, unsigned char val)
+{
+ const char hex[] = "0123456789abcdef";
+
+ out[0] = hex[(val >> 4) & 0xf];
+ out[1] = hex[val & 0xf];
+}
+
+static inline void print_int(const char *desc, u64 addr)
+{
+ unsigned char *addr_c = (unsigned char*)&addr;
+ char out[] = ": 0xffffffffffffffff\n";
+ unsigned int i;
+
+ for (i = 0; i < sizeof(addr); i++) {
+ fill_hex(&out[4 + (i*2)], addr_c[i]);
+ }
+
+ sclp_print(desc);
+ sclp_print(out);
+}
+
+static inline void debug_print_int(const char *desc, u64 addr)
+{
+#ifdef DEBUG
+ print_int(desc, addr);
+#endif
+}
+
+static inline void debug_print_addr(const char *desc, void *p)
+{
+#ifdef DEBUG
+ debug_print_int(desc, (unsigned int)(unsigned long)p);
+#endif
+}
+
+/***********************************************
+ * Hypercall functions *
+ ***********************************************/
+
+#define KVM_S390_VIRTIO_NOTIFY 0
+#define KVM_S390_VIRTIO_RESET 1
+#define KVM_S390_VIRTIO_SET_STATUS 2
+#define KVM_S390_VIRTIO_CCW_NOTIFY 3
+
+static inline void yield(void)
+{
+ asm volatile ("diag 0,0,0x44"
+ : :
+ : "memory", "cc");
+}
+
+#define SECTOR_SIZE 512
+
+#endif /* S390_CCW_H */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 09/12] S390: ccw firmware: Add bootmap interpreter
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (7 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 08/12] S390: ccw firmware: Add glue header Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 10/12] S390: ccw firmware: Add Makefile Alexander Graf
` (4 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
On s390, there is an architected boot map format that we can read to
boot a certain entry off the disk. Implement a simple reader for this
that always boots the first (default) entry.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
pc-bios/s390-ccw/bootmap.c | 235 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 235 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw/bootmap.c
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
new file mode 100644
index 0000000..53a460d
--- /dev/null
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -0,0 +1,235 @@
+/*
+ * QEMU S390 bootmap interpreter
+ *
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+
+// #define DEBUG_FALLBACK
+
+#ifdef DEBUG_FALLBACK
+#define dputs(txt) \
+ do { sclp_print("zipl: " txt); } while (0)
+#else
+#define dputs(fmt, ...) \
+ do { } while (0)
+#endif
+
+struct scsi_blockptr {
+ uint64_t blockno;
+ uint16_t size;
+ uint16_t blockct;
+ uint8_t reserved[4];
+} __attribute__ ((packed));
+
+struct component_entry {
+ struct scsi_blockptr data;
+ uint8_t pad[7];
+ uint8_t component_type;
+ uint64_t load_address;
+} __attribute((packed));
+
+struct component_header {
+ uint8_t magic[4];
+ uint8_t type;
+ uint8_t reserved[27];
+} __attribute((packed));
+
+struct mbr {
+ uint8_t magic[4];
+ uint32_t version_id;
+ uint8_t reserved[8];
+ struct scsi_blockptr blockptr;
+} __attribute__ ((packed));
+
+#define ZIPL_MAGIC "zIPL"
+
+#define ZIPL_COMP_HEADER_IPL 0x00
+#define ZIPL_COMP_HEADER_DUMP 0x01
+
+#define ZIPL_COMP_ENTRY_LOAD 0x02
+#define ZIPL_COMP_ENTRY_EXEC 0x01
+
+/* Scratch space */
+static uint8_t sec[SECTOR_SIZE] __attribute__((__aligned__(SECTOR_SIZE)));
+
+/* Check for ZIPL magic. Returns 0 if not matched. */
+static int zipl_magic(uint8_t *ptr)
+{
+ uint32_t *p = (void*)ptr;
+ uint32_t *z = (void*)ZIPL_MAGIC;
+
+ if (*p != *z) {
+ debug_print_int("invalid magic", *p);
+ virtio_panic("invalid magic");
+ }
+
+ return 1;
+}
+
+static int zipl_load_segment(struct component_entry *entry)
+{
+ const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr));
+ struct scsi_blockptr *bprs = (void*)sec;
+ uint64_t blockno;
+ long address;
+ int i;
+
+ blockno = entry->data.blockno;
+ address = entry->load_address;
+
+ debug_print_int("loading segment at block", blockno);
+ debug_print_int("addr", address);
+
+ do {
+ if (virtio_read(blockno, (uint8_t *)bprs)) {
+ debug_print_int("failed reading bprs at", blockno);
+ goto fail;
+ }
+
+ for (i = 0;; i++) {
+ u64 *cur_desc = (void*)&bprs[i];
+
+ blockno = bprs[i].blockno;
+ if (!blockno)
+ break;
+
+ /* we need the updated blockno for the next indirect entry in the
+ chain, but don't want to advance address */
+ if (i == (max_entries - 1))
+ break;
+
+ address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
+ (void*)address);
+ if (address == -1)
+ goto fail;
+ }
+ } while (blockno);
+
+ return 0;
+
+fail:
+ sclp_print("failed loading segment\n");
+ return -1;
+}
+
+/* Run a zipl program */
+static int zipl_run(struct scsi_blockptr *pte)
+{
+ struct component_header *header;
+ struct component_entry *entry;
+ void (*ipl)(void);
+ uint8_t tmp_sec[SECTOR_SIZE];
+
+ virtio_read(pte->blockno, tmp_sec);
+ header = (struct component_header *)tmp_sec;
+
+ if (!zipl_magic(tmp_sec)) {
+ goto fail;
+ }
+
+ if (header->type != ZIPL_COMP_HEADER_IPL) {
+ goto fail;
+ }
+
+ dputs("start loading images\n");
+
+ /* Load image(s) into RAM */
+ entry = (struct component_entry *)(&header[1]);
+ while (entry->component_type == ZIPL_COMP_ENTRY_LOAD) {
+ if (zipl_load_segment(entry) < 0) {
+ goto fail;
+ }
+
+ entry++;
+
+ if ((uint8_t*)(&entry[1]) > (tmp_sec + SECTOR_SIZE)) {
+ goto fail;
+ }
+ }
+
+ if (entry->component_type != ZIPL_COMP_ENTRY_EXEC) {
+ goto fail;
+ }
+
+ /* Ensure the guest output starts fresh */
+ sclp_print("\n");
+
+ /* And run the OS! */
+ ipl = (void*)(entry->load_address & 0x7fffffff);
+ debug_print_addr("set IPL addr to", ipl);
+ /* should not return */
+ ipl();
+
+ return 0;
+
+fail:
+ sclp_print("failed running zipl\n");
+ return -1;
+}
+
+int zipl_load(void)
+{
+ struct mbr *mbr = (void*)sec;
+ uint8_t *ns, *ns_end;
+ int program_table_entries = 0;
+ int pte_len = sizeof(struct scsi_blockptr);
+ struct scsi_blockptr *prog_table_entry;
+ const char *error = "";
+
+ /* Grab the MBR */
+ virtio_read(0, (void*)mbr);
+
+ dputs("checking magic\n");
+
+ if (!zipl_magic(mbr->magic)) {
+ error = "zipl_magic 1";
+ goto fail;
+ }
+
+ debug_print_int("program table", mbr->blockptr.blockno);
+
+ /* Parse the program table */
+ if (virtio_read(mbr->blockptr.blockno, sec)) {
+ error = "virtio_read";
+ goto fail;
+ }
+
+ if (!zipl_magic(sec)) {
+ error = "zipl_magic 2";
+ goto fail;
+ }
+
+ ns_end = sec + SECTOR_SIZE;
+ for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns++) {
+ prog_table_entry = (struct scsi_blockptr *)ns;
+ if (!prog_table_entry->blockno) {
+ break;
+ }
+
+ program_table_entries++;
+ }
+
+ debug_print_int("program table entries", program_table_entries);
+
+ if (!program_table_entries) {
+ goto fail;
+ }
+
+ /* Run the default entry */
+
+ prog_table_entry = (struct scsi_blockptr *)(sec + pte_len);
+
+ return zipl_run(prog_table_entry);
+
+fail:
+ sclp_print("failed loading zipl: ");
+ sclp_print(error);
+ sclp_print("\n");
+ return -1;
+}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 10/12] S390: ccw firmware: Add Makefile
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (8 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 09/12] S390: ccw firmware: Add bootmap interpreter Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-23 10:31 ` Christian Borntraeger
2013-04-22 19:18 ` [Qemu-devel] [PATCH 11/12] S390: ccw firmware: Add compiled blob Alexander Graf
` (3 subsequent siblings)
13 siblings, 1 reply; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
This patch adds a makefile, so we can build our ccw firmware. Also
add the resulting binaries to .gitignore, so that nobody is annoyed
they might be in the tree.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
.gitignore | 2 ++
pc-bios/s390-ccw/Makefile | 26 ++++++++++++++++++++++++++
2 files changed, 28 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw/Makefile
diff --git a/.gitignore b/.gitignore
index 27ad002..c08e2cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,6 +95,8 @@ pc-bios/optionrom/kvmvapic.asm
pc-bios/optionrom/kvmvapic.bin
pc-bios/optionrom/kvmvapic.raw
pc-bios/optionrom/kvmvapic.img
+pc-bios/s390-ccw/s390-ccw.elf
+pc-bios/s390-ccw/s390-ccw.img
.stgit-*
cscope.*
tags
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
new file mode 100644
index 0000000..c126194
--- /dev/null
+++ b/pc-bios/s390-ccw/Makefile
@@ -0,0 +1,26 @@
+all: build-all
+# Dummy command so that make thinks it has done something
+ @true
+
+include ../../config-host.mak
+include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
+
+.PHONY : all clean build-all
+
+OBJECTS=main.o bootmap.o sclp-ascii.o virtio.o start.o
+CFLAGS += -fno-stack-protector
+# XXX find a more clever to locate the bootloader
+LDFLAGS += -Wl,-Ttext,0x7e00000,-Tbss,0x7f00000 -nostdlib
+
+build-all: s390-ccw.img
+
+s390-ccw.elf: $(OBJECTS)
+ $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS)," Building $(TARGET_DIR)$@")
+
+s390-ccw.img: s390-ccw.elf
+ $(call quiet-command,strip $@," Stripping $(TARGET_DIR)$@")
+
+clean:
+ rm -f *.o *.d *.img *~
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 11/12] S390: ccw firmware: Add compiled blob
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (9 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 10/12] S390: ccw firmware: Add Makefile Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-22 19:18 ` [Qemu-devel] [PATCH 12/12] S390: CCW: Use new, working firmware by default Alexander Graf
` (2 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
Now that we have all the source code ready, add a compiled blob into
the QEMU source tree, so that people without access to an s390 compiler
can run the s390-ccw firmware.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Makefile | 1 +
pc-bios/s390-ccw.img | Bin 0 -> 9432 bytes
2 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/s390-ccw.img
diff --git a/Makefile b/Makefile
index 12c7662..abb069f 100644
--- a/Makefile
+++ b/Makefile
@@ -273,6 +273,7 @@ qemu-icon.bmp \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
multiboot.bin linuxboot.bin kvmvapic.bin \
s390-zipl.rom \
+s390-ccw.img \
spapr-rtas.bin slof.bin \
palcode-clipper
else
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
new file mode 100644
index 0000000000000000000000000000000000000000..b549a86e55194bbf54e25f839e52b490ac308260
GIT binary patch
literal 9432
zcmeHNZ){W76+h25c_s<r5hCiA2yP;41r}UG!d56%pD6@rvts&Zm~|TsaUfPhLLGxp
zyJ^viw9r4pMQ!(GAFOuhO=~66jIN|Z>f406zuF>AsFk{@-d@ovnXb=mw5D|A?sx9<
zb4~Z9Q@{F3*XQ1I&pG$p-#z!-_iTS}TVHP=pi#91Xc^jyp%=r23g7f-XG&3%Zl(q@
zsgV|<&$0`=aYGTk==FR`)NFbjpDH=lYw-9&5#9BAKJ|M1S%`b>s$R(JcjTFllXeXS
zE9#B=ROzwK|EWizbna5}Q@!iYvR%En@EQtMj`=7)Wxd_#>x%pNKf<41v@TgkppHNt
zfjR<p1nLOX5vU_jN1%>C9f3Lmbp$>?0;Tue!xVK~`G9=LzJ!<gSFKsRw(6ymuBrG0
zeu2Wf{-s7wSm%hI)e2f7?-uNF@c(i8Po$ZXg+R(E(A0)JO?8qnVNkoZf`Zm@YD|f7
zV%^~Lt({hmTC7(|vtF0)+5)fRUCQb>&uJU5_REwoJn1z&LetRMN+C7Q@<Am(WX;Ms
z-$#1}{5u`@DpueK7E0J|VLC*c)vRonLi)v^TQCUzgw?zO`;wIM_%mdO;M1N&-WFJm
zE+4^Kb$QG&^4C!wD+pk8uOsp>;Y{Wu6td$OA7aaazo_+eU({!4oGtHxWnF&5`W+Gc
zZF9OXVQ4x)ofz9`{ecYY𝔷mqjJlo9Ghc#6=h~A-do5+}a5o7^_>Yo1_GP%F4;V
zvB$wl=2J<vf1%o!tW{Dv=7&5>8+DdWeo(|hXW_L5t@o7VBT8}x>uIO!7X95?#lFdZ
zCh~caFg_?u3wjE&kAZg)c)sSQD9U&SEiWRh)$j)^o`2t-#OGzU7T9Ckkofk+;3U~q
zM1y-7(fPN4wm$!+(z)me1HLJpTNPHmPL6i7oV?%|GZE^rE>M@!y8tYq0=%M5d<Mu^
ztF<Cp1eqvpwQi&)#%_KRp3cGYEcTEb<2F}@tXoI})=Pk|YuzY6!ip{{KNl(-VhV>o
zAgUscwlg=N)<X%$EW=N0wUnM+eO8USYDHOCdO=xgK<h0aqQU-e&^~V`fkP)e4>#-s
zvhAjT@2e;T+6ZbUg%Lq*Mr}hiQX)xHf;w<Q;uCRd*XMQJnQ@0Im}}3F;I-cZFIy9a
zp+(j$U;hljW=>wQP0Z3|ZK4*;8g7W0ag(e~at<^MdgT<Ef!6L*H<*oRH389P>w2Qw
zH9=dnBw5Sh^;hJTlrh5|w7~;0A*fx=9@6L8`hu%g1gA4h4W?n@%RMv9HmeqArQ^ki
z<IbOx4_RR;d4|YT#CD7_az&)|jiz!>xhEmYG}R+G57-kn^1yFl%Py~&TCaF&UdZg&
z5-*$98abCV%UhG8y!qMj@<uaR-h#27Q{&}LQ{76QCWzYK*yk49LPEHO$nvQTim!4^
zEARIl_V1iJ1ETa=xxi-tv3#Cm+1jlU(EK%O5cMohbHp*QO(Dlb04(G9cH%~Wo|^sv
zMW>fh=Z?7DQ0l~Ynv2Z!M#vF%2q!siBNo98(W1z<)7$5z6NuwGM#rcbUBaWum*U}y
zj`69Exy5Ks#ce*NOG`=)`=~)XOyMN>)^23bxX}XdnxGBub{HaH-2g5q<dAoE*mi?y
z8v(U0>{#iHo8<gFU&LNSkSIg+Jn98&FLrt-8ICB2DVm6vDQT1m@f`lz637jluxTMU
zIF&d%hoP|vUiGPQ&DyIWzk;9Ue&5H?UI|;w_wr?GYC+lHSm`S{!h}~TG6nDietQj*
zGwIeu(k&#(Eg&|64&ogcZzOs&x_}-f+Ugjrg}lHT0vg9<2|PaO$V^Faa8AO!9@qyL
z>u*j8Q+WFyX`R}D6I8ihs(YVji{+J+FP$kL=G|u>a6T`x?<z+OBOVl9oZGbB$Zb1-
z+D7W;d<(=V@*GZhxNlsY_>;&=o<~~3bS=m&g^Zz2cZ9~1hE1neG?;4tqLDR_#_f<S
z*gyh%hp1p}wQEsN&b1JU5d%Bnp5e8bhWm5SanP65j9)($a$mt*uSC{hwspLRihl<p
zdle$@4E7T1D!uLJ3i=2;kNXbN?_hW64XMtDi94CIa7<;}))dam=`WGoBW4IEP2$9_
zEWP~!Z1H`e&okz=eGjA3Qi@Y^CI7DoaAZxPo<?SBs>zgRTvz$Dlms;+UWi_b{L1>h
z=lRtioqioL*+yTkMi~3`Q>%j{qGT~gp=S%@Yo;UAg}IeIW$8&?#V0Rg58tz03g0<t
z&3-bitMAf#`!mCXX^|Th!=wFavFjdjAUk?U4E1NzBApp~u#xT>6-P7KTxN9b{^18j
zdhlpwU{D+wJu;H+Xe4@gXR?ndGjg<lIFlBK`VVFX=zwRF4Q56Tim}0ihXzM-jXpnn
zWMqW-4`&V!!-8jgUv{uR?MwKYEU}59xVGqSKrwWeI%-GI7j&%h+sRS?Hx&FRg3#xJ
zL`-z^dZiqroj2_g+p^iwENRPww_x}%>LMxsjrGtIplQ&vQhvnB??^e9Laet*`SAqk
zX3#%^-YeymW1u<U8wLHbl>Z5Vo|p0}qCvY1+Jl=h1Ud)WgI$B2z&ByD4Hbz|JJ!;?
zxS(;zE3iZD+|-Ns@XE5@lM8;>(A#2rD_6`ed~W5IUZe<9l;@P(lll|k#}_`<c%o^d
zxwoYd^u|~|$4$LR=b2*myZ%SMuf=Zg2HB6Fa8oY^nwdgAULy}l<qfX`Sg>4hGgFi;
zsJw=ExC8z;Q<N8bpRE3b1N&NtnR+qAzH#|kjs4!1ca`U`qp5Moz3GWjv6olqbugy&
zaZ@iYIOnmnXpNo68i88{10III+IP627aRV{6a{feZ0Bk2fd4L2lnd9`>1%nj27mVd
z0t@Ly{Y9oI4^-rVjanM>*zRR+=*4g|Q<SGaW4Cr+J&F2f9f3Lmbp+}Nd{G2A5%V1t
z+<w=6v^aD8yJt?^c=sLOzuexqvNJsYLg$t3x8J@=th(pEd$x(b%*c^rt3^+&JJuua
zKR7V3wr5}W+Wp!7k%1wR#k0>?W^_cX+pvD)SG&JOyT%Uh*-jK28yd@HbN%}%mK!{l
zquBnjF^Y|h<_2R2M~=kyAIS`-*Jjcb%Z{e|bNv(>9NKpv+ka?q-%vXHX^&z9qlfrO
zsoIFKPqAIed&j;g2CUzN>OW?vD_$>xqY9pjR0;d{Sfx+ZOAL%9sQfI%MO~+O-l`N)
zp@q25@u+WC_4t1<{^hT((ecXvOz?F?zM>bcP@mM!k9W(e|4JYC>7*wZsZj5E!dC|M
z{bklVRDb;yeeZuKMBe{UFrH(<no>LeZQy@KzY))PTyCh)fd3rkv9FyU??zSqxG&(*
zj<c0M-tDd_{(MaDM)muj)qk&|Re5x)+VJI>a;<p`s>-0z@nNMmSj$D**Qfsi-qmcN
literal 0
HcmV?d00001
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 12/12] S390: CCW: Use new, working firmware by default
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (10 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 11/12] S390: ccw firmware: Add compiled blob Alexander Graf
@ 2013-04-22 19:18 ` Alexander Graf
2013-04-23 9:20 ` [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Christian Borntraeger
2013-04-23 11:23 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Christian Borntraeger
13 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-22 19:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Dominik Dingel
Since we now have working firmware for s390-ccw in the tree, we can
default to it on our s390-ccw machine, rendering it more useful.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/s390x/s390-virtio-ccw.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 89670f2..0e8a0b5 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -80,7 +80,7 @@ static void ccw_init(QEMUMachineInitArgs *args)
css_bus = virtual_css_bus_init();
s390_sclp_init();
s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
- args->initrd_filename, "s390-zipl.rom");
+ args->initrd_filename, "s390-ccw.img");
/* register hypercalls */
virtio_ccw_register_hcalls();
--
1.6.0.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (11 preceding siblings ...)
2013-04-22 19:18 ` [Qemu-devel] [PATCH 12/12] S390: CCW: Use new, working firmware by default Alexander Graf
@ 2013-04-23 9:20 ` Christian Borntraeger
2013-04-23 11:38 ` Alexander Graf
2013-04-23 11:23 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Christian Borntraeger
13 siblings, 1 reply; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 9:20 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel, Dominik Dingel
On 22/04/13 21:18, Alexander Graf wrote:
> We used to be able to boot from the virtio-s390 machine using a
> modified version of zipl. However, for our new virtio-ccw machine,
> there was not such support available.
>
> This patch set adds a tiny but of firmware to the game, so that we
> get the same functionality back that we used to have on virtio-s390.
>
> It should live in the QEMU tree, so that we can easily extend it
> to support more fancy features, like asking the user to choose which
> entry to boot, or boot menus.
>
> Alex
Thanks.
In general this seems to work for scsi disks or image files that contain
a scsi bootmap. There are several things that we should fix or extend, though:
- disabled wait
- make cio better
- pass a device id
- loadparm
- dasd bootmap (which is not architectured, but pretty similar to the scsi one)
Can you provide a qemu tree so that we can help to fix/extend this?
I think this should go into 1.5, lets see how much we can improve this before the
hard freeze
Christian
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware
2013-04-23 9:20 ` [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Christian Borntraeger
@ 2013-04-23 11:38 ` Alexander Graf
0 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-23 11:38 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: qemu-devel, Dominik Dingel
On 04/23/2013 11:20 AM, Christian Borntraeger wrote:
> On 22/04/13 21:18, Alexander Graf wrote:
>> We used to be able to boot from the virtio-s390 machine using a
>> modified version of zipl. However, for our new virtio-ccw machine,
>> there was not such support available.
>>
>> This patch set adds a tiny but of firmware to the game, so that we
>> get the same functionality back that we used to have on virtio-s390.
>>
>> It should live in the QEMU tree, so that we can easily extend it
>> to support more fancy features, like asking the user to choose which
>> entry to boot, or boot menus.
>>
>> Alex
> Thanks.
> In general this seems to work for scsi disks or image files that contain
> a scsi bootmap. There are several things that we should fix or extend, though:
> - disabled wait
> - make cio better
> - pass a device id
> - loadparm
> - dasd bootmap (which is not architectured, but pretty similar to the scsi one)
>
> Can you provide a qemu tree so that we can help to fix/extend this?
> I think this should go into 1.5, lets see how much we can improve this before the
> hard freeze
I agree :). This patch set is mostly to get us started on something. But
we should have something in for 1.5, yes.
My WIP tree is at:
git://repo.or.cz/qemu/agraf.git s390-ccw-loader
<http://repo.or.cz/w/qemu/agraf.git/shortlog/refs/heads/s390-ccw-loader>
Alex
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img
2013-04-22 19:18 [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Alexander Graf
` (12 preceding siblings ...)
2013-04-23 9:20 ` [Qemu-devel] [PATCH 00/12] S390: Add virtio-ccw firmware Christian Borntraeger
@ 2013-04-23 11:23 ` Christian Borntraeger
2013-04-23 11:23 ` [Qemu-devel] [PATCH 1/4] s390-ccw.img: replace while loop with a disabled wait on s390 bios Christian Borntraeger
` (4 more replies)
13 siblings, 5 replies; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 11:23 UTC (permalink / raw)
To: Alexander Graf
Cc: cornelia.huck, Christian Borntraeger, qemu-devel, Dominik Dingel
Alex,
here are the quick things that I needed to make the s390-ccw.img working.
Please have a look and feel free to apply.
Christian Borntraeger (4):
s390-ccw.img: replace while loop with a disabled wait on s390 bios
s390-ccw.img: build s390-ccw rom on s3900 system by default
s390-ccw.img: Fix compile warning in s390 ccw virtio code
s390-ccw.img: Take care of the elf->img transition
configure | 7 ++++++-
pc-bios/s390-ccw/Makefile | 4 ++--
pc-bios/s390-ccw/main.c | 2 ++
pc-bios/s390-ccw/s390-ccw.h | 3 +++
pc-bios/s390-ccw/start.S | 15 +++++++++++++++
pc-bios/s390-ccw/virtio.c | 4 +++-
6 files changed, 31 insertions(+), 4 deletions(-)
--
1.8.1.4
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 1/4] s390-ccw.img: replace while loop with a disabled wait on s390 bios
2013-04-23 11:23 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Christian Borntraeger
@ 2013-04-23 11:23 ` Christian Borntraeger
2013-04-23 11:23 ` [Qemu-devel] [PATCH 2/4] s390-ccw.img: build s390-ccw rom on s3900 system by default Christian Borntraeger
` (3 subsequent siblings)
4 siblings, 0 replies; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 11:23 UTC (permalink / raw)
To: Alexander Graf
Cc: cornelia.huck, Christian Borntraeger, qemu-devel, Dominik Dingel
dont waste cpu power on an error condition. Lets stop the guest
with a disabled wait.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
pc-bios/s390-ccw/main.c | 2 ++
pc-bios/s390-ccw/s390-ccw.h | 3 +++
pc-bios/s390-ccw/start.S | 15 +++++++++++++++
3 files changed, 20 insertions(+)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 0913aac..67f4987 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -16,6 +16,7 @@ char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
void virtio_panic(const char *string)
{
sclp_print(string);
+ disabled_wait();
while (1) { }
}
@@ -52,5 +53,6 @@ int main(void)
virtio_setup();
if (zipl_load() < 0)
sclp_print("Failed to load OS from hard disk\n");
+ disabled_wait();
while (1) { }
}
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index a03dbaf..8241b0a 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -45,6 +45,9 @@ typedef unsigned long long __u64;
#include "cio.h"
+/* start.s */
+void disabled_wait(void);
+
/* main.c */
void virtio_panic(const char *string);
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
index c2b9a19..09deee7 100644
--- a/pc-bios/s390-ccw/start.S
+++ b/pc-bios/s390-ccw/start.S
@@ -3,6 +3,7 @@
* into the pc-bios directory of qemu.
*
* Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ * Copyright 2013 IBM Corp.
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at
* your option) any later version. See the COPYING file in the top-level
@@ -14,3 +15,17 @@ _start:
larl %r15, stack + 0x8000 /* Set up stack */
j main /* And call C */
+
+/*
+ * void disabled_wait(void)
+ *
+ * stops the current guest cpu.
+ */
+ .globl disabled_wait
+disabled_wait:
+ larl %r1,disabled_wait_psw
+ lpswe 0(%r1)
+
+ .align 8
+disabled_wait_psw:
+ .quad 0x0002000180000000,0x0000000000000000
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 2/4] s390-ccw.img: build s390-ccw rom on s3900 system by default
2013-04-23 11:23 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Christian Borntraeger
2013-04-23 11:23 ` [Qemu-devel] [PATCH 1/4] s390-ccw.img: replace while loop with a disabled wait on s390 bios Christian Borntraeger
@ 2013-04-23 11:23 ` Christian Borntraeger
2013-04-23 11:23 ` [Qemu-devel] [PATCH 3/4] s390-ccw.img: Fix compile warning in s390 ccw virtio code Christian Borntraeger
` (2 subsequent siblings)
4 siblings, 0 replies; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 11:23 UTC (permalink / raw)
To: Alexander Graf
Cc: cornelia.huck, Christian Borntraeger, qemu-devel, Dominik Dingel
Lets build the s390-ccw rom if on s390. Also fix the separate build
folder case.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
configure | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index a382ff2..cb29b69 100755
--- a/configure
+++ b/configure
@@ -3320,6 +3320,10 @@ if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
roms="$roms spapr-rtas"
fi
+if test "$cpu" = "s390x" ; then
+ roms="$roms s390-ccw"
+fi
+
# add pixman flags after all config tests are done
QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags"
libs_softmmu="$libs_softmmu $pixman_libs"
@@ -4369,7 +4373,7 @@ fi
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32"
-DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
+DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS qapi-generated"
FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
@@ -4377,6 +4381,7 @@ FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
FILES="$FILES tests/tcg/lm32/Makefile po/Makefile"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES pc-bios/spapr-rtas/Makefile"
+FILES="$FILES pc-bios/s390-ccw/Makefile"
FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
FILES="$FILES pc-bios/qemu-icon.bmp"
for bios_file in \
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 3/4] s390-ccw.img: Fix compile warning in s390 ccw virtio code
2013-04-23 11:23 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Christian Borntraeger
2013-04-23 11:23 ` [Qemu-devel] [PATCH 1/4] s390-ccw.img: replace while loop with a disabled wait on s390 bios Christian Borntraeger
2013-04-23 11:23 ` [Qemu-devel] [PATCH 2/4] s390-ccw.img: build s390-ccw rom on s3900 system by default Christian Borntraeger
@ 2013-04-23 11:23 ` Christian Borntraeger
2013-04-23 11:31 ` Alexander Graf
2013-04-23 11:23 ` [Qemu-devel] [PATCH 4/4] s390-ccw.img: Take care of the elf->img transition Christian Borntraeger
2013-04-23 11:33 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Alexander Graf
4 siblings, 1 reply; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 11:23 UTC (permalink / raw)
To: Alexander Graf
Cc: cornelia.huck, Christian Borntraeger, qemu-devel, Dominik Dingel
Lets fix this gcc warning:
virtio.c: In function ‘vring_send_buf’:
virtio.c:125:35: error: operation on ‘vr->next_idx’ may be undefined
[-Werror=sequence-point]
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
pc-bios/s390-ccw/virtio.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 79e2941..1968fc6 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -122,7 +122,9 @@ static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
vr->desc[vr->next_idx].addr = (ulong)p;
vr->desc[vr->next_idx].len = len;
vr->desc[vr->next_idx].flags = flags & ~VRING_HIDDEN_IS_CHAIN;
- vr->desc[vr->next_idx].next = ++vr->next_idx;
+ vr->desc[vr->next_idx].next = vr->next_idx;
+ vr->desc[vr->next_idx].next++;
+ vr->next_idx++;
/* Chains only have a single ID */
if (!(flags & VRING_DESC_F_NEXT)) {
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 3/4] s390-ccw.img: Fix compile warning in s390 ccw virtio code
2013-04-23 11:23 ` [Qemu-devel] [PATCH 3/4] s390-ccw.img: Fix compile warning in s390 ccw virtio code Christian Borntraeger
@ 2013-04-23 11:31 ` Alexander Graf
2013-04-23 11:45 ` Christian Borntraeger
0 siblings, 1 reply; 30+ messages in thread
From: Alexander Graf @ 2013-04-23 11:31 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: cornelia.huck, qemu-devel, Dominik Dingel
On 04/23/2013 01:23 PM, Christian Borntraeger wrote:
> Lets fix this gcc warning:
>
> virtio.c: In function ‘vring_send_buf’:
> virtio.c:125:35: error: operation on ‘vr->next_idx’ may be undefined
> [-Werror=sequence-point]
>
> Signed-off-by: Christian Borntraeger<borntraeger@de.ibm.com>
> ---
> pc-bios/s390-ccw/virtio.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
> index 79e2941..1968fc6 100644
> --- a/pc-bios/s390-ccw/virtio.c
> +++ b/pc-bios/s390-ccw/virtio.c
> @@ -122,7 +122,9 @@ static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
> vr->desc[vr->next_idx].addr = (ulong)p;
> vr->desc[vr->next_idx].len = len;
> vr->desc[vr->next_idx].flags = flags& ~VRING_HIDDEN_IS_CHAIN;
> - vr->desc[vr->next_idx].next = ++vr->next_idx;
> + vr->desc[vr->next_idx].next = vr->next_idx;
> + vr->desc[vr->next_idx].next++;
> + vr->next_idx++;
Hrm. This looks a lot more complicated than it needs to. Why is gcc
emitting a warning here? Maybe it only wants braces. Please try whether
.next = ++(vr->next_id);
works for you.
Alex
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 3/4] s390-ccw.img: Fix compile warning in s390 ccw virtio code
2013-04-23 11:31 ` Alexander Graf
@ 2013-04-23 11:45 ` Christian Borntraeger
2013-04-26 6:38 ` Alexander Graf
0 siblings, 1 reply; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 11:45 UTC (permalink / raw)
To: Alexander Graf; +Cc: cornelia.huck, qemu-devel, Dominik Dingel
On 23/04/13 13:31, Alexander Graf wrote:
> On 04/23/2013 01:23 PM, Christian Borntraeger wrote:
>> Lets fix this gcc warning:
>>
>> virtio.c: In function ‘vring_send_buf’:
>> virtio.c:125:35: error: operation on ‘vr->next_idx’ may be undefined
>> [-Werror=sequence-point]
>>
>> Signed-off-by: Christian Borntraeger<borntraeger@de.ibm.com>
>> ---
>> pc-bios/s390-ccw/virtio.c | 4 +++-
>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
>> index 79e2941..1968fc6 100644
>> --- a/pc-bios/s390-ccw/virtio.c
>> +++ b/pc-bios/s390-ccw/virtio.c
>> @@ -122,7 +122,9 @@ static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
>> vr->desc[vr->next_idx].addr = (ulong)p;
>> vr->desc[vr->next_idx].len = len;
>> vr->desc[vr->next_idx].flags = flags& ~VRING_HIDDEN_IS_CHAIN;
>> - vr->desc[vr->next_idx].next = ++vr->next_idx;
>> + vr->desc[vr->next_idx].next = vr->next_idx;
>> + vr->desc[vr->next_idx].next++;
>> + vr->next_idx++;
>
> Hrm. This looks a lot more complicated than it needs to. Why is gcc emitting a warning here? Maybe it only wants braces. Please try whether
>
> .next = ++(vr->next_id);
>
> works for you.
>
>
> Alex
>
>
I already did that, but I get the same error message. I dont understand why gcc emits that warning,
but it does :-(
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 3/4] s390-ccw.img: Fix compile warning in s390 ccw virtio code
2013-04-23 11:45 ` Christian Borntraeger
@ 2013-04-26 6:38 ` Alexander Graf
0 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-26 6:38 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: cornelia.huck, qemu-devel, Dominik Dingel
On 23.04.2013, at 13:45, Christian Borntraeger wrote:
> On 23/04/13 13:31, Alexander Graf wrote:
>> On 04/23/2013 01:23 PM, Christian Borntraeger wrote:
>>> Lets fix this gcc warning:
>>>
>>> virtio.c: In function ‘vring_send_buf’:
>>> virtio.c:125:35: error: operation on ‘vr->next_idx’ may be undefined
>>> [-Werror=sequence-point]
>>>
>>> Signed-off-by: Christian Borntraeger<borntraeger@de.ibm.com>
>>> ---
>>> pc-bios/s390-ccw/virtio.c | 4 +++-
>>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
>>> index 79e2941..1968fc6 100644
>>> --- a/pc-bios/s390-ccw/virtio.c
>>> +++ b/pc-bios/s390-ccw/virtio.c
>>> @@ -122,7 +122,9 @@ static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
>>> vr->desc[vr->next_idx].addr = (ulong)p;
>>> vr->desc[vr->next_idx].len = len;
>>> vr->desc[vr->next_idx].flags = flags& ~VRING_HIDDEN_IS_CHAIN;
>>> - vr->desc[vr->next_idx].next = ++vr->next_idx;
>>> + vr->desc[vr->next_idx].next = vr->next_idx;
>>> + vr->desc[vr->next_idx].next++;
>>> + vr->next_idx++;
>>
>> Hrm. This looks a lot more complicated than it needs to. Why is gcc emitting a warning here? Maybe it only wants braces. Please try whether
>>
>> .next = ++(vr->next_id);
>>
>> works for you.
>>
>>
>> Alex
>>
>>
>
> I already did that, but I get the same error message. I dont understand why gcc emits that warning,
> but it does :-(
*shrug* I'll just add it to the queue.
Alex
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [PATCH 4/4] s390-ccw.img: Take care of the elf->img transition
2013-04-23 11:23 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Christian Borntraeger
` (2 preceding siblings ...)
2013-04-23 11:23 ` [Qemu-devel] [PATCH 3/4] s390-ccw.img: Fix compile warning in s390 ccw virtio code Christian Borntraeger
@ 2013-04-23 11:23 ` Christian Borntraeger
2013-04-23 11:33 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Alexander Graf
4 siblings, 0 replies; 30+ messages in thread
From: Christian Borntraeger @ 2013-04-23 11:23 UTC (permalink / raw)
To: Alexander Graf
Cc: cornelia.huck, Christian Borntraeger, qemu-devel, Dominik Dingel
We have to call strip with s390-ccw.elf as input and
s390-ccw.img as output
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
pc-bios/s390-ccw/Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index c126194..ad55a14 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -20,7 +20,7 @@ s390-ccw.elf: $(OBJECTS)
$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS)," Building $(TARGET_DIR)$@")
s390-ccw.img: s390-ccw.elf
- $(call quiet-command,strip $@," Stripping $(TARGET_DIR)$@")
+ $(call quiet-command,strip $< -o $@," Stripping $(TARGET_DIR)$@")
clean:
- rm -f *.o *.d *.img *~
+ rm -f *.o *.d *.img *.elf *~
--
1.8.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img
2013-04-23 11:23 ` [Qemu-devel] [PATCH 0/4] updates for s390-ccw.img Christian Borntraeger
` (3 preceding siblings ...)
2013-04-23 11:23 ` [Qemu-devel] [PATCH 4/4] s390-ccw.img: Take care of the elf->img transition Christian Borntraeger
@ 2013-04-23 11:33 ` Alexander Graf
4 siblings, 0 replies; 30+ messages in thread
From: Alexander Graf @ 2013-04-23 11:33 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: cornelia.huck, qemu-devel, Dominik Dingel
On 04/23/2013 01:23 PM, Christian Borntraeger wrote:
> Alex,
>
> here are the quick things that I needed to make the s390-ccw.img working.
> Please have a look and feel free to apply.
Thanks, applied all except for 3/4 to my branch :)
Alex
>
> Christian Borntraeger (4):
> s390-ccw.img: replace while loop with a disabled wait on s390 bios
> s390-ccw.img: build s390-ccw rom on s3900 system by default
> s390-ccw.img: Fix compile warning in s390 ccw virtio code
> s390-ccw.img: Take care of the elf->img transition
>
> configure | 7 ++++++-
> pc-bios/s390-ccw/Makefile | 4 ++--
> pc-bios/s390-ccw/main.c | 2 ++
> pc-bios/s390-ccw/s390-ccw.h | 3 +++
> pc-bios/s390-ccw/start.S | 15 +++++++++++++++
> pc-bios/s390-ccw/virtio.c | 4 +++-
> 6 files changed, 31 insertions(+), 4 deletions(-)
>
^ permalink raw reply [flat|nested] 30+ messages in thread