Skip to content

Commit 0815d5c

Browse files
committed
Merge tag 'for-linus-6.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen updates from Juergen Gross: - Xen event channel handling fix for a regression with a rare kernel config and some added hardening - better support of running Xen dom0 in PVH mode - a cleanup for the xen grant-dma-iommu driver * tag 'for-linus-6.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/events: increment refcnt only if event channel is refcounted xen/evtchn: avoid WARN() when unbinding an event channel x86/xen: attempt to inflate the memory balloon on PVH xen/grant-dma-iommu: Convert to platform remove callback returning void
2 parents b3603fc + d277f9d commit 0815d5c

File tree

10 files changed

+143
-59
lines changed

10 files changed

+143
-59
lines changed

arch/x86/include/asm/xen/hypervisor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ void xen_arch_unregister_cpu(int num);
6262
#ifdef CONFIG_PVH
6363
void __init xen_pvh_init(struct boot_params *boot_params);
6464
void __init mem_map_via_hcall(struct boot_params *boot_params_p);
65+
#ifdef CONFIG_XEN_PVH
66+
void __init xen_reserve_extra_memory(struct boot_params *bootp);
67+
#else
68+
static inline void xen_reserve_extra_memory(struct boot_params *bootp) { }
69+
#endif
6570
#endif
6671

6772
/* Lazy mode for batching updates / context switch */

arch/x86/platform/pvh/enlighten.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ static void __init init_pvh_bootparams(bool xen_guest)
7575
} else
7676
xen_raw_printk("Warning: Can fit ISA range into e820\n");
7777

78+
if (xen_guest)
79+
xen_reserve_extra_memory(&pvh_bootparams);
80+
7881
pvh_bootparams.hdr.cmd_line_ptr =
7982
pvh_start_info.cmdline_paddr;
8083

arch/x86/xen/enlighten.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/console.h>
77
#include <linux/cpu.h>
88
#include <linux/kexec.h>
9+
#include <linux/memblock.h>
910
#include <linux/slab.h>
1011
#include <linux/panic_notifier.h>
1112

@@ -350,3 +351,34 @@ void xen_arch_unregister_cpu(int num)
350351
}
351352
EXPORT_SYMBOL(xen_arch_unregister_cpu);
352353
#endif
354+
355+
/* Amount of extra memory space we add to the e820 ranges */
356+
struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
357+
358+
void __init xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns)
359+
{
360+
unsigned int i;
361+
362+
/*
363+
* No need to check for zero size, should happen rarely and will only
364+
* write a new entry regarded to be unused due to zero size.
365+
*/
366+
for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
367+
/* Add new region. */
368+
if (xen_extra_mem[i].n_pfns == 0) {
369+
xen_extra_mem[i].start_pfn = start_pfn;
370+
xen_extra_mem[i].n_pfns = n_pfns;
371+
break;
372+
}
373+
/* Append to existing region. */
374+
if (xen_extra_mem[i].start_pfn + xen_extra_mem[i].n_pfns ==
375+
start_pfn) {
376+
xen_extra_mem[i].n_pfns += n_pfns;
377+
break;
378+
}
379+
}
380+
if (i == XEN_EXTRA_MEM_MAX_REGIONS)
381+
printk(KERN_WARNING "Warning: not enough extra memory regions\n");
382+
383+
memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns));
384+
}

arch/x86/xen/enlighten_pvh.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/acpi.h>
33
#include <linux/export.h>
4+
#include <linux/mm.h>
45

56
#include <xen/hvc-console.h>
67

