2022-01-21 21:10:21

by Laurent Vivier

[permalink] [raw]
Subject: [PATCH v11 0/5] m68k: Add Virtual M68k Machine

The most powerful m68k machine emulated by QEMU is a Quadra 800,

but this machine is very limited: only 1 GiB of memory and only some

specific interfaces, with no DMA.



The Virtual M68k Machine is based on Goldfish interfaces defined by Google

for Android simulator. It uses Goldfish-rtc (timer and RTC),

Goldfish-pic (PIC) and Goldfish-tty (for early tty).



The machine is created with 128 virtio-mmio buses, and they can

be used to add serial console, GPU, disk, NIC, HID, hwrng, 9PFS...



The virtual m68k machine has been merged in QEMU and will be available

with the release 6.0.



This series introduces the support of this new machine in the linux kernel.



If you want to try:



- Configure and build latest QEMU with (or download qemu 6.0 binary):



.../configure --target-list=m68k-softmmu --enable-virglrenderer

make



- Configure and build linux with:



make virt_defconfig

make vmlinux



A pre-installed qcow2 disk image is available at:



http://vivier.eu/debian-10.0.qcow2



You can run the machine with something like:



qemu-system-m68k -M virt \

-m 3G \

-chardev stdio,signal=off,mux=on,id=char0 \

-mon chardev=char0,mode=readline \

-kernel vmlinux \

-append "console=hvc0 root=/dev/vda2" \

-blockdev node-name=system,driver=file,filename=debian-10.0.qcow2 \

-blockdev node-name=drive0,driver=qcow2,file=system \

-device virtio-blk-device,drive=drive0 \

-serial chardev:char0 \

-device virtio-net-device,netdev=hostnet0 \

-netdev bridge,id=hostnet0,br=virbr0,helper=/usr/libexec/qemu-bridge-helper \

-device virtio-serial-device \

-device virtio-gpu-device \

-device virtconsole,chardev=char0 \

-device virtio-keyboard-device \

-device virtio-mouse-device



You can watch a presentation about the machine on the Planet m68k channel:



https://youtu.be/s_ve0bCC9q4

[Demo at 38:00]



v11:

- rename goldfish_ioread32()/goldfish_iowrite32() to gf_ioread32()/gfiowrite32()

- move them to linux/goldfish.h and m68k/asm/io.h

- change patches order (tty first to revert my previous work)

- fix clocksource by clearing interrupt on tick not on next_event()

and clearing shift

- add missing clocksource_register_hz()

- rebase



v10:

- move goldfish_ioread32()/goldfish_iowrite32() to io.h

- also update goldfish-tty

- use READ_ONCE()/WRITE_ONCE() for in_nmi



v9:

- include <linux/memblock.h> to declare min_low_pfn

- goldfish accessors: s/CONFIG_CPU_BIG_ENDIAN/CONFIG_M68K/



v8:

- GF_PUT_CHAR is a 32bit register (in arch/m68k/kernel/head.S)

- rework goldfish-pic and virt_ctrl



v7:

- add "#include <linux/slab.h>" in timer-goldfish.c for kzalloc()

- update timer-goldfish Kconfig

- remove EXPORT_SYMBOL()

- introduce goldfish_ioread32()/goldfish_iowrite32()



v6:

- fix goldfish-rtc endianness

- move goldfish-timer code to drivers/clocksource

- remove LEGACY_TIMER_TICK and use directly goldfish-timer



v5:

- add GENERIC_CLOCKEVENTS in Kconfig.machine



v4:

- update PATCH 1: comments and parameter names

- add a patch to move to generic clockevents

(I prefer to have a separate patch as it can be used as an example to

move from legacy timer tick to generic clockevents)



v3:

- introduce config.h to export prototypes to arch/m68k/kernel/setup_mm.c

- define virt_nmi_handler as static



v2:

- Remove VIRTO_MENU set y

- sort the selects

- add CONFIG_LOCALVERSION="-virt"

- generate virt_defconfig using "make savedefconfig"

- rename MACH_VIRTONLY to MACH_VIRT_ONLY

- add a test_notvirt label in head.S

- rework iounmap() to use two separate #ifdefs

- use %u in virt_get_model()

- drop show_registers() in config.c

- drop pr_err() from config_virt()

- sort includes in ints.c

- call virt_irq_enable() in virt_irq_startup()

