LKML Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/2] m68k: Add Virtual M68k Machine
@ 2021-03-23 22:14 Laurent Vivier
  2021-03-23 22:14 ` [PATCH 1/2] rtc: goldfish: remove dependency to OF Laurent Vivier
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Laurent Vivier @ 2021-03-23 22:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m68k, Geert Uytterhoeven, linux-rtc, Alessandro Zummo,
	Alexandre Belloni, Laurent Vivier

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=3Dm68k-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=3Doff,mux=3Don,id=3Dchar0 \
  -mon chardev=3Dchar0,mode=3Dreadline \
  -kernel vmlinux \
  -append "console=3Dhvc0 root=3D/dev/vda2" \
  -blockdev node-name=3Dsystem,driver=3Dfile,filename=3Ddebian-10.0.qcow2 \
  -blockdev node-name=3Ddrive0,driver=3Dqcow2,file=3Dsystem \
  -device virtio-blk-device,drive=3Ddrive0 \
  -serial chardev:char0 \
  -device virtio-net-device,netdev=3Dhostnet0 \
  -netdev bridge,id=3Dhostnet0,br=3Dvirbr0,helper=3D/usr/libexec/qemu-bridge-=
helper \
  -device virtio-serial-device \
  -device virtio-gpu-device \
  -device virtconsole,chardev=3Dchar0 \
  -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]

Thanks,
Laurent

Laurent Vivier (2):
  rtc: goldfish: remove dependency to OF
  m68k: introduce a virtual m68k machine

 arch/m68k/Kbuild                           |   1 +
 arch/m68k/Kconfig.machine                  |  17 +++
 arch/m68k/configs/virt_defconfig           |  93 ++++++++++++++++
 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               |  26 +++++
 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                    |  30 ++++++
 arch/m68k/kernel/setup_mm.c                |   9 ++
 arch/m68k/mm/kmap.c                        |  20 ++--
 arch/m68k/virt/Makefile                    |   6 ++
 arch/m68k/virt/config.c                    | 118 +++++++++++++++++++++
 arch/m68k/virt/ints.c                      | 110 +++++++++++++++++++
 arch/m68k/virt/platform.c                  |  80 ++++++++++++++
 arch/m68k/virt/timer.c                     |  91 ++++++++++++++++
 drivers/rtc/Kconfig                        |   2 +-
 19 files changed, 659 insertions(+), 18 deletions(-)
 create mode 100644 arch/m68k/configs/virt_defconfig
 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 arch/m68k/virt/timer.c

--=20
2.30.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/2] rtc: goldfish: remove dependency to OF
  2021-03-23 22:14 [PATCH 0/2] m68k: Add Virtual M68k Machine Laurent Vivier
@ 2021-03-23 22:14 ` Laurent Vivier
  2021-03-23 22:14 ` [PATCH 2/2] m68k: introduce a virtual m68k machine Laurent Vivier
  2021-04-16 20:26 ` [PATCH 0/2] m68k: Add Virtual M68k Machine Alexandre Belloni
  2 siblings, 0 replies; 11+ messages in thread
From: Laurent Vivier @ 2021-03-23 22:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m68k, Geert Uytterhoeven, linux-rtc, Alessandro Zummo,
	Alexandre Belloni, Laurent Vivier

We want to use the goldfish RTC on a machine without OF.
As there is no real dependency on it, remove the OF dependency from the
goldfish entry in Kconfig

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 drivers/rtc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ce723dc54aa4..5a35ddddd8c6 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1898,7 +1898,7 @@ config RTC_DRV_HID_SENSOR_TIME
 
 config RTC_DRV_GOLDFISH
 	tristate "Goldfish Real Time Clock"