@@ -73,3 +74,70 @@ void __init mem_map_via_hcall(struct boot_params *boot_params_p)
7374
}
7475
boot_params_p->e820_entries = memmap.nr_entries;
7576
}
77+
78+
/*
79+
* Reserve e820 UNUSABLE regions to inflate the memory balloon.
80+
*
81+
* On PVH dom0 the host memory map is used, RAM regions available to dom0 are
82+
* located as the same place as in the native memory map, but since dom0 gets
83+
* less memory than the total amount of host RAM the ranges that can't be
84+
* populated are converted from RAM -> UNUSABLE. Use such regions (up to the
85+
* ratio signaled in EXTRA_MEM_RATIO) in order to inflate the balloon driver at
86+
* boot. Doing so prevents the guest (even if just temporary) from using holes
87+
* in the memory map in order to map grants or foreign addresses, and
88+
* hopefully limits the risk of a clash with a device MMIO region. Ideally the
89+
* hypervisor should notify us which memory ranges are suitable for creating
90+
* foreign mappings, but that's not yet implemented.
91+
*/
92+
void __init xen_reserve_extra_memory(struct boot_params *bootp)
93+
{
94+
unsigned int i, ram_pages = 0, extra_pages;
95+
96+
for (i = 0; i < bootp->e820_entries; i++) {
97+
struct boot_e820_entry *e = &bootp->e820_table[i];
98+
99+
if (e->type != E820_TYPE_RAM)
100+
continue;
101+
ram_pages += PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr);
102+
}
103+
104+
/* Max amount of extra memory. */
105+
extra_pages = EXTRA_MEM_RATIO * ram_pages;
106+
107+
/*
108+
* Convert UNUSABLE ranges to RAM and reserve them for foreign mapping
109+
* purposes.
110+
*/
111+
for (i = 0; i < bootp->e820_entries && extra_pages; i++) {
112+
struct boot_e820_entry *e = &bootp->e820_table[i];
113+
unsigned long pages;
114+
115+
if (e->type != E820_TYPE_UNUSABLE)
116+
continue;
117+
118+
pages = min(extra_pages,
119+
PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr));
120+
121+
if (pages != (PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr))) {
122+
struct boot_e820_entry *next;
123+
124+
if (bootp->e820_entries ==
125+
ARRAY_SIZE(bootp->e820_table))
126+
/* No space left to split - skip region. */
127+
continue;
128+
129+
/* Split entry. */
130+
next = e + 1;
131+
memmove(next, e,
132+
(bootp->e820_entries - i) * sizeof(*e));
133+
bootp->e820_entries++;
134+
next->addr = PAGE_ALIGN(e->addr) + PFN_PHYS(pages);
135+
e->size = next->addr - e->addr;
136+
next->size -= e->size;
137+
}
138+
e->type = E820_TYPE_RAM;
139+
extra_pages -= pages;
140+
141+
xen_add_extra_mem(PFN_UP(e->addr), pages);
142+
}
143+
}

arch/x86/xen/setup.c

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@
3838

3939
#define GB(x) ((uint64_t)(x) * 1024 * 1024 * 1024)
4040

41-
/* Amount of extra memory space we add to the e820 ranges */
42-
struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
43-
4441
/* Number of pages released from the initial allocation. */
4542
unsigned long xen_released_pages;
4643

@@ -64,18 +61,6 @@ static struct {
6461
} xen_remap_buf __initdata __aligned(PAGE_SIZE);
6562
static unsigned long xen_remap_mfn __initdata = INVALID_P2M_ENTRY;
6663

67-
/*
68-
* The maximum amount of extra memory compared to the base size. The
69-
* main scaling factor is the size of struct page. At extreme ratios
70-
* of base:extra, all the base memory can be filled with page
71-
* structures for the extra memory, leaving no space for anything
72-
* else.
73-
*
74-
* 10x seems like a reasonable balance between scaling flexibility and
75-
* leaving a practically usable system.
76-
*/
77-
#define EXTRA_MEM_RATIO (10)
78-
7964
static bool xen_512gb_limit __initdata = IS_ENABLED(CONFIG_XEN_512GB);
8065

8166
static void __init xen_parse_512gb(void)
@@ -96,35 +81,6 @@ static void __init xen_parse_512gb(void)
9681
xen_512gb_limit = val;
9782
}
9883

