* Re: [linux-lvm] LVM mapper and device names
From: Martin Schröder @ 2009-01-03 18:35 UTC (permalink / raw)
To: LVM general discussion and development
In-Reply-To: <20090103182852.GG11060@agk.fab.redhat.com>
2009/1/3 Alasdair G Kergon <agk@redhat.com>:
>> When I now have a mounted filesystem, how can I
>> determine reliably which is the original lv I've used ?
>
> lvs -o vg_name,name /dev/mapper/datavg-work
Volume group "mapper" not found
> sudo /sbin/lvs --version
LVM version: 2.02.13 (2006-10-27)
Library version: 1.02.12 (2006-10-13)
Driver version: 4.7.0
Best
Martin
^ permalink raw reply
* Re: Corrupt data - RAID sata_sil 3114 chip
From: Robert Hancock @ 2009-01-03 18:31 UTC (permalink / raw)
To: linux-ide; +Cc: debian-user, linux-raid
In-Reply-To: <20090103162046.GA29292@lanczos.q-leap.de>
Bernd Schubert wrote:
> On Sat, Jan 03, 2009 at 01:39:36PM +0000, Alan Cox wrote:
>> On Fri, 2 Jan 2009 22:30:07 +0100
>> Bernd Schubert <bs@q-leap.de> wrote:
>>
>>> Hello Bengt,
>>>
>>> sil3114 is known to cause data corruption with some disks.
>> News to me. There are a few people with lots of SI and other devices
>
> No no, you just forgot about it, since you even reviewed the patches ;)
>
> http://lkml.org/lkml/2007/10/11/137
And Jeff explained why they were not merged:
http://lkml.org/lkml/2007/10/11/166
All the patch does is try to reduce the speed impact of the workaround.
But as was pointed out, they don't reliably solve the problem the
workaround is trying to fix, and besides, the workaround is already not
applied to SiI3114 at all, as it is apparently not applicable on that
controller (only 3112).
>
>> jammed into the same mainboard who had problems but that doesn't appear
>> to be an SI problem as far as I can tell.
>>
>> There are some incompatibilities between certain silicon image chips and
>> Nvidia chipsets needing BIOS workarounds according to the errata docs.
Do you have details of these Alan?
>
> Well, I already posted the the links to the discussion we had in the past.
> The corruption issue is easily reproducible on Tyan S2882 with AMD-8111,
> SiI 3114 and ST3250820AS disks. This is on a compute cluster, and we run into
> the problem, when a few ST3200822AS failed and got replaced by newer 250GB
> disks. The 200GB ST3200822AS work perfectly fine, while the 250GB ST3250820AS
> disks cause data corrution.
>
> Presently the cluster is empty, so if you want do help me, your help to
> properly solve the issue would be highly appreciated (*).
>
>
> Cheers,
> Bernd
>
> PS: The patches I posted work fine on these systems, but they are not upstream
> and I really would prefer to find a way in vanilla linux to prevent this
> data corruption.
Some people have tried turning on the slow_down option or adding their
drive to the mod15 blacklist and found that problems went away, but that
in no way implies that their setup actually needs this workaround, only
that it slows down the IO enough that the problem no longer shows up.
It's a big hammer that can cover up all kinds of other issues and has
confused a lot of people into thinking the mod15write problem is bigger
than it actually is.
>
> PPS: Its a bit funny with this cluster, since it is located at my university
> group and I did and do many calculations on it myself. But presently I work
> for the company we bought it from and which is responsible to maintain it... ;)
^ permalink raw reply
* gitweb config with some public, some basic-authenticated repos
From: Matt McCutchen @ 2009-01-03 18:29 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <200901022033.18041.jnareb@gmail.com>
This thread's topic has moved from a proposed patch to how I should
configure my gitweb, so I'm updating the subject. As a review: I have
several public repos and several basic-authentication realms, each of
which requires a single user and contains a single repo (some realms
might contain multiple repos in the future). Each request has its
authorization checked by the Web server before it reaches gitweb, so my
main concern here is to avoid publicly disclosing the private repos'
paths, authors, and descriptions in the main project list.
On Fri, 2009-01-02 at 20:33 +0100, Jakub Narebski wrote:
> On Wed, 2008-12-24, Matt McCutchen wrote:
> > On Sat, 2008-12-13 at 14:02 -0800, Jakub Narebski wrote:
> > >
> > > Cannot you do this with new $export_auth_hook gitweb configuration
> > > variable, added by Alexander Gavrilov in
> > > dd7f5f1 (gitweb: Add a per-repository authorization hook.)
> > > It is used in check_export_ok subroutine, and is is checked also when
> > > getting list of project from file
> > >
> > > From gitweb/INSTALL
> [...]
> > > For example, if you use mod_perl to run the script, and have dumb
> > > http protocol authentication configured for your repositories, you
> > > can use the following hook to allow access only if the user is
> > > authorized to read the files:
> [...]
>
> > $export_auth_hook would work, and it would have the nice (but not
> > essential) feature of including private projects in the list shown to
> > suitably authenticated users. The only problem is that my Web host
> > doesn't support mod_perl. Is there a practical way to accomplish the
> > same thing as the above example in a CGI script? I would like to avoid
> > reimplementing Apache authentication-checking functionality if at all
> > possible.
>
> I know it is written that the example code is for mod_perl, but I
> don't think it is mod_perl specific; have you checked if it works
> for you? I assume that you use Apache, and have Apache Perl bindings
> installed...
I'm quite sure that the code is mod_perl specific. CGI scripts do get
some information from Apache via the environment, but interaction as
rich as executing Apache subrequests is only possible when the code is
running inside Apache via mod_perl. In fact, the Apache2::SubRequest
and Apache2::RequestUtil modules are part of mod_perl. To make sure I'm
not missing something, I tested the code on an Apache with mod_perl
enabled but gitweb executing as a CGI, and gitweb failed with the
following message:
Can't locate object method "request" via package
"Apache2::RequestUtil" at gitweb_config.perl line 60.
So this approach won't work for me.
But even ignoring this problem, I'm now thinking that trying to show
repos from *multiple authentication realms* in the main list according
to the user's credentials was a foolish idea. I don't want to ask
anonymous visitors to my main list for multiple logins they probably
don't have, yet I think it would be poor practice from a predictability
standpoint for the list to behave differently if the user volunteers
login information that hasn't been requested.
Instead, I will use a separate project list file for public repositories
and for each realm, and no export_auth_hook. This is simple and
requires no change to gitweb; my rewrite rule just has to tell my
gitweb_config via an environment variable which list to use. Comments
on this solution?
(Note: I'm no longer advocating the hidden-repos feature at this time,
but I think I will still advocate the forks-and-strict-export bug fix
now that I have it written.)
--
Matt
^ permalink raw reply
* Re: [linux-lvm] LVM mapper and device names
From: Alasdair G Kergon @ 2009-01-03 18:28 UTC (permalink / raw)
To: LVM general discussion and development
In-Reply-To: <b08d3e870901030855i7d8f7d25x4dee43a6fc93a397@mail.gmail.com>
On Sat, Jan 03, 2009 at 05:55:37PM +0100, Markus Baertschi wrote:
> /dev/mapper/datavg-work on /work type jfs (rw)
> When I now have a mounted filesystem, how can I
> determine reliably which is the original lv I've used ?
lvs -o vg_name,name /dev/mapper/datavg-work
Alasdair
--
agk@redhat.com
^ permalink raw reply
* Re: [PATCH] libudev: device - add devtype support
From: Marcel Holtmann @ 2009-01-03 18:28 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1230866522.14544.4.camel@californication>
Hi Kay,
> >> >>> >> > I was playing a little bit with libudev and I actually need the DEVTYPE
> >> >>> >> > from uevent for various tasks. Especially with USB and Bluetooth, the
> >> >>> >> > subsystem value is too generic.
> >> >>> >> >
> >> >>> >> > Attached is a patch that implements udev_device_get_devtype() and also
> >> >>> >> > udev_device_get_parent_with_devtype(). Please double check that I did it
> >> >>> >> > the right way.
> >> >>> >>
> >> >>> >> Looks good. Applied.
> >> >>> >
> >> >>> > one minor thing that came to my mind is that DEVTYPE and subsystem are
> >> >>> > actually kinda coupled. So a DEVTYPE="host" has a different semantic for
> >> >>> > USB than for Bluetooth subsystem for example. Not sure if we actually
> >> >>> > care or just add a udev_device_get_parent_with_subsystem_devtype()
> >> >>> > function to give applications a choice if they wanna care.
> >> >>>
> >> >>> You mean replacing:
> >> >>> udev_device_get_parent_with_devtype(..., *devtype)
> >> >>> by:
> >> >>> udev_device_get_parent_with_subsystem_devtype(..., *subsystem, *devtype)
> >> >>> ?
> >> >>>
> >> >>> Sounds sensible, because in most cases you don't want to check for
> >> >>> parents of a different subsystem. As you are using it, want to send a
> >> >>> patch?
> >> >>
> >> >> I am thinking of keeping both. So just adding ...subsystem_devtype() and
> >> >> keeping also the original one. My reason for it is that in some case you
> >> >> already know the subsystem you are looking at (or don't care in). So no
> >> >> point in doing a lookup with two checks.
> >> >
> >> > We could make it accept NULL for the subsystem in that case?
> >>
> >> I guess, we should just have
> >> udev_device_get_parent_with_subsystem_devtype(), and drop the both
> >> other ones, and accept NULL as parameters, if you want to match only
> >> one. You are right that subsystem and devtype belong together, so we
> >> should probably reflect that in the API. Any problems with such
> >> change?
> >
> > I think that make sense. So I opted for allowing devtype being NULL
> > while subsystem is required. I tried to come up with a good reason why
> > you would look for devtype and not subsystem and couldn't find it right
> > now. The USB case is double information since they prefixed their
> > devtypes with "usb_", but that is really an USB subsystem problem. For
> > Bluetooth I am not doing this at all and neither does SCSI. In future no
> > subsystem should.
>
> Yeah, sounds all fine. Patches are applied.
you even fixed my typo. Just found that one a few minutes ago. Thanks :)
Regards
Marcel
^ permalink raw reply
* Re: USB / udev only work for root
From: Piter PUNK @ 2009-01-03 18:24 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <580562.39355.qm@web50706.mail.re2.yahoo.com>
Sarah Messer wrote:
> The problem is not present on an OpenSUSE 10.0 machine running identical code with straight libusb-0.1/pyusb
>
> /etc/udev/rules.d/55-libsane.rules contains the following lines (among many others):
>
> # ENV{DEVTYPE}="usb_device", NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0664", OWNER="root", GROUP="root"
>
> SUBSYSTEM="usb", ACTION="add|change", SYSFS{idVendor}="0699", SYSFS{idProduct}="0368", GROUP="usb", MODE="0664"
Change SYSFS to ATTRS.
Piter Punk
^ permalink raw reply
* Re: [linux-dvb] Kernel oops loading cx88 drivers when two WinTV-HVR4000 cards present
From: Thomas Keil @ 2009-01-03 18:18 UTC (permalink / raw)
To: linux-dvb
In-Reply-To: <495FA03F.7040208@datacrystal.de>
A little correction, the first oops is purely lirc-related.
Relevant is just the latter part:
> cx88_audio 0000:04:06.1: PCI INT A -> GSI 19 (level, low) -> IRQ
> 19
> cx88[0]: subsystem: 0070:6906, board: Hauppauge WinTV-HVR4000(Lite)
> DVB-S/S2 [card=69,autodetected], frontend(s):
> 1
> cx88[0]: TV tuner type -1, Radio tuner type
> -1
> tveeprom 1-0050: Hauppauge model 69100, rev B2C3, serial#
> 3247308
> tveeprom 1-0050: MAC address is
> 00-0D-FE-31-8C-CC
> tveeprom 1-0050: tuner model is Conexant CX24118A (idx 123, type
> 4)
> tveeprom 1-0050: TV standards ATSC/DVB Digital (eeprom
> 0x80)
> tveeprom 1-0050: audio processor is None (idx
> 0)
> tveeprom 1-0050: decoder processor is CX882 (idx
> 25)
> tveeprom 1-0050: has no radio, has IR receiver, has no IR
> transmitter
> cx88[0]: hauppauge eeprom:
> model=69100
> input: cx88 IR (Hauppauge WinTV-HVR400 as
> /class/input/input3
> cx88[0]/1: CX88x/0: ALSA support for cx2388x
> boards
> cx88_audio 0000:04:07.1: PCI INT A -> GSI 20 (level, low) -> IRQ
> 20
> allocation failed: out of vmalloc space - use vmalloc=<size> to increase
> size.
> cx88[1]: subsystem: 0070:6906, board: Hauppauge WinTV-HVR4000(Lite)
> DVB-S/S2 [card=69,autodetected], frontend(s):
> 1
> cx88[1]: TV tuner type -1, Radio tuner type
> -1
> BUG: unable to handle kernel paging request at
> 00200034
>
> IP: [<fd917277>]
> :cx88xx:cx88_shutdown+0xb/0x94
>
> *pde =
> 00000000
>
> Oops: 0002 [#2]
> SMP
>
> Modules linked in: tuner v4l2_common lirc_imon(+) lirc_dev cx88_alsa(+)
> cx88xx videodev v4l1_compat snd_hda_intel ir_common i2c_algo_bit
> videobuf_dvb dvb_core snd_pcm tveeprom videobuf_dma_sg videobuf_core
> snd_timer ehci_hcd snd btcx_risc soundcore snd_page_alloc i2c_viapro
> i2c_core uhci_hcd usbcore 8250_pnp 8250
> serial_core
>
>
> Pid: 959, comm: modprobe Tainted: G D (2.6.27-gentoo-r7 #1)
> EIP: 0060:[<fd917277>] EFLAGS: 00010202 CPU: 0
> EIP is at cx88_shutdown+0xb/0x94 [cx88xx]
> EAX: f7ba6800 EBX: ffffffff ECX: 00200034 EDX: 00000000
> ESI: f7ba6800 EDI: f7ba6cb0 EBP: f7ba6800 ESP: f7b6bdf8
> DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
> Process modprobe (pid: 959, ti=f7b6a000 task=f7b81ef0 task.ti=f7b6a000)
> Stack: fd917fb6 00000070 f7ba6810 fd916a4c fd920a1f f7ba6810 ffffffff
> ffffffff
> 00000004 f7b6be64 c02bc88d 0000000d f78fec00 00b6be64 00000039
> f7ba6bb8
> 0000000d 00000286 c02bc96b 0000000d 00000001 f7b6be64 00000286
> c01fb6bf
> Call
> Trace:
> [<fd917fb6>] cx88_reset+0x2d/0x186
> [cx88xx]
> [<fd916a4c>] cx88_core_create+0x393/0xac3
> [cx88xx]
> [<c02bc88d>]
> raw_pci_read+0x4d/0x55
> [<c02bc96b>]
> pci_read+0x1c/0x21
> [<c01fb6bf>]
> pci_bus_read_config_byte+0x4e/0x58
> [<c02bb057>]
> pcibios_set_master+0x1c/0x8d
> [<fd917406>] cx88_core_get+0x6e/0x9f
> [cx88xx]
> [<f98ae864>] cx88_audio_initdev+0x94/0x30f
> [cx88_alsa]
> [<c01f416f>]
> kobject_get+0xf/0x13
> [<c0255009>] __driver_attach+0x0/0x55
> [<c01ff34e>] pci_device_probe+0x36/0x57
> [<c0254f92>] driver_probe_device+0xb5/0x12c
> [<c0255040>] __driver_attach+0x37/0x55
> [<c02548d9>] bus_for_each_dev+0x34/0x56
> [<c0254e2d>] driver_attach+0x11/0x13
> [<c0255009>] __driver_attach+0x0/0x55
> [<c0254c2f>] bus_add_driver+0x8a/0x1a7
> [<c01f4193>] kset_find_obj+0x20/0x4a
> [<f98ae1e7>] cx88_audio_init+0x0/0x27 [cx88_alsa]
> [<c025521d>] driver_register+0x6d/0xc1
> [<c011e942>] printk+0x14/0x18
> [<f98ae1e7>] cx88_audio_init+0x0/0x27 [cx88_alsa]
> [<c01ff50d>] __pci_register_driver+0x3c/0x67
> [<c010111f>] _stext+0x37/0xfb
> [<c0116088>] enqueue_task+0xa/0x14
> [<c0118e6f>] try_to_wake_up+0x11c/0x125
> [<c013a8b4>] sys_init_module+0x87/0x176
> [<c0102d91>] sysenter_do_call+0x12/0x25
> [<c0350000>] rt_mutex_slowlock+0x213/0x3e1
> =======================
> Code: 41 0c 89 42 04 89 f0 8b 4c 24 1c 45 8d 34 08 3b 6c 24 20 0f 85 40
> ff ff ff 5b 89 f8 5e 5f 5d c3 8b 48 38 31 d2 81 c1 34 00 20 00 <89> 11
> 8b 48 38 81 c1 40 c0 31 00 89 11 8b 48 38 81 c1 40 c0 32
> EIP: [<fd917277>] cx88_shutdown+0xb/0x94 [cx88xx] SS:ESP 0068:f7b6bdf8
> ---[ end trace d1865b13e5b6eb16 ]---
>
>
Thomas
_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
^ permalink raw reply
* [RESEND][PATCH] Populate-on-demand patch series
From: George Dunlap @ 2009-01-03 18:16 UTC (permalink / raw)
To: xen-devel@lists.xensource.com
[-- Attachment #1: Type: text/plain, Size: 204 bytes --]
Apparently my word-wrap mangled some of the patches. Here they are,
as attachments.
Forgot one patch before: fix-audit.diff should be applied beforehand
to fix some of the p2m auditing logic.
-George
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 01-p2m-query-type.diff --]
[-- Type: text/x-diff; name=01-p2m-query-type.diff, Size: 6068 bytes --]
diff -r e9c8cd6c3de7 xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c Wed Nov 19 15:49:55 2008 +0000
+++ b/xen/arch/x86/mm/hap/p2m-ept.c Wed Nov 19 16:00:04 2008 +0000
@@ -274,7 +274,8 @@
}
/* Read ept p2m entries */
-static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t)
+static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
+ p2m_query_t q)
{
ept_entry_t *table =
map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
@@ -359,9 +360,10 @@
return content;
}
-static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t)
+static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t,
+ p2m_query_t q)
{
- return ept_get_entry(current->domain, gfn, t);
+ return ept_get_entry(current->domain, gfn, t, q);
}
void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
diff -r e9c8cd6c3de7 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Wed Nov 19 15:49:55 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Wed Nov 19 16:00:04 2008 +0000
@@ -345,7 +345,8 @@
}
static mfn_t
-p2m_gfn_to_mfn(struct domain *d, unsigned long gfn, p2m_type_t *t)
+p2m_gfn_to_mfn(struct domain *d, unsigned long gfn, p2m_type_t *t,
+ p2m_query_t q)
{
mfn_t mfn;
paddr_t addr = ((paddr_t)gfn) << PAGE_SHIFT;
@@ -436,7 +437,8 @@
}
/* Read the current domain's p2m table (through the linear mapping). */
-static mfn_t p2m_gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t)
+static mfn_t p2m_gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t,
+ p2m_query_t q)
{
mfn_t mfn = _mfn(INVALID_MFN);
p2m_type_t p2mt = p2m_mmio_dm;
diff -r e9c8cd6c3de7 xen/include/asm-x86/guest_pt.h
--- a/xen/include/asm-x86/guest_pt.h Wed Nov 19 15:49:55 2008 +0000
+++ b/xen/include/asm-x86/guest_pt.h Wed Nov 19 16:00:04 2008 +0000
@@ -49,7 +49,7 @@
/* Override gfn_to_mfn to work with gfn_t */
#undef gfn_to_mfn
-#define gfn_to_mfn(d, g, t) _gfn_to_mfn((d), gfn_x(g), (t))
+#define gfn_to_mfn(d, g, t) _gfn_to_mfn_type((d), gfn_x(g), (t), p2m_alloc)
/* Types of the guest's page tables and access functions for them */
diff -r e9c8cd6c3de7 xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Wed Nov 19 15:49:55 2008 +0000
+++ b/xen/include/asm-x86/p2m.h Wed Nov 19 16:00:04 2008 +0000
@@ -66,6 +66,12 @@
p2m_mmio_direct = 5, /* Read/write mapping of genuine MMIO area */
} p2m_type_t;
+typedef enum {
+ p2m_query = 0, /* Do not populate a PoD entries */
+ p2m_alloc = 1, /* Automatically populate PoD entries */
+ p2m_guest = 2, /* Guest demand-fault; implies alloc */
+} p2m_query_t;
+
/* We use bitmaps and maks to handle groups of types */
#define p2m_to_mask(_t) (1UL << (_t))
@@ -105,9 +111,11 @@
mfn_t mfn, unsigned int page_order,
p2m_type_t p2mt);
mfn_t (*get_entry )(struct domain *d, unsigned long gfn,
- p2m_type_t *p2mt);
+ p2m_type_t *p2mt,
+ p2m_query_t q);
mfn_t (*get_entry_current)(unsigned long gfn,
- p2m_type_t *p2mt);
+ p2m_type_t *p2mt,
+ p2m_query_t q);
void (*change_entry_type_global)(struct domain *d,
p2m_type_t ot,
p2m_type_t nt);
@@ -123,23 +131,26 @@
return (flags >> 9) & 0x7;
}
-/* Read the current domain's p2m table. */
-static inline mfn_t gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t)
+/* Read the current domain's p2m table. Do not populate PoD pages. */
+static inline mfn_t gfn_to_mfn_type_current(unsigned long gfn, p2m_type_t *t,
+ p2m_query_t q)
{
- return current->domain->arch.p2m->get_entry_current(gfn, t);
+ return current->domain->arch.p2m->get_entry_current(gfn, t, q);
}
-/* Read another domain's P2M table, mapping pages as we go */
+/* Read another domain's P2M table, mapping pages as we go.
+ * Do not populate PoD pages. */
static inline
-mfn_t gfn_to_mfn_foreign(struct domain *d, unsigned long gfn, p2m_type_t *t)
+mfn_t gfn_to_mfn_type_foreign(struct domain *d, unsigned long gfn, p2m_type_t *t,
+ p2m_query_t q)
{
- return d->arch.p2m->get_entry(d, gfn, t);
+ return d->arch.p2m->get_entry(d, gfn, t, q);
}
/* General conversion function from gfn to mfn */
-#define gfn_to_mfn(d, g, t) _gfn_to_mfn((d), (g), (t))
-static inline mfn_t _gfn_to_mfn(struct domain *d,
- unsigned long gfn, p2m_type_t *t)
+static inline mfn_t _gfn_to_mfn_type(struct domain *d,
+ unsigned long gfn, p2m_type_t *t,
+ p2m_query_t q)
{
if ( !paging_mode_translate(d) )
{
@@ -149,10 +160,17 @@
return _mfn(gfn);
}
if ( likely(current->domain == d) )
- return gfn_to_mfn_current(gfn, t);
+ return gfn_to_mfn_type_current(gfn, t, q);
else
- return gfn_to_mfn_foreign(d, gfn, t);
+ return gfn_to_mfn_type_foreign(d, gfn, t, q);
}
+
+#define gfn_to_mfn(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_alloc)
+#define gfn_to_mfn_query(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_query)
+#define gfn_to_mfn_guest(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_guest)
+
+#define gfn_to_mfn_current(g, t) gfn_to_mfn_type_current((g), (t), p2m_alloc)
+#define gfn_to_mfn_foreign(d, g, t) gfn_to_mfn_type_foreign((d), (g), (t), p2m_alloc)
/* Compatibility function exporting the old untyped interface */
static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 02-shadow-code-calls-p2m-query.diff --]
[-- Type: text/x-diff; name=02-shadow-code-calls-p2m-query.diff, Size: 10601 bytes --]
diff -r 65c24b33082a xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Wed Dec 17 12:59:28 2008 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c Wed Dec 17 12:59:50 2008 +0000
@@ -888,7 +888,7 @@
* If this GFN is emulated MMIO or marked as read-only, pass the fault
* to the mmio handler.
*/
- mfn = gfn_to_mfn_current(gfn, &p2mt);
+ mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
if ( (p2mt == p2m_mmio_dm) || (p2mt == p2m_ram_ro) )
{
if ( !handle_mmio() )
diff -r 65c24b33082a xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Wed Dec 17 12:59:28 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Dec 17 12:59:50 2008 +0000
@@ -2099,9 +2099,9 @@
mfn_t mfn;
p2m_type_t t;
- mfn = gfn_to_mfn(d, gfn, &t);
+ mfn = gfn_to_mfn_guest(d, gfn, &t);
- /* There are two legitimate reasons for taking an EPT violation.
+ /* There are three legitimate reasons for taking an EPT violation.
* One is a guest access to MMIO space. */
if ( gla_validity == EPT_GLA_VALIDITY_MATCH && p2m_is_mmio(t) )
{
@@ -2109,15 +2109,18 @@
return;
}
- /* The other is log-dirty mode, writing to a read-only page */
- if ( paging_mode_log_dirty(d)
- && (gla_validity == EPT_GLA_VALIDITY_MATCH
- || gla_validity == EPT_GLA_VALIDITY_GPT_WALK)
+ /* The second is log-dirty mode, writing to a read-only page;
+ * The third is populating a populate-on-demand page. */
+ if ( (gla_validity == EPT_GLA_VALIDITY_MATCH
+ || gla_validity == EPT_GLA_VALIDITY_GPT_WALK)
&& p2m_is_ram(t) && (t != p2m_ram_ro) )
{
- paging_mark_dirty(d, mfn_x(mfn));
- p2m_change_type(d, gfn, p2m_ram_logdirty, p2m_ram_rw);
- flush_tlb_mask(d->domain_dirty_cpumask);
+ if ( paging_mode_log_dirty(d) )
+ {
+ paging_mark_dirty(d, mfn_x(mfn));
+ p2m_change_type(d, gfn, p2m_ram_logdirty, p2m_ram_rw);
+ flush_tlb_mask(d->domain_dirty_cpumask);
+ }
return;
}
diff -r 65c24b33082a xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Wed Dec 17 12:59:28 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Wed Dec 17 12:59:50 2008 +0000
@@ -734,7 +734,7 @@
continue;
}
- p2mfn = gfn_to_mfn_foreign(d, gfn, &type);
+ p2mfn = gfn_to_mfn_type_foreign(d, gfn, &type, p2m_query);
if ( mfn_x(p2mfn) != mfn )
{
mpbad++;
@@ -752,7 +752,7 @@
if ( test_linear && (gfn <= d->arch.p2m->max_mapped_pfn) )
{
- lp2mfn = mfn_x(gfn_to_mfn(d, gfn, &type));
+ lp2mfn = mfn_x(gfn_to_mfn_query(d, gfn, &type));
if ( lp2mfn != mfn_x(p2mfn) )
{
P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx "
@@ -963,7 +963,7 @@
/* First, remove m->p mappings for existing p->m mappings */
for ( i = 0; i < (1UL << page_order); i++ )
{
- omfn = gfn_to_mfn(d, gfn + i, &ot);
+ omfn = gfn_to_mfn_query(d, gfn + i, &ot);
if ( p2m_is_ram(ot) )
{
ASSERT(mfn_valid(omfn));
@@ -988,7 +988,7 @@
* address */
P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n",
mfn + i, ogfn, gfn + i);
- omfn = gfn_to_mfn(d, ogfn, &ot);
+ omfn = gfn_to_mfn_query(d, ogfn, &ot);
if ( p2m_is_ram(ot) )
{
ASSERT(mfn_valid(omfn));
@@ -1157,7 +1157,7 @@
if ( !paging_mode_translate(d) )
return 0;
- omfn = gfn_to_mfn(d, gfn, &ot);
+ omfn = gfn_to_mfn_query(d, gfn, &ot);
if ( p2m_is_ram(ot) )
{
ASSERT(mfn_valid(omfn));
diff -r 65c24b33082a xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c Wed Dec 17 12:59:28 2008 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c Wed Dec 17 12:59:50 2008 +0000
@@ -2170,7 +2170,7 @@
if ( guest_l4e_get_flags(new_gl4e) & _PAGE_PRESENT )
{
gfn_t gl3gfn = guest_l4e_get_gfn(new_gl4e);
- mfn_t gl3mfn = gfn_to_mfn(d, gl3gfn, &p2mt);
+ mfn_t gl3mfn = gfn_to_mfn_query(d, gl3gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl3mfn = get_shadow_status(v, gl3mfn, SH_type_l3_shadow);
else
@@ -2227,7 +2227,7 @@
if ( guest_l3e_get_flags(new_gl3e) & _PAGE_PRESENT )
{
gfn_t gl2gfn = guest_l3e_get_gfn(new_gl3e);
- mfn_t gl2mfn = gfn_to_mfn(v->domain, gl2gfn, &p2mt);
+ mfn_t gl2mfn = gfn_to_mfn_query(v->domain, gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl2mfn = get_shadow_status(v, gl2mfn, SH_type_l2_shadow);
else
@@ -2276,7 +2276,7 @@
}
else
{
- mfn_t gl1mfn = gfn_to_mfn(v->domain, gl1gfn, &p2mt);
+ mfn_t gl1mfn = gfn_to_mfn_query(v->domain, gl1gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow);
else
@@ -2346,7 +2346,7 @@
perfc_incr(shadow_validate_gl1e_calls);
gfn = guest_l1e_get_gfn(new_gl1e);
- gmfn = gfn_to_mfn(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch, p2mt);
result |= shadow_set_l1e(v, sl1p, new_sl1e, sl1mfn);
@@ -2406,7 +2406,7 @@
shadow_l1e_t nsl1e;
gfn = guest_l1e_get_gfn(gl1e);
- gmfn = gfn_to_mfn(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch, p2mt);
rc |= shadow_set_l1e(v, sl1p, nsl1e, sl1mfn);
@@ -2723,7 +2723,7 @@
/* Look at the gfn that the l1e is pointing at */
gfn = guest_l1e_get_gfn(gl1e);
- gmfn = gfn_to_mfn(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
/* Propagate the entry. */
l1e_propagate_from_guest(v, gl1e, gmfn, &sl1e, ft_prefetch, p2mt);
@@ -3079,7 +3079,7 @@
/* What mfn is the guest trying to access? */
gfn = guest_l1e_get_gfn(gw.l1e);
- gmfn = gfn_to_mfn(d, gfn, &p2mt);
+ gmfn = gfn_to_mfn_guest(d, gfn, &p2mt);
if ( shadow_mode_refcounts(d) &&
(!p2m_is_valid(p2mt) || (!p2m_is_mmio(p2mt) && !mfn_valid(gmfn))) )
@@ -4126,7 +4126,7 @@
if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
{
gl2gfn = guest_l3e_get_gfn(gl3e[i]);
- gl2mfn = gfn_to_mfn(d, gl2gfn, &p2mt);
+ gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
flush |= sh_remove_write_access(v, gl2mfn, 2, 0);
}
@@ -4139,7 +4139,7 @@
if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
{
gl2gfn = guest_l3e_get_gfn(gl3e[i]);
- gl2mfn = gfn_to_mfn(d, gl2gfn, &p2mt);
+ gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
? SH_type_l2h_shadow
@@ -4525,7 +4525,12 @@
}
/* Translate the GFN to an MFN */
- mfn = gfn_to_mfn(v->domain, _gfn(gfn), &p2mt);
+ /* PoD: query only if shadow lock is held (to avoid deadlock) */
+ if ( shadow_locked_by_me(v->domain) )
+ mfn = gfn_to_mfn_query(v->domain, _gfn(gfn), &p2mt);
+ else
+ mfn = gfn_to_mfn(v->domain, _gfn(gfn), &p2mt);
+
if ( p2mt == p2m_ram_ro )
return _mfn(READONLY_GFN);
if ( !p2m_is_ram(p2mt) )
@@ -4929,7 +4934,7 @@
{
gfn = guest_l1e_get_gfn(*gl1e);
mfn = shadow_l1e_get_mfn(*sl1e);
- gmfn = gfn_to_mfn(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
if ( mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
" --> %" PRI_mfn " != mfn %" PRI_mfn,
@@ -4996,7 +5001,7 @@
mfn = shadow_l2e_get_mfn(*sl2e);
gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)
? get_fl1_shadow_status(v, gfn)
- : get_shadow_status(v, gfn_to_mfn(v->domain, gfn, &p2mt),
+ : get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, &p2mt),
SH_type_l1_shadow);
if ( mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
@@ -5004,7 +5009,7 @@
" --> %" PRI_mfn " != mfn %" PRI_mfn,
gfn_x(gfn),
(guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0
- : mfn_x(gfn_to_mfn(v->domain, gfn, &p2mt)),
+ : mfn_x(gfn_to_mfn_query(v->domain, gfn, &p2mt)),
mfn_x(gmfn), mfn_x(mfn));
}
});
@@ -5043,7 +5048,7 @@
{
gfn = guest_l3e_get_gfn(*gl3e);
mfn = shadow_l3e_get_mfn(*sl3e);
- gmfn = get_shadow_status(v, gfn_to_mfn(v->domain, gfn, &p2mt),
+ gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, &p2mt),
((GUEST_PAGING_LEVELS == 3 ||
is_pv_32on64_vcpu(v))
&& !shadow_mode_external(v->domain)
@@ -5090,7 +5095,7 @@
{
gfn = guest_l4e_get_gfn(*gl4e);
mfn = shadow_l4e_get_mfn(*sl4e);
- gmfn = get_shadow_status(v, gfn_to_mfn(v->domain, gfn, &p2mt),
+ gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, &p2mt),
SH_type_l3_shadow);
if ( mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
diff -r 65c24b33082a xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h Wed Dec 17 12:59:28 2008 +0000
+++ b/xen/arch/x86/mm/shadow/types.h Wed Dec 17 12:59:50 2008 +0000
@@ -191,6 +191,12 @@
})
#endif
+ /* Override gfn_to_mfn to work with gfn_t */
+#undef gfn_to_mfn_query
+#define gfn_to_mfn_query(d, g, t) _gfn_to_mfn_type((d), gfn_x(g), (t), p2m_query)
+#undef gfn_to_mfn_guest
+#define gfn_to_mfn_guest(d, g, t) _gfn_to_mfn_type((d), gfn_x(g), (t), p2m_guest)
+
/* The shadow types needed for the various levels. */
#if GUEST_PAGING_LEVELS == 2
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 03-populate-on-demand-core.diff --]
[-- Type: text/x-diff; name=03-populate-on-demand-core.diff, Size: 25470 bytes --]
diff -r e61e4075a710 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Wed Dec 17 12:59:51 2008 +0000
+++ b/xen/arch/x86/domain.c Fri Dec 19 17:51:53 2008 +0000
@@ -147,6 +147,11 @@
_p(page_to_mfn(page)),
page->count_info, page->u.inuse.type_info);
}
+ }
+
+ if ( is_hvm_domain(d) )
+ {
+ p2m_pod_dump_data(d);
}
list_for_each_entry ( page, &d->xenpage_list, list )
diff -r e61e4075a710 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Wed Dec 17 12:59:51 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Fri Dec 19 17:51:53 2008 +0000
@@ -118,9 +118,16 @@
return flags;
case p2m_mmio_direct:
return flags | P2M_BASE_FLAGS | _PAGE_RW | _PAGE_PCD;
+ case p2m_populate_on_demand:
+ return flags;
}
}
+#if P2M_AUDIT
+static void audit_p2m(struct domain *d);
+#else
+# define audit_p2m(_d) do { (void)(_d); } while(0)
+#endif /* P2M_AUDIT */
// Find the next level's P2M entry, checking for out-of-range gfn's...
// Returns NULL on error.
@@ -162,7 +169,8 @@
shift, max)) )
return 0;
- if ( !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) )
+ /* PoD: Not present doesn't imply empty. */
+ if ( !l1e_get_flags(*p2m_entry) )
{
struct page_info *pg = d->arch.p2m->alloc_page(d);
if ( pg == NULL )
@@ -197,7 +205,7 @@
}
}
- ASSERT(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT);
+ ASSERT(l1e_get_flags(*p2m_entry) & (_PAGE_PRESENT|_PAGE_PSE));
/* split single large page into 4KB page in P2M table */
if ( type == PGT_l1_page_table && (l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
@@ -240,6 +248,236 @@
*table = next;
return 1;
+}
+
+/*
+ * Populate-on-demand functionality
+ */
+int
+p2m_pod_cache_add(struct domain *d,
+ struct page_info *page,
+ unsigned long order)
+{
+ int i;
+ struct page_info *p;
+ struct p2m_domain *p2md = d->arch.p2m;
+
+#ifndef NDEBUG
+ mfn_t mfn;
+
+ mfn = page_to_mfn(page);
+
+ /* Check to make sure this is a contiguous region */
+ if( mfn_x(mfn) & ((1 << order) - 1) )
+ {
+ printk("%s: mfn %lx not aligned order %lu! (mask %lx)\n",
+ __func__, mfn_x(mfn), order, ((1UL << order) - 1));
+ return -1;
+ }
+
+ for(i=0; i < 1 << order ; i++) {
+ struct domain * od;
+
+ p = mfn_to_page(_mfn(mfn_x(mfn) + i));
+ od = page_get_owner(p);
+ if(od != d)
+ {
+ printk("%s: mfn %lx expected owner d%d, got owner d%d!\n",
+ __func__, mfn_x(mfn), d->domain_id,
+ od?od->domain_id:-1);
+ return -1;
+ }
+ }
+#endif
+
+ spin_lock(&d->page_alloc_lock);
+
+ /* First, take all pages off the domain list */
+ for(i=0; i < 1 << order ; i++)
+ {
+ p = page + i;
+ list_del(&p->list);
+ }
+
+ /* Then add the first one to the appropriate populate-on-demand list */
+ switch(order)
+ {
+ case 9:
+ list_add_tail(&page->list, &p2md->pod.super); /* lock: page_alloc */
+ p2md->pod.count += 1 << order;
+ break;
+ case 0:
+ list_add_tail(&page->list, &p2md->pod.single); /* lock: page_alloc */
+ p2md->pod.count += 1 ;
+ break;
+ default:
+ BUG();
+ }
+
+ spin_unlock(&d->page_alloc_lock);
+
+ return 0;
+}
+
+void
+p2m_pod_empty_cache(struct domain *d)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+ struct list_head *q, *p;
+
+ spin_lock(&d->page_alloc_lock);
+
+ list_for_each_safe(p, q, &p2md->pod.super) /* lock: page_alloc */
+ {
+ int i;
+ struct page_info *page;
+
+ list_del(p);
+
+ page = list_entry(p, struct page_info, list);
+
+ for ( i = 0 ; i < (1 << 9) ; i++ )
+ {
+ BUG_ON(page_get_owner(page + i) != d);
+ list_add_tail(&page[i].list, &d->page_list);
+ }
+
+ p2md->pod.count -= 1<<9;
+ }
+
+ list_for_each_safe(p, q, &p2md->pod.single)
+ {
+ struct page_info *page;
+
+ list_del(p);
+
+ page = list_entry(p, struct page_info, list);
+
+ BUG_ON(page_get_owner(page) != d);
+ list_add_tail(&page->list, &d->page_list);
+
+ p2md->pod.count -= 1;
+ }
+
+ BUG_ON(p2md->pod.count != 0);
+
+ spin_unlock(&d->page_alloc_lock);
+}
+
+void
+p2m_pod_dump_data(struct domain *d)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+
+ printk(" PoD entries=%d cachesize=%d\n",
+ p2md->pod.entry_count, p2md->pod.count);
+}
+
+static int
+p2m_pod_demand_populate(struct domain *d, unsigned long gfn,
+ mfn_t table_mfn,
+ l1_pgentry_t *p2m_entry,
+ unsigned int order,
+ p2m_query_t q)
+{
+ struct page_info *p = NULL; /* Compiler warnings */
+ unsigned long gfn_aligned;
+ mfn_t mfn;
+ l1_pgentry_t entry_content = l1e_empty();
+ struct p2m_domain *p2md = d->arch.p2m;
+ int i;
+
+ /* We need to grab the p2m lock here and re-check the entry to make
+ * sure that someone else hasn't populated it for us, then hold it
+ * until we're done. */
+ p2m_lock(p2md);
+ audit_p2m(d);
+
+ /* Check to make sure this is still PoD */
+ if ( p2m_flags_to_type(l1e_get_flags(*p2m_entry)) != p2m_populate_on_demand )
+ {
+ p2m_unlock(p2md);
+ return 0;
+ }
+
+ spin_lock(&d->page_alloc_lock);
+
+ if ( p2md->pod.count == 0 )
+ goto out_of_memory;
+
+ /* FIXME -- use single pages / splinter superpages if need be */
+ switch ( order )
+ {
+ case 9:
+ BUG_ON( list_empty(&p2md->pod.super) );
+ p = list_entry(p2md->pod.super.next, struct page_info, list);
+ p2md->pod.count -= 1 << order; /* Lock: page_alloc */
+ break;
+ case 0:
+ BUG_ON( list_empty(&p2md->pod.single) );
+ p = list_entry(p2md->pod.single.next, struct page_info, list);
+ p2md->pod.count -= 1;
+ break;
+ default:
+ BUG();
+ }
+
+ list_del(&p->list);
+
+ mfn = page_to_mfn(p);
+
+ BUG_ON((mfn_x(mfn) & ((1 << order)-1)) != 0);
+
+ /* Put the pages back on the domain page_list */
+ for ( i = 0 ; i < (1 << order) ; i++ )
+ {
+ BUG_ON(page_get_owner(p + i) != d);
+ list_add_tail(&p[i].list, &d->page_list);
+ }
+
+ spin_unlock(&d->page_alloc_lock);
+
+ /* Fill in the entry in the p2m */
+ switch ( order )
+ {
+ case 9:
+ {
+ l2_pgentry_t l2e_content;
+
+ l2e_content = l2e_from_pfn(mfn_x(mfn),
+ p2m_type_to_flags(p2m_ram_rw) | _PAGE_PSE);
+
+ entry_content.l1 = l2e_content.l2;
+ }
+ break;
+ case 0:
+ entry_content = l1e_from_pfn(mfn_x(mfn),
+ p2m_type_to_flags(p2m_ram_rw));
+ break;
+
+ }
+
+ gfn_aligned = (gfn >> order) << order;
+
+ paging_write_p2m_entry(d, gfn_aligned, p2m_entry, table_mfn,
+ entry_content, (order==9)?2:1);
+
+ for( i = 0 ; i < (1UL << order) ; i++ )
+ set_gpfn_from_mfn(mfn_x(mfn) + i, gfn_aligned + i);
+
+ p2md->pod.entry_count -= (1 << order); /* Lock: p2m */
+ BUG_ON(p2md->pod.entry_count < 0);
+ audit_p2m(d);
+ p2m_unlock(p2md);
+
+ return 0;
+out_of_memory:
+ spin_unlock(&d->page_alloc_lock);
+ audit_p2m(d);
+ p2m_unlock(p2md);
+ printk("%s: Out of populate-on-demand memory!\n", __func__);
+ domain_crash(d);
+ return -1;
}
// Returns 0 on error (out of memory)
@@ -303,6 +541,7 @@
L2_PAGETABLE_ENTRIES);
ASSERT(p2m_entry);
+ /* FIXME: Deal with 4k replaced by 2meg pages */
if ( (l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) &&
!(l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
{
@@ -311,7 +550,7 @@
goto out;
}
- if ( mfn_valid(mfn) )
+ if ( mfn_valid(mfn) || p2m_is_magic(p2mt) )
l2e_content = l2e_from_pfn(mfn_x(mfn),
p2m_type_to_flags(p2mt) | _PAGE_PSE);
else
@@ -403,8 +642,21 @@
l2e = map_domain_page(mfn_x(mfn));
l2e += l2_table_offset(addr);
+
+pod_retry_l2:
if ( (l2e_get_flags(*l2e) & _PAGE_PRESENT) == 0 )
{
+ /* PoD: Try to populate a 2-meg chunk */
+ if ( p2m_flags_to_type(l2e_get_flags(*l2e)) == p2m_populate_on_demand )
+ {
+ if ( q != p2m_query ) {
+ if( !p2m_pod_demand_populate(d, gfn, mfn,
+ (l1_pgentry_t *)l2e, 9, q) )
+ goto pod_retry_l2;
+ } else
+ *t = p2m_populate_on_demand;
+ }
+
unmap_domain_page(l2e);
return _mfn(INVALID_MFN);
}
@@ -423,8 +675,20 @@
l1e = map_domain_page(mfn_x(mfn));
l1e += l1_table_offset(addr);
+pod_retry_l1:
if ( (l1e_get_flags(*l1e) & _PAGE_PRESENT) == 0 )
{
+ /* PoD: Try to populate */
+ if ( p2m_flags_to_type(l1e_get_flags(*l1e)) == p2m_populate_on_demand )
+ {
+ if ( q != p2m_query ) {
+ if( !p2m_pod_demand_populate(d, gfn, mfn,
+ (l1_pgentry_t *)l1e, 0, q) )
+ goto pod_retry_l1;
+ } else
+ *t = p2m_populate_on_demand;
+ }
+
unmap_domain_page(l1e);
return _mfn(INVALID_MFN);
}
@@ -450,48 +714,114 @@
if ( gfn <= current->domain->arch.p2m->max_mapped_pfn )
{
- l1_pgentry_t l1e = l1e_empty();
+ l1_pgentry_t l1e = l1e_empty(), *p2m_entry;
l2_pgentry_t l2e = l2e_empty();
int ret;
ASSERT(gfn < (RO_MPT_VIRT_END - RO_MPT_VIRT_START)
/ sizeof(l1_pgentry_t));
+ /*
+ * Read & process L2
+ */
+ p2m_entry = &__linear_l1_table[l1_linear_offset(RO_MPT_VIRT_START)
+ + l2_linear_offset(addr)];
+
+ pod_retry_l2:
ret = __copy_from_user(&l2e,
- &__linear_l1_table[l1_linear_offset(RO_MPT_VIRT_START) + l2_linear_offset(addr)],
+ p2m_entry,
sizeof(l2e));
+ if ( ret != 0
+ || !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+ {
+ if( (l2e_get_flags(l2e) & _PAGE_PSE)
+ && ( p2m_flags_to_type(l2e_get_flags(l2e))
+ == p2m_populate_on_demand ) )
+ {
+ /* The read has succeeded, so we know that the mapping
+ * exits at this point. */
+ if ( q != p2m_query )
+ {
+ if( !p2m_pod_demand_populate(current->domain, gfn, mfn,
+ p2m_entry, 9, q) )
+ goto pod_retry_l2;
+
+ /* Allocate failed. */
+ p2mt = p2m_invalid;
+ printk("%s: Allocate failed!\n", __func__);
+ goto out;
+ }
+ else
+ {
+ p2mt = p2m_populate_on_demand;
+ goto out;
+ }
+ }
+
+ goto pod_retry_l1;
+ }
- if ( (ret == 0) && (l2e_get_flags(l2e) & _PAGE_PRESENT) &&
- (l2e_get_flags(l2e) & _PAGE_PSE) )
+ if (l2e_get_flags(l2e) & _PAGE_PSE)
{
p2mt = p2m_flags_to_type(l2e_get_flags(l2e));
ASSERT(l2e_get_pfn(l2e) != INVALID_MFN || !p2m_is_ram(p2mt));
+
if ( p2m_is_valid(p2mt) )
mfn = _mfn(l2e_get_pfn(l2e) + l1_table_offset(addr));
else
p2mt = p2m_mmio_dm;
+
+ goto out;
}
- else
- {
-
- /* Need to __copy_from_user because the p2m is sparse and this
- * part might not exist */
- ret = __copy_from_user(&l1e,
- &phys_to_machine_mapping[gfn],
- sizeof(l1e));
+
+ /*
+ * Read and process L1
+ */
+
+ /* Need to __copy_from_user because the p2m is sparse and this
+ * part might not exist */
+ pod_retry_l1:
+ p2m_entry = &phys_to_machine_mapping[gfn];
+
+ ret = __copy_from_user(&l1e,
+ p2m_entry,
+ sizeof(l1e));
- if ( ret == 0 ) {
- p2mt = p2m_flags_to_type(l1e_get_flags(l1e));
- ASSERT(l1e_get_pfn(l1e) != INVALID_MFN || !p2m_is_ram(p2mt));
- if ( p2m_is_valid(p2mt) )
- mfn = _mfn(l1e_get_pfn(l1e));
- else
- /* XXX see above */
- p2mt = p2m_mmio_dm;
+ if ( ret == 0 ) {
+ p2mt = p2m_flags_to_type(l1e_get_flags(l1e));
+ ASSERT(l1e_get_pfn(l1e) != INVALID_MFN || !p2m_is_ram(p2mt));
+
+ if ( p2m_flags_to_type(l1e_get_flags(l1e))
+ == p2m_populate_on_demand )
+ {
+ /* The read has succeeded, so we know that the mapping
+ * exits at this point. */
+ if ( q != p2m_query )
+ {
+ if( !p2m_pod_demand_populate(current->domain, gfn, mfn,
+ (l1_pgentry_t *)p2m_entry, 0,
+ q) )
+ goto pod_retry_l1;
+
+ /* Allocate failed. */
+ p2mt = p2m_invalid;
+ goto out;
+ }
+ else
+ {
+ p2mt = p2m_populate_on_demand;
+ goto out;
+ }
}
+
+ if ( p2m_is_valid(p2mt) )
+ mfn = _mfn(l1e_get_pfn(l1e));
+ else
+ /* XXX see above */
+ p2mt = p2m_mmio_dm;
}
}
-
+out:
*t = p2mt;
return mfn;
}
@@ -510,6 +840,8 @@
memset(p2m, 0, sizeof(*p2m));
p2m_lock_init(p2m);
INIT_LIST_HEAD(&p2m->pages);
+ INIT_LIST_HEAD(&p2m->pod.super);
+ INIT_LIST_HEAD(&p2m->pod.single);
p2m->set_entry = p2m_set_entry;
p2m->get_entry = p2m_gfn_to_mfn;
@@ -680,6 +1012,7 @@
struct page_info *page;
struct domain *od;
unsigned long mfn, gfn, m2pfn, lp2mfn = 0;
+ int entry_count = 0;
mfn_t p2mfn;
unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0;
int test_linear;
@@ -809,6 +1142,10 @@
{
if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) )
{
+ if ( (l2e_get_flags(l2e[i2]) & _PAGE_PSE)
+ && ( p2m_flags_to_type(l2e_get_flags(l2e[i2]))
+ == p2m_populate_on_demand ) )
+ entry_count+=(1<<9);
gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT);
continue;
}
@@ -839,13 +1176,20 @@
for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ )
{
if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) )
+ {
+ if ( p2m_flags_to_type(l1e_get_flags(l1e[i1]))
+ == p2m_populate_on_demand )
+ entry_count++;
continue;
+ }
mfn = l1e_get_pfn(l1e[i1]);
ASSERT(mfn_valid(_mfn(mfn)));
m2pfn = get_gpfn_from_mfn(mfn);
if ( m2pfn != gfn )
{
pmbad++;
+ printk("mismatch: gfn %#lx -> mfn %#lx"
+ " -> gfn %#lx\n", gfn, mfn, m2pfn);
P2M_PRINTK("mismatch: gfn %#lx -> mfn %#lx"
" -> gfn %#lx\n", gfn, mfn, m2pfn);
BUG();
@@ -868,6 +1212,15 @@
}
+ if ( entry_count != d->arch.p2m->pod.entry_count )
+ {
+ printk("%s: refcounted entry count %d, audit count %d!\n",
+ __func__,
+ d->arch.p2m->pod.entry_count,
+ entry_count);
+ BUG();
+ }
+
//P2M_PRINTK("p2m audit complete\n");
//if ( orphans_i | orphans_d | mpbad | pmbad )
// P2M_PRINTK("p2m audit found %lu orphans (%lu inval %lu debug)\n",
@@ -876,8 +1229,6 @@
P2M_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n",
pmbad, mpbad);
}
-#else
-#define audit_p2m(_d) do { (void)(_d); } while(0)
#endif /* P2M_AUDIT */
@@ -915,6 +1266,77 @@
}
int
+guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
+ unsigned int order)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+ unsigned long i;
+ p2m_type_t ot;
+ mfn_t omfn;
+ int pod_count = 0;
+ int rc = 0;
+
+ BUG_ON(!paging_mode_translate(d));
+
+#if CONFIG_PAGING_LEVELS == 3
+ /*
+ * 32bit PAE nested paging does not support over 4GB guest due to
+ * hardware translation limit. This limitation is checked by comparing
+ * gfn with 0xfffffUL.
+ */
+ if ( paging_mode_hap(d) && (gfn > 0xfffffUL) )
+ {
+ if ( !test_and_set_bool(d->arch.hvm_domain.svm.npt_4gb_warning) )
+ dprintk(XENLOG_WARNING, "Dom%d failed to populate memory beyond"
+ " 4GB: specify 'hap=0' domain config option.\n",
+ d->domain_id);
+ return -EINVAL;
+ }
+#endif
+
+ p2m_lock(p2md);
+ audit_p2m(d);
+
+ P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn);
+
+ /* Make sure all gpfns are unused */
+ for ( i = 0; i < (1UL << order); i++ )
+ {
+ omfn = gfn_to_mfn_query(d, gfn + i, &ot);
+ if ( p2m_is_ram(ot) )
+ {
+ printk("%s: gfn_to_mfn returned type %d!\n",
+ __func__, ot);
+ rc = -EBUSY;
+ goto out;
+ }
+ else if ( ot == p2m_populate_on_demand )
+ {
+ /* Count how man PoD entries we'll be replacing if successful */
+ pod_count++;
+ }
+ }
+
+ /* Now, actually do the two-way mapping */
+ if ( !set_p2m_entry(d, gfn, _mfn(POPULATE_ON_DEMAND_MFN), order,
+ p2m_populate_on_demand) )
+ rc = -EINVAL;
+ else
+ {
+ p2md->pod.entry_count += 1 << order; /* Lock: p2m */
+ p2md->pod.entry_count -= pod_count;
+ BUG_ON(p2md->pod.entry_count < 0);
+ }
+
+ audit_p2m(d);
+ p2m_unlock(p2md);
+
+out:
+ return rc;
+
+}
+
+int
guest_physmap_add_entry(struct domain *d, unsigned long gfn,
unsigned long mfn, unsigned int page_order,
p2m_type_t t)
@@ -922,6 +1344,7 @@
unsigned long i, ogfn;
p2m_type_t ot;
mfn_t omfn;
+ int pod_count = 0;
int rc = 0;
if ( !paging_mode_translate(d) )
@@ -969,6 +1392,11 @@
ASSERT(mfn_valid(omfn));
set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
}
+ else if ( ot == p2m_populate_on_demand )
+ {
+ /* Count how man PoD entries we'll be replacing if successful */
+ pod_count++;
+ }
}
/* Then, look for m->p mappings for this range and deal with them */
@@ -1015,6 +1443,11 @@
if ( !set_p2m_entry(d, gfn, _mfn(INVALID_MFN), page_order,
p2m_invalid) )
rc = -EINVAL;
+ else
+ {
+ d->arch.p2m->pod.entry_count -= pod_count; /* Lock: p2m */
+ BUG_ON(d->arch.p2m->pod.entry_count < 0);
+ }
}
audit_p2m(d);
diff -r e61e4075a710 xen/arch/x86/mm/paging.c
--- a/xen/arch/x86/mm/paging.c Wed Dec 17 12:59:51 2008 +0000
+++ b/xen/arch/x86/mm/paging.c Fri Dec 19 17:51:53 2008 +0000
@@ -585,6 +585,9 @@
/* clean up log dirty resources. */
paging_log_dirty_teardown(d);
+
+ /* Move populate-on-demand cache back to domain_list for destruction */
+ p2m_pod_empty_cache(d);
}
/* Call once all of the references to the domain have gone away */
diff -r e61e4075a710 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c Wed Dec 17 12:59:51 2008 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c Fri Dec 19 17:51:53 2008 +0000
@@ -2173,7 +2173,7 @@
mfn_t gl3mfn = gfn_to_mfn_query(d, gl3gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl3mfn = get_shadow_status(v, gl3mfn, SH_type_l3_shadow);
- else
+ else if ( p2mt != p2m_populate_on_demand )
result |= SHADOW_SET_ERROR;
#if (SHADOW_OPTIMIZATIONS && SHOPT_OUT_OF_SYNC )
@@ -2230,7 +2230,7 @@
mfn_t gl2mfn = gfn_to_mfn_query(v->domain, gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl2mfn = get_shadow_status(v, gl2mfn, SH_type_l2_shadow);
- else
+ else if ( p2mt != p2m_populate_on_demand )
result |= SHADOW_SET_ERROR;
#if (SHADOW_OPTIMIZATIONS && SHOPT_OUT_OF_SYNC )
@@ -2278,8 +2278,8 @@
{
mfn_t gl1mfn = gfn_to_mfn_query(v->domain, gl1gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
- sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow);
- else
+ sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow);
+ else if ( p2mt != p2m_populate_on_demand )
result |= SHADOW_SET_ERROR;
}
}
diff -r e61e4075a710 xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Wed Dec 17 12:59:51 2008 +0000
+++ b/xen/include/asm-x86/p2m.h Fri Dec 19 17:51:53 2008 +0000
@@ -64,6 +64,7 @@
p2m_ram_ro = 3, /* Read-only; writes are silently dropped */
p2m_mmio_dm = 4, /* Reads and write go to the device model */
p2m_mmio_direct = 5, /* Read/write mapping of genuine MMIO area */
+ p2m_populate_on_demand = 6, /* Place-holder for empty memory */
} p2m_type_t;
typedef enum {
@@ -88,11 +89,19 @@
#define P2M_RO_TYPES (p2m_to_mask(p2m_ram_logdirty) \
| p2m_to_mask(p2m_ram_ro))
+#define P2M_MAGIC_TYPES (p2m_to_mask(p2m_populate_on_demand))
+
/* Useful predicates */
#define p2m_is_ram(_t) (p2m_to_mask(_t) & P2M_RAM_TYPES)
#define p2m_is_mmio(_t) (p2m_to_mask(_t) & P2M_MMIO_TYPES)
#define p2m_is_readonly(_t) (p2m_to_mask(_t) & P2M_RO_TYPES)
+#define p2m_is_magic(_t) (p2m_to_mask(_t) & P2M_MAGIC_TYPES)
#define p2m_is_valid(_t) (p2m_to_mask(_t) & (P2M_RAM_TYPES | P2M_MMIO_TYPES))
+
+/* Populate-on-demand */
+#define POPULATE_ON_DEMAND_MFN (1<<9)
+#define POD_PAGE_ORDER 9
+
struct p2m_domain {
/* Lock that protects updates to the p2m */
@@ -122,6 +131,28 @@
/* Highest guest frame that's ever been mapped in the p2m */
unsigned long max_mapped_pfn;
+
+ /* Populate-on-demand variables
+ * NB on locking. {super,single,count} are
+ * covered by d->page_alloc_lock, since they're almost always used in
+ * conjunction with that functionality. {entry_count} is covered by
+ * the domain p2m lock, since it's almost always used in conjunction
+ * with changing the p2m tables.
+ *
+ * At this point, both locks are held in two places. In both,
+ * the order is [p2m,page_alloc]:
+ * + p2m_pod_decrease_reservation() calls p2m_pod_cache_add(),
+ * which grabs page_alloc
+ * + p2m_pod_demand_populate() grabs both; the p2m lock to avoid
+ * double-demand-populating of pages, the page_alloc lock to
+ * protect moving stuff from the PoD cache to the domain page list.
+ */
+ struct {
+ struct list_head super, /* List of superpages */
+ single; /* Non-super lists */
+ int count, /* # of pages in cache lists */
+ entry_count; /* # of pages in p2m marked pod */
+ } pod;
};
/* Extract the type from the PTE flags that store it */
@@ -220,10 +251,21 @@
void p2m_teardown(struct domain *d);
void p2m_final_teardown(struct domain *d);
+/* Dump PoD information about the domain */
+void p2m_pod_dump_data(struct domain *d);
+
+/* Move all pages from the populate-on-demand cache to the domain page_list
+ * (usually in preparation for domain destruction) */
+void p2m_pod_empty_cache(struct domain *d);
+
/* Add a page to a domain's p2m table */
int guest_physmap_add_entry(struct domain *d, unsigned long gfn,
unsigned long mfn, unsigned int page_order,
p2m_type_t t);
+
+/* Set a p2m range as populate-on-demand */
+int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
+ unsigned int order);
/* Untyped version for RAM only, for compatibility
*
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #5: 04-pod-decrease-reservation.diff --]
[-- Type: text/x-diff; name=04-pod-decrease-reservation.diff, Size: 5234 bytes --]
diff -r 919fb6b530b1 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Fri Dec 19 17:41:11 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Fri Dec 19 17:41:17 2008 +0000
@@ -253,6 +253,10 @@
/*
* Populate-on-demand functionality
*/
+static
+int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+ unsigned int page_order, p2m_type_t p2mt);
+
int
p2m_pod_cache_add(struct domain *d,
struct page_info *page,
@@ -362,6 +366,125 @@
BUG_ON(p2md->pod.count != 0);
spin_unlock(&d->page_alloc_lock);
+}
+
+/* This function is needed for two reasons:
+ * + To properly handle clearing of PoD entries
+ * + To "steal back" memory being freed for the PoD cache, rather than
+ * releasing it.
+ *
+ * Once both of these functions have been completed, we can return and
+ * allow decrease_reservation() to handle everything else.
+ */
+int
+p2m_pod_decrease_reservation(struct domain *d,
+ xen_pfn_t gpfn,
+ unsigned int order)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+ int ret=0;
+ int i;
+
+ int steal_for_cache = 0;
+ int pod = 0, nonpod = 0, ram = 0;
+
+
+ /* If we don't have any outstanding PoD entries, let things take their
+ * course */
+ if ( p2md->pod.entry_count == 0 )
+ goto out;
+
+ /* Figure out if we need to steal some freed memory for our cache */
+ steal_for_cache = ( p2md->pod.entry_count > p2md->pod.count );
+
+ p2m_lock(p2md);
+ audit_p2m(d);
+
+ /* See what's in here. */
+ /* FIXME: Add contiguous; query for PSE entries? */
+ for ( i=0; i<(1<<order); i++)
+ {
+ p2m_type_t t;
+
+ gfn_to_mfn_query(d, gpfn + i, &t);
+
+ if ( t == p2m_populate_on_demand )
+ pod++;
+ else
+ {
+ nonpod++;
+ if ( p2m_is_ram(t) )
+ ram++;
+ }
+ }
+
+ /* No populate-on-demand? Don't need to steal anything? Then we're done!*/
+ if(!pod && !steal_for_cache)
+ goto out_unlock;
+
+ if ( !nonpod )
+ {
+ /* All PoD: Mark the whole region invalid and tell caller
+ * we're done. */
+ set_p2m_entry(d, gpfn, _mfn(INVALID_MFN), order, p2m_invalid);
+ p2md->pod.entry_count-=(1<<order); /* Lock: p2m */
+ BUG_ON(p2md->pod.entry_count < 0);
+ ret = 1;
+ goto out_unlock;
+ }
+
+ /* FIXME: Steal contig 2-meg regions for cache */
+
+ /* Process as long as:
+ * + There are PoD entries to handle, or
+ * + There is ram left, and we want to steal it
+ */
+ for ( i=0;
+ i<(1<<order) && (pod>0 || (steal_for_cache && ram > 0));
+ i++)
+ {
+ mfn_t mfn;
+ p2m_type_t t;
+
+ mfn = gfn_to_mfn_query(d, gpfn + i, &t);
+ if ( t == p2m_populate_on_demand )
+ {
+ set_p2m_entry(d, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
+ p2md->pod.entry_count--; /* Lock: p2m */
+ BUG_ON(p2md->pod.entry_count < 0);
+ pod--;
+ }
+ else if ( steal_for_cache && p2m_is_ram(t) )
+ {
+ struct page_info *page;
+
+ ASSERT(mfn_valid(mfn));
+
+ page = mfn_to_page(mfn);
+
+ set_p2m_entry(d, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
+ set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
+
+ p2m_pod_cache_add(d, page, 0);
+
+ steal_for_cache = ( p2md->pod.entry_count > p2md->pod.count );
+
+ nonpod--;
+ ram--;
+ }
+ }
+
+ /* If there are no more non-PoD entries, tell decrease_reservation() that
+ * there's nothing left to do. */
+ if ( nonpod == 0 )
+ ret = 1;
+
+out_unlock:
+ audit_p2m(d);
+ p2m_unlock(p2md);
+
+out:
+ return ret;
}
void
diff -r 919fb6b530b1 xen/common/memory.c
--- a/xen/common/memory.c Fri Dec 19 17:41:11 2008 +0000
+++ b/xen/common/memory.c Fri Dec 19 17:41:17 2008 +0000
@@ -191,6 +191,11 @@
if ( unlikely(__copy_from_guest_offset(&gmfn, a->extent_list, i, 1)) )
goto out;
+
+ /* See if populate-on-demand wants to handle this */
+ if ( is_hvm_domain(a->domain)
+ && p2m_pod_decrease_reservation(a->domain, gmfn, a->extent_order) )
+ continue;
for ( j = 0; j < (1 << a->extent_order); j++ )
if ( !guest_remove_page(a->domain, gmfn + j) )
diff -r 919fb6b530b1 xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Fri Dec 19 17:41:11 2008 +0000
+++ b/xen/include/asm-x86/p2m.h Fri Dec 19 17:41:17 2008 +0000
@@ -255,6 +255,13 @@
* (usually in preparation for domain destruction) */
void p2m_pod_empty_cache(struct domain *d);
+/* Call when decreasing memory reservation to handle PoD entries properly.
+ * Will return '1' if all entries were handled and nothing more need be done.*/
+int
+p2m_pod_decrease_reservation(struct domain *d,
+ xen_pfn_t gpfn,
+ unsigned int order);
+
/* Add a page to a domain's p2m table */
int guest_physmap_add_entry(struct domain *d, unsigned long gfn,
unsigned long mfn, unsigned int page_order,
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #6: 05-emergency-scan.diff --]
[-- Type: text/x-diff; name=05-emergency-scan.diff, Size: 12566 bytes --]
diff -r 1e9ad800991c xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Fri Dec 19 17:41:18 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Fri Dec 19 17:41:25 2008 +0000
@@ -496,6 +496,289 @@
p2md->pod.entry_count, p2md->pod.count);
}
+#define superpage_aligned(_x) (((_x)&((1<<9)-1))==0)
+
+/* Must be called w/ p2m lock held, page_alloc lock not held */
+static int
+p2m_pod_zero_check_superpage(struct domain *d, unsigned long gfn)
+{
+ mfn_t mfns[1<<9];
+ p2m_type_t types[1<<9];
+ unsigned long * map[1<<9] = { NULL };
+ int ret=0, reset = 0, reset_max = 0;
+ int i, j;
+
+ if ( !superpage_aligned(gfn) )
+ goto out;
+
+ /* Look up the mfns, checking to make sure they're the same mfn
+ * and aligned, and mapping them. */
+ for ( i=0; i<(1<<9); i++ )
+ {
+ mfns[i] = gfn_to_mfn_query(d, gfn + i, types + i);
+
+ /* Conditions that must be met for superpage-superpage:
+ * + All gfns are ram types
+ * + All gfns have the same type
+ * + None of the mfns are used as pagetables
+ * + The first mfn is 2-meg aligned
+ * + All the other mfns are in sequence
+ */
+ if ( p2m_is_ram(types[i])
+ && types[i] == types[0]
+ && ( (mfn_to_page(mfns[i])->count_info & PGC_page_table) == 0 )
+ && ( ( i == 0 && superpage_aligned(mfn_x(mfns[0])) )
+ || ( i != 0 && mfn_x(mfns[i]) == mfn_x(mfns[0]) + i ) ) )
+ map[i] = map_domain_page(mfn_x(mfns[i]));
+ else
+ goto out_unmap;
+ }
+
+ /* Now, do a quick check to see if it may be zero before unmapping. */
+ for ( i=0; i<(1<<9); i++ )
+ {
+ /* Quick zero-check */
+ for ( j=0; j<16; j++ )
+ if( *(map[i]+j) != 0 )
+ break;
+
+ if ( j < 16 )
+ goto out_unmap;
+
+ }
+
+ /* Try to remove the page, restoring old mapping if it fails. */
+ reset_max = 1<<9;
+ set_p2m_entry(d, gfn,
+ _mfn(POPULATE_ON_DEMAND_MFN), 9,
+ p2m_populate_on_demand);
+
+ if ( (mfn_to_page(mfns[0])->u.inuse.type_info & PGT_count_mask) != 0 )
+ {
+ reset = 1;
+ goto out_reset;
+ }
+
+ /* Timing here is important. We need to make sure not to reclaim
+ * a page which has been grant-mapped to another domain. But we
+ * can't grab the grant table lock, because we may be invoked from
+ * the grant table code! So we first remove the page from the
+ * p2m, then check to see if the gpfn has been granted. Once this
+ * gpfn is marked PoD, any future gfn_to_mfn() call will block
+ * waiting for the p2m lock. If we find that it has been granted, we
+ * simply restore the old value.
+ */
+ if ( gnttab_is_granted(d, gfn, 9) )
+ {
+ printk("gfn contains grant table %lx\n", gfn);
+ reset = 1;
+ goto out_reset;
+ }
+
+ /* Finally, do a full zero-check */
+ for ( i=0; i < (1<<9); i++ )
+ {
+ for ( j=0; j<PAGE_SIZE/sizeof(*map[i]); j++ )
+ if( *(map[i]+j) != 0 )
+ {
+ reset = 1;
+ break;
+ }
+
+ if ( reset )
+ goto out_reset;
+ }
+
+ /* Finally! We've passed all the checks, and can add the mfn superpage
+ * back on the PoD cache, and account for the new p2m PoD entries */
+ p2m_pod_cache_add(d, mfn_to_page(mfns[0]), 9);
+ d->arch.p2m->pod.entry_count += (1<<9);
+
+out_reset:
+ if ( reset )
+ {
+ if (reset_max == (1<<9) )
+ set_p2m_entry(d, gfn, mfns[0], 9, types[0]);
+ else
+ for ( i=0; i<reset_max; i++)
+ set_p2m_entry(d, gfn + i, mfns[i], 0, types[i]);
+ }
+
+out_unmap:
+ for ( i=0; i<(1<<9); i++ )
+ if ( map[i] )
+ unmap_domain_page(map[i]);
+out:
+ return ret;
+}
+
+static void
+p2m_pod_zero_check(struct domain *d, unsigned long *gfns, int count)
+{
+ mfn_t mfns[count];
+ p2m_type_t types[count];
+ unsigned long * map[count];
+
+ int i, j;
+
+ /* First, get the gfn list, translate to mfns, and map the pages. */
+ for ( i=0; i<count; i++ )
+ {
+ mfns[i] = gfn_to_mfn_query(d, gfns[i], types + i);
+ /* If this is ram, and not a pagetable, map it; otherwise,
+ * skip. */
+ if ( p2m_is_ram(types[i])
+ && ( (mfn_to_page(mfns[i])->count_info & PGC_page_table) == 0 ) )
+ map[i] = map_domain_page(mfn_x(mfns[i]));
+ else
+ map[i] = NULL;
+ }
+
+ /* Then, go through and check for zeroed pages, removing write permission
+ * for those with zeroes. */
+ for ( i=0; i<count; i++ )
+ {
+ if(!map[i])
+ continue;
+
+ /* Quick zero-check */
+ for ( j=0; j<16; j++ )
+ if( *(map[i]+j) != 0 )
+ break;
+
+ if ( j < 16 )
+ {
+ unmap_domain_page(map[i]);
+ map[i] = NULL;
+ continue;
+ }
+
+ /* Try to remove the page, restoring old mapping if it fails. */
+ set_p2m_entry(d, gfns[i],
+ _mfn(POPULATE_ON_DEMAND_MFN), 0,
+ p2m_populate_on_demand);
+
+ if ( (mfn_to_page(mfns[i])->u.inuse.type_info & PGT_count_mask) != 0 )
+ {
+ unmap_domain_page(map[i]);
+ map[i] = NULL;
+
+ set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
+
+ continue;
+ }
+ }
+
+ /* Now check each page for real */
+ for ( i=0; i < count; i++ )
+ {
+ if(!map[i])
+ continue;
+
+ for ( j=0; j<PAGE_SIZE/sizeof(*map[i]); j++ )
+ if( *(map[i]+j) != 0 )
+ break;
+
+ /* See comment in p2m_pod_zero_check_superpage() re gnttab
+ * check timing. */
+ if ( j < PAGE_SIZE/sizeof(*map[i])
+ || gnttab_is_granted(d, gfns[i], 0) )
+ {
+ set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
+ continue;
+ }
+ else
+ {
+ /* Add to cache, and account for the new p2m PoD entry */
+ p2m_pod_cache_add(d, mfn_to_page(mfns[i]), 0);
+ d->arch.p2m->pod.entry_count++;
+ }
+
+ unmap_domain_page(map[i]);
+ map[i] = NULL;
+ }
+
+}
+
+#define POD_SWEEP_LIMIT 1024
+static void
+p2m_pod_emergency_sweep_super(struct domain *d)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+ unsigned long i, start, limit;
+
+ if ( p2md->pod.reclaim_super == 0 )
+ {
+ p2md->pod.reclaim_super = (p2md->pod.max_guest>>9)<<9;
+ p2md->pod.reclaim_super -= (1<<9);
+ }
+
+ start = p2md->pod.reclaim_super;
+ limit = (start > POD_SWEEP_LIMIT) ? (start - POD_SWEEP_LIMIT) : 0;
+
+ for ( i=p2md->pod.reclaim_super ; i > 0 ; i-=(1<<9) )
+ {
+ p2m_pod_zero_check_superpage(d, i);
+ /* Stop if we're past our limit and we have found *something*.
+ *
+ * NB that this is a zero-sum game; we're increasing our cache size
+ * by re-increasing our 'debt'. Since we hold the p2m lock,
+ * (entry_count - count) must remain the same. */
+ if ( !list_empty(&p2md->pod.super) && i < limit )
+ break;
+ }
+
+ p2md->pod.reclaim_super = i ? i - (1<<9) : 0;
+
+}
+
+#define POD_SWEEP_STRIDE 16
+static void
+p2m_pod_emergency_sweep(struct domain *d)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+ unsigned long gfns[POD_SWEEP_STRIDE];
+ unsigned long i, j=0, start, limit;
+ p2m_type_t t;
+
+
+ if ( p2md->pod.reclaim_single == 0 )
+ p2md->pod.reclaim_single = p2md->pod.max_guest;
+
+ start = p2md->pod.reclaim_single;
+ limit = (start > POD_SWEEP_LIMIT) ? (start - POD_SWEEP_LIMIT) : 0;
+
+ /* FIXME: Figure out how to avoid superpages */
+ for ( i=p2md->pod.reclaim_single ; i > 0 ; i-- )
+ {
+ gfn_to_mfn_query(d, i, &t );
+ if ( p2m_is_ram(t) )
+ {
+ gfns[j] = i;
+ j++;
+ BUG_ON(j > POD_SWEEP_STRIDE);
+ if ( j == POD_SWEEP_STRIDE )
+ {
+ p2m_pod_zero_check(d, gfns, j);
+ j = 0;
+ }
+ }
+ /* Stop if we're past our limit and we have found *something*.
+ *
+ * NB that this is a zero-sum game; we're increasing our cache size
+ * by re-increasing our 'debt'. Since we hold the p2m lock,
+ * (entry_count - count) must remain the same. */
+ if ( p2md->pod.count > 0 && i < limit )
+ break;
+ }
+
+ if ( j )
+ p2m_pod_zero_check(d, gfns, j);
+
+ p2md->pod.reclaim_single = i ? i - 1 : i;
+
+}
+
static int
p2m_pod_demand_populate(struct domain *d, unsigned long gfn,
mfn_t table_mfn,
@@ -522,6 +805,19 @@
p2m_unlock(p2md);
return 0;
}
+
+ /* If we're low, start a sweep */
+ if ( order == 9 && list_empty(&p2md->pod.super) )
+ p2m_pod_emergency_sweep_super(d);
+
+ if ( list_empty(&p2md->pod.single) &&
+ ( ( order == 0 )
+ || (order == 9 && list_empty(&p2md->pod.super) ) ) )
+ p2m_pod_emergency_sweep(d);
+
+ /* Keep track of the highest gfn demand-populated by a guest fault */
+ if ( q == p2m_guest && gfn > p2md->pod.max_guest )
+ p2md->pod.max_guest = gfn;
spin_lock(&d->page_alloc_lock);
diff -r 1e9ad800991c xen/common/grant_table.c
--- a/xen/common/grant_table.c Fri Dec 19 17:41:18 2008 +0000
+++ b/xen/common/grant_table.c Fri Dec 19 17:41:25 2008 +0000
@@ -110,6 +110,33 @@
#define ACGNT_PER_PAGE (PAGE_SIZE / sizeof(struct active_grant_entry))
#define active_entry(t, e) \
((t)->active[(e)/ACGNT_PER_PAGE][(e)%ACGNT_PER_PAGE])
+
+/* The p2m emergency sweep code should not reclaim a frame that is currenlty
+ * grant mapped by another domain. That would involve checking all other
+ * domains grant maps, which is impractical. Instead, we check the active
+ * grant table for this domain to see if it's been granted. Since this
+ * may be called as a result of a grant table op, we can't grab the lock. */
+int
+gnttab_is_granted(struct domain *d, xen_pfn_t gfn, int order)
+{
+ int i, found=0;
+ struct active_grant_entry *act;
+
+ /* We need to compare with active grant entries to make sure that
+ * pinned (== currently mapped) entries don't disappear under our
+ * feet. */
+ for ( i=0; i<nr_grant_entries(d->grant_table); i++ )
+ {
+ act = &active_entry(d->grant_table, i);
+ if ( act->gfn >> order == gfn >> order )
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ return found;
+}
static inline int
__get_maptrack_handle(
@@ -317,6 +344,7 @@
if ( !act->pin )
{
act->domid = scombo.shorts.domid;
+ act->gfn = sha->frame;
act->frame = gmfn_to_mfn(rd, sha->frame);
}
}
@@ -1335,6 +1363,7 @@
if ( !act->pin )
{
act->domid = scombo.shorts.domid;
+ act->gfn = sha->frame;
act->frame = gmfn_to_mfn(rd, sha->frame);
}
}
diff -r 1e9ad800991c xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Fri Dec 19 17:41:18 2008 +0000
+++ b/xen/include/asm-x86/p2m.h Fri Dec 19 17:41:25 2008 +0000
@@ -152,6 +152,9 @@
single; /* Non-super lists */
int count, /* # of pages in cache lists */
entry_count; /* # of pages in p2m marked pod */
+ unsigned reclaim_super; /* Last gpfn of a scan */
+ unsigned reclaim_single; /* Last gpfn of a scan */
+ unsigned max_guest; /* gpfn of max guest demand-populate */
} pod;
};
diff -r 1e9ad800991c xen/include/xen/grant_table.h
--- a/xen/include/xen/grant_table.h Fri Dec 19 17:41:18 2008 +0000
+++ b/xen/include/xen/grant_table.h Fri Dec 19 17:41:25 2008 +0000
@@ -32,6 +32,7 @@
struct active_grant_entry {
u32 pin; /* Reference count information. */
domid_t domid; /* Domain being granted access. */
+ unsigned long gfn; /* Guest's idea of the frame being granted. */
unsigned long frame; /* Frame being granted. */
};
@@ -146,4 +147,7 @@
return num_act_frames_from_sha_frames(nr_grant_frames(gt));
}
+int
+gnttab_is_granted(struct domain *d, xen_pfn_t gfn, int order);
+
#endif /* __XEN_GRANT_TABLE_H__ */
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #7: 06-pod-cache-superpages.diff --]
[-- Type: text/x-diff; name=06-pod-cache-superpages.diff, Size: 3971 bytes --]
diff -r d7ac5e33d86c xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Wed Dec 17 14:12:52 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Wed Dec 17 14:13:56 2008 +0000
@@ -321,6 +321,70 @@
spin_unlock(&d->page_alloc_lock);
return 0;
+}
+
+/* Get a page of size order from the populate-on-demand cache. Will break
+ * down 2-meg pages into singleton pages automatically. Returns null if
+ * a superpage is requested and no superpages are available. Must be called
+ * with the d->page_lock held. */
+static struct page_info * p2m_pod_cache_get(struct domain *d,
+ unsigned long order)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+ struct page_info *p = NULL;
+ int i;
+
+ if ( order == 9 && list_empty(&p2md->pod.super) )
+ {
+ return NULL;
+ }
+ else if ( order == 0 && list_empty(&p2md->pod.single) )
+ {
+ unsigned long mfn;
+ struct page_info *q;
+
+ BUG_ON( list_empty(&p2md->pod.super) );
+
+ /* Break up a superpage to make single pages. NB count doesn't
+ * need to be adjusted. */
+ printk("%s: Breaking up superpage.\n", __func__);
+ p = list_entry(p2md->pod.super.next, struct page_info, list);
+ list_del(&p->list);
+ mfn = mfn_x(page_to_mfn(p));
+
+ for ( i=0; i<(1<<9); i++ )
+ {
+ q = mfn_to_page(_mfn(mfn+i));
+ list_add_tail(&q->list, &p2md->pod.single);
+ }
+ }
+
+ switch ( order )
+ {
+ case 9:
+ BUG_ON( list_empty(&p2md->pod.super) );
+ p = list_entry(p2md->pod.super.next, struct page_info, list);
+ p2md->pod.count -= 1 << order; /* Lock: page_alloc */
+ break;
+ case 0:
+ BUG_ON( list_empty(&p2md->pod.single) );
+ p = list_entry(p2md->pod.single.next, struct page_info, list);
+ p2md->pod.count -= 1;
+ break;
+ default:
+ BUG();
+ }
+
+ list_del(&p->list);
+
+ /* Put the pages back on the domain page_list */
+ for ( i = 0 ; i < (1 << order) ; i++ )
+ {
+ BUG_ON(page_get_owner(p + i) != d);
+ list_add_tail(&p[i].list, &d->page_list);
+ }
+
+ return p;
}
void
@@ -815,35 +879,14 @@
if ( p2md->pod.count == 0 )
goto out_of_memory;
- /* FIXME -- use single pages / splinter superpages if need be */
- switch ( order )
- {
- case 9:
- BUG_ON( list_empty(&p2md->pod.super) );
- p = list_entry(p2md->pod.super.next, struct page_info, list);
- p2md->pod.count -= 1 << order; /* Lock: page_alloc */
- break;
- case 0:
- BUG_ON( list_empty(&p2md->pod.single) );
- p = list_entry(p2md->pod.single.next, struct page_info, list);
- p2md->pod.count -= 1;
- break;
- default:
- BUG();
- }
-
- list_del(&p->list);
+ /* Get a page f/ the cache. A NULL return value indicates that the
+ * 2-meg range should be marked singleton PoD, and retried */
+ if ( (p = p2m_pod_cache_get(d, order)) == NULL )
+ goto remap_and_retry;
mfn = page_to_mfn(p);
BUG_ON((mfn_x(mfn) & ((1 << order)-1)) != 0);
-
- /* Put the pages back on the domain page_list */
- for ( i = 0 ; i < (1 << order) ; i++ )
- {
- BUG_ON(page_get_owner(p + i) != d);
- list_add_tail(&p[i].list, &d->page_list);
- }
spin_unlock(&d->page_alloc_lock);
@@ -888,6 +931,18 @@
printk("%s: Out of populate-on-demand memory!\n", __func__);
domain_crash(d);
return -1;
+remap_and_retry:
+ BUG_ON(order != 9);
+ spin_unlock(&d->page_alloc_lock);
+
+ /* Remap this 2-meg region in singleton chunks */
+ gfn_aligned = (gfn>>order)<<order;
+ for(i=0; i<(1<<order); i++)
+ set_p2m_entry(d, gfn_aligned+i, _mfn(POPULATE_ON_DEMAND_MFN), 0,
+ p2m_populate_on_demand);
+ audit_p2m(d);
+ p2m_unlock(p2md);
+ return 0;
}
// Returns 0 on error (out of memory)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #8: 07-pod-xen-interface.diff --]
[-- Type: text/x-diff; name=07-pod-xen-interface.diff, Size: 13933 bytes --]
diff -r 90feb993b0b8 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/arch/x86/mm.c Tue Dec 23 11:35:30 2008 +0000
@@ -3976,6 +3976,49 @@
return 0;
}
+ case XENMEM_set_pod_target:
+ case XENMEM_get_pod_target:
+ {
+ xen_pod_target_t target;
+ struct domain *d;
+
+ /* Support DOMID_SELF? */
+ if ( !IS_PRIV(current->domain) )
+ return -EINVAL;
+
+ if ( copy_from_guest(&target, arg, 1) )
+ return -EFAULT;
+
+ rc = rcu_lock_target_domain_by_id(target.domid, &d);
+ if ( rc != 0 )
+ return rc;
+
+ if ( op == XENMEM_set_pod_target )
+ {
+ if ( target.target_pages > d->max_pages )
+ {
+ rc = -EINVAL;
+ goto pod_target_out_unlock;
+ }
+
+ rc = p2m_pod_set_mem_target(d, target.target_pages);
+ }
+
+ target.tot_pages = d->tot_pages;
+ target.pod_cache_pages = d->arch.p2m->pod.count;
+ target.pod_entries = d->arch.p2m->pod.entry_count;
+
+ if ( copy_to_guest(arg, &target, 1) )
+ {
+ rc= -EFAULT;
+ goto pod_target_out_unlock;
+ }
+
+ pod_target_out_unlock:
+ rcu_unlock_domain(d);
+ return rc;
+ }
+
default:
return subarch_memory_op(op, arg);
}
diff -r 90feb993b0b8 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Tue Dec 23 11:35:30 2008 +0000
@@ -387,6 +387,150 @@
return p;
}
+/* Set the size of the cache, allocating or freeing as necessary. */
+static int
+p2m_pod_set_cache_target(struct domain *d, unsigned long pod_target)
+{
+ struct p2m_domain *p2md = d->arch.p2m;
+ int ret = 0;
+
+ /* Increasing the target */
+ while ( pod_target > p2md->pod.count )
+ {
+ struct page_info * page;
+ int order;
+
+ if ( (pod_target - p2md->pod.count) >= (1>>9) )
+ order = 9;
+ else
+ order = 0;
+
+ page = alloc_domheap_pages(d, order, 0);
+ if ( unlikely(page == NULL) )
+ goto out;
+
+ p2m_pod_cache_add(d, page, order);
+ }
+
+ /* Decreasing the target */
+ /* We hold the p2m lock here, so we don't need to worry about
+ * cache disappearing under our feet. */
+ while ( pod_target < p2md->pod.count )
+ {
+ struct page_info * page;
+ int order, i;
+
+ /* Grab the lock before checking that pod.super is empty, or the last
+ * entries may disappear before we grab the lock. */
+ spin_lock(&d->page_alloc_lock);
+
+ if ( (p2md->pod.count - pod_target) > (1>>9)
+ && !list_empty(&p2md->pod.super) )
+ order = 9;
+ else
+ order = 0;
+
+ page = p2m_pod_cache_get(d, order);
+
+ ASSERT(page != NULL);
+
+ spin_unlock(&d->page_alloc_lock);
+
+ /* Then free them */
+ for ( i = 0 ; i < (1 << order) ; i++ )
+ {
+ /* Copied from common/memory.c:guest_remove_page() */
+ if ( unlikely(!get_page(page+i, d)) )
+ {
+ gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d->domain_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if ( test_and_clear_bit(_PGT_pinned, &(page+i)->u.inuse.type_info) )
+ put_page_and_type(page+i);
+
+ if ( test_and_clear_bit(_PGC_allocated, &(page+i)->count_info) )
+ put_page(page+i);
+
+ put_page(page+i);
+ }
+ }
+
+out:
+ return ret;
+}
+
+/*
+ * The "right behavior" here requires some careful thought. First, some
+ * definitions:
+ * + M: static_max
+ * + B: number of pages the balloon driver has ballooned down to.
+ * + P: Number of populated pages.
+ * + T: Old target
+ * + T': New target
+ *
+ * The following equations should hold:
+ * 0 <= P <= T <= B <= M
+ * d->arch.p2m->pod.entry_count == B - P
+ * d->tot_pages == P + d->arch.p2m->pod.count
+ *
+ * Now we have the following potential cases to cover:
+ * B <T': Set the PoD cache size equal to the number of outstanding PoD
+ * entries. The balloon driver will deflate the balloon to give back
+ * the remainder of the ram to the guest OS.
+ * T <T'<B : Increase PoD cache size.
+ * T'<T<=B : Here we have a choice. We can decrease the size of the cache,
+ * get the memory right away. However, that means every time we
+ * reduce the memory target we risk the guest attempting to populate the
+ * memory before the balloon driver has reached its new target. Safer to
+ * never reduce the cache size here, but only when the balloon driver frees
+ * PoD ranges.
+ *
+ * If there are many zero pages, we could reach the target also by doing
+ * zero sweeps and marking the ranges PoD; but the balloon driver will have
+ * to free this memory eventually anyway, so we don't actually gain that much
+ * by doing so.
+ *
+ * NB that the equation (B<T') may require adjustment to the cache
+ * size as PoD pages are freed as well; i.e., freeing a PoD-backed
+ * entry when pod.entry_count == pod.count requires us to reduce both
+ * pod.entry_count and pod.count.
+ */
+int
+p2m_pod_set_mem_target(struct domain *d, unsigned long target)
+{
+ unsigned pod_target;
+ struct p2m_domain *p2md = d->arch.p2m;
+ int ret = 0;
+ unsigned long populated;
+
+ /* P == B: Nothing to do. */
+ if ( p2md->pod.entry_count == 0 )
+ goto out;
+
+ /* T' < B: Don't reduce the cache size; let the balloon driver
+ * take care of it. */
+ if ( target < d->tot_pages )
+ goto out;
+
+ populated = d->tot_pages - p2md->pod.count;
+
+ pod_target = target - populated;
+
+ /* B < T': Set the cache size equal to # of outstanding entries,
+ * let the balloon driver fill in the rest. */
+ if ( pod_target > p2md->pod.entry_count )
+ pod_target = p2md->pod.entry_count;
+
+ ASSERT( pod_target > p2md->pod.count );
+
+ ret = p2m_pod_set_cache_target(d, pod_target);
+
+out:
+ return ret;
+}
+
void
p2m_pod_empty_cache(struct domain *d)
{
@@ -537,6 +681,13 @@
ram--;
}
}
+
+ /* If we've reduced our "liabilities" beyond our "assets", free some */
+ if ( p2md->pod.entry_count < p2md->pod.count )
+ {
+ printk("b %d\n", p2md->pod.entry_count);
+ p2m_pod_set_cache_target(d, p2md->pod.entry_count);
+ }
/* If there are no more non-PoD entries, tell decrease_reservation() that
* there's nothing left to do. */
@@ -786,7 +937,7 @@
/* Stop if we're past our limit and we have found *something*.
*
* NB that this is a zero-sum game; we're increasing our cache size
- * by re-increasing our 'debt'. Since we hold the p2m lock,
+ * by increasing our 'debt'. Since we hold the p2m lock,
* (entry_count - count) must remain the same. */
if ( !list_empty(&p2md->pod.super) && i < limit )
break;
diff -r 90feb993b0b8 xen/arch/x86/x86_64/compat/mm.c
--- a/xen/arch/x86/x86_64/compat/mm.c Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/arch/x86/x86_64/compat/mm.c Tue Dec 23 11:35:30 2008 +0000
@@ -122,6 +122,29 @@
#define XLAT_memory_map_HNDL_buffer(_d_, _s_) ((void)0)
XLAT_memory_map(&cmp, nat);
#undef XLAT_memory_map_HNDL_buffer
+ if ( copy_to_guest(arg, &cmp, 1) )
+ rc = -EFAULT;
+
+ break;
+ }
+
+ case XENMEM_set_pod_target:
+ case XENMEM_get_pod_target:
+ {
+ struct compat_pod_target cmp;
+ struct xen_pod_target *nat = (void *)COMPAT_ARG_XLAT_VIRT_BASE;
+
+ if ( copy_from_guest(&cmp, arg, 1) )
+ return -EFAULT;
+
+ XLAT_pod_target(nat, &cmp);
+
+ rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+ if ( rc < 0 )
+ break;
+
+ XLAT_pod_target(&cmp, nat);
+
if ( copy_to_guest(arg, &cmp, 1) )
rc = -EFAULT;
diff -r 90feb993b0b8 xen/common/memory.c
--- a/xen/common/memory.c Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/common/memory.c Tue Dec 23 11:35:30 2008 +0000
@@ -111,31 +111,40 @@
if ( unlikely(__copy_from_guest_offset(&gpfn, a->extent_list, i, 1)) )
goto out;
- page = alloc_domheap_pages(d, a->extent_order, a->memflags);
- if ( unlikely(page == NULL) )
+ if ( a->memflags & MEMF_populate_on_demand )
{
- gdprintk(XENLOG_INFO, "Could not allocate order=%d extent: "
- "id=%d memflags=%x (%ld of %d)\n",
- a->extent_order, d->domain_id, a->memflags,
- i, a->nr_extents);
- goto out;
+ if ( guest_physmap_mark_populate_on_demand(d, gpfn,
+ a->extent_order) < 0 )
+ goto out;
}
+ else
+ {
+ page = alloc_domheap_pages(d, a->extent_order, a->memflags);
+ if ( unlikely(page == NULL) )
+ {
+ gdprintk(XENLOG_INFO, "Could not allocate order=%d extent: "
+ "id=%d memflags=%x (%ld of %d)\n",
+ a->extent_order, d->domain_id, a->memflags,
+ i, a->nr_extents);
+ goto out;
+ }
- mfn = page_to_mfn(page);
- guest_physmap_add_page(d, gpfn, mfn, a->extent_order);
+ mfn = page_to_mfn(page);
+ guest_physmap_add_page(d, gpfn, mfn, a->extent_order);
- if ( !paging_mode_translate(d) )
- {
- for ( j = 0; j < (1 << a->extent_order); j++ )
- set_gpfn_from_mfn(mfn + j, gpfn + j);
+ if ( !paging_mode_translate(d) )
+ {
+ for ( j = 0; j < (1 << a->extent_order); j++ )
+ set_gpfn_from_mfn(mfn + j, gpfn + j);
- /* Inform the domain of the new page's machine address. */
- if ( unlikely(__copy_to_guest_offset(a->extent_list, i, &mfn, 1)) )
- goto out;
+ /* Inform the domain of the new page's machine address. */
+ if ( unlikely(__copy_to_guest_offset(a->extent_list, i, &mfn, 1)) )
+ goto out;
+ }
}
}
- out:
+out:
a->nr_done = i;
}
@@ -527,6 +536,10 @@
args.memflags |= MEMF_node(XENMEMF_get_node(reservation.mem_flags));
+ if ( op == XENMEM_populate_physmap
+ && (reservation.mem_flags & XENMEMF_populate_on_demand) )
+ args.memflags |= MEMF_populate_on_demand;
+
if ( likely(reservation.domid == DOMID_SELF) )
{
d = rcu_lock_current_domain();
diff -r 90feb993b0b8 xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/include/asm-x86/p2m.h Tue Dec 23 11:35:30 2008 +0000
@@ -261,6 +261,10 @@
* (usually in preparation for domain destruction) */
void p2m_pod_empty_cache(struct domain *d);
+/* Set populate-on-demand cache size so that the total memory allocated to a
+ * domain matches target */
+int p2m_pod_set_mem_target(struct domain *d, unsigned long target);
+
/* Call when decreasing memory reservation to handle PoD entries properly.
* Will return '1' if all entries were handled and nothing more need be done.*/
int
diff -r 90feb993b0b8 xen/include/public/memory.h
--- a/xen/include/public/memory.h Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/include/public/memory.h Tue Dec 23 11:35:30 2008 +0000
@@ -48,6 +48,8 @@
/* NUMA node to allocate from. */
#define XENMEMF_node(x) (((x) + 1) << 8)
#define XENMEMF_get_node(x) ((((x) >> 8) - 1) & 0xffu)
+/* Flag to populate physmap with populate-on-demand entries */
+#define XENMEMF_populate_on_demand (1<<16)
#endif
struct xen_memory_reservation {
@@ -299,6 +301,19 @@
typedef struct xen_foreign_memory_map xen_foreign_memory_map_t;
DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t);
+#define XENMEM_set_pod_target 16
+#define XENMEM_get_pod_target 17
+struct xen_pod_target {
+ /* IN */
+ uint64_t target_pages;
+ /* OUT */
+ uint64_t tot_pages;
+ uint64_t pod_cache_pages;
+ uint64_t pod_entries;
+ /* IN */
+ domid_t domid;
+};
+typedef struct xen_pod_target xen_pod_target_t;
#endif /* __XEN_PUBLIC_MEMORY_H__ */
/*
diff -r 90feb993b0b8 xen/include/xen/hypercall.h
--- a/xen/include/xen/hypercall.h Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/include/xen/hypercall.h Tue Dec 23 11:35:30 2008 +0000
@@ -48,7 +48,7 @@
* at what point in the page list to resume. For this purpose I steal the
* high-order bits of the @cmd parameter, which are otherwise unused and zero.
*/
-#define MEMOP_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
+#define MEMOP_EXTENT_SHIFT 6 /* cmd[:6] == start_extent */
#define MEMOP_CMD_MASK ((1 << MEMOP_EXTENT_SHIFT) - 1)
extern long
diff -r 90feb993b0b8 xen/include/xen/mm.h
--- a/xen/include/xen/mm.h Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/include/xen/mm.h Tue Dec 23 11:35:30 2008 +0000
@@ -72,6 +72,8 @@
/* memflags: */
#define _MEMF_no_refcount 0
#define MEMF_no_refcount (1U<<_MEMF_no_refcount)
+#define _MEMF_populate_on_demand 1
+#define MEMF_populate_on_demand (1U<<_MEMF_populate_on_demand)
#define _MEMF_node 8
#define MEMF_node(n) ((((n)+1)&0xff)<<_MEMF_node)
#define _MEMF_bits 24
diff -r 90feb993b0b8 xen/include/xlat.lst
--- a/xen/include/xlat.lst Fri Dec 19 17:54:23 2008 +0000
+++ b/xen/include/xlat.lst Tue Dec 23 11:35:30 2008 +0000
@@ -38,6 +38,7 @@
! memory_exchange memory.h
! memory_map memory.h
! memory_reservation memory.h
+! pod_target memory.h
! translate_gpfn_list memory.h
! sched_poll sched.h
? sched_remote_shutdown sched.h
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #9: 08-libxc-interface.diff --]
[-- Type: text/x-diff; name=08-libxc-interface.diff, Size: 9972 bytes --]
diff -r 2e9bacf8915c tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Fri Dec 19 17:54:23 2008 +0000
+++ b/tools/libxc/xc_domain.c Fri Dec 19 17:54:45 2008 +0000
@@ -562,6 +562,76 @@
}
return err;
+}
+
+static int xc_domain_memory_pod_target(int xc_handle,
+ int op,
+ uint32_t domid,
+ uint64_t target_pages,
+ uint64_t *tot_pages,
+ uint64_t *pod_cache_pages,
+ uint64_t *pod_entries)
+{
+ int err;
+
+ struct xen_pod_target pod_target = {
+ .domid = domid,
+ .target_pages = target_pages
+ };
+
+ err = xc_memory_op(xc_handle, op, &pod_target);
+
+ if ( err < 0 )
+ {
+ DPRINTF("Failed %s_memory_target dom %d\n",
+ (op==XENMEM_set_pod_target)?"set":"get",
+ domid);
+ errno = -err;
+ err = -1;
+ }
+ else
+ err = 0;
+
+ if ( tot_pages )
+ *tot_pages = pod_target.tot_pages;
+ if ( pod_cache_pages )
+ *pod_cache_pages = pod_target.pod_cache_pages;
+ if ( pod_entries )
+ *pod_entries = pod_target.pod_entries;
+
+ return err;
+}
+
+
+int xc_domain_memory_set_pod_target(int xc_handle,
+ uint32_t domid,
+ uint64_t target_pages,
+ uint64_t *tot_pages,
+ uint64_t *pod_cache_pages,
+ uint64_t *pod_entries)
+{
+ return xc_domain_memory_pod_target(xc_handle,
+ XENMEM_set_pod_target,
+ domid,
+ target_pages,
+ tot_pages,
+ pod_cache_pages,
+ pod_entries);
+}
+
+int xc_domain_memory_get_pod_target(int xc_handle,
+ uint32_t domid,
+ uint64_t *tot_pages,
+ uint64_t *pod_cache_pages,
+ uint64_t *pod_entries)
+{
+ return xc_domain_memory_pod_target(xc_handle,
+ XENMEM_get_pod_target,
+ domid,
+ -1,
+ tot_pages,
+ pod_cache_pages,
+ pod_entries);
}
int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
diff -r 2e9bacf8915c tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c Fri Dec 19 17:54:23 2008 +0000
+++ b/tools/libxc/xc_hvm_build.c Fri Dec 19 17:54:45 2008 +0000
@@ -146,11 +146,13 @@
}
static int setup_guest(int xc_handle,
- uint32_t dom, int memsize,
+ uint32_t dom, int memsize, int target,
char *image, unsigned long image_size)
{
xen_pfn_t *page_array = NULL;
unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
+ unsigned long target_pages = (unsigned long)target << (20 - PAGE_SHIFT);
+ unsigned long pod_pages = 0;
unsigned long special_page_nr, entry_eip, cur_pages;
struct xen_add_to_physmap xatp;
struct shared_info *shared_info;
@@ -160,10 +162,15 @@
uint64_t v_start, v_end;
int rc;
xen_capabilities_info_t caps;
+ int pod_mode = 0;
+
/* An HVM guest must be initialised with at least 2MB memory. */
- if ( memsize < 2 )
+ if ( memsize < 2 || target < 2 )
goto error_out;
+
+ if ( memsize > target )
+ pod_mode = 1;
if ( elf_init(&elf, image, image_size) != 0 )
goto error_out;
@@ -235,6 +242,10 @@
.extent_order = SUPERPAGE_PFN_SHIFT,
.domid = dom
};
+
+ if ( pod_mode )
+ sp_req.mem_flags = XENMEMF_populate_on_demand;
+
set_xen_guest_handle(sp_req.extent_start, sp_extents);
for ( i = 0; i < sp_req.nr_extents; i++ )
sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_PFN_SHIFT)];
@@ -242,6 +253,11 @@
if ( done > 0 )
{
done <<= SUPERPAGE_PFN_SHIFT;
+ if ( pod_mode && target_pages > cur_pages )
+ {
+ int d = target_pages - cur_pages;
+ pod_pages += ( done < d ) ? done : d;
+ }
cur_pages += done;
count -= done;
}
@@ -253,8 +269,16 @@
rc = xc_domain_memory_populate_physmap(
xc_handle, dom, count, 0, 0, &page_array[cur_pages]);
cur_pages += count;
+ if ( pod_mode )
+ pod_pages -= count;
}
}
+
+ if ( pod_mode )
+ rc = xc_domain_memory_set_pod_target(xc_handle,
+ dom,
+ pod_pages,
+ NULL, NULL, NULL);
if ( rc != 0 )
{
@@ -354,6 +378,7 @@
static int xc_hvm_build_internal(int xc_handle,
uint32_t domid,
int memsize,
+ int target,
char *image,
unsigned long image_size)
{
@@ -363,7 +388,7 @@
return -1;
}
- return setup_guest(xc_handle, domid, memsize, image, image_size);
+ return setup_guest(xc_handle, domid, memsize, target, image, image_size);
}
static inline int is_loadable_phdr(Elf32_Phdr *phdr)
@@ -388,7 +413,34 @@
((image = xc_read_image(image_name, &image_size)) == NULL) )
return -1;
- sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+ sts = xc_hvm_build_internal(xc_handle, domid, memsize, memsize, image, image_size);
+
+ free(image);
+
+ return sts;
+}
+
+/* xc_hvm_build_target_mem:
+ * Create a domain for a pre-ballooned virtualized Linux, using
+ * files/filenames. If target < memsize, domain is created with
+ * memsize pages marked populate-on-demand, and with a PoD cache size
+ * of target. If target == memsize, pages are populated normally.
+ */
+int xc_hvm_build_target_mem(int xc_handle,
+ uint32_t domid,
+ int memsize,
+ int target,
+ const char *image_name)
+{
+ char *image;
+ int sts;
+ unsigned long image_size;
+
+ if ( (image_name == NULL) ||
+ ((image = xc_read_image(image_name, &image_size)) == NULL) )
+ return -1;
+
+ sts = xc_hvm_build_internal(xc_handle, domid, memsize, target, image, image_size);
free(image);
@@ -423,7 +475,7 @@
return -1;
}
- sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+ sts = xc_hvm_build_internal(xc_handle, domid, memsize, memsize,
img, img_len);
/* xc_inflate_buffer may return the original buffer pointer (for
diff -r 2e9bacf8915c tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c Fri Dec 19 17:54:23 2008 +0000
+++ b/tools/libxc/xc_private.c Fri Dec 19 17:54:45 2008 +0000
@@ -323,6 +323,14 @@
goto out1;
}
break;
+ case XENMEM_set_pod_target:
+ case XENMEM_get_pod_target:
+ if ( lock_pages(arg, sizeof(struct xen_pod_target)) )
+ {
+ PERROR("Could not lock");
+ goto out1;
+ }
+ break;
}
ret = do_xen_hypercall(xc_handle, &hypercall);
@@ -354,6 +362,10 @@
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
unlock_pages(arg, sizeof(domid_t));
+ break;
+ case XENMEM_set_pod_target:
+ case XENMEM_get_pod_target:
+ unlock_pages(arg, sizeof(struct xen_pod_target));
break;
}
diff -r 2e9bacf8915c tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Fri Dec 19 17:54:23 2008 +0000
+++ b/tools/libxc/xenctrl.h Fri Dec 19 17:54:45 2008 +0000
@@ -634,6 +634,19 @@
xen_pfn_t *gpfn_list,
xen_pfn_t *mfn_list);
+int xc_domain_memory_set_pod_target(int xc_handle,
+ uint32_t domid,
+ uint64_t target_pages,
+ uint64_t *tot_pages,
+ uint64_t *pod_cache_pages,
+ uint64_t *pod_entries);
+
+int xc_domain_memory_get_pod_target(int xc_handle,
+ uint32_t domid,
+ uint64_t *tot_pages,
+ uint64_t *pod_cache_pages,
+ uint64_t *pod_entries);
+
int xc_domain_ioport_permission(int xc_handle,
uint32_t domid,
uint32_t first_port,
diff -r 2e9bacf8915c tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Fri Dec 19 17:54:23 2008 +0000
+++ b/tools/libxc/xenguest.h Fri Dec 19 17:54:45 2008 +0000
@@ -130,6 +130,12 @@
int memsize,
const char *image_name);
+int xc_hvm_build_target_mem(int xc_handle,
+ uint32_t domid,
+ int memsize,
+ int target,
+ const char *image_name);
+
int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #10: 09-xend.diff --]
[-- Type: text/x-diff; name=09-xend.diff, Size: 5075 bytes --]
diff -r a6133df55f3f tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Fri Dec 19 17:54:46 2008 +0000
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Dec 19 17:55:08 2008 +0000
@@ -890,17 +890,20 @@
int i;
#endif
char *image;
- int memsize, vcpus = 1, acpi = 0, apic = 1;
+ int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1;
static char *kwd_list[] = { "domid",
- "memsize", "image", "vcpus", "acpi",
+ "memsize", "image", "target", "vcpus", "acpi",
"apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iii", kwd_list,
- &dom, &memsize,
- &image, &vcpus, &acpi, &apic) )
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
+ &dom, &memsize, &image, &target, &vcpus,
+ &acpi, &apic) )
return NULL;
- if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
+ if ( target == -1 )
+ target = memsize;
+
+ if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize, target, image) != 0 )
return pyxc_error_to_exception();
#if !defined(__ia64__)
@@ -1329,6 +1332,24 @@
return NULL;
if (xc_domain_setmaxmem(self->xc_handle, dom, maxmem_kb) != 0)
+ return pyxc_error_to_exception();
+
+ Py_INCREF(zero);
+ return zero;
+}
+
+static PyObject *pyxc_domain_set_target_mem(XcObject *self, PyObject *args)
+{
+ uint32_t dom;
+ unsigned int mem_kb, mem_pages;
+
+ if (!PyArg_ParseTuple(args, "ii", &dom, &mem_kb))
+ return NULL;
+
+ mem_pages = mem_kb / 4;
+
+ if (xc_domain_memory_set_pod_target(self->xc_handle, dom, mem_pages,
+ NULL, NULL, NULL) != 0)
return pyxc_error_to_exception();
Py_INCREF(zero);
@@ -1815,6 +1836,14 @@
" maxmem_kb [int]: .\n"
"Returns: [int] 0 on success; -1 on error.\n" },
+ { "domain_set_target_mem",
+ (PyCFunction)pyxc_domain_set_target_mem,
+ METH_VARARGS, "\n"
+ "Set a domain's memory target\n"
+ " dom [int]: Identifier of domain.\n"
+ " mem_kb [int]: .\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
{ "domain_set_memmap_limit",
(PyCFunction)pyxc_domain_set_memmap_limit,
METH_VARARGS, "\n"
diff -r a6133df55f3f tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Fri Dec 19 17:54:46 2008 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py Fri Dec 19 17:55:08 2008 +0000
@@ -1104,10 +1104,10 @@
self.info['name_label'], str(self.domid), target)
MiB = 1024 * 1024
+ memory_cur = self.get_memory_dynamic_max() / MiB
if self.domid == 0:
dom0_min_mem = xoptions.get_dom0_min_mem()
- memory_cur = self.get_memory_dynamic_max() / MiB
if target < memory_cur and dom0_min_mem > target:
raise XendError("memory_dynamic_max too small")
@@ -1115,8 +1115,12 @@
self._safe_set_memory('memory_dynamic_max', target * MiB)
if self.domid >= 0:
+ if target > memory_cur:
+ balloon.free( (target-memory_cur)*1024 )
self.storeVm("memory", target)
self.storeDom("memory/target", target << 10)
+ xc.domain_set_target_mem(self.domid,
+ (target * 1024))
xen.xend.XendDomain.instance().managed_config_save(self)
def setMemoryMaximum(self, limit):
diff -r a6133df55f3f tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Fri Dec 19 17:54:46 2008 +0000
+++ b/tools/python/xen/xend/image.py Fri Dec 19 17:55:08 2008 +0000
@@ -799,19 +799,22 @@
def buildDomain(self):
store_evtchn = self.vm.getStorePort()
+ memmax_mb = self.getRequiredMaximumReservation() / 1024
mem_mb = self.getRequiredInitialReservation() / 1024
log.debug("domid = %d", self.vm.getDomid())
log.debug("image = %s", self.loader)
log.debug("store_evtchn = %d", store_evtchn)
- log.debug("memsize = %d", mem_mb)
+ log.debug("memsize = %d", memmax_mb)
+ log.debug("target = %d", mem_mb)
log.debug("vcpus = %d", self.vm.getVCpuCount())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
- memsize = mem_mb,
+ memsize = memmax_mb,
+ target = mem_mb,
vcpus = self.vm.getVCpuCount(),
acpi = self.acpi,
apic = self.apic)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #11: fix-audit.diff --]
[-- Type: text/x-diff; name=fix-audit.diff, Size: 1120 bytes --]
diff -r a76b4e00e186 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Tue Dec 16 13:14:25 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c Wed Dec 17 12:59:25 2008 +0000
@@ -693,6 +693,8 @@
if ( test_linear )
flush_tlb_local();
+ spin_lock(&d->page_alloc_lock);
+
/* Audit part one: walk the domain's page allocation list, checking
* the m2p entries. */
for ( entry = d->page_list.next;
@@ -760,6 +762,8 @@
// mfn, gfn, p2mfn, lp2mfn);
}
+ spin_unlock(&d->page_alloc_lock);
+
/* Audit part two: walk the domain's p2m table, checking the entries. */
if ( pagetable_get_pfn(d->arch.phys_table) != 0 )
{
@@ -815,7 +819,7 @@
for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++)
{
m2pfn = get_gpfn_from_mfn(mfn+i1);
- if ( m2pfn != (gfn + i) )
+ if ( m2pfn != (gfn + i1) )
{
pmbad++;
P2M_PRINTK("mismatch: gfn %#lx -> mfn %#lx"
[-- Attachment #12: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply
* Re: [PULL] cpumask tree
From: Mike Travis @ 2009-01-03 18:14 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Rusty Russell, Linus Torvalds, linux-kernel
In-Reply-To: <20090103174520.GA16704@elte.hu>
Ingo Molnar wrote:
> * Mike Travis <travis@sgi.com> wrote:
>
>>> yep, that's the bad one. Should i revert it or do you have a safe fix
>>> in mind?
>> Probably revert for now. [...]
>
> done.
>
> But -tip testing found another bug today as well, a boot crash with
> certain (rare) 64-bit configs:
>
> [ 1.588202] ACPI: PCI Interrupt Link [LNKA] (IRQs<1>BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
> [ 1.588012] IP: [<ffffffff80239778>] find_busiest_group+0x198/0xa20
>
> [ 1.588048] Call Trace:
> [ 1.588049] <IRQ> <0> [<ffffffff80240f96>] rebalance_domains+0x196/0x5e0
> [ 1.588052] [<ffffffff80270b15>] ? lock_release_holdtime+0x35/0x1e0
> [ 1.588055] [<ffffffff80983f70>] ? _spin_unlock_irq+0x30/0x40
> [ 1.588058] [<ffffffff8024300e>] run_rebalance_domains+0x4e/0x120
> [ 1.588060] [<ffffffff8024f80c>] __do_softirq+0xac/0x190
> [ 1.588063] [<ffffffff8020d13c>] call_softirq+0x1c/0x30
> [ 1.588066] [<ffffffff8020ef35>] do_softirq+0x75/0xa0
> [ 1.588067] [<ffffffff8024f47d>] irq_exit+0x9d/0xb0
> [ 1.588069] [<ffffffff80984f5d>] smp_apic_timer_interrupt+0x8d/0xc3
> [ 1.588071] [<ffffffff8020cb73>] apic_timer_interrupt+0x13/0x20
>
> i just bisected it back to:
>
> | 74c5409893751c400547184751410c61930043b2 is first bad commit
> | commit 74c5409893751c400547184751410c61930043b2
> | Author: Mike Travis <travis@sgi.com>
> | Date: Wed Dec 31 18:08:45 2008 -0800
> |
> | x86: cleanup remaining cpumask_t ops in smpboot code
> |
> | Impact: Reduce memory usage and use new cpumask API.
>
> this is in the final pieces of changes you did after pulling Rusty's tree:
>
> 26e2013: x86: setup_per_cpu_areas() cleanup
> 44aa683: cpumask: fix compile error when CONFIG_NR_CPUS is not defined
> eeff031: cpumask: use alloc_cpumask_var_node where appropriate
> 40fbcb0: cpumask: convert shared_cpu_map in acpi_processor* structs to cpumask_var
> 197e99c: x86: use cpumask_var_t in acpi/boot.c
> 2d22bd5: x86: cleanup remaining cpumask_t code in microcode_core.c
> 22022f5: x86: cleanup remaining cpumask_t code in mce_amd_64.c
> b5f3096: x86: cleanup some remaining usages of NR_CPUS where s/b nr_cpu_ids
> efb897c: sched: put back some stack hog changes that were undone in kernel/sched.c
> 74c5409: x86: cleanup remaining cpumask_t ops in smpboot code
> 8627b2a: x86: enable cpus display of kernel_max and offlined cpus
> 095fb96: Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/ru
>
> i think i'll just rebase the tail portion of cpus4096 starting at 8627b2a
> - this keeps most of the history intact and avoids these ugly reverts.
>
> Also, while bisecting this window of commits i found that neither would
> build successfully due to a typo - and the typo is fixed in 095fb96. So
> since we rebase this portion anyway due to excessive amount of bugs, i'll
> make it fully bisectable by rebasing right at 095fb96, backmerge the
> fixlet from eeff031 and redo the whole series dropping the two bad
> patches. Since this portion of the tree has no appreciable testing value
> the rebase is the right thing to do here.
>
> Ingo
Ok, thanks. Still working through my queue... I'll re-pull when you've
got your part done.
Mike
^ permalink raw reply
* Re: [PULL] cpumask tree
From: Ingo Molnar @ 2009-01-03 18:13 UTC (permalink / raw)
To: Mike Travis; +Cc: Rusty Russell, Linus Torvalds, linux-kernel
In-Reply-To: <20090103174520.GA16704@elte.hu>
* Ingo Molnar <mingo@elte.hu> wrote:
> Also, while bisecting this window of commits i found that neither would
> build successfully due to a typo - and the typo is fixed in 095fb96. So
> since we rebase this portion anyway due to excessive amount of bugs,
> i'll make it fully bisectable by rebasing right at 095fb96, backmerge
> the fixlet from eeff031 and redo the whole series dropping the two bad
> patches. Since this portion of the tree has no appreciable testing value
> the rebase is the right thing to do here.
okay, i've done this now and pushed out the resulting tree to
tip/cpus4096-v2. It is a no-content-changed reshuffle of the tail ~10
commits of tip/cpus4096:
$ git diff cpus4096..cpus4096-v2
$
i dropped the two broken patches i bisected today, and backmerged a fixlet
to make it more bisectable, and reordered fixes next to the merge point -
and the new changes now come after that.
this finally is something that has no known regressions and looks pushable
to Linus. I've started the -tip tests, lets see how well this holds up
now.
Ingo
^ permalink raw reply
* Re: [PATCH for -tip 4/4] irq: for_each_irq_desc() makes simplify
From: KOSAKI Motohiro @ 2009-01-03 18:11 UTC (permalink / raw)
To: Raja R Harinath, linux-kernel, Ingo Molnar, Yinghai Lu; +Cc: kosaki.motohiro
In-Reply-To: <2f11576a0901012156w30a6b162v96aed31d357929e6@mail.gmail.com>
> Hi
>
> >> # define for_each_irq_desc(irq, desc) \
> >> for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; \
> >> - irq++, desc = irq_to_desc(irq))
> >> + irq++, desc = irq_to_desc(irq)) \
> >> + if (desc)
> >> +
> >> +
> >> # define for_each_irq_desc_reverse(irq, desc) \
> >> for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; \
> >> - irq--, desc = irq_to_desc(irq))
> >> + irq--, desc = irq_to_desc(irq)) \
> >> + if (desc)
> >
> > I know this has gone in, but isn't this naked 'if' unsafe. Consider the
> > following hypothetical code:
> >
> > if (safe)
> > for_each_irq_desc(irq, desc) {
> > ...
> > }
> > else
> > panic();
> >
> > With the macro definition above, the loop would panic() each time !desc,
> > and _not_ panic() when !safe. I'd consider this behaviour to be
> > unexpected, to say the least :-)
>
> Correct.
>
> > The fix is to change the
> >
> > if (desc)
> >
> > in the macro to
> >
> > if (!desc) ; else
>
> Ok. I'll do that.
> Very thanks for good reviewing.
Done.
Thnaks Raja.
Ingo, could you please apply this patch to -tip tree?
===
>From 6f1210e6912afd8ca07518e82f89ba92137302b2 Mon Sep 17 00:00:00 2001
From: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Date: Sun, 4 Jan 2009 02:37:26 +0900
Subject: [PATCH] sparseirq: fix for_each_irq_desc() nit
Raja reported for_each_irq_desc() has possibility unsafeness.
if anyone write folliwing code, for_each_irq_desc() doesn't works intetionally.
(Now, its code doesn't exist at all)
if (safe)
for_each_irq_desc(irq, desc) {
...
}
else
panic();
Reported-by: Raja R Harinath <harinath@hurrynot.org>
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Yinghai Lu <yinghai@kernel.org>
---
include/linux/irqnr.h | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h
index 5504a5c..99b91c6 100644
--- a/include/linux/irqnr.h
+++ b/include/linux/irqnr.h
@@ -23,13 +23,17 @@ extern struct irq_desc *irq_to_desc(unsigned int irq);
# define for_each_irq_desc(irq, desc) \
for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; \
irq++, desc = irq_to_desc(irq)) \
- if (desc)
+ if (!desc) \
+ ; \
+ else
# define for_each_irq_desc_reverse(irq, desc) \
for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; \
irq--, desc = irq_to_desc(irq)) \
- if (desc)
+ if (!desc) \
+ ; \
+ else
#endif /* CONFIG_GENERIC_HARDIRQS */
--
1.5.3
^ permalink raw reply related
* Re: [linux-dvb] DVB-S Channel searching problem
From: Roman Jarosz @ 2009-01-03 18:11 UTC (permalink / raw)
To: linux-dvb
In-Reply-To: <c74595dc0901030928r7a3e3353h5c2a44ffd8ffd82f@mail.gmail.com>
On Sat, 03 Jan 2009 18:28:03 +0100, Alex Betis <alex.betis@gmail.com> wrote:
> On Sat, Jan 3, 2009 at 6:42 PM, Roman Jarosz <roman.jarosz@gmail.com>
> wrote:
>
>> Hi,
>>
>> I have a problem with DVB-S channel searching, the scan command doesn't
>> find all channels in Linux on Astra 19.2E.
>> It works in Windows.
>>
> Please specify what driver you use, what scan application, what is the
> command line you gave to the scan application, what is the frequency file
> you've used for scan application, what is the result of the scan you
> have.
>
> Than maybe I can help somehow.
I use scan from dvb-apps, the command is
"scan -o vdr /root/dvb/Astra-19.2E > /etc/vdr/channels.conf"
where /root/dvb/Astra-19.2E is file with "S 11567500 V 22000000 5/6"
I use cx88-dvb driver but many modules are loaded with it see
http://kedge.wz.cz/dvb/lsmod.txt
Scan console output is in file http://kedge.wz.cz/dvb/channels.conf
and the result in http://kedge.wz.cz/dvb/channels.conf
When console shows
__tune_to_transponder:1508: ERROR: Setting frontend parameters failed: 22 Invalid argument
the dmesg prints
DVB: adapter 0 frontend 0 frequency 8175750 out of range (950000..2150000)
Roman
_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
^ permalink raw reply
* [linux-dvb] Problem in 2.6.28 kernel with dvb-usb
From: Tero Siironen @ 2009-01-03 18:09 UTC (permalink / raw)
To: linux-dvb
Hi,
I compiled 2.6.28 kernel to my Fedora 9 setup yesterday and my Artec
T14BR DVB-T USB stick stopped to work properly. It is recognized
correctly but when the stream receiver is started I get this message:
kernel: dvb-usb: could not submit URB no. 0 - get them all back
and no sound or picture is played with vdr. This happen 9 times out of
10. And that 1/10 time the reception is very bad. My previous kernel
compilation is 2.6.28-rc6 and the device works just fine with that
kernel.
Here is the snippets from dmesg and /var/log/messages:
2.6.28 kernel:
dmesg:
usb 1-5: new high speed USB device using ehci_hcd and address 8
usb 1-5: configuration #1 chosen from 1 choice
usb 1-5: New USB device found, idVendor=05d8, idProduct=810f
usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-5: Product: ART7070
usb 1-5: Manufacturer: Ultima
usb 1-5: SerialNumber: 001
dib0700: loaded with support for 8 different device-types
dvb-usb: found a 'Artec T14BR DVB-T' in cold state, will try to load a
firmware
usb 1-5: firmware: requesting dvb-usb-dib0700-1.20.fw
dvb-usb: downloading firmware from file 'dvb-usb-dib0700-1.20.fw'
dib0700: firmware started successfully.
dvb-usb: found a 'Artec T14BR DVB-T' in warm state.
dvb-usb: will pass the complete MPEG2 transport stream to the software
demuxer.
DVB: registering new adapter (Artec T14BR DVB-T)
DVB: registering adapter 0 frontend 0 (DiBcom 7000PC)...
DiB0070: successfully identified
dvb-usb: Artec T14BR DVB-T successfully initialized and connected.
usbcore: registered new interface driver dvb_usb_dib0700
usbcore: registered new interface driver dvb_usb_dibusb_mc
dvb-usb: could not submit URB no. 0 - get them all back
/var/log/messages:
Jan 3 13:38:13 dvbsystem kernel: usbcore: registered new interface
driver dvb_usb_dibusb_mc
Jan 3 13:38:13 dvbsystem kernel: dib0700: loaded with support for 8
different device-types
Jan 3 13:38:13 dvbsystem kernel: dvb-usb: found a 'Artec T14BR DVB-T'
in warm state.
Jan 3 13:38:13 dvbsystem kernel: dvb-usb: will pass the complete
MPEG2 transport stream to the software demuxer.
Jan 3 13:38:13 dvbsystem kernel: DVB: registering new adapter (Artec
T14BR DVB-T)
Jan 3 13:38:13 dvbsystem kernel: DVB: registering adapter 0 frontend
0 (DiBcom 7000PC)...
Jan 3 13:38:13 dvbsystem kernel: DiB0070: successfully identified
Jan 3 13:38:13 dvbsystem kernel: dvb-usb: Artec T14BR DVB-T
successfully initialized and connected.
Jan 3 13:38:13 dvbsystem kernel: usbcore: registered new interface
driver dvb_usb_dib0700
Jan 3 13:38:16 dvbsystem vdr: [4204] receiver on device 1 thread
started (pid=4172, tid=4204)
Jan 3 13:38:16 dvbsystem kernel: dvb-usb: could not submit URB no. 0
- get them all back
Jan 3 13:38:16 dvbsystem vdr: [4205] TS buffer on device 1 thread
started (pid=4172, tid=4205)
2.6.28-rc6 kernel:
dmesg:
usb 1-5: new high speed USB device using ehci_hcd and address 6
usb 1-5: configuration #1 chosen from 1 choice
usb 1-5: New USB device found, idVendor=05d8, idProduct=810f
usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-5: Product: ART7070
usb 1-5: Manufacturer: Ultima
usb 1-5: SerialNumber: 001
dib0700: loaded with support for 8 different device-types
dvb-usb: found a 'Artec T14BR DVB-T' in cold state, will try to load a
firmware
usb 1-5: firmware: requesting dvb-usb-dib0700-1.20.fw
dvb-usb: downloading firmware from file 'dvb-usb-dib0700-1.20.fw'
dib0700: firmware started successfully.
dvb-usb: found a 'Artec T14BR DVB-T' in warm state.
dvb-usb: will pass the complete MPEG2 transport stream to the software
demuxer.
DVB: registering new adapter (Artec T14BR DVB-T)
DVB: registering adapter 0 frontend 0 (DiBcom 7000PC)...
DiB0070: successfully identified
dvb-usb: Artec T14BR DVB-T successfully initialized and connected.
usbcore: registered new interface driver dvb_usb_dib0700
usbcore: registered new interface driver dvb_usb_dibusb_mc
/var/log/messages:
Jan 3 13:21:04 dvbsystem kernel: usb 1-5: new high speed USB device
using ehci_hcd and address 6
Jan 3 13:21:05 dvbsystem kernel: usb 1-5: configuration #1 chosen
from 1 choice
Jan 3 13:21:05 dvbsystem kernel: usb 1-5: New USB device found,
idVendor=05d8, idProduct=810f
Jan 3 13:21:05 dvbsystem kernel: usb 1-5: New USB device strings:
Mfr=1, Product=2, SerialNumber=3
Jan 3 13:21:05 dvbsystem kernel: usb 1-5: Product: ART7070
Jan 3 13:21:05 dvbsystem kernel: usb 1-5: Manufacturer: Ultima
Jan 3 13:21:05 dvbsystem kernel: usb 1-5: SerialNumber: 001
Jan 3 13:21:05 dvbsystem kernel: dib0700: loaded with support for 8
different device-types
Jan 3 13:21:05 dvbsystem kernel: dvb-usb: found a 'Artec T14BR DVB-T'
in cold state, will try to load a firmware
Jan 3 13:21:05 dvbsystem kernel: usb 1-5: firmware: requesting dvb-
usb-dib0700-1.20.fw
Jan 3 13:21:05 dvbsystem kernel: dvb-usb: downloading firmware from
file 'dvb-usb-dib0700-1.20.fw'
Jan 3 13:21:05 dvbsystem kernel: dib0700: firmware started
successfully.
Jan 3 13:21:05 dvbsystem kernel: dvb-usb: found a 'Artec T14BR DVB-T'
in warm state.
Jan 3 13:21:05 dvbsystem kernel: dvb-usb: will pass the complete
MPEG2 transport stream to the software demuxer.
Jan 3 13:21:05 dvbsystem kernel: DVB: registering new adapter (Artec
T14BR DVB-T)
Jan 3 13:21:06 dvbsystem kernel: DVB: registering adapter 0 frontend
0 (DiBcom 7000PC)...
Jan 3 13:21:06 dvbsystem kernel: DiB0070: successfully identified
Jan 3 13:21:06 dvbsystem kernel: dvb-usb: Artec T14BR DVB-T
successfully initialized and connected.
Jan 3 13:21:06 dvbsystem kernel: usbcore: registered new interface
driver dvb_usb_dib0700
Jan 3 13:22:38 dvbsystem kernel: usbcore: registered new interface
driver dvb_usb_dibusb_mc
Jan 3 13:22:41 dvbsystem vdr: [3021] receiver on device 1 thread
started (pid=2990, tid=3021)
Jan 3 13:22:41 dvbsystem vdr: [3022] TS buffer on device 1 thread
started (pid=2990, tid=3022)
--
Tero
_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
^ permalink raw reply
* Re: Problem with fonts in different width
From: Colin D Bennett @ 2009-01-03 18:06 UTC (permalink / raw)
To: The development of GRUB 2; +Cc: bean123ch
In-Reply-To: <ca0f59980901030953p45c5345el2c323a7c9cf3f62f@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1092 bytes --]
On Sun, 4 Jan 2009 01:53:16 +0800
Bean <bean123ch@gmail.com> wrote:
> Hi,
>
> Unicode characters are split into two sizes, 16x16 and 16x8, and are
> stored in different files, for example:
>
> f16.pcf.gz
> -efont-fixed-medium-r-normal--16-160-75-75-c-160-iso10646-1
>
> h16.pcf.gz
> -efont-fixed-medium-r-normal--16-160-75-75-c-80-iso10646-1
>
> They can be converted to f16.pf2 and h16.pf2. However, only one font
> can be active at at time. So if we use both full and half width
> characters, some of them is not displayed properly. The pf2 format
> seems to allow different font widths. Perhaps the converter should
> allow multiple input, so that we can merge the two fonts into one pf2
> ?
This would be fairly simple to do. The font would then effectively be
a proportional-width font since the new font engine+gfxterm does not
handle "bi-width" fonts in a character-cell environment.
I try adding the multiple font input feature when I have a chance.
Vesa wants the convert re-implemented in C, though, which will take
some time.
Regards,
Colin
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH] pxa-camera: fix redefinition warnings and missing DMA definitions
From: Mauro Carvalho Chehab @ 2009-01-03 18:02 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: video4linux-list, Mauro Carvalho Chehab
In-Reply-To: <Pine.LNX.4.64.0901031714150.3955@axis700.grange>
On Sat, 3 Jan 2009, Guennadi Liakhovetski wrote:
>> At the way your patches were on -hg, they didn't apply upstream. I had to do
>> some manual work to make them apply.
>
> Right, I think, this is also a side effect of this "dualistic" development
> model - I prepared my patches to apply to the hg tree, and, as you know,
> back-porting of upstream work from mainline git to hg is not trivial, so,
> the two versions drifted apart by the time you tried to port the patches
> to git, so, merge-conflicts resulted.
Yes. You got the point.
>> Agreed. This means more work to me.
>
> Yes, that's why I tried to use hg - to avoid creating extra work for you,
> I'm sure, you have enough of it already. But it seems this way the
> problems are hardly fewer, they are just different...
True. Probably, for day-to-day changes, using -hg is better for my side,
but when arch changes, it seems that using -git could work better...
>> I think we need to do this, but it is not so easy to make it happen. I intend
>> to work on it this year.
>
> I certainly understand this is not easy, and is not done in 1 hour,
> probably, not even in 10 hours. But as you write in your other post, if
> you're already spending _days_ on the hg-git merges, maybe it would be
> good to try to make this happen soon enough? In fact, what is needed for
> this?
I intend to do this work soon, but I want to finish some pending things
before start this.
> You already have a git-tree and you already can handle git-based
> patches rom contributors, right? So, you will just drop your hg work
> completely and only handle git.
This will break the development model for all the other guys, so, this is
not an alternative. I need first provide some way for them to send
patches.
I can see a few alternatives:
1) provide some space for storing git trees at linuxtv.org. Not sure if
we have enough space there for all those -git trees. This also envolves
changing the current scripts for the new model;
2) Just accept patches sent by email. After having patchwork.kernel.org
working for linux-media, handling patches by email could be almost as easy
as handling pull requests, after some scripting. The advantage of this
approach is that it makes easier to review individual patches, but I'm not
sure if this scales for about 1000 patches per kernel cycle (we are close
to this rate).
> The only work that I can see on this, is
> creating those snapshots and applying the compatibility craft, that we
> currently have in hg to make them compile against older kernels. Am I
> missing something?
This will require some additional work, since we'll need to find a way to
convert patches from in-tree to out-of-tree. Probably, the better will be
to keep using hg or migrating the out-of-tree also to git, in order to
store the compatibility and building system patches.
-
> And now, Mauro, what do we do with this specific case? Are you going to
> fix it in your hg-/git-trees or are you expecting anything from me / Eric?
Please send me a patch fixing the issue, and I'll send it forward. You can
write it against -hg or -git, since both trees are syncronized.
Cheers,
Mauro.
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
^ permalink raw reply
* Re: [PATCH] v2 Re: Bug: Status/Summary of slashdot leap-second crash on new years 2008-2009
From: Chris Adams @ 2009-01-03 18:01 UTC (permalink / raw)
To: Duane Griffin; +Cc: Linas Vepstas, linux-kernel
In-Reply-To: <20090103045227.GA5994@dastardly.home.dghda.com>
Once upon a time, Duane Griffin <duaneg@dghda.com> said:
> How about instead of a switch statement, assigning the message to a
> variable and printing that. I.e. something like:
Good point. Here's an updated version that also adds a comment to the
xtime_lock definition about not using printk.
--
Chris Adams <cmadams@hiwaay.net>
Systems and Network Administrator - HiWAAY Internet Services
I don't speak for anybody but myself - that's enough trouble.
From: Chris Adams <cmadams@hiwaay.net>
The code to handle leap seconds printks an information message when the
second is inserted or deleted. It does this while holding xtime_lock.
However, printk wakes up klogd, and in some cases, the scheduler tries
to get the current kernel time, trying to get xtime_lock (which results
in a deadlock). This moved the printks outside of the lock. It also
adds a comment to not use printk while holding xtime_lock.
Signed-off-by: Chris Adams <cmadams@hiwaay.net>
---
diff -urpN linux-2.6.28-git5-vanilla/include/linux/time.h linux-2.6.28-git5/include/linux/time.h
--- linux-2.6.28-git5-vanilla/include/linux/time.h 2009-01-02 22:09:10.000000000 -0600
+++ linux-2.6.28-git5/include/linux/time.h 2009-01-03 11:57:27.000000000 -0600
@@ -99,6 +99,12 @@ static inline struct timespec timespec_s
extern struct timespec xtime;
extern struct timespec wall_to_monotonic;
+
+/*
+ * Do not call printk while holding this lock; it wakes klogd and the
+ * scheduler may try to get the current kernel time, which will try to get
+ * this lock.
+ */
extern seqlock_t xtime_lock;
extern unsigned long read_persistent_clock(void);
diff -urpN linux-2.6.28-git5-vanilla/kernel/time/ntp.c linux-2.6.28-git5/kernel/time/ntp.c
--- linux-2.6.28-git5-vanilla/kernel/time/ntp.c 2009-01-02 22:09:34.000000000 -0600
+++ linux-2.6.28-git5/kernel/time/ntp.c 2009-01-03 11:57:46.000000000 -0600
@@ -130,6 +130,7 @@ void ntp_clear(void)
static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
{
enum hrtimer_restart res = HRTIMER_NORESTART;
+ const char *msg = NULL;
write_seqlock(&xtime_lock);
@@ -140,8 +141,7 @@ static enum hrtimer_restart ntp_leap_sec
xtime.tv_sec--;
wall_to_monotonic.tv_sec++;
time_state = TIME_OOP;
- printk(KERN_NOTICE "Clock: "
- "inserting leap second 23:59:60 UTC\n");
+ msg = "Clock: inserting leap second 23:59:60 UTC";
hrtimer_add_expires_ns(&leap_timer, NSEC_PER_SEC);
res = HRTIMER_RESTART;
break;
@@ -150,8 +150,7 @@ static enum hrtimer_restart ntp_leap_sec
time_tai--;
wall_to_monotonic.tv_sec--;
time_state = TIME_WAIT;
- printk(KERN_NOTICE "Clock: "
- "deleting leap second 23:59:59 UTC\n");
+ msg = "Clock: deleting leap second 23:59:59 UTC";
break;
case TIME_OOP:
time_tai++;
@@ -166,6 +165,9 @@ static enum hrtimer_restart ntp_leap_sec
write_sequnlock(&xtime_lock);
+ if (msg)
+ printk(KERN_NOTICE "%s\n", msg);
+
return res;
}
^ permalink raw reply
* Re: [PATCH for -mm] getrusage: fill ru_maxrss value
From: Oleg Nesterov @ 2009-01-03 17:59 UTC (permalink / raw)
To: KOSAKI Motohiro
Cc: Jiri Pirko, linux-kernel, Hugh Dickins, linux-mm, Andrew Morton
In-Reply-To: <20081231213705.1293.KOSAKI.MOTOHIRO@jp.fujitsu.com>
sorry for delay!
On 12/31, KOSAKI Motohiro wrote:
>
> Jiri's resend3 -> v1
> - At wait_task_zombie(), parent process doesn't only collect child maxrss,
> but also cmaxrss.
Ah yes, this looks very right to me.
> - ru_maxrss inherit at exec()
I must admit, I hate this ;)
That said, I agree with you point about compatibility. So I have to
agree with this change.
Still, I'd like to know what other people think ;)
And I also agree that xacct is linux specific feature, but I still
I dislike the fact that xacct and getrusage report different numbers.
Perhaps we should change xacct as well?
> --- a/kernel/exit.c 2008-12-29 23:27:59.000000000 +0900
> +++ b/kernel/exit.c 2008-12-31 21:08:08.000000000 +0900
> @@ -1053,6 +1053,12 @@ NORET_TYPE void do_exit(long code)
> if (group_dead) {
> hrtimer_cancel(&tsk->signal->real_timer);
> exit_itimers(tsk->signal);
> + if (tsk->mm) {
> + unsigned long hiwater_rss = get_mm_hiwater_rss(tsk->mm);
> +
> + if (tsk->signal->maxrss < hiwater_rss)
> + tsk->signal->maxrss = hiwater_rss;
> + }
[...snip...]
> --- a/fs/exec.c 2008-12-25 08:26:37.000000000 +0900
> +++ b/fs/exec.c 2008-12-31 21:11:28.000000000 +0900
> @@ -870,6 +870,13 @@ static int de_thread(struct task_struct
> sig->notify_count = 0;
>
> no_thread_group:
> + if (current->mm) {
> + unsigned long hiwater_rss = get_mm_hiwater_rss(current->mm);
> +
> + if (sig->maxrss < hiwater_rss)
> + sig->maxrss = hiwater_rss;
> + }
Perhaps it makes sense to factor out this code and make a helper?
Unfortunately, exit_mm() and exec_mmap() do not have the common
path which can update sig->maxrss, mm_release() can't do this...
> + if (who != RUSAGE_CHILDREN) {
> + struct mm_struct *mm = get_task_mm(p);
> + if (mm) {
> + unsigned long hiwater_rss = get_mm_hiwater_rss(mm);
> +
> + if (maxrss < hiwater_rss)
> + maxrss = hiwater_rss;
> + mmput(mm);
> + }
> + }
> + r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
Hmm... So, RUSAGE_THREAD always report maxrss == get_mm_hiwater_rss(mm)
and ignores signal->maxrss. Doesn't look right to me...
Unless I missed something, Jiris's patch was fine, but given that now
we inherit maxrss at exec(), signal->maxrss can have the "inherited"
value?
Oleg.
^ permalink raw reply
* Re: [PATCH for -mm] getrusage: fill ru_maxrss value
From: Oleg Nesterov @ 2009-01-03 17:59 UTC (permalink / raw)
To: KOSAKI Motohiro
Cc: Jiri Pirko, linux-kernel, Hugh Dickins, linux-mm, Andrew Morton
In-Reply-To: <20081231213705.1293.KOSAKI.MOTOHIRO@jp.fujitsu.com>
sorry for delay!
On 12/31, KOSAKI Motohiro wrote:
>
> Jiri's resend3 -> v1
> - At wait_task_zombie(), parent process doesn't only collect child maxrss,
> but also cmaxrss.
Ah yes, this looks very right to me.
> - ru_maxrss inherit at exec()
I must admit, I hate this ;)
That said, I agree with you point about compatibility. So I have to
agree with this change.
Still, I'd like to know what other people think ;)
And I also agree that xacct is linux specific feature, but I still
I dislike the fact that xacct and getrusage report different numbers.
Perhaps we should change xacct as well?
> --- a/kernel/exit.c 2008-12-29 23:27:59.000000000 +0900
> +++ b/kernel/exit.c 2008-12-31 21:08:08.000000000 +0900
> @@ -1053,6 +1053,12 @@ NORET_TYPE void do_exit(long code)
> if (group_dead) {
> hrtimer_cancel(&tsk->signal->real_timer);
> exit_itimers(tsk->signal);
> + if (tsk->mm) {
> + unsigned long hiwater_rss = get_mm_hiwater_rss(tsk->mm);
> +
> + if (tsk->signal->maxrss < hiwater_rss)
> + tsk->signal->maxrss = hiwater_rss;
> + }
[...snip...]
> --- a/fs/exec.c 2008-12-25 08:26:37.000000000 +0900
> +++ b/fs/exec.c 2008-12-31 21:11:28.000000000 +0900
> @@ -870,6 +870,13 @@ static int de_thread(struct task_struct
> sig->notify_count = 0;
>
> no_thread_group:
> + if (current->mm) {
> + unsigned long hiwater_rss = get_mm_hiwater_rss(current->mm);
> +
> + if (sig->maxrss < hiwater_rss)
> + sig->maxrss = hiwater_rss;
> + }
Perhaps it makes sense to factor out this code and make a helper?
Unfortunately, exit_mm() and exec_mmap() do not have the common
path which can update sig->maxrss, mm_release() can't do this...
> + if (who != RUSAGE_CHILDREN) {
> + struct mm_struct *mm = get_task_mm(p);
> + if (mm) {
> + unsigned long hiwater_rss = get_mm_hiwater_rss(mm);
> +
> + if (maxrss < hiwater_rss)
> + maxrss = hiwater_rss;
> + mmput(mm);
> + }
> + }
> + r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
Hmm... So, RUSAGE_THREAD always report maxrss == get_mm_hiwater_rss(mm)
and ignores signal->maxrss. Doesn't look right to me...
Unless I missed something, Jiris's patch was fine, but given that now
we inherit maxrss at exec(), signal->maxrss can have the "inherited"
value?
Oleg.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Problem with fonts in different width
From: Bean @ 2009-01-03 17:53 UTC (permalink / raw)
To: The development of GRUB 2
Hi,
Unicode characters are split into two sizes, 16x16 and 16x8, and are
stored in different files, for example:
f16.pcf.gz
-efont-fixed-medium-r-normal--16-160-75-75-c-160-iso10646-1
h16.pcf.gz
-efont-fixed-medium-r-normal--16-160-75-75-c-80-iso10646-1
They can be converted to f16.pf2 and h16.pf2. However, only one font
can be active at at time. So if we use both full and half width
characters, some of them is not displayed properly. The pf2 format
seems to allow different font widths. Perhaps the converter should
allow multiple input, so that we can merge the two fonts into one pf2
?
--
Bean
^ permalink raw reply
* Re: [PULL] cpumask tree
From: Ingo Molnar @ 2009-01-03 17:45 UTC (permalink / raw)
To: Mike Travis; +Cc: Rusty Russell, Linus Torvalds, linux-kernel
In-Reply-To: <495F8DCA.1060905@sgi.com>
* Mike Travis <travis@sgi.com> wrote:
> > yep, that's the bad one. Should i revert it or do you have a safe fix
> > in mind?
>
> Probably revert for now. [...]
done.
But -tip testing found another bug today as well, a boot crash with
certain (rare) 64-bit configs:
[ 1.588202] ACPI: PCI Interrupt Link [LNKA] (IRQs<1>BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
[ 1.588012] IP: [<ffffffff80239778>] find_busiest_group+0x198/0xa20
[ 1.588048] Call Trace:
[ 1.588049] <IRQ> <0> [<ffffffff80240f96>] rebalance_domains+0x196/0x5e0
[ 1.588052] [<ffffffff80270b15>] ? lock_release_holdtime+0x35/0x1e0
[ 1.588055] [<ffffffff80983f70>] ? _spin_unlock_irq+0x30/0x40
[ 1.588058] [<ffffffff8024300e>] run_rebalance_domains+0x4e/0x120
[ 1.588060] [<ffffffff8024f80c>] __do_softirq+0xac/0x190
[ 1.588063] [<ffffffff8020d13c>] call_softirq+0x1c/0x30
[ 1.588066] [<ffffffff8020ef35>] do_softirq+0x75/0xa0
[ 1.588067] [<ffffffff8024f47d>] irq_exit+0x9d/0xb0
[ 1.588069] [<ffffffff80984f5d>] smp_apic_timer_interrupt+0x8d/0xc3
[ 1.588071] [<ffffffff8020cb73>] apic_timer_interrupt+0x13/0x20
i just bisected it back to:
| 74c5409893751c400547184751410c61930043b2 is first bad commit
| commit 74c5409893751c400547184751410c61930043b2
| Author: Mike Travis <travis@sgi.com>
| Date: Wed Dec 31 18:08:45 2008 -0800
|
| x86: cleanup remaining cpumask_t ops in smpboot code
|
| Impact: Reduce memory usage and use new cpumask API.
this is in the final pieces of changes you did after pulling Rusty's tree:
26e2013: x86: setup_per_cpu_areas() cleanup
44aa683: cpumask: fix compile error when CONFIG_NR_CPUS is not defined
eeff031: cpumask: use alloc_cpumask_var_node where appropriate
40fbcb0: cpumask: convert shared_cpu_map in acpi_processor* structs to cpumask_var
197e99c: x86: use cpumask_var_t in acpi/boot.c
2d22bd5: x86: cleanup remaining cpumask_t code in microcode_core.c
22022f5: x86: cleanup remaining cpumask_t code in mce_amd_64.c
b5f3096: x86: cleanup some remaining usages of NR_CPUS where s/b nr_cpu_ids
efb897c: sched: put back some stack hog changes that were undone in kernel/sched.c
74c5409: x86: cleanup remaining cpumask_t ops in smpboot code
8627b2a: x86: enable cpus display of kernel_max and offlined cpus
095fb96: Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/ru
i think i'll just rebase the tail portion of cpus4096 starting at 8627b2a
- this keeps most of the history intact and avoids these ugly reverts.
Also, while bisecting this window of commits i found that neither would
build successfully due to a typo - and the typo is fixed in 095fb96. So
since we rebase this portion anyway due to excessive amount of bugs, i'll
make it fully bisectable by rebasing right at 095fb96, backmerge the
fixlet from eeff031 and redo the whole series dropping the two bad
patches. Since this portion of the tree has no appreciable testing value
the rebase is the right thing to do here.
Ingo
^ permalink raw reply
* Re: [PATCH] gitweb: merge boolean feature subroutines
From: demerphq @ 2009-01-03 17:41 UTC (permalink / raw)
To: Matt Kraai; +Cc: git
In-Reply-To: <20090103171333.GB4205@ftbfs.org>
2009/1/3 Matt Kraai <kraai@ftbfs.org>:
> On Sat, Jan 03, 2009 at 05:51:50PM +0100, demerphq wrote:
>> 2009/1/3 Matt Kraai <kraai@ftbfs.org>:
>> > I don't think Perl has *a* false value, but rather has multiple values
>> > that are treated as false, such as undef, zero, and the empty string.
>> > Personally, I find 0 clearer than the empty string, but that's
>> > probably just my C bias sneaking in.
>>
>> Yes it definitely does have a false value, PL_sv_no, and a true value,
>> PL_sv_yes (although it is much less important). It is these values
>> which are copied to signify true and false in the cases where the
>> internals need to, such as for boolean operators that must return
>> false, and things like negation and (in)equality checks.
>>
>> It is a so called "dual var" SvPVNV, with 0 in the NV (numeric) slot
>> and the empty string in the PV (string) slot.
>>
>> You can see one example of its behaviour in my previous mail, and can
>> see it further here:
>>
>> $ perl -MDevel::Peek -e'print Dump(shift @ARGV eq "true")'
>> SV = PVNV(0x952eb10) at 0x952b6f0
>> REFCNT = 2147483647
>> FLAGS = (IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
>> IV = 0
>> NV = 0
>> PV = 0x952eae8 ""\0
>> CUR = 0
>> LEN = 4
>>
>> Compare that to:
>>
>> perl -MDevel::Peek -e'print Dump(shift @ARGV eq "true" ? 1 : 0)'
>> SV = IV(0x94d8398) at 0x94bd678
>> REFCNT = 1
>> FLAGS = (PADBUSY,PADTMP,IOK,READONLY,pIOK)
>> IV = 0
>
> Wow, I had no idea about this. Thanks for the information.
>
> It seems like using these values would require obfuscating the code,
> though. :( They only seem to be exposed directly via XS.
Depend how you look at it. You have access to them via the negation
and inequality operators. In a way you can think of the 'not' (or !)
operator as being the "inverted boolean constructor". So for instance
the kind of surprising
my $bool= !!$val;
can be used to get a copy of the appropriate PL_sv_yes/no. But the
need to do is rare. Luckily. :-)
But yeah, they are not exposed directly at the perl level. There is no
keyword to use to generate them like there is for undef/PL_sv_undef,
although I guess it would be fairly easy to expose them in a similar
fashion via Scalar::Util.
cheers,
Yves
--
perl -Mre=debug -e "/just|another|perl|hacker/"
^ permalink raw reply
* Re: [PATCH] cx18, cx2341x, ivtv: Add AC-3 audio encoding control to cx18
From: Andy Walls @ 2009-01-03 17:36 UTC (permalink / raw)
To: ivtv-devel, video4linux-list, linux-media
In-Reply-To: <200901031036.15661.hverkuil@xs4all.nl>
On Sat, 2009-01-03 at 10:36 +0100, Hans Verkuil wrote:
> Hi Andy,
>
> I've done a quick review:
>
> On Thursday 01 January 2009 23:20:08 Andy Walls wrote:
> > The patch in line below adds a control to the cx18 driver to request
> > AC-3 audio instead of MPEG Layer II. It doesn't quite work yet due to
> > cx18 firmware issues.
> >
> > However, I think I've got the basic control work done and need a review
> > to make sure I didn't muck anything up with the cx2341x or ivtv modules.
> >
> > Of particular concern to me is
> >
> > a) changing the cx2341x "audio_properties" from a u16 to a u32, as this
> > is what rippled down in source code to the to ivtv driver.
> >
> > b) accidentally adding a bogus options or controls to ivtv.
> >
> >
> > The change can also be found at
> >
> > http://linuxtv.org/hg/~awalls/v4l-dvb
> >
> Regards,
>
> Hans
All,
OK. I've committed a patch to the patch in the same repo. I actually
read my (slightly dated) copy of the V4L2 API spec, and tried to bring
things into compliance with that as well. Thanks go to Hans for
pointing out my errors.
Below is the diff that includes both changes for easier review.
Regards,
Andy
diff -r 41242777b3d8 -r 70b1c2992d87 linux/drivers/media/video/cx18/cx18-driver.c
--- a/linux/drivers/media/video/cx18/cx18-driver.c Thu Jan 01 10:35:06 2009 -0500
+++ b/linux/drivers/media/video/cx18/cx18-driver.c Sat Jan 03 12:21:30 2009 -0500
@@ -592,7 +592,7 @@ static int __devinit cx18_init_struct1(s
(cx->params.video_temporal_filter_mode << 1) |
(cx->params.video_median_filter_type << 2);
cx->params.port = CX2341X_PORT_MEMORY;
- cx->params.capabilities = CX2341X_CAP_HAS_TS;
+ cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3;
init_waitqueue_head(&cx->cap_w);
init_waitqueue_head(&cx->mb_apu_waitq);
init_waitqueue_head(&cx->mb_cpu_waitq);
diff -r 41242777b3d8 -r 70b1c2992d87 linux/drivers/media/video/cx18/cx18-driver.h
--- a/linux/drivers/media/video/cx18/cx18-driver.h Thu Jan 01 10:35:06 2009 -0500
+++ b/linux/drivers/media/video/cx18/cx18-driver.h Sat Jan 03 12:21:30 2009 -0500
@@ -413,7 +413,7 @@ struct cx18 {
/* dualwatch */
unsigned long dualwatch_jiffies;
- u16 dualwatch_stereo_mode;
+ u32 dualwatch_stereo_mode;
/* Digitizer type */
int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */
diff -r 41242777b3d8 -r 70b1c2992d87 linux/drivers/media/video/cx18/cx18-fileops.c
--- a/linux/drivers/media/video/cx18/cx18-fileops.c Thu Jan 01 10:35:06 2009 -0500
+++ b/linux/drivers/media/video/cx18/cx18-fileops.c Sat Jan 03 12:21:30 2009 -0500
@@ -128,10 +128,10 @@ static void cx18_dualwatch(struct cx18 *
static void cx18_dualwatch(struct cx18 *cx)
{
struct v4l2_tuner vt;
- u16 new_bitmap;
- u16 new_stereo_mode;
- const u16 stereo_mask = 0x0300;
- const u16 dual = 0x0200;
+ u32 new_bitmap;
+ u32 new_stereo_mode;
+ const u32 stereo_mask = 0x0300;
+ const u32 dual = 0x0200;
u32 h;
new_stereo_mode = cx->params.audio_properties & stereo_mask;
diff -r 41242777b3d8 -r 70b1c2992d87 linux/drivers/media/video/cx2341x.c
--- a/linux/drivers/media/video/cx2341x.c Thu Jan 01 10:35:06 2009 -0500
+++ b/linux/drivers/media/video/cx2341x.c Sat Jan 03 12:21:30 2009 -0500
@@ -1,5 +1,5 @@
/*
- * cx2341x - generic code for cx23415/6 based devices
+ * cx2341x - generic code for cx23415/6/8 based devices
*
* Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
*
@@ -31,7 +31,7 @@
#include <media/v4l2-common.h>
#include "compat.h"
-MODULE_DESCRIPTION("cx23415/6 driver");
+MODULE_DESCRIPTION("cx23415/6/8 driver");
MODULE_AUTHOR("Hans Verkuil");
MODULE_LICENSE("GPL");
@@ -46,6 +46,7 @@ const u32 cx2341x_mpeg_ctrls[] = {
V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
V4L2_CID_MPEG_AUDIO_ENCODING,
V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+ V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
V4L2_CID_MPEG_AUDIO_MODE,
V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
V4L2_CID_MPEG_AUDIO_EMPHASIS,
@@ -95,6 +96,7 @@ static const struct cx2341x_mpeg_params
.audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
.audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
.audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
+ .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,
.audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
.audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
.audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
@@ -149,6 +151,9 @@ static int cx2341x_get_ctrl(const struct
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
ctrl->value = params->audio_l2_bitrate;
break;
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ ctrl->value = params->audio_ac3_bitrate;
+ break;
case V4L2_CID_MPEG_AUDIO_MODE:
ctrl->value = params->audio_mode;
break;
@@ -257,12 +262,25 @@ static int cx2341x_set_ctrl(struct cx234
params->audio_sampling_freq = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_ENCODING:
+ if (busy)
+ return -EBUSY;
+ if (params->capabilities & CX2341X_CAP_HAS_AC3)
+ if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
+ ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)
+ return -ERANGE;
params->audio_encoding = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
if (busy)
return -EBUSY;
params->audio_l2_bitrate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ if (busy)
+ return -EBUSY;
+ if (!(params->capabilities & CX2341X_CAP_HAS_AC3))
+ return -EINVAL;
+ params->audio_ac3_bitrate = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_MODE:
params->audio_mode = ctrl->value;
@@ -483,20 +501,54 @@ int cx2341x_ctrl_query(const struct cx23
switch (qctrl->id) {
case V4L2_CID_MPEG_AUDIO_ENCODING:
+ if (params->capabilities & CX2341X_CAP_HAS_AC3) {
+ /*
+ * The state of L2 & AC3 bitrate controls can change
+ * when this control changes, but v4l2_ctrl_query_fill()
+ * already sets V4L2_CTRL_FLAG_UPDATE for
+ * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
+ */
+ return v4l2_ctrl_query_fill(qctrl,
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
+ default_params.audio_encoding);
+ }
+
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
default_params.audio_encoding);
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- return v4l2_ctrl_query_fill(qctrl,
+ err = v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_L2_BITRATE_192K,
V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
default_params.audio_l2_bitrate);
+ if (err)
+ return err;
+ if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
+ params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ return 0;
case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
return -EINVAL;
+
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ err = v4l2_ctrl_query_fill(qctrl,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
+ default_params.audio_ac3_bitrate);
+ if (err)
+ return err;
+ if (params->capabilities & CX2341X_CAP_HAS_AC3) {
+ if (params->audio_encoding !=
+ V4L2_MPEG_AUDIO_ENCODING_AC3)
+ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ } else
+ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+ return 0;
case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
err = v4l2_ctrl_query_fill_std(qctrl);
@@ -672,6 +724,15 @@ const char **cx2341x_ctrl_get_menu(const
NULL
};
+ static const char *mpeg_audio_encoding_l2_ac3[] = {
+ "",
+ "MPEG-1/2 Layer II",
+ "",
+ "",
+ "AC-3",
+ NULL
+ };
+
static const char *cx2341x_video_spatial_filter_mode_menu[] = {
"Manual",
"Auto",
@@ -712,6 +773,9 @@ const char **cx2341x_ctrl_get_menu(const
case V4L2_CID_MPEG_STREAM_TYPE:
return (p->capabilities & CX2341X_CAP_HAS_TS) ?
mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
+ case V4L2_CID_MPEG_AUDIO_ENCODING:
+ return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
+ mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
return NULL;
@@ -731,16 +795,36 @@ const char **cx2341x_ctrl_get_menu(const
}
EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
+/* definitions for audio properties bits 29-28 */
+#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0
+#define CX2341X_AUDIO_ENCODING_METHOD_AC3 1
+#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2
+
static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
{
- params->audio_properties = (params->audio_sampling_freq << 0) |
- ((3 - params->audio_encoding) << 2) |
- ((1 + params->audio_l2_bitrate) << 4) |
+ params->audio_properties =
+ (params->audio_sampling_freq << 0) |
(params->audio_mode << 8) |
(params->audio_mode_extension << 10) |
(((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
? 3 : params->audio_emphasis) << 12) |
(params->audio_crc << 14);
+
+ if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
+ params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+ params->audio_properties |=
+#if 1
+ /* Not sure if this MPEG Layer II setting is required */
+ ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
+#endif
+ (params->audio_ac3_bitrate << 4) |
+ (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
+ } else {
+ /* Assuming MPEG Layer II */
+ params->audio_properties |=
+ ((3 - params->audio_encoding) << 2) |
+ ((1 + params->audio_l2_bitrate) << 4);
+ }
}
int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
@@ -1023,7 +1107,10 @@ void cx2341x_log_status(const struct cx2
prefix,
cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
- cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
+ cx2341x_menu_item(p,
+ p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
+ ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
+ : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
p->audio_mute ? " (muted)" : "");
if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
diff -r 41242777b3d8 -r 70b1c2992d87 linux/drivers/media/video/ivtv/ivtv-driver.h
--- a/linux/drivers/media/video/ivtv/ivtv-driver.h Thu Jan 01 10:35:06 2009 -0500
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.h Sat Jan 03 12:21:30 2009 -0500
@@ -697,7 +697,7 @@ struct ivtv {
u64 vbi_data_inserted; /* number of VBI bytes inserted into the MPEG stream */
u32 last_dec_timing[3]; /* cache last retrieved pts/scr/frame values */
unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */
- u16 dualwatch_stereo_mode; /* current detected dualwatch stereo mode */
+ u32 dualwatch_stereo_mode; /* current detected dualwatch stereo mode */
/* VBI state info */
diff -r 41242777b3d8 -r 70b1c2992d87 linux/drivers/media/video/ivtv/ivtv-fileops.c
--- a/linux/drivers/media/video/ivtv/ivtv-fileops.c Thu Jan 01 10:35:06 2009 -0500
+++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c Sat Jan 03 12:21:30 2009 -0500
@@ -148,10 +148,10 @@ static void ivtv_dualwatch(struct ivtv *
static void ivtv_dualwatch(struct ivtv *itv)
{
struct v4l2_tuner vt;
- u16 new_bitmap;
- u16 new_stereo_mode;
- const u16 stereo_mask = 0x0300;
- const u16 dual = 0x0200;
+ u32 new_bitmap;
+ u32 new_stereo_mode;
+ const u32 stereo_mask = 0x0300;
+ const u32 dual = 0x0200;
new_stereo_mode = itv->params.audio_properties & stereo_mask;
memset(&vt, 0, sizeof(vt));
diff -r 41242777b3d8 -r 70b1c2992d87 linux/include/media/cx2341x.h
--- a/linux/include/media/cx2341x.h Thu Jan 01 10:35:06 2009 -0500
+++ b/linux/include/media/cx2341x.h Sat Jan 03 12:21:30 2009 -0500
@@ -1,5 +1,5 @@
/*
- cx23415/6 header containing common defines.
+ cx23415/6/8 header containing common defines.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@ enum cx2341x_cap {
enum cx2341x_cap {
CX2341X_CAP_HAS_SLICED_VBI = 1 << 0,
CX2341X_CAP_HAS_TS = 1 << 1,
+ CX2341X_CAP_HAS_AC3 = 1 << 2,
};
struct cx2341x_mpeg_params {
@@ -47,11 +48,12 @@ struct cx2341x_mpeg_params {
enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq;
enum v4l2_mpeg_audio_encoding audio_encoding;
enum v4l2_mpeg_audio_l2_bitrate audio_l2_bitrate;
+ enum v4l2_mpeg_audio_ac3_bitrate audio_ac3_bitrate;
enum v4l2_mpeg_audio_mode audio_mode;
enum v4l2_mpeg_audio_mode_extension audio_mode_extension;
enum v4l2_mpeg_audio_emphasis audio_emphasis;
enum v4l2_mpeg_audio_crc audio_crc;
- u16 audio_properties;
+ u32 audio_properties;
u16 audio_mute;
/* video */
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
^ permalink raw reply
* [GIT PULL] various IOMMU updates for 2.6.29
From: Joerg Roedel @ 2009-01-03 17:31 UTC (permalink / raw)
To: Linus Torvalds
Cc: gregkh, avi, mingo, dwmw2, weidong.han, linux-kernel, iommu
Hi Linus,
The following changes since commit 6680598b44ed3c0052d155522eb21fc5a00de5f3:
Ingo Molnar (1):
Disallow gcc versions 3.{0,1}
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git for-linus
The changes include:
- VT-d updates for 2.6.29
- multiple device assignment support for KVM from Han Weidong
- refactoring of the VT-d functions for KVM into a generic iommu api
and necessary KVM changes (required for amd iommu support in KVM)
- AMD IOMMU support for the iommu api (makes AMD IOMMU usable for pci
device assignment in kvm)
- other AMD IOMMU updates for 2.6.29 including:
+ cleanups and minor improvements
+ a debugfs stats interface
This code touches areas of various subsystem maintainers. Because it
would have required some special care if we merged this code over the
different subsystems I agreed with David Woodhouse and Avi Kivity that I
send you a seperate pull request for this stuff. The iommu api was
reviewed, discussed with and acked by Greg Kroah-Hartman.
Please pull.
Jaswinder Singh Rajput (1):
AMD IOMMU: prealloc_protection_domains should be static
Joerg Roedel (58):
KVM: rename vtd.c to iommu.c
introcude linux/iommu.h for an iommu api
add frontend implementation for the IOMMU API
select IOMMU_API when DMAR and/or AMD_IOMMU is selected
KVM: change KVM to use IOMMU API
VT-d: adapt domain init and destroy functions for IOMMU API
VT-d: adapt device attach and detach functions for IOMMU API
VT-d: adapt domain map and unmap functions for IOMMU API
VT-d: adapt domain iova_to_phys function for IOMMU API
VT-d: register functions for the IOMMU API
VT-d: remove now unused intel_iommu_found function
AMD IOMMU: rename iommu_map to iommu_map_page
AMD IOMMU: make dma_ops_free_pagetable generic
AMD IOMMU: add domain id free function
AMD IOMMU: refactor completion wait handling into separate functions
AMD IOMMU: move invalidation command building to a separate function
AMD IOMMU: don't remove protection domain from iommu_pd_list
AMD IOMMU: add iommu_flush_domain function
AMD IOMMU: add protection domain flags
AMD IOMMU: add checks for dma_ops domain to dma_ops functions
AMD IOMMU: add device reference counting for protection domains
AMD IOMMU: rename set_device_domain function
AMD IOMMU: add device detach helper functions
AMD IOMMU: add device notifier callback
AMD IOMMU: add domain cleanup helper function
AMD IOMMU: add domain init function for IOMMU API
AMD IOMMU: add domain destroy function for IOMMU API
AMD IOMMU: add device detach function for IOMMU API
AMD IOMMU: add device attach function for IOMMU API
AMD IOMMU: add domain map function for IOMMU API
AMD IOMMU: add domain unmap function for IOMMU API
AMD IOMMU: add domain address lookup function for IOMMU API
AMD IOMMU: register functions for the IOMMU API
AMD IOMMU: add a domain flag for default domains
AMD IOMMU: allocate a new protection for hotplugged devices
AMD IOMMU: use dev_name instead of self-build print_devid
AMD IOMMU: convert iommu->need_sync to bool
AMD IOMMU: convert amd_iommu_isolate to bool
AMD IOMMU: use calc_devid in prealloc_protection_domains
AMD IOMMU: use dev_name in iommu_enable function
AMD IOMMU: add Kconfig entry for statistic collection code
AMD IOMMU: add necessary header defines for stats counting
AMD IOMMU: add init code for statistic collection
AMD IOMMU: add stats counter for completion wait events
AMD IOMMU: add stats counter for map_single requests
AMD IOMMU: add stats counter for unmap_single requests
AMD IOMMU: add stats counter for map_sg requests
AMD IOMMU: add stats counter for unmap_sg requests
AMD IOMMU: add stats counter for alloc_coherent requests
AMD IOMMU: add stats counter for free_coherent requests
AMD IOMMU: add stats counter for cross-page request
AMD IOMMU: add stats counter for single iommu domain tlb flushes
AMD IOMMU: add stats counter for domain tlb flushes
AMD IOMMU: add statistics about allocated io memory
AMD IOMMU: add statistics about total number of map requests
kvm/iommu: fix compile warning
Merge branches 'iommu/api' and 'iommu/amd' into for-linus
AMD IOMMU: remove now unnecessary #ifdefs
Mark McLoughlin (12):
intel-iommu: remove some unused struct intel_iommu fields
intel-iommu: make init_dmars() static
intel-iommu: move DMA_32/64BIT_PFN into intel-iommu.c
intel-iommu: move root entry defs from dma_remapping.h
intel-iommu: move context entry defs out from dma_remapping.h
intel-iommu: move DMA PTE defs out of dma_remapping.h
intel-iommu: move struct dmar_domain def out dma_remapping.h
intel-iommu: move struct device_domain_info out of dma_remapping.h
intel-iommu: kill off duplicate def of dmar_disabled
intel-iommu: move iommu_prepare_gfx_mapping() out of dma_remapping.h
intel-iommu: trivially inline context entry macros
intel-iommu: trivially inline DMA PTE macros
Mike Day (1):
intel-iommu: fix bit shift at DOMAIN_FLAG_P2P_MULTIPLE_DEVICES
Weidong Han (17):
Initialize domain flags to 0
change P2P domain flags
Add global iommu list
Get iommu from g_iommus for deferred flush
iommu bitmap instead of iommu pointer in dmar_domain
calculate agaw for each iommu
iommu coherency
Add domain flag DOMAIN_FLAG_VIRTUAL_MACHINE
Add/remove domain device info for virtual machine domain
Add domain_flush_cache
Allocation and free functions of virtual machine domain
Change domain_context_mapping_one for virtual machine domain
Change intel iommu APIs of virtual machine domain
Check agaw is sufficient for mapped memory
KVM: use the new intel iommu APIs
KVM: support device deassignment
Deassign device in kvm_free_assgined_device
Yu Zhao (1):
VT-d: fix segment number being ignored when searching DRHD
arch/ia64/Kconfig | 3 +
arch/ia64/include/asm/kvm_host.h | 2 +-
arch/ia64/kvm/Makefile | 4 +-
arch/ia64/kvm/kvm-ia64.c | 3 +-
arch/x86/Kconfig | 13 +
arch/x86/include/asm/amd_iommu_types.h | 61 ++-
arch/x86/include/asm/kvm_host.h | 2 +-
arch/x86/kernel/amd_iommu.c | 666 ++++++++++++++++++++--
arch/x86/kernel/amd_iommu_init.c | 15 +-
arch/x86/kvm/Makefile | 4 +-
arch/x86/kvm/x86.c | 3 +-
drivers/base/Makefile | 1 +
drivers/base/iommu.c | 100 ++++
drivers/pci/dmar.c | 46 +-
drivers/pci/intel-iommu.c | 944 +++++++++++++++++++++++++++-----
include/linux/dma_remapping.h | 138 +-----
include/linux/dmar.h | 1 -
include/linux/intel-iommu.h | 25 +-
include/linux/iommu.h | 112 ++++
include/linux/kvm_host.h | 30 +-
virt/kvm/{vtd.c => iommu.c} | 135 +++--
virt/kvm/kvm_main.c | 50 ++-
22 files changed, 1894 insertions(+), 464 deletions(-)
create mode 100644 drivers/base/iommu.c
create mode 100644 include/linux/iommu.h
rename virt/kvm/{vtd.c => iommu.c} (58%)
--
| AMD Saxony Limited Liability Company & Co. KG
Operating | Wilschdorfer Landstr. 101, 01109 Dresden, Germany
System | Register Court Dresden: HRA 4896
Research | General Partner authorized to represent:
Center | AMD Saxony LLC (Wilmington, Delaware, US)
| General Manager of AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy
^ permalink raw reply
* [linux-dvb] Kernel oops loading cx88 drivers when two WinTV-HVR4000 cards present
From: Thomas Keil @ 2009-01-03 17:28 UTC (permalink / raw)
To: linux-dvb
Hello everyone,
I'm having trouble with my Nova-HD-S2 WinTV / WinTV-HVR4000(Lite) cards.
As long as just one card is present in the system everything is fine,
with two cards the driver oopses:
------------------------------------------------------------------------
BUG: unable to handle kernel NULL pointer dereference at
00000000
IP: [<c01f798e>]
vsnprintf+0x41e/0x452
*pde =
00000000
Oops: 0000 [#1]
SMP
Modules linked in: lirc_imon(+) lirc_dev cx88_alsa(+) cx88xx videodev
v4l1_compat snd_hda_intel(+) ir_common i2c_algo_bit videobuf_dvb
dvb_core snd_pcm tveeprom videobuf_dma_sg videobuf_core snd_timer
ehci_hcd(+) snd btcx_risc soundcore snd_page_alloc i2c_viapro(+)
i2c_core uhci_hcd usbcore 8250_pnp 8250
serial_core
Pid: 1108, comm: modprobe Not tainted (2.6.27-gentoo-r7 #1)
EIP: 0060:[<c01f798e>] EFLAGS: 00010216 CPU: 0
EIP is at vsnprintf+0x41e/0x452
EAX: 00000000 EBX: f7b5e400 ECX: 00000000 EDX: 00000014
ESI: f7b5e49c EDI: f7121e30 EBP: 03d00000 ESP: f7121cd8
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process modprobe (pid: 1108, ti=f7120000 task=f7bac6e0 task.ti=f7120000)
Stack: 00000014 f7b5e49c c01f7528 c01f7528 f7b5e4b0 f7124628 f7121e74
00000000
c01f77fd ffffffff ffffffff 00000000 00000006 f7124628 00ffffff
ffffffff
f712462e 00000000 ffffffff c042ab22 f7189a40 f7bac6e0 f7121df4
c04d2500
Call
Trace:
[<c01f7528>]
string+0x27/0x6f
[<c01f7528>]
string+0x27/0x6f
[<c01f77fd>]
vsnprintf+0x28d/0x452
[<c01f37d0>]
idr_get_empty_slot+0x146/0x239
[<c01f7528>]
string+0x27/0x6f
[<c012fd78>]
up+0x9/0x2a
[<c011e506>]
release_console_sem+0x16d/0x186
[<c012fd78>]
up+0x9/0x2a
[<c0253b3a>]
device_create_vargs+0x71/0x99
[<c0253b86>]
device_create+0x24/0x28
[<f98c9eb7>] lirc_register_plugin+0x2e3/0x3bc
[lirc_dev]
[<f98c5744>] init_module+0x109c744/0x109c8d8
[lirc_imon]
[<f885e577>] usb_probe_interface+0xbd/0xe2
[usbcore]
[<c0255009>]
__driver_attach+0x0/0x55
[<c0254f92>]
driver_probe_device+0xb5/0x12c
[<c0255040>]
__driver_attach+0x37/0x55
[<c02548d9>]
bus_for_each_dev+0x34/0x56
[<c0254e2d>]
driver_attach+0x11/0x13
[<c0255009>]
__driver_attach+0x0/0x55
[<c0254c2f>]
bus_add_driver+0x8a/0x1a7
[<c01f4193>]
kset_find_obj+0x20/0x4a
[<c025521d>]
driver_register+0x6d/0xc1
[<f885dda7>] usb_register_driver+0x5d/0xb4
[usbcore]
[<f8829000>] init_module+0x0/0x4b
[lirc_imon]
[<f8829028>] init_module+0x28/0x4b
[lirc_imon]
[<c010111f>]
_stext+0x37/0xfb
[<c013a8b4>]
sys_init_module+0x87/0x176
[<c0102d91>]
sysenter_do_call+0x12/0x25
[<c0350000>]
rt_mutex_slowlock+0x213/0x3e1
=======================
Code: f9 1f ff 74 24 14 89 f0 89 df ff 74 24 1c 55 ff 74 24 18 51 52 8b
54 24 28 e8 62 f5 ff ff 89 c6 83 c4 18 ff 44 24 1c 8b 44 24 1c <8a> 00
84 c0 0f 85 4f fc ff ff 83 3c 24 00 74 13 3b 74 24 10 73
EIP: [<c01f798e>] vsnprintf+0x41e/0x452 SS:ESP
0068:f7121cd8
---[ end trace d1865b13e5b6eb16
]---
HDA Intel 0000:80:01.0: PCI INT A -> GSI 17 (level, low) -> IRQ
17
HDA Intel 0000:80:01.0: setting latency timer to
64
HDA Intel 0000:80:01.0: PCI: Disallowing DAC for
device
cx88_audio 0000:04:06.1: PCI INT A -> GSI 19 (level, low) -> IRQ
19
cx88[0]: subsystem: 0070:6906, board: Hauppauge WinTV-HVR4000(Lite)
DVB-S/S2 [card=69,autodetected], frontend(s):
1
cx88[0]: TV tuner type -1, Radio tuner type
-1
tveeprom 1-0050: Hauppauge model 69100, rev B2C3, serial#
3247308
tveeprom 1-0050: MAC address is
00-0D-FE-31-8C-CC
tveeprom 1-0050: tuner model is Conexant CX24118A (idx 123, type
4)
tveeprom 1-0050: TV standards ATSC/DVB Digital (eeprom
0x80)
tveeprom 1-0050: audio processor is None (idx
0)
tveeprom 1-0050: decoder processor is CX882 (idx
25)
tveeprom 1-0050: has no radio, has IR receiver, has no IR
transmitter
cx88[0]: hauppauge eeprom:
model=69100
input: cx88 IR (Hauppauge WinTV-HVR400 as
/class/input/input3
cx88[0]/1: CX88x/0: ALSA support for cx2388x
boards
cx88_audio 0000:04:07.1: PCI INT A -> GSI 20 (level, low) -> IRQ
20
allocation failed: out of vmalloc space - use vmalloc=<size> to increase
size.
cx88[1]: subsystem: 0070:6906, board: Hauppauge WinTV-HVR4000(Lite)
DVB-S/S2 [card=69,autodetected], frontend(s):
1
cx88[1]: TV tuner type -1, Radio tuner type
-1
BUG: unable to handle kernel paging request at
00200034
IP: [<fd917277>]
:cx88xx:cx88_shutdown+0xb/0x94
*pde =
00000000
Oops: 0002 [#2]
SMP
Modules linked in: tuner v4l2_common lirc_imon(+) lirc_dev cx88_alsa(+)
cx88xx videodev v4l1_compat snd_hda_intel ir_common i2c_algo_bit
videobuf_dvb dvb_core snd_pcm tveeprom videobuf_dma_sg videobuf_core
snd_timer ehci_hcd snd btcx_risc soundcore snd_page_alloc i2c_viapro
i2c_core uhci_hcd usbcore 8250_pnp 8250
serial_core
Pid: 959, comm: modprobe Tainted: G D (2.6.27-gentoo-r7 #1)
EIP: 0060:[<fd917277>] EFLAGS: 00010202 CPU: 0
EIP is at cx88_shutdown+0xb/0x94 [cx88xx]
EAX: f7ba6800 EBX: ffffffff ECX: 00200034 EDX: 00000000
ESI: f7ba6800 EDI: f7ba6cb0 EBP: f7ba6800 ESP: f7b6bdf8
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process modprobe (pid: 959, ti=f7b6a000 task=f7b81ef0 task.ti=f7b6a000)
Stack: fd917fb6 00000070 f7ba6810 fd916a4c fd920a1f f7ba6810 ffffffff
ffffffff
00000004 f7b6be64 c02bc88d 0000000d f78fec00 00b6be64 00000039
f7ba6bb8
0000000d 00000286 c02bc96b 0000000d 00000001 f7b6be64 00000286
c01fb6bf
Call
Trace:
[<fd917fb6>] cx88_reset+0x2d/0x186
[cx88xx]
[<fd916a4c>] cx88_core_create+0x393/0xac3
[cx88xx]
[<c02bc88d>]
raw_pci_read+0x4d/0x55
[<c02bc96b>]
pci_read+0x1c/0x21
[<c01fb6bf>]
pci_bus_read_config_byte+0x4e/0x58
[<c02bb057>]
pcibios_set_master+0x1c/0x8d
[<fd917406>] cx88_core_get+0x6e/0x9f
[cx88xx]
[<f98ae864>] cx88_audio_initdev+0x94/0x30f
[cx88_alsa]
[<c01f416f>]
kobject_get+0xf/0x13
[<c0255009>] __driver_attach+0x0/0x55
[<c01ff34e>] pci_device_probe+0x36/0x57
[<c0254f92>] driver_probe_device+0xb5/0x12c
[<c0255040>] __driver_attach+0x37/0x55
[<c02548d9>] bus_for_each_dev+0x34/0x56
[<c0254e2d>] driver_attach+0x11/0x13
[<c0255009>] __driver_attach+0x0/0x55
[<c0254c2f>] bus_add_driver+0x8a/0x1a7
[<c01f4193>] kset_find_obj+0x20/0x4a
[<f98ae1e7>] cx88_audio_init+0x0/0x27 [cx88_alsa]
[<c025521d>] driver_register+0x6d/0xc1
[<c011e942>] printk+0x14/0x18
[<f98ae1e7>] cx88_audio_init+0x0/0x27 [cx88_alsa]
[<c01ff50d>] __pci_register_driver+0x3c/0x67
[<c010111f>] _stext+0x37/0xfb
[<c0116088>] enqueue_task+0xa/0x14
[<c0118e6f>] try_to_wake_up+0x11c/0x125
[<c013a8b4>] sys_init_module+0x87/0x176
[<c0102d91>] sysenter_do_call+0x12/0x25
[<c0350000>] rt_mutex_slowlock+0x213/0x3e1
=======================
Code: 41 0c 89 42 04 89 f0 8b 4c 24 1c 45 8d 34 08 3b 6c 24 20 0f 85 40
ff ff ff 5b 89 f8 5e 5f 5d c3 8b 48 38 31 d2 81 c1 34 00 20 00 <89> 11
8b 48 38 81 c1 40 c0 31 00 89 11 8b 48 38 81 c1 40 c0 32
EIP: [<fd917277>] cx88_shutdown+0xb/0x94 [cx88xx] SS:ESP 0068:f7b6bdf8
---[ end trace d1865b13e5b6eb16 ]---
------------------------------------------------------------------------
I'm using the current HG from
http://mercurial.intuxication.org/hg/s2-liplianin with kernel 2.6.27
Does anyone know what's wrong here?
Thanks
Thomas
_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
^ permalink raw reply
* [U-Boot] [RFC] Build errors in u-boot mainline and daily builds
From: Jerry Van Baren @ 2009-01-03 17:28 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20090103151852.45E798387CDB@gemini.denx.de>
Wolfgang Denk wrote:
> Dear Remy,
>
> In message <3efb10970901030310r7cfc1245g97ac0db4375ddc33@mail.gmail.com> you wrote:
>> I started a server to do only daily builds of all U-boot board
>> configurations. (currently on a old slow box, but it works, it takes
>> about 2 hours to build all boards for ARM only)
That's still not bad.
> I appreciate your efforts. Actually this is something everybody is
> supposed to do before submitting a patch, and especially the
> custodians before submitting a pull request.
>
> Unfortually, that's theory only :-(
An unenforceable demand. :-( A build machine is the pragmatic solution,
but it puts the burden on the build machine maintainer. :-/ Thanks for
volunteering, Remy. :-)
Side note: I've been looking at BuildBot but haven't done anything
useful. I've looked at CruiseControl a few times and then I see how it
does the control logic in (haxtended) XML. Bleah!
[snip]
>> Further, is there any interest to make the daily build results public?
>> * Is it appreciated if I post the build results in a daily post to the
>> mailinglist, _if_ there is a build failure? (No news is good news)
>> What format is preferred?
>
> Please do not post such results here.
Wolfgang: I would suggest another mailman list. Interested parties can
subscribe to it, disinterested parties can look in the list archives if
they need to. There probably isn't a need for long term archives, say 6
months (~2-3 releases).
>> * Or is it preferred to post the results on a website?
>
> Yes, that would be beter, IMO.
Web sites are awfully easy to ignore/forget. :-/
> Best regards,
>
> Wolfgang Denk
Ditto,
gvb
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.