Skip to content

Commit badf2bd

Browse files
committed
lkl: add rumpun unikernel support for LKL
This commit offers an integration with rumprun unikernel. It is only tested with qemu-system-x86_64 but it potentially works fine with x86 baremetal machines as well as xen hypervior. An initial PCI device support is also implemented by relying on exposed virtual devices from hyperviros: virtio-net device is tested for the moment. The rumprun repository to support lkl build is not upstreamed yet - you can try with the following repository before it will be in. https://github.com/libos-nuse/rumprun Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
1 parent 75bae62 commit badf2bd

12 files changed

Lines changed: 450 additions & 2 deletions

File tree

arch/lkl/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ config RWSEM_GENERIC_SPINLOCK
6161
bool
6262
default y
6363

64+
config PCI
65+
bool "PCI support"
66+
select NO_GENERIC_PCI_IOPORT_MAP
67+
select GENERIC_PCI_IOMAP
68+
default y
69+
6470
source init/Kconfig
6571

6672
source net/Kconfig

arch/lkl/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ endif
6262

6363
core-y += arch/lkl/kernel/
6464
core-y += arch/lkl/mm/
65+
core-y += arch/lkl/drivers/
6566

6667
all: lkl.o
6768

arch/lkl/defconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,7 @@ CONFIG_DEBUG_INFO=y
9494
CONFIG_DEBUG_INFO_REDUCED=y
9595
# CONFIG_ENABLE_WARN_DEPRECATED is not set
9696
# CONFIG_ENABLE_MUST_CHECK is not set
97+
CONFIG_PCI=y
98+
CONFIG_NET_CORE=y
99+
CONFIG_VIRTIO_PCI=y
100+
CONFIG_GENERIC_IOMAP=y

arch/lkl/drivers/Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
obj-y = rumpdev_pci.o
3+
4+
# need to build with
5+
librumpdev_linux_pci.a: ${RUMP_BMK_PCI_HYPERCALLS}
6+
rm -f $@
7+
$(AR) rc $@ ${RUMP_BMK_PCI_HYPERCALLS}
8+
9+
install: librumpdev_linux_pci.a
10+
install -D librumpdev_linux_pci.a ${DESTDIR}/lib/
11+
12+
13+
.PHONY: ${RUMP_BMK_PCI_HYPERCALLS}

arch/lkl/drivers/pci_user.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* Reused from src-netbsd/sys/rump/dev/lib/libpci/pci_user.h */
2+
/*
3+
* Possible userfeature macro flags:
4+
*
5+
* RUMPCOMP_USERFEATURE_PCI_DMAFREE:
6+
* Support free'ing DMA memory. If not, panic() when free() is called.
7+
*
8+
* RUMPCOMP_USERFEATURE_PCI_IOSPACE
9+
* Support for PCI I/O space. If yes, rumpcomp_pci_iospace_init()
10+
* must be provided.
11+
*/
12+
13+
14+
void *rumpcomp_pci_map(unsigned long addr, unsigned long len);
15+
int rumpcomp_pci_confread(unsigned int bus, unsigned int dev,
16+
unsigned int fun, int reg, unsigned int *value);
17+
int rumpcomp_pci_confwrite(unsigned int bus, unsigned int dev,
18+
unsigned int fun, int reg, unsigned int value);
19+
int rumpcomp_pci_irq_map(unsigned int bus, unsigned int device,
20+
unsigned int fun, int intrline, unsigned int cookie);
21+
void *rumpcomp_pci_irq_establish(unsigned int cookie,
22+
int (*handler)(void *), void *data);
23+
24+
/* XXX: needs work: support boundary-restricted allocations */
25+
int rumpcomp_pci_dmalloc(size_t size, size_t align,
26+
unsigned long *pap, unsigned long *vap);
27+
#ifdef RUMPCOMP_USERFEATURE_PCI_DMAFREE
28+
void rumpcomp_pci_dmafree(unsigned long mem, size_t size);
29+
#endif
30+
31+
struct rumpcomp_pci_dmaseg {
32+
unsigned long ds_pa;
33+
unsigned long ds_len;
34+
unsigned long ds_vacookie;
35+
};
36+
int rumpcomp_pci_dmamem_map(struct rumpcomp_pci_dmaseg *dss, size_t nseg,
37+
size_t totlen, void **vap);
38+
39+
unsigned long rumpcomp_pci_virt_to_mach(void *virt);
40+
41+
#ifdef RUMPCOMP_USERFEATURE_PCI_IOSPACE
42+
int rumpcomp_pci_iospace_init(void);
43+
#endif