-	depends on OF && HAS_IOMEM
+	depends on HAS_IOMEM
 	help
 	  Say yes to enable RTC driver for the Goldfish based virtual platform.
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 2/2] m68k: introduce a virtual m68k machine
  2021-03-23 22:14 [PATCH 0/2] m68k: Add Virtual M68k Machine Laurent Vivier
  2021-03-23 22:14 ` [PATCH 1/2] rtc: goldfish: remove dependency to OF Laurent Vivier
@ 2021-03-23 22:14 ` Laurent Vivier
  2021-04-27 17:20   ` Laurent Vivier
  2021-04-28 12:04   ` Geert Uytterhoeven
  2021-04-16 20:26 ` [PATCH 0/2] m68k: Add Virtual M68k Machine Alexandre Belloni
  2 siblings, 2 replies; 11+ messages in thread
From: Laurent Vivier @ 2021-03-23 22:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m68k, Geert Uytterhoeven, linux-rtc, Alessandro Zummo,
	Alexandre Belloni, Laurent Vivier

This machine allows to have up to 3.2 GiB and 128 Virtio devices.

It is based on android goldfish devices.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 arch/m68k/Kbuild                           |   1 +
 arch/m68k/Kconfig.machine                  |  17 +++
 arch/m68k/configs/virt_defconfig           |  93 ++++++++++++++++
 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               |  26 +++++
 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                    |  30 ++++++
 arch/m68k/kernel/setup_mm.c                |   9 ++
 arch/m68k/mm/kmap.c                        |  20 ++--
 arch/m68k/virt/Makefile                    |   6 ++
 arch/m68k/virt/config.c                    | 118 +++++++++++++++++++++
 arch/m68k/virt/ints.c                      | 110 +++++++++++++++++++
 arch/m68k/virt/platform.c                  |  80 ++++++++++++++
 arch/m68k/virt/timer.c                     |  91 ++++++++++++++++
 18 files changed, 658 insertions(+), 17 deletions(-)
 create mode 100644 arch/m68k/configs/virt_defconfig
 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 arch/m68k/virt/timer.c

diff --git a/arch/m68k/Kbuild b/arch/m68k/Kbuild
index 18abb35c26a1..7762af9f6def 100644
--- a/arch/m68k/Kbuild
+++ b/arch/m68k/Kbuild
@@ -17,3 +17,4 @@ obj-$(CONFIG_M68060)		+= ifpsp060/
 obj-$(CONFIG_M68KFPU_EMU)	+= math-emu/
 obj-$(CONFIG_M68000)		+= 68000/
 obj-$(CONFIG_COLDFIRE)		+= coldfire/
+obj-$(CONFIG_VIRT)		+= virt/
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index 4d59ec2f5b8d..71d9d7b69ed1 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -145,6 +145,23 @@ config SUN3
 
 	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
 
+config VIRT
+	bool "Virtual M68k Machine support"
+	depends on MMU
+	select MMU_MOTOROLA if MMU
+	select M68040
+	select LEGACY_TIMER_TICK
+	select VIRTIO_MENU
+	select VIRTIO_MMIO
+	select GOLDFISH
+	select TTY
+	select GOLDFISH_TTY
+	select RTC_CLASS
+	select RTC_DRV_GOLDFISH
+	help
+	  This options enable a pure virtual machine based on m68k,
+	  VIRTIO MMIO devices and GOLDFISH interfaces (TTY, RTC, PIC)
+
 config PILOT
 	bool
 
diff --git a/arch/m68k/configs/virt_defconfig b/arch/m68k/configs/virt_defconfig
new file mode 100644
index 000000000000..51842acd5434
--- /dev/null
+++ b/arch/m68k/configs/virt_defconfig
@@ -0,0 +1,93 @@
+CONFIG_M68K=y
+CONFIG_M68040=y
+CONFIG_VIRT=y
+CONFIG_DEVTMPFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_UNIX=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_AUTOFS_FS=y
+CONFIG_SYSFS=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_SYSCTL=y
+CONFIG_SGETMASK_SYSCALL=y
+CONFIG_SYSFS_SYSCALL=y
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_EXT4_FS=y
+CONFIG_SHMEM=y
+CONFIG_CGROUPS=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_CGROUP_NET_CLASSID=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+CONFIG_SUN_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_BLK_MQ_VIRTIO=y
+CONFIG_INET=y
+CONFIG_PACKET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NETDEVICES=y
+CONFIG_NET=y
+CONFIG_NET_CORE=y
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_ETHTOOL_NETLINK=y
+CONFIG_9P_FS=y
+CONFIG_9P_FS_POSIX_ACL=y
+CONFIG_9P_FS_SECURITY=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_SCSI=y
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_SCSI_VIRTIO=y
+CONFIG_VIRTIO_NET=y
+CONFIG_GOLDFISH_TTY=y
+CONFIG_GOLDFISH_TTY_EARLY_CONSOLE=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_DRM=y
+CONFIG_DRM_VIRTIO_GPU=y
+CONFIG_VIRT_DRIVERS=y
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_MENU=y
+CONFIG_VIRTIO_INPUT=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_DMA_SHARED_BUFFER=y
+CONFIG_GOLDFISH=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_INPUT=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_PROC_HARDWARE=y
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index 91dd493791d7..7829e955ca04 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -12,7 +12,8 @@
  */
 #if defined(CONFIG_COLDFIRE)
 #define NR_IRQS 256
-#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || \
+      defined(CONFIG_SUN3X) || defined(CONFIG_VIRT)
 #define NR_IRQS 200
 #elif defined(CONFIG_ATARI)
 #define NR_IRQS 141
diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h
index aca22c2c1ee2..8b9279971ff6 100644
--- a/arch/m68k/include/asm/pgtable_mm.h
+++ b/arch/m68k/include/asm/pgtable_mm.h
@@ -81,6 +81,9 @@
 #elif defined(CONFIG_COLDFIRE)
 #define KMAP_START	0xe0000000
 #define KMAP_END	0xf0000000
+#elif defined(CONFIG_VIRT)
+#define	KMAP_START	0xdf000000
+#define	KMAP_END	0xff000000
 #else
 #define	KMAP_START	0xd0000000
 #define	KMAP_END	0xf0000000
@@ -93,6 +96,10 @@ extern unsigned long m68k_vmalloc_end;
 #elif defined(CONFIG_COLDFIRE)
 #define VMALLOC_START	0xd0000000
 #define VMALLOC_END	0xe0000000
+#elif defined(CONFIG_VIRT)
+#define VMALLOC_OFFSET	PAGE_SIZE
+#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_END     KMAP_START
 #else
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
diff --git a/arch/m68k/include/asm/setup.h b/arch/m68k/include/asm/setup.h
index 8f2023f8c1c4..20de7f30f484 100644
--- a/arch/m68k/include/asm/setup.h
+++ b/arch/m68k/include/asm/setup.h
@@ -37,7 +37,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
 	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
 	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                  \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
 #else
 #  define MACH_AMIGA_ONLY
@@ -50,7 +51,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
 	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
 	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                  \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
 #else
 #  define MACH_ATARI_ONLY
@@ -63,7 +65,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \
 	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)                 \
 	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                        \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                    \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_MAC (m68k_machtype == MACH_MAC)
 #else
 #  define MACH_MAC_ONLY
@@ -84,7 +87,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
 	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)              \
 	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                 \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO)
 #else
 #  define MACH_APOLLO_ONLY
@@ -97,7 +101,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
 	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
 	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME16x)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME16x)                 \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_MVME147 (m68k_machtype == MACH_MVME147)
 #else
 #  define MACH_MVME147_ONLY
@@ -110,7 +115,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
 	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
 	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                 \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_MVME16x (m68k_machtype == MACH_MVME16x)
 #else
 #  define MACH_MVME16x_ONLY
@@ -123,7 +129,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
 	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
 	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                 \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_BVME6000 (m68k_machtype == MACH_BVME6000)
 #else
 #  define MACH_BVME6000_ONLY
@@ -136,7 +143,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
 	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
 	|| defined(CONFIG_BVME6000) || defined(CONFIG_Q40) \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_HP300 (m68k_machtype == MACH_HP300)
 #else
 #  define MACH_HP300_ONLY
@@ -149,7 +157,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
 	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
 	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
-	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                 \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_Q40 (m68k_machtype == MACH_Q40)
 #else
 #  define MACH_Q40_ONLY
@@ -162,7 +171,8 @@ extern unsigned long m68k_machtype;
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
 	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
 	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
-	|| defined(CONFIG_Q40) || defined(CONFIG_MVME147)
+	|| defined(CONFIG_Q40) || defined(CONFIG_MVME147)                   \
+	|| defined(CONFIG_VIRT)
 #  define MACH_IS_SUN3X (m68k_machtype == MACH_SUN3X)
 #else
 #  define CONFIG_SUN3X_ONLY
@@ -170,6 +180,20 @@ extern unsigned long m68k_machtype;
 #  define MACH_TYPE (MACH_SUN3X)
 #endif
 
+#if !defined(CONFIG_VIRT)
+#  define MACH_IS_VIRT (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \
+	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)                 \
+	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                        \
+	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                    \
+	|| defined(CONFIG_MAC)
+#  define MACH_IS_VIRT (m68k_machtype == MACH_VIRT)
+#else
+#  define MACH_VIRTONLY
+#  define MACH_IS_VIRT (1)
+#  define MACH_TYPE (MACH_VIRT)
+#endif
+
 #ifndef MACH_TYPE
 #  define MACH_TYPE (m68k_machtype)
 #endif
diff --git a/arch/m68k/include/asm/virt.h b/arch/m68k/include/asm/virt.h
new file mode 100644
index 000000000000..2795a70f709b
--- /dev/null
+++ b/arch/m68k/include/asm/virt.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_VIRT_H
+#define __ASM_VIRT_H
+
+#define NUM_VIRT_SOURCES 200
+
+struct virt_booter_device_data {
+	unsigned long mmio;
+	unsigned long irq;
+};
+
+struct virt_booter_data {
+	unsigned long qemu_version;
+	struct virt_booter_device_data pic;
+	struct virt_booter_device_data rtc;
+	struct virt_booter_device_data tty;
+	struct virt_booter_device_data ctrl;
+	struct virt_booter_device_data virtio;
+};
+
+extern struct virt_booter_data virt_bi_data;
+
+extern void __init virt_init_IRQ(void);
+extern void __init virt_sched_init(void);
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/bootinfo-virt.h b/arch/m68k/include/uapi/asm/bootinfo-virt.h
new file mode 100644
index 000000000000..ab17fd9d200d
--- /dev/null
+++ b/arch/m68k/include/uapi/asm/bootinfo-virt.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * asm/bootinfo-virt.h -- Virtual-m68k-specific boot information definitions
+ */
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_VIRT_H
+#define _UAPI_ASM_M68K_BOOTINFO_VIRT_H
+
+#define BI_VIRT_QEMU_VERSION	0x8000
+#define BI_VIRT_GF_PIC_BASE	0x8001
+#define BI_VIRT_GF_RTC_BASE	0x8002
+#define BI_VIRT_GF_TTY_BASE	0x8003
+#define BI_VIRT_VIRTIO_BASE	0x8004
+#define BI_VIRT_CTRL_BASE       0x8005
+
+#define VIRT_BOOTI_VERSION	MK_BI_VERSION(2, 0)
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo.h b/arch/m68k/include/uapi/asm/bootinfo.h
index 38d3140381fa..203d9cbf9630 100644
--- a/arch/m68k/include/uapi/asm/bootinfo.h
+++ b/arch/m68k/include/uapi/asm/bootinfo.h
@@ -83,6 +83,7 @@ struct mem_info {
 #define MACH_SUN3X		11
 #define MACH_M54XX		12
 #define MACH_M5441X		13
+#define MACH_VIRT		14
 
 
     /*
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index dbac7f8743fc..c0833da6a2ca 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -11,6 +11,7 @@ extra-$(CONFIG_VME)	:= head.o
 extra-$(CONFIG_HP300)	:= head.o
 extra-$(CONFIG_Q40)	:= head.o
 extra-$(CONFIG_SUN3X)	:= head.o
+extra-$(CONFIG_VIRT)	:= head.o
 extra-$(CONFIG_SUN3)	:= sun3-head.o
 extra-y			+= vmlinux.lds
 
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 493c95db0e51..d4a4bbecf6c0 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -262,6 +262,7 @@
 #include <asm/bootinfo-hp300.h>
 #include <asm/bootinfo-mac.h>
 #include <asm/bootinfo-q40.h>
+#include <asm/bootinfo-virt.h>
 #include <asm/bootinfo-vme.h>
 #include <asm/setup.h>
 #include <asm/entry.h>
@@ -534,6 +535,7 @@ func_define	putn,1
 #define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab
 #define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab
 #define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab
+#define is_not_virt(lab) cmpl &MACH_VIRT,%pc@(m68k_machtype); jne lab
 
 #define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \
 			jeq 42f; \
@@ -647,6 +649,14 @@ ENTRY(__start)
 L(test_notmac):
 #endif /* CONFIG_MAC */
 
+#ifdef CONFIG_VIRT
+	is_not_virt(L(test_notvirt))
+
+	get_bi_record BI_VIRT_GF_TTY_BASE
+	lea	%pc@(L(virt_gf_tty_base)),%a1
+	movel	%a0@,%a1@
+L(test_notvirt):
+#endif /* CONFIG_VIRT */
 
 /*
  * There are ultimately two pieces of information we want for all kinds of
@@ -1237,6 +1247,13 @@ L(mmu_init_not_mac):
 L(notsun3x):
 #endif
 
+#ifdef CONFIG_VIRT
+	is_not_virt(L(novirt))
+	mmu_map_tt	#1,#0xFF000000,#0x01000000,#_PAGE_NOCACHE_S
+	jbra    L(mmu_init_done)
+L(novirt):
+#endif
+
 #ifdef CONFIG_APOLLO
 	is_not_apollo(L(notapollo))
 
@@ -3186,6 +3203,13 @@ func_start	serial_putc,%d0/%d1/%a0/%a1
 3:
 #endif
 
+#ifdef CONFIG_VIRT
+	is_not_virt(L(serial_putc_done))
+
+	movel L(virt_gf_tty_base),%a1
+	moveb %d0,%a1@(GF_PUT_CHAR)
+#endif
+
 L(serial_putc_done):
 func_return	serial_putc
 
@@ -3865,3 +3889,9 @@ q40_mem_cptr:
 L(q40_do_debug):
 	.long	0
 #endif
+
+#if defined(CONFIG_VIRT)
+GF_PUT_CHAR = 0x00
+L(virt_gf_tty_base):
+	.long 0
+#endif /* CONFIG_VIRT */
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index 017bac3aab80..b628d0a1f3f1 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -122,6 +122,7 @@ extern int mvme16x_parse_bootinfo(const struct bi_record *);
 extern int mvme147_parse_bootinfo(const struct bi_record *);
 extern int hp300_parse_bootinfo(const struct bi_record *);
 extern int apollo_parse_bootinfo(const struct bi_record *);
+extern int virt_parse_bootinfo(const struct bi_record *);
 
 extern void config_amiga(void);
 extern void config_atari(void);
@@ -134,6 +135,7 @@ extern void config_bvme6000(void);
 extern void config_hp300(void);
 extern void config_q40(void);
 extern void config_sun3x(void);
+extern void config_virt(void);
 
 #define MASK_256K 0xfffc0000
 
@@ -203,6 +205,8 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
 				unknown = hp300_parse_bootinfo(record);
 			else if (MACH_IS_APOLLO)
 				unknown = apollo_parse_bootinfo(record);
+			else if (MACH_IS_VIRT)
+				unknown = virt_parse_bootinfo(record);
 			else
 				unknown = 1;
 		}
@@ -336,6 +340,11 @@ void __init setup_arch(char **cmdline_p)
 		cf_mmu_context_init();
 		config_BSP(NULL, 0);
 		break;
+#endif
+#ifdef CONFIG_VIRT
+	case MACH_VIRT:
+		config_virt();
+		break;
 #endif
 	default:
 		panic("No configuration setup");
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index 1269d513b221..41c72f50c0a2 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -180,6 +180,12 @@ void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
 			return (void __iomem *)physaddr;
 	}
 #endif
+#ifdef CONFIG_VIRT
+	if (MACH_IS_VIRT) {
+		if (physaddr >= 0xff000000 && cacheflag == IOMAP_NOCACHE_SER)
+			return (void __iomem *)physaddr;
+	}
+#endif
 #ifdef CONFIG_COLDFIRE
 	if (__cf_internalio(physaddr))
 		return (void __iomem *) physaddr;
@@ -293,18 +299,20 @@ EXPORT_SYMBOL(__ioremap);
  */
 void iounmap(void __iomem *addr)
 {
-#ifdef CONFIG_AMIGA
-	if ((!MACH_IS_AMIGA) ||
-	    (((unsigned long)addr < 0x40000000) ||
-	     ((unsigned long)addr > 0x60000000)))
-			free_io_area((__force void *)addr);
+#if defined(CONFIG_AMIGA) || defined(CONFIG_VIRT)
+	if (MACH_IS_AMIGA &&
+	    ((unsigned long)addr >= 0x40000000) &&
+	    ((unsigned long)addr < 0x60000000))
+		return;
+	if (MACH_IS_VIRT && (unsigned long)addr >= 0xff000000)
+		return;
 #else
 #ifdef CONFIG_COLDFIRE
 	if (cf_internalio(addr))
 		return;
 #endif
-	free_io_area((__force void *)addr);
 #endif
+	free_io_area((__force void *)addr);
 }
 EXPORT_SYMBOL(iounmap);
 
diff --git a/arch/m68k/virt/Makefile b/arch/m68k/virt/Makefile
new file mode 100644
index 000000000000..40420fc886bb
--- /dev/null
+++ b/arch/m68k/virt/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for Linux arch/m68k/virt source directory
+#
+
+obj-y		:= config.o ints.o platform.o timer.o
diff --git a/arch/m68k/virt/config.c b/arch/m68k/virt/config.c
new file mode 100644
index 000000000000..ea22eed73a90
--- /dev/null
+++ b/arch/m68k/virt/config.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/serial_core.h>
+
+#include <asm/bootinfo.h>
+#include <asm/bootinfo-virt.h>
+#include <asm/byteorder.h>
+
+#include <asm/machdep.h>
+#include <asm/virt.h>
+
+struct virt_booter_data virt_bi_data;
+
+struct virt_ctrl {
+	u32 features;
+	u32 cmd;
+};
+
+enum {
+	CMD_NOOP,
+	CMD_RESET,
+	CMD_HALT,
+	CMD_PANIC,
+};
+
+#define virt_ctrl ((volatile struct virt_ctrl *)virt_bi_data.ctrl.mmio)
+
+static void virt_get_model(char *str)
+{
+	/* str is 80 characters long */
+	sprintf(str, "QEMU Virtual M68K Machine (%d.%d.%d)",
+		(u8)(virt_bi_data.qemu_version >> 24),
+		(u8)(virt_bi_data.qemu_version >> 16),
+		(u8)(virt_bi_data.qemu_version >> 8));
+}
+
+extern void show_registers(struct pt_regs *);
+
+static void virt_halt(void)
+{
+	virt_ctrl->cmd = CMD_HALT;
+	local_irq_disable();
+	while (1)
+		;
+}
+
+static void virt_reset(void)
+{
+	virt_ctrl->cmd = CMD_RESET;
+	local_irq_disable();
+	while (1)
+		;
+}
+
+/*
+ * Parse a virtual-m68k-specific record in the bootinfo
+ */
+
+int __init virt_parse_bootinfo(const struct bi_record *record)
+{
+	int unknown = 0;
+	const void *data = record->data;
+
+	switch (be16_to_cpu(record->tag)) {
+	case BI_VIRT_QEMU_VERSION:
+		virt_bi_data.qemu_version = be32_to_cpup(data);
+		break;
+	case BI_VIRT_GF_PIC_BASE:
+		virt_bi_data.pic.mmio = be32_to_cpup(data);
+		data += 4;
+		virt_bi_data.pic.irq = be32_to_cpup(data);
+		break;
+	case BI_VIRT_GF_RTC_BASE:
+		virt_bi_data.rtc.mmio = be32_to_cpup(data);
+		data += 4;
+		virt_bi_data.rtc.irq = be32_to_cpup(data);
+		break;
+	case BI_VIRT_GF_TTY_BASE:
+		virt_bi_data.tty.mmio = be32_to_cpup(data);
+		data += 4;
+		virt_bi_data.tty.irq = be32_to_cpup(data);
+		break;
+	case BI_VIRT_CTRL_BASE:
+		virt_bi_data.ctrl.mmio = be32_to_cpup(data);
+		data += 4;
+		virt_bi_data.ctrl.irq = be32_to_cpup(data);
+		break;
+	case BI_VIRT_VIRTIO_BASE:
+		virt_bi_data.virtio.mmio = be32_to_cpup(data);
+		data += 4;
+		virt_bi_data.virtio.irq = be32_to_cpup(data);
+		break;
+	default:
+		unknown = 1;
+		break;
+	}
+	return unknown;
+}
+
+void __init config_virt(void)
+{
+	char earlycon[24];
+
+	if (!MACH_IS_VIRT)
+		pr_err("ERROR: no Virtual M68k Machine, but %s called!!\n",
+		       __func__);
+
+	snprintf(earlycon, sizeof(earlycon), "early_gf_tty,0x%08lx",
+		 virt_bi_data.tty.mmio);
+	setup_earlycon(earlycon);
+
+	mach_init_IRQ = virt_init_IRQ;
+	mach_sched_init = virt_sched_init;
+	mach_get_model = virt_get_model;
+	mach_reset = virt_reset;
+	mach_halt = virt_halt;
+	mach_power_off = virt_halt;
+}
diff --git a/arch/m68k/virt/ints.c b/arch/m68k/virt/ints.c
new file mode 100644
index 000000000000..aa94cb3b6d96
--- /dev/null
+++ b/arch/m68k/virt/ints.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/sched/debug.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <asm/virt.h>
+#include <asm/irq.h>
+#include <asm/hwtest.h>
+#include <asm/irq_regs.h>
+
+struct goldfish_pic {
+	u32 status;
+	u32 irq_pending;
+	u32 irq_diable_all;
+	u32 disable;
+	u32 enable;
+	u32 pad[1019];
+};
+
+extern void show_registers(struct pt_regs *);
+
+#define gf_pic ((volatile struct goldfish_pic *)virt_bi_data.pic.mmio)
+
+#define GF_PIC(irq) (gf_pic[(irq - IRQ_USER) / 32])
+#define GF_IRQ(irq) ((irq - IRQ_USER) % 32)
+
+static void virt_irq_enable(struct irq_data *data)
+{
+	GF_PIC(data->irq).enable = 1 << GF_IRQ(data->irq);
+}
+
+static void virt_irq_disable(struct irq_data *data)
+{
+	GF_PIC(data->irq).disable = 1 << GF_IRQ(data->irq);
+}
+
+static unsigned int virt_irq_startup(struct irq_data *data)
+{
+	GF_PIC(data->irq).enable = 1 << GF_IRQ(data->irq);
+	return 0;
+}
+
+static void virt_irq_shutdown(struct irq_data *data)
+{
+	GF_PIC(data->irq).disable = 1 << GF_IRQ(data->irq);
+}
+
+static volatile int in_nmi;
+
+irqreturn_t virt_nmi_handler(int irq, void *dev_id)
+{
+	if (in_nmi)
+		return IRQ_HANDLED;
+	in_nmi = 1;
+
+	pr_info("Non-Maskable Interrupt\n");
+	show_registers(get_irq_regs());
+
+	in_nmi = 0;
+	return IRQ_HANDLED;
+}
+
+static struct irq_chip virt_irq_chip = {
+	.name		= "virt",
+	.irq_enable	= virt_irq_enable,
+	.irq_disable	= virt_irq_disable,
+	.irq_startup	= virt_irq_startup,
+	.irq_shutdown	= virt_irq_shutdown,
+};
+
+static void goldfish_pic_irq(struct irq_desc *desc)
+{
+	u32 irq_pending, irq_bit;
+	int irq_num;
+
+	irq_pending = gf_pic[desc->irq_data.irq - 1].irq_pending;
+	irq_num = IRQ_USER + (desc->irq_data.irq - 1) * 32;
+	irq_bit = 1;
+
+	do {
+		if (irq_pending & irq_bit) {
+			generic_handle_irq(irq_num);
+			irq_pending &= ~irq_bit;
+		}
+		++irq_num;
+		irq_bit <<= 1;
+	} while (irq_pending);
+}
+
+void __init virt_init_IRQ(void)
+{
+	int i;
+
+	m68k_setup_irq_controller(&virt_irq_chip, handle_simple_irq, IRQ_USER,
+				  NUM_VIRT_SOURCES - IRQ_USER);
+
+	for (i = 0; i < 6; i++) {
+		irq_set_chained_handler(virt_bi_data.pic.irq + i,
+					goldfish_pic_irq);
+	}
+
+	if (request_irq(IRQ_AUTO_7, virt_nmi_handler, 0, "NMI",
+			virt_nmi_handler))
+		pr_err("Couldn't register NMI\n");
+}
diff --git a/arch/m68k/virt/platform.c b/arch/m68k/virt/platform.c
new file mode 100644
index 000000000000..311d53dec487
--- /dev/null
+++ b/arch/m68k/virt/platform.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <asm/virt.h>
+#include <asm/irq.h>
+
+static struct platform_device virt_m68k_goldfish_tty = {
+	.name = "goldfish_tty",
+	.id = PLATFORM_DEVID_NONE,
+	.num_resources = 2,
+	.resource = (struct resource [2]) { },
+};
+static struct platform_device virt_m68k_goldfish_rtc = {
+	.name = "goldfish_rtc",
+	.id = PLATFORM_DEVID_NONE,
+	.num_resources = 2,
+	.resource = (struct resource [2]) { },
+};
+
+#define VIRTIO_BUS_NB	128
+static struct platform_device virt_m68k_virtio_mmio_device[VIRTIO_BUS_NB];
+static struct resource virt_m68k_virtio_mmio_resources[VIRTIO_BUS_NB][2];
+
+static int __init virt_platform_init(void)
+{
+	int err;
+	int i;
+	extern unsigned long min_low_pfn;
+
+	if (!MACH_IS_VIRT)
+		return -ENODEV;
+
+	min_low_pfn = 0;
+
+	virt_m68k_goldfish_tty.resource[0].flags = IORESOURCE_MEM;
+	virt_m68k_goldfish_tty.resource[0].start = virt_bi_data.tty.mmio;
+	virt_m68k_goldfish_tty.resource[0].end   = virt_bi_data.tty.mmio;
+	virt_m68k_goldfish_tty.resource[1].flags = IORESOURCE_IRQ;
+	virt_m68k_goldfish_tty.resource[1].start = virt_bi_data.tty.irq;
+	virt_m68k_goldfish_tty.resource[1].end   = virt_bi_data.tty.irq;
+
+	err = platform_device_register(&virt_m68k_goldfish_tty);
+	if (err)
+		return err;
+
+	virt_m68k_goldfish_rtc.resource[0].flags = IORESOURCE_MEM;
+	virt_m68k_goldfish_rtc.resource[0].start = virt_bi_data.rtc.mmio + 0x1000;
+	virt_m68k_goldfish_rtc.resource[0].end   = virt_bi_data.rtc.mmio + 0x1fff;
+	virt_m68k_goldfish_rtc.resource[1].flags = IORESOURCE_IRQ;
+	virt_m68k_goldfish_rtc.resource[1].start = virt_bi_data.rtc.irq + 1;
+	virt_m68k_goldfish_rtc.resource[1].end   = virt_bi_data.rtc.irq + 1;
+	err = platform_device_register(&virt_m68k_goldfish_rtc);
+	if (err)
+		return err;
+
+	for (i = 0; i < VIRTIO_BUS_NB; i++) {
+		virt_m68k_virtio_mmio_device[i].name = "virtio-mmio";
+		virt_m68k_virtio_mmio_device[i].id = i;
+		virt_m68k_virtio_mmio_device[i].num_resources = 2;
+		virt_m68k_virtio_mmio_device[i].resource = virt_m68k_virtio_mmio_resources[i];
+
+		virt_m68k_virtio_mmio_resources[i][0].flags = IORESOURCE_MEM;
+		virt_m68k_virtio_mmio_resources[i][0].start = virt_bi_data.virtio.mmio +
+							      i * 0x200;
+		virt_m68k_virtio_mmio_resources[i][0].end   = virt_bi_data.virtio.mmio +
+							      (i + 1) * 0x200 - 1;
+		virt_m68k_virtio_mmio_resources[i][1].flags = IORESOURCE_IRQ;
+		virt_m68k_virtio_mmio_resources[i][1].start = virt_bi_data.virtio.irq + i;
+		virt_m68k_virtio_mmio_resources[i][1].end   = virt_bi_data.virtio.irq + i;
+
+		err = platform_device_register(&virt_m68k_virtio_mmio_device[i]);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+arch_initcall(virt_platform_init);
diff --git a/arch/m68k/virt/timer.c b/arch/m68k/virt/timer.c
new file mode 100644
index 000000000000..705fd53beac5
--- /dev/null
+++ b/arch/m68k/virt/timer.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clocksource.h>
+#include <asm/virt.h>
+
+struct goldfish_timer {
+	u32 time_low;
+	u32 time_high;
+	u32 alarm_low;
+	u32 alarm_high;
+	u32 irq_enabled;
+	u32 clear_alarm;
+	u32 alarm_status;
+	u32 clear_interrupt;
+};
+
+#define gf_timer ((volatile struct goldfish_timer *)virt_bi_data.rtc.mmio)
+
+static u64 goldfish_timer_read(struct clocksource *cs)
+{
+	u64 ticks;
+
+	ticks = gf_timer->time_low;
+	ticks += (u64)gf_timer->time_high << 32;
+
+	return ticks;
+}
+
+static struct clocksource goldfish_timer = {
+	.name		= "goldfish_timer",
+	.rating		= 400,
+	.read		= goldfish_timer_read,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= 0,
+	.max_idle_ns	= LONG_MAX,
+};
+
+static irqreturn_t golfish_timer_handler(int irq, void *dev_id)
+{
+	unsigned long flags;
+	u64 now;
+
+	local_irq_save(flags);
+	gf_timer->clear_interrupt = 1;
+
+	now = gf_timer->time_low;
+	now += (u64)gf_timer->time_high << 32;
+
+	legacy_timer_tick(1);
+
+	now += NSEC_PER_SEC / HZ;
+	gf_timer->alarm_high = now >> 32;
+	gf_timer->alarm_low = (u32)now;
+	local_irq_restore(flags);
+
+	return IRQ_HANDLED;
+}
+
+void __init virt_sched_init(void)
+{
+	u64 now;
+	static struct resource sched_res;
+
+	sched_res.name  = "goldfish_timer";
+	sched_res.start = virt_bi_data.rtc.mmio;
+	sched_res.end   = virt_bi_data.rtc.mmio + 0xfff;
+
+	if (request_resource(&iomem_resource, &sched_res)) {
+		pr_err("Cannot allocate goldfish-timer resource\n");
+		return;
+	}
+
+	if (request_irq(virt_bi_data.rtc.irq, golfish_timer_handler, IRQF_TIMER,
+			"timer", NULL)) {
+		pr_err("Couldn't register timer interrupt\n");
+		return;
+	}
+
+	now = gf_timer->time_low;
+	now += (u64)gf_timer->time_high << 32;
+	now += NSEC_PER_SEC / HZ;
+
+	gf_timer->clear_interrupt = 1;
+	gf_timer->alarm_high = now >> 32;
+	gf_timer->alarm_low = (u32)now;
+	gf_timer->irq_enabled = 1;
+
+	clocksource_register_hz(&goldfish_timer, NSEC_PER_SEC);
+}
-- 
2.30.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/2] m68k: Add Virtual M68k Machine
  2021-03-23 22:14 [PATCH 0/2] m68k: Add Virtual M68k Machine Laurent Vivier
  2021-03-23 22:14 ` [PATCH 1/2] rtc: goldfish: remove dependency to OF Laurent Vivier
  2021-03-23 22:14 ` [PATCH 2/2] m68k: introduce a virtual m68k machine Laurent Vivier
@ 2021-04-16 20:26 ` Alexandre Belloni
  2021-04-16 20:34   ` Alexandre Belloni
  2 siblings, 1 reply; 11+ messages in thread
From: Alexandre Belloni @ 2021-04-16 20:26 UTC (permalink / raw)
  To: linux-kernel, Laurent Vivier
  Cc: Alexandre Belloni, Alessandro Zummo, linux-m68k, linux-rtc,
	Geert Uytterhoeven

On Tue, 23 Mar 2021 23:14:28 +0100, Laurent Vivier wrote:
> 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).
> 
> [...]

Applied, thanks!

[1/2] rtc: goldfish: remove dependency to OF
      commit: 3fd00fdc4f11c656a63e6a6280c0bcb63cf109a2
[2/2] m68k: introduce a virtual m68k machine
      commit: 95631785c64840f3816f7a4cc2ce1a5332f43184

Best regards,
-- 
Alexandre Belloni <alexandre.belloni@bootlin.com>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/2] m68k: Add Virtual M68k Machine
  2021-04-16 20:26 ` [PATCH 0/2] m68k: Add Virtual M68k Machine Alexandre Belloni