- drop virt_irq_shutdown() and use virt_irq_disable()

- move in_nmi into virt_nmi_handler()

- use pr_warn() in virt_nmi_handler()

- rework goldfish_pic_irq() IRQ scan

- copy goldfish-pic IRQs related information from QEMU hw/m68k/virt

- add a comment to "min_low_pfn = 0"

- use platform_device_register_simple()

- use goldfish_timer_read(), upper_32_bits() and lower_32_bits()



Thanks,

Laurent



Laurent Vivier (5):

m68k: add asm/config.h

tty: goldfish: introduce gf_ioread32()/gf_iowrite32()

rtc: goldfish: use gf_ioread32()/gf_iowrite32()

clocksource/drivers: Add a goldfish-timer clocksource

m68k: introduce a virtual m68k machine



arch/m68k/Kbuild | 1 +

arch/m68k/Kconfig.machine | 17 +++

arch/m68k/amiga/config.c | 1 +

arch/m68k/apollo/config.c | 1 +

arch/m68k/atari/config.c | 1 +

arch/m68k/bvme6000/config.c | 1 +

arch/m68k/configs/virt_defconfig | 65 +++++++++

arch/m68k/hp300/config.c | 1 +

arch/m68k/include/asm/config.h | 35 +++++

arch/m68k/include/asm/io.h | 3 +

arch/m68k/include/asm/irq.h | 3 +-

arch/m68k/include/asm/pgtable_mm.h | 7 +

arch/m68k/include/asm/setup.h | 44 ++++--

arch/m68k/include/asm/virt.h | 25 ++++

arch/m68k/include/uapi/asm/bootinfo-virt.h | 18 +++

arch/m68k/include/uapi/asm/bootinfo.h | 1 +

arch/m68k/kernel/Makefile | 1 +

arch/m68k/kernel/head.S | 31 ++++

arch/m68k/kernel/setup_mm.c | 30 +---

arch/m68k/mac/config.c | 1 +

arch/m68k/mm/kmap.c | 23 ++-

arch/m68k/mvme147/config.c | 1 +

arch/m68k/mvme16x/config.c | 1 +

arch/m68k/q40/config.c | 1 +

arch/m68k/virt/Makefile | 6 +

arch/m68k/virt/config.c | 119 +++++++++++++++

arch/m68k/virt/ints.c | 133 +++++++++++++++++

arch/m68k/virt/platform.c | 72 +++++++++

drivers/clocksource/Kconfig | 7 +

drivers/clocksource/Makefile | 1 +

drivers/clocksource/timer-goldfish.c | 162 +++++++++++++++++++++

drivers/rtc/rtc-goldfish.c | 30 ++--

drivers/tty/goldfish.c | 20 +--

include/clocksource/timer-goldfish.h | 11 ++

include/linux/goldfish.h | 15 +-

35 files changed, 820 insertions(+), 69 deletions(-)

create mode 100644 arch/m68k/configs/virt_defconfig

create mode 100644 arch/m68k/include/asm/config.h

create mode 100644 arch/m68k/include/asm/virt.h

create mode 100644 arch/m68k/include/uapi/asm/bootinfo-virt.h

create mode 100644 arch/m68k/virt/Makefile

create mode 100644 arch/m68k/virt/config.c

create mode 100644 arch/m68k/virt/ints.c

create mode 100644 arch/m68k/virt/platform.c

create mode 100644 drivers/clocksource/timer-goldfish.c

create mode 100644 include/clocksource/timer-goldfish.h



--

2.34.1




2022-01-21 21:10:27

by Laurent Vivier

[permalink] [raw]
Subject: [PATCH v11 2/5] tty: goldfish: introduce gf_ioread32()/gf_iowrite32()

Revert
commit da31de35cd2f ("tty: goldfish: use __raw_writel()/__raw_readl()")

to use accessors defined by the architecture.

Define by default the accessor to be little-endian as we
have only little-endian architectures using goldfish devices.