arch/lkl/drivers/rumpdev_pci.c

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
/*
2+
* rumprun PCI access (reused from src-netbsd/.../rumpdev_pci.c)
3+
*/
4+
5+
/*
6+
* Copyright (c) 2013 Antti Kantee. All Rights Reserved.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions
10+
* are met:
11+
* 1. Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright
14+
* notice, this list of conditions and the following disclaimer in the
15+
* documentation and/or other materials provided with the distribution.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18+
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27+
* SUCH DAMAGE.
28+
*/
29+
30+
#include <linux/init.h>
31+
#include <linux/kernel.h>
32+
#include <linux/pci.h>
33+
#include <linux/slab.h>
34+
#include <linux/interrupt.h>
35+
#include <linux/types.h>
36+
#include <linux/io.h>
37+
#include <asm/host_ops.h>
38+
39+
#include "pci_user.h"
40+
41+
struct rump_pci_sysdata {
42+
int domain; /* PCI domain */
43+
};
44+
45+
/* stubs: should not called */
46+
int __weak rumpcomp_pci_confread(unsigned int bus, unsigned int dev,
47+
unsigned int fun,
48+
int reg, unsigned int *value)
49+
{
50+
return 0;
51+
}
52+
53+
int __weak rumpcomp_pci_confwrite(unsigned int bus, unsigned int dev,
54+
unsigned int fun,
55+
int reg, unsigned int value)
56+
{
57+
return 0;
58+
}
59+
60+
void * __weak rumpcomp_pci_map(unsigned long addr, unsigned long len)
61+
{
62+
return NULL;
63+
}
64+
65+
int __weak rumpcomp_pci_irq_map(unsigned int bus, unsigned int device,
66+
unsigned int fun,
67+
int intrline, unsigned int cookie)
68+
{
69+
return 0;
70+
}
71+
72+
void * __weak rumpcomp_pci_irq_establish(unsigned int cookie,
73+
int (*handler)(void *), void *data)
74+
{
75+
return NULL;
76+
}
77+
78+
void __iomem *__pci_ioport_map(struct pci_dev *dev,
79+
unsigned long port, unsigned int nr)
80+
{
81+
/* XXX: no care at the moment */
82+
return rumpcomp_pci_map(port, nr);
83+
}
84+
85+
/* from arch/x86/pci/common.c */
86+
void pcibios_fixup_bus(struct pci_bus *b)
87+
{
88+
pci_read_bridge_bases(b);
89+
}
90+
91+
/* from arch/x86/pci/i386.c */
92+
resource_size_t
93+
pcibios_align_resource(void *data, const struct resource *res,
94+
resource_size_t size, resource_size_t align)
95+
{
96+
return 0;
97+
}
98+
99+
/* from drivers/pci/access.c
100+
*
101+
* @bus: PCI bus to scan
102+
* @devfn: slot number to scan (must have zero function.)
103+
*/
104+
void *rump_pci_map_bus(struct pci_bus *bus, unsigned int devfn, int where)
105+
{
106+
unsigned long addr;
107+
108+
addr = (1 << 31) | (bus->number << 16) | (PCI_SLOT(devfn) << 11) |
109+
(PCI_FUNC(devfn) << 8) | (where & 0xfc);
110+
111+
/* FIXME: length? */
112+
return rumpcomp_pci_map(addr, 0);
113+
}
114+
115+
int rump_pci_generic_read(struct pci_bus *bus, unsigned int devfn,
116+
int where, int size, u32 *val)
117+
{
118+
119+
rumpcomp_pci_confread(bus->number, PCI_SLOT(devfn),
120+
PCI_FUNC(devfn), where, val);
121+
if (size <= 2)
122+
*val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
123+
124+
return PCIBIOS_SUCCESSFUL;
125+
}
126+
127+
int rump_pci_generic_write(struct pci_bus *bus, unsigned int devfn,
128+
int where, int size, u32 val)
129+
{
130+
u32 mask, tmp;
131+
132+
if (size == 4) {
133+
rumpcomp_pci_confwrite(bus->number, PCI_SLOT(devfn),
134+
PCI_FUNC(devfn), where, val);
135+
return PCIBIOS_SUCCESSFUL;
136+
}
137+
138+
mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
139+
140+
/* This brings the way much overhead though I picked this
141+
* code from access.c.. maybe should come up with single
142+
* write method to avoid that.
143+
*/
144+
145+
rumpcomp_pci_confread(bus->number, PCI_SLOT(devfn),
146+
PCI_FUNC(devfn), where, &tmp);
147+
tmp &= mask;
148+
tmp |= val << ((where & 0x3) * 8);
149+
150+
rumpcomp_pci_confwrite(bus->number, PCI_SLOT(devfn),
151+
PCI_FUNC(devfn), where, tmp);
152+
153+
return PCIBIOS_SUCCESSFUL;
154+
}
155+
156+
157+
#ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
158+
#include <dev/pci/pcireg.h>
159+
#include <dev/pci/pcivar.h>
160+
#include <dev/pci/pciidereg.h>
161+
#include <dev/pci/pciidevar.h>
162+
163+
void *
164+
pciide_machdep_compat_intr_establish(device_t dev,
165+
const struct pci_attach_args *pa, int chan,
166+
int (*func)(void *), void *arg)
167+
{
168+
pci_intr_handle_t ih;
169+
struct pci_attach_args mypa = *pa;
170+
171+
mypa.pa_intrline = PCIIDE_COMPAT_IRQ(chan);
172+
if (pci_intr_map(&mypa, &ih) != 0)
173+
return NULL;
174+
return rumpcomp_pci_irq_establish(ih, func, arg);
175+
}
176+
177+
__strong_alias(pciide_machdep_compat_intr_disestablish, pci_intr_disestablish);
178+
#endif /* __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH */
179+
180+
181+
/* from drivers/pci/xen-pcifront.c */
182+
static int pci_lib_claim_resource(struct pci_dev *dev, void *data)
183+
{
184+
int i;
185+
struct resource *r;
186+
187+
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
188+
r = &dev->resource[i];
189+
190+
if (!r->parent && r->start && r->flags) {
191+
dev_info(&dev->dev, "claiming resource %s/%d\n",
192+
pci_name(dev), i);
193+
if (pci_claim_resource(dev, i)) {
194+
dev_err(&dev->dev,
195+
"Could not claim resource %s/%d!",
196+
pci_name(dev), i);
197+
}
198+
}
199+
}
200+
201+
return 0;
202+
}
203+
204+
static int rump_trigger_irq(void *arg)
205+
{
206+
struct irq_data *data = arg;
207+
208+
lkl_trigger_irq(data->irq);
209+
return 0;
210+
}
211+
212+
int rump_pci_irq_request(struct irq_data *data)
213+
{
214+
int ret, int_irq;
215+
struct irq_desc *desc = irq_to_desc(data->irq);
216+
const char *name = desc->name ? desc->name : "null"; /* XXX */
217+
218+
static int intr[5] = {9, 10, 11, 14, 15};
219+
static int intnum;
220+
221+
/* setup IRQ */
222+
int_irq = lkl_get_free_irq(name);
223+
224+
ret = rumpcomp_pci_irq_map(0, 0, 0, intr[intnum++], int_irq);
225+
rumpcomp_pci_irq_establish(int_irq, rump_trigger_irq, data);
226+
227+
return 0;
228+
}
229+
230+
void rump_pci_irq_release(struct irq_data *data)
231+
{
232+
/* XXX: NOP */
233+
}
234+
235+
struct pci_ops rump_pci_root_ops = {
236+
.map_bus = rump_pci_map_bus,
237+
.read = rump_pci_generic_read,
238+
.write = rump_pci_generic_write,
239+
};
240+
241+
242+
static int __init rump_pci_init(void)
243+
{
244+
struct pci_bus *bus;
245+
struct rump_pci_sysdata *sd;
246+
int busnum = 0;
247+
248+
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
249+
if (!sd)
250+
return -1;
251+
252+
pr_info("PCI: root bus %02x: using default resources\n", busnum);
253+
bus = pci_scan_bus(busnum, &rump_pci_root_ops, sd);
254+
if (!bus) {
255+
kfree(sd);
256+
return -1;
257+
}
258+
pci_walk_bus(bus, pci_lib_claim_resource, NULL);
259+
pci_bus_add_devices(bus);
260+
261+
return 0;
262+
}
263+
subsys_initcall(rump_pci_init);