99-
static void __init xen_add_extra_mem(unsigned long start_pfn,
100-
unsigned long n_pfns)
101-
{
102-
int i;
103-
104-
/*
105-
* No need to check for zero size, should happen rarely and will only
106-
* write a new entry regarded to be unused due to zero size.
107-
*/
108-
for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
109-
/* Add new region. */
110-
if (xen_extra_mem[i].n_pfns == 0) {
111-
xen_extra_mem[i].start_pfn = start_pfn;
112-
xen_extra_mem[i].n_pfns = n_pfns;
113-
break;
114-
}
115-
/* Append to existing region. */
116-
if (xen_extra_mem[i].start_pfn + xen_extra_mem[i].n_pfns ==
117-
start_pfn) {
118-
xen_extra_mem[i].n_pfns += n_pfns;
119-
break;
120-
}
121-
}
122-
if (i == XEN_EXTRA_MEM_MAX_REGIONS)
123-
printk(KERN_WARNING "Warning: not enough extra memory regions\n");
124-
125-
memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns));
126-
}
127-
12884
static void __init xen_del_extra_mem(unsigned long start_pfn,
12985
unsigned long n_pfns)
13086
{

arch/x86/xen/xen-ops.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,18 @@ void xen_hvm_post_suspend(int suspend_cancelled);
163163
static inline void xen_hvm_post_suspend(int suspend_cancelled) {}
164164
#endif
165165

166+
/*
167+
* The maximum amount of extra memory compared to the base size. The
168+
* main scaling factor is the size of struct page. At extreme ratios
169+
* of base:extra, all the base memory can be filled with page
170+
* structures for the extra memory, leaving no space for anything
171+
* else.
172+
*
173+
* 10x seems like a reasonable balance between scaling flexibility and
174+
* leaving a practically usable system.
175+
*/
176+
#define EXTRA_MEM_RATIO (10)
177+
178+
void xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns);
179+
166180
#endif /* XEN_OPS_H */

drivers/xen/balloon.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,6 @@ EXPORT_SYMBOL(xen_free_ballooned_pages);
672672

673673
static void __init balloon_add_regions(void)
674674
{
675-
#if defined(CONFIG_XEN_PV)
676675
unsigned long start_pfn, pages;
677676
unsigned long pfn, extra_pfn_end;
678677
unsigned int i;
@@ -696,7 +695,6 @@ static void __init balloon_add_regions(void)
696695

697696
balloon_stats.total_pages += extra_pfn_end - start_pfn;
698697
}
699-
#endif
700698
}
701699

702700
static int __init balloon_init(void)

drivers/xen/events/events_base.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,7 @@ int xen_pirq_from_irq(unsigned irq)
11901190
EXPORT_SYMBOL_GPL(xen_pirq_from_irq);
11911191

11921192
static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip,
1193-
struct xenbus_device *dev)
1193+
struct xenbus_device *dev, bool shared)
11941194
{
11951195
int ret = -ENOMEM;
11961196
struct irq_info *info;
@@ -1224,7 +1224,8 @@ static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip,
12241224
*/
12251225
bind_evtchn_to_cpu(info, 0, false);
12261226
} else if (!WARN_ON(info->type != IRQT_EVTCHN)) {
1227-
info->refcnt++;
1227+
if (shared && !WARN_ON(info->refcnt < 0))
1228+
info->refcnt++;
12281229
}
12291230

12301231
ret = info->irq;
@@ -1237,13 +1238,13 @@ static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip,
12371238

12381239
int bind_evtchn_to_irq(evtchn_port_t evtchn)
12391240
{
1240-
return bind_evtchn_to_irq_chip(evtchn, &xen_dynamic_chip, NULL);
1241+
return bind_evtchn_to_irq_chip(evtchn, &xen_dynamic_chip, NULL, false);
12411242
}
12421243
EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
12431244

12441245
int bind_evtchn_to_irq_lateeoi(evtchn_port_t evtchn)
12451246
{
1246-
return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL);
1247+
return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL, false);
12471248
}
12481249
EXPORT_SYMBOL_GPL(bind_evtchn_to_irq_lateeoi);
12491250

@@ -1295,7 +1296,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
12951296

