lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 29 Jan 2022 20:29:10 +0100
From:   Geert Uytterhoeven <geert@...ux-m68k.org>
To:     Laurent Vivier <laurent@...ier.eu>
Cc:     Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
        Alessandro Zummo <a.zummo@...ertech.it>,
        Daniel Lezcano <daniel.lezcano@...aro.org>,
        Alexandre Belloni <alexandre.belloni@...tlin.com>,
        Thomas Gleixner <tglx@...utronix.de>,
        Stephen Boyd <sboyd@...nel.org>,
        linux-m68k <linux-m68k@...ts.linux-m68k.org>,
        linux-rtc@...r.kernel.org, Jiaxun Yang <jiaxun.yang@...goat.com>,
        Arnd Bergmann <arnd@...db.de>,
        John Stultz <john.stultz@...aro.org>
Subject: Re: [PATCH v13 5/5] m68k: introduce a virtual m68k machine

Hi Laurent,

On Sat, Jan 29, 2022 at 7:42 PM Laurent Vivier <laurent@...ier.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@...ier.eu>

Thanks for your patch!

> --- a/arch/m68k/Kconfig.machine
> +++ b/arch/m68k/Kconfig.machine
> @@ -149,6 +149,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 GENERIC_CLOCKEVENTS
> +       select M68040
> +       select MMU_MOTOROLA if MMU
> +       select RTC_CLASS
> +       select GOLDFISH
> +       select RTC_DRV_GOLDFISH
> +       select GOLDFISH_TIMER
> +       select GOLDFISH_TTY
> +       select TTY
> +       select VIRTIO_MMIO

Please sort alphabetically.

> +       help
> +         This options enable a pure virtual machine based on m68k,
> +         VIRTIO MMIO devices and GOLDFISH interfaces (TTY, RTC, PIC)
> +
>  config PILOT
>         bool
>

> --- /dev/null
> +++ b/arch/m68k/include/asm/virt.h
> @@ -0,0 +1,25 @@
> +/* 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;

Probably you want to make these explicitly sized (u32)?
Or perhaps mmio should be void __iomem *, to avoid some casts
(at expense of other casts)?

> +};
> +
> +struct virt_booter_data {
> +       unsigned long qemu_version;

u32?

> +       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);
> +
> +#endif

> --- a/arch/m68k/mm/kmap.c
> +++ b/arch/m68k/mm/kmap.c
> @@ -179,6 +179,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;
> @@ -292,18 +298,21 @@ 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);
> -#else
> +#if defined(CONFIG_AMIGA)

"#ifdef CONFIG_AMIGA" was fine

> +       if (MACH_IS_AMIGA &&
> +           ((unsigned long)addr >= 0x40000000) &&
> +           ((unsigned long)addr < 0x60000000))
> +               return;
> +#endif
> +#if defined(CONFIG_VIRT)

#ifdef CONFIG_VIRT

> +       if (MACH_IS_VIRT && (unsigned long)addr >= 0xff000000)
> +               return;
> +#endif
>  #ifdef CONFIG_COLDFIRE
>         if (cf_internalio(addr))
>                 return;
>  #endif
>         free_io_area((__force void *)addr);
> -#endif
>  }
>  EXPORT_SYMBOL(iounmap);
>

> --- /dev/null
> +++ b/arch/m68k/virt/config.c
> @@ -0,0 +1,130 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/serial_core.h>
> +#include <clocksource/timer-goldfish.h>
> +
> +#include <asm/bootinfo.h>
> +#include <asm/bootinfo-virt.h>
> +#include <asm/byteorder.h>
> +#include <asm/machdep.h>
> +#include <asm/virt.h>
> +#include <asm/config.h>
> +
> +struct virt_booter_data virt_bi_data;
> +
> +#define VIRT_CTRL_REG_FEATURES 0x00
> +#define VIRT_CTRL_REG_CMD      0x04
> +
> +static struct resource ctrlres;
> +
> +enum {
> +       CMD_NOOP,
> +       CMD_RESET,
> +       CMD_HALT,
> +       CMD_PANIC,
> +};
> +
> +static void virt_get_model(char *str)
> +{
> +       /* str is 80 characters long */
> +       sprintf(str, "QEMU Virtual M68K Machine (%u.%u.%u)",
> +               (u8)(virt_bi_data.qemu_version >> 24),
> +               (u8)(virt_bi_data.qemu_version >> 16),
> +               (u8)(virt_bi_data.qemu_version >> 8));
> +}
> +
> +static void virt_halt(void)
> +{
> +       void __iomem *base = (void *)virt_bi_data.ctrl.mmio;

"(void __iomem *)" everywhere, else sparse complains (make C=1)

> +
> +       iowrite32be(CMD_HALT, base + VIRT_CTRL_REG_CMD);
> +       local_irq_disable();
> +       while (1)
> +               ;
> +}