arch/lkl/include/asm/Kbuild

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ generic-y += current.h
1313
generic-y += delay.h
1414
generic-y += device.h
1515
generic-y += div64.h
16-
generic-y += dma.h
1716
generic-y += emergency-restart.h
1817
generic-y += errno.h
1918
generic-y += exec.h
@@ -39,7 +38,7 @@ generic-y += msgbuf.h
3938
generic-y += page.h
4039
generic-y += param.h
4140
generic-y += parport.h
42-
generic-y += pci.h
41+
generic-y += pci_iomap.h
4342
generic-y += percpu.h
4443
generic-y += pgalloc.h
4544
generic-y += poll.h

arch/lkl/include/asm/dma.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef _ASM_LKL_DMA_H
2+
#define _ASM_LKL_DMA_H
3+
4+
#include <asm-generic/dma.h>
5+
6+
#ifdef CONFIG_PCI
7+
extern int isa_dma_bridge_buggy;
8+
#else
9+
#define isa_dma_bridge_buggy (0)
10+
#endif
11+
12+
#endif /* _ASM_LKL_DMA_H */

arch/lkl/include/asm/pci.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef _ASM_LKL_PCI_H
2+
#define _ASM_LKL_PCI_H
3+
4+
#include <asm-generic/pci.h>
5+
6+
# define pcibios_assign_all_busses() 0
7+
#define PCIBIOS_MIN_IO 0x1000
8+
#define PCIBIOS_MIN_MEM 0x10000000
9+
10+
#endif /* _ASM_LKL_PCI_H */

0 commit comments

Comments
 (0)