12961297
static int bind_interdomain_evtchn_to_irq_chip(struct xenbus_device *dev,
12971298
evtchn_port_t remote_port,
1298-
struct irq_chip *chip)
1299+
struct irq_chip *chip,
1300+
bool shared)
12991301
{
13001302
struct evtchn_bind_interdomain bind_interdomain;
13011303
int err;
@@ -1307,14 +1309,14 @@ static int bind_interdomain_evtchn_to_irq_chip(struct xenbus_device *dev,
13071309
&bind_interdomain);
13081310

13091311
return err ? : bind_evtchn_to_irq_chip(bind_interdomain.local_port,
1310-
chip, dev);
1312+
chip, dev, shared);
13111313
}
13121314

13131315
int bind_interdomain_evtchn_to_irq_lateeoi(struct xenbus_device *dev,
13141316
evtchn_port_t remote_port)
13151317
{
13161318
return bind_interdomain_evtchn_to_irq_chip(dev, remote_port,
1317-
&xen_lateeoi_chip);
1319+
&xen_lateeoi_chip, false);
13181320
}
13191321
EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irq_lateeoi);
13201322

@@ -1430,7 +1432,8 @@ static int bind_evtchn_to_irqhandler_chip(evtchn_port_t evtchn,
14301432
{
14311433
int irq, retval;
14321434

1433-
irq = bind_evtchn_to_irq_chip(evtchn, chip, NULL);
1435+
irq = bind_evtchn_to_irq_chip(evtchn, chip, NULL,
1436+
irqflags & IRQF_SHARED);
14341437
if (irq < 0)
14351438
return irq;
14361439
retval = request_irq(irq, handler, irqflags, devname, dev_id);
@@ -1471,7 +1474,8 @@ static int bind_interdomain_evtchn_to_irqhandler_chip(
14711474
{
14721475
int irq, retval;
14731476

1474-
irq = bind_interdomain_evtchn_to_irq_chip(dev, remote_port, chip);
1477+
irq = bind_interdomain_evtchn_to_irq_chip(dev, remote_port, chip,
1478+
irqflags & IRQF_SHARED);
14751479
if (irq < 0)
14761480
return irq;
14771481

drivers/xen/evtchn.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct user_evtchn {
8585
struct per_user_data *user;
8686
evtchn_port_t port;
8787
bool enabled;
88+
bool unbinding;
8889
};
8990

9091
static void evtchn_free_ring(evtchn_port_t *ring)
@@ -164,6 +165,10 @@ static irqreturn_t evtchn_interrupt(int irq, void *data)
164165
struct per_user_data *u = evtchn->user;
165166
unsigned int prod, cons;
166167

168+
/* Handler might be called when tearing down the IRQ. */
169+
if (evtchn->unbinding)
170+
return IRQ_HANDLED;
171+
167172
WARN(!evtchn->enabled,
168173
"Interrupt for port %u, but apparently not enabled; per-user %p\n",
169174
evtchn->port, u);
@@ -421,6 +426,7 @@ static void evtchn_unbind_from_user(struct per_user_data *u,
421426

422427
BUG_ON(irq < 0);
423428

429+
evtchn->unbinding = true;
424430
unbind_from_irqhandler(irq, evtchn);
425431

426432
del_evtchn(u, evtchn);

drivers/xen/grant-dma-iommu.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,12 @@ static int grant_dma_iommu_probe(struct platform_device *pdev)
5151
return 0;
5252
}
5353

54-
static int grant_dma_iommu_remove(struct platform_device *pdev)
54+
static void grant_dma_iommu_remove(struct platform_device *pdev)
5555
{
5656
struct grant_dma_iommu_device *mmu = platform_get_drvdata(pdev);
5757

5858
platform_set_drvdata(pdev, NULL);
5959
iommu_device_unregister(&mmu->iommu);
60-
61-
return 0;
6260
}
6361

6462
static struct platform_driver grant_dma_iommu_driver = {
@@ -67,7 +65,7 @@ static struct platform_driver grant_dma_iommu_driver = {
6765
.of_match_table = grant_dma_iommu_of_match,
6866
},
6967
.probe = grant_dma_iommu_probe,
70-
.remove = grant_dma_iommu_remove,
68+
.remove_new = grant_dma_iommu_remove,
7169
};
7270

7371
static int __init grant_dma_iommu_init(void)

0 commit comments

Comments
 (0)