Signed-off-by: Laurent Vivier <[email protected]>
---
drivers/tty/goldfish.c | 20 ++++++++++----------
include/linux/goldfish.h | 15 +++++++++++----
2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index 5ed19a9857ad..10c13b93ed52 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -61,13 +61,13 @@ static void do_rw_io(struct goldfish_tty *qtty,
spin_lock_irqsave(&qtty->lock, irq_flags);
gf_write_ptr((void *)address, base + GOLDFISH_TTY_REG_DATA_PTR,
base + GOLDFISH_TTY_REG_DATA_PTR_HIGH);
- __raw_writel(count, base + GOLDFISH_TTY_REG_DATA_LEN);
+ gf_iowrite32(count, base + GOLDFISH_TTY_REG_DATA_LEN);

if (is_write)
- __raw_writel(GOLDFISH_TTY_CMD_WRITE_BUFFER,
+ gf_iowrite32(GOLDFISH_TTY_CMD_WRITE_BUFFER,
base + GOLDFISH_TTY_REG_CMD);
else
- __raw_writel(GOLDFISH_TTY_CMD_READ_BUFFER,
+ gf_iowrite32(GOLDFISH_TTY_CMD_READ_BUFFER,
base + GOLDFISH_TTY_REG_CMD);

spin_unlock_irqrestore(&qtty->lock, irq_flags);
@@ -142,7 +142,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
unsigned char *buf;
u32 count;

- count = __raw_readl(base + GOLDFISH_TTY_REG_BYTES_READY);
+ count = gf_ioread32(base + GOLDFISH_TTY_REG_BYTES_READY);
if (count == 0)
return IRQ_NONE;

@@ -159,7 +159,7 @@ static int goldfish_tty_activate(struct tty_port *port, struct tty_struct *tty)
{
struct goldfish_tty *qtty = container_of(port, struct goldfish_tty,
port);
- __raw_writel(GOLDFISH_TTY_CMD_INT_ENABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
+ gf_iowrite32(GOLDFISH_TTY_CMD_INT_ENABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
return 0;
}

@@ -167,7 +167,7 @@ static void goldfish_tty_shutdown(struct tty_port *port)
{
struct goldfish_tty *qtty = container_of(port, struct goldfish_tty,
port);
- __raw_writel(GOLDFISH_TTY_CMD_INT_DISABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
+ gf_iowrite32(GOLDFISH_TTY_CMD_INT_DISABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
}

static int goldfish_tty_open(struct tty_struct *tty, struct file *filp)
@@ -202,7 +202,7 @@ static unsigned int goldfish_tty_chars_in_buffer(struct tty_struct *tty)
{
struct goldfish_tty *qtty = &goldfish_ttys[tty->index];
void __iomem *base = qtty->base;
- return __raw_readl(base + GOLDFISH_TTY_REG_BYTES_READY);
+ return gf_ioread32(base + GOLDFISH_TTY_REG_BYTES_READY);
}

static void goldfish_tty_console_write(struct console *co, const char *b,
@@ -355,7 +355,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
* on Ranchu emulator (qemu2) returns 1 here and
* driver will use physical addresses.
*/
- qtty->version = __raw_readl(base + GOLDFISH_TTY_REG_VERSION);
+ qtty->version = gf_ioread32(base + GOLDFISH_TTY_REG_VERSION);

/*
* Goldfish TTY device on Ranchu emulator (qemu2)
@@ -374,7 +374,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
}
}

- __raw_writel(GOLDFISH_TTY_CMD_INT_DISABLE, base + GOLDFISH_TTY_REG_CMD);
+ gf_iowrite32(GOLDFISH_TTY_CMD_INT_DISABLE, base + GOLDFISH_TTY_REG_CMD);

ret = request_irq(irq, goldfish_tty_interrupt, IRQF_SHARED,
"goldfish_tty", qtty);
@@ -436,7 +436,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
static void gf_early_console_putchar(struct uart_port *port, int ch)
{
- __raw_writel(ch, port->membase);
+ gf_iowrite32(ch, port->membase);
}

static void gf_early_write(struct console *con, const char *s, unsigned int n)
diff --git a/include/linux/goldfish.h b/include/linux/goldfish.h
index 12be1601fd84..bcc17f95b906 100644
--- a/include/linux/goldfish.h
+++ b/include/linux/goldfish.h
@@ -8,14 +8,21 @@

/* Helpers for Goldfish virtual platform */

+#ifndef gf_ioread32
+#define gf_ioread32 ioread32
+#endif
+#ifndef gf_iowrite32
+#define gf_iowrite32 iowrite32
+#endif
+
static inline void gf_write_ptr(const void *ptr, void __iomem *portl,
void __iomem *porth)
{
const unsigned long addr = (unsigned long)ptr;

- __raw_writel(lower_32_bits(addr), portl);
+ gf_iowrite32(lower_32_bits(addr), portl);
#ifdef CONFIG_64BIT
- __raw_writel(upper_32_bits(addr), porth);
+ gf_iowrite32(upper_32_bits(addr), porth);
#endif
}

@@ -23,9 +30,9 @@ static inline void gf_write_dma_addr(const dma_addr_t addr,
void __iomem *portl,
void __iomem *porth)
{
- __raw_writel(lower_32_bits(addr), portl);
+ gf_iowrite32(lower_32_bits(addr), portl);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- __raw_writel(upper_32_bits(addr), porth);
+ gf_iowrite32(upper_32_bits(addr), porth);
#endif
}

--
2.34.1

2022-01-21 21:12:43

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH v11 2/5] tty: goldfish: introduce gf_ioread32()/gf_iowrite32()

On Thu, Jan 20, 2022 at 9:03 AM Laurent Vivier <[email protected]> wrote:
>
> Revert
> commit da31de35cd2f ("tty: goldfish: use __raw_writel()/__raw_readl()")
>
> to use accessors defined by the architecture.
>
> Define by default the accessor to be little-endian as we
> have only little-endian architectures using goldfish devices.
>
> Signed-off-by: Laurent Vivier <[email protected]>

The patch looks good, but the description seems wrong to me:

Talking about "little-endian architectures" makes no sense here, the
point is that the device was clearly defined as having little-endian
registers, and your earlier patch broke this driver when running
on big-endian kernels (if anyone ever tried this).

This means you should also add

Cc: [email protected] # v5.11+
Fixes: da31de35cd2f ("tty: goldfish: use __raw_writel()/__raw_readl()")

The fact that m68k gets this wrong is just a bug in qemu, but it's
probably impossible to fix that since there is no way of knowing which
other operating systems have started relying on that bug over the years.

It might be a good idea to revisit the qemu implementation and make
sure that the extra byteswap is only inserted on m68k and not on
other targets, but hopefully there are no new targets based on goldfish
anymore and we don't need to care.

Arnd

2022-01-21 22:27:35

by Laurent Vivier

[permalink] [raw]
Subject: Re: [PATCH v11 2/5] tty: goldfish: introduce gf_ioread32()/gf_iowrite32()

Le 20/01/2022 à 09:50, Arnd Bergmann a écrit :
> On Thu, Jan 20, 2022 at 9:03 AM Laurent Vivier <[email protected]> wrote:
>>
>> Revert
>> commit da31de35cd2f ("tty: goldfish: use __raw_writel()/__raw_readl()")
>>
>> to use accessors defined by the architecture.
>>
>> Define by default the accessor to be little-endian as we
>> have only little-endian architectures using goldfish devices.
>>
>> Signed-off-by: Laurent Vivier <[email protected]>
>
> The patch looks good, but the description seems wrong to me:
>
> Talking about "little-endian architectures" makes no sense here, the
> point is that the device was clearly defined as having little-endian
> registers, and your earlier patch broke this driver when running
> on big-endian kernels (if anyone ever tried this).
To explain why I did that:

The reference document[1] doesn't define the endianness of goldfish.

In QEMU, goldfish devices are defined with the DEVICE_NATIVE_ENDIAN flag [2], that means all the
target architectures defined in QEMU with TARGET_WORDS_BIGENDIAN will present them as big-endian
devices, the others as little-endian devices.

According to TARGET_WORDS_BIGENDIAN definition:

On the following QEMU target architectures (qemu-system-XXX), goldfish devices must be accessed with
big-endian read/write:

mips, mips64, s390x, sparc, sparc64, or1k, m68k, ppc, ppc64, xtensaeb, hppa, sh4eb, microblaze

On the following QEMU target architectures, goldfish devices must be accessed with little-endian
read/write:

arm, aarch64, alpha, avr, cris, i386, x86_64, microblazeel, mipsel, mips64el, nios2, riscv32,
riscv64, rx, sh4, tricore, xtensa

Thanks,
Laurent

[1] https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT
[2]
https://android.googlesource.com/platform/external/qemu/+/refs/heads/emu-master-dev/hw/char/goldfish_tty.c#222