> --- /dev/null
> +++ b/arch/m68k/virt/ints.c
> @@ -0,0 +1,153 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/sched/debug.h>
> +#include <linux/types.h>
> +#include <linux/ioport.h>
> +
> +#include <asm/hwtest.h>
> +#include <asm/irq.h>
> +#include <asm/irq_regs.h>
> +#include <asm/virt.h>
> +
> +#define GFPIC_REG_IRQ_PENDING           0x04
> +#define GFPIC_REG_IRQ_DISABLE_ALL       0x08
> +#define GFPIC_REG_IRQ_DISABLE           0x0c
> +#define GFPIC_REG_IRQ_ENABLE            0x10
> +
> +extern void show_registers(struct pt_regs *regs);
> +
> +static struct resource picres[6];
> +static const char *picname[6] = {
> +       "goldfish_pic.0",
> +       "goldfish_pic.1",
> +       "goldfish_pic.2",
> +       "goldfish_pic.3",
> +       "goldfish_pic.4",
> +       "goldfish_pic.5"
> +};
> +
> +/*
> + * 6 goldfish-pic for CPU IRQ #1 to IRQ #6
> + * CPU IRQ #1 -> PIC #1
> + *               IRQ #1 to IRQ #31 -> unused
> + *               IRQ #32 -> goldfish-tty
> + * CPU IRQ #2 -> PIC #2
> + *               IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32
> + * CPU IRQ #3 -> PIC #3
> + *               IRQ #1 to IRQ #32 -> virtio-mmio from 33 to 64
> + * CPU IRQ #4 -> PIC #4
> + *               IRQ #1 to IRQ #32 -> virtio-mmio from 65 to 96
> + * CPU IRQ #5 -> PIC #5
> + *               IRQ #1 to IRQ #32 -> virtio-mmio from 97 to 128
> + * CPU IRQ #6 -> PIC #6
> + *               IRQ #1 -> goldfish-timer
> + *               IRQ #2 -> goldfish-rtc
> + *               IRQ #3 to IRQ #32 -> unused
> + * CPU IRQ #7 -> NMI
> + */
> +
> +static u32 gfpic_read(int pic, int reg)
> +{
> +       void __iomem *base = (void *)(virt_bi_data.pic.mmio + pic * 0x1000);

(void __iomem *)

> +
> +       return ioread32be(base + reg);
> +}
> +
> +static void gfpic_write(u32 value, int pic, int reg)
> +{
> +       void __iomem *base = (void *)(virt_bi_data.pic.mmio + pic * 0x1000);
> +
> +       iowrite32be(value, base + reg);
> +}
> +
> +#define GF_PIC(irq) ((irq - IRQ_USER) / 32)
> +#define GF_IRQ(irq) ((irq - IRQ_USER) % 32)
> +
> +static void virt_irq_enable(struct irq_data *data)
> +{
> +       gfpic_write(1 << GF_IRQ(data->irq), GF_PIC(data->irq),

"1U". Or perhaps "BIT(GF_IRQ(data->irq)"?

> +                   GFPIC_REG_IRQ_ENABLE);
> +}
> +
> +static void virt_irq_disable(struct irq_data *data)
> +{
> +       gfpic_write(1 << GF_IRQ(data->irq), GF_PIC(data->irq),

likewise

> +                   GFPIC_REG_IRQ_DISABLE);
> +}