@ 2021-04-16 20:34   ` Alexandre Belloni
  0 siblings, 0 replies; 11+ messages in thread
From: Alexandre Belloni @ 2021-04-16 20:34 UTC (permalink / raw)
  To: linux-kernel, Laurent Vivier
  Cc: Alessandro Zummo, linux-m68k, linux-rtc, Geert Uytterhoeven

On 16/04/2021 22:26:26+0200, Alexandre Belloni wrote:
> On Tue, 23 Mar 2021 23:14:28 +0100, Laurent Vivier wrote:
> > 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).
> > 
> > [...]
> 
> Applied, thanks!
> 
> [1/2] rtc: goldfish: remove dependency to OF
>       commit: 3fd00fdc4f11c656a63e6a6280c0bcb63cf109a2
> [2/2] m68k: introduce a virtual m68k machine
>       commit: 95631785c64840f3816f7a4cc2ce1a5332f43184
> 

Ah, obviously, I'm not applying the m68k patch.

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/2] m68k: introduce a virtual m68k machine
  2021-03-23 22:14 ` [PATCH 2/2] m68k: introduce a virtual m68k machine Laurent Vivier
@ 2021-04-27 17:20   ` Laurent Vivier
  2021-04-28 12:07     ` Geert Uytterhoeven
  2021-04-28 12:04   ` Geert Uytterhoeven
  1 sibling, 1 reply; 11+ messages in thread
From: Laurent Vivier @ 2021-04-27 17:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-m68k, Geert Uytterhoeven, linux-rtc, Alessandro Zummo,
	Alexandre Belloni

Hi,

Le 23/03/2021 à 23:14, Laurent Vivier a écrit :
> This machine allows to have up to 3.2 GiB and 128 Virtio devices.
> 
> It is based on android goldfish devices.
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  arch/m68k/Kbuild                           |   1 +
>  arch/m68k/Kconfig.machine                  |  17 +++
>  arch/m68k/configs/virt_defconfig           |  93 ++++++++++++++++
>  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               |  26 +++++
>  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                    |  30 ++++++
>  arch/m68k/kernel/setup_mm.c                |   9 ++
>  arch/m68k/mm/kmap.c                        |  20 ++--
>  arch/m68k/virt/Makefile                    |   6 ++
>  arch/m68k/virt/config.c                    | 118 +++++++++++++++++++++
>  arch/m68k/virt/ints.c                      | 110 +++++++++++++++++++
>  arch/m68k/virt/platform.c                  |  80 ++++++++++++++
>  arch/m68k/virt/timer.c                     |  91 ++++++++++++++++
>  18 files changed, 658 insertions(+), 17 deletions(-)
>  create mode 100644 arch/m68k/configs/virt_defconfig
>  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 arch/m68k/virt/timer.c
> 

As 5.12 has been released, is this possible to consider having this new machine in the next release?

All changes are contained under arch/m68k and protected by the CONFIG_VIRT flag. This should not
have any impact on the other m68k machines. In any case, I'll be able to maintain the machine and
fix any problem.

Thanks,
Laurent

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/2] m68k: introduce a virtual m68k machine
  2021-03-23 22:14 ` [PATCH 2/2] m68k: introduce a virtual m68k machine Laurent Vivier
  2021-04-27 17:20   ` Laurent Vivier
@ 2021-04-28 12:04   ` Geert Uytterhoeven
  2021-04-28 23:06     ` Josh Juran
  1 sibling, 1 reply; 11+ messages in thread
From: Geert Uytterhoeven @ 2021-04-28 12:04 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: Linux Kernel Mailing List, linux-m68k, linux-rtc,
	Alessandro Zummo, Alexandre Belloni

Hi Laurent,

On Tue, Mar 23, 2021 at 11:14 PM Laurent Vivier <laurent@vivier.eu> wrote:
> This machine allows to have up to 3.2 GiB and 128 Virtio devices.
>
> It is based on android goldfish devices.
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>

Thanks for your patch!

> --- a/arch/m68k/Kconfig.machine
> +++ b/arch/m68k/Kconfig.machine
> @@ -145,6 +145,23 @@ config SUN3
>
>           If you don't want to compile a kernel exclusively for a Sun 3, say N.
>
> +config VIRT
> +       bool "Virtual M68k Machine support"
> +       depends on MMU
> +       select MMU_MOTOROLA if MMU
> +       select M68040
> +       select LEGACY_TIMER_TICK

Can we avoid selecting this for a new platform?

> +       select VIRTIO_MENU

VIRTIO_MENU defaults to y (should it?), so this can be dropped.

> +       select VIRTIO_MMIO
> +       select GOLDFISH
> +       select TTY
> +       select GOLDFISH_TTY
> +       select RTC_CLASS
> +       select RTC_DRV_GOLDFISH

Please sort the selects.

> +       help
> +         This options enable a pure virtual machine based on m68k,
> +         VIRTIO MMIO devices and GOLDFISH interfaces (TTY, RTC, PIC)
> +
>  config PILOT
>         bool
>
> diff --git a/arch/m68k/configs/virt_defconfig b/arch/m68k/configs/virt_defconfig
> new file mode 100644
> index 000000000000..51842acd5434
> --- /dev/null
> +++ b/arch/m68k/configs/virt_defconfig
> @@ -0,0 +1,93 @@

This is not a minimal config, please run "make savedefconfig"
and replace by the generated defconfig.

Please also add CONFIG_LOCALVERSION="-virt", for consistency with the
other configs.

> --- a/arch/m68k/include/asm/irq.h
> +++ b/arch/m68k/include/asm/irq.h
> @@ -12,7 +12,8 @@
>   */
>  #if defined(CONFIG_COLDFIRE)
>  #define NR_IRQS 256
> -#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
> +#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || \
> +      defined(CONFIG_SUN3X) || defined(CONFIG_VIRT)
>  #define NR_IRQS 200

Is this related to NUM_VIRT_SOURCES?

Yes it is:

        m68k_setup_irq_controller(&virt_irq_chip, handle_simple_irq, IRQ_USER,
                                  NUM_VIRT_SOURCES - IRQ_USER);

>  #elif defined(CONFIG_ATARI)
>  #define NR_IRQS 141

> --- a/arch/m68k/include/asm/setup.h
> +++ b/arch/m68k/include/asm/setup.h
> @@ -170,6 +180,20 @@ extern unsigned long m68k_machtype;
>  #  define MACH_TYPE (MACH_SUN3X)
>  #endif
>
> +#if !defined(CONFIG_VIRT)
> +#  define MACH_IS_VIRT (0)
> +#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \
> +       || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)                 \
> +       || defined(CONFIG_HP300) || defined(CONFIG_Q40)                        \
> +       || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                    \
> +       || defined(CONFIG_MAC)

Please move the MAC check between the ATARI and APOLLO checks.

> +#  define MACH_IS_VIRT (m68k_machtype == MACH_VIRT)
> +#else
> +#  define MACH_VIRTONLY

MACH_VIRT_ONLY (albeit unused)

> +#  define MACH_IS_VIRT (1)
> +#  define MACH_TYPE (MACH_VIRT)
> +#endif
> +
>  #ifndef MACH_TYPE
>  #  define MACH_TYPE (m68k_machtype)
>  #endif

> --- /dev/null
> +++ b/arch/m68k/include/asm/virt.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __ASM_VIRT_H
> +#define __ASM_VIRT_H
> +
> +#define NUM_VIRT_SOURCES 200
> +
> +struct virt_booter_device_data {
> +       unsigned long mmio;
> +       unsigned long irq;
> +};
> +
> +struct virt_booter_data {
> +       unsigned long qemu_version;
> +       struct virt_booter_device_data pic;
> +       struct virt_booter_device_data rtc;
> +       struct virt_booter_device_data tty;
> +       struct virt_booter_device_data ctrl;
> +       struct virt_booter_device_data virtio;
> +};
> +
> +extern struct virt_booter_data virt_bi_data;
> +
> +extern void __init virt_init_IRQ(void);
> +extern void __init virt_sched_init(void);
> +
> +#endif
> diff --git a/arch/m68k/include/uapi/asm/bootinfo-virt.h b/arch/m68k/include/uapi/asm/bootinfo-virt.h
> new file mode 100644
> index 000000000000..ab17fd9d200d
> --- /dev/null
> +++ b/arch/m68k/include/uapi/asm/bootinfo-virt.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * asm/bootinfo-virt.h -- Virtual-m68k-specific boot information definitions
> + */
> +
> +#ifndef _UAPI_ASM_M68K_BOOTINFO_VIRT_H
> +#define _UAPI_ASM_M68K_BOOTINFO_VIRT_H
> +
> +#define BI_VIRT_QEMU_VERSION   0x8000
> +#define BI_VIRT_GF_PIC_BASE    0x8001
> +#define BI_VIRT_GF_RTC_BASE    0x8002
> +#define BI_VIRT_GF_TTY_BASE    0x8003
> +#define BI_VIRT_VIRTIO_BASE    0x8004
> +#define BI_VIRT_CTRL_BASE       0x8005
> +
> +#define VIRT_BOOTI_VERSION     MK_BI_VERSION(2, 0)
> +
> +#endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */
> diff --git a/arch/m68k/include/uapi/asm/bootinfo.h b/arch/m68k/include/uapi/asm/bootinfo.h
> index 38d3140381fa..203d9cbf9630 100644
> --- a/arch/m68k/include/uapi/asm/bootinfo.h
> +++ b/arch/m68k/include/uapi/asm/bootinfo.h
> @@ -83,6 +83,7 @@ struct mem_info {
>  #define MACH_SUN3X             11
>  #define MACH_M54XX             12
>  #define MACH_M5441X            13
> +#define MACH_VIRT              14

All of the above are already in use in qemu, so I have to accept them ;-)

(Do I see a missed opportunity for adding DT support?...)

> --- a/arch/m68k/kernel/head.S
> +++ b/arch/m68k/kernel/head.S

> @@ -3186,6 +3203,13 @@ func_start       serial_putc,%d0/%d1/%a0/%a1
>  3:
>  #endif
>
> +#ifdef CONFIG_VIRT
> +       is_not_virt(L(serial_putc_done))

Please jump to a new label before the #endif, to make it easier to add
new platforms.

> +
> +       movel L(virt_gf_tty_base),%a1
> +       moveb %d0,%a1@(GF_PUT_CHAR)
> +#endif
> +
>  L(serial_putc_done):
>  func_return    serial_putc


> --- a/arch/m68k/mm/kmap.c
> +++ b/arch/m68k/mm/kmap.c

> @@ -293,18 +299,20 @@ EXPORT_SYMBOL(__ioremap);
>   */
>  void iounmap(void __iomem *addr)
>  {
> -#ifdef CONFIG_AMIGA
> -       if ((!MACH_IS_AMIGA) ||
> -           (((unsigned long)addr < 0x40000000) ||
> -            ((unsigned long)addr > 0x60000000)))
> -                       free_io_area((__force void *)addr);
> +#if defined(CONFIG_AMIGA) || defined(CONFIG_VIRT)

Please split in two separate #ifdefs,...

> +       if (MACH_IS_AMIGA &&
> +           ((unsigned long)addr >= 0x40000000) &&
> +           ((unsigned long)addr < 0x60000000))
> +               return;
> +       if (MACH_IS_VIRT && (unsigned long)addr >= 0xff000000)
> +               return;
>  #else

... drop the #else, ...

>  #ifdef CONFIG_COLDFIRE
>         if (cf_internalio(addr))
>                 return;
>  #endif
> -       free_io_area((__force void *)addr);
>  #endif

... and drop this #endif

> +       free_io_area((__force void *)addr);
>  }
>  EXPORT_SYMBOL(iounmap);

> --- /dev/null
> +++ b/arch/m68k/virt/config.c
> @@ -0,0 +1,118 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/serial_core.h>
> +
> +#include <asm/bootinfo.h>
> +#include <asm/bootinfo-virt.h>
> +#include <asm/byteorder.h>
> +

Please drop this blank line.

> +#include <asm/machdep.h>
> +#include <asm/virt.h>

> +static void virt_get_model(char *str)
> +{
> +       /* str is 80 characters long */
> +       sprintf(str, "QEMU Virtual M68K Machine (%d.%d.%d)",

Please use %u for unsigned numbers.

> +               (u8)(virt_bi_data.qemu_version >> 24),
> +               (u8)(virt_bi_data.qemu_version >> 16),
> +               (u8)(virt_bi_data.qemu_version >> 8));
> +}
> +
> +extern void show_registers(struct pt_regs *);

This is unused.

> +void __init config_virt(void)
> +{
> +       char earlycon[24];
> +
> +       if (!MACH_IS_VIRT)
> +               pr_err("ERROR: no Virtual M68k Machine, but %s called!!\n",
> +                      __func__);

This cannot happen, so please drop.

> diff --git a/arch/m68k/virt/ints.c b/arch/m68k/virt/ints.c
> new file mode 100644
> index 000000000000..aa94cb3b6d96
> --- /dev/null
> +++ b/arch/m68k/virt/ints.c
> @@ -0,0 +1,110 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/sched/debug.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/delay.h>
> +
> +#include <asm/virt.h>
> +#include <asm/irq.h>
> +#include <asm/hwtest.h>
> +#include <asm/irq_regs.h>

Please sort includes.

> +static void virt_irq_enable(struct irq_data *data)
> +{
> +       GF_PIC(data->irq).enable = 1 << GF_IRQ(data->irq);
> +}
> +
> +static void virt_irq_disable(struct irq_data *data)
> +{
> +       GF_PIC(data->irq).disable = 1 << GF_IRQ(data->irq);
> +}
> +
> +static unsigned int virt_irq_startup(struct irq_data *data)
> +{
> +       GF_PIC(data->irq).enable = 1 << GF_IRQ(data->irq);

Just call virt_irq_enable()?

> +       return 0;
> +}
> +
> +static void virt_irq_shutdown(struct irq_data *data)
> +{
> +       GF_PIC(data->irq).disable = 1 << GF_IRQ(data->irq);
> +}

This is identical to virt_irq_disable(), so you can just use the latter below.

> +
> +static volatile int in_nmi;

This is used inside virt_nmi_handler() only, so please move it there.
> +
> +irqreturn_t virt_nmi_handler(int irq, void *dev_id)
> +{
> +       if (in_nmi)
> +               return IRQ_HANDLED;
> +       in_nmi = 1;
> +
> +       pr_info("Non-Maskable Interrupt\n");

pr_warn()? Or another pr_*()?

> +       show_registers(get_irq_regs());
> +
> +       in_nmi = 0;
> +       return IRQ_HANDLED;
> +}
> +
> +static struct irq_chip virt_irq_chip = {
> +       .name           = "virt",
> +       .irq_enable     = virt_irq_enable,
> +       .irq_disable    = virt_irq_disable,
> +       .irq_startup    = virt_irq_startup,
> +       .irq_shutdown   = virt_irq_shutdown,

... = virt_irq_disable,

> +};
> +
> +static void goldfish_pic_irq(struct irq_desc *desc)
> +{
> +       u32 irq_pending, irq_bit;
> +       int irq_num;
> +
> +       irq_pending = gf_pic[desc->irq_data.irq - 1].irq_pending;
> +       irq_num = IRQ_USER + (desc->irq_data.irq - 1) * 32;
> +       irq_bit = 1;
> +
> +       do {
> +               if (irq_pending & irq_bit) {
> +                       generic_handle_irq(irq_num);
> +                       irq_pending &= ~irq_bit;
> +               }
> +               ++irq_num;
> +               irq_bit <<= 1;
> +       } while (irq_pending);

This can be simplified by shifting irq_pending instead of irq_bit:

    do {
            if (irq_pending & 1)
                    generic_handle_irq(irq_num);

            ++irq_num;
            irq_pending >>= 1;
    } while (irq_pending);

Unfortunately m68k doesn't have a single-instruction __ffs().

> +}
> +
> +void __init virt_init_IRQ(void)
> +{
> +       int i;
> +
> +       m68k_setup_irq_controller(&virt_irq_chip, handle_simple_irq, IRQ_USER,
> +                                 NUM_VIRT_SOURCES - IRQ_USER);
> +
> +       for (i = 0; i < 6; i++) {

6 = NUM_VIRT_SOURCES / 32?
If yes, what about the last 8 irqs?

> +               irq_set_chained_handler(virt_bi_data.pic.irq + i,
> +                                       goldfish_pic_irq);
> +       }

> --- /dev/null
> +++ b/arch/m68k/virt/platform.c
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <asm/virt.h>
> +#include <asm/irq.h>
> +
> +static struct platform_device virt_m68k_goldfish_tty = {
> +       .name = "goldfish_tty",
> +       .id = PLATFORM_DEVID_NONE,
> +       .num_resources = 2,
> +       .resource = (struct resource [2]) { },
> +};
> +static struct platform_device virt_m68k_goldfish_rtc = {
> +       .name = "goldfish_rtc",
> +       .id = PLATFORM_DEVID_NONE,
> +       .num_resources = 2,
> +       .resource = (struct resource [2]) { },
> +};
> +
> +#define VIRTIO_BUS_NB  128
> +static struct platform_device virt_m68k_virtio_mmio_device[VIRTIO_BUS_NB];
> +static struct resource virt_m68k_virtio_mmio_resources[VIRTIO_BUS_NB][2];

This consumes more than 40 KiB, even when unused.
While this doesn't matter much for a virtual machine with 3.2 GiB of
RAM, it does matter for running a multi-platform kernel on a real
machine.  Hence please allocate dynamically.

> +
> +static int __init virt_platform_init(void)
> +{
> +       int err;
> +       int i;
> +       extern unsigned long min_low_pfn;

Please use reverse Christmas tree declaration order.

> +
> +       if (!MACH_IS_VIRT)
> +               return -ENODEV;
> +
> +       min_low_pfn = 0;

Why is this needed?

> +
> +       virt_m68k_goldfish_tty.resource[0].flags = IORESOURCE_MEM;
> +       virt_m68k_goldfish_tty.resource[0].start = virt_bi_data.tty.mmio;
> +       virt_m68k_goldfish_tty.resource[0].end   = virt_bi_data.tty.mmio;
> +       virt_m68k_goldfish_tty.resource[1].flags = IORESOURCE_IRQ;
> +       virt_m68k_goldfish_tty.resource[1].start = virt_bi_data.tty.irq;
> +       virt_m68k_goldfish_tty.resource[1].end   = virt_bi_data.tty.irq;
> +
> +       err = platform_device_register(&virt_m68k_goldfish_tty);

You could probably save a little bit of memory by calling
platform_device_register_simple() instead.

> +       if (err)
> +               return err;
> +
> +       virt_m68k_goldfish_rtc.resource[0].flags = IORESOURCE_MEM;
> +       virt_m68k_goldfish_rtc.resource[0].start = virt_bi_data.rtc.mmio + 0x1000;
> +       virt_m68k_goldfish_rtc.resource[0].end   = virt_bi_data.rtc.mmio + 0x1fff;
> +       virt_m68k_goldfish_rtc.resource[1].flags = IORESOURCE_IRQ;
> +       virt_m68k_goldfish_rtc.resource[1].start = virt_bi_data.rtc.irq + 1;
> +       virt_m68k_goldfish_rtc.resource[1].end   = virt_bi_data.rtc.irq + 1;
> +       err = platform_device_register(&virt_m68k_goldfish_rtc);

Likewise.

> --- /dev/null
> +++ b/arch/m68k/virt/timer.c
> @@ -0,0 +1,91 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/interrupt.h>
> +#include <linux/ioport.h>
> +#include <linux/clocksource.h>
> +#include <asm/virt.h>
> +
> +struct goldfish_timer {
> +       u32 time_low;
> +       u32 time_high;
> +       u32 alarm_low;
> +       u32 alarm_high;
> +       u32 irq_enabled;
> +       u32 clear_alarm;
> +       u32 alarm_status;
> +       u32 clear_interrupt;
> +};
> +
> +#define gf_timer ((volatile struct goldfish_timer *)virt_bi_data.rtc.mmio)
> +
> +static u64 goldfish_timer_read(struct clocksource *cs)
> +{
> +       u64 ticks;
> +
> +       ticks = gf_timer->time_low;
> +       ticks += (u64)gf_timer->time_high << 32;

Can time_low wrap in between the two reads?

> +
> +       return ticks;
> +}
> +
> +static struct clocksource goldfish_timer = {
> +       .name           = "goldfish_timer",
> +       .rating         = 400,
> +       .read           = goldfish_timer_read,
> +       .mask           = CLOCKSOURCE_MASK(64),
> +       .flags          = 0,
> +       .max_idle_ns    = LONG_MAX,
> +};
> +
> +static irqreturn_t golfish_timer_handler(int irq, void *dev_id)
> +{
> +       unsigned long flags;
> +       u64 now;
> +
> +       local_irq_save(flags);

Do we need this in an interrupt handler?

> +       gf_timer->clear_interrupt = 1;
> +
> +       now = gf_timer->time_low;
> +       now += (u64)gf_timer->time_high << 32;

now = goldfish_timer_read();

> +
> +       legacy_timer_tick(1);
> +
> +       now += NSEC_PER_SEC / HZ;
> +       gf_timer->alarm_high = now >> 32;

upper_32_bits(now)

> +       gf_timer->alarm_low = (u32)now;

lower_32_bits(now)

> +       local_irq_restore(flags);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +void __init virt_sched_init(void)
> +{
> +       u64 now;
> +       static struct resource sched_res;

Please use reverse Christmas tree declaration order.

> +
> +       sched_res.name  = "goldfish_timer";
> +       sched_res.start = virt_bi_data.rtc.mmio;
> +       sched_res.end   = virt_bi_data.rtc.mmio + 0xfff;
> +
> +       if (request_resource(&iomem_resource, &sched_res)) {
> +               pr_err("Cannot allocate goldfish-timer resource\n");
> +               return;
> +       }
> +
> +       if (request_irq(virt_bi_data.rtc.irq, golfish_timer_handler, IRQF_TIMER,
> +                       "timer", NULL)) {
> +               pr_err("Couldn't register timer interrupt\n");
> +               return;
> +       }
> +
> +       now = gf_timer->time_low;
> +       now += (u64)gf_timer->time_high << 32;

now = goldfish_timer_read();

> +       now += NSEC_PER_SEC / HZ;
> +
> +       gf_timer->clear_interrupt = 1;
> +       gf_timer->alarm_high = now >> 32;

upper_32_bits(now)

> +       gf_timer->alarm_low = (u32)now;

lower_32_bits(now)

> +       gf_timer->irq_enabled = 1;
> +
> +       clocksource_register_hz(&goldfish_timer, NSEC_PER_SEC);
> +}

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/2] m68k: introduce a virtual m68k machine
  2021-04-27 17:20   ` Laurent Vivier
