xen: set IO permission early (before early_cpu_init())

This patch is based off "xen dom0: Set up basic IO permissions for dom0."
by Juan Quintela <quintela@redhat.com>.

On AMD machines when we boot the kernel as Domain 0 we get this nasty:

mapping kernel into physical memory
Xen: setup ISA identity maps
about to get started...
(XEN) traps.c:475:d0 Unhandled general protection fault fault/trap [#13] on VCPU 0 [ec=0000]
(XEN) domain_crash_sync called from entry.S
(XEN) Domain 0 (vcpu#0) crashed on cpu#0:
(XEN) ----[ Xen-4.1-101116  x86_64  debug=y  Not tainted ]----
(XEN) CPU:    0
(XEN) RIP:    e033:[<ffffffff8130271b>]
(XEN) RFLAGS: 0000000000000282   EM: 1   CONTEXT: pv guest
(XEN) rax: 000000008000c068   rbx: ffffffff8186c680   rcx: 0000000000000068
(XEN) rdx: 0000000000000cf8   rsi: 000000000000c000   rdi: 0000000000000000
(XEN) rbp: ffffffff81801e98   rsp: ffffffff81801e50   r8:  ffffffff81801eac
(XEN) r9:  ffffffff81801ea8   r10: ffffffff81801eb4   r11: 00000000ffffffff
(XEN) r12: ffffffff8186c694   r13: ffffffff81801f90   r14: ffffffffffffffff
(XEN) r15: 0000000000000000   cr0: 000000008005003b   cr4: 00000000000006f0
(XEN) cr3: 0000000221803000   cr2: 0000000000000000
(XEN) ds: 0000   es: 0000   fs: 0000   gs: 0000   ss: e02b   cs: e033
(XEN) Guest stack trace from rsp=ffffffff81801e50:

RIP points to read_pci_config() function.

The issue is that we don't set IO permissions for the Linux kernel early enough.

The call sequence used to be:

    xen_start_kernel()
	x86_init.oem.arch_setup = xen_setup_arch;
        setup_arch:
           - early_cpu_init
               - early_init_amd
                  - read_pci_config
           - x86_init.oem.arch_setup [ xen_arch_setup ]
               - set IO permissions.

We need to set the IO permissions earlier on, which this patch does.

Acked-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
This commit is contained in:
Konrad Rzeszutek Wilk 2010-11-16 12:09:59 -05:00 коммит произвёл Jeremy Fitzhardinge
Родитель d2a817130c
Коммит ec35a69c46
2 изменённых файлов: 11 добавлений и 9 удалений

Просмотреть файл

@ -1095,6 +1095,8 @@ static void __init xen_setup_stackprotector(void)
/* First C function to be called on Xen boot */ /* First C function to be called on Xen boot */
asmlinkage void __init xen_start_kernel(void) asmlinkage void __init xen_start_kernel(void)
{ {
struct physdev_set_iopl set_iopl;
int rc;
pgd_t *pgd; pgd_t *pgd;
if (!xen_start_info) if (!xen_start_info)
@ -1209,10 +1211,18 @@ asmlinkage void __init xen_start_kernel(void)
#else #else
pv_info.kernel_rpl = 0; pv_info.kernel_rpl = 0;
#endif #endif
/* set the limit of our address space */ /* set the limit of our address space */
xen_reserve_top(); xen_reserve_top();
/* We used to do this in xen_arch_setup, but that is too late on AMD
* were early_cpu_init (run before ->arch_setup()) calls early_amd_init
* which pokes 0xcf8 port.
*/
set_iopl.iopl = 1;
rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
if (rc != 0)
xen_raw_printk("physdev_op failed %d\n", rc);
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
/* set up basic CPUID stuff */ /* set up basic CPUID stuff */
cpu_detect(&new_cpu_data); cpu_detect(&new_cpu_data);

Просмотреть файл

@ -336,9 +336,6 @@ void __cpuinit xen_enable_syscall(void)
void __init xen_arch_setup(void) void __init xen_arch_setup(void)
{ {
struct physdev_set_iopl set_iopl;
int rc;
xen_panic_handler_init(); xen_panic_handler_init();
HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
@ -355,11 +352,6 @@ void __init xen_arch_setup(void)
xen_enable_sysenter(); xen_enable_sysenter();
xen_enable_syscall(); xen_enable_syscall();
set_iopl.iopl = 1;
rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
if (rc != 0)
printk(KERN_INFO "physdev_op failed %d\n", rc);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
if (!(xen_start_info->flags & SIF_INITDOMAIN)) { if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
printk(KERN_INFO "ACPI in unprivileged domain disabled\n"); printk(KERN_INFO "ACPI in unprivileged domain disabled\n");