void goldfish_pic_irq(struct irq_desc *desc)
> +{
> +       u32 irq_pending;
> +       int irq_num;

unsigned int

> +       int pic = desc->irq_data.irq - 1;

unsigned int

> +
> +       irq_pending = gfpic_read(pic, GFPIC_REG_IRQ_PENDING);
> +       irq_num = IRQ_USER + pic * 32;
> +
> +       do {
> +               if (irq_pending & 1)
> +                       generic_handle_irq(irq_num);
> +               ++irq_num;
> +               irq_pending >>= 1;
> +       } while (irq_pending);
> +}
> +
> +void __init virt_init_IRQ(void)
> +{
> +       int pic;

unsigned int i

> +
> +       m68k_setup_irq_controller(&virt_irq_chip, handle_simple_irq, IRQ_USER,
> +                                 NUM_VIRT_SOURCES - IRQ_USER);
> +
> +       for (pic = 0; pic < 6; pic++) {
> +
> +               picres[pic] = (struct resource)
> +                   DEFINE_RES_MEM_NAMED(virt_bi_data.pic.mmio + pic * 0x1000,
> +                                        0x1000, picname[pic]);
> +               if (request_resource(&iomem_resource, &picres[pic])) {
> +                       pr_err("Cannot allocate %s resource\n", picname[pic]);
> +                       return;
> +               }
> +
> +               irq_set_chained_handler(virt_bi_data.pic.irq + pic,
> +                                       goldfish_pic_irq);
> +       }
> +
> +       if (request_irq(IRQ_AUTO_7, virt_nmi_handler, 0, "NMI",
> +                       virt_nmi_handler))
> +               pr_err("Couldn't register NMI\n");
> +}

> --- /dev/null
> +++ b/arch/m68k/virt/platform.c
> @@ -0,0 +1,72 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <linux/memblock.h>
> +#include <asm/virt.h>
> +#include <asm/irq.h>
> +
> +#define VIRTIO_BUS_NB  128
> +
> +static int __init virt_virtio_init(int id)

unsigned int id

> +{
> +       const struct resource res[] = {
> +               DEFINE_RES_MEM(virt_bi_data.virtio.mmio + id * 0x200, 0x200),
> +               DEFINE_RES_IRQ(virt_bi_data.virtio.irq + id),
> +       };
> +       struct platform_device *pdev;
> +
> +       pdev = platform_device_register_simple("virtio-mmio", id,
> +                                              res, ARRAY_SIZE(res));
> +       if (IS_ERR(pdev))
> +               return PTR_ERR(pdev);
> +
> +       return 0;
> +}
> +
> +static int __init virt_platform_init(void)
> +{
> +       const struct resource goldfish_tty_res[] = {
> +               DEFINE_RES_MEM(virt_bi_data.tty.mmio, 1),
> +               DEFINE_RES_IRQ(virt_bi_data.tty.irq),
> +       };
> +       /* this is the second gf-rtc, the first one is used by the scheduler */
> +       const struct resource goldfish_rtc_res[] = {
> +               DEFINE_RES_MEM(virt_bi_data.rtc.mmio + 0x1000, 0x1000),
> +               DEFINE_RES_IRQ(virt_bi_data.rtc.irq + 1),
> +       };
> +       struct platform_device *pdev;
> +       int i;

unsigned int

> +
> +       if (!MACH_IS_VIRT)
> +               return -ENODEV;
> +
> +       /* We need this to have DMA'able memory provided to goldfish-tty */
> +       min_low_pfn = 0;
> +
> +       pdev = platform_device_register_simple("goldfish_tty",
> +                                              PLATFORM_DEVID_NONE,
> +                                              goldfish_tty_res,
> +                                              ARRAY_SIZE(goldfish_tty_res));
> +       if (IS_ERR(pdev))
> +               return PTR_ERR(pdev);
> +
> +       pdev = platform_device_register_simple("goldfish_rtc",
> +                                              PLATFORM_DEVID_NONE,
> +                                              goldfish_rtc_res,
> +                                              ARRAY_SIZE(goldfish_rtc_res));
> +       if (IS_ERR(pdev))
> +               return PTR_ERR(pdev);
> +
> +       for (i = 0; i < VIRTIO_BUS_NB; i++) {
> +               int err;
> +
> +               err = virt_virtio_init(i);
> +               if (err)
> +                       return err;
> +       }
> +
> +       return 0;
> +}

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@...ux-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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