@ 2021-04-28 12:07     ` Geert Uytterhoeven
  2021-04-28 12:15       ` Laurent Vivier
  0 siblings, 1 reply; 11+ messages in thread
From: Geert Uytterhoeven @ 2021-04-28 12:07 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: Linux Kernel Mailing List, linux-m68k, linux-rtc,
	Alessandro Zummo, Alexandre Belloni

Hi Laurent,

On Tue, Apr 27, 2021 at 7:20 PM Laurent Vivier <laurent@vivier.eu> wrote:
> Le 23/03/2021 à 23:14, Laurent Vivier a écrit :
> > This machine allows to have up to 3.2 GiB and 128 Virtio devices.
> >
> > It is based on android goldfish devices.
> >
> > Signed-off-by: Laurent Vivier <laurent@vivier.eu>

> As 5.12 has been released, is this possible to consider having this new machine in the next release?
>
> All changes are contained under arch/m68k and protected by the CONFIG_VIRT flag. This should not
> have any impact on the other m68k machines. In any case, I'll be able to maintain the machine and
> fix any problem.

Thanks for the reminder!

Please accept my apologies: I had completely forgotten about your patch.
By the time it reappeared on my radar (due to Alexandre's reply), it was
already too late for v5.13.

I have tested and reviewed your patch, great work!
I'm confident this can make v5.14, with the small nits fixed.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/2] m68k: introduce a virtual m68k machine
  2021-04-28 12:07     ` Geert Uytterhoeven
@ 2021-04-28 12:15       ` Laurent Vivier
  0 siblings, 0 replies; 11+ messages in thread
From: Laurent Vivier @ 2021-04-28 12:15 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Kernel Mailing List, linux-m68k, linux-rtc,
	Alessandro Zummo, Alexandre Belloni

Le 28/04/2021 à 14:07, Geert Uytterhoeven a écrit :
> Hi Laurent,
> 
> On Tue, Apr 27, 2021 at 7:20 PM Laurent Vivier <laurent@vivier.eu> wrote:
>> Le 23/03/2021 à 23:14, Laurent Vivier a écrit :
>>> This machine allows to have up to 3.2 GiB and 128 Virtio devices.
>>>
>>> It is based on android goldfish devices.
>>>
>>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> 
>> As 5.12 has been released, is this possible to consider having this new machine in the next release?
>>
>> All changes are contained under arch/m68k and protected by the CONFIG_VIRT flag. This should not
>> have any impact on the other m68k machines. In any case, I'll be able to maintain the machine and
>> fix any problem.
> 
> Thanks for the reminder!
> 
> Please accept my apologies: I had completely forgotten about your patch.
> By the time it reappeared on my radar (due to Alexandre's reply), it was
> already too late for v5.13.

No problem.

> I have tested and reviewed your patch, great work!
> I'm confident this can make v5.14, with the small nits fixed.

Thank you for your review.

I will answer to some of your comments and update accordingly my patch.

Thanks,
Laurent

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/2] m68k: introduce a virtual m68k machine
  2021-04-28 12:04   ` Geert Uytterhoeven
@ 2021-04-28 23:06     ` Josh Juran
  2021-04-29  7:23       ` Geert Uytterhoeven
  0 siblings, 1 reply; 11+ messages in thread
From: Josh Juran @ 2021-04-28 23:06 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Laurent Vivier, Linux Kernel Mailing List, linux-m68k, linux-rtc,
	Alessandro Zummo, Alexandre Belloni

On Apr 28, 2021, at 8:04 AM, Geert Uytterhoeven <geert@linux-m68k.org> wrote:

> This can be simplified by shifting irq_pending instead of irq_bit:
> 
>    do {
>            if (irq_pending & 1)
>                    generic_handle_irq(irq_num);
> 
>            ++irq_num;
>            irq_pending >>= 1;
>    } while (irq_pending);
> 
> Unfortunately m68k doesn't have a single-instruction __ffs().

The 68000 and 68010 don't, but couldn't the 68020's BFFFO do the job?

Josh


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/2] m68k: introduce a virtual m68k machine
  2021-04-28 23:06     ` Josh Juran
@ 2021-04-29  7:23       ` Geert Uytterhoeven
  0 siblings, 0 replies; 11+ messages in thread
From: Geert Uytterhoeven @ 2021-04-29  7:23 UTC (permalink / raw)
  To: Josh Juran
  Cc: Laurent Vivier, Linux Kernel Mailing List, linux-m68k, linux-rtc,
	Alessandro Zummo, Alexandre Belloni

Hi Josh,

On Thu, Apr 29, 2021 at 1:06 AM Josh Juran <jjuran@gmail.com> wrote:
> On Apr 28, 2021, at 8:04 AM, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> > This can be simplified by shifting irq_pending instead of irq_bit:
> >
> >    do {
> >            if (irq_pending & 1)
> >                    generic_handle_irq(irq_num);
> >
> >            ++irq_num;
> >            irq_pending >>= 1;
> >    } while (irq_pending);
> >
> > Unfortunately m68k doesn't have a single-instruction __ffs().
>
> The 68000 and 68010 don't, but couldn't the 68020's BFFFO do the job?

I looked at the code generated by gcc for __builtin_ffs(), and while
it did use BFFFO, it needs several other instructions.

The same can be seen in arch/m68k/include/asm/bitops.h:

    static inline int ffs(int x)
    {
            int cnt;

            __asm__ ("bfffo %1{#0:#0},%0"
                    : "=d" (cnt)
                    : "dm" (x & -x));
            return 32 - cnt;
    }


Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, back to index

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-23 22:14 [PATCH 0/2] m68k: Add Virtual M68k Machine Laurent Vivier
2021-03-23 22:14 ` [PATCH 1/2] rtc: goldfish: remove dependency to OF Laurent Vivier
2021-03-23 22:14 ` [PATCH 2/2] m68k: introduce a virtual m68k machine Laurent Vivier
2021-04-27 17:20   ` Laurent Vivier
2021-04-28 12:07     ` Geert Uytterhoeven
2021-04-28 12:15       ` Laurent Vivier
2021-04-28 12:04   ` Geert Uytterhoeven
2021-04-28 23:06     ` Josh Juran
2021-04-29  7:23       ` Geert Uytterhoeven
2021-04-16 20:26 ` [PATCH 0/2] m68k: Add Virtual M68k Machine Alexandre Belloni
2021-04-16 20:34   ` Alexandre Belloni

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git
	git clone --mirror https://lore.kernel.org/lkml/8 lkml/git/8.git
	git clone --mirror https://lore.kernel.org/lkml/9 lkml/git/9.git
	git clone --mirror https://lore.kernel.org/lkml/10 lkml/git/